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.implementation.bytecode.member.MethodVariableAccess;
27 import net.bytebuddy.jar.asm.ClassVisitor;
28 import net.bytebuddy.jar.asm.ClassWriter;
29 import net.bytebuddy.jar.asm.Label;
30 import net.bytebuddy.jar.asm.MethodVisitor;
31 import net.bytebuddy.jar.asm.Opcodes;
32 import net.bytebuddy.matcher.ElementMatchers;
33 import net.bytebuddy.pool.TypePool;
35 final class ByteBuddyUtils {
36 static final StackManipulation THIS = MethodVariableAccess.loadThis();
38 private ByteBuddyUtils() {
42 static StackManipulation invokeMethod(final Method method) {
43 return MethodInvocation.invoke(describe(method));
46 static StackManipulation invokeMethod(final Class<?> clazz, final String name, final Class<?>... args) {
47 return MethodInvocation.invoke(describe(clazz, name, args));
50 static AsmVisitorWrapper computeFrames() {
51 return ComputeFrames.INSTANCE;
54 static StackManipulation ifEq(final Label label) {
55 return new IfEq(label);
58 static StackManipulation markLabel(final Label label) {
59 return new Mark(label);
62 static StackManipulation loadThis() {
66 static StackManipulation getField(final Field field) {
67 return FieldAccess.forField(new ForLoadedField(field).asDefined()).read();
70 static StackManipulation getField(final TypeDescription instrumentedType, final String fieldName) {
71 return fieldAccess(instrumentedType, fieldName).read();
74 static StackManipulation putField(final TypeDescription instrumentedType, final String fieldName) {
75 return fieldAccess(instrumentedType, fieldName).write();
78 private static ForLoadedMethod describe(final Method method) {
79 return new ForLoadedMethod(method);
82 private static ForLoadedMethod describe(final Class<?> clazz, final String name, final Class<?>... args) {
83 return describe(getMethod(clazz, name, args));
86 private static Defined fieldAccess(final TypeDescription instrumentedType, final String fieldName) {
87 return FieldAccess.forField(instrumentedType.getDeclaredFields().filter(ElementMatchers.named(fieldName))
92 * Utility wrapper to force ASM to compute frames.
94 private enum ComputeFrames implements AsmVisitorWrapper {
98 public int mergeWriter(final int flags) {
99 return flags | ClassWriter.COMPUTE_FRAMES;
103 public int mergeReader(final int flags) {
104 return flags | ClassWriter.COMPUTE_FRAMES;
108 public ClassVisitor wrap(final TypeDescription td, final ClassVisitor cv, final Implementation.Context ctx,
109 final TypePool tp, final FieldList<FieldDescription.InDefinedShape> fields, final MethodList<?> methods,
110 final int wflags, final int rflags) {
116 * IFEQ opcode invocation, jumping to a particular label.
118 private static final class IfEq implements StackManipulation {
119 private static final StackManipulation.Size SIZE = new StackManipulation.Size(-1, 0);
121 private final Label label;
123 IfEq(final Label label) {
124 this.label = requireNonNull(label);
128 public boolean isValid() {
133 public StackManipulation.Size apply(final MethodVisitor mv, final Implementation.Context ctx) {
134 mv.visitJumpInsn(Opcodes.IFEQ, label);
140 * A label definition, marking the spot where IfEq should jump.
142 private static final class Mark implements StackManipulation {
143 private static final StackManipulation.Size SIZE = new StackManipulation.Size(0, 0);
145 private final Label label;
147 Mark(final Label label) {
148 this.label = requireNonNull(label);
152 public boolean isValid() {
157 public StackManipulation.Size apply(final MethodVisitor mv, final Implementation.Context ctx) {
158 mv.visitLabel(label);
163 private static Method getMethod(final Class<?> clazz, final String name, final Class<?>... args) {
165 return clazz.getDeclaredMethod(name, args);
166 } catch (NoSuchMethodException e) {
167 throw new IllegalStateException(e);