2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
10 import static java.util.Objects.requireNonNull;
12 import java.lang.reflect.Field;
13 import java.lang.reflect.Method;
14 import net.bytebuddy.asm.AsmVisitorWrapper;
15 import net.bytebuddy.description.field.FieldDescription;
16 import net.bytebuddy.description.field.FieldDescription.ForLoadedField;
17 import net.bytebuddy.description.field.FieldList;
18 import net.bytebuddy.description.method.MethodDescription.ForLoadedMethod;
19 import net.bytebuddy.description.method.MethodList;
20 import net.bytebuddy.description.type.TypeDescription;
21 import net.bytebuddy.implementation.Implementation;
22 import net.bytebuddy.implementation.bytecode.StackManipulation;
23 import net.bytebuddy.implementation.bytecode.member.FieldAccess;
24 import net.bytebuddy.implementation.bytecode.member.FieldAccess.Defined;
25 import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
26 import net.bytebuddy.jar.asm.ClassVisitor;
27 import net.bytebuddy.jar.asm.ClassWriter;
28 import net.bytebuddy.jar.asm.Label;
29 import net.bytebuddy.jar.asm.MethodVisitor;
30 import net.bytebuddy.jar.asm.Opcodes;
31 import net.bytebuddy.matcher.ElementMatchers;
32 import net.bytebuddy.pool.TypePool;
34 final class ByteBuddyUtils {
35 private ByteBuddyUtils() {
39 static StackManipulation invokeMethod(final Method method) {
40 return MethodInvocation.invoke(describe(method));
43 static StackManipulation invokeMethod(final Class<?> clazz, final String name, final Class<?>... args) {
44 return MethodInvocation.invoke(describe(clazz, name, args));
47 static AsmVisitorWrapper computeFrames() {
48 return ComputeFrames.INSTANCE;
51 static StackManipulation ifEq(final Label label) {
52 return new IfEq(label);
55 static StackManipulation markLabel(final Label label) {
56 return new Mark(label);
59 static StackManipulation getField(final Field field) {
60 return FieldAccess.forField(new ForLoadedField(field).asDefined()).read();
63 static StackManipulation getField(final TypeDescription instrumentedType, final String fieldName) {
64 return fieldAccess(instrumentedType, fieldName).read();
67 static StackManipulation putField(final TypeDescription instrumentedType, final String fieldName) {
68 return fieldAccess(instrumentedType, fieldName).write();
71 private static ForLoadedMethod describe(final Method method) {
72 return new ForLoadedMethod(method);
75 private static ForLoadedMethod describe(final Class<?> clazz, final String name, final Class<?>... args) {
76 return describe(getMethod(clazz, name, args));
79 private static Defined fieldAccess(final TypeDescription instrumentedType, final String fieldName) {
80 return FieldAccess.forField(instrumentedType.getDeclaredFields().filter(ElementMatchers.named(fieldName))
85 * Utility wrapper to force ASM to compute frames.
87 private enum ComputeFrames implements AsmVisitorWrapper {
91 public int mergeWriter(final int flags) {
92 return flags | ClassWriter.COMPUTE_FRAMES;
96 public int mergeReader(final int flags) {
97 return flags | ClassWriter.COMPUTE_FRAMES;
101 public ClassVisitor wrap(final TypeDescription td, final ClassVisitor cv, final Implementation.Context ctx,
102 final TypePool tp, final FieldList<FieldDescription.InDefinedShape> fields, final MethodList<?> methods,
103 final int wflags, final int rflags) {
109 * IFEQ opcode invocation, jumping to a particular label.
111 private static final class IfEq implements StackManipulation {
112 private static final StackManipulation.Size SIZE = new StackManipulation.Size(-1, 0);
114 private final Label label;
116 IfEq(final Label label) {
117 this.label = requireNonNull(label);
121 public boolean isValid() {
126 public StackManipulation.Size apply(final MethodVisitor mv, final Implementation.Context ctx) {
127 mv.visitJumpInsn(Opcodes.IFEQ, label);
133 * A label definition, marking the spot where IfEq should jump.
135 private static final class Mark implements StackManipulation {
136 private static final StackManipulation.Size SIZE = new StackManipulation.Size(0, 0);
138 private final Label label;
140 Mark(final Label label) {
141 this.label = requireNonNull(label);
145 public boolean isValid() {
150 public StackManipulation.Size apply(final MethodVisitor mv, final Implementation.Context ctx) {
151 mv.visitLabel(label);
156 private static Method getMethod(final Class<?> clazz, final String name, final Class<?>... args) {
158 return clazz.getDeclaredMethod(name, args);
159 } catch (NoSuchMethodException e) {
160 throw new IllegalStateException(e);