mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8213480: update internal ASM version to 7.0
Reviewed-by: dholmes, iignatyev, alanb
This commit is contained in:
parent
147fc3ed13
commit
61082e6b25
155 changed files with 29496 additions and 27123 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
|
@ -43,7 +43,7 @@ public class Main {
|
|||
/**
|
||||
* ASM version to be used by nasgen tool.
|
||||
*/
|
||||
public static final int ASM_VERSION = Opcodes.ASM5;
|
||||
public static final int ASM_VERSION = Opcodes.ASM7;
|
||||
|
||||
private static final boolean DEBUG = Boolean.getBoolean("nasgen.debug");
|
||||
|
||||
|
|
|
|||
|
|
@ -1433,7 +1433,7 @@ public final class Module implements AnnotatedElement {
|
|||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
|
||||
+ ClassWriter.COMPUTE_FRAMES);
|
||||
|
||||
ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
|
||||
ClassVisitor cv = new ClassVisitor(Opcodes.ASM7, cw) {
|
||||
@Override
|
||||
public void visit(int version,
|
||||
int access,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
|
@ -35,7 +35,7 @@ import static sun.invoke.util.Wrapper.*;
|
|||
class TypeConvertingMethodAdapter extends MethodVisitor {
|
||||
|
||||
TypeConvertingMethodAdapter(MethodVisitor mv) {
|
||||
super(Opcodes.ASM5, mv);
|
||||
super(Opcodes.ASM7, mv);
|
||||
}
|
||||
|
||||
private static final int NUM_WRAPPERS = Wrapper.COUNT;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
|
@ -153,7 +153,7 @@ public final class ModuleInfoExtender {
|
|||
|
||||
ClassReader cr = new ClassReader(in);
|
||||
|
||||
ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
|
||||
ClassVisitor cv = new ClassVisitor(Opcodes.ASM7, cw) {
|
||||
@Override
|
||||
public ModuleVisitor visitModule(String name, int flags, String version) {
|
||||
Version v = ModuleInfoExtender.this.version;
|
||||
|
|
@ -170,7 +170,7 @@ public final class ModuleInfoExtender {
|
|||
packages.forEach(pn -> mv.visitPackage(pn.replace('.', '/')));
|
||||
}
|
||||
|
||||
return new ModuleVisitor(Opcodes.ASM6, mv) {
|
||||
return new ModuleVisitor(Opcodes.ASM7, mv) {
|
||||
public void visitMainClass(String existingMainClass) {
|
||||
// skip main class if there is a new value
|
||||
if (mainClass == null) {
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java annotation. The methods of this class must be
|
||||
* called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
|
||||
* <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
|
||||
* A visitor to visit a Java annotation. The methods of this class must be called in the following
|
||||
* order: ( {@code visit} | {@code visitEnum} | {@code visitAnnotation} | {@code visitArray} )*
|
||||
* {@code visitEnd}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
|
|
@ -69,127 +69,105 @@ package jdk.internal.org.objectweb.asm;
|
|||
public abstract class AnnotationVisitor {
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The annotation visitor to which this visitor must delegate method calls.
|
||||
* May be null.
|
||||
*/
|
||||
/** The annotation visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected AnnotationVisitor av;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Constructs a new {@link AnnotationVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public AnnotationVisitor(final int api) {
|
||||
this(api, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param av
|
||||
* the annotation visitor to which this visitor must delegate
|
||||
* method calls. May be null.
|
||||
*/
|
||||
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
* Constructs a new {@link AnnotationVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param annotationVisitor the annotation visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) {
|
||||
if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.av = av;
|
||||
this.av = annotationVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a primitive value of the annotation.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param value
|
||||
* the actual value, whose type must be {@link Byte},
|
||||
* {@link Boolean}, {@link Character}, {@link Short},
|
||||
* {@link Integer} , {@link Long}, {@link Float}, {@link Double},
|
||||
* {@link String} or {@link Type} of OBJECT or ARRAY sort. This
|
||||
* value can also be an array of byte, boolean, short, char, int,
|
||||
* long, float or double values (this is equivalent to using
|
||||
* {@link #visitArray visitArray} and visiting each array element
|
||||
* in turn, but is more convenient).
|
||||
*/
|
||||
public void visit(String name, Object value) {
|
||||
* Visits a primitive value of the annotation.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
|
||||
* Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
|
||||
* {@link String} or {@link Type} of {@link Type#OBJECT} or {@link Type#ARRAY} sort. This
|
||||
* value can also be an array of byte, boolean, short, char, int, long, float or double values
|
||||
* (this is equivalent to using {@link #visitArray} and visiting each array element in turn,
|
||||
* but is more convenient).
|
||||
*/
|
||||
public void visit(final String name, final Object value) {
|
||||
if (av != null) {
|
||||
av.visit(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an enumeration value of the annotation.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param desc
|
||||
* the class descriptor of the enumeration class.
|
||||
* @param value
|
||||
* the actual enumeration value.
|
||||
*/
|
||||
public void visitEnum(String name, String desc, String value) {
|
||||
* Visits an enumeration value of the annotation.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @param descriptor the class descriptor of the enumeration class.
|
||||
* @param value the actual enumeration value.
|
||||
*/
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
if (av != null) {
|
||||
av.visitEnum(name, desc, value);
|
||||
av.visitEnum(name, descriptor, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a nested annotation value of the annotation.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param desc
|
||||
* the class descriptor of the nested annotation class.
|
||||
* @return a visitor to visit the actual nested annotation value, or
|
||||
* <tt>null</tt> if this visitor is not interested in visiting this
|
||||
* nested annotation. <i>The nested annotation value must be fully
|
||||
* visited before calling other methods on this annotation
|
||||
* visitor</i>.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc) {
|
||||
* Visits a nested annotation value of the annotation.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @param descriptor the class descriptor of the nested annotation class.
|
||||
* @return a visitor to visit the actual nested annotation value, or {@literal null} if this
|
||||
* visitor is not interested in visiting this nested annotation. <i>The nested annotation
|
||||
* value must be fully visited before calling other methods on this annotation visitor</i>.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
if (av != null) {
|
||||
return av.visitAnnotation(name, desc);
|
||||
return av.visitAnnotation(name, descriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an array value of the annotation. Note that arrays of primitive
|
||||
* types (such as byte, boolean, short, char, int, long, float or double)
|
||||
* can be passed as value to {@link #visit visit}. This is what
|
||||
* {@link ClassReader} does.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @return a visitor to visit the actual array value elements, or
|
||||
* <tt>null</tt> if this visitor is not interested in visiting these
|
||||
* values. The 'name' parameters passed to the methods of this
|
||||
* visitor are ignored. <i>All the array values must be visited
|
||||
* before calling other methods on this annotation visitor</i>.
|
||||
*/
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
* Visits an array value of the annotation. Note that arrays of primitive types (such as byte,
|
||||
* boolean, short, char, int, long, float or double) can be passed as value to {@link #visit
|
||||
* visit}. This is what {@link ClassReader} does.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @return a visitor to visit the actual array value elements, or {@literal null} if this visitor
|
||||
* is not interested in visiting these values. The 'name' parameters passed to the methods of
|
||||
* this visitor are ignored. <i>All the array values must be visited before calling other
|
||||
* methods on this annotation visitor</i>.
|
||||
*/
|
||||
public AnnotationVisitor visitArray(final String name) {
|
||||
if (av != null) {
|
||||
return av.visitArray(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the end of the annotation.
|
||||
*/
|
||||
/** Visits the end of the annotation. */
|
||||
public void visitEnd() {
|
||||
if (av != null) {
|
||||
av.visitEnd();
|
||||
|
|
|
|||
|
|
@ -59,342 +59,391 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* An {@link AnnotationVisitor} that generates annotations in bytecode form.
|
||||
* An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation'
|
||||
* structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter
|
||||
* instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations
|
||||
* attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such
|
||||
* lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS
|
||||
* 4.7.16</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
|
||||
* 4.7.20</a>
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
final class AnnotationWriter extends AnnotationVisitor {
|
||||
|
||||
/**
|
||||
* The class writer to which this annotation must be added.
|
||||
*/
|
||||
private final ClassWriter cw;
|
||||
/** Where the constants used in this AnnotationWriter must be stored. */
|
||||
private final SymbolTable symbolTable;
|
||||
|
||||
/**
|
||||
* The number of values in this annotation.
|
||||
*/
|
||||
private int size;
|
||||
* Whether values are named or not. AnnotationWriter instances used for annotation default and
|
||||
* annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each
|
||||
* value, instead of an element_name_index followed by an element_value).
|
||||
*/
|
||||
private final boolean useNamedValues;
|
||||
|
||||
/**
|
||||
* <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
|
||||
* writers used for annotation default and annotation arrays use unnamed
|
||||
* values.
|
||||
*/
|
||||
private final boolean named;
|
||||
* The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values
|
||||
* visited so far. All the fields of these structures, except the last one - the
|
||||
* element_value_pairs array, must be set before this ByteVector is passed to the constructor
|
||||
* (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link
|
||||
* #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit()
|
||||
* methods.
|
||||
*
|
||||
* <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a
|
||||
* single element_value by definition), this ByteVector is initially empty when passed to the
|
||||
* constructor, and {@link #numElementValuePairsOffset} is set to -1.
|
||||
*/
|
||||
private final ByteVector annotation;
|
||||
|
||||
/**
|
||||
* The annotation values in bytecode form. This byte vector only contains
|
||||
* the values themselves, i.e. the number of values must be stored as a
|
||||
* unsigned short just before these bytes.
|
||||
*/
|
||||
private final ByteVector bv;
|
||||
* The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for
|
||||
* the case of AnnotationDefault attributes).
|
||||
*/
|
||||
private final int numElementValuePairsOffset;
|
||||
|
||||
/** The number of element value pairs visited so far. */
|
||||
private int numElementValuePairs;
|
||||
|
||||
/**
|
||||
* The byte vector to be used to store the number of values of this
|
||||
* annotation. See {@link #bv}.
|
||||
*/
|
||||
private final ByteVector parent;
|
||||
* The previous AnnotationWriter. This field is used to store the list of annotations of a
|
||||
* Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
|
||||
* (annotation values of annotation type), or for AnnotationDefault attributes.
|
||||
*/
|
||||
private final AnnotationWriter previousAnnotation;
|
||||
|
||||
/**
|
||||
* Where the number of values of this annotation must be stored in
|
||||
* {@link #parent}.
|
||||
*/
|
||||
private final int offset;
|
||||
* The next AnnotationWriter. This field is used to store the list of annotations of a
|
||||
* Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
|
||||
* (annotation values of annotation type), or for AnnotationDefault attributes.
|
||||
*/
|
||||
private AnnotationWriter nextAnnotation;
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Next annotation writer. This field is used to store annotation lists.
|
||||
*/
|
||||
AnnotationWriter next;
|
||||
|
||||
/**
|
||||
* Previous annotation writer. This field is used to store annotation lists.
|
||||
*/
|
||||
AnnotationWriter prev;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationWriter}.
|
||||
*
|
||||
* @param cw
|
||||
* the class writer to which this annotation must be added.
|
||||
* @param named
|
||||
* <tt>true<tt> if values are named, <tt>false</tt> otherwise.
|
||||
* @param bv
|
||||
* where the annotation values must be stored.
|
||||
* @param parent
|
||||
* where the number of annotation values must be stored.
|
||||
* @param offset
|
||||
* where in <tt>parent</tt> the number of annotation values must
|
||||
* be stored.
|
||||
*/
|
||||
AnnotationWriter(final ClassWriter cw, final boolean named,
|
||||
final ByteVector bv, final ByteVector parent, final int offset) {
|
||||
super(Opcodes.ASM6);
|
||||
this.cw = cw;
|
||||
this.named = named;
|
||||
this.bv = bv;
|
||||
this.parent = parent;
|
||||
this.offset = offset;
|
||||
* Constructs a new {@link AnnotationWriter}.
|
||||
*
|
||||
* @param symbolTable where the constants used in this AnnotationWriter must be stored.
|
||||
* @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays
|
||||
* use unnamed values.
|
||||
* @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
|
||||
* the visited content must be stored. This ByteVector must already contain all the fields of
|
||||
* the structure except the last one (the element_value_pairs array).
|
||||
* @param previousAnnotation the previously visited annotation of the
|
||||
* Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
|
||||
* other cases (e.g. nested or array annotations).
|
||||
*/
|
||||
AnnotationWriter(
|
||||
final SymbolTable symbolTable,
|
||||
final boolean useNamedValues,
|
||||
final ByteVector annotation,
|
||||
final AnnotationWriter previousAnnotation) {
|
||||
super(Opcodes.ASM7);
|
||||
this.symbolTable = symbolTable;
|
||||
this.useNamedValues = useNamedValues;
|
||||
this.annotation = annotation;
|
||||
// By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'.
|
||||
this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2;
|
||||
this.previousAnnotation = previousAnnotation;
|
||||
if (previousAnnotation != null) {
|
||||
previousAnnotation.nextAnnotation = this;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
* Constructs a new {@link AnnotationWriter} using named values.
|
||||
*
|
||||
* @param symbolTable where the constants used in this AnnotationWriter must be stored.
|
||||
* @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
|
||||
* the visited content must be stored. This ByteVector must already contain all the fields of
|
||||
* the structure except the last one (the element_value_pairs array).
|
||||
* @param previousAnnotation the previously visited annotation of the
|
||||
* Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
|
||||
* other cases (e.g. nested or array annotations).
|
||||
*/
|
||||
AnnotationWriter(
|
||||
final SymbolTable symbolTable,
|
||||
final ByteVector annotation,
|
||||
final AnnotationWriter previousAnnotation) {
|
||||
this(symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the AnnotationVisitor abstract class
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void visit(final String name, final Object value) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
// Case of an element_value with a const_value_index, class_info_index or array_index field.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
if (value instanceof String) {
|
||||
bv.put12('s', cw.newUTF8((String) value));
|
||||
annotation.put12('s', symbolTable.addConstantUtf8((String) value));
|
||||
} else if (value instanceof Byte) {
|
||||
bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
|
||||
annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index);
|
||||
} else if (value instanceof Boolean) {
|
||||
int v = ((Boolean) value).booleanValue() ? 1 : 0;
|
||||
bv.put12('Z', cw.newInteger(v).index);
|
||||
int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0;
|
||||
annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index);
|
||||
} else if (value instanceof Character) {
|
||||
bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
|
||||
annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index);
|
||||
} else if (value instanceof Short) {
|
||||
bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
|
||||
annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index);
|
||||
} else if (value instanceof Type) {
|
||||
bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
|
||||
annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor()));
|
||||
} else if (value instanceof byte[]) {
|
||||
byte[] v = (byte[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('B', cw.newInteger(v[i]).index);
|
||||
byte[] byteArray = (byte[]) value;
|
||||
annotation.put12('[', byteArray.length);
|
||||
for (byte byteValue : byteArray) {
|
||||
annotation.put12('B', symbolTable.addConstantInteger(byteValue).index);
|
||||
}
|
||||
} else if (value instanceof boolean[]) {
|
||||
boolean[] v = (boolean[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
|
||||
boolean[] booleanArray = (boolean[]) value;
|
||||
annotation.put12('[', booleanArray.length);
|
||||
for (boolean booleanValue : booleanArray) {
|
||||
annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index);
|
||||
}
|
||||
} else if (value instanceof short[]) {
|
||||
short[] v = (short[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('S', cw.newInteger(v[i]).index);
|
||||
short[] shortArray = (short[]) value;
|
||||
annotation.put12('[', shortArray.length);
|
||||
for (short shortValue : shortArray) {
|
||||
annotation.put12('S', symbolTable.addConstantInteger(shortValue).index);
|
||||
}
|
||||
} else if (value instanceof char[]) {
|
||||
char[] v = (char[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('C', cw.newInteger(v[i]).index);
|
||||
char[] charArray = (char[]) value;
|
||||
annotation.put12('[', charArray.length);
|
||||
for (char charValue : charArray) {
|
||||
annotation.put12('C', symbolTable.addConstantInteger(charValue).index);
|
||||
}
|
||||
} else if (value instanceof int[]) {
|
||||
int[] v = (int[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('I', cw.newInteger(v[i]).index);
|
||||
int[] intArray = (int[]) value;
|
||||
annotation.put12('[', intArray.length);
|
||||
for (int intValue : intArray) {
|
||||
annotation.put12('I', symbolTable.addConstantInteger(intValue).index);
|
||||
}
|
||||
} else if (value instanceof long[]) {
|
||||
long[] v = (long[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('J', cw.newLong(v[i]).index);
|
||||
long[] longArray = (long[]) value;
|
||||
annotation.put12('[', longArray.length);
|
||||
for (long longValue : longArray) {
|
||||
annotation.put12('J', symbolTable.addConstantLong(longValue).index);
|
||||
}
|
||||
} else if (value instanceof float[]) {
|
||||
float[] v = (float[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('F', cw.newFloat(v[i]).index);
|
||||
float[] floatArray = (float[]) value;
|
||||
annotation.put12('[', floatArray.length);
|
||||
for (float floatValue : floatArray) {
|
||||
annotation.put12('F', symbolTable.addConstantFloat(floatValue).index);
|
||||
}
|
||||
} else if (value instanceof double[]) {
|
||||
double[] v = (double[]) value;
|
||||
bv.put12('[', v.length);
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
bv.put12('D', cw.newDouble(v[i]).index);
|
||||
double[] doubleArray = (double[]) value;
|
||||
annotation.put12('[', doubleArray.length);
|
||||
for (double doubleValue : doubleArray) {
|
||||
annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index);
|
||||
}
|
||||
} else {
|
||||
Item i = cw.newConstItem(value);
|
||||
bv.put12(".s.IFJDCS".charAt(i.type), i.index);
|
||||
Symbol symbol = symbolTable.addConstant(value);
|
||||
annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(final String name, final String desc,
|
||||
final String value) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
// Case of an element_value with an enum_const_value field.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
|
||||
annotation
|
||||
.put12('e', symbolTable.addConstantUtf8(descriptor))
|
||||
.putShort(symbolTable.addConstantUtf8(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String name,
|
||||
final String desc) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
// Case of an element_value with an annotation_value field.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
// write tag and type, and reserve space for values count
|
||||
bv.put12('@', cw.newUTF8(desc)).putShort(0);
|
||||
return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
|
||||
// Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
|
||||
annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0);
|
||||
return new AnnotationWriter(symbolTable, annotation, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(final String name) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
// Case of an element_value with an array_value field.
|
||||
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
// write tag, and reserve space for array size
|
||||
bv.put12('[', 0);
|
||||
return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
|
||||
// Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the
|
||||
// end of an element_value of array type is similar to the end of an 'annotation' structure: an
|
||||
// unsigned short num_values followed by num_values element_value, versus an unsigned short
|
||||
// num_element_value_pairs, followed by num_element_value_pairs { element_name_index,
|
||||
// element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to
|
||||
// visit the array elements. Its num_element_value_pairs will correspond to the number of array
|
||||
// elements and will be stored in what is in fact num_values.
|
||||
annotation.put12('[', 0);
|
||||
return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (parent != null) {
|
||||
byte[] data = parent.data;
|
||||
data[offset] = (byte) (size >>> 8);
|
||||
data[offset + 1] = (byte) size;
|
||||
if (numElementValuePairsOffset != -1) {
|
||||
byte[] data = annotation.data;
|
||||
data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8);
|
||||
data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the size of this annotation writer list.
|
||||
*
|
||||
* @return the size of this annotation writer list.
|
||||
*/
|
||||
int getSize() {
|
||||
int size = 0;
|
||||
AnnotationWriter aw = this;
|
||||
while (aw != null) {
|
||||
size += aw.bv.length;
|
||||
aw = aw.next;
|
||||
* Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation
|
||||
* and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name
|
||||
* to the constant pool of the class (if not null).
|
||||
*
|
||||
* @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
|
||||
* @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
|
||||
* annotation and all its predecessors. This includes the size of the attribute_name_index and
|
||||
* attribute_length fields.
|
||||
*/
|
||||
int computeAnnotationsSize(final String attributeName) {
|
||||
if (attributeName != null) {
|
||||
symbolTable.addConstantUtf8(attributeName);
|
||||
}
|
||||
return size;
|
||||
// The attribute_name_index, attribute_length and num_annotations fields use 8 bytes.
|
||||
int attributeSize = 8;
|
||||
AnnotationWriter annotationWriter = this;
|
||||
while (annotationWriter != null) {
|
||||
attributeSize += annotationWriter.annotation.length;
|
||||
annotationWriter = annotationWriter.previousAnnotation;
|
||||
}
|
||||
return attributeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the annotations of this annotation writer list into the given byte
|
||||
* vector.
|
||||
*
|
||||
* @param out
|
||||
* where the annotations must be put.
|
||||
*/
|
||||
void put(final ByteVector out) {
|
||||
int n = 0;
|
||||
int size = 2;
|
||||
AnnotationWriter aw = this;
|
||||
AnnotationWriter last = null;
|
||||
while (aw != null) {
|
||||
++n;
|
||||
size += aw.bv.length;
|
||||
aw.visitEnd(); // in case user forgot to call visitEnd
|
||||
aw.prev = last;
|
||||
last = aw;
|
||||
aw = aw.next;
|
||||
* Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
|
||||
* <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
|
||||
* put in the same order they have been visited.
|
||||
*
|
||||
* @param attributeNameIndex the constant pool index of the attribute name (one of
|
||||
* "Runtime[In]Visible[Type]Annotations").
|
||||
* @param output where the attribute must be put.
|
||||
*/
|
||||
void putAnnotations(final int attributeNameIndex, final ByteVector output) {
|
||||
int attributeLength = 2; // For num_annotations.
|
||||
int numAnnotations = 0;
|
||||
AnnotationWriter annotationWriter = this;
|
||||
AnnotationWriter firstAnnotation = null;
|
||||
while (annotationWriter != null) {
|
||||
// In case the user forgot to call visitEnd().
|
||||
annotationWriter.visitEnd();
|
||||
attributeLength += annotationWriter.annotation.length;
|
||||
numAnnotations++;
|
||||
firstAnnotation = annotationWriter;
|
||||
annotationWriter = annotationWriter.previousAnnotation;
|
||||
}
|
||||
out.putInt(size);
|
||||
out.putShort(n);
|
||||
aw = last;
|
||||
while (aw != null) {
|
||||
out.putByteArray(aw.bv.data, 0, aw.bv.length);
|
||||
aw = aw.prev;
|
||||
output.putShort(attributeNameIndex);
|
||||
output.putInt(attributeLength);
|
||||
output.putShort(numAnnotations);
|
||||
annotationWriter = firstAnnotation;
|
||||
while (annotationWriter != null) {
|
||||
output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
|
||||
annotationWriter = annotationWriter.nextAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given annotation lists into the given byte vector.
|
||||
*
|
||||
* @param panns
|
||||
* an array of annotation writer lists.
|
||||
* @param off
|
||||
* index of the first annotation to be written.
|
||||
* @param out
|
||||
* where the annotations must be put.
|
||||
*/
|
||||
static void put(final AnnotationWriter[] panns, final int off,
|
||||
final ByteVector out) {
|
||||
int size = 1 + 2 * (panns.length - off);
|
||||
for (int i = off; i < panns.length; ++i) {
|
||||
size += panns[i] == null ? 0 : panns[i].getSize();
|
||||
* Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the
|
||||
* annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the
|
||||
* constant pool of the class.
|
||||
*
|
||||
* @param attributeName one of "Runtime[In]VisibleParameterAnnotations".
|
||||
* @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
|
||||
* element).
|
||||
* @param annotableParameterCount the number of elements in annotationWriters to take into account
|
||||
* (elements [0..annotableParameterCount[ are taken into account).
|
||||
* @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding
|
||||
* to the given sub-array of AnnotationWriter lists. This includes the size of the
|
||||
* attribute_name_index and attribute_length fields.
|
||||
*/
|
||||
static int computeParameterAnnotationsSize(
|
||||
final String attributeName,
|
||||
final AnnotationWriter[] annotationWriters,
|
||||
final int annotableParameterCount) {
|
||||
// Note: attributeName is added to the constant pool by the call to computeAnnotationsSize
|
||||
// below. This assumes that there is at least one non-null element in the annotationWriters
|
||||
// sub-array (which is ensured by the lazy instantiation of this array in MethodWriter).
|
||||
// The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each
|
||||
// element of the parameter_annotations array uses 2 bytes for its num_annotations field.
|
||||
int attributeSize = 7 + 2 * annotableParameterCount;
|
||||
for (int i = 0; i < annotableParameterCount; ++i) {
|
||||
AnnotationWriter annotationWriter = annotationWriters[i];
|
||||
attributeSize +=
|
||||
annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8;
|
||||
}
|
||||
out.putInt(size).putByte(panns.length - off);
|
||||
for (int i = off; i < panns.length; ++i) {
|
||||
AnnotationWriter aw = panns[i];
|
||||
AnnotationWriter last = null;
|
||||
int n = 0;
|
||||
while (aw != null) {
|
||||
++n;
|
||||
aw.visitEnd(); // in case user forgot to call visitEnd
|
||||
aw.prev = last;
|
||||
last = aw;
|
||||
aw = aw.next;
|
||||
return attributeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists
|
||||
* from the given AnnotationWriter sub-array in the given ByteVector.
|
||||
*
|
||||
* @param attributeNameIndex constant pool index of the attribute name (one of
|
||||
* Runtime[In]VisibleParameterAnnotations).
|
||||
* @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i>
|
||||
* element).
|
||||
* @param annotableParameterCount the number of elements in annotationWriters to put (elements
|
||||
* [0..annotableParameterCount[ are put).
|
||||
* @param output where the attribute must be put.
|
||||
*/
|
||||
static void putParameterAnnotations(
|
||||
final int attributeNameIndex,
|
||||
final AnnotationWriter[] annotationWriters,
|
||||
final int annotableParameterCount,
|
||||
final ByteVector output) {
|
||||
// The num_parameters field uses 1 byte, and each element of the parameter_annotations array
|
||||
// uses 2 bytes for its num_annotations field.
|
||||
int attributeLength = 1 + 2 * annotableParameterCount;
|
||||
for (int i = 0; i < annotableParameterCount; ++i) {
|
||||
AnnotationWriter annotationWriter = annotationWriters[i];
|
||||
attributeLength +=
|
||||
annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8;
|
||||
}
|
||||
output.putShort(attributeNameIndex);
|
||||
output.putInt(attributeLength);
|
||||
output.putByte(annotableParameterCount);
|
||||
for (int i = 0; i < annotableParameterCount; ++i) {
|
||||
AnnotationWriter annotationWriter = annotationWriters[i];
|
||||
AnnotationWriter firstAnnotation = null;
|
||||
int numAnnotations = 0;
|
||||
while (annotationWriter != null) {
|
||||
// In case user the forgot to call visitEnd().
|
||||
annotationWriter.visitEnd();
|
||||
numAnnotations++;
|
||||
firstAnnotation = annotationWriter;
|
||||
annotationWriter = annotationWriter.previousAnnotation;
|
||||
}
|
||||
out.putShort(n);
|
||||
aw = last;
|
||||
while (aw != null) {
|
||||
out.putByteArray(aw.bv.data, 0, aw.bv.length);
|
||||
aw = aw.prev;
|
||||
output.putShort(numAnnotations);
|
||||
annotationWriter = firstAnnotation;
|
||||
while (annotationWriter != null) {
|
||||
output.putByteArray(
|
||||
annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
|
||||
annotationWriter = annotationWriter.nextAnnotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given type reference and type path into the given bytevector.
|
||||
* LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. See {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param out
|
||||
* where the type reference and type path must be put.
|
||||
*/
|
||||
static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
|
||||
switch (typeRef >>> 24) {
|
||||
case 0x00: // CLASS_TYPE_PARAMETER
|
||||
case 0x01: // METHOD_TYPE_PARAMETER
|
||||
case 0x16: // METHOD_FORMAL_PARAMETER
|
||||
out.putShort(typeRef >>> 16);
|
||||
break;
|
||||
case 0x13: // FIELD
|
||||
case 0x14: // METHOD_RETURN
|
||||
case 0x15: // METHOD_RECEIVER
|
||||
out.putByte(typeRef >>> 24);
|
||||
break;
|
||||
case 0x47: // CAST
|
||||
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
|
||||
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
|
||||
out.putInt(typeRef);
|
||||
break;
|
||||
// case 0x10: // CLASS_EXTENDS
|
||||
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
|
||||
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
|
||||
// case 0x17: // THROWS
|
||||
// case 0x42: // EXCEPTION_PARAMETER
|
||||
// case 0x43: // INSTANCEOF
|
||||
// case 0x44: // NEW
|
||||
// case 0x45: // CONSTRUCTOR_REFERENCE
|
||||
// case 0x46: // METHOD_REFERENCE
|
||||
default:
|
||||
out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
|
||||
break;
|
||||
}
|
||||
if (typePath == null) {
|
||||
out.putByte(0);
|
||||
} else {
|
||||
int length = typePath.b[typePath.offset] * 2 + 1;
|
||||
out.putByteArray(typePath.b, typePath.offset, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,297 +58,299 @@
|
|||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A non standard class, field, method or code attribute.
|
||||
* A non standard class, field, method or code attribute, as defined in the Java Virtual Machine
|
||||
* Specification (JVMS).
|
||||
*
|
||||
* @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS
|
||||
* 4.7</a>
|
||||
* @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
|
||||
* 4.7.3</a>
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class Attribute {
|
||||
|
||||
/**
|
||||
* The type of this attribute.
|
||||
*/
|
||||
/** The type of this attribute, also called its name in the JVMS. */
|
||||
public final String type;
|
||||
|
||||
/**
|
||||
* The raw value of this attribute, used only for unknown attributes.
|
||||
*/
|
||||
byte[] value;
|
||||
* The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}).
|
||||
* The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i>
|
||||
* included.
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
/**
|
||||
* The next attribute in this attribute list. May be <tt>null</tt>.
|
||||
*/
|
||||
Attribute next;
|
||||
* The next attribute in this attribute list (Attribute instances can be linked via this field to
|
||||
* store a list of class, field, method or code attributes). May be {@literal null}.
|
||||
*/
|
||||
Attribute nextAttribute;
|
||||
|
||||
/**
|
||||
* Constructs a new empty attribute.
|
||||
*
|
||||
* @param type
|
||||
* the type of the attribute.
|
||||
*/
|
||||
* Constructs a new empty attribute.
|
||||
*
|
||||
* @param type the type of the attribute.
|
||||
*/
|
||||
protected Attribute(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this type of attribute is unknown. The default
|
||||
* implementation of this method always returns <tt>true</tt>.
|
||||
*
|
||||
* @return <tt>true</tt> if this type of attribute is unknown.
|
||||
*/
|
||||
* Returns {@literal true} if this type of attribute is unknown. This means that the attribute
|
||||
* content can't be parsed to extract constant pool references, labels, etc. Instead, the
|
||||
* attribute content is read as an opaque byte array, and written back as is. This can lead to
|
||||
* invalid attributes, if the content actually contains constant pool references, labels, or other
|
||||
* symbolic references that need to be updated when there are changes to the constant pool, the
|
||||
* method bytecode, etc. The default implementation of this method always returns {@literal true}.
|
||||
*
|
||||
* @return {@literal true} if this type of attribute is unknown.
|
||||
*/
|
||||
public boolean isUnknown() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this type of attribute is a code attribute.
|
||||
*
|
||||
* @return <tt>true</tt> if this type of attribute is a code attribute.
|
||||
*/
|
||||
* Returns {@literal true} if this type of attribute is a code attribute.
|
||||
*
|
||||
* @return {@literal true} if this type of attribute is a code attribute.
|
||||
*/
|
||||
public boolean isCodeAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the labels corresponding to this attribute.
|
||||
*
|
||||
* @return the labels corresponding to this attribute, or <tt>null</tt> if
|
||||
* this attribute is not a code attribute that contains labels.
|
||||
*/
|
||||
* Returns the labels corresponding to this attribute.
|
||||
*
|
||||
* @return the labels corresponding to this attribute, or {@literal null} if this attribute is not
|
||||
* a code attribute that contains labels.
|
||||
*/
|
||||
protected Label[] getLabels() {
|
||||
return null;
|
||||
return new Label[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a {@link #type type} attribute. This method must return a
|
||||
* <i>new</i> {@link Attribute} object, of type {@link #type type},
|
||||
* corresponding to the <tt>len</tt> bytes starting at the given offset, in
|
||||
* the given class reader.
|
||||
*
|
||||
* @param cr
|
||||
* the class that contains the attribute to be read.
|
||||
* @param off
|
||||
* index of the first byte of the attribute's content in
|
||||
* {@link ClassReader#b cr.b}. The 6 attribute header bytes,
|
||||
* containing the type and the length of the attribute, are not
|
||||
* taken into account here.
|
||||
* @param len
|
||||
* the length of the attribute's content.
|
||||
* @param buf
|
||||
* buffer to be used to call {@link ClassReader#readUTF8
|
||||
* readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
|
||||
* or {@link ClassReader#readConst readConst}.
|
||||
* @param codeOff
|
||||
* index of the first byte of code's attribute content in
|
||||
* {@link ClassReader#b cr.b}, or -1 if the attribute to be read
|
||||
* is not a code attribute. The 6 attribute header bytes,
|
||||
* containing the type and the length of the attribute, are not
|
||||
* taken into account here.
|
||||
* @param labels
|
||||
* the labels of the method's code, or <tt>null</tt> if the
|
||||
* attribute to be read is not a code attribute.
|
||||
* @return a <i>new</i> {@link Attribute} object corresponding to the given
|
||||
* bytes.
|
||||
*/
|
||||
protected Attribute read(final ClassReader cr, final int off,
|
||||
final int len, final char[] buf, final int codeOff,
|
||||
* Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object,
|
||||
* of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given
|
||||
* ClassReader.
|
||||
*
|
||||
* @param classReader the class that contains the attribute to be read.
|
||||
* @param offset index of the first byte of the attribute's content in {@link ClassReader#b}. The
|
||||
* 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
|
||||
* account here.
|
||||
* @param length the length of the attribute's content (excluding the 6 attribute header bytes).
|
||||
* @param charBuffer the buffer to be used to call the ClassReader methods requiring a
|
||||
* 'charBuffer' parameter.
|
||||
* @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute
|
||||
* in {@link ClassReader#b}, or -1 if the attribute to be read is not a code attribute. The 6
|
||||
* attribute header bytes (attribute_name_index and attribute_length) are not taken into
|
||||
* account here.
|
||||
* @param labels the labels of the method's code, or {@literal null} if the attribute to be read
|
||||
* is not a code attribute.
|
||||
* @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes.
|
||||
*/
|
||||
protected Attribute read(
|
||||
final ClassReader classReader,
|
||||
final int offset,
|
||||
final int length,
|
||||
final char[] charBuffer,
|
||||
final int codeAttributeOffset,
|
||||
final Label[] labels) {
|
||||
Attribute attr = new Attribute(type);
|
||||
attr.value = new byte[len];
|
||||
System.arraycopy(cr.b, off, attr.value, 0, len);
|
||||
return attr;
|
||||
Attribute attribute = new Attribute(type);
|
||||
attribute.content = new byte[length];
|
||||
System.arraycopy(classReader.b, offset, attribute.content, 0, length);
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte array form of this attribute.
|
||||
*
|
||||
* @param cw
|
||||
* the class to which this attribute must be added. This
|
||||
* parameter can be used to add to the constant pool of this
|
||||
* class the items that corresponds to this attribute.
|
||||
* @param code
|
||||
* the bytecode of the method corresponding to this code
|
||||
* attribute, or <tt>null</tt> if this attribute is not a code
|
||||
* attributes.
|
||||
* @param len
|
||||
* the length of the bytecode of the method corresponding to this
|
||||
* code attribute, or <tt>null</tt> if this attribute is not a
|
||||
* code attribute.
|
||||
* @param maxStack
|
||||
* the maximum stack size of the method corresponding to this
|
||||
* code attribute, or -1 if this attribute is not a code
|
||||
* attribute.
|
||||
* @param maxLocals
|
||||
* the maximum number of local variables of the method
|
||||
* corresponding to this code attribute, or -1 if this attribute
|
||||
* is not a code attribute.
|
||||
* @return the byte array form of this attribute.
|
||||
*/
|
||||
protected ByteVector write(final ClassWriter cw, final byte[] code,
|
||||
final int len, final int maxStack, final int maxLocals) {
|
||||
ByteVector v = new ByteVector();
|
||||
v.data = value;
|
||||
v.length = value.length;
|
||||
return v;
|
||||
* Returns the byte array form of the content of this attribute. The 6 header bytes
|
||||
* (attribute_name_index and attribute_length) must <i>not</i> be added in the returned
|
||||
* ByteVector.
|
||||
*
|
||||
* @param classWriter the class to which this attribute must be added. This parameter can be used
|
||||
* to add the items that corresponds to this attribute to the constant pool of this class.
|
||||
* @param code the bytecode of the method corresponding to this code attribute, or {@literal null}
|
||||
* if this attribute is not a code attribute. Corresponds to the 'code' field of the Code
|
||||
* attribute.
|
||||
* @param codeLength the length of the bytecode of the method corresponding to this code
|
||||
* attribute, or 0 if this attribute is not a code attribute. Corresponds to the 'code_length'
|
||||
* field of the Code attribute.
|
||||
* @param maxStack the maximum stack size of the method corresponding to this code attribute, or
|
||||
* -1 if this attribute is not a code attribute.
|
||||
* @param maxLocals the maximum number of local variables of the method corresponding to this code
|
||||
* attribute, or -1 if this attribute is not a code attribute.
|
||||
* @return the byte array form of this attribute.
|
||||
*/
|
||||
protected ByteVector write(
|
||||
final ClassWriter classWriter,
|
||||
final byte[] code,
|
||||
final int codeLength,
|
||||
final int maxStack,
|
||||
final int maxLocals) {
|
||||
return new ByteVector(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the attribute list that begins with this attribute.
|
||||
*
|
||||
* @return the length of the attribute list that begins with this attribute.
|
||||
*/
|
||||
final int getCount() {
|
||||
* Returns the number of attributes of the attribute list that begins with this attribute.
|
||||
*
|
||||
* @return the number of attributes of the attribute list that begins with this attribute.
|
||||
*/
|
||||
final int getAttributeCount() {
|
||||
int count = 0;
|
||||
Attribute attr = this;
|
||||
while (attr != null) {
|
||||
Attribute attribute = this;
|
||||
while (attribute != null) {
|
||||
count += 1;
|
||||
attr = attr.next;
|
||||
attribute = attribute.nextAttribute;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of all the attributes in this attribute list.
|
||||
*
|
||||
* @param cw
|
||||
* the class writer to be used to convert the attributes into
|
||||
* byte arrays, with the {@link #write write} method.
|
||||
* @param code
|
||||
* the bytecode of the method corresponding to these code
|
||||
* attributes, or <tt>null</tt> if these attributes are not code
|
||||
* attributes.
|
||||
* @param len
|
||||
* the length of the bytecode of the method corresponding to
|
||||
* these code attributes, or <tt>null</tt> if these attributes
|
||||
* are not code attributes.
|
||||
* @param maxStack
|
||||
* the maximum stack size of the method corresponding to these
|
||||
* code attributes, or -1 if these attributes are not code
|
||||
* attributes.
|
||||
* @param maxLocals
|
||||
* the maximum number of local variables of the method
|
||||
* corresponding to these code attributes, or -1 if these
|
||||
* attributes are not code attributes.
|
||||
* @return the size of all the attributes in this attribute list. This size
|
||||
* includes the size of the attribute headers.
|
||||
*/
|
||||
final int getSize(final ClassWriter cw, final byte[] code, final int len,
|
||||
final int maxStack, final int maxLocals) {
|
||||
Attribute attr = this;
|
||||
* Returns the total size in bytes of all the attributes in the attribute list that begins with
|
||||
* this attribute. This size includes the 6 header bytes (attribute_name_index and
|
||||
* attribute_length) per attribute. Also adds the attribute type names to the constant pool.
|
||||
*
|
||||
* @param symbolTable where the constants used in the attributes must be stored.
|
||||
* @return the size of all the attributes in this attribute list. This size includes the size of
|
||||
* the attribute headers.
|
||||
*/
|
||||
final int computeAttributesSize(final SymbolTable symbolTable) {
|
||||
final byte[] code = null;
|
||||
final int codeLength = 0;
|
||||
final int maxStack = -1;
|
||||
final int maxLocals = -1;
|
||||
return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total size in bytes of all the attributes in the attribute list that begins with
|
||||
* this attribute. This size includes the 6 header bytes (attribute_name_index and
|
||||
* attribute_length) per attribute. Also adds the attribute type names to the constant pool.
|
||||
*
|
||||
* @param symbolTable where the constants used in the attributes must be stored.
|
||||
* @param code the bytecode of the method corresponding to these code attributes, or {@literal
|
||||
* null} if they are not code attributes. Corresponds to the 'code' field of the Code
|
||||
* attribute.
|
||||
* @param codeLength the length of the bytecode of the method corresponding to these code
|
||||
* attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
|
||||
* the Code attribute.
|
||||
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or
|
||||
* -1 if they are not code attributes.
|
||||
* @param maxLocals the maximum number of local variables of the method corresponding to these
|
||||
* code attributes, or -1 if they are not code attribute.
|
||||
* @return the size of all the attributes in this attribute list. This size includes the size of
|
||||
* the attribute headers.
|
||||
*/
|
||||
final int computeAttributesSize(
|
||||
final SymbolTable symbolTable,
|
||||
final byte[] code,
|
||||
final int codeLength,
|
||||
final int maxStack,
|
||||
final int maxLocals) {
|
||||
final ClassWriter classWriter = symbolTable.classWriter;
|
||||
int size = 0;
|
||||
while (attr != null) {
|
||||
cw.newUTF8(attr.type);
|
||||
size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
|
||||
attr = attr.next;
|
||||
Attribute attribute = this;
|
||||
while (attribute != null) {
|
||||
symbolTable.addConstantUtf8(attribute.type);
|
||||
size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length;
|
||||
attribute = attribute.nextAttribute;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all the attributes of this attribute list in the given byte
|
||||
* vector.
|
||||
*
|
||||
* @param cw
|
||||
* the class writer to be used to convert the attributes into
|
||||
* byte arrays, with the {@link #write write} method.
|
||||
* @param code
|
||||
* the bytecode of the method corresponding to these code
|
||||
* attributes, or <tt>null</tt> if these attributes are not code
|
||||
* attributes.
|
||||
* @param len
|
||||
* the length of the bytecode of the method corresponding to
|
||||
* these code attributes, or <tt>null</tt> if these attributes
|
||||
* are not code attributes.
|
||||
* @param maxStack
|
||||
* the maximum stack size of the method corresponding to these
|
||||
* code attributes, or -1 if these attributes are not code
|
||||
* attributes.
|
||||
* @param maxLocals
|
||||
* the maximum number of local variables of the method
|
||||
* corresponding to these code attributes, or -1 if these
|
||||
* attributes are not code attributes.
|
||||
* @param out
|
||||
* where the attributes must be written.
|
||||
*/
|
||||
final void put(final ClassWriter cw, final byte[] code, final int len,
|
||||
final int maxStack, final int maxLocals, final ByteVector out) {
|
||||
Attribute attr = this;
|
||||
while (attr != null) {
|
||||
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
|
||||
out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
|
||||
out.putByteArray(b.data, 0, b.length);
|
||||
attr = attr.next;
|
||||
* Puts all the attributes of the attribute list that begins with this attribute, in the given
|
||||
* byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
|
||||
* attribute.
|
||||
*
|
||||
* @param symbolTable where the constants used in the attributes must be stored.
|
||||
* @param output where the attributes must be written.
|
||||
*/
|
||||
final void putAttributes(final SymbolTable symbolTable, final ByteVector output) {
|
||||
final byte[] code = null;
|
||||
final int codeLength = 0;
|
||||
final int maxStack = -1;
|
||||
final int maxLocals = -1;
|
||||
putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all the attributes of the attribute list that begins with this attribute, in the given
|
||||
* byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
|
||||
* attribute.
|
||||
*
|
||||
* @param symbolTable where the constants used in the attributes must be stored.
|
||||
* @param code the bytecode of the method corresponding to these code attributes, or {@literal
|
||||
* null} if they are not code attributes. Corresponds to the 'code' field of the Code
|
||||
* attribute.
|
||||
* @param codeLength the length of the bytecode of the method corresponding to these code
|
||||
* attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
|
||||
* the Code attribute.
|
||||
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or
|
||||
* -1 if they are not code attributes.
|
||||
* @param maxLocals the maximum number of local variables of the method corresponding to these
|
||||
* code attributes, or -1 if they are not code attribute.
|
||||
* @param output where the attributes must be written.
|
||||
*/
|
||||
final void putAttributes(
|
||||
final SymbolTable symbolTable,
|
||||
final byte[] code,
|
||||
final int codeLength,
|
||||
final int maxStack,
|
||||
final int maxLocals,
|
||||
final ByteVector output) {
|
||||
final ClassWriter classWriter = symbolTable.classWriter;
|
||||
Attribute attribute = this;
|
||||
while (attribute != null) {
|
||||
ByteVector attributeContent =
|
||||
attribute.write(classWriter, code, codeLength, maxStack, maxLocals);
|
||||
// Put attribute_name_index and attribute_length.
|
||||
output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length);
|
||||
output.putByteArray(attributeContent.data, 0, attributeContent.length);
|
||||
attribute = attribute.nextAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
//The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely removed.
|
||||
//see also changes in ClassReader.accept.
|
||||
/** A set of attribute prototypes (attributes with the same type are considered equal). */
|
||||
static final class Set {
|
||||
|
||||
public static class NestMembers extends Attribute {
|
||||
public NestMembers() {
|
||||
super("NestMembers");
|
||||
}
|
||||
private static final int SIZE_INCREMENT = 6;
|
||||
|
||||
byte[] bytes;
|
||||
String[] classes;
|
||||
private int size;
|
||||
private Attribute[] data = new Attribute[SIZE_INCREMENT];
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
|
||||
int offset = off;
|
||||
NestMembers a = new NestMembers();
|
||||
int size = cr.readShort(off);
|
||||
a.classes = new String[size];
|
||||
off += 2;
|
||||
for (int i = 0; i < size ; i++) {
|
||||
a.classes[i] = cr.readClass(off, buf);
|
||||
off += 2;
|
||||
void addAttributes(final Attribute attributeList) {
|
||||
Attribute attribute = attributeList;
|
||||
while (attribute != null) {
|
||||
if (!contains(attribute)) {
|
||||
add(attribute);
|
||||
}
|
||||
attribute = attribute.nextAttribute;
|
||||
}
|
||||
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector(bytes.length);
|
||||
v.putShort(classes.length);
|
||||
for (String s : classes) {
|
||||
v.putShort(cw.newClass(s));
|
||||
Attribute[] toArray() {
|
||||
Attribute[] result = new Attribute[size];
|
||||
System.arraycopy(data, 0, result, 0, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean contains(final Attribute attribute) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (data[i].type.equals(attribute.type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void add(final Attribute attribute) {
|
||||
if (size >= data.length) {
|
||||
Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT];
|
||||
System.arraycopy(data, 0, newData, 0, size);
|
||||
data = newData;
|
||||
}
|
||||
data[size++] = attribute;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NestHost extends Attribute {
|
||||
|
||||
byte[] bytes;
|
||||
String clazz;
|
||||
|
||||
public NestHost() {
|
||||
super("NestHost");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
|
||||
int offset = off;
|
||||
NestHost a = new NestHost();
|
||||
a.clazz = cr.readClass(off, buf);
|
||||
a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector(bytes.length);
|
||||
v.putShort(cw.newClass(clazz));
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
static final Attribute[] DEFAULT_ATTRIBUTE_PROTOS = new Attribute[] {
|
||||
new NestMembers(),
|
||||
new NestHost()
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,309 +59,333 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A dynamically extensible vector of bytes. This class is roughly equivalent to
|
||||
* a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
|
||||
* A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream
|
||||
* on top of a ByteArrayOutputStream, but is more efficient.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class ByteVector {
|
||||
|
||||
/**
|
||||
* The content of this vector.
|
||||
*/
|
||||
/** The content of this vector. Only the first {@link #length} bytes contain real data. */
|
||||
byte[] data;
|
||||
|
||||
/**
|
||||
* Actual number of bytes in this vector.
|
||||
*/
|
||||
/** The actual number of bytes in this vector. */
|
||||
int length;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ByteVector ByteVector} with a default initial
|
||||
* size.
|
||||
*/
|
||||
/** Constructs a new {@link ByteVector} with a default initial capacity. */
|
||||
public ByteVector() {
|
||||
data = new byte[64];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ByteVector ByteVector} with the given initial
|
||||
* size.
|
||||
*
|
||||
* @param initialSize
|
||||
* the initial size of the byte vector to be constructed.
|
||||
*/
|
||||
public ByteVector(final int initialSize) {
|
||||
data = new byte[initialSize];
|
||||
* Constructs a new {@link ByteVector} with the given initial capacity.
|
||||
*
|
||||
* @param initialCapacity the initial capacity of the byte vector to be constructed.
|
||||
*/
|
||||
public ByteVector(final int initialCapacity) {
|
||||
data = new byte[initialCapacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a byte into this byte vector. The byte vector is automatically
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param b
|
||||
* a byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByte(final int b) {
|
||||
int length = this.length;
|
||||
if (length + 1 > data.length) {
|
||||
* Constructs a new {@link ByteVector} from the given initial data.
|
||||
*
|
||||
* @param data the initial data of the new byte vector.
|
||||
*/
|
||||
ByteVector(final byte[] data) {
|
||||
this.data = data;
|
||||
this.length = data.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param byteValue a byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByte(final int byteValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 1 > data.length) {
|
||||
enlarge(1);
|
||||
}
|
||||
data[length++] = (byte) b;
|
||||
this.length = length;
|
||||
data[currentLength++] = (byte) byteValue;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts two bytes into this byte vector. The byte vector is automatically
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param b1
|
||||
* a byte.
|
||||
* @param b2
|
||||
* another byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
ByteVector put11(final int b1, final int b2) {
|
||||
int length = this.length;
|
||||
if (length + 2 > data.length) {
|
||||
* Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param byteValue1 a byte.
|
||||
* @param byteValue2 another byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put11(final int byteValue1, final int byteValue2) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 2 > data.length) {
|
||||
enlarge(2);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
data[length++] = (byte) b1;
|
||||
data[length++] = (byte) b2;
|
||||
this.length = length;
|
||||
byte[] currentData = data;
|
||||
currentData[currentLength++] = (byte) byteValue1;
|
||||
currentData[currentLength++] = (byte) byteValue2;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a short into this byte vector. The byte vector is automatically
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param s
|
||||
* a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putShort(final int s) {
|
||||
int length = this.length;
|
||||
if (length + 2 > data.length) {
|
||||
* Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param shortValue a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putShort(final int shortValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 2 > data.length) {
|
||||
enlarge(2);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
data[length++] = (byte) (s >>> 8);
|
||||
data[length++] = (byte) s;
|
||||
this.length = length;
|
||||
byte[] currentData = data;
|
||||
currentData[currentLength++] = (byte) (shortValue >>> 8);
|
||||
currentData[currentLength++] = (byte) shortValue;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a byte and a short into this byte vector. The byte vector is
|
||||
* automatically enlarged if necessary.
|
||||
*
|
||||
* @param b
|
||||
* a byte.
|
||||
* @param s
|
||||
* a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
ByteVector put12(final int b, final int s) {
|
||||
int length = this.length;
|
||||
if (length + 3 > data.length) {
|
||||
* Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param byteValue a byte.
|
||||
* @param shortValue a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put12(final int byteValue, final int shortValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 3 > data.length) {
|
||||
enlarge(3);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
data[length++] = (byte) b;
|
||||
data[length++] = (byte) (s >>> 8);
|
||||
data[length++] = (byte) s;
|
||||
this.length = length;
|
||||
byte[] currentData = data;
|
||||
currentData[currentLength++] = (byte) byteValue;
|
||||
currentData[currentLength++] = (byte) (shortValue >>> 8);
|
||||
currentData[currentLength++] = (byte) shortValue;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an int into this byte vector. The byte vector is automatically
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param i
|
||||
* an int.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putInt(final int i) {
|
||||
int length = this.length;
|
||||
if (length + 4 > data.length) {
|
||||
* Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param byteValue1 a byte.
|
||||
* @param byteValue2 another byte.
|
||||
* @param shortValue a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 4 > data.length) {
|
||||
enlarge(4);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
data[length++] = (byte) (i >>> 24);
|
||||
data[length++] = (byte) (i >>> 16);
|
||||
data[length++] = (byte) (i >>> 8);
|
||||
data[length++] = (byte) i;
|
||||
this.length = length;
|
||||
byte[] currentData = data;
|
||||
currentData[currentLength++] = (byte) byteValue1;
|
||||
currentData[currentLength++] = (byte) byteValue2;
|
||||
currentData[currentLength++] = (byte) (shortValue >>> 8);
|
||||
currentData[currentLength++] = (byte) shortValue;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a long into this byte vector. The byte vector is automatically
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param l
|
||||
* a long.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putLong(final long l) {
|
||||
int length = this.length;
|
||||
if (length + 8 > data.length) {
|
||||
* Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param intValue an int.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putInt(final int intValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 4 > data.length) {
|
||||
enlarge(4);
|
||||
}
|
||||
byte[] currentData = data;
|
||||
currentData[currentLength++] = (byte) (intValue >>> 24);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 16);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 8);
|
||||
currentData[currentLength++] = (byte) intValue;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged
|
||||
* if necessary.
|
||||
*
|
||||
* @param byteValue a byte.
|
||||
* @param shortValue1 a short.
|
||||
* @param shortValue2 another short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 5 > data.length) {
|
||||
enlarge(5);
|
||||
}
|
||||
byte[] currentData = data;
|
||||
currentData[currentLength++] = (byte) byteValue;
|
||||
currentData[currentLength++] = (byte) (shortValue1 >>> 8);
|
||||
currentData[currentLength++] = (byte) shortValue1;
|
||||
currentData[currentLength++] = (byte) (shortValue2 >>> 8);
|
||||
currentData[currentLength++] = (byte) shortValue2;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param longValue a long.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putLong(final long longValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 8 > data.length) {
|
||||
enlarge(8);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
int i = (int) (l >>> 32);
|
||||
data[length++] = (byte) (i >>> 24);
|
||||
data[length++] = (byte) (i >>> 16);
|
||||
data[length++] = (byte) (i >>> 8);
|
||||
data[length++] = (byte) i;
|
||||
i = (int) l;
|
||||
data[length++] = (byte) (i >>> 24);
|
||||
data[length++] = (byte) (i >>> 16);
|
||||
data[length++] = (byte) (i >>> 8);
|
||||
data[length++] = (byte) i;
|
||||
this.length = length;
|
||||
byte[] currentData = data;
|
||||
int intValue = (int) (longValue >>> 32);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 24);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 16);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 8);
|
||||
currentData[currentLength++] = (byte) intValue;
|
||||
intValue = (int) longValue;
|
||||
currentData[currentLength++] = (byte) (intValue >>> 24);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 16);
|
||||
currentData[currentLength++] = (byte) (intValue >>> 8);
|
||||
currentData[currentLength++] = (byte) intValue;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an UTF8 string into this byte vector. The byte vector is
|
||||
* automatically enlarged if necessary.
|
||||
*
|
||||
* @param s
|
||||
* a String whose UTF8 encoded length must be less than 65536.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putUTF8(final String s) {
|
||||
int charLength = s.length();
|
||||
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param stringValue a String whose UTF8 encoded length must be less than 65536.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
|
||||
public ByteVector putUTF8(final String stringValue) {
|
||||
int charLength = stringValue.length();
|
||||
if (charLength > 65535) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("UTF8 string too large");
|
||||
}
|
||||
int len = length;
|
||||
if (len + 2 + charLength > data.length) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 2 + charLength > data.length) {
|
||||
enlarge(2 + charLength);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
// optimistic algorithm: instead of computing the byte length and then
|
||||
// serializing the string (which requires two loops), we assume the byte
|
||||
// length is equal to char length (which is the most frequent case), and
|
||||
// we start serializing the string right away. During the serialization,
|
||||
// if we find that this assumption is wrong, we continue with the
|
||||
// general method.
|
||||
data[len++] = (byte) (charLength >>> 8);
|
||||
data[len++] = (byte) charLength;
|
||||
byte[] currentData = data;
|
||||
// Optimistic algorithm: instead of computing the byte length and then serializing the string
|
||||
// (which requires two loops), we assume the byte length is equal to char length (which is the
|
||||
// most frequent case), and we start serializing the string right away. During the
|
||||
// serialization, if we find that this assumption is wrong, we continue with the general method.
|
||||
currentData[currentLength++] = (byte) (charLength >>> 8);
|
||||
currentData[currentLength++] = (byte) charLength;
|
||||
for (int i = 0; i < charLength; ++i) {
|
||||
char c = s.charAt(i);
|
||||
if (c >= '\001' && c <= '\177') {
|
||||
data[len++] = (byte) c;
|
||||
char charValue = stringValue.charAt(i);
|
||||
if (charValue >= '\u0001' && charValue <= '\u007F') {
|
||||
currentData[currentLength++] = (byte) charValue;
|
||||
} else {
|
||||
length = len;
|
||||
return encodeUTF8(s, i, 65535);
|
||||
length = currentLength;
|
||||
return encodeUtf8(stringValue, i, 65535);
|
||||
}
|
||||
}
|
||||
length = len;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an UTF8 string into this byte vector. The byte vector is
|
||||
* automatically enlarged if necessary. The string length is encoded in two
|
||||
* bytes before the encoded characters, if there is space for that (i.e. if
|
||||
* this.length - i - 2 >= 0).
|
||||
*
|
||||
* @param s
|
||||
* the String to encode.
|
||||
* @param i
|
||||
* the index of the first character to encode. The previous
|
||||
* characters are supposed to have already been encoded, using
|
||||
* only one byte per character.
|
||||
* @param maxByteLength
|
||||
* the maximum byte length of the encoded string, including the
|
||||
* already encoded characters.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
|
||||
int charLength = s.length();
|
||||
int byteLength = i;
|
||||
char c;
|
||||
for (int j = i; j < charLength; ++j) {
|
||||
c = s.charAt(j);
|
||||
if (c >= '\001' && c <= '\177') {
|
||||
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary. The string length is encoded in two bytes before the encoded characters, if there is
|
||||
* space for that (i.e. if this.length - offset - 2 >= 0).
|
||||
*
|
||||
* @param stringValue the String to encode.
|
||||
* @param offset the index of the first character to encode. The previous characters are supposed
|
||||
* to have already been encoded, using only one byte per character.
|
||||
* @param maxByteLength the maximum byte length of the encoded string, including the already
|
||||
* encoded characters.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength) {
|
||||
int charLength = stringValue.length();
|
||||
int byteLength = offset;
|
||||
for (int i = offset; i < charLength; ++i) {
|
||||
char charValue = stringValue.charAt(i);
|
||||
if (charValue >= 0x0001 && charValue <= 0x007F) {
|
||||
byteLength++;
|
||||
} else if (c > '\u07FF') {
|
||||
byteLength += 3;
|
||||
} else {
|
||||
} else if (charValue <= 0x07FF) {
|
||||
byteLength += 2;
|
||||
} else {
|
||||
byteLength += 3;
|
||||
}
|
||||
}
|
||||
if (byteLength > maxByteLength) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("UTF8 string too large");
|
||||
}
|
||||
int start = length - i - 2;
|
||||
if (start >= 0) {
|
||||
data[start] = (byte) (byteLength >>> 8);
|
||||
data[start + 1] = (byte) byteLength;
|
||||
// Compute where 'byteLength' must be stored in 'data', and store it at this location.
|
||||
int byteLengthOffset = length - offset - 2;
|
||||
if (byteLengthOffset >= 0) {
|
||||
data[byteLengthOffset] = (byte) (byteLength >>> 8);
|
||||
data[byteLengthOffset + 1] = (byte) byteLength;
|
||||
}
|
||||
if (length + byteLength - i > data.length) {
|
||||
enlarge(byteLength - i);
|
||||
if (length + byteLength - offset > data.length) {
|
||||
enlarge(byteLength - offset);
|
||||
}
|
||||
int len = length;
|
||||
for (int j = i; j < charLength; ++j) {
|
||||
c = s.charAt(j);
|
||||
if (c >= '\001' && c <= '\177') {
|
||||
data[len++] = (byte) c;
|
||||
} else if (c > '\u07FF') {
|
||||
data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
|
||||
data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
|
||||
data[len++] = (byte) (0x80 | c & 0x3F);
|
||||
int currentLength = length;
|
||||
for (int i = offset; i < charLength; ++i) {
|
||||
char charValue = stringValue.charAt(i);
|
||||
if (charValue >= 0x0001 && charValue <= 0x007F) {
|
||||
data[currentLength++] = (byte) charValue;
|
||||
} else if (charValue <= 0x07FF) {
|
||||
data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F);
|
||||
data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
|
||||
} else {
|
||||
data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
|
||||
data[len++] = (byte) (0x80 | c & 0x3F);
|
||||
data[currentLength++] = (byte) (0xE0 | charValue >> 12 & 0xF);
|
||||
data[currentLength++] = (byte) (0x80 | charValue >> 6 & 0x3F);
|
||||
data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
|
||||
}
|
||||
}
|
||||
length = len;
|
||||
length = currentLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an array of bytes into this byte vector. The byte vector is
|
||||
* automatically enlarged if necessary.
|
||||
*
|
||||
* @param b
|
||||
* an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
|
||||
* null bytes into this byte vector.
|
||||
* @param off
|
||||
* index of the fist byte of b that must be copied.
|
||||
* @param len
|
||||
* number of bytes of b that must be copied.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByteArray(final byte[] b, final int off, final int len) {
|
||||
if (length + len > data.length) {
|
||||
enlarge(len);
|
||||
* Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param byteArrayValue an array of bytes. May be {@literal null} to put {@code byteLength} null
|
||||
* bytes into this byte vector.
|
||||
* @param byteOffset index of the first byte of byteArrayValue that must be copied.
|
||||
* @param byteLength number of bytes of byteArrayValue that must be copied.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByteArray(
|
||||
final byte[] byteArrayValue, final int byteOffset, final int byteLength) {
|
||||
if (length + byteLength > data.length) {
|
||||
enlarge(byteLength);
|
||||
}
|
||||
if (b != null) {
|
||||
System.arraycopy(b, off, data, length, len);
|
||||
if (byteArrayValue != null) {
|
||||
System.arraycopy(byteArrayValue, byteOffset, data, length, byteLength);
|
||||
}
|
||||
length += len;
|
||||
length += byteLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enlarge this byte vector so that it can receive n more bytes.
|
||||
*
|
||||
* @param size
|
||||
* number of additional bytes that this byte vector should be
|
||||
* able to receive.
|
||||
*/
|
||||
* Enlarges this byte vector so that it can receive 'size' more bytes.
|
||||
*
|
||||
* @param size number of additional bytes that this byte vector should be able to receive.
|
||||
*/
|
||||
private void enlarge(final int size) {
|
||||
int length1 = 2 * data.length;
|
||||
int length2 = length + size;
|
||||
byte[] newData = new byte[length1 > length2 ? length1 : length2];
|
||||
int doubleCapacity = 2 * data.length;
|
||||
int minimalCapacity = length + size;
|
||||
byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity];
|
||||
System.arraycopy(data, 0, newData, 0, length);
|
||||
data = newData;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* Exception thrown when the constant pool of a class produced by a {@link ClassWriter} is too
|
||||
* large.
|
||||
*
|
||||
* @author Jason Zaugg
|
||||
*/
|
||||
public final class ClassTooLargeException extends IndexOutOfBoundsException {
|
||||
private static final long serialVersionUID = 160715609518896765L;
|
||||
|
||||
private final String className;
|
||||
private final int constantPoolCount;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ClassTooLargeException}.
|
||||
*
|
||||
* @param className the internal name of the class.
|
||||
* @param constantPoolCount the number of constant pool items of the class.
|
||||
*/
|
||||
public ClassTooLargeException(final String className, final int constantPoolCount) {
|
||||
super("Class too large: " + className);
|
||||
this.className = className;
|
||||
this.constantPoolCount = constantPoolCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the internal name of the class.
|
||||
*
|
||||
* @return the internal name of the class.
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of constant pool items of the class.
|
||||
*
|
||||
* @return the number of constant pool items of the class.
|
||||
*/
|
||||
public int getConstantPoolCount() {
|
||||
return constantPoolCount;
|
||||
}
|
||||
}
|
||||
|
|
@ -59,122 +59,106 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java class. The methods of this class must be called in
|
||||
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
|
||||
* <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
||||
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
|
||||
* <tt>visitEnd</tt>.
|
||||
* A visitor to visit a Java class. The methods of this class must be called in the following order:
|
||||
* {@code visit} [ {@code visitSource} ] [ {@code visitModule} ][ {@code visitNestHost} ][ {@code
|
||||
* visitOuterClass} ] ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code
|
||||
* visitAttribute} )* ( {@code visitNestMember} | {@code visitInnerClass} | {@code visitField} |
|
||||
* {@code visitMethod} )* {@code visitEnd}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class ClassVisitor {
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The class visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
/** The class visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected ClassVisitor cv;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ClassVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Constructs a new {@link ClassVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public ClassVisitor(final int api) {
|
||||
this(api, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ClassVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param cv
|
||||
* the class visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public ClassVisitor(final int api, final ClassVisitor cv) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
* Constructs a new {@link ClassVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param classVisitor the class visitor to which this visitor must delegate method calls. May be
|
||||
* null.
|
||||
*/
|
||||
public ClassVisitor(final int api, final ClassVisitor classVisitor) {
|
||||
if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.cv = cv;
|
||||
this.cv = classVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the header of the class.
|
||||
*
|
||||
* @param version
|
||||
* the class version.
|
||||
* @param access
|
||||
* the class's access flags (see {@link Opcodes}). This parameter
|
||||
* also indicates if the class is deprecated.
|
||||
* @param name
|
||||
* the internal name of the class (see
|
||||
* {@link Type#getInternalName() getInternalName}).
|
||||
* @param signature
|
||||
* the signature of this class. May be <tt>null</tt> if the class
|
||||
* is not a generic one, and does not extend or implement generic
|
||||
* classes or interfaces.
|
||||
* @param superName
|
||||
* the internal of name of the super class (see
|
||||
* {@link Type#getInternalName() getInternalName}). For
|
||||
* interfaces, the super class is {@link Object}. May be
|
||||
* <tt>null</tt>, but only for the {@link Object} class.
|
||||
* @param interfaces
|
||||
* the internal names of the class's interfaces (see
|
||||
* {@link Type#getInternalName() getInternalName}). May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visit(int version, int access, String name, String signature,
|
||||
String superName, String[] interfaces) {
|
||||
* Visits the header of the class.
|
||||
*
|
||||
* @param version the class version. The minor version is stored in the 16 most significant bits,
|
||||
* and the major version in the 16 least significant bits.
|
||||
* @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the class is deprecated.
|
||||
* @param name the internal name of the class (see {@link Type#getInternalName()}).
|
||||
* @param signature the signature of this class. May be {@literal null} if the class is not a
|
||||
* generic one, and does not extend or implement generic classes or interfaces.
|
||||
* @param superName the internal of name of the super class (see {@link Type#getInternalName()}).
|
||||
* For interfaces, the super class is {@link Object}. May be {@literal null}, but only for the
|
||||
* {@link Object} class.
|
||||
* @param interfaces the internal names of the class's interfaces (see {@link
|
||||
* Type#getInternalName()}). May be {@literal null}.
|
||||
*/
|
||||
public void visit(
|
||||
final int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces) {
|
||||
if (cv != null) {
|
||||
cv.visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the source of the class.
|
||||
*
|
||||
* @param source
|
||||
* the name of the source file from which the class was compiled.
|
||||
* May be <tt>null</tt>.
|
||||
* @param debug
|
||||
* additional debug information to compute the correspondance
|
||||
* between source and compiled elements of the class. May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visitSource(String source, String debug) {
|
||||
* Visits the source of the class.
|
||||
*
|
||||
* @param source the name of the source file from which the class was compiled. May be {@literal
|
||||
* null}.
|
||||
* @param debug additional debug information to compute the correspondence between source and
|
||||
* compiled elements of the class. May be {@literal null}.
|
||||
*/
|
||||
public void visitSource(final String source, final String debug) {
|
||||
if (cv != null) {
|
||||
cv.visitSource(source, debug);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the module corresponding to the class.
|
||||
* @param name
|
||||
* module name
|
||||
* @param access
|
||||
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
|
||||
* and {@code ACC_MANDATED}.
|
||||
* @param version
|
||||
* module version or null.
|
||||
* @return a visitor to visit the module values, or <tt>null</tt> if
|
||||
* this visitor is not interested in visiting this module.
|
||||
*/
|
||||
public ModuleVisitor visitModule(String name, int access, String version) {
|
||||
* Visit the module corresponding to the class.
|
||||
*
|
||||
* @param name the fully qualified name (using dots) of the module.
|
||||
* @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
* @param version the module version, or {@literal null}.
|
||||
* @return a visitor to visit the module values, or {@literal null} if this visitor is not
|
||||
* interested in visiting this module.
|
||||
*/
|
||||
public ModuleVisitor visitModule(final String name, final int access, final String version) {
|
||||
if (api < Opcodes.ASM6) {
|
||||
throw new RuntimeException();
|
||||
throw new UnsupportedOperationException("This feature requires ASM6");
|
||||
}
|
||||
if (cv != null) {
|
||||
return cv.visitModule(name, access, version);
|
||||
|
|
@ -183,186 +167,191 @@ public abstract class ClassVisitor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Visits the enclosing class of the class. This method must be called only
|
||||
* if the class has an enclosing class.
|
||||
*
|
||||
* @param owner
|
||||
* internal name of the enclosing class of the class.
|
||||
* @param name
|
||||
* the name of the method that contains the class, or
|
||||
* <tt>null</tt> if the class is not enclosed in a method of its
|
||||
* enclosing class.
|
||||
* @param desc
|
||||
* the descriptor of the method that contains the class, or
|
||||
* <tt>null</tt> if the class is not enclosed in a method of its
|
||||
* enclosing class.
|
||||
*/
|
||||
public void visitOuterClass(String owner, String name, String desc) {
|
||||
* Visits the nest host class of the class. A nest is a set of classes of the same package that
|
||||
* share access to their private members. One of these classes, called the host, lists the other
|
||||
* members of the nest, which in turn should link to the host of their nest. This method must be
|
||||
* called only once and only if the visited class is a non-host member of a nest. A class is
|
||||
* implicitly its own nest, so it's invalid to call this method with the visited class name as
|
||||
* argument.
|
||||
*
|
||||
* @param nestHost the internal name of the host class of the nest.
|
||||
*/
|
||||
public void visitNestHost(final String nestHost) {
|
||||
if (api < Opcodes.ASM7) {
|
||||
throw new UnsupportedOperationException("This feature requires ASM7");
|
||||
}
|
||||
if (cv != null) {
|
||||
cv.visitOuterClass(owner, name, desc);
|
||||
cv.visitNestHost(nestHost);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation of the class.
|
||||
*
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
* @param visible
|
||||
* <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> if
|
||||
* this visitor is not interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
* Visits the enclosing class of the class. This method must be called only if the class has an
|
||||
* enclosing class.
|
||||
*
|
||||
* @param owner internal name of the enclosing class of the class.
|
||||
* @param name the name of the method that contains the class, or {@literal null} if the class is
|
||||
* not enclosed in a method of its enclosing class.
|
||||
* @param descriptor the descriptor of the method that contains the class, or {@literal null} if
|
||||
* the class is not enclosed in a method of its enclosing class.
|
||||
*/
|
||||
public void visitOuterClass(final String owner, final String name, final String descriptor) {
|
||||
if (cv != null) {
|
||||
return cv.visitAnnotation(desc, visible);
|
||||
cv.visitOuterClass(owner, name, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation of the class.
|
||||
*
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
* @param visible {@literal true} if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
|
||||
* interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
if (cv != null) {
|
||||
return cv.visitAnnotation(descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation on a type in the class signature.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. The sort of this type
|
||||
* reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
|
||||
* CLASS_TYPE_PARAMETER},
|
||||
* {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
|
||||
* CLASS_TYPE_PARAMETER_BOUND} or
|
||||
* {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
|
||||
* {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
* @param visible
|
||||
* <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> if
|
||||
* this visitor is not interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
* Visits an annotation on a type in the class signature.
|
||||
*
|
||||
* @param typeRef a reference to the annotated type. The sort of this type reference must be
|
||||
* {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link
|
||||
* TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See
|
||||
* {@link TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
* @param visible {@literal true} if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
|
||||
* interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
if (api < Opcodes.ASM5) {
|
||||
throw new RuntimeException();
|
||||
throw new UnsupportedOperationException("This feature requires ASM5");
|
||||
}
|
||||
if (cv != null) {
|
||||
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
return cv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a non standard attribute of the class.
|
||||
*
|
||||
* @param attr
|
||||
* an attribute.
|
||||
*/
|
||||
public void visitAttribute(Attribute attr) {
|
||||
* Visits a non standard attribute of the class.
|
||||
*
|
||||
* @param attribute an attribute.
|
||||
*/
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (cv != null) {
|
||||
cv.visitAttribute(attr);
|
||||
cv.visitAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits information about an inner class. This inner class is not
|
||||
* necessarily a member of the class being visited.
|
||||
*
|
||||
* @param name
|
||||
* the internal name of an inner class (see
|
||||
* {@link Type#getInternalName() getInternalName}).
|
||||
* @param outerName
|
||||
* the internal name of the class to which the inner class
|
||||
* belongs (see {@link Type#getInternalName() getInternalName}).
|
||||
* May be <tt>null</tt> for not member classes.
|
||||
* @param innerName
|
||||
* the (simple) name of the inner class inside its enclosing
|
||||
* class. May be <tt>null</tt> for anonymous inner classes.
|
||||
* @param access
|
||||
* the access flags of the inner class as originally declared in
|
||||
* the enclosing class.
|
||||
*/
|
||||
public void visitInnerClass(String name, String outerName,
|
||||
String innerName, int access) {
|
||||
* Visits a member of the nest. A nest is a set of classes of the same package that share access
|
||||
* to their private members. One of these classes, called the host, lists the other members of the
|
||||
* nest, which in turn should link to the host of their nest. This method must be called only if
|
||||
* the visited class is the host of a nest. A nest host is implicitly a member of its own nest, so
|
||||
* it's invalid to call this method with the visited class name as argument.
|
||||
*
|
||||
* @param nestMember the internal name of a nest member.
|
||||
*/
|
||||
public void visitNestMember(final String nestMember) {
|
||||
if (api < Opcodes.ASM7) {
|
||||
throw new UnsupportedOperationException("This feature requires ASM7");
|
||||
}
|
||||
if (cv != null) {
|
||||
cv.visitNestMember(nestMember);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits information about an inner class. This inner class is not necessarily a member of the
|
||||
* class being visited.
|
||||
*
|
||||
* @param name the internal name of an inner class (see {@link Type#getInternalName()}).
|
||||
* @param outerName the internal name of the class to which the inner class belongs (see {@link
|
||||
* Type#getInternalName()}). May be {@literal null} for not member classes.
|
||||
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
|
||||
* {@literal null} for anonymous inner classes.
|
||||
* @param access the access flags of the inner class as originally declared in the enclosing
|
||||
* class.
|
||||
*/
|
||||
public void visitInnerClass(
|
||||
final String name, final String outerName, final String innerName, final int access) {
|
||||
if (cv != null) {
|
||||
cv.visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a field of the class.
|
||||
*
|
||||
* @param access
|
||||
* the field's access flags (see {@link Opcodes}). This parameter
|
||||
* also indicates if the field is synthetic and/or deprecated.
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link Type Type}).
|
||||
* @param signature
|
||||
* the field's signature. May be <tt>null</tt> if the field's
|
||||
* type does not use generic types.
|
||||
* @param value
|
||||
* the field's initial value. This parameter, which may be
|
||||
* <tt>null</tt> if the field does not have an initial value,
|
||||
* must be an {@link Integer}, a {@link Float}, a {@link Long}, a
|
||||
* {@link Double} or a {@link String} (for <tt>int</tt>,
|
||||
* <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
|
||||
* respectively). <i>This parameter is only used for static
|
||||
* fields</i>. Its value is ignored for non static fields, which
|
||||
* must be initialized through bytecode instructions in
|
||||
* constructors or methods.
|
||||
* @return a visitor to visit field annotations and attributes, or
|
||||
* <tt>null</tt> if this class visitor is not interested in visiting
|
||||
* these annotations and attributes.
|
||||
*/
|
||||
public FieldVisitor visitField(int access, String name, String desc,
|
||||
String signature, Object value) {
|
||||
* Visits a field of the class.
|
||||
*
|
||||
* @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the field is synthetic and/or deprecated.
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link Type}).
|
||||
* @param signature the field's signature. May be {@literal null} if the field's type does not use
|
||||
* generic types.
|
||||
* @param value the field's initial value. This parameter, which may be {@literal null} if the
|
||||
* field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
|
||||
* Long}, a {@link Double} or a {@link String} (for {@code int}, {@code float}, {@code long}
|
||||
* or {@code String} fields respectively). <i>This parameter is only used for static
|
||||
* fields</i>. Its value is ignored for non static fields, which must be initialized through
|
||||
* bytecode instructions in constructors or methods.
|
||||
* @return a visitor to visit field annotations and attributes, or {@literal null} if this class
|
||||
* visitor is not interested in visiting these annotations and attributes.
|
||||
*/
|
||||
public FieldVisitor visitField(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
if (cv != null) {
|
||||
return cv.visitField(access, name, desc, signature, value);
|
||||
return cv.visitField(access, name, descriptor, signature, value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a method of the class. This method <i>must</i> return a new
|
||||
* {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
|
||||
* i.e., it should not return a previously returned visitor.
|
||||
*
|
||||
* @param access
|
||||
* the method's access flags (see {@link Opcodes}). This
|
||||
* parameter also indicates if the method is synthetic and/or
|
||||
* deprecated.
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link Type Type}).
|
||||
* @param signature
|
||||
* the method's signature. May be <tt>null</tt> if the method
|
||||
* parameters, return type and exceptions do not use generic
|
||||
* types.
|
||||
* @param exceptions
|
||||
* the internal names of the method's exception classes (see
|
||||
* {@link Type#getInternalName() getInternalName}). May be
|
||||
* <tt>null</tt>.
|
||||
* @return an object to visit the byte code of the method, or <tt>null</tt>
|
||||
* if this class visitor is not interested in visiting the code of
|
||||
* this method.
|
||||
*/
|
||||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions) {
|
||||
* Visits a method of the class. This method <i>must</i> return a new {@link MethodVisitor}
|
||||
* instance (or {@literal null}) each time it is called, i.e., it should not return a previously
|
||||
* returned visitor.
|
||||
*
|
||||
* @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the method is synthetic and/or deprecated.
|
||||
* @param name the method's name.
|
||||
* @param descriptor the method's descriptor (see {@link Type}).
|
||||
* @param signature the method's signature. May be {@literal null} if the method parameters,
|
||||
* return type and exceptions do not use generic types.
|
||||
* @param exceptions the internal names of the method's exception classes (see {@link
|
||||
* Type#getInternalName()}). May be {@literal null}.
|
||||
* @return an object to visit the byte code of the method, or {@literal null} if this class
|
||||
* visitor is not interested in visiting the code of this method.
|
||||
*/
|
||||
public MethodVisitor visitMethod(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
if (cv != null) {
|
||||
return cv.visitMethod(access, name, desc, signature, exceptions);
|
||||
return cv.visitMethod(access, name, descriptor, signature, exceptions);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the end of the class. This method, which is the last one to be
|
||||
* called, is used to inform the visitor that all the fields and methods of
|
||||
* the class have been visited.
|
||||
*/
|
||||
* Visits the end of the class. This method, which is the last one to be called, is used to inform
|
||||
* the visitor that all the fields and methods of the class have been visited.
|
||||
*/
|
||||
public void visitEnd() {
|
||||
if (cv != null) {
|
||||
cv.visitEnd();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A constant whose value is computed at runtime, with a bootstrap method.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public final class ConstantDynamic {
|
||||
|
||||
/** The constant name (can be arbitrary). */
|
||||
private final String name;
|
||||
|
||||
/** The constant type (must be a field descriptor). */
|
||||
private final String descriptor;
|
||||
|
||||
/** The bootstrap method to use to compute the constant value at runtime. */
|
||||
private final Handle bootstrapMethod;
|
||||
|
||||
/**
|
||||
* The arguments to pass to the bootstrap method, in order to compute the constant value at
|
||||
* runtime.
|
||||
*/
|
||||
private final Object[] bootstrapMethodArguments;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ConstantDynamic}.
|
||||
*
|
||||
* @param name the constant name (can be arbitrary).
|
||||
* @param descriptor the constant type (must be a field descriptor).
|
||||
* @param bootstrapMethod the bootstrap method to use to compute the constant value at runtime.
|
||||
* @param bootstrapMethodArguments the arguments to pass to the bootstrap method, in order to
|
||||
* compute the constant value at runtime.
|
||||
*/
|
||||
public ConstantDynamic(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final Handle bootstrapMethod,
|
||||
final Object... bootstrapMethodArguments) {
|
||||
this.name = name;
|
||||
this.descriptor = descriptor;
|
||||
this.bootstrapMethod = bootstrapMethod;
|
||||
this.bootstrapMethodArguments = bootstrapMethodArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this constant.
|
||||
*
|
||||
* @return the name of this constant.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this constant.
|
||||
*
|
||||
* @return the type of this constant, as a field descriptor.
|
||||
*/
|
||||
public String getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bootstrap method used to compute the value of this constant.
|
||||
*
|
||||
* @return the bootstrap method used to compute the value of this constant.
|
||||
*/
|
||||
public Handle getBootstrapMethod() {
|
||||
return bootstrapMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of arguments passed to the bootstrap method, in order to compute the value
|
||||
* of this constant.
|
||||
*
|
||||
* @return the number of arguments passed to the bootstrap method, in order to compute the value
|
||||
* of this constant.
|
||||
*/
|
||||
public int getBootstrapMethodArgumentCount() {
|
||||
return bootstrapMethodArguments.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an argument passed to the bootstrap method, in order to compute the value of this
|
||||
* constant.
|
||||
*
|
||||
* @param index an argument index, between 0 and {@link #getBootstrapMethodArgumentCount()}
|
||||
* (exclusive).
|
||||
* @return the argument passed to the bootstrap method, with the given index.
|
||||
*/
|
||||
public Object getBootstrapMethodArgument(final int index) {
|
||||
return bootstrapMethodArguments[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arguments to pass to the bootstrap method, in order to compute the value of this
|
||||
* constant. WARNING: this array must not be modified, and must not be returned to the user.
|
||||
*
|
||||
* @return the arguments to pass to the bootstrap method, in order to compute the value of this
|
||||
* constant.
|
||||
*/
|
||||
Object[] getBootstrapMethodArgumentsUnsafe() {
|
||||
return bootstrapMethodArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this constant.
|
||||
*
|
||||
* @return the size of this constant, i.e., 2 for {@code long} and {@code double}, 1 otherwise.
|
||||
*/
|
||||
public int getSize() {
|
||||
char firstCharOfDescriptor = descriptor.charAt(0);
|
||||
return (firstCharOfDescriptor == 'J' || firstCharOfDescriptor == 'D') ? 2 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (object == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof ConstantDynamic)) {
|
||||
return false;
|
||||
}
|
||||
ConstantDynamic constantDynamic = (ConstantDynamic) object;
|
||||
return name.equals(constantDynamic.name)
|
||||
&& descriptor.equals(constantDynamic.descriptor)
|
||||
&& bootstrapMethod.equals(constantDynamic.bootstrapMethod)
|
||||
&& Arrays.equals(bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode()
|
||||
^ Integer.rotateLeft(descriptor.hashCode(), 8)
|
||||
^ Integer.rotateLeft(bootstrapMethod.hashCode(), 16)
|
||||
^ Integer.rotateLeft(Arrays.hashCode(bootstrapMethodArguments), 24);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name
|
||||
+ " : "
|
||||
+ descriptor
|
||||
+ ' '
|
||||
+ bootstrapMethod
|
||||
+ ' '
|
||||
+ Arrays.toString(bootstrapMethodArguments);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* Defines additional JVM opcodes, access flags and constants which are not part of the ASM public
|
||||
* API.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class Constants implements Opcodes {
|
||||
|
||||
// The ClassFile attribute names, in the order they are defined in
|
||||
// https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
|
||||
|
||||
static final String CONSTANT_VALUE = "ConstantValue";
|
||||
static final String CODE = "Code";
|
||||
static final String STACK_MAP_TABLE = "StackMapTable";
|
||||
static final String EXCEPTIONS = "Exceptions";
|
||||
static final String INNER_CLASSES = "InnerClasses";
|
||||
static final String ENCLOSING_METHOD = "EnclosingMethod";
|
||||
static final String SYNTHETIC = "Synthetic";
|
||||
static final String SIGNATURE = "Signature";
|
||||
static final String SOURCE_FILE = "SourceFile";
|
||||
static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
|
||||
static final String LINE_NUMBER_TABLE = "LineNumberTable";
|
||||
static final String LOCAL_VARIABLE_TABLE = "LocalVariableTable";
|
||||
static final String LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
|
||||
static final String DEPRECATED = "Deprecated";
|
||||
static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
|
||||
static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
|
||||
static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
|
||||
static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
|
||||
"RuntimeInvisibleParameterAnnotations";
|
||||
static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
|
||||
static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
|
||||
static final String ANNOTATION_DEFAULT = "AnnotationDefault";
|
||||
static final String BOOTSTRAP_METHODS = "BootstrapMethods";
|
||||
static final String METHOD_PARAMETERS = "MethodParameters";
|
||||
static final String MODULE = "Module";
|
||||
static final String MODULE_PACKAGES = "ModulePackages";
|
||||
static final String MODULE_MAIN_CLASS = "ModuleMainClass";
|
||||
static final String NEST_HOST = "NestHost";
|
||||
static final String NEST_MEMBERS = "NestMembers";
|
||||
|
||||
// ASM specific access flags.
|
||||
// WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
|
||||
// access flags, and also to make sure that these flags are automatically filtered out when
|
||||
// written in class files (because access flags are stored using 16 bits only).
|
||||
|
||||
static final int ACC_CONSTRUCTOR = 0x40000; // method access flag.
|
||||
|
||||
// ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
|
||||
|
||||
/**
|
||||
* A frame inserted between already existing frames. This internal stack map frame type (in
|
||||
* addition to the ones declared in {@link Opcodes}) can only be used if the frame content can be
|
||||
* computed from the previous existing frame and from the instructions between this existing frame
|
||||
* and the inserted one, without any knowledge of the type hierarchy. This kind of frame is only
|
||||
* used when an unconditional jump is inserted in a method while expanding an ASM specific
|
||||
* instruction. Keep in sync with Opcodes.java.
|
||||
*/
|
||||
static final int F_INSERT = 256;
|
||||
|
||||
// The JVM opcode values which are not part of the ASM public API.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
|
||||
|
||||
static final int LDC_W = 19;
|
||||
static final int LDC2_W = 20;
|
||||
static final int ILOAD_0 = 26;
|
||||
static final int ILOAD_1 = 27;
|
||||
static final int ILOAD_2 = 28;
|
||||
static final int ILOAD_3 = 29;
|
||||
static final int LLOAD_0 = 30;
|
||||
static final int LLOAD_1 = 31;
|
||||
static final int LLOAD_2 = 32;
|
||||
static final int LLOAD_3 = 33;
|
||||
static final int FLOAD_0 = 34;
|
||||
static final int FLOAD_1 = 35;
|
||||
static final int FLOAD_2 = 36;
|
||||
static final int FLOAD_3 = 37;
|
||||
static final int DLOAD_0 = 38;
|
||||
static final int DLOAD_1 = 39;
|
||||
static final int DLOAD_2 = 40;
|
||||
static final int DLOAD_3 = 41;
|
||||
static final int ALOAD_0 = 42;
|
||||
static final int ALOAD_1 = 43;
|
||||
static final int ALOAD_2 = 44;
|
||||
static final int ALOAD_3 = 45;
|
||||
static final int ISTORE_0 = 59;
|
||||
static final int ISTORE_1 = 60;
|
||||
static final int ISTORE_2 = 61;
|
||||
static final int ISTORE_3 = 62;
|
||||
static final int LSTORE_0 = 63;
|
||||
static final int LSTORE_1 = 64;
|
||||
static final int LSTORE_2 = 65;
|
||||
static final int LSTORE_3 = 66;
|
||||
static final int FSTORE_0 = 67;
|
||||
static final int FSTORE_1 = 68;
|
||||
static final int FSTORE_2 = 69;
|
||||
static final int FSTORE_3 = 70;
|
||||
static final int DSTORE_0 = 71;
|
||||
static final int DSTORE_1 = 72;
|
||||
static final int DSTORE_2 = 73;
|
||||
static final int DSTORE_3 = 74;
|
||||
static final int ASTORE_0 = 75;
|
||||
static final int ASTORE_1 = 76;
|
||||
static final int ASTORE_2 = 77;
|
||||
static final int ASTORE_3 = 78;
|
||||
static final int WIDE = 196;
|
||||
static final int GOTO_W = 200;
|
||||
static final int JSR_W = 201;
|
||||
|
||||
// Constants to convert between normal and wide jump instructions.
|
||||
|
||||
// The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP.
|
||||
static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - GOTO;
|
||||
|
||||
// Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa.
|
||||
|
||||
// The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes
|
||||
// and IFEQ, ..., IF_ACMPNE, GOTO and JSR.
|
||||
static final int ASM_OPCODE_DELTA = 49;
|
||||
|
||||
// The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL.
|
||||
static final int ASM_IFNULL_OPCODE_DELTA = 20;
|
||||
|
||||
// ASM specific opcodes, used for long forward jump instructions.
|
||||
|
||||
static final int ASM_IFEQ = IFEQ + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IFNE = IFNE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IFLT = IFLT + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IFGE = IFGE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IFGT = IFGT + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IFLE = IFLE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ICMPEQ = IF_ICMPEQ + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ICMPNE = IF_ICMPNE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ICMPLT = IF_ICMPLT + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ICMPGE = IF_ICMPGE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ICMPGT = IF_ICMPGT + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ICMPLE = IF_ICMPLE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ACMPEQ = IF_ACMPEQ + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IF_ACMPNE = IF_ACMPNE + ASM_OPCODE_DELTA;
|
||||
static final int ASM_GOTO = GOTO + ASM_OPCODE_DELTA;
|
||||
static final int ASM_JSR = JSR + ASM_OPCODE_DELTA;
|
||||
static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA;
|
||||
static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
|
||||
static final int ASM_GOTO_W = 220;
|
||||
|
||||
private Constants() {}
|
||||
}
|
||||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
|
|
@ -64,111 +63,105 @@ package jdk.internal.org.objectweb.asm;
|
|||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Context {
|
||||
final class Context {
|
||||
|
||||
/** The prototypes of the attributes that must be parsed in this class. */
|
||||
Attribute[] attributePrototypes;
|
||||
|
||||
/**
|
||||
* Prototypes of the attributes that must be parsed for this class.
|
||||
*/
|
||||
Attribute[] attrs;
|
||||
* The options used to parse this class. One or more of {@link ClassReader#SKIP_CODE}, {@link
|
||||
* ClassReader#SKIP_DEBUG}, {@link ClassReader#SKIP_FRAMES}, {@link ClassReader#EXPAND_FRAMES} or
|
||||
* {@link ClassReader#EXPAND_ASM_INSNS}.
|
||||
*/
|
||||
int parsingOptions;
|
||||
|
||||
/** The buffer used to read strings in the constant pool. */
|
||||
char[] charBuffer;
|
||||
|
||||
// Information about the current method, i.e. the one read in the current (or latest) call
|
||||
// to {@link ClassReader#readMethod()}.
|
||||
|
||||
/** The access flags of the current method. */
|
||||
int currentMethodAccessFlags;
|
||||
|
||||
/** The name of the current method. */
|
||||
String currentMethodName;
|
||||
|
||||
/** The descriptor of the current method. */
|
||||
String currentMethodDescriptor;
|
||||
|
||||
/**
|
||||
* The {@link ClassReader} option flags for the parsing of this class.
|
||||
*/
|
||||
int flags;
|
||||
* The labels of the current method, indexed by bytecode offset (only bytecode offsets for which a
|
||||
* label is needed have a non null associated Label).
|
||||
*/
|
||||
Label[] currentMethodLabels;
|
||||
|
||||
// Information about the current type annotation target, i.e. the one read in the current
|
||||
// (or latest) call to {@link ClassReader#readAnnotationTarget()}.
|
||||
|
||||
/**
|
||||
* The buffer used to read strings.
|
||||
*/
|
||||
char[] buffer;
|
||||
* The target_type and target_info of the current type annotation target, encoded as described in
|
||||
* {@link TypeReference}.
|
||||
*/
|
||||
int currentTypeAnnotationTarget;
|
||||
|
||||
/** The target_path of the current type annotation target. */
|
||||
TypePath currentTypeAnnotationTargetPath;
|
||||
|
||||
/** The start of each local variable range in the current local variable annotation. */
|
||||
Label[] currentLocalVariableAnnotationRangeStarts;
|
||||
|
||||
/** The end of each local variable range in the current local variable annotation. */
|
||||
Label[] currentLocalVariableAnnotationRangeEnds;
|
||||
|
||||
/**
|
||||
* The start index of each bootstrap method.
|
||||
*/
|
||||
int[] bootstrapMethods;
|
||||
* The local variable index of each local variable range in the current local variable annotation.
|
||||
*/
|
||||
int[] currentLocalVariableAnnotationRangeIndices;
|
||||
|
||||
// Information about the current stack map frame, i.e. the one read in the current (or latest)
|
||||
// call to {@link ClassReader#readFrame()}.
|
||||
|
||||
/** The bytecode offset of the current stack map frame. */
|
||||
int currentFrameOffset;
|
||||
|
||||
/**
|
||||
* The access flags of the method currently being parsed.
|
||||
*/
|
||||
int access;
|
||||
* The type of the current stack map frame. One of {@link Opcodes#F_FULL}, {@link
|
||||
* Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or {@link Opcodes#F_SAME1}.
|
||||
*/
|
||||
int currentFrameType;
|
||||
|
||||
/**
|
||||
* The name of the method currently being parsed.
|
||||
*/
|
||||
String name;
|
||||
* The number of local variable types in the current stack map frame. Each type is represented
|
||||
* with a single array element (even long and double).
|
||||
*/
|
||||
int currentFrameLocalCount;
|
||||
|
||||
/**
|
||||
* The descriptor of the method currently being parsed.
|
||||
*/
|
||||
String desc;
|
||||
* The delta number of local variable types in the current stack map frame (each type is
|
||||
* represented with a single array element - even long and double). This is the number of local
|
||||
* variable types in this frame, minus the number of local variable types in the previous frame.
|
||||
*/
|
||||
int currentFrameLocalCountDelta;
|
||||
|
||||
/**
|
||||
* The label objects, indexed by bytecode offset, of the method currently
|
||||
* being parsed (only bytecode offsets for which a label is needed have a
|
||||
* non null associated Label object).
|
||||
*/
|
||||
Label[] labels;
|
||||
* The types of the local variables in the current stack map frame. Each type is represented with
|
||||
* a single array element (even long and double), using the format described in {@link
|
||||
* MethodVisitor#visitFrame}. Depending on {@link #currentFrameType}, this contains the types of
|
||||
* all the local variables, or only those of the additional ones (compared to the previous frame).
|
||||
*/
|
||||
Object[] currentFrameLocalTypes;
|
||||
|
||||
/**
|
||||
* The target of the type annotation currently being parsed.
|
||||
*/
|
||||
int typeRef;
|
||||
* The number stack element types in the current stack map frame. Each type is represented with a
|
||||
* single array element (even long and double).
|
||||
*/
|
||||
int currentFrameStackCount;
|
||||
|
||||
/**
|
||||
* The path of the type annotation currently being parsed.
|
||||
*/
|
||||
TypePath typePath;
|
||||
|
||||
/**
|
||||
* The offset of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int offset;
|
||||
|
||||
/**
|
||||
* The labels corresponding to the start of the local variable ranges in the
|
||||
* local variable type annotation currently being parsed.
|
||||
*/
|
||||
Label[] start;
|
||||
|
||||
/**
|
||||
* The labels corresponding to the end of the local variable ranges in the
|
||||
* local variable type annotation currently being parsed.
|
||||
*/
|
||||
Label[] end;
|
||||
|
||||
/**
|
||||
* The local variable indices for each local variable range in the local
|
||||
* variable type annotation currently being parsed.
|
||||
*/
|
||||
int[] index;
|
||||
|
||||
/**
|
||||
* The encoding of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int mode;
|
||||
|
||||
/**
|
||||
* The number of locals in the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int localCount;
|
||||
|
||||
/**
|
||||
* The number locals in the latest stack map frame that has been parsed,
|
||||
* minus the number of locals in the previous frame.
|
||||
*/
|
||||
int localDiff;
|
||||
|
||||
/**
|
||||
* The local values of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
Object[] local;
|
||||
|
||||
/**
|
||||
* The stack size of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int stackCount;
|
||||
|
||||
/**
|
||||
* The stack values of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
Object[] stack;
|
||||
* The types of the stack elements in the current stack map frame. Each type is represented with a
|
||||
* single array element (even long and double), using the format described in {@link
|
||||
* MethodVisitor#visitFrame}.
|
||||
*/
|
||||
Object[] currentFrameStackTypes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,30 +56,31 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* Information about the input stack map frame at the "current" instruction of a
|
||||
* method. This is implemented as a Frame subclass for a "basic block"
|
||||
* containing only one instruction.
|
||||
* Information about the input stack map frame at the "current" instruction of a method. This is
|
||||
* implemented as a Frame subclass for a "basic block" containing only one instruction.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class CurrentFrame extends Frame {
|
||||
final class CurrentFrame extends Frame {
|
||||
|
||||
CurrentFrame(final Label owner) {
|
||||
super(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this CurrentFrame to the input stack map frame of the next "current"
|
||||
* instruction, i.e. the instruction just after the given one. It is assumed
|
||||
* that the value of this object when this method is called is the stack map
|
||||
* frame status just before the given instruction is executed.
|
||||
*/
|
||||
* Sets this CurrentFrame to the input stack map frame of the next "current" instruction, i.e. the
|
||||
* instruction just after the given one. It is assumed that the value of this object when this
|
||||
* method is called is the stack map frame status just before the given instruction is executed.
|
||||
*/
|
||||
@Override
|
||||
void execute(int opcode, int arg, ClassWriter cw, Item item) {
|
||||
super.execute(opcode, arg, cw, item);
|
||||
Frame successor = new Frame();
|
||||
merge(cw, successor, 0);
|
||||
set(successor);
|
||||
owner.inputStackTop = 0;
|
||||
void execute(
|
||||
final int opcode, final int arg, final Symbol symbolArg, final SymbolTable symbolTable) {
|
||||
super.execute(opcode, arg, symbolArg, symbolTable);
|
||||
Frame successor = new Frame(null);
|
||||
merge(symbolTable, successor, 0);
|
||||
copyFrom(successor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,46 +59,64 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* An edge in the control flow graph of a method body. See {@link Label Label}.
|
||||
* An edge in the control flow graph of a method. Each node of this graph is a basic block,
|
||||
* represented with the Label corresponding to its first instruction. Each edge goes from one node
|
||||
* to another, i.e. from one basic block to another (called the predecessor and successor blocks,
|
||||
* respectively). An edge corresponds either to a jump or ret instruction or to an exception
|
||||
* handler.
|
||||
*
|
||||
* @see Label
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Edge {
|
||||
final class Edge {
|
||||
|
||||
/**
|
||||
* Denotes a normal control flow graph edge.
|
||||
*/
|
||||
static final int NORMAL = 0;
|
||||
* A control flow graph edge corresponding to a jump or ret instruction. Only used with {@link
|
||||
* ClassWriter#COMPUTE_FRAMES}.
|
||||
*/
|
||||
static final int JUMP = 0;
|
||||
|
||||
/**
|
||||
* Denotes a control flow graph edge corresponding to an exception handler.
|
||||
* More precisely any {@link Edge} whose {@link #info} is strictly positive
|
||||
* corresponds to an exception handler. The actual value of {@link #info} is
|
||||
* the index, in the {@link ClassWriter} type table, of the exception that
|
||||
* is catched.
|
||||
*/
|
||||
* A control flow graph edge corresponding to an exception handler. Only used with {@link
|
||||
* ClassWriter#COMPUTE_MAXS}.
|
||||
*/
|
||||
static final int EXCEPTION = 0x7FFFFFFF;
|
||||
|
||||
/**
|
||||
* Information about this control flow graph edge. If
|
||||
* {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
|
||||
* stack size in the basic block from which this edge originates. This size
|
||||
* is equal to the stack size at the "jump" instruction to which this edge
|
||||
* corresponds, relatively to the stack size at the beginning of the
|
||||
* originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
|
||||
* this field is the kind of this control flow graph edge (i.e. NORMAL or
|
||||
* EXCEPTION).
|
||||
*/
|
||||
int info;
|
||||
* Information about this control flow graph edge.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If {@link ClassWriter#COMPUTE_MAXS} is used, this field contains either a stack size
|
||||
* delta (for an edge corresponding to a jump instruction), or the value EXCEPTION (for an
|
||||
* edge corresponding to an exception handler). The stack size delta is the stack size just
|
||||
* after the jump instruction, minus the stack size at the beginning of the predecessor
|
||||
* basic block, i.e. the one containing the jump instruction.
|
||||
* <li>If {@link ClassWriter#COMPUTE_FRAMES} is used, this field contains either the value JUMP
|
||||
* (for an edge corresponding to a jump instruction), or the index, in the {@link
|
||||
* ClassWriter} type table, of the exception type that is handled (for an edge corresponding
|
||||
* to an exception handler).
|
||||
* </ul>
|
||||
*/
|
||||
final int info;
|
||||
|
||||
/** The successor block of this control flow graph edge. */
|
||||
final Label successor;
|
||||
|
||||
/**
|
||||
* The successor block of the basic block from which this edge originates.
|
||||
*/
|
||||
Label successor;
|
||||
* The next edge in the list of outgoing edges of a basic block. See {@link Label#outgoingEdges}.
|
||||
*/
|
||||
Edge nextEdge;
|
||||
|
||||
/**
|
||||
* The next edge in the list of successors of the originating basic block.
|
||||
* See {@link Label#successors successors}.
|
||||
*/
|
||||
Edge next;
|
||||
* Constructs a new Edge.
|
||||
*
|
||||
* @param info see {@link #info}.
|
||||
* @param successor see {@link #successor}.
|
||||
* @param nextEdge see {@link #nextEdge}.
|
||||
*/
|
||||
Edge(final int info, final Label successor, final Edge nextEdge) {
|
||||
this.info = info;
|
||||
this.successor = successor;
|
||||
this.nextEdge = nextEdge;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,118 +59,103 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java field. The methods of this class must be called in
|
||||
* the following order: ( <tt>visitAnnotation</tt> |
|
||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
|
||||
* A visitor to visit a Java field. The methods of this class must be called in the following order:
|
||||
* ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code visitAttribute} )* {@code
|
||||
* visitEnd}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class FieldVisitor {
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The field visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
/** The field visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected FieldVisitor fv;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Constructs a new {@link FieldVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public FieldVisitor(final int api) {
|
||||
this(api, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param fv
|
||||
* the field visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public FieldVisitor(final int api, final FieldVisitor fv) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
* Constructs a new {@link FieldVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param fieldVisitor the field visitor to which this visitor must delegate method calls. May be
|
||||
* null.
|
||||
*/
|
||||
public FieldVisitor(final int api, final FieldVisitor fieldVisitor) {
|
||||
if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.fv = fv;
|
||||
this.fv = fieldVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation of the field.
|
||||
*
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
* @param visible
|
||||
* <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> if
|
||||
* this visitor is not interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
* Visits an annotation of the field.
|
||||
*
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
* @param visible {@literal true} if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
|
||||
* interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
if (fv != null) {
|
||||
return fv.visitAnnotation(desc, visible);
|
||||
return fv.visitAnnotation(descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation on the type of the field.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. The sort of this type
|
||||
* reference must be {@link TypeReference#FIELD FIELD}. See
|
||||
* {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
* @param visible
|
||||
* <tt>true</tt> if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or <tt>null</tt> if
|
||||
* this visitor is not interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
* Visits an annotation on the type of the field.
|
||||
*
|
||||
* @param typeRef a reference to the annotated type. The sort of this type reference must be
|
||||
* {@link TypeReference#FIELD}. See {@link TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
* @param visible {@literal true} if the annotation is visible at runtime.
|
||||
* @return a visitor to visit the annotation values, or {@literal null} if this visitor is not
|
||||
* interested in visiting this annotation.
|
||||
*/
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
if (api < Opcodes.ASM5) {
|
||||
throw new RuntimeException();
|
||||
throw new UnsupportedOperationException("This feature requires ASM5");
|
||||
}
|
||||
if (fv != null) {
|
||||
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
return fv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a non standard attribute of the field.
|
||||
*
|
||||
* @param attr
|
||||
* an attribute.
|
||||
*/
|
||||
public void visitAttribute(Attribute attr) {
|
||||
* Visits a non standard attribute of the field.
|
||||
*
|
||||
* @param attribute an attribute.
|
||||
*/
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (fv != null) {
|
||||
fv.visitAttribute(attr);
|
||||
fv.visitAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the end of the field. This method, which is the last one to be
|
||||
* called, is used to inform the visitor that all the annotations and
|
||||
* attributes of the field have been visited.
|
||||
*/
|
||||
* Visits the end of the field. This method, which is the last one to be called, is used to inform
|
||||
* the visitor that all the annotations and attributes of the field have been visited.
|
||||
*/
|
||||
public void visitEnd() {
|
||||
if (fv != null) {
|
||||
fv.visitEnd();
|
||||
|
|
|
|||
|
|
@ -59,294 +59,319 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* An {@link FieldVisitor} that generates Java fields in bytecode form.
|
||||
* A {@link FieldVisitor} that generates a corresponding 'field_info' structure, as defined in the
|
||||
* Java Virtual Machine Specification (JVMS).
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5">JVMS
|
||||
* 4.5</a>
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class FieldWriter extends FieldVisitor {
|
||||
|
||||
/**
|
||||
* The class writer to which this field must be added.
|
||||
*/
|
||||
private final ClassWriter cw;
|
||||
/** Where the constants used in this FieldWriter must be stored. */
|
||||
private final SymbolTable symbolTable;
|
||||
|
||||
// Note: fields are ordered as in the field_info structure, and those related to attributes are
|
||||
// ordered as in Section 4.7 of the JVMS.
|
||||
|
||||
/**
|
||||
* Access flags of this field.
|
||||
*/
|
||||
private final int access;
|
||||
* The access_flags field of the field_info JVMS structure. This field can contain ASM specific
|
||||
* access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
|
||||
* ClassFile structure.
|
||||
*/
|
||||
private final int accessFlags;
|
||||
|
||||
/** The name_index field of the field_info JVMS structure. */
|
||||
private final int nameIndex;
|
||||
|
||||
/** The descriptor_index field of the field_info JVMS structure. */
|
||||
private final int descriptorIndex;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the name of this
|
||||
* method.
|
||||
*/
|
||||
private final int name;
|
||||
* The signature_index field of the Signature attribute of this field_info, or 0 if there is no
|
||||
* Signature attribute.
|
||||
*/
|
||||
private int signatureIndex;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the descriptor of this
|
||||
* field.
|
||||
*/
|
||||
private final int desc;
|
||||
* The constantvalue_index field of the ConstantValue attribute of this field_info, or 0 if there
|
||||
* is no ConstantValue attribute.
|
||||
*/
|
||||
private int constantValueIndex;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the signature of this
|
||||
* field.
|
||||
*/
|
||||
private int signature;
|
||||
* The last runtime visible annotation of this field. The previous ones can be accessed with the
|
||||
* {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
|
||||
*/
|
||||
private AnnotationWriter lastRuntimeVisibleAnnotation;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the constant value of
|
||||
* this field.
|
||||
*/
|
||||
private int value;
|
||||
* The last runtime invisible annotation of this field. The previous ones can be accessed with the
|
||||
* {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
|
||||
*/
|
||||
private AnnotationWriter lastRuntimeInvisibleAnnotation;
|
||||
|
||||
/**
|
||||
* The runtime visible annotations of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter anns;
|
||||
* The last runtime visible type annotation of this field. The previous ones can be accessed with
|
||||
* the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
|
||||
*/
|
||||
private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
|
||||
|
||||
/**
|
||||
* The runtime invisible annotations of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter ianns;
|
||||
* The last runtime invisible type annotation of this field. The previous ones can be accessed
|
||||
* with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
|
||||
*/
|
||||
private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter tanns;
|
||||
* The first non standard attribute of this field. The next ones can be accessed with the {@link
|
||||
* Attribute#nextAttribute} field. May be {@literal null}.
|
||||
*
|
||||
* <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
|
||||
* firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
|
||||
* #putFieldInfo} method writes the attributes in the order defined by this list, i.e. in the
|
||||
* reverse order specified by the user.
|
||||
*/
|
||||
private Attribute firstAttribute;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations of this field. May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter itanns;
|
||||
|
||||
/**
|
||||
* The non standard attributes of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private Attribute attrs;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldWriter}.
|
||||
*
|
||||
* @param cw
|
||||
* the class writer to which this field must be added.
|
||||
* @param access
|
||||
* the field's access flags (see {@link Opcodes}).
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link Type}).
|
||||
* @param signature
|
||||
* the field's signature. May be <tt>null</tt>.
|
||||
* @param value
|
||||
* the field's constant value. May be <tt>null</tt>.
|
||||
*/
|
||||
FieldWriter(final ClassWriter cw, final int access, final String name,
|
||||
final String desc, final String signature, final Object value) {
|
||||
super(Opcodes.ASM6);
|
||||
if (cw.firstField == null) {
|
||||
cw.firstField = this;
|
||||
} else {
|
||||
cw.lastField.fv = this;
|
||||
}
|
||||
cw.lastField = this;
|
||||
this.cw = cw;
|
||||
this.access = access;
|
||||
this.name = cw.newUTF8(name);
|
||||
this.desc = cw.newUTF8(desc);
|
||||
* Constructs a new {@link FieldWriter}.
|
||||
*
|
||||
* @param symbolTable where the constants used in this FieldWriter must be stored.
|
||||
* @param access the field's access flags (see {@link Opcodes}).
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link Type}).
|
||||
* @param signature the field's signature. May be {@literal null}.
|
||||
* @param constantValue the field's constant value. May be {@literal null}.
|
||||
*/
|
||||
FieldWriter(
|
||||
final SymbolTable symbolTable,
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object constantValue) {
|
||||
super(Opcodes.ASM7);
|
||||
this.symbolTable = symbolTable;
|
||||
this.accessFlags = access;
|
||||
this.nameIndex = symbolTable.addConstantUtf8(name);
|
||||
this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
|
||||
if (signature != null) {
|
||||
this.signature = cw.newUTF8(signature);
|
||||
this.signatureIndex = symbolTable.addConstantUtf8(signature);
|
||||
}
|
||||
if (value != null) {
|
||||
this.value = cw.newConstItem(value).index;
|
||||
if (constantValue != null) {
|
||||
this.constantValueIndex = symbolTable.addConstant(constantValue).index;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the FieldVisitor abstract class
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc,
|
||||
final boolean visible) {
|
||||
ByteVector bv = new ByteVector();
|
||||
// write type, and reserve space for values count
|
||||
bv.putShort(cw.newUTF8(desc)).putShort(0);
|
||||
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
// Create a ByteVector to hold an 'annotation' JVMS structure.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
|
||||
ByteVector annotation = new ByteVector();
|
||||
// Write type_index and reserve space for num_element_value_pairs.
|
||||
annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
|
||||
if (visible) {
|
||||
aw.next = anns;
|
||||
anns = aw;
|
||||
return lastRuntimeVisibleAnnotation =
|
||||
new AnnotationWriter(symbolTable, annotation, lastRuntimeVisibleAnnotation);
|
||||
} else {
|
||||
aw.next = ianns;
|
||||
ianns = aw;
|
||||
return lastRuntimeInvisibleAnnotation =
|
||||
new AnnotationWriter(symbolTable, annotation, lastRuntimeInvisibleAnnotation);
|
||||
}
|
||||
return aw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(final int typeRef,
|
||||
final TypePath typePath, final String desc, final boolean visible) {
|
||||
ByteVector bv = new ByteVector();
|
||||
// write target_type and target_info
|
||||
AnnotationWriter.putTarget(typeRef, typePath, bv);
|
||||
// write type, and reserve space for values count
|
||||
bv.putShort(cw.newUTF8(desc)).putShort(0);
|
||||
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
|
||||
bv.length - 2);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
// Create a ByteVector to hold a 'type_annotation' JVMS structure.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
|
||||
ByteVector typeAnnotation = new ByteVector();
|
||||
// Write target_type, target_info, and target_path.
|
||||
TypeReference.putTarget(typeRef, typeAnnotation);
|
||||
TypePath.put(typePath, typeAnnotation);
|
||||
// Write type_index and reserve space for num_element_value_pairs.
|
||||
typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
|
||||
if (visible) {
|
||||
aw.next = tanns;
|
||||
tanns = aw;
|
||||
return lastRuntimeVisibleTypeAnnotation =
|
||||
new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeVisibleTypeAnnotation);
|
||||
} else {
|
||||
aw.next = itanns;
|
||||
itanns = aw;
|
||||
return lastRuntimeInvisibleTypeAnnotation =
|
||||
new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeInvisibleTypeAnnotation);
|
||||
}
|
||||
return aw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(final Attribute attr) {
|
||||
attr.next = attrs;
|
||||
attrs = attr;
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
// Store the attributes in the <i>reverse</i> order of their visit by this method.
|
||||
attribute.nextAttribute = firstAttribute;
|
||||
firstAttribute = attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the size of this field.
|
||||
*
|
||||
* @return the size of this field.
|
||||
*/
|
||||
int getSize() {
|
||||
* Returns the size of the field_info JVMS structure generated by this FieldWriter. Also adds the
|
||||
* names of the attributes of this field in the constant pool.
|
||||
*
|
||||
* @return the size in bytes of the field_info JVMS structure.
|
||||
*/
|
||||
int computeFieldInfoSize() {
|
||||
// The access_flags, name_index, descriptor_index and attributes_count fields use 8 bytes.
|
||||
int size = 8;
|
||||
if (value != 0) {
|
||||
cw.newUTF8("ConstantValue");
|
||||
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
|
||||
if (constantValueIndex != 0) {
|
||||
// ConstantValue attributes always use 8 bytes.
|
||||
symbolTable.addConstantUtf8(Constants.CONSTANT_VALUE);
|
||||
size += 8;
|
||||
}
|
||||
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
|
||||
if ((cw.version & 0xFFFF) < Opcodes.V1_5
|
||||
|| (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
|
||||
cw.newUTF8("Synthetic");
|
||||
size += 6;
|
||||
}
|
||||
}
|
||||
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
||||
cw.newUTF8("Deprecated");
|
||||
// Before Java 1.5, synthetic fields are represented with a Synthetic attribute.
|
||||
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0
|
||||
&& symbolTable.getMajorVersion() < Opcodes.V1_5) {
|
||||
// Synthetic attributes always use 6 bytes.
|
||||
symbolTable.addConstantUtf8(Constants.SYNTHETIC);
|
||||
size += 6;
|
||||
}
|
||||
if (signature != 0) {
|
||||
cw.newUTF8("Signature");
|
||||
if (signatureIndex != 0) {
|
||||
// Signature attributes always use 8 bytes.
|
||||
symbolTable.addConstantUtf8(Constants.SIGNATURE);
|
||||
size += 8;
|
||||
}
|
||||
if (anns != null) {
|
||||
cw.newUTF8("RuntimeVisibleAnnotations");
|
||||
size += 8 + anns.getSize();
|
||||
// ACC_DEPRECATED is ASM specific, the ClassFile format uses a Deprecated attribute instead.
|
||||
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
|
||||
// Deprecated attributes always use 6 bytes.
|
||||
symbolTable.addConstantUtf8(Constants.DEPRECATED);
|
||||
size += 6;
|
||||
}
|
||||
if (ianns != null) {
|
||||
cw.newUTF8("RuntimeInvisibleAnnotations");
|
||||
size += 8 + ianns.getSize();
|
||||
if (lastRuntimeVisibleAnnotation != null) {
|
||||
size +=
|
||||
lastRuntimeVisibleAnnotation.computeAnnotationsSize(
|
||||
Constants.RUNTIME_VISIBLE_ANNOTATIONS);
|
||||
}
|
||||
if (tanns != null) {
|
||||
cw.newUTF8("RuntimeVisibleTypeAnnotations");
|
||||
size += 8 + tanns.getSize();
|
||||
if (lastRuntimeInvisibleAnnotation != null) {
|
||||
size +=
|
||||
lastRuntimeInvisibleAnnotation.computeAnnotationsSize(
|
||||
Constants.RUNTIME_INVISIBLE_ANNOTATIONS);
|
||||
}
|
||||
if (itanns != null) {
|
||||
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
|
||||
size += 8 + itanns.getSize();
|
||||
if (lastRuntimeVisibleTypeAnnotation != null) {
|
||||
size +=
|
||||
lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize(
|
||||
Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
|
||||
}
|
||||
if (attrs != null) {
|
||||
size += attrs.getSize(cw, null, 0, -1, -1);
|
||||
if (lastRuntimeInvisibleTypeAnnotation != null) {
|
||||
size +=
|
||||
lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize(
|
||||
Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
|
||||
}
|
||||
if (firstAttribute != null) {
|
||||
size += firstAttribute.computeAttributesSize(symbolTable);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the content of this field into the given byte vector.
|
||||
*
|
||||
* @param out
|
||||
* where the content of this field must be put.
|
||||
*/
|
||||
void put(final ByteVector out) {
|
||||
final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
|
||||
int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
|
||||
| ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
|
||||
out.putShort(access & ~mask).putShort(name).putShort(desc);
|
||||
int attributeCount = 0;
|
||||
if (value != 0) {
|
||||
++attributeCount;
|
||||
* Puts the content of the field_info JVMS structure generated by this FieldWriter into the given
|
||||
* ByteVector.
|
||||
*
|
||||
* @param output where the field_info structure must be put.
|
||||
*/
|
||||
void putFieldInfo(final ByteVector output) {
|
||||
boolean useSyntheticAttribute = symbolTable.getMajorVersion() < Opcodes.V1_5;
|
||||
// Put the access_flags, name_index and descriptor_index fields.
|
||||
int mask = useSyntheticAttribute ? Opcodes.ACC_SYNTHETIC : 0;
|
||||
output.putShort(accessFlags & ~mask).putShort(nameIndex).putShort(descriptorIndex);
|
||||
// Compute and put the attributes_count field.
|
||||
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
|
||||
int attributesCount = 0;
|
||||
if (constantValueIndex != 0) {
|
||||
++attributesCount;
|
||||
}
|
||||
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
|
||||
if ((cw.version & 0xFFFF) < Opcodes.V1_5
|
||||
|| (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
|
||||
++attributeCount;
|
||||
}
|
||||
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
|
||||
++attributesCount;
|
||||
}
|
||||
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
||||
++attributeCount;
|
||||
if (signatureIndex != 0) {
|
||||
++attributesCount;
|
||||
}
|
||||
if (signature != 0) {
|
||||
++attributeCount;
|
||||
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
|
||||
++attributesCount;
|
||||
}
|
||||
if (anns != null) {
|
||||
++attributeCount;
|
||||
if (lastRuntimeVisibleAnnotation != null) {
|
||||
++attributesCount;
|
||||
}
|
||||
if (ianns != null) {
|
||||
++attributeCount;
|
||||
if (lastRuntimeInvisibleAnnotation != null) {
|
||||
++attributesCount;
|
||||
}
|
||||
if (tanns != null) {
|
||||
++attributeCount;
|
||||
if (lastRuntimeVisibleTypeAnnotation != null) {
|
||||
++attributesCount;
|
||||
}
|
||||
if (itanns != null) {
|
||||
++attributeCount;
|
||||
if (lastRuntimeInvisibleTypeAnnotation != null) {
|
||||
++attributesCount;
|
||||
}
|
||||
if (attrs != null) {
|
||||
attributeCount += attrs.getCount();
|
||||
if (firstAttribute != null) {
|
||||
attributesCount += firstAttribute.getAttributeCount();
|
||||
}
|
||||
out.putShort(attributeCount);
|
||||
if (value != 0) {
|
||||
out.putShort(cw.newUTF8("ConstantValue"));
|
||||
out.putInt(2).putShort(value);
|
||||
output.putShort(attributesCount);
|
||||
// Put the field_info attributes.
|
||||
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
|
||||
if (constantValueIndex != 0) {
|
||||
output
|
||||
.putShort(symbolTable.addConstantUtf8(Constants.CONSTANT_VALUE))
|
||||
.putInt(2)
|
||||
.putShort(constantValueIndex);
|
||||
}
|
||||
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
|
||||
if ((cw.version & 0xFFFF) < Opcodes.V1_5
|
||||
|| (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
|
||||
out.putShort(cw.newUTF8("Synthetic")).putInt(0);
|
||||
}
|
||||
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
|
||||
output.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0);
|
||||
}
|
||||
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
||||
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
|
||||
if (signatureIndex != 0) {
|
||||
output
|
||||
.putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE))
|
||||
.putInt(2)
|
||||
.putShort(signatureIndex);
|
||||
}
|
||||
if (signature != 0) {
|
||||
out.putShort(cw.newUTF8("Signature"));
|
||||
out.putInt(2).putShort(signature);
|
||||
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
|
||||
output.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0);
|
||||
}
|
||||
if (anns != null) {
|
||||
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
|
||||
anns.put(out);
|
||||
if (lastRuntimeVisibleAnnotation != null) {
|
||||
lastRuntimeVisibleAnnotation.putAnnotations(
|
||||
symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_ANNOTATIONS), output);
|
||||
}
|
||||
if (ianns != null) {
|
||||
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
|
||||
ianns.put(out);
|
||||
if (lastRuntimeInvisibleAnnotation != null) {
|
||||
lastRuntimeInvisibleAnnotation.putAnnotations(
|
||||
symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_ANNOTATIONS), output);
|
||||
}
|
||||
if (tanns != null) {
|
||||
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
|
||||
tanns.put(out);
|
||||
if (lastRuntimeVisibleTypeAnnotation != null) {
|
||||
lastRuntimeVisibleTypeAnnotation.putAnnotations(
|
||||
symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS), output);
|
||||
}
|
||||
if (itanns != null) {
|
||||
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
|
||||
itanns.put(out);
|
||||
if (lastRuntimeInvisibleTypeAnnotation != null) {
|
||||
lastRuntimeInvisibleTypeAnnotation.putAnnotations(
|
||||
symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS), output);
|
||||
}
|
||||
if (attrs != null) {
|
||||
attrs.put(cw, null, 0, -1, -1, out);
|
||||
if (firstAttribute != null) {
|
||||
firstAttribute.putAttributes(symbolTable, output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the attributes of this field into the given set of attribute prototypes.
|
||||
*
|
||||
* @param attributePrototypes a set of attribute prototypes.
|
||||
*/
|
||||
final void collectAttributePrototypes(final Attribute.Set attributePrototypes) {
|
||||
attributePrototypes.addAttributes(firstAttribute);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
|
|
@ -68,184 +67,153 @@ package jdk.internal.org.objectweb.asm;
|
|||
public final class Handle {
|
||||
|
||||
/**
|
||||
* The kind of field or method designated by this Handle. Should be
|
||||
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
|
||||
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
|
||||
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
|
||||
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or
|
||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
||||
*/
|
||||
final int tag;
|
||||
* The kind of field or method designated by this Handle. Should be {@link Opcodes#H_GETFIELD},
|
||||
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
|
||||
* Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
|
||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
|
||||
*/
|
||||
private final int tag;
|
||||
|
||||
/** The internal name of the class that owns the field or method designated by this handle. */
|
||||
private final String owner;
|
||||
|
||||
/** The name of the field or method designated by this handle. */
|
||||
private final String name;
|
||||
|
||||
/** The descriptor of the field or method designated by this handle. */
|
||||
private final String descriptor;
|
||||
|
||||
/** Whether the owner is an interface or not. */
|
||||
private final boolean isInterface;
|
||||
|
||||
/**
|
||||
* The internal name of the class that owns the field or method designated
|
||||
* by this handle.
|
||||
*/
|
||||
final String owner;
|
||||
|
||||
/**
|
||||
* The name of the field or method designated by this handle.
|
||||
*/
|
||||
final String name;
|
||||
|
||||
/**
|
||||
* The descriptor of the field or method designated by this handle.
|
||||
*/
|
||||
final String desc;
|
||||
|
||||
|
||||
/**
|
||||
* Indicate if the owner is an interface or not.
|
||||
*/
|
||||
final boolean itf;
|
||||
|
||||
/**
|
||||
* Constructs a new field or method handle.
|
||||
*
|
||||
* @param tag
|
||||
* the kind of field or method designated by this Handle. Must be
|
||||
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
|
||||
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
|
||||
* {@link Opcodes#H_INVOKEVIRTUAL},
|
||||
* {@link Opcodes#H_INVOKESTATIC},
|
||||
* {@link Opcodes#H_INVOKESPECIAL},
|
||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
||||
* @param owner
|
||||
* the internal name of the class that owns the field or method
|
||||
* designated by this handle.
|
||||
* @param name
|
||||
* the name of the field or method designated by this handle.
|
||||
* @param desc
|
||||
* the descriptor of the field or method designated by this
|
||||
* handle.
|
||||
*
|
||||
* @deprecated this constructor has been superseded
|
||||
* by {@link #Handle(int, String, String, String, boolean)}.
|
||||
*/
|
||||
* Constructs a new field or method handle.
|
||||
*
|
||||
* @param tag the kind of field or method designated by this Handle. Must be {@link
|
||||
* Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
|
||||
* Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
|
||||
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
|
||||
* Opcodes#H_INVOKEINTERFACE}.
|
||||
* @param owner the internal name of the class that owns the field or method designated by this
|
||||
* handle.
|
||||
* @param name the name of the field or method designated by this handle.
|
||||
* @param descriptor the descriptor of the field or method designated by this handle.
|
||||
* @deprecated this constructor has been superseded by {@link #Handle(int, String, String, String,
|
||||
* boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Handle(int tag, String owner, String name, String desc) {
|
||||
this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
|
||||
public Handle(final int tag, final String owner, final String name, final String descriptor) {
|
||||
this(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new field or method handle.
|
||||
*
|
||||
* @param tag
|
||||
* the kind of field or method designated by this Handle. Must be
|
||||
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
|
||||
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
|
||||
* {@link Opcodes#H_INVOKEVIRTUAL},
|
||||
* {@link Opcodes#H_INVOKESTATIC},
|
||||
* {@link Opcodes#H_INVOKESPECIAL},
|
||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
||||
* @param owner
|
||||
* the internal name of the class that owns the field or method
|
||||
* designated by this handle.
|
||||
* @param name
|
||||
* the name of the field or method designated by this handle.
|
||||
* @param desc
|
||||
* the descriptor of the field or method designated by this
|
||||
* handle.
|
||||
* @param itf
|
||||
* true if the owner is an interface.
|
||||
*/
|
||||
public Handle(int tag, String owner, String name, String desc, boolean itf) {
|
||||
* Constructs a new field or method handle.
|
||||
*
|
||||
* @param tag the kind of field or method designated by this Handle. Must be {@link
|
||||
* Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
|
||||
* Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
|
||||
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
|
||||
* Opcodes#H_INVOKEINTERFACE}.
|
||||
* @param owner the internal name of the class that owns the field or method designated by this
|
||||
* handle.
|
||||
* @param name the name of the field or method designated by this handle.
|
||||
* @param descriptor the descriptor of the field or method designated by this handle.
|
||||
* @param isInterface whether the owner is an interface or not.
|
||||
*/
|
||||
public Handle(
|
||||
final int tag,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
this.tag = tag;
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.itf = itf;
|
||||
this.descriptor = descriptor;
|
||||
this.isInterface = isInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind of field or method designated by this handle.
|
||||
*
|
||||
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
|
||||
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
|
||||
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
|
||||
* {@link Opcodes#H_INVOKESPECIAL},
|
||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
||||
*/
|
||||
* Returns the kind of field or method designated by this handle.
|
||||
*
|
||||
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
|
||||
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
|
||||
* Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
|
||||
* Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
|
||||
*/
|
||||
public int getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the internal name of the class that owns the field or method
|
||||
* designated by this handle.
|
||||
*
|
||||
* @return the internal name of the class that owns the field or method
|
||||
* designated by this handle.
|
||||
*/
|
||||
* Returns the internal name of the class that owns the field or method designated by this handle.
|
||||
*
|
||||
* @return the internal name of the class that owns the field or method designated by this handle.
|
||||
*/
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the field or method designated by this handle.
|
||||
*
|
||||
* @return the name of the field or method designated by this handle.
|
||||
*/
|
||||
* Returns the name of the field or method designated by this handle.
|
||||
*
|
||||
* @return the name of the field or method designated by this handle.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the descriptor of the field or method designated by this handle.
|
||||
*
|
||||
* @return the descriptor of the field or method designated by this handle.
|
||||
*/
|
||||
* Returns the descriptor of the field or method designated by this handle.
|
||||
*
|
||||
* @return the descriptor of the field or method designated by this handle.
|
||||
*/
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the owner of the field or method designated
|
||||
* by this handle is an interface.
|
||||
*
|
||||
* @return true if the owner of the field or method designated
|
||||
* by this handle is an interface.
|
||||
*/
|
||||
* Returns true if the owner of the field or method designated by this handle is an interface.
|
||||
*
|
||||
* @return true if the owner of the field or method designated by this handle is an interface.
|
||||
*/
|
||||
public boolean isInterface() {
|
||||
return itf;
|
||||
return isInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
public boolean equals(final Object object) {
|
||||
if (object == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof Handle)) {
|
||||
if (!(object instanceof Handle)) {
|
||||
return false;
|
||||
}
|
||||
Handle h = (Handle) obj;
|
||||
return tag == h.tag && itf == h.itf && owner.equals(h.owner)
|
||||
&& name.equals(h.name) && desc.equals(h.desc);
|
||||
Handle handle = (Handle) object;
|
||||
return tag == handle.tag
|
||||
&& isInterface == handle.isInterface
|
||||
&& owner.equals(handle.owner)
|
||||
&& name.equals(handle.name)
|
||||
&& descriptor.equals(handle.descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode();
|
||||
return tag
|
||||
+ (isInterface ? 64 : 0)
|
||||
+ owner.hashCode() * name.hashCode() * descriptor.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textual representation of this handle. The textual
|
||||
* representation is:
|
||||
*
|
||||
* <pre>
|
||||
* for a reference to a class:
|
||||
* owner '.' name desc ' ' '(' tag ')'
|
||||
* for a reference to an interface:
|
||||
* owner '.' name desc ' ' '(' tag ' ' itf ')'
|
||||
* </pre>
|
||||
*
|
||||
* . As this format is unambiguous, it can be parsed if necessary.
|
||||
*/
|
||||
* Returns the textual representation of this handle. The textual representation is:
|
||||
*
|
||||
* <ul>
|
||||
* <li>for a reference to a class: owner "." name descriptor " (" tag ")",
|
||||
* <li>for a reference to an interface: owner "." name descriptor " (" tag " itf)".
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')';
|
||||
return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,92 +59,171 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* Information about an exception handler block.
|
||||
* Information about an exception handler. Corresponds to an element of the exception_table array of
|
||||
* a Code attribute, as defined in the Java Virtual Machine Specification (JVMS). Handler instances
|
||||
* can be chained together, with their {@link #nextHandler} field, to describe a full JVMS
|
||||
* exception_table array.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
|
||||
* 4.7.3</a>
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Handler {
|
||||
final class Handler {
|
||||
|
||||
/**
|
||||
* Beginning of the exception handler's scope (inclusive).
|
||||
*/
|
||||
Label start;
|
||||
* The start_pc field of this JVMS exception_table entry. Corresponds to the beginning of the
|
||||
* exception handler's scope (inclusive).
|
||||
*/
|
||||
final Label startPc;
|
||||
|
||||
/**
|
||||
* End of the exception handler's scope (exclusive).
|
||||
*/
|
||||
Label end;
|
||||
* The end_pc field of this JVMS exception_table entry. Corresponds to the end of the exception
|
||||
* handler's scope (exclusive).
|
||||
*/
|
||||
final Label endPc;
|
||||
|
||||
/**
|
||||
* Beginning of the exception handler's code.
|
||||
*/
|
||||
Label handler;
|
||||
* The handler_pc field of this JVMS exception_table entry. Corresponding to the beginning of the
|
||||
* exception handler's code.
|
||||
*/
|
||||
final Label handlerPc;
|
||||
|
||||
/**
|
||||
* Internal name of the type of exceptions handled by this handler, or
|
||||
* <tt>null</tt> to catch any exceptions.
|
||||
*/
|
||||
String desc;
|
||||
* The catch_type field of this JVMS exception_table entry. This is the constant pool index of the
|
||||
* internal name of the type of exceptions handled by this handler, or 0 to catch any exceptions.
|
||||
*/
|
||||
final int catchType;
|
||||
|
||||
/**
|
||||
* Constant pool index of the internal name of the type of exceptions
|
||||
* handled by this handler, or 0 to catch any exceptions.
|
||||
*/
|
||||
int type;
|
||||
* The internal name of the type of exceptions handled by this handler, or {@literal null} to
|
||||
* catch any exceptions.
|
||||
*/
|
||||
final String catchTypeDescriptor;
|
||||
|
||||
/** The next exception handler. */
|
||||
Handler nextHandler;
|
||||
|
||||
/**
|
||||
* Next exception handler block info.
|
||||
*/
|
||||
Handler next;
|
||||
* Constructs a new Handler.
|
||||
*
|
||||
* @param startPc the start_pc field of this JVMS exception_table entry.
|
||||
* @param endPc the end_pc field of this JVMS exception_table entry.
|
||||
* @param handlerPc the handler_pc field of this JVMS exception_table entry.
|
||||
* @param catchType The catch_type field of this JVMS exception_table entry.
|
||||
* @param catchTypeDescriptor The internal name of the type of exceptions handled by this handler,
|
||||
* or {@literal null} to catch any exceptions.
|
||||
*/
|
||||
Handler(
|
||||
final Label startPc,
|
||||
final Label endPc,
|
||||
final Label handlerPc,
|
||||
final int catchType,
|
||||
final String catchTypeDescriptor) {
|
||||
this.startPc = startPc;
|
||||
this.endPc = endPc;
|
||||
this.handlerPc = handlerPc;
|
||||
this.catchType = catchType;
|
||||
this.catchTypeDescriptor = catchTypeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the range between start and end from the given exception
|
||||
* handlers.
|
||||
*
|
||||
* @param h
|
||||
* an exception handler list.
|
||||
* @param start
|
||||
* the start of the range to be removed.
|
||||
* @param end
|
||||
* the end of the range to be removed. Maybe null.
|
||||
* @return the exception handler list with the start-end range removed.
|
||||
*/
|
||||
static Handler remove(Handler h, Label start, Label end) {
|
||||
if (h == null) {
|
||||
* Constructs a new Handler from the given one, with a different scope.
|
||||
*
|
||||
* @param handler an existing Handler.
|
||||
* @param startPc the start_pc field of this JVMS exception_table entry.
|
||||
* @param endPc the end_pc field of this JVMS exception_table entry.
|
||||
*/
|
||||
Handler(final Handler handler, final Label startPc, final Label endPc) {
|
||||
this(startPc, endPc, handler.handlerPc, handler.catchType, handler.catchTypeDescriptor);
|
||||
this.nextHandler = handler.nextHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the range between start and end from the Handler list that begins with the given
|
||||
* element.
|
||||
*
|
||||
* @param firstHandler the beginning of a Handler list. May be {@literal null}.
|
||||
* @param start the start of the range to be removed.
|
||||
* @param end the end of the range to be removed. Maybe {@literal null}.
|
||||
* @return the exception handler list with the start-end range removed.
|
||||
*/
|
||||
static Handler removeRange(final Handler firstHandler, final Label start, final Label end) {
|
||||
if (firstHandler == null) {
|
||||
return null;
|
||||
} else {
|
||||
h.next = remove(h.next, start, end);
|
||||
firstHandler.nextHandler = removeRange(firstHandler.nextHandler, start, end);
|
||||
}
|
||||
int hstart = h.start.position;
|
||||
int hend = h.end.position;
|
||||
int s = start.position;
|
||||
int e = end == null ? Integer.MAX_VALUE : end.position;
|
||||
// if [hstart,hend[ and [s,e[ intervals intersect...
|
||||
if (s < hend && e > hstart) {
|
||||
if (s <= hstart) {
|
||||
if (e >= hend) {
|
||||
// [hstart,hend[ fully included in [s,e[, h removed
|
||||
h = h.next;
|
||||
} else {
|
||||
// [hstart,hend[ minus [s,e[ = [e,hend[
|
||||
h.start = end;
|
||||
}
|
||||
} else if (e >= hend) {
|
||||
// [hstart,hend[ minus [s,e[ = [hstart,s[
|
||||
h.end = start;
|
||||
int handlerStart = firstHandler.startPc.bytecodeOffset;
|
||||
int handlerEnd = firstHandler.endPc.bytecodeOffset;
|
||||
int rangeStart = start.bytecodeOffset;
|
||||
int rangeEnd = end == null ? Integer.MAX_VALUE : end.bytecodeOffset;
|
||||
// Return early if [handlerStart,handlerEnd[ and [rangeStart,rangeEnd[ don't intersect.
|
||||
if (rangeStart >= handlerEnd || rangeEnd <= handlerStart) {
|
||||
return firstHandler;
|
||||
}
|
||||
if (rangeStart <= handlerStart) {
|
||||
if (rangeEnd >= handlerEnd) {
|
||||
// If [handlerStart,handlerEnd[ is included in [rangeStart,rangeEnd[, remove firstHandler.
|
||||
return firstHandler.nextHandler;
|
||||
} else {
|
||||
// [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
|
||||
Handler g = new Handler();
|
||||
g.start = end;
|
||||
g.end = h.end;
|
||||
g.handler = h.handler;
|
||||
g.desc = h.desc;
|
||||
g.type = h.type;
|
||||
g.next = h.next;
|
||||
h.end = start;
|
||||
h.next = g;
|
||||
// [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ = [rangeEnd,handlerEnd[
|
||||
return new Handler(firstHandler, end, firstHandler.endPc);
|
||||
}
|
||||
} else if (rangeEnd >= handlerEnd) {
|
||||
// [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ = [handlerStart,rangeStart[
|
||||
return new Handler(firstHandler, firstHandler.startPc, start);
|
||||
} else {
|
||||
// [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ =
|
||||
// [handlerStart,rangeStart[ + [rangeEnd,handerEnd[
|
||||
firstHandler.nextHandler = new Handler(firstHandler, end, firstHandler.endPc);
|
||||
return new Handler(firstHandler, firstHandler.startPc, start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements of the Handler list that begins with the given element.
|
||||
*
|
||||
* @param firstHandler the beginning of a Handler list. May be {@literal null}.
|
||||
* @return the number of elements of the Handler list that begins with 'handler'.
|
||||
*/
|
||||
static int getExceptionTableLength(final Handler firstHandler) {
|
||||
int length = 0;
|
||||
Handler handler = firstHandler;
|
||||
while (handler != null) {
|
||||
length++;
|
||||
handler = handler.nextHandler;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size in bytes of the JVMS exception_table corresponding to the Handler list that
|
||||
* begins with the given element. <i>This includes the exception_table_length field.</i>
|
||||
*
|
||||
* @param firstHandler the beginning of a Handler list. May be {@literal null}.
|
||||
* @return the size in bytes of the exception_table_length and exception_table structures.
|
||||
*/
|
||||
static int getExceptionTableSize(final Handler firstHandler) {
|
||||
return 2 + 8 * getExceptionTableLength(firstHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the JVMS exception_table corresponding to the Handler list that begins with the given
|
||||
* element. <i>This includes the exception_table_length field.</i>
|
||||
*
|
||||
* @param firstHandler the beginning of a Handler list. May be {@literal null}.
|
||||
* @param output where the exception_table_length and exception_table structures must be put.
|
||||
*/
|
||||
static void putExceptionTable(final Handler firstHandler, final ByteVector output) {
|
||||
output.putShort(getExceptionTableLength(firstHandler));
|
||||
Handler handler = firstHandler;
|
||||
while (handler != null) {
|
||||
output
|
||||
.putShort(handler.startPc.bytecodeOffset)
|
||||
.putShort(handler.endPc.bytecodeOffset)
|
||||
.putShort(handler.handlerPc.bytecodeOffset)
|
||||
.putShort(handler.catchType);
|
||||
handler = handler.nextHandler;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,347 +0,0 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A constant pool item. Constant pool items can be created with the 'newXXX'
|
||||
* methods in the {@link ClassWriter} class.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class Item {
|
||||
|
||||
/**
|
||||
* Index of this item in the constant pool.
|
||||
*/
|
||||
int index;
|
||||
|
||||
/**
|
||||
* Type of this constant pool item. A single class is used to represent all
|
||||
* constant pool item types, in order to minimize the bytecode size of this
|
||||
* package. The value of this field is one of {@link ClassWriter#INT},
|
||||
* {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
|
||||
* {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
|
||||
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
|
||||
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
|
||||
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
|
||||
* {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
|
||||
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
|
||||
*
|
||||
* MethodHandle constant 9 variations are stored using a range of 9 values
|
||||
* from {@link ClassWriter#HANDLE_BASE} + 1 to
|
||||
* {@link ClassWriter#HANDLE_BASE} + 9.
|
||||
*
|
||||
* Special Item types are used for Items that are stored in the ClassWriter
|
||||
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to
|
||||
* avoid clashes with normal constant pool items in the ClassWriter constant
|
||||
* pool's hash table. These special item types are
|
||||
* {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
|
||||
* {@link ClassWriter#TYPE_MERGED}.
|
||||
*/
|
||||
int type;
|
||||
|
||||
/**
|
||||
* Value of this item, for an integer item.
|
||||
*/
|
||||
int intVal;
|
||||
|
||||
/**
|
||||
* Value of this item, for a long item.
|
||||
*/
|
||||
long longVal;
|
||||
|
||||
/**
|
||||
* First part of the value of this item, for items that do not hold a
|
||||
* primitive value.
|
||||
*/
|
||||
String strVal1;
|
||||
|
||||
/**
|
||||
* Second part of the value of this item, for items that do not hold a
|
||||
* primitive value.
|
||||
*/
|
||||
String strVal2;
|
||||
|
||||
/**
|
||||
* Third part of the value of this item, for items that do not hold a
|
||||
* primitive value.
|
||||
*/
|
||||
String strVal3;
|
||||
|
||||
/**
|
||||
* The hash code value of this constant pool item.
|
||||
*/
|
||||
int hashCode;
|
||||
|
||||
/**
|
||||
* Link to another constant pool item, used for collision lists in the
|
||||
* constant pool's hash table.
|
||||
*/
|
||||
Item next;
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized {@link Item}.
|
||||
*/
|
||||
Item() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized {@link Item} for constant pool element at
|
||||
* given position.
|
||||
*
|
||||
* @param index
|
||||
* index of the item to be constructed.
|
||||
*/
|
||||
Item(final int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a copy of the given item.
|
||||
*
|
||||
* @param index
|
||||
* index of the item to be constructed.
|
||||
* @param i
|
||||
* the item that must be copied into the item to be constructed.
|
||||
*/
|
||||
Item(final int index, final Item i) {
|
||||
this.index = index;
|
||||
type = i.type;
|
||||
intVal = i.intVal;
|
||||
longVal = i.longVal;
|
||||
strVal1 = i.strVal1;
|
||||
strVal2 = i.strVal2;
|
||||
strVal3 = i.strVal3;
|
||||
hashCode = i.hashCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item to an integer item.
|
||||
*
|
||||
* @param intVal
|
||||
* the value of this item.
|
||||
*/
|
||||
void set(final int intVal) {
|
||||
this.type = ClassWriter.INT;
|
||||
this.intVal = intVal;
|
||||
this.hashCode = 0x7FFFFFFF & (type + intVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item to a long item.
|
||||
*
|
||||
* @param longVal
|
||||
* the value of this item.
|
||||
*/
|
||||
void set(final long longVal) {
|
||||
this.type = ClassWriter.LONG;
|
||||
this.longVal = longVal;
|
||||
this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item to a float item.
|
||||
*
|
||||
* @param floatVal
|
||||
* the value of this item.
|
||||
*/
|
||||
void set(final float floatVal) {
|
||||
this.type = ClassWriter.FLOAT;
|
||||
this.intVal = Float.floatToRawIntBits(floatVal);
|
||||
this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item to a double item.
|
||||
*
|
||||
* @param doubleVal
|
||||
* the value of this item.
|
||||
*/
|
||||
void set(final double doubleVal) {
|
||||
this.type = ClassWriter.DOUBLE;
|
||||
this.longVal = Double.doubleToRawLongBits(doubleVal);
|
||||
this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item to an item that do not hold a primitive value.
|
||||
*
|
||||
* @param type
|
||||
* the type of this item.
|
||||
* @param strVal1
|
||||
* first part of the value of this item.
|
||||
* @param strVal2
|
||||
* second part of the value of this item.
|
||||
* @param strVal3
|
||||
* third part of the value of this item.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
void set(final int type, final String strVal1, final String strVal2,
|
||||
final String strVal3) {
|
||||
this.type = type;
|
||||
this.strVal1 = strVal1;
|
||||
this.strVal2 = strVal2;
|
||||
this.strVal3 = strVal3;
|
||||
switch (type) {
|
||||
case ClassWriter.CLASS:
|
||||
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
|
||||
case ClassWriter.UTF8:
|
||||
case ClassWriter.STR:
|
||||
case ClassWriter.MTYPE:
|
||||
case ClassWriter.MODULE:
|
||||
case ClassWriter.PACKAGE:
|
||||
case ClassWriter.TYPE_NORMAL:
|
||||
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
|
||||
return;
|
||||
case ClassWriter.NAME_TYPE: {
|
||||
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
|
||||
* strVal2.hashCode());
|
||||
return;
|
||||
}
|
||||
// ClassWriter.FIELD:
|
||||
// ClassWriter.METH:
|
||||
// ClassWriter.IMETH:
|
||||
// ClassWriter.HANDLE_BASE + 1..9
|
||||
default:
|
||||
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
|
||||
* strVal2.hashCode() * strVal3.hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item to an InvokeDynamic item.
|
||||
*
|
||||
* @param name
|
||||
* invokedynamic's name.
|
||||
* @param desc
|
||||
* invokedynamic's desc.
|
||||
* @param bsmIndex
|
||||
* zero based index into the class attribute BootrapMethods.
|
||||
*/
|
||||
void set(String name, String desc, int bsmIndex) {
|
||||
this.type = ClassWriter.INDY;
|
||||
this.longVal = bsmIndex;
|
||||
this.strVal1 = name;
|
||||
this.strVal2 = desc;
|
||||
this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
|
||||
* strVal1.hashCode() * strVal2.hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item to a BootstrapMethod item.
|
||||
*
|
||||
* @param position
|
||||
* position in byte in the class attribute BootrapMethods.
|
||||
* @param hashCode
|
||||
* hashcode of the item. This hashcode is processed from the
|
||||
* hashcode of the bootstrap method and the hashcode of all
|
||||
* bootstrap arguments.
|
||||
*/
|
||||
void set(int position, int hashCode) {
|
||||
this.type = ClassWriter.BSM;
|
||||
this.intVal = position;
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the given item is equal to this one. <i>This method assumes
|
||||
* that the two items have the same {@link #type}</i>.
|
||||
*
|
||||
* @param i
|
||||
* the item to be compared to this one. Both items must have the
|
||||
* same {@link #type}.
|
||||
* @return <tt>true</tt> if the given item if equal to this one,
|
||||
* <tt>false</tt> otherwise.
|
||||
*/
|
||||
boolean isEqualTo(final Item i) {
|
||||
switch (type) {
|
||||
case ClassWriter.UTF8:
|
||||
case ClassWriter.STR:
|
||||
case ClassWriter.CLASS:
|
||||
case ClassWriter.MODULE:
|
||||
case ClassWriter.PACKAGE:
|
||||
case ClassWriter.MTYPE:
|
||||
case ClassWriter.TYPE_NORMAL:
|
||||
return i.strVal1.equals(strVal1);
|
||||
case ClassWriter.TYPE_MERGED:
|
||||
case ClassWriter.LONG:
|
||||
case ClassWriter.DOUBLE:
|
||||
return i.longVal == longVal;
|
||||
case ClassWriter.INT:
|
||||
case ClassWriter.FLOAT:
|
||||
return i.intVal == intVal;
|
||||
case ClassWriter.TYPE_UNINIT:
|
||||
return i.intVal == intVal && i.strVal1.equals(strVal1);
|
||||
case ClassWriter.NAME_TYPE:
|
||||
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
|
||||
case ClassWriter.INDY: {
|
||||
return i.longVal == longVal && i.strVal1.equals(strVal1)
|
||||
&& i.strVal2.equals(strVal2);
|
||||
}
|
||||
// case ClassWriter.FIELD:
|
||||
// case ClassWriter.METH:
|
||||
// case ClassWriter.IMETH:
|
||||
// case ClassWriter.HANDLE_BASE + 1..9
|
||||
default:
|
||||
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
|
||||
&& i.strVal3.equals(strVal3);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* Exception thrown when the Code attribute of a method produced by a {@link ClassWriter} is too
|
||||
* large.
|
||||
*
|
||||
* @author Jason Zaugg
|
||||
*/
|
||||
public final class MethodTooLargeException extends IndexOutOfBoundsException {
|
||||
private static final long serialVersionUID = 6807380416709738314L;
|
||||
|
||||
private final String className;
|
||||
private final String methodName;
|
||||
private final String descriptor;
|
||||
private final int codeSize;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MethodTooLargeException}.
|
||||
*
|
||||
* @param className the internal name of the owner class.
|
||||
* @param methodName the name of the method.
|
||||
* @param descriptor the descriptor of the method.
|
||||
* @param codeSize the size of the method's Code attribute, in bytes.
|
||||
*/
|
||||
public MethodTooLargeException(
|
||||
final String className,
|
||||
final String methodName,
|
||||
final String descriptor,
|
||||
final int codeSize) {
|
||||
super("Method too large: " + className + "." + methodName + " " + descriptor);
|
||||
this.className = className;
|
||||
this.methodName = methodName;
|
||||
this.descriptor = descriptor;
|
||||
this.codeSize = codeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the internal name of the owner class.
|
||||
*
|
||||
* @return the internal name of the owner class.
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the method.
|
||||
*
|
||||
* @return the name of the method.
|
||||
*/
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the descriptor of the method.
|
||||
*
|
||||
* @return the descriptor of the method.
|
||||
*/
|
||||
public String getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the method's Code attribute, in bytes.
|
||||
*
|
||||
* @return the size of the method's Code attribute, in bytes.
|
||||
*/
|
||||
public int getCodeSize() {
|
||||
return codeSize;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -59,158 +59,144 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A visitor to visit a Java module. The methods of this class must be called in
|
||||
* the following order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
|
||||
* <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
|
||||
* <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
|
||||
* {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)}
|
||||
* take as parameter a package name or a module name. Unlike the other names which are internal names
|
||||
* (names separated by slash), module and package names are qualified names (names separated by dot).
|
||||
* A visitor to visit a Java module. The methods of this class must be called in the following
|
||||
* order: ( {@code visitMainClass} | ( {@code visitPackage} | {@code visitRequire} | {@code
|
||||
* visitExport} | {@code visitOpen} | {@code visitUse} | {@code visitProvide} )* ) {@code visitEnd}.
|
||||
*
|
||||
* @author Remi Forax
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class ModuleVisitor {
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The module visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
/** The module visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected ModuleVisitor mv;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Constructs a new {@link ModuleVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
|
||||
* or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public ModuleVisitor(final int api) {
|
||||
this(api, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
|
||||
* @param mv
|
||||
* the module visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public ModuleVisitor(final int api, final ModuleVisitor mv) {
|
||||
if (api != Opcodes.ASM6) {
|
||||
* Constructs a new {@link ModuleVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
|
||||
* or {@link Opcodes#ASM7}.
|
||||
* @param moduleVisitor the module visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
public ModuleVisitor(final int api, final ModuleVisitor moduleVisitor) {
|
||||
if (api != Opcodes.ASM6 && api != Opcodes.ASM7) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.mv = mv;
|
||||
this.mv = moduleVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the main class of the current module.
|
||||
*
|
||||
* @param mainClass the internal name of the main class of the current module.
|
||||
*/
|
||||
public void visitMainClass(String mainClass) {
|
||||
* Visit the main class of the current module.
|
||||
*
|
||||
* @param mainClass the internal name of the main class of the current module.
|
||||
*/
|
||||
public void visitMainClass(final String mainClass) {
|
||||
if (mv != null) {
|
||||
mv.visitMainClass(mainClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a package of the current module.
|
||||
*
|
||||
* @param packaze the qualified name of a package.
|
||||
*/
|
||||
public void visitPackage(String packaze) {
|
||||
* Visit a package of the current module.
|
||||
*
|
||||
* @param packaze the internal name of a package.
|
||||
*/
|
||||
public void visitPackage(final String packaze) {
|
||||
if (mv != null) {
|
||||
mv.visitPackage(packaze);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a dependence of the current module.
|
||||
*
|
||||
* @param module the qualified name of the dependence.
|
||||
* @param access the access flag of the dependence among
|
||||
* ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
|
||||
* and ACC_MANDATED.
|
||||
* @param version the module version at compile time or null.
|
||||
*/
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
* Visits a dependence of the current module.
|
||||
*
|
||||
* @param module the fully qualified name (using dots) of the dependence.
|
||||
* @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
|
||||
* ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param version the module version at compile time, or {@literal null}.
|
||||
*/
|
||||
public void visitRequire(final String module, final int access, final String version) {
|
||||
if (mv != null) {
|
||||
mv.visitRequire(module, access, version);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an exported package of the current module.
|
||||
*
|
||||
* @param packaze the qualified name of the exported package.
|
||||
* @param access the access flag of the exported package,
|
||||
* valid values are among {@code ACC_SYNTHETIC} and
|
||||
* {@code ACC_MANDATED}.
|
||||
* @param modules the qualified names of the modules that can access to
|
||||
* the public classes of the exported package or
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
* Visit an exported package of the current module.
|
||||
*
|
||||
* @param packaze the internal name of the exported package.
|
||||
* @param access the access flag of the exported package, valid values are among {@code
|
||||
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param modules the fully qualified names (using dots) of the modules that can access the public
|
||||
* classes of the exported package, or {@literal null}.
|
||||
*/
|
||||
public void visitExport(final String packaze, final int access, final String... modules) {
|
||||
if (mv != null) {
|
||||
mv.visitExport(packaze, access, modules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an open package of the current module.
|
||||
*
|
||||
* @param packaze the qualified name of the opened package.
|
||||
* @param access the access flag of the opened package,
|
||||
* valid values are among {@code ACC_SYNTHETIC} and
|
||||
* {@code ACC_MANDATED}.
|
||||
* @param modules the qualified names of the modules that can use deep
|
||||
* reflection to the classes of the open package or
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visitOpen(String packaze, int access, String... modules) {
|
||||
* Visit an open package of the current module.
|
||||
*
|
||||
* @param packaze the internal name of the opened package.
|
||||
* @param access the access flag of the opened package, valid values are among {@code
|
||||
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param modules the fully qualified names (using dots) of the modules that can use deep
|
||||
* reflection to the classes of the open package, or {@literal null}.
|
||||
*/
|
||||
public void visitOpen(final String packaze, final int access, final String... modules) {
|
||||
if (mv != null) {
|
||||
mv.visitOpen(packaze, access, modules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a service used by the current module.
|
||||
* The name must be the internal name of an interface or a class.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
*/
|
||||
public void visitUse(String service) {
|
||||
* Visit a service used by the current module. The name must be the internal name of an interface
|
||||
* or a class.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
*/
|
||||
public void visitUse(final String service) {
|
||||
if (mv != null) {
|
||||
mv.visitUse(service);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an implementation of a service.
|
||||
*
|
||||
* @param service the internal name of the service
|
||||
* @param providers the internal names of the implementations
|
||||
* of the service (there is at least one provider).
|
||||
*/
|
||||
public void visitProvide(String service, String... providers) {
|
||||
* Visit an implementation of a service.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
* @param providers the internal names of the implementations of the service (there is at least
|
||||
* one provider).
|
||||
*/
|
||||
public void visitProvide(final String service, final String... providers) {
|
||||
if (mv != null) {
|
||||
mv.visitProvide(service, providers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the end of the module. This method, which is the last one to be
|
||||
* called, is used to inform the visitor that everything have been visited.
|
||||
*/
|
||||
* Visits the end of the module. This method, which is the last one to be called, is used to
|
||||
* inform the visitor that everything have been visited.
|
||||
*/
|
||||
public void visitEnd() {
|
||||
if (mv != null) {
|
||||
mv.visitEnd();
|
||||
|
|
|
|||
|
|
@ -56,267 +56,229 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A {@link ModuleVisitor} that generates the corresponding Module, ModulePackages and
|
||||
* ModuleMainClass attributes, as defined in the Java Virtual Machine Specification (JVMS).
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25">JVMS
|
||||
* 4.7.25</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.26">JVMS
|
||||
* 4.7.26</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.27">JVMS
|
||||
* 4.7.27</a>
|
||||
* @author Remi Forax
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class ModuleWriter extends ModuleVisitor {
|
||||
/**
|
||||
* The class writer to which this Module attribute must be added.
|
||||
*/
|
||||
private final ClassWriter cw;
|
||||
|
||||
/**
|
||||
* size in byte of the Module attribute.
|
||||
*/
|
||||
int size;
|
||||
/** Where the constants used in this AnnotationWriter must be stored. */
|
||||
private final SymbolTable symbolTable;
|
||||
|
||||
/**
|
||||
* Number of attributes associated with the current module
|
||||
* (Version, ConcealPackages, etc)
|
||||
*/
|
||||
int attributeCount;
|
||||
/** The module_name_index field of the JVMS Module attribute. */
|
||||
private final int moduleNameIndex;
|
||||
|
||||
/**
|
||||
* Size in bytes of the attributes associated with the current module
|
||||
*/
|
||||
int attributesSize;
|
||||
/** The module_flags field of the JVMS Module attribute. */
|
||||
private final int moduleFlags;
|
||||
|
||||
/**
|
||||
* module name index in the constant pool
|
||||
*/
|
||||
private final int name;
|
||||
/** The module_version_index field of the JVMS Module attribute. */
|
||||
private final int moduleVersionIndex;
|
||||
|
||||
/**
|
||||
* module access flags
|
||||
*/
|
||||
private final int access;
|
||||
/** The requires_count field of the JVMS Module attribute. */
|
||||
private int requiresCount;
|
||||
|
||||
/**
|
||||
* module version index in the constant pool or 0
|
||||
*/
|
||||
private final int version;
|
||||
/** The binary content of the 'requires' array of the JVMS Module attribute. */
|
||||
private final ByteVector requires;
|
||||
|
||||
/**
|
||||
* module main class index in the constant pool or 0
|
||||
*/
|
||||
private int mainClass;
|
||||
/** The exports_count field of the JVMS Module attribute. */
|
||||
private int exportsCount;
|
||||
|
||||
/**
|
||||
* number of packages
|
||||
*/
|
||||
/** The binary content of the 'exports' array of the JVMS Module attribute. */
|
||||
private final ByteVector exports;
|
||||
|
||||
/** The opens_count field of the JVMS Module attribute. */
|
||||
private int opensCount;
|
||||
|
||||
/** The binary content of the 'opens' array of the JVMS Module attribute. */
|
||||
private final ByteVector opens;
|
||||
|
||||
/** The uses_count field of the JVMS Module attribute. */
|
||||
private int usesCount;
|
||||
|
||||
/** The binary content of the 'uses_index' array of the JVMS Module attribute. */
|
||||
private final ByteVector usesIndex;
|
||||
|
||||
/** The provides_count field of the JVMS Module attribute. */
|
||||
private int providesCount;
|
||||
|
||||
/** The binary content of the 'provides' array of the JVMS Module attribute. */
|
||||
private final ByteVector provides;
|
||||
|
||||
/** The provides_count field of the JVMS ModulePackages attribute. */
|
||||
private int packageCount;
|
||||
|
||||
/**
|
||||
* The packages in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in packageCount
|
||||
*/
|
||||
private ByteVector packages;
|
||||
/** The binary content of the 'package_index' array of the JVMS ModulePackages attribute. */
|
||||
private final ByteVector packageIndex;
|
||||
|
||||
/**
|
||||
* number of requires items
|
||||
*/
|
||||
private int requireCount;
|
||||
/** The main_class_index field of the JVMS ModuleMainClass attribute, or 0. */
|
||||
private int mainClassIndex;
|
||||
|
||||
/**
|
||||
* The requires items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in requireCount
|
||||
*/
|
||||
private ByteVector requires;
|
||||
|
||||
/**
|
||||
* number of exports items
|
||||
*/
|
||||
private int exportCount;
|
||||
|
||||
/**
|
||||
* The exports items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in exportCount
|
||||
*/
|
||||
private ByteVector exports;
|
||||
|
||||
/**
|
||||
* number of opens items
|
||||
*/
|
||||
private int openCount;
|
||||
|
||||
/**
|
||||
* The opens items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in openCount
|
||||
*/
|
||||
private ByteVector opens;
|
||||
|
||||
/**
|
||||
* number of uses items
|
||||
*/
|
||||
private int useCount;
|
||||
|
||||
/**
|
||||
* The uses items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in useCount
|
||||
*/
|
||||
private ByteVector uses;
|
||||
|
||||
/**
|
||||
* number of provides items
|
||||
*/
|
||||
private int provideCount;
|
||||
|
||||
/**
|
||||
* The uses provides in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in provideCount
|
||||
*/
|
||||
private ByteVector provides;
|
||||
|
||||
ModuleWriter(final ClassWriter cw, final int name,
|
||||
final int access, final int version) {
|
||||
super(Opcodes.ASM6);
|
||||
this.cw = cw;
|
||||
this.size = 16; // name + access + version + 5 counts
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
this.version = version;
|
||||
ModuleWriter(final SymbolTable symbolTable, final int name, final int access, final int version) {
|
||||
super(Opcodes.ASM7);
|
||||
this.symbolTable = symbolTable;
|
||||
this.moduleNameIndex = name;
|
||||
this.moduleFlags = access;
|
||||
this.moduleVersionIndex = version;
|
||||
this.requires = new ByteVector();
|
||||
this.exports = new ByteVector();
|
||||
this.opens = new ByteVector();
|
||||
this.usesIndex = new ByteVector();
|
||||
this.provides = new ByteVector();
|
||||
this.packageIndex = new ByteVector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMainClass(String mainClass) {
|
||||
if (this.mainClass == 0) { // protect against several calls to visitMainClass
|
||||
cw.newUTF8("ModuleMainClass");
|
||||
attributeCount++;
|
||||
attributesSize += 8;
|
||||
}
|
||||
this.mainClass = cw.newClass(mainClass);
|
||||
public void visitMainClass(final String mainClass) {
|
||||
this.mainClassIndex = symbolTable.addConstantClass(mainClass).index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPackage(String packaze) {
|
||||
if (packages == null) {
|
||||
// protect against several calls to visitPackage
|
||||
cw.newUTF8("ModulePackages");
|
||||
packages = new ByteVector();
|
||||
attributeCount++;
|
||||
attributesSize += 8;
|
||||
}
|
||||
packages.putShort(cw.newPackage(packaze));
|
||||
public void visitPackage(final String packaze) {
|
||||
packageIndex.putShort(symbolTable.addConstantPackage(packaze).index);
|
||||
packageCount++;
|
||||
attributesSize += 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
if (requires == null) {
|
||||
requires = new ByteVector();
|
||||
}
|
||||
requires.putShort(cw.newModule(module))
|
||||
public void visitRequire(final String module, final int access, final String version) {
|
||||
requires
|
||||
.putShort(symbolTable.addConstantModule(module).index)
|
||||
.putShort(access)
|
||||
.putShort(version == null? 0: cw.newUTF8(version));
|
||||
requireCount++;
|
||||
size += 6;
|
||||
.putShort(version == null ? 0 : symbolTable.addConstantUtf8(version));
|
||||
requiresCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
if (exports == null) {
|
||||
exports = new ByteVector();
|
||||
}
|
||||
exports.putShort(cw.newPackage(packaze)).putShort(access);
|
||||
public void visitExport(final String packaze, final int access, final String... modules) {
|
||||
exports.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
|
||||
if (modules == null) {
|
||||
exports.putShort(0);
|
||||
size += 6;
|
||||
} else {
|
||||
exports.putShort(modules.length);
|
||||
for(String module: modules) {
|
||||
exports.putShort(cw.newModule(module));
|
||||
for (String module : modules) {
|
||||
exports.putShort(symbolTable.addConstantModule(module).index);
|
||||
}
|
||||
size += 6 + 2 * modules.length;
|
||||
}
|
||||
exportCount++;
|
||||
exportsCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOpen(String packaze, int access, String... modules) {
|
||||
if (opens == null) {
|
||||
opens = new ByteVector();
|
||||
}
|
||||
opens.putShort(cw.newPackage(packaze)).putShort(access);
|
||||
public void visitOpen(final String packaze, final int access, final String... modules) {
|
||||
opens.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
|
||||
if (modules == null) {
|
||||
opens.putShort(0);
|
||||
size += 6;
|
||||
} else {
|
||||
opens.putShort(modules.length);
|
||||
for(String module: modules) {
|
||||
opens.putShort(cw.newModule(module));
|
||||
for (String module : modules) {
|
||||
opens.putShort(symbolTable.addConstantModule(module).index);
|
||||
}
|
||||
size += 6 + 2 * modules.length;
|
||||
}
|
||||
openCount++;
|
||||
opensCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUse(String service) {
|
||||
if (uses == null) {
|
||||
uses = new ByteVector();
|
||||
}
|
||||
uses.putShort(cw.newClass(service));
|
||||
useCount++;
|
||||
size += 2;
|
||||
public void visitUse(final String service) {
|
||||
usesIndex.putShort(symbolTable.addConstantClass(service).index);
|
||||
usesCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProvide(String service, String... providers) {
|
||||
if (provides == null) {
|
||||
provides = new ByteVector();
|
||||
}
|
||||
provides.putShort(cw.newClass(service));
|
||||
public void visitProvide(final String service, final String... providers) {
|
||||
provides.putShort(symbolTable.addConstantClass(service).index);
|
||||
provides.putShort(providers.length);
|
||||
for(String provider: providers) {
|
||||
provides.putShort(cw.newClass(provider));
|
||||
for (String provider : providers) {
|
||||
provides.putShort(symbolTable.addConstantClass(provider).index);
|
||||
}
|
||||
provideCount++;
|
||||
size += 4 + 2 * providers.length;
|
||||
providesCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// empty
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
void putAttributes(ByteVector out) {
|
||||
if (mainClass != 0) {
|
||||
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
|
||||
}
|
||||
if (packages != null) {
|
||||
out.putShort(cw.newUTF8("ModulePackages"))
|
||||
.putInt(2 + 2 * packageCount)
|
||||
.putShort(packageCount)
|
||||
.putByteArray(packages.data, 0, packages.length);
|
||||
}
|
||||
/**
|
||||
* Returns the number of Module, ModulePackages and ModuleMainClass attributes generated by this
|
||||
* ModuleWriter.
|
||||
*
|
||||
* @return the number of Module, ModulePackages and ModuleMainClass attributes (between 1 and 3).
|
||||
*/
|
||||
int getAttributeCount() {
|
||||
return 1 + (packageCount > 0 ? 1 : 0) + (mainClassIndex > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
void put(ByteVector out) {
|
||||
out.putInt(size);
|
||||
out.putShort(name).putShort(access).putShort(version);
|
||||
out.putShort(requireCount);
|
||||
if (requires != null) {
|
||||
out.putByteArray(requires.data, 0, requires.length);
|
||||
/**
|
||||
* Returns the size of the Module, ModulePackages and ModuleMainClass attributes generated by this
|
||||
* ModuleWriter. Also add the names of these attributes in the constant pool.
|
||||
*
|
||||
* @return the size in bytes of the Module, ModulePackages and ModuleMainClass attributes.
|
||||
*/
|
||||
int computeAttributesSize() {
|
||||
symbolTable.addConstantUtf8(Constants.MODULE);
|
||||
// 6 attribute header bytes, 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
|
||||
int size =
|
||||
22 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
|
||||
if (packageCount > 0) {
|
||||
symbolTable.addConstantUtf8(Constants.MODULE_PACKAGES);
|
||||
// 6 attribute header bytes, and 2 bytes for package_count.
|
||||
size += 8 + packageIndex.length;
|
||||
}
|
||||
out.putShort(exportCount);
|
||||
if (exports != null) {
|
||||
out.putByteArray(exports.data, 0, exports.length);
|
||||
if (mainClassIndex > 0) {
|
||||
symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS);
|
||||
// 6 attribute header bytes, and 2 bytes for main_class_index.
|
||||
size += 8;
|
||||
}
|
||||
out.putShort(openCount);
|
||||
if (opens != null) {
|
||||
out.putByteArray(opens.data, 0, opens.length);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the Module, ModulePackages and ModuleMainClass attributes generated by this ModuleWriter
|
||||
* in the given ByteVector.
|
||||
*
|
||||
* @param output where the attributes must be put.
|
||||
*/
|
||||
void putAttributes(final ByteVector output) {
|
||||
// 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
|
||||
int moduleAttributeLength =
|
||||
16 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
|
||||
output
|
||||
.putShort(symbolTable.addConstantUtf8(Constants.MODULE))
|
||||
.putInt(moduleAttributeLength)
|
||||
.putShort(moduleNameIndex)
|
||||
.putShort(moduleFlags)
|
||||
.putShort(moduleVersionIndex)
|
||||
.putShort(requiresCount)
|
||||
.putByteArray(requires.data, 0, requires.length)
|
||||
.putShort(exportsCount)
|
||||
.putByteArray(exports.data, 0, exports.length)
|
||||
.putShort(opensCount)
|
||||
.putByteArray(opens.data, 0, opens.length)
|
||||
.putShort(usesCount)
|
||||
.putByteArray(usesIndex.data, 0, usesIndex.length)
|
||||
.putShort(providesCount)
|
||||
.putByteArray(provides.data, 0, provides.length);
|
||||
if (packageCount > 0) {
|
||||
output
|
||||
.putShort(symbolTable.addConstantUtf8(Constants.MODULE_PACKAGES))
|
||||
.putInt(2 + packageIndex.length)
|
||||
.putShort(packageCount)
|
||||
.putByteArray(packageIndex.data, 0, packageIndex.length);
|
||||
}
|
||||
out.putShort(useCount);
|
||||
if (uses != null) {
|
||||
out.putByteArray(uses.data, 0, uses.length);
|
||||
}
|
||||
out.putShort(provideCount);
|
||||
if (provides != null) {
|
||||
out.putByteArray(provides.data, 0, provides.length);
|
||||
if (mainClassIndex > 0) {
|
||||
output
|
||||
.putShort(symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS))
|
||||
.putInt(2)
|
||||
.putShort(mainClassIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,26 +59,29 @@
|
|||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* Defines the JVM opcodes, access flags and array type codes. This interface
|
||||
* does not define all the JVM opcodes because some opcodes are automatically
|
||||
* handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
|
||||
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
|
||||
* opcodes are therefore not defined in this interface. Likewise for LDC,
|
||||
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
|
||||
* JSR_W.
|
||||
* The JVM opcodes, access flags and array type codes. This interface does not define all the JVM
|
||||
* opcodes because some opcodes are automatically handled. For example, the xLOAD and xSTORE opcodes
|
||||
* are automatically replaced by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and
|
||||
* xSTORE_n opcodes are therefore not defined in this interface. Likewise for LDC, automatically
|
||||
* replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and JSR_W.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
// DontCheck(InterfaceIsType): can't be fixed (for backward binary compatibility).
|
||||
public interface Opcodes {
|
||||
|
||||
// ASM API versions
|
||||
// ASM API versions.
|
||||
|
||||
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
||||
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
||||
int ASM6 = 6 << 16 | 0 << 8 | 0;
|
||||
int ASM4 = 4 << 16 | 0 << 8;
|
||||
int ASM5 = 5 << 16 | 0 << 8;
|
||||
int ASM6 = 6 << 16 | 0 << 8;
|
||||
int ASM7 = 7 << 16 | 0 << 8;
|
||||
|
||||
// versions
|
||||
// Java ClassFile versions (the minor version is stored in the 16 most
|
||||
// significant bits, and the
|
||||
// major version in the 16 least significant bits).
|
||||
|
||||
int V1_1 = 3 << 16 | 45;
|
||||
int V1_2 = 0 << 16 | 46;
|
||||
|
|
@ -93,7 +96,19 @@ public interface Opcodes {
|
|||
int V11 = 0 << 16 | 55;
|
||||
int V12 = 0 << 16 | 56;
|
||||
|
||||
// access flags
|
||||
/**
|
||||
* Version flag indicating that the class is using 'preview' features.
|
||||
*
|
||||
* <p>{@code version & V_PREVIEW == V_PREVIEW} tests if a version is flagged with {@code
|
||||
* V_PREVIEW}.
|
||||
*/
|
||||
int V_PREVIEW = 0xFFFF0000;
|
||||
|
||||
// Access flags values, defined in
|
||||
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1
|
||||
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5-200-A.1
|
||||
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6-200-A.1
|
||||
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25
|
||||
|
||||
int ACC_PUBLIC = 0x0001; // class, field, method
|
||||
int ACC_PRIVATE = 0x0002; // class, field, method
|
||||
|
|
@ -119,12 +134,15 @@ public interface Opcodes {
|
|||
int ACC_MANDATED = 0x8000; // parameter, module, module *
|
||||
int ACC_MODULE = 0x8000; // class
|
||||
|
||||
|
||||
// ASM specific pseudo access flags
|
||||
// ASM specific access flags.
|
||||
// WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
|
||||
// access flags, and also to make sure that these flags are automatically filtered out when
|
||||
// written in class files (because access flags are stored using 16 bits only).
|
||||
|
||||
int ACC_DEPRECATED = 0x20000; // class, field, method
|
||||
|
||||
// types for NEWARRAY
|
||||
// Possible values for the type operand of the NEWARRAY instruction.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html#jvms-6.5.newarray.
|
||||
|
||||
int T_BOOLEAN = 4;
|
||||
int T_CHAR = 5;
|
||||
|
|
@ -135,7 +153,8 @@ public interface Opcodes {
|
|||
int T_INT = 10;
|
||||
int T_LONG = 11;
|
||||
|
||||
// tags for Handle
|
||||
// Possible values for the reference_kind field of CONSTANT_MethodHandle_info structures.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.8.
|
||||
|
||||
int H_GETFIELD = 1;
|
||||
int H_GETSTATIC = 2;
|
||||
|
|
@ -147,57 +166,50 @@ public interface Opcodes {
|
|||
int H_NEWINVOKESPECIAL = 8;
|
||||
int H_INVOKEINTERFACE = 9;
|
||||
|
||||
// stack map frame types
|
||||
// ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
|
||||
|
||||
/**
|
||||
* Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
|
||||
*/
|
||||
/** An expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
|
||||
int F_NEW = -1;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame with complete frame data.
|
||||
*/
|
||||
/** A compressed frame with complete frame data. */
|
||||
int F_FULL = 0;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame where locals are the same as the locals in
|
||||
* the previous frame, except that additional 1-3 locals are defined, and
|
||||
* with an empty stack.
|
||||
*/
|
||||
* A compressed frame where locals are the same as the locals in the previous frame, except that
|
||||
* additional 1-3 locals are defined, and with an empty stack.
|
||||
*/
|
||||
int F_APPEND = 1;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame where locals are the same as the locals in
|
||||
* the previous frame, except that the last 1-3 locals are absent and with
|
||||
* an empty stack.
|
||||
*/
|
||||
* A compressed frame where locals are the same as the locals in the previous frame, except that
|
||||
* the last 1-3 locals are absent and with an empty stack.
|
||||
*/
|
||||
int F_CHOP = 2;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame with exactly the same locals as the
|
||||
* previous frame and with an empty stack.
|
||||
*/
|
||||
* A compressed frame with exactly the same locals as the previous frame and with an empty stack.
|
||||
*/
|
||||
int F_SAME = 3;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame with exactly the same locals as the
|
||||
* previous frame and with a single value on the stack.
|
||||
*/
|
||||
* A compressed frame with exactly the same locals as the previous frame and with a single value
|
||||
* on the stack.
|
||||
*/
|
||||
int F_SAME1 = 4;
|
||||
|
||||
// Do not try to change the following code to use auto-boxing,
|
||||
// these values are compared by reference and not by value
|
||||
// The constructor of Integer was deprecated in 9
|
||||
// but we are stuck with it by backward compatibility
|
||||
@SuppressWarnings("deprecation") Integer TOP = new Integer(0);
|
||||
@SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
|
||||
@SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
|
||||
@SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
|
||||
@SuppressWarnings("deprecation") Integer LONG = new Integer(4);
|
||||
@SuppressWarnings("deprecation") Integer NULL = new Integer(5);
|
||||
@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
|
||||
// Standard stack map frame element types, used in {@link ClassVisitor#visitFrame}.
|
||||
|
||||
// opcodes // visit method (- = idem)
|
||||
Integer TOP = Frame.ITEM_TOP;
|
||||
Integer INTEGER = Frame.ITEM_INTEGER;
|
||||
Integer FLOAT = Frame.ITEM_FLOAT;
|
||||
Integer DOUBLE = Frame.ITEM_DOUBLE;
|
||||
Integer LONG = Frame.ITEM_LONG;
|
||||
Integer NULL = Frame.ITEM_NULL;
|
||||
Integer UNINITIALIZED_THIS = Frame.ITEM_UNINITIALIZED_THIS;
|
||||
|
||||
// The JVM opcode values (with the MethodVisitor method name used to visit them in comment, and
|
||||
// where '-' means 'same method name as on the previous line').
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
|
||||
|
||||
int NOP = 0; // visitInsn
|
||||
int ACONST_NULL = 1; // -
|
||||
|
|
@ -218,33 +230,11 @@ public interface Opcodes {
|
|||
int BIPUSH = 16; // visitIntInsn
|
||||
int SIPUSH = 17; // -
|
||||
int LDC = 18; // visitLdcInsn
|
||||
// int LDC_W = 19; // -
|
||||
// int LDC2_W = 20; // -
|
||||
int ILOAD = 21; // visitVarInsn
|
||||
int LLOAD = 22; // -
|
||||
int FLOAD = 23; // -
|
||||
int DLOAD = 24; // -
|
||||
int ALOAD = 25; // -
|
||||
// int ILOAD_0 = 26; // -
|
||||
// int ILOAD_1 = 27; // -
|
||||
// int ILOAD_2 = 28; // -
|
||||
// int ILOAD_3 = 29; // -
|
||||
// int LLOAD_0 = 30; // -
|
||||
// int LLOAD_1 = 31; // -
|
||||
// int LLOAD_2 = 32; // -
|
||||
// int LLOAD_3 = 33; // -
|
||||
// int FLOAD_0 = 34; // -
|
||||
// int FLOAD_1 = 35; // -
|
||||
// int FLOAD_2 = 36; // -
|
||||
// int FLOAD_3 = 37; // -
|
||||
// int DLOAD_0 = 38; // -
|
||||
// int DLOAD_1 = 39; // -
|
||||
// int DLOAD_2 = 40; // -
|
||||
// int DLOAD_3 = 41; // -
|
||||
// int ALOAD_0 = 42; // -
|
||||
// int ALOAD_1 = 43; // -
|
||||
// int ALOAD_2 = 44; // -
|
||||
// int ALOAD_3 = 45; // -
|
||||
int IALOAD = 46; // visitInsn
|
||||
int LALOAD = 47; // -
|
||||
int FALOAD = 48; // -
|
||||
|
|
@ -258,26 +248,6 @@ public interface Opcodes {
|
|||
int FSTORE = 56; // -
|
||||
int DSTORE = 57; // -
|
||||
int ASTORE = 58; // -
|
||||
// int ISTORE_0 = 59; // -
|
||||
// int ISTORE_1 = 60; // -
|
||||
// int ISTORE_2 = 61; // -
|
||||
// int ISTORE_3 = 62; // -
|
||||
// int LSTORE_0 = 63; // -
|
||||
// int LSTORE_1 = 64; // -
|
||||
// int LSTORE_2 = 65; // -
|
||||
// int LSTORE_3 = 66; // -
|
||||
// int FSTORE_0 = 67; // -
|
||||
// int FSTORE_1 = 68; // -
|
||||
// int FSTORE_2 = 69; // -
|
||||
// int FSTORE_3 = 70; // -
|
||||
// int DSTORE_0 = 71; // -
|
||||
// int DSTORE_1 = 72; // -
|
||||
// int DSTORE_2 = 73; // -
|
||||
// int DSTORE_3 = 74; // -
|
||||
// int ASTORE_0 = 75; // -
|
||||
// int ASTORE_1 = 76; // -
|
||||
// int ASTORE_2 = 77; // -
|
||||
// int ASTORE_3 = 78; // -
|
||||
int IASTORE = 79; // visitInsn
|
||||
int LASTORE = 80; // -
|
||||
int FASTORE = 81; // -
|
||||
|
|
@ -395,10 +365,7 @@ public interface Opcodes {
|
|||
int INSTANCEOF = 193; // -
|
||||
int MONITORENTER = 194; // visitInsn
|
||||
int MONITOREXIT = 195; // -
|
||||
// int WIDE = 196; // NOT VISITED
|
||||
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
|
||||
int IFNULL = 198; // visitJumpInsn
|
||||
int IFNONNULL = 199; // -
|
||||
// int GOTO_W = 200; // -
|
||||
// int JSR_W = 201; // -
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* An entry of the constant pool, of the BootstrapMethods attribute, or of the (ASM specific) type
|
||||
* table of a class.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4">JVMS
|
||||
* 4.4</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
|
||||
* 4.7.23</a>
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
abstract class Symbol {
|
||||
|
||||
// Tag values for the constant pool entries (using the same order as in the JVMS).
|
||||
|
||||
/** The tag value of CONSTANT_Class_info JVMS structures. */
|
||||
static final int CONSTANT_CLASS_TAG = 7;
|
||||
|
||||
/** The tag value of CONSTANT_Fieldref_info JVMS structures. */
|
||||
static final int CONSTANT_FIELDREF_TAG = 9;
|
||||
|
||||
/** The tag value of CONSTANT_Methodref_info JVMS structures. */
|
||||
static final int CONSTANT_METHODREF_TAG = 10;
|
||||
|
||||
/** The tag value of CONSTANT_InterfaceMethodref_info JVMS structures. */
|
||||
static final int CONSTANT_INTERFACE_METHODREF_TAG = 11;
|
||||
|
||||
/** The tag value of CONSTANT_String_info JVMS structures. */
|
||||
static final int CONSTANT_STRING_TAG = 8;
|
||||
|
||||
/** The tag value of CONSTANT_Integer_info JVMS structures. */
|
||||
static final int CONSTANT_INTEGER_TAG = 3;
|
||||
|
||||
/** The tag value of CONSTANT_Float_info JVMS structures. */
|
||||
static final int CONSTANT_FLOAT_TAG = 4;
|
||||
|
||||
/** The tag value of CONSTANT_Long_info JVMS structures. */
|
||||
static final int CONSTANT_LONG_TAG = 5;
|
||||
|
||||
/** The tag value of CONSTANT_Double_info JVMS structures. */
|
||||
static final int CONSTANT_DOUBLE_TAG = 6;
|
||||
|
||||
/** The tag value of CONSTANT_NameAndType_info JVMS structures. */
|
||||
static final int CONSTANT_NAME_AND_TYPE_TAG = 12;
|
||||
|
||||
/** The tag value of CONSTANT_Utf8_info JVMS structures. */
|
||||
static final int CONSTANT_UTF8_TAG = 1;
|
||||
|
||||
/** The tag value of CONSTANT_MethodHandle_info JVMS structures. */
|
||||
static final int CONSTANT_METHOD_HANDLE_TAG = 15;
|
||||
|
||||
/** The tag value of CONSTANT_MethodType_info JVMS structures. */
|
||||
static final int CONSTANT_METHOD_TYPE_TAG = 16;
|
||||
|
||||
/** The tag value of CONSTANT_Dynamic_info JVMS structures. */
|
||||
static final int CONSTANT_DYNAMIC_TAG = 17;
|
||||
|
||||
/** The tag value of CONSTANT_InvokeDynamic_info JVMS structures. */
|
||||
static final int CONSTANT_INVOKE_DYNAMIC_TAG = 18;
|
||||
|
||||
/** The tag value of CONSTANT_Module_info JVMS structures. */
|
||||
static final int CONSTANT_MODULE_TAG = 19;
|
||||
|
||||
/** The tag value of CONSTANT_Package_info JVMS structures. */
|
||||
static final int CONSTANT_PACKAGE_TAG = 20;
|
||||
|
||||
// Tag values for the BootstrapMethods attribute entries (ASM specific tag).
|
||||
|
||||
/** The tag value of the BootstrapMethods attribute entries. */
|
||||
static final int BOOTSTRAP_METHOD_TAG = 64;
|
||||
|
||||
// Tag values for the type table entries (ASM specific tags).
|
||||
|
||||
/** The tag value of a normal type entry in the (ASM specific) type table of a class. */
|
||||
static final int TYPE_TAG = 128;
|
||||
|
||||
/**
|
||||
* The tag value of an {@link Frame#ITEM_UNINITIALIZED} type entry in the type table of a class.
|
||||
*/
|
||||
static final int UNINITIALIZED_TYPE_TAG = 129;
|
||||
|
||||
/** The tag value of a merged type entry in the (ASM specific) type table of a class. */
|
||||
static final int MERGED_TYPE_TAG = 130;
|
||||
|
||||
// Instance fields.
|
||||
|
||||
/**
|
||||
* The index of this symbol in the constant pool, in the BootstrapMethods attribute, or in the
|
||||
* (ASM specific) type table of a class (depending on the {@link #tag} value).
|
||||
*/
|
||||
final int index;
|
||||
|
||||
/**
|
||||
* A tag indicating the type of this symbol. Must be one of the static tag values defined in this
|
||||
* class.
|
||||
*/
|
||||
final int tag;
|
||||
|
||||
/**
|
||||
* The internal name of the owner class of this symbol. Only used for {@link
|
||||
* #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link
|
||||
* #CONSTANT_INTERFACE_METHODREF_TAG}, and {@link #CONSTANT_METHOD_HANDLE_TAG} symbols.
|
||||
*/
|
||||
final String owner;
|
||||
|
||||
/**
|
||||
* The name of the class field or method corresponding to this symbol. Only used for {@link
|
||||
* #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link
|
||||
* #CONSTANT_INTERFACE_METHODREF_TAG}, {@link #CONSTANT_NAME_AND_TYPE_TAG}, {@link
|
||||
* #CONSTANT_METHOD_HANDLE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link
|
||||
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.
|
||||
*/
|
||||
final String name;
|
||||
|
||||
/**
|
||||
* The string value of this symbol. This is:
|
||||
*
|
||||
* <ul>
|
||||
* <li>a field or method descriptor for {@link #CONSTANT_FIELDREF_TAG}, {@link
|
||||
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG}, {@link
|
||||
* #CONSTANT_NAME_AND_TYPE_TAG}, {@link #CONSTANT_METHOD_HANDLE_TAG}, {@link
|
||||
* #CONSTANT_METHOD_TYPE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link
|
||||
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
|
||||
* <li>an arbitrary string for {@link #CONSTANT_UTF8_TAG} and {@link #CONSTANT_STRING_TAG}
|
||||
* symbols,
|
||||
* <li>an internal class name for {@link #CONSTANT_CLASS_TAG}, {@link #TYPE_TAG} and {@link
|
||||
* #UNINITIALIZED_TYPE_TAG} symbols,
|
||||
* <li>{@literal null} for the other types of symbol.
|
||||
* </ul>
|
||||
*/
|
||||
final String value;
|
||||
|
||||
/**
|
||||
* The numeric value of this symbol. This is:
|
||||
*
|
||||
* <ul>
|
||||
* <li>the symbol's value for {@link #CONSTANT_INTEGER_TAG},{@link #CONSTANT_FLOAT_TAG}, {@link
|
||||
* #CONSTANT_LONG_TAG}, {@link #CONSTANT_DOUBLE_TAG},
|
||||
* <li>the CONSTANT_MethodHandle_info reference_kind field value for {@link
|
||||
* #CONSTANT_METHOD_HANDLE_TAG} symbols,
|
||||
* <li>the CONSTANT_InvokeDynamic_info bootstrap_method_attr_index field value for {@link
|
||||
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
|
||||
* <li>the offset of a bootstrap method in the BootstrapMethods boostrap_methods array, for
|
||||
* {@link #CONSTANT_DYNAMIC_TAG} or {@link #BOOTSTRAP_METHOD_TAG} symbols,
|
||||
* <li>the bytecode offset of the NEW instruction that created an {@link
|
||||
* Frame#ITEM_UNINITIALIZED} type for {@link #UNINITIALIZED_TYPE_TAG} symbols,
|
||||
* <li>the indices (in the class' type table) of two {@link #TYPE_TAG} source types for {@link
|
||||
* #MERGED_TYPE_TAG} symbols,
|
||||
* <li>0 for the other types of symbol.
|
||||
* </ul>
|
||||
*/
|
||||
final long data;
|
||||
|
||||
/**
|
||||
* Additional information about this symbol, generally computed lazily. <i>Warning: the value of
|
||||
* this field is ignored when comparing Symbol instances</i> (to avoid duplicate entries in a
|
||||
* SymbolTable). Therefore, this field should only contain data that can be computed from the
|
||||
* other fields of this class. It contains:
|
||||
*
|
||||
* <ul>
|
||||
* <li>the {@link Type#getArgumentsAndReturnSizes} of the symbol's method descriptor for {@link
|
||||
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link
|
||||
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
|
||||
* <li>the index in the InnerClasses_attribute 'classes' array (plus one) corresponding to this
|
||||
* class, for {@link #CONSTANT_CLASS_TAG} symbols,
|
||||
* <li>the index (in the class' type table) of the merged type of the two source types for
|
||||
* {@link #MERGED_TYPE_TAG} symbols,
|
||||
* <li>0 for the other types of symbol, or if this field has not been computed yet.
|
||||
* </ul>
|
||||
*/
|
||||
int info;
|
||||
|
||||
/**
|
||||
* Constructs a new Symbol. This constructor can't be used directly because the Symbol class is
|
||||
* abstract. Instead, use the factory methods of the {@link SymbolTable} class.
|
||||
*
|
||||
* @param index the symbol index in the constant pool, in the BootstrapMethods attribute, or in
|
||||
* the (ASM specific) type table of a class (depending on 'tag').
|
||||
* @param tag the symbol type. Must be one of the static tag values defined in this class.
|
||||
* @param owner The internal name of the symbol's owner class. Maybe {@literal null}.
|
||||
* @param name The name of the symbol's corresponding class field or method. Maybe {@literal
|
||||
* null}.
|
||||
* @param value The string value of this symbol. Maybe {@literal null}.
|
||||
* @param data The numeric value of this symbol.
|
||||
*/
|
||||
Symbol(
|
||||
final int index,
|
||||
final int tag,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String value,
|
||||
final long data) {
|
||||
this.index = index;
|
||||
this.tag = tag;
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result {@link Type#getArgumentsAndReturnSizes} on {@link #value}.
|
||||
*
|
||||
* @return the result {@link Type#getArgumentsAndReturnSizes} on {@link #value} (memoized in
|
||||
* {@link #info} for efficiency). This should only be used for {@link
|
||||
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link
|
||||
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.
|
||||
*/
|
||||
int getArgumentsAndReturnSizes() {
|
||||
if (info == 0) {
|
||||
info = Type.getArgumentsAndReturnSizes(value);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -29,7 +29,7 @@
|
|||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -56,170 +56,176 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* The path to a type argument, wildcard bound, array element type, or static
|
||||
* inner type within an enclosing type.
|
||||
* The path to a type argument, wildcard bound, array element type, or static inner type within an
|
||||
* enclosing type.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class TypePath {
|
||||
public final class TypePath {
|
||||
|
||||
/** A type path step that steps into the element type of an array type. See {@link #getStep}. */
|
||||
public static final int ARRAY_ELEMENT = 0;
|
||||
|
||||
/** A type path step that steps into the nested type of a class type. See {@link #getStep}. */
|
||||
public static final int INNER_TYPE = 1;
|
||||
|
||||
/** A type path step that steps into the bound of a wildcard type. See {@link #getStep}. */
|
||||
public static final int WILDCARD_BOUND = 2;
|
||||
|
||||
/** A type path step that steps into a type argument of a generic type. See {@link #getStep}. */
|
||||
public static final int TYPE_ARGUMENT = 3;
|
||||
|
||||
/**
|
||||
* A type path step that steps into the element type of an array type. See
|
||||
* {@link #getStep getStep}.
|
||||
*/
|
||||
public final static int ARRAY_ELEMENT = 0;
|
||||
* The byte array where the 'type_path' structure - as defined in the Java Virtual Machine
|
||||
* Specification (JVMS) - corresponding to this TypePath is stored. The first byte of the
|
||||
* structure in this array is given by {@link #typePathOffset}.
|
||||
*
|
||||
* @see <a
|
||||
* href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.2">JVMS
|
||||
* 4.7.20.2</a>
|
||||
*/
|
||||
private final byte[] typePathContainer;
|
||||
|
||||
/** The offset of the first byte of the type_path JVMS structure in {@link #typePathContainer}. */
|
||||
private final int typePathOffset;
|
||||
|
||||
/**
|
||||
* A type path step that steps into the nested type of a class type. See
|
||||
* {@link #getStep getStep}.
|
||||
*/
|
||||
public final static int INNER_TYPE = 1;
|
||||
|
||||
/**
|
||||
* A type path step that steps into the bound of a wildcard type. See
|
||||
* {@link #getStep getStep}.
|
||||
*/
|
||||
public final static int WILDCARD_BOUND = 2;
|
||||
|
||||
/**
|
||||
* A type path step that steps into a type argument of a generic type. See
|
||||
* {@link #getStep getStep}.
|
||||
*/
|
||||
public final static int TYPE_ARGUMENT = 3;
|
||||
|
||||
/**
|
||||
* The byte array where the path is stored, in Java class file format.
|
||||
*/
|
||||
byte[] b;
|
||||
|
||||
/**
|
||||
* The offset of the first byte of the type path in 'b'.
|
||||
*/
|
||||
int offset;
|
||||
|
||||
/**
|
||||
* Creates a new type path.
|
||||
*
|
||||
* @param b
|
||||
* the byte array containing the type path in Java class file
|
||||
* format.
|
||||
* @param offset
|
||||
* the offset of the first byte of the type path in 'b'.
|
||||
*/
|
||||
TypePath(byte[] b, int offset) {
|
||||
this.b = b;
|
||||
this.offset = offset;
|
||||
* Constructs a new TypePath.
|
||||
*
|
||||
* @param typePathContainer a byte array containing a type_path JVMS structure.
|
||||
* @param typePathOffset the offset of the first byte of the type_path structure in
|
||||
* typePathContainer.
|
||||
*/
|
||||
TypePath(final byte[] typePathContainer, final int typePathOffset) {
|
||||
this.typePathContainer = typePathContainer;
|
||||
this.typePathOffset = typePathOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of this path.
|
||||
*
|
||||
* @return the length of this path.
|
||||
*/
|
||||
* Returns the length of this path, i.e. its number of steps.
|
||||
*
|
||||
* @return the length of this path.
|
||||
*/
|
||||
public int getLength() {
|
||||
return b[offset];
|
||||
// path_length is stored in the first byte of a type_path.
|
||||
return typePathContainer[typePathOffset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given step of this path.
|
||||
*
|
||||
* @param index
|
||||
* an index between 0 and {@link #getLength()}, exclusive.
|
||||
* @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
|
||||
* INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
|
||||
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
|
||||
*/
|
||||
public int getStep(int index) {
|
||||
return b[offset + 2 * index + 1];
|
||||
* Returns the value of the given step of this path.
|
||||
*
|
||||
* @param index an index between 0 and {@link #getLength()}, exclusive.
|
||||
* @return one of {@link #ARRAY_ELEMENT}, {@link #INNER_TYPE}, {@link #WILDCARD_BOUND}, or {@link
|
||||
* #TYPE_ARGUMENT}.
|
||||
*/
|
||||
public int getStep(final int index) {
|
||||
// Returns the type_path_kind of the path element of the given index.
|
||||
return typePathContainer[typePathOffset + 2 * index + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the type argument that the given step is stepping
|
||||
* into. This method should only be used for steps whose value is
|
||||
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
|
||||
*
|
||||
* @param index
|
||||
* an index between 0 and {@link #getLength()}, exclusive.
|
||||
* @return the index of the type argument that the given step is stepping
|
||||
* into.
|
||||
*/
|
||||
public int getStepArgument(int index) {
|
||||
return b[offset + 2 * index + 2];
|
||||
* Returns the index of the type argument that the given step is stepping into. This method should
|
||||
* only be used for steps whose value is {@link #TYPE_ARGUMENT}.
|
||||
*
|
||||
* @param index an index between 0 and {@link #getLength()}, exclusive.
|
||||
* @return the index of the type argument that the given step is stepping into.
|
||||
*/
|
||||
public int getStepArgument(final int index) {
|
||||
// Returns the type_argument_index of the path element of the given index.
|
||||
return typePathContainer[typePathOffset + 2 * index + 2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a type path in string form, in the format used by
|
||||
* {@link #toString()}, into a TypePath object.
|
||||
*
|
||||
* @param typePath
|
||||
* a type path in string form, in the format used by
|
||||
* {@link #toString()}. May be null or empty.
|
||||
* @return the corresponding TypePath object, or null if the path is empty.
|
||||
*/
|
||||
* Converts a type path in string form, in the format used by {@link #toString()}, into a TypePath
|
||||
* object.
|
||||
*
|
||||
* @param typePath a type path in string form, in the format used by {@link #toString()}. May be
|
||||
* {@literal null} or empty.
|
||||
* @return the corresponding TypePath object, or {@literal null} if the path is empty.
|
||||
*/
|
||||
public static TypePath fromString(final String typePath) {
|
||||
if (typePath == null || typePath.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
int n = typePath.length();
|
||||
ByteVector out = new ByteVector(n);
|
||||
out.putByte(0);
|
||||
for (int i = 0; i < n;) {
|
||||
char c = typePath.charAt(i++);
|
||||
int typePathLength = typePath.length();
|
||||
ByteVector output = new ByteVector(typePathLength);
|
||||
output.putByte(0);
|
||||
int typePathIndex = 0;
|
||||
while (typePathIndex < typePathLength) {
|
||||
char c = typePath.charAt(typePathIndex++);
|
||||
if (c == '[') {
|
||||
out.put11(ARRAY_ELEMENT, 0);
|
||||
output.put11(ARRAY_ELEMENT, 0);
|
||||
} else if (c == '.') {
|
||||
out.put11(INNER_TYPE, 0);
|
||||
output.put11(INNER_TYPE, 0);
|
||||
} else if (c == '*') {
|
||||
out.put11(WILDCARD_BOUND, 0);
|
||||
output.put11(WILDCARD_BOUND, 0);
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
int typeArg = c - '0';
|
||||
while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
|
||||
typeArg = typeArg * 10 + c - '0';
|
||||
i += 1;
|
||||
while (typePathIndex < typePathLength) {
|
||||
c = typePath.charAt(typePathIndex++);
|
||||
if (c >= '0' && c <= '9') {
|
||||
typeArg = typeArg * 10 + c - '0';
|
||||
} else if (c == ';') {
|
||||
break;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
if (i < n && typePath.charAt(i) == ';') {
|
||||
i += 1;
|
||||
}
|
||||
out.put11(TYPE_ARGUMENT, typeArg);
|
||||
output.put11(TYPE_ARGUMENT, typeArg);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
out.data[0] = (byte) (out.length / 2);
|
||||
return new TypePath(out.data, 0);
|
||||
output.data[0] = (byte) (output.length / 2);
|
||||
return new TypePath(output.data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT
|
||||
* ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
|
||||
* INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
|
||||
* with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
|
||||
* argument index in decimal form followed by ';'.
|
||||
*/
|
||||
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT} steps are represented
|
||||
* with '[', {@link #INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND} steps with '*' and {@link
|
||||
* #TYPE_ARGUMENT} steps with their type argument index in decimal form followed by ';'.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
int length = getLength();
|
||||
StringBuilder result = new StringBuilder(length * 2);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
switch (getStep(i)) {
|
||||
case ARRAY_ELEMENT:
|
||||
result.append('[');
|
||||
break;
|
||||
case INNER_TYPE:
|
||||
result.append('.');
|
||||
break;
|
||||
case WILDCARD_BOUND:
|
||||
result.append('*');
|
||||
break;
|
||||
case TYPE_ARGUMENT:
|
||||
result.append(getStepArgument(i)).append(';');
|
||||
break;
|
||||
default:
|
||||
result.append('_');
|
||||
case ARRAY_ELEMENT:
|
||||
result.append('[');
|
||||
break;
|
||||
case INNER_TYPE:
|
||||
result.append('.');
|
||||
break;
|
||||
case WILDCARD_BOUND:
|
||||
result.append('*');
|
||||
break;
|
||||
case TYPE_ARGUMENT:
|
||||
result.append(getStepArgument(i)).append(';');
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the type_path JVMS structure corresponding to the given TypePath into the given
|
||||
* ByteVector.
|
||||
*
|
||||
* @param typePath a TypePath instance, or {@literal null} for empty paths.
|
||||
* @param output where the type path must be put.
|
||||
*/
|
||||
static void put(final TypePath typePath, final ByteVector output) {
|
||||
if (typePath == null) {
|
||||
output.putByte(0);
|
||||
} else {
|
||||
int length = typePath.typePathContainer[typePath.typePathOffset] * 2 + 1;
|
||||
output.putByteArray(typePath.typePathContainer, typePath.typePathOffset, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -56,426 +56,411 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm;
|
||||
|
||||
/**
|
||||
* A reference to a type appearing in a class, field or method declaration, or
|
||||
* on an instruction. Such a reference designates the part of the class where
|
||||
* the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
|
||||
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
|
||||
* declaration, etc).
|
||||
* A reference to a type appearing in a class, field or method declaration, or on an instruction.
|
||||
* Such a reference designates the part of the class where the referenced type is appearing (e.g. an
|
||||
* 'extends', 'implements' or 'throws' clause, a 'new' instruction, a 'catch' clause, a type cast, a
|
||||
* local variable declaration, etc).
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class TypeReference {
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* class. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CLASS_TYPE_PARAMETER = 0x00;
|
||||
* The sort of type references that target a type parameter of a generic class. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int CLASS_TYPE_PARAMETER = 0x00;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_TYPE_PARAMETER = 0x01;
|
||||
* The sort of type references that target a type parameter of a generic method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int METHOD_TYPE_PARAMETER = 0x01;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the super class of a class or one
|
||||
* of the interfaces it implements. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CLASS_EXTENDS = 0x10;
|
||||
* The sort of type references that target the super class of a class or one of the interfaces it
|
||||
* implements. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CLASS_EXTENDS = 0x10;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a bound of a type parameter of a
|
||||
* generic class. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
||||
* The sort of type references that target a bound of a type parameter of a generic class. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a bound of a type parameter of a
|
||||
* generic method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
||||
* The sort of type references that target a bound of a type parameter of a generic method. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
||||
|
||||
/** The sort of type references that target the type of a field. See {@link #getSort}. */
|
||||
public static final int FIELD = 0x13;
|
||||
|
||||
/** The sort of type references that target the return type of a method. See {@link #getSort}. */
|
||||
public static final int METHOD_RETURN = 0x14;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a field. See
|
||||
* {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int FIELD = 0x13;
|
||||
* The sort of type references that target the receiver type of a method. See {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_RECEIVER = 0x15;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the return type of a method. See
|
||||
* {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_RETURN = 0x14;
|
||||
* The sort of type references that target the type of a formal parameter of a method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int METHOD_FORMAL_PARAMETER = 0x16;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a method.
|
||||
* See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_RECEIVER = 0x15;
|
||||
* The sort of type references that target the type of an exception declared in the throws clause
|
||||
* of a method. See {@link #getSort}.
|
||||
*/
|
||||
public static final int THROWS = 0x17;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a formal parameter of
|
||||
* a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_FORMAL_PARAMETER = 0x16;
|
||||
* The sort of type references that target the type of a local variable in a method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int LOCAL_VARIABLE = 0x40;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of an exception declared
|
||||
* in the throws clause of a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int THROWS = 0x17;
|
||||
* The sort of type references that target the type of a resource variable in a method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int RESOURCE_VARIABLE = 0x41;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a local variable in a
|
||||
* method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int LOCAL_VARIABLE = 0x40;
|
||||
* The sort of type references that target the type of the exception of a 'catch' clause in a
|
||||
* method. See {@link #getSort}.
|
||||
*/
|
||||
public static final int EXCEPTION_PARAMETER = 0x42;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a resource variable
|
||||
* in a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int RESOURCE_VARIABLE = 0x41;
|
||||
* The sort of type references that target the type declared in an 'instanceof' instruction. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int INSTANCEOF = 0x43;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of the exception of a
|
||||
* 'catch' clause in a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int EXCEPTION_PARAMETER = 0x42;
|
||||
* The sort of type references that target the type of the object created by a 'new' instruction.
|
||||
* See {@link #getSort}.
|
||||
*/
|
||||
public static final int NEW = 0x44;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type declared in an
|
||||
* 'instanceof' instruction. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int INSTANCEOF = 0x43;
|
||||
* The sort of type references that target the receiver type of a constructor reference. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int CONSTRUCTOR_REFERENCE = 0x45;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of the object created by
|
||||
* a 'new' instruction. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int NEW = 0x44;
|
||||
* The sort of type references that target the receiver type of a method reference. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int METHOD_REFERENCE = 0x46;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a
|
||||
* constructor reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CONSTRUCTOR_REFERENCE = 0x45;
|
||||
* The sort of type references that target the type declared in an explicit or implicit cast
|
||||
* instruction. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CAST = 0x47;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a method
|
||||
* reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_REFERENCE = 0x46;
|
||||
* The sort of type references that target a type parameter of a generic constructor in a
|
||||
* constructor call. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type declared in an explicit
|
||||
* or implicit cast instruction. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CAST = 0x47;
|
||||
* The sort of type references that target a type parameter of a generic method in a method call.
|
||||
* See {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* constructor in a constructor call. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
|
||||
* The sort of type references that target a type parameter of a generic constructor in a
|
||||
* constructor reference. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* method in a method call. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
|
||||
* The sort of type references that target a type parameter of a generic method in a method
|
||||
* reference. See {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* constructor in a constructor reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
|
||||
* The target_type and target_info structures - as defined in the Java Virtual Machine
|
||||
* Specification (JVMS) - corresponding to this type reference. target_type uses one byte, and all
|
||||
* the target_info union fields use up to 3 bytes (except localvar_target, handled with the
|
||||
* specific method {@link MethodVisitor#visitLocalVariableAnnotation}). Thus, both structures can
|
||||
* be stored in an int.
|
||||
*
|
||||
* <p>This int field stores target_type (called the TypeReference 'sort' in the public API of this
|
||||
* class) in its most significant byte, followed by the target_info fields. Depending on
|
||||
* target_type, 1, 2 or even 3 least significant bytes of this field are unused. target_info
|
||||
* fields which reference bytecode offsets are set to 0 (these offsets are ignored in ClassReader,
|
||||
* and recomputed in MethodWriter).
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
|
||||
* 4.7.20</a>
|
||||
* @see <a
|
||||
* href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.1">JVMS
|
||||
* 4.7.20.1</a>
|
||||
*/
|
||||
private final int targetTypeAndInfo;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* method in a method reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
|
||||
|
||||
/**
|
||||
* The type reference value in Java class file format.
|
||||
*/
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* Creates a new TypeReference.
|
||||
*
|
||||
* @param typeRef
|
||||
* the int encoded value of the type reference, as received in a
|
||||
* visit method related to type annotations, like
|
||||
* visitTypeAnnotation.
|
||||
*/
|
||||
public TypeReference(int typeRef) {
|
||||
this.value = typeRef;
|
||||
* Constructs a new TypeReference.
|
||||
*
|
||||
* @param typeRef the int encoded value of the type reference, as received in a visit method
|
||||
* related to type annotations, such as {@link ClassVisitor#visitTypeAnnotation}.
|
||||
*/
|
||||
public TypeReference(final int typeRef) {
|
||||
this.targetTypeAndInfo = typeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a type reference of the given sort.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
||||
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
||||
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
||||
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
||||
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
||||
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
|
||||
* {@link #METHOD_REFERENCE METHOD_REFERENCE}.
|
||||
* @return a type reference of the given sort.
|
||||
*/
|
||||
public static TypeReference newTypeReference(int sort) {
|
||||
* Returns a type reference of the given sort.
|
||||
*
|
||||
* @param sort one of {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
|
||||
* #LOCAL_VARIABLE}, {@link #RESOURCE_VARIABLE}, {@link #INSTANCEOF}, {@link #NEW}, {@link
|
||||
* #CONSTRUCTOR_REFERENCE}, or {@link #METHOD_REFERENCE}.
|
||||
* @return a type reference of the given sort.
|
||||
*/
|
||||
public static TypeReference newTypeReference(final int sort) {
|
||||
return new TypeReference(sort << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a type parameter of a generic class or method.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex
|
||||
* the type parameter index.
|
||||
* @return a reference to the given generic class or method type parameter.
|
||||
*/
|
||||
public static TypeReference newTypeParameterReference(int sort,
|
||||
int paramIndex) {
|
||||
* Returns a reference to a type parameter of a generic class or method.
|
||||
*
|
||||
* @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex the type parameter index.
|
||||
* @return a reference to the given generic class or method type parameter.
|
||||
*/
|
||||
public static TypeReference newTypeParameterReference(final int sort, final int paramIndex) {
|
||||
return new TypeReference((sort << 24) | (paramIndex << 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a type parameter bound of a generic class or
|
||||
* method.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex
|
||||
* the type parameter index.
|
||||
* @param boundIndex
|
||||
* the type bound index within the above type parameters.
|
||||
* @return a reference to the given generic class or method type parameter
|
||||
* bound.
|
||||
*/
|
||||
public static TypeReference newTypeParameterBoundReference(int sort,
|
||||
int paramIndex, int boundIndex) {
|
||||
return new TypeReference((sort << 24) | (paramIndex << 16)
|
||||
| (boundIndex << 8));
|
||||
* Returns a reference to a type parameter bound of a generic class or method.
|
||||
*
|
||||
* @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex the type parameter index.
|
||||
* @param boundIndex the type bound index within the above type parameters.
|
||||
* @return a reference to the given generic class or method type parameter bound.
|
||||
*/
|
||||
public static TypeReference newTypeParameterBoundReference(
|
||||
final int sort, final int paramIndex, final int boundIndex) {
|
||||
return new TypeReference((sort << 24) | (paramIndex << 16) | (boundIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the super class or to an interface of the
|
||||
* 'implements' clause of a class.
|
||||
*
|
||||
* @param itfIndex
|
||||
* the index of an interface in the 'implements' clause of a
|
||||
* class, or -1 to reference the super class of the class.
|
||||
* @return a reference to the given super type of a class.
|
||||
*/
|
||||
public static TypeReference newSuperTypeReference(int itfIndex) {
|
||||
itfIndex &= 0xFFFF;
|
||||
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
|
||||
* Returns a reference to the super class or to an interface of the 'implements' clause of a
|
||||
* class.
|
||||
*
|
||||
* @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to
|
||||
* reference the super class of the class.
|
||||
* @return a reference to the given super type of a class.
|
||||
*/
|
||||
public static TypeReference newSuperTypeReference(final int itfIndex) {
|
||||
return new TypeReference((CLASS_EXTENDS << 24) | ((itfIndex & 0xFFFF) << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of a formal parameter of a method.
|
||||
*
|
||||
* @param paramIndex
|
||||
* the formal parameter index.
|
||||
*
|
||||
* @return a reference to the type of the given method formal parameter.
|
||||
*/
|
||||
public static TypeReference newFormalParameterReference(int paramIndex) {
|
||||
return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
|
||||
| (paramIndex << 16));
|
||||
* Returns a reference to the type of a formal parameter of a method.
|
||||
*
|
||||
* @param paramIndex the formal parameter index.
|
||||
* @return a reference to the type of the given method formal parameter.
|
||||
*/
|
||||
public static TypeReference newFormalParameterReference(final int paramIndex) {
|
||||
return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of an exception, in a 'throws' clause of
|
||||
* a method.
|
||||
*
|
||||
* @param exceptionIndex
|
||||
* the index of an exception in a 'throws' clause of a method.
|
||||
*
|
||||
* @return a reference to the type of the given exception.
|
||||
*/
|
||||
public static TypeReference newExceptionReference(int exceptionIndex) {
|
||||
* Returns a reference to the type of an exception, in a 'throws' clause of a method.
|
||||
*
|
||||
* @param exceptionIndex the index of an exception in a 'throws' clause of a method.
|
||||
* @return a reference to the type of the given exception.
|
||||
*/
|
||||
public static TypeReference newExceptionReference(final int exceptionIndex) {
|
||||
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of the exception declared in a 'catch'
|
||||
* clause of a method.
|
||||
*
|
||||
* @param tryCatchBlockIndex
|
||||
* the index of a try catch block (using the order in which they
|
||||
* are visited with visitTryCatchBlock).
|
||||
*
|
||||
* @return a reference to the type of the given exception.
|
||||
*/
|
||||
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
|
||||
return new TypeReference((EXCEPTION_PARAMETER << 24)
|
||||
| (tryCatchBlockIndex << 8));
|
||||
* Returns a reference to the type of the exception declared in a 'catch' clause of a method.
|
||||
*
|
||||
* @param tryCatchBlockIndex the index of a try catch block (using the order in which they are
|
||||
* visited with visitTryCatchBlock).
|
||||
* @return a reference to the type of the given exception.
|
||||
*/
|
||||
public static TypeReference newTryCatchReference(final int tryCatchBlockIndex) {
|
||||
return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of a type argument in a constructor or
|
||||
* method call or reference.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #CAST CAST},
|
||||
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
||||
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
|
||||
* METHOD_INVOCATION_TYPE_ARGUMENT},
|
||||
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
||||
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
|
||||
* METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
* @param argIndex
|
||||
* the type argument index.
|
||||
*
|
||||
* @return a reference to the type of the given type argument.
|
||||
*/
|
||||
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
|
||||
* Returns a reference to the type of a type argument in a constructor or method call or
|
||||
* reference.
|
||||
*
|
||||
* @param sort one of {@link #CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
|
||||
* #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
|
||||
* #METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
* @param argIndex the type argument index.
|
||||
* @return a reference to the type of the given type argument.
|
||||
*/
|
||||
public static TypeReference newTypeArgumentReference(final int sort, final int argIndex) {
|
||||
return new TypeReference((sort << 24) | argIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sort of this type reference.
|
||||
*
|
||||
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
||||
* {@link #CLASS_EXTENDS CLASS_EXTENDS},
|
||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
|
||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
|
||||
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
||||
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
||||
* {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
|
||||
* {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
||||
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
||||
* {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
|
||||
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
||||
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
|
||||
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
|
||||
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
||||
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
|
||||
* METHOD_INVOCATION_TYPE_ARGUMENT},
|
||||
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
||||
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
|
||||
* METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
*/
|
||||
* Returns the sort of this type reference.
|
||||
*
|
||||
* @return one of {@link #CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER}, {@link
|
||||
* #CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND}, {@link #METHOD_TYPE_PARAMETER_BOUND},
|
||||
* {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
|
||||
* #METHOD_FORMAL_PARAMETER}, {@link #THROWS}, {@link #LOCAL_VARIABLE}, {@link
|
||||
* #RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER}, {@link #INSTANCEOF}, {@link #NEW},
|
||||
* {@link #CONSTRUCTOR_REFERENCE}, {@link #METHOD_REFERENCE}, {@link #CAST}, {@link
|
||||
* #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
|
||||
* #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
*/
|
||||
public int getSort() {
|
||||
return value >>> 24;
|
||||
return targetTypeAndInfo >>> 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the type parameter referenced by this type
|
||||
* reference. This method must only be used for type references whose sort
|
||||
* is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
* Returns the index of the type parameter referenced by this type reference. This method must
|
||||
* only be used for type references whose sort is {@link #CLASS_TYPE_PARAMETER}, {@link
|
||||
* #METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
|
||||
* #METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
public int getTypeParameterIndex() {
|
||||
return (value & 0x00FF0000) >> 16;
|
||||
return (targetTypeAndInfo & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the type parameter bound, within the type parameter
|
||||
* {@link #getTypeParameterIndex}, referenced by this type reference. This
|
||||
* method must only be used for type references whose sort is
|
||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter bound index.
|
||||
*/
|
||||
* Returns the index of the type parameter bound, within the type parameter {@link
|
||||
* #getTypeParameterIndex}, referenced by this type reference. This method must only be used for
|
||||
* type references whose sort is {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
|
||||
* #METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter bound index.
|
||||
*/
|
||||
public int getTypeParameterBoundIndex() {
|
||||
return (value & 0x0000FF00) >> 8;
|
||||
return (targetTypeAndInfo & 0x0000FF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the "super type" of a class that is referenced by
|
||||
* this type reference. This method must only be used for type references
|
||||
* whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
|
||||
*
|
||||
* @return the index of an interface in the 'implements' clause of a class,
|
||||
* or -1 if this type reference references the type of the super
|
||||
* class.
|
||||
*/
|
||||
* Returns the index of the "super type" of a class that is referenced by this type reference.
|
||||
* This method must only be used for type references whose sort is {@link #CLASS_EXTENDS}.
|
||||
*
|
||||
* @return the index of an interface in the 'implements' clause of a class, or -1 if this type
|
||||
* reference references the type of the super class.
|
||||
*/
|
||||
public int getSuperTypeIndex() {
|
||||
return (short) ((value & 0x00FFFF00) >> 8);
|
||||
return (short) ((targetTypeAndInfo & 0x00FFFF00) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the formal parameter whose type is referenced by
|
||||
* this type reference. This method must only be used for type references
|
||||
* whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
|
||||
*
|
||||
* @return a formal parameter index.
|
||||
*/
|
||||
* Returns the index of the formal parameter whose type is referenced by this type reference. This
|
||||
* method must only be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER}.
|
||||
*
|
||||
* @return a formal parameter index.
|
||||
*/
|
||||
public int getFormalParameterIndex() {
|
||||
return (value & 0x00FF0000) >> 16;
|
||||
return (targetTypeAndInfo & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the exception, in a 'throws' clause of a method,
|
||||
* whose type is referenced by this type reference. This method must only be
|
||||
* used for type references whose sort is {@link #THROWS THROWS}.
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
* Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced
|
||||
* by this type reference. This method must only be used for type references whose sort is {@link
|
||||
* #THROWS}.
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
public int getExceptionIndex() {
|
||||
return (value & 0x00FFFF00) >> 8;
|
||||
return (targetTypeAndInfo & 0x00FFFF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the try catch block (using the order in which they
|
||||
* are visited with visitTryCatchBlock), whose 'catch' type is referenced by
|
||||
* this type reference. This method must only be used for type references
|
||||
* whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
* Returns the index of the try catch block (using the order in which they are visited with
|
||||
* visitTryCatchBlock), whose 'catch' type is referenced by this type reference. This method must
|
||||
* only be used for type references whose sort is {@link #EXCEPTION_PARAMETER} .
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
public int getTryCatchBlockIndex() {
|
||||
return (value & 0x00FFFF00) >> 8;
|
||||
return (targetTypeAndInfo & 0x00FFFF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the type argument referenced by this type reference.
|
||||
* This method must only be used for type references whose sort is
|
||||
* {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
||||
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
|
||||
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
||||
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
* Returns the index of the type argument referenced by this type reference. This method must only
|
||||
* be used for type references whose sort is {@link #CAST}, {@link
|
||||
* #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
|
||||
* #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
public int getTypeArgumentIndex() {
|
||||
return value & 0xFF;
|
||||
return targetTypeAndInfo & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the int encoded value of this type reference, suitable for use in
|
||||
* visit methods related to type annotations, like visitTypeAnnotation.
|
||||
*
|
||||
* @return the int encoded value of this type reference.
|
||||
*/
|
||||
* Returns the int encoded value of this type reference, suitable for use in visit methods related
|
||||
* to type annotations, like visitTypeAnnotation.
|
||||
*
|
||||
* @return the int encoded value of this type reference.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
return targetTypeAndInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given target_type and target_info JVMS structures into the given ByteVector.
|
||||
*
|
||||
* @param targetTypeAndInfo a target_type and a target_info structures encoded as in {@link
|
||||
* #targetTypeAndInfo}. LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
|
||||
* @param output where the type reference must be put.
|
||||
*/
|
||||
static void putTarget(final int targetTypeAndInfo, final ByteVector output) {
|
||||
switch (targetTypeAndInfo >>> 24) {
|
||||
case CLASS_TYPE_PARAMETER:
|
||||
case METHOD_TYPE_PARAMETER:
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
output.putShort(targetTypeAndInfo >>> 16);
|
||||
break;
|
||||
case FIELD:
|
||||
case METHOD_RETURN:
|
||||
case METHOD_RECEIVER:
|
||||
output.putByte(targetTypeAndInfo >>> 24);
|
||||
break;
|
||||
case CAST:
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
output.putInt(targetTypeAndInfo);
|
||||
break;
|
||||
case CLASS_EXTENDS:
|
||||
case CLASS_TYPE_PARAMETER_BOUND:
|
||||
case METHOD_TYPE_PARAMETER_BOUND:
|
||||
case THROWS:
|
||||
case EXCEPTION_PARAMETER:
|
||||
case INSTANCEOF:
|
||||
case NEW:
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
output.put12(targetTypeAndInfo >>> 24, (targetTypeAndInfo & 0xFFFF00) >> 8);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -56,53 +56,78 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* An {@link AnnotationVisitor} adapter for type remapping.
|
||||
* An {@link AnnotationVisitor} that remaps types with a {@link Remapper}.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class AnnotationRemapper extends AnnotationVisitor {
|
||||
|
||||
/** The remapper used to remap the types in the visited annotation. */
|
||||
protected final Remapper remapper;
|
||||
|
||||
public AnnotationRemapper(final AnnotationVisitor av,
|
||||
final Remapper remapper) {
|
||||
this(Opcodes.ASM6, av, remapper);
|
||||
/**
|
||||
* Constructs a new {@link AnnotationRemapper}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #AnnotationRemapper(int,AnnotationVisitor,Remapper)} version.
|
||||
*
|
||||
* @param annotationVisitor the annotation visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited annotation.
|
||||
*/
|
||||
public AnnotationRemapper(final AnnotationVisitor annotationVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM7, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
protected AnnotationRemapper(final int api, final AnnotationVisitor av,
|
||||
final Remapper remapper) {
|
||||
super(api, av);
|
||||
/**
|
||||
* Constructs a new {@link AnnotationRemapper}.
|
||||
*
|
||||
* @param api the ASM API version supported by this remapper. Must be one of {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5} or {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM6}.
|
||||
* @param annotationVisitor the annotation visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited annotation.
|
||||
*/
|
||||
protected AnnotationRemapper(
|
||||
final int api, final AnnotationVisitor annotationVisitor, final Remapper remapper) {
|
||||
super(api, annotationVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(String name, Object value) {
|
||||
av.visit(name, remapper.mapValue(value));
|
||||
public void visit(final String name, final Object value) {
|
||||
super.visit(name, remapper.mapValue(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(String name, String desc, String value) {
|
||||
av.visitEnum(name, remapper.mapDesc(desc), value);
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
super.visitEnum(name, remapper.mapDesc(descriptor), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc) {
|
||||
AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
|
||||
return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
|
||||
remapper));
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
AnnotationVisitor annotationVisitor = super.visitAnnotation(name, remapper.mapDesc(descriptor));
|
||||
if (annotationVisitor == null) {
|
||||
return null;
|
||||
} else {
|
||||
return annotationVisitor == av
|
||||
? this
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
AnnotationVisitor v = av.visitArray(name);
|
||||
return v == null ? null : (v == av ? this : new AnnotationRemapper(v,
|
||||
remapper));
|
||||
public AnnotationVisitor visitArray(final String name) {
|
||||
AnnotationVisitor annotationVisitor = super.visitArray(name);
|
||||
if (annotationVisitor == null) {
|
||||
return null;
|
||||
} else {
|
||||
return annotationVisitor == av
|
||||
? this
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,11 +56,9 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Attribute;
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
|
|
@ -71,117 +69,198 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
import jdk.internal.org.objectweb.asm.TypePath;
|
||||
|
||||
/**
|
||||
* A {@link ClassVisitor} for type remapping.
|
||||
* A {@link ClassVisitor} that remaps types with a {@link Remapper}.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class ClassRemapper extends ClassVisitor {
|
||||
|
||||
/** The remapper used to remap the types in the visited class. */
|
||||
protected final Remapper remapper;
|
||||
|
||||
/** The internal name of the visited class. */
|
||||
protected String className;
|
||||
|
||||
public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, cv, remapper);
|
||||
/**
|
||||
* Constructs a new {@link ClassRemapper}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #ClassRemapper(int,ClassVisitor,Remapper)} version.
|
||||
*
|
||||
* @param classVisitor the class visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited class.
|
||||
*/
|
||||
public ClassRemapper(final ClassVisitor classVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM7, classVisitor, remapper);
|
||||
}
|
||||
|
||||
protected ClassRemapper(final int api, final ClassVisitor cv,
|
||||
final Remapper remapper) {
|
||||
super(api, cv);
|
||||
/**
|
||||
* Constructs a new {@link ClassRemapper}.
|
||||
*
|
||||
* @param api the ASM API version supported by this remapper. Must be one of {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5}, {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM6} or {@link jdk.internal.org.objectweb.asm.Opcodes#ASM7}.
|
||||
* @param classVisitor the class visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited class.
|
||||
*/
|
||||
protected ClassRemapper(final int api, final ClassVisitor classVisitor, final Remapper remapper) {
|
||||
super(api, classVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature,
|
||||
String superName, String[] interfaces) {
|
||||
public void visit(
|
||||
final int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces) {
|
||||
this.className = name;
|
||||
super.visit(version, access, remapper.mapType(name), remapper
|
||||
.mapSignature(signature, false), remapper.mapType(superName),
|
||||
super.visit(
|
||||
version,
|
||||
access,
|
||||
remapper.mapType(name),
|
||||
remapper.mapSignature(signature, false),
|
||||
remapper.mapType(superName),
|
||||
interfaces == null ? null : remapper.mapTypes(interfaces));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleVisitor visitModule(String name, int flags, String version) {
|
||||
ModuleVisitor mv = super.visitModule(remapper.mapModuleName(name), flags, version);
|
||||
return mv == null ? null : createModuleRemapper(mv);
|
||||
public ModuleVisitor visitModule(final String name, final int flags, final String version) {
|
||||
ModuleVisitor moduleVisitor = super.visitModule(remapper.mapModuleName(name), flags, version);
|
||||
return moduleVisitor == null ? null : createModuleRemapper(moduleVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
|
||||
visible);
|
||||
return av == null ? null : createAnnotationRemapper(av);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitAnnotation(remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? null : createAnnotationRemapper(av);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null ? null : createAnnotationRemapper(annotationVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(Attribute attr) {
|
||||
if (attr instanceof ModuleHashesAttribute) {
|
||||
ModuleHashesAttribute hashesAttr = new ModuleHashesAttribute();
|
||||
List<String> modules = hashesAttr.modules;
|
||||
for(int i = 0; i < modules.size(); i++) {
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (attribute instanceof ModuleHashesAttribute) {
|
||||
ModuleHashesAttribute moduleHashesAttribute = (ModuleHashesAttribute) attribute;
|
||||
List<String> modules = moduleHashesAttribute.modules;
|
||||
for (int i = 0; i < modules.size(); ++i) {
|
||||
modules.set(i, remapper.mapModuleName(modules.get(i)));
|
||||
}
|
||||
}
|
||||
super.visitAttribute(attr);
|
||||
super.visitAttribute(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc,
|
||||
String signature, Object value) {
|
||||
FieldVisitor fv = super.visitField(access,
|
||||
remapper.mapFieldName(className, name, desc),
|
||||
remapper.mapDesc(desc), remapper.mapSignature(signature, true),
|
||||
remapper.mapValue(value));
|
||||
return fv == null ? null : createFieldRemapper(fv);
|
||||
public FieldVisitor visitField(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
FieldVisitor fieldVisitor =
|
||||
super.visitField(
|
||||
access,
|
||||
remapper.mapFieldName(className, name, descriptor),
|
||||
remapper.mapDesc(descriptor),
|
||||
remapper.mapSignature(signature, true),
|
||||
(value == null) ? null : remapper.mapValue(value));
|
||||
return fieldVisitor == null ? null : createFieldRemapper(fieldVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions) {
|
||||
String newDesc = remapper.mapMethodDesc(desc);
|
||||
MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
|
||||
className, name, desc), newDesc, remapper.mapSignature(
|
||||
signature, false),
|
||||
exceptions == null ? null : remapper.mapTypes(exceptions));
|
||||
return mv == null ? null : createMethodRemapper(mv);
|
||||
public MethodVisitor visitMethod(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
String remappedDescriptor = remapper.mapMethodDesc(descriptor);
|
||||
MethodVisitor methodVisitor =
|
||||
super.visitMethod(
|
||||
access,
|
||||
remapper.mapMethodName(className, name, descriptor),
|
||||
remappedDescriptor,
|
||||
remapper.mapSignature(signature, false),
|
||||
exceptions == null ? null : remapper.mapTypes(exceptions));
|
||||
return methodVisitor == null ? null : createMethodRemapper(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName,
|
||||
String innerName, int access) {
|
||||
// TODO should innerName be changed?
|
||||
super.visitInnerClass(remapper.mapType(name), outerName == null ? null
|
||||
: remapper.mapType(outerName), innerName, access);
|
||||
public void visitInnerClass(
|
||||
final String name, final String outerName, final String innerName, final int access) {
|
||||
super.visitInnerClass(
|
||||
remapper.mapType(name),
|
||||
outerName == null ? null : remapper.mapType(outerName),
|
||||
innerName == null ? null : remapper.mapInnerClassName(name, outerName, innerName),
|
||||
access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(String owner, String name, String desc) {
|
||||
super.visitOuterClass(remapper.mapType(owner), name == null ? null
|
||||
: remapper.mapMethodName(owner, name, desc),
|
||||
desc == null ? null : remapper.mapMethodDesc(desc));
|
||||
public void visitOuterClass(final String owner, final String name, final String descriptor) {
|
||||
super.visitOuterClass(
|
||||
remapper.mapType(owner),
|
||||
name == null ? null : remapper.mapMethodName(owner, name, descriptor),
|
||||
descriptor == null ? null : remapper.mapMethodDesc(descriptor));
|
||||
}
|
||||
|
||||
protected FieldVisitor createFieldRemapper(FieldVisitor fv) {
|
||||
return new FieldRemapper(fv, remapper);
|
||||
@Override
|
||||
public void visitNestHost(final String nestHost) {
|
||||
super.visitNestHost(remapper.mapType(nestHost));
|
||||
}
|
||||
|
||||
protected MethodVisitor createMethodRemapper(MethodVisitor mv) {
|
||||
return new MethodRemapper(mv, remapper);
|
||||
@Override
|
||||
public void visitNestMember(final String nestMember) {
|
||||
super.visitNestMember(remapper.mapType(nestMember));
|
||||
}
|
||||
|
||||
protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
|
||||
return new AnnotationRemapper(av, remapper);
|
||||
/**
|
||||
* Constructs a new remapper for fields. The default implementation of this method returns a new
|
||||
* {@link FieldRemapper}.
|
||||
*
|
||||
* @param fieldVisitor the FieldVisitor the remapper must delegate to.
|
||||
* @return the newly created remapper.
|
||||
*/
|
||||
protected FieldVisitor createFieldRemapper(final FieldVisitor fieldVisitor) {
|
||||
return new FieldRemapper(api, fieldVisitor, remapper);
|
||||
}
|
||||
|
||||
protected ModuleVisitor createModuleRemapper(ModuleVisitor mv) {
|
||||
return new ModuleRemapper(mv, remapper);
|
||||
/**
|
||||
* Constructs a new remapper for methods. The default implementation of this method returns a new
|
||||
* {@link MethodRemapper}.
|
||||
*
|
||||
* @param methodVisitor the MethodVisitor the remapper must delegate to.
|
||||
* @return the newly created remapper.
|
||||
*/
|
||||
protected MethodVisitor createMethodRemapper(final MethodVisitor methodVisitor) {
|
||||
return new MethodRemapper(api, methodVisitor, remapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new remapper for annotations. The default implementation of this method returns a
|
||||
* new {@link AnnotationRemapper}.
|
||||
*
|
||||
* @param annotationVisitor the AnnotationVisitor the remapper must delegate to.
|
||||
* @return the newly created remapper.
|
||||
*/
|
||||
protected AnnotationVisitor createAnnotationRemapper(final AnnotationVisitor annotationVisitor) {
|
||||
return new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new remapper for modules. The default implementation of this method returns a new
|
||||
* {@link ModuleRemapper}.
|
||||
*
|
||||
* @param moduleVisitor the ModuleVisitor the remapper must delegate to.
|
||||
* @return the newly created remapper.
|
||||
*/
|
||||
protected ModuleVisitor createModuleRemapper(final ModuleVisitor moduleVisitor) {
|
||||
return new ModuleRemapper(api, moduleVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,28 +58,31 @@
|
|||
*/
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ConstantDynamic;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A {@link MethodVisitor} that can be used to approximate method size.
|
||||
* A {@link MethodVisitor} that approximates the size of the methods it visits.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
||||
|
||||
/** The minimum size in bytes of the visited method. */
|
||||
private int minSize;
|
||||
|
||||
/** The maximum size in bytes of the visited method. */
|
||||
private int maxSize;
|
||||
|
||||
public CodeSizeEvaluator(final MethodVisitor mv) {
|
||||
this(Opcodes.ASM6, mv);
|
||||
public CodeSizeEvaluator(final MethodVisitor methodVisitor) {
|
||||
this(Opcodes.ASM7, methodVisitor);
|
||||
}
|
||||
|
||||
protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
|
||||
super(api, mv);
|
||||
protected CodeSizeEvaluator(final int api, final MethodVisitor methodVisitor) {
|
||||
super(api, methodVisitor);
|
||||
}
|
||||
|
||||
public int getMinSize() {
|
||||
|
|
@ -94,9 +97,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
|||
public void visitInsn(final int opcode) {
|
||||
minSize += 1;
|
||||
maxSize += 1;
|
||||
if (mv != null) {
|
||||
mv.visitInsn(opcode);
|
||||
}
|
||||
super.visitInsn(opcode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -108,9 +109,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
|||
minSize += 2;
|
||||
maxSize += 2;
|
||||
}
|
||||
if (mv != null) {
|
||||
mv.visitIntInsn(opcode, operand);
|
||||
}
|
||||
super.visitIntInsn(opcode, operand);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -125,54 +124,60 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
|||
minSize += 2;
|
||||
maxSize += 2;
|
||||
}
|
||||
if (mv != null) {
|
||||
mv.visitVarInsn(opcode, var);
|
||||
}
|
||||
super.visitVarInsn(opcode, var);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(final int opcode, final String type) {
|
||||
minSize += 3;
|
||||
maxSize += 3;
|
||||
if (mv != null) {
|
||||
mv.visitTypeInsn(opcode, type);
|
||||
}
|
||||
super.visitTypeInsn(opcode, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
public void visitFieldInsn(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
minSize += 3;
|
||||
maxSize += 3;
|
||||
if (mv != null) {
|
||||
mv.visitFieldInsn(opcode, owner, name, desc);
|
||||
}
|
||||
super.visitFieldInsn(opcode, owner, name, descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
public void visitMethodInsn(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
if (api >= Opcodes.ASM5) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor);
|
||||
return;
|
||||
}
|
||||
doVisitMethodInsn(opcode, owner, name, desc,
|
||||
opcode == Opcodes.INVOKEINTERFACE);
|
||||
doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc, final boolean itf) {
|
||||
public void visitMethodInsn(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
if (api < Opcodes.ASM5) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
return;
|
||||
}
|
||||
doVisitMethodInsn(opcode, owner, name, desc, itf);
|
||||
doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
}
|
||||
|
||||
private void doVisitMethodInsn(int opcode, final String owner,
|
||||
final String name, final String desc, final boolean itf) {
|
||||
private void doVisitMethodInsn(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
if (opcode == INVOKEINTERFACE) {
|
||||
minSize += 5;
|
||||
maxSize += 5;
|
||||
|
|
@ -181,18 +186,19 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
|||
maxSize += 3;
|
||||
}
|
||||
if (mv != null) {
|
||||
mv.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
|
||||
Object... bsmArgs) {
|
||||
public void visitInvokeDynamicInsn(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final Handle bootstrapMethodHandle,
|
||||
final Object... bootstrapMethodArguments) {
|
||||
minSize += 5;
|
||||
maxSize += 5;
|
||||
if (mv != null) {
|
||||
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
|
||||
}
|
||||
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -203,23 +209,21 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
|||
} else {
|
||||
maxSize += 8;
|
||||
}
|
||||
if (mv != null) {
|
||||
mv.visitJumpInsn(opcode, label);
|
||||
}
|
||||
super.visitJumpInsn(opcode, label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(final Object cst) {
|
||||
if (cst instanceof Long || cst instanceof Double) {
|
||||
public void visitLdcInsn(final Object value) {
|
||||
if (value instanceof Long
|
||||
|| value instanceof Double
|
||||
|| (value instanceof ConstantDynamic && ((ConstantDynamic) value).getSize() == 2)) {
|
||||
minSize += 3;
|
||||
maxSize += 3;
|
||||
} else {
|
||||
minSize += 2;
|
||||
maxSize += 3;
|
||||
}
|
||||
if (mv != null) {
|
||||
mv.visitLdcInsn(cst);
|
||||
}
|
||||
super.visitLdcInsn(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -231,37 +235,28 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
|
|||
minSize += 3;
|
||||
maxSize += 3;
|
||||
}
|
||||
if (mv != null) {
|
||||
mv.visitIincInsn(var, increment);
|
||||
}
|
||||
super.visitIincInsn(var, increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTableSwitchInsn(final int min, final int max,
|
||||
final Label dflt, final Label... labels) {
|
||||
public void visitTableSwitchInsn(
|
||||
final int min, final int max, final Label dflt, final Label... labels) {
|
||||
minSize += 13 + labels.length * 4;
|
||||
maxSize += 16 + labels.length * 4;
|
||||
if (mv != null) {
|
||||
mv.visitTableSwitchInsn(min, max, dflt, labels);
|
||||
}
|
||||
super.visitTableSwitchInsn(min, max, dflt, labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
|
||||
final Label[] labels) {
|
||||
public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
|
||||
minSize += 9 + keys.length * 8;
|
||||
maxSize += 12 + keys.length * 8;
|
||||
if (mv != null) {
|
||||
mv.visitLookupSwitchInsn(dflt, keys, labels);
|
||||
}
|
||||
super.visitLookupSwitchInsn(dflt, keys, labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMultiANewArrayInsn(final String desc, final int dims) {
|
||||
public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
|
||||
minSize += 4;
|
||||
maxSize += 4;
|
||||
if (mv != null) {
|
||||
mv.visitMultiANewArrayInsn(desc, dims);
|
||||
}
|
||||
super.visitMultiANewArrayInsn(descriptor, numDimensions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
|
|
@ -65,36 +64,56 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
import jdk.internal.org.objectweb.asm.TypePath;
|
||||
|
||||
/**
|
||||
* A {@link FieldVisitor} adapter for type remapping.
|
||||
* A {@link FieldVisitor} that remaps types with a {@link Remapper}.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class FieldRemapper extends FieldVisitor {
|
||||
|
||||
private final Remapper remapper;
|
||||
/** The remapper used to remap the types in the visited field. */
|
||||
protected final Remapper remapper;
|
||||
|
||||
public FieldRemapper(final FieldVisitor fv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, fv, remapper);
|
||||
/**
|
||||
* Constructs a new {@link FieldRemapper}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #FieldRemapper(int,FieldVisitor,Remapper)} version.
|
||||
*
|
||||
* @param fieldVisitor the field visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited field.
|
||||
*/
|
||||
public FieldRemapper(final FieldVisitor fieldVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM7, fieldVisitor, remapper);
|
||||
}
|
||||
|
||||
protected FieldRemapper(final int api, final FieldVisitor fv,
|
||||
final Remapper remapper) {
|
||||
super(api, fv);
|
||||
/**
|
||||
* Constructs a new {@link FieldRemapper}.
|
||||
*
|
||||
* @param api the ASM API version supported by this remapper. Must be one of {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5} or {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM6}.
|
||||
* @param fieldVisitor the field visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited field.
|
||||
*/
|
||||
protected FieldRemapper(final int api, final FieldVisitor fieldVisitor, final Remapper remapper) {
|
||||
super(api, fieldVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
|
||||
visible);
|
||||
return av == null ? null : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitAnnotation(remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? null
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? null : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? null
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -66,12 +66,11 @@ import jdk.internal.org.objectweb.asm.Type;
|
|||
import jdk.internal.org.objectweb.asm.TypePath;
|
||||
|
||||
/**
|
||||
* A {@link MethodVisitor} that renumbers local variables in their order of
|
||||
* appearance. This adapter allows one to easily add new local variables to a
|
||||
* method. It may be used by inheriting from this class, but the preferred way
|
||||
* of using it is via delegation: the next visitor in the chain can indeed add
|
||||
* new locals when needed by calling {@link #newLocal} on this adapter (this
|
||||
* requires a reference back to this {@link LocalVariablesSorter}).
|
||||
* A {@link MethodVisitor} that renumbers local variables in their order of appearance. This adapter
|
||||
* allows one to easily add new local variables to a method. It may be used by inheriting from this
|
||||
* class, but the preferred way of using it is via delegation: the next visitor in the chain can
|
||||
* indeed add new locals when needed by calling {@link #newLocal} on this adapter (this requires a
|
||||
* reference back to this {@link LocalVariablesSorter}).
|
||||
*
|
||||
* @author Chris Nokleberg
|
||||
* @author Eugene Kuleshov
|
||||
|
|
@ -79,291 +78,278 @@ import jdk.internal.org.objectweb.asm.TypePath;
|
|||
*/
|
||||
public class LocalVariablesSorter extends MethodVisitor {
|
||||
|
||||
private static final Type OBJECT_TYPE = Type
|
||||
.getObjectType("java/lang/Object");
|
||||
/** The type of the java.lang.Object class. */
|
||||
private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
|
||||
|
||||
/**
|
||||
* Mapping from old to new local variable indexes. A local variable at index
|
||||
* i of size 1 is remapped to 'mapping[2*i]', while a local variable at
|
||||
* index i of size 2 is remapped to 'mapping[2*i+1]'.
|
||||
*/
|
||||
private int[] mapping = new int[40];
|
||||
* The mapping from old to new local variable indices. A local variable at index i of size 1 is
|
||||
* remapped to 'mapping[2*i]', while a local variable at index i of size 2 is remapped to
|
||||
* 'mapping[2*i+1]'.
|
||||
*/
|
||||
private int[] remappedVariableIndices = new int[40];
|
||||
|
||||
/**
|
||||
* Array used to store stack map local variable types after remapping.
|
||||
*/
|
||||
private Object[] newLocals = new Object[20];
|
||||
* The local variable types after remapping. The format of this array is the same as in {@link
|
||||
* MethodVisitor#visitFrame}, except that long and double types use two slots.
|
||||
*/
|
||||
private Object[] remappedLocalTypes = new Object[20];
|
||||
|
||||
/**
|
||||
* Index of the first local variable, after formal parameters.
|
||||
*/
|
||||
/** The index of the first local variable, after formal parameters. */
|
||||
protected final int firstLocal;
|
||||
|
||||
/**
|
||||
* Index of the next local variable to be created by {@link #newLocal}.
|
||||
*/
|
||||
/** The index of the next local variable to be created by {@link #newLocal}. */
|
||||
protected int nextLocal;
|
||||
|
||||
/**
|
||||
* Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
|
||||
* this constructor</i>. Instead, they must use the
|
||||
* {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
|
||||
*
|
||||
* @param access
|
||||
* access flags of the adapted method.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link Type Type}).
|
||||
* @param mv
|
||||
* the method visitor to which this adapter delegates calls.
|
||||
* @throws IllegalStateException
|
||||
* If a subclass calls this constructor.
|
||||
*/
|
||||
public LocalVariablesSorter(final int access, final String desc,
|
||||
final MethodVisitor mv) {
|
||||
this(Opcodes.ASM6, access, desc, mv);
|
||||
* Constructs a new {@link LocalVariablesSorter}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #LocalVariablesSorter(int, int, String, MethodVisitor)}
|
||||
* version.
|
||||
*
|
||||
* @param access access flags of the adapted method.
|
||||
* @param descriptor the method's descriptor (see {@link Type}).
|
||||
* @param methodVisitor the method visitor to which this adapter delegates calls.
|
||||
* @throws IllegalStateException if a subclass calls this constructor.
|
||||
*/
|
||||
public LocalVariablesSorter(
|
||||
final int access, final String descriptor, final MethodVisitor methodVisitor) {
|
||||
this(Opcodes.ASM7, access, descriptor, methodVisitor);
|
||||
if (getClass() != LocalVariablesSorter.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link LocalVariablesSorter}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param access
|
||||
* access flags of the adapted method.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link Type Type}).
|
||||
* @param mv
|
||||
* the method visitor to which this adapter delegates calls.
|
||||
*/
|
||||
protected LocalVariablesSorter(final int api, final int access,
|
||||
final String desc, final MethodVisitor mv) {
|
||||
super(api, mv);
|
||||
Type[] args = Type.getArgumentTypes(desc);
|
||||
* Constructs a new {@link LocalVariablesSorter}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param access access flags of the adapted method.
|
||||
* @param descriptor the method's descriptor (see {@link Type}).
|
||||
* @param methodVisitor the method visitor to which this adapter delegates calls.
|
||||
*/
|
||||
protected LocalVariablesSorter(
|
||||
final int api, final int access, final String descriptor, final MethodVisitor methodVisitor) {
|
||||
super(api, methodVisitor);
|
||||
nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
nextLocal += args[i].getSize();
|
||||
for (Type argumentType : Type.getArgumentTypes(descriptor)) {
|
||||
nextLocal += argumentType.getSize();
|
||||
}
|
||||
firstLocal = nextLocal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVarInsn(final int opcode, final int var) {
|
||||
Type type;
|
||||
Type varType;
|
||||
switch (opcode) {
|
||||
case Opcodes.LLOAD:
|
||||
case Opcodes.LSTORE:
|
||||
type = Type.LONG_TYPE;
|
||||
break;
|
||||
|
||||
case Opcodes.DLOAD:
|
||||
case Opcodes.DSTORE:
|
||||
type = Type.DOUBLE_TYPE;
|
||||
break;
|
||||
|
||||
case Opcodes.FLOAD:
|
||||
case Opcodes.FSTORE:
|
||||
type = Type.FLOAT_TYPE;
|
||||
break;
|
||||
|
||||
case Opcodes.ILOAD:
|
||||
case Opcodes.ISTORE:
|
||||
type = Type.INT_TYPE;
|
||||
break;
|
||||
|
||||
default:
|
||||
// case Opcodes.ALOAD:
|
||||
// case Opcodes.ASTORE:
|
||||
// case RET:
|
||||
type = OBJECT_TYPE;
|
||||
break;
|
||||
case Opcodes.LLOAD:
|
||||
case Opcodes.LSTORE:
|
||||
varType = Type.LONG_TYPE;
|
||||
break;
|
||||
case Opcodes.DLOAD:
|
||||
case Opcodes.DSTORE:
|
||||
varType = Type.DOUBLE_TYPE;
|
||||
break;
|
||||
case Opcodes.FLOAD:
|
||||
case Opcodes.FSTORE:
|
||||
varType = Type.FLOAT_TYPE;
|
||||
break;
|
||||
case Opcodes.ILOAD:
|
||||
case Opcodes.ISTORE:
|
||||
varType = Type.INT_TYPE;
|
||||
break;
|
||||
case Opcodes.ALOAD:
|
||||
case Opcodes.ASTORE:
|
||||
case Opcodes.RET:
|
||||
varType = OBJECT_TYPE;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid opcode " + opcode);
|
||||
}
|
||||
mv.visitVarInsn(opcode, remap(var, type));
|
||||
super.visitVarInsn(opcode, remap(var, varType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIincInsn(final int var, final int increment) {
|
||||
mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
|
||||
super.visitIincInsn(remap(var, Type.INT_TYPE), increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMaxs(final int maxStack, final int maxLocals) {
|
||||
mv.visitMaxs(maxStack, nextLocal);
|
||||
super.visitMaxs(maxStack, nextLocal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(final String name, final String desc,
|
||||
final String signature, final Label start, final Label end,
|
||||
public void visitLocalVariable(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Label start,
|
||||
final Label end,
|
||||
final int index) {
|
||||
int newIndex = remap(index, Type.getType(desc));
|
||||
mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
|
||||
int remappedIndex = remap(index, Type.getType(descriptor));
|
||||
super.visitLocalVariable(name, descriptor, signature, start, end, remappedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
||||
TypePath typePath, Label[] start, Label[] end, int[] index,
|
||||
String desc, boolean visible) {
|
||||
Type t = Type.getType(desc);
|
||||
int[] newIndex = new int[index.length];
|
||||
for (int i = 0; i < newIndex.length; ++i) {
|
||||
newIndex[i] = remap(index[i], t);
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(
|
||||
final int typeRef,
|
||||
final TypePath typePath,
|
||||
final Label[] start,
|
||||
final Label[] end,
|
||||
final int[] index,
|
||||
final String descriptor,
|
||||
final boolean visible) {
|
||||
Type type = Type.getType(descriptor);
|
||||
int[] remappedIndex = new int[index.length];
|
||||
for (int i = 0; i < remappedIndex.length; ++i) {
|
||||
remappedIndex[i] = remap(index[i], type);
|
||||
}
|
||||
return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
|
||||
newIndex, desc, visible);
|
||||
return super.visitLocalVariableAnnotation(
|
||||
typeRef, typePath, start, end, remappedIndex, descriptor, visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFrame(final int type, final int nLocal,
|
||||
final Object[] local, final int nStack, final Object[] stack) {
|
||||
if (type != Opcodes.F_NEW) { // uncompressed frame
|
||||
throw new IllegalStateException(
|
||||
"ClassReader.accept() should be called with EXPAND_FRAMES flag");
|
||||
public void visitFrame(
|
||||
final int type,
|
||||
final int numLocal,
|
||||
final Object[] local,
|
||||
final int numStack,
|
||||
final Object[] stack) {
|
||||
if (type != Opcodes.F_NEW) { // Uncompressed frame.
|
||||
throw new IllegalArgumentException(
|
||||
"LocalVariablesSorter only accepts expanded frames (see ClassReader.EXPAND_FRAMES)");
|
||||
}
|
||||
|
||||
// creates a copy of newLocals
|
||||
Object[] oldLocals = new Object[newLocals.length];
|
||||
System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
|
||||
// Create a copy of remappedLocals.
|
||||
Object[] oldRemappedLocals = new Object[remappedLocalTypes.length];
|
||||
System.arraycopy(remappedLocalTypes, 0, oldRemappedLocals, 0, oldRemappedLocals.length);
|
||||
|
||||
updateNewLocals(newLocals);
|
||||
updateNewLocals(remappedLocalTypes);
|
||||
|
||||
// copies types from 'local' to 'newLocals'
|
||||
// 'newLocals' already contains the variables added with 'newLocal'
|
||||
|
||||
int index = 0; // old local variable index
|
||||
int number = 0; // old local variable number
|
||||
for (; number < nLocal; ++number) {
|
||||
Object t = local[number];
|
||||
int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
|
||||
if (t != Opcodes.TOP) {
|
||||
Type typ = OBJECT_TYPE;
|
||||
if (t == Opcodes.INTEGER) {
|
||||
typ = Type.INT_TYPE;
|
||||
} else if (t == Opcodes.FLOAT) {
|
||||
typ = Type.FLOAT_TYPE;
|
||||
} else if (t == Opcodes.LONG) {
|
||||
typ = Type.LONG_TYPE;
|
||||
} else if (t == Opcodes.DOUBLE) {
|
||||
typ = Type.DOUBLE_TYPE;
|
||||
} else if (t instanceof String) {
|
||||
typ = Type.getObjectType((String) t);
|
||||
// Copy the types from 'local' to 'remappedLocals'. 'remappedLocals' already contains the
|
||||
// variables added with 'newLocal'.
|
||||
int oldVar = 0; // Old local variable index.
|
||||
for (int i = 0; i < numLocal; ++i) {
|
||||
Object localType = local[i];
|
||||
if (localType != Opcodes.TOP) {
|
||||
Type varType = OBJECT_TYPE;
|
||||
if (localType == Opcodes.INTEGER) {
|
||||
varType = Type.INT_TYPE;
|
||||
} else if (localType == Opcodes.FLOAT) {
|
||||
varType = Type.FLOAT_TYPE;
|
||||
} else if (localType == Opcodes.LONG) {
|
||||
varType = Type.LONG_TYPE;
|
||||
} else if (localType == Opcodes.DOUBLE) {
|
||||
varType = Type.DOUBLE_TYPE;
|
||||
} else if (localType instanceof String) {
|
||||
varType = Type.getObjectType((String) localType);
|
||||
}
|
||||
setFrameLocal(remap(index, typ), t);
|
||||
setFrameLocal(remap(oldVar, varType), localType);
|
||||
}
|
||||
index += size;
|
||||
oldVar += localType == Opcodes.LONG || localType == Opcodes.DOUBLE ? 2 : 1;
|
||||
}
|
||||
|
||||
// removes TOP after long and double types as well as trailing TOPs
|
||||
|
||||
index = 0;
|
||||
number = 0;
|
||||
for (int i = 0; index < newLocals.length; ++i) {
|
||||
Object t = newLocals[index++];
|
||||
if (t != null && t != Opcodes.TOP) {
|
||||
newLocals[i] = t;
|
||||
number = i + 1;
|
||||
if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
|
||||
index += 1;
|
||||
}
|
||||
// Remove TOP after long and double types as well as trailing TOPs.
|
||||
oldVar = 0;
|
||||
int newVar = 0;
|
||||
int remappedNumLocal = 0;
|
||||
while (oldVar < remappedLocalTypes.length) {
|
||||
Object localType = remappedLocalTypes[oldVar];
|
||||
oldVar += localType == Opcodes.LONG || localType == Opcodes.DOUBLE ? 2 : 1;
|
||||
if (localType != null && localType != Opcodes.TOP) {
|
||||
remappedLocalTypes[newVar++] = localType;
|
||||
remappedNumLocal = newVar;
|
||||
} else {
|
||||
newLocals[i] = Opcodes.TOP;
|
||||
remappedLocalTypes[newVar++] = Opcodes.TOP;
|
||||
}
|
||||
}
|
||||
|
||||
// visits remapped frame
|
||||
mv.visitFrame(type, number, newLocals, nStack, stack);
|
||||
// Visit the remapped frame.
|
||||
super.visitFrame(type, remappedNumLocal, remappedLocalTypes, numStack, stack);
|
||||
|
||||
// restores original value of 'newLocals'
|
||||
newLocals = oldLocals;
|
||||
// Restore the original value of 'remappedLocals'.
|
||||
remappedLocalTypes = oldRemappedLocals;
|
||||
}
|
||||
|
||||
// -------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a new local variable of the given type.
|
||||
*
|
||||
* @param type
|
||||
* the type of the local variable to be created.
|
||||
* @return the identifier of the newly created local variable.
|
||||
*/
|
||||
* Constructs a new local variable of the given type.
|
||||
*
|
||||
* @param type the type of the local variable to be created.
|
||||
* @return the identifier of the newly created local variable.
|
||||
*/
|
||||
public int newLocal(final Type type) {
|
||||
Object t;
|
||||
Object localType;
|
||||
switch (type.getSort()) {
|
||||
case Type.BOOLEAN:
|
||||
case Type.CHAR:
|
||||
case Type.BYTE:
|
||||
case Type.SHORT:
|
||||
case Type.INT:
|
||||
t = Opcodes.INTEGER;
|
||||
break;
|
||||
case Type.FLOAT:
|
||||
t = Opcodes.FLOAT;
|
||||
break;
|
||||
case Type.LONG:
|
||||
t = Opcodes.LONG;
|
||||
break;
|
||||
case Type.DOUBLE:
|
||||
t = Opcodes.DOUBLE;
|
||||
break;
|
||||
case Type.ARRAY:
|
||||
t = type.getDescriptor();
|
||||
break;
|
||||
// case Type.OBJECT:
|
||||
default:
|
||||
t = type.getInternalName();
|
||||
break;
|
||||
case Type.BOOLEAN:
|
||||
case Type.CHAR:
|
||||
case Type.BYTE:
|
||||
case Type.SHORT:
|
||||
case Type.INT:
|
||||
localType = Opcodes.INTEGER;
|
||||
break;
|
||||
case Type.FLOAT:
|
||||
localType = Opcodes.FLOAT;
|
||||
break;
|
||||
case Type.LONG:
|
||||
localType = Opcodes.LONG;
|
||||
break;
|
||||
case Type.DOUBLE:
|
||||
localType = Opcodes.DOUBLE;
|
||||
break;
|
||||
case Type.ARRAY:
|
||||
localType = type.getDescriptor();
|
||||
break;
|
||||
case Type.OBJECT:
|
||||
localType = type.getInternalName();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
int local = newLocalMapping(type);
|
||||
setLocalType(local, type);
|
||||
setFrameLocal(local, t);
|
||||
setFrameLocal(local, localType);
|
||||
return local;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies subclasses that a new stack map frame is being visited. The
|
||||
* array argument contains the stack map frame types corresponding to the
|
||||
* local variables added with {@link #newLocal}. This method can update
|
||||
* these types in place for the stack map frame being visited. The default
|
||||
* implementation of this method does nothing, i.e. a local variable added
|
||||
* with {@link #newLocal} will have the same type in all stack map frames.
|
||||
* But this behavior is not always the desired one, for instance if a local
|
||||
* variable is added in the middle of a try/catch block: the frame for the
|
||||
* exception handler should have a TOP type for this new local.
|
||||
*
|
||||
* @param newLocals
|
||||
* the stack map frame types corresponding to the local variables
|
||||
* added with {@link #newLocal} (and null for the others). The
|
||||
* format of this array is the same as in
|
||||
* {@link MethodVisitor#visitFrame}, except that long and double
|
||||
* types use two slots. The types for the current stack map frame
|
||||
* must be updated in place in this array.
|
||||
*/
|
||||
protected void updateNewLocals(Object[] newLocals) {
|
||||
* Notifies subclasses that a new stack map frame is being visited. The array argument contains
|
||||
* the stack map frame types corresponding to the local variables added with {@link #newLocal}.
|
||||
* This method can update these types in place for the stack map frame being visited. The default
|
||||
* implementation of this method does nothing, i.e. a local variable added with {@link #newLocal}
|
||||
* will have the same type in all stack map frames. But this behavior is not always the desired
|
||||
* one, for instance if a local variable is added in the middle of a try/catch block: the frame
|
||||
* for the exception handler should have a TOP type for this new local.
|
||||
*
|
||||
* @param newLocals the stack map frame types corresponding to the local variables added with
|
||||
* {@link #newLocal} (and null for the others). The format of this array is the same as in
|
||||
* {@link MethodVisitor#visitFrame}, except that long and double types use two slots. The
|
||||
* types for the current stack map frame must be updated in place in this array.
|
||||
*/
|
||||
protected void updateNewLocals(final Object[] newLocals) {
|
||||
// The default implementation does nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies subclasses that a local variable has been added or remapped. The
|
||||
* default implementation of this method does nothing.
|
||||
*
|
||||
* @param local
|
||||
* a local variable identifier, as returned by {@link #newLocal
|
||||
* newLocal()}.
|
||||
* @param type
|
||||
* the type of the value being stored in the local variable.
|
||||
*/
|
||||
* Notifies subclasses that a local variable has been added or remapped. The default
|
||||
* implementation of this method does nothing.
|
||||
*
|
||||
* @param local a local variable identifier, as returned by {@link #newLocal}.
|
||||
* @param type the type of the value being stored in the local variable.
|
||||
*/
|
||||
protected void setLocalType(final int local, final Type type) {
|
||||
// The default implementation does nothing.
|
||||
}
|
||||
|
||||
private void setFrameLocal(final int local, final Object type) {
|
||||
int l = newLocals.length;
|
||||
if (local >= l) {
|
||||
Object[] a = new Object[Math.max(2 * l, local + 1)];
|
||||
System.arraycopy(newLocals, 0, a, 0, l);
|
||||
newLocals = a;
|
||||
int numLocals = remappedLocalTypes.length;
|
||||
if (local >= numLocals) {
|
||||
Object[] newRemappedLocalTypes = new Object[Math.max(2 * numLocals, local + 1)];
|
||||
System.arraycopy(remappedLocalTypes, 0, newRemappedLocalTypes, 0, numLocals);
|
||||
remappedLocalTypes = newRemappedLocalTypes;
|
||||
}
|
||||
newLocals[local] = type;
|
||||
remappedLocalTypes[local] = type;
|
||||
}
|
||||
|
||||
private int remap(final int var, final Type type) {
|
||||
|
|
@ -371,17 +357,17 @@ public class LocalVariablesSorter extends MethodVisitor {
|
|||
return var;
|
||||
}
|
||||
int key = 2 * var + type.getSize() - 1;
|
||||
int size = mapping.length;
|
||||
int size = remappedVariableIndices.length;
|
||||
if (key >= size) {
|
||||
int[] newMapping = new int[Math.max(2 * size, key + 1)];
|
||||
System.arraycopy(mapping, 0, newMapping, 0, size);
|
||||
mapping = newMapping;
|
||||
int[] newRemappedVariableIndices = new int[Math.max(2 * size, key + 1)];
|
||||
System.arraycopy(remappedVariableIndices, 0, newRemappedVariableIndices, 0, size);
|
||||
remappedVariableIndices = newRemappedVariableIndices;
|
||||
}
|
||||
int value = mapping[key];
|
||||
int value = remappedVariableIndices[key];
|
||||
if (value == 0) {
|
||||
value = newLocalMapping(type);
|
||||
setLocalType(value, type);
|
||||
mapping[key] = value + 1;
|
||||
remappedVariableIndices[key] = value + 1;
|
||||
} else {
|
||||
value--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ package jdk.internal.org.objectweb.asm.commons;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
|
||||
/**
|
||||
|
|
@ -72,240 +71,223 @@ import jdk.internal.org.objectweb.asm.Type;
|
|||
*/
|
||||
public class Method {
|
||||
|
||||
/**
|
||||
* The method name.
|
||||
*/
|
||||
/** The method name. */
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The method descriptor.
|
||||
*/
|
||||
private final String desc;
|
||||
/** The method descriptor. */
|
||||
private final String descriptor;
|
||||
|
||||
/**
|
||||
* Maps primitive Java type names to their descriptors.
|
||||
*/
|
||||
private static final Map<String, String> DESCRIPTORS;
|
||||
/** The descriptors of the primitive Java types (plus void). */
|
||||
private static final Map<String, String> PRIMITIVE_TYPE_DESCRIPTORS;
|
||||
|
||||
static {
|
||||
DESCRIPTORS = new HashMap<String, String>();
|
||||
DESCRIPTORS.put("void", "V");
|
||||
DESCRIPTORS.put("byte", "B");
|
||||
DESCRIPTORS.put("char", "C");
|
||||
DESCRIPTORS.put("double", "D");
|
||||
DESCRIPTORS.put("float", "F");
|
||||
DESCRIPTORS.put("int", "I");
|
||||
DESCRIPTORS.put("long", "J");
|
||||
DESCRIPTORS.put("short", "S");
|
||||
DESCRIPTORS.put("boolean", "Z");
|
||||
HashMap<String, String> descriptors = new HashMap<String, String>();
|
||||
descriptors.put("void", "V");
|
||||
descriptors.put("byte", "B");
|
||||
descriptors.put("char", "C");
|
||||
descriptors.put("double", "D");
|
||||
descriptors.put("float", "F");
|
||||
descriptors.put("int", "I");
|
||||
descriptors.put("long", "J");
|
||||
descriptors.put("short", "S");
|
||||
descriptors.put("boolean", "Z");
|
||||
PRIMITIVE_TYPE_DESCRIPTORS = descriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Method}.
|
||||
*
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor.
|
||||
*/
|
||||
public Method(final String name, final String desc) {
|
||||
* Constructs a new {@link Method}.
|
||||
*
|
||||
* @param name the method's name.
|
||||
* @param descriptor the method's descriptor.
|
||||
*/
|
||||
public Method(final String name, final String descriptor) {
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Method}.
|
||||
*
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param returnType
|
||||
* the method's return type.
|
||||
* @param argumentTypes
|
||||
* the method's argument types.
|
||||
*/
|
||||
public Method(final String name, final Type returnType,
|
||||
final Type[] argumentTypes) {
|
||||
* Constructs a new {@link Method}.
|
||||
*
|
||||
* @param name the method's name.
|
||||
* @param returnType the method's return type.
|
||||
* @param argumentTypes the method's argument types.
|
||||
*/
|
||||
public Method(final String name, final Type returnType, final Type[] argumentTypes) {
|
||||
this(name, Type.getMethodDescriptor(returnType, argumentTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Method}.
|
||||
*
|
||||
* @param m
|
||||
* a java.lang.reflect method descriptor
|
||||
* @return a {@link Method} corresponding to the given Java method
|
||||
* declaration.
|
||||
*/
|
||||
public static Method getMethod(java.lang.reflect.Method m) {
|
||||
return new Method(m.getName(), Type.getMethodDescriptor(m));
|
||||
* Creates a new {@link Method}.
|
||||
*
|
||||
* @param method a java.lang.reflect method descriptor
|
||||
* @return a {@link Method} corresponding to the given Java method declaration.
|
||||
*/
|
||||
public static Method getMethod(final java.lang.reflect.Method method) {
|
||||
return new Method(method.getName(), Type.getMethodDescriptor(method));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Method}.
|
||||
*
|
||||
* @param c
|
||||
* a java.lang.reflect constructor descriptor
|
||||
* @return a {@link Method} corresponding to the given Java constructor
|
||||
* declaration.
|
||||
*/
|
||||
public static Method getMethod(java.lang.reflect.Constructor<?> c) {
|
||||
return new Method("<init>", Type.getConstructorDescriptor(c));
|
||||
* Creates a new {@link Method}.
|
||||
*
|
||||
* @param constructor a java.lang.reflect constructor descriptor
|
||||
* @return a {@link Method} corresponding to the given Java constructor declaration.
|
||||
*/
|
||||
public static Method getMethod(final java.lang.reflect.Constructor<?> constructor) {
|
||||
return new Method("<init>", Type.getConstructorDescriptor(constructor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Method} corresponding to the given Java method
|
||||
* declaration.
|
||||
*
|
||||
* @param method
|
||||
* a Java method declaration, without argument names, of the form
|
||||
* "returnType name (argumentType1, ... argumentTypeN)", where
|
||||
* the types are in plain Java (e.g. "int", "float",
|
||||
* "java.util.List", ...). Classes of the java.lang package can
|
||||
* be specified by their unqualified name; all other classes
|
||||
* names must be fully qualified.
|
||||
* @return a {@link Method} corresponding to the given Java method
|
||||
* declaration.
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>method</code> could not get parsed.
|
||||
*/
|
||||
public static Method getMethod(final String method)
|
||||
throws IllegalArgumentException {
|
||||
* Returns a {@link Method} corresponding to the given Java method declaration.
|
||||
*
|
||||
* @param method a Java method declaration, without argument names, of the form "returnType name
|
||||
* (argumentType1, ... argumentTypeN)", where the types are in plain Java (e.g. "int",
|
||||
* "float", "java.util.List", ...). Classes of the java.lang package can be specified by their
|
||||
* unqualified name; all other classes names must be fully qualified.
|
||||
* @return a {@link Method} corresponding to the given Java method declaration.
|
||||
* @throws IllegalArgumentException if <code>method</code> could not get parsed.
|
||||
*/
|
||||
public static Method getMethod(final String method) {
|
||||
return getMethod(method, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Method} corresponding to the given Java method
|
||||
* declaration.
|
||||
*
|
||||
* @param method
|
||||
* a Java method declaration, without argument names, of the form
|
||||
* "returnType name (argumentType1, ... argumentTypeN)", where
|
||||
* the types are in plain Java (e.g. "int", "float",
|
||||
* "java.util.List", ...). Classes of the java.lang package may
|
||||
* be specified by their unqualified name, depending on the
|
||||
* defaultPackage argument; all other classes names must be fully
|
||||
* qualified.
|
||||
* @param defaultPackage
|
||||
* true if unqualified class names belong to the default package,
|
||||
* or false if they correspond to java.lang classes. For instance
|
||||
* "Object" means "Object" if this option is true, or
|
||||
* "java.lang.Object" otherwise.
|
||||
* @return a {@link Method} corresponding to the given Java method
|
||||
* declaration.
|
||||
* @throws IllegalArgumentException
|
||||
* if <code>method</code> could not get parsed.
|
||||
*/
|
||||
public static Method getMethod(final String method,
|
||||
final boolean defaultPackage) throws IllegalArgumentException {
|
||||
int space = method.indexOf(' ');
|
||||
int start = method.indexOf('(', space) + 1;
|
||||
int end = method.indexOf(')', start);
|
||||
if (space == -1 || start == -1 || end == -1) {
|
||||
* Returns a {@link Method} corresponding to the given Java method declaration.
|
||||
*
|
||||
* @param method a Java method declaration, without argument names, of the form "returnType name
|
||||
* (argumentType1, ... argumentTypeN)", where the types are in plain Java (e.g. "int",
|
||||
* "float", "java.util.List", ...). Classes of the java.lang package may be specified by their
|
||||
* unqualified name, depending on the defaultPackage argument; all other classes names must be
|
||||
* fully qualified.
|
||||
* @param defaultPackage true if unqualified class names belong to the default package, or false
|
||||
* if they correspond to java.lang classes. For instance "Object" means "Object" if this
|
||||
* option is true, or "java.lang.Object" otherwise.
|
||||
* @return a {@link Method} corresponding to the given Java method declaration.
|
||||
* @throws IllegalArgumentException if <code>method</code> could not get parsed.
|
||||
*/
|
||||
public static Method getMethod(final String method, final boolean defaultPackage) {
|
||||
final int spaceIndex = method.indexOf(' ');
|
||||
int currentArgumentStartIndex = method.indexOf('(', spaceIndex) + 1;
|
||||
final int endIndex = method.indexOf(')', currentArgumentStartIndex);
|
||||
if (spaceIndex == -1 || currentArgumentStartIndex == 0 || endIndex == -1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
String returnType = method.substring(0, space);
|
||||
String methodName = method.substring(space + 1, start - 1).trim();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
int p;
|
||||
final String returnType = method.substring(0, spaceIndex);
|
||||
final String methodName =
|
||||
method.substring(spaceIndex + 1, currentArgumentStartIndex - 1).trim();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append('(');
|
||||
int currentArgumentEndIndex;
|
||||
do {
|
||||
String s;
|
||||
p = method.indexOf(',', start);
|
||||
if (p == -1) {
|
||||
s = map(method.substring(start, end).trim(), defaultPackage);
|
||||
String argumentDescriptor;
|
||||
currentArgumentEndIndex = method.indexOf(',', currentArgumentStartIndex);
|
||||
if (currentArgumentEndIndex == -1) {
|
||||
argumentDescriptor =
|
||||
getDescriptorInternal(
|
||||
method.substring(currentArgumentStartIndex, endIndex).trim(), defaultPackage);
|
||||
} else {
|
||||
s = map(method.substring(start, p).trim(), defaultPackage);
|
||||
start = p + 1;
|
||||
argumentDescriptor =
|
||||
getDescriptorInternal(
|
||||
method.substring(currentArgumentStartIndex, currentArgumentEndIndex).trim(),
|
||||
defaultPackage);
|
||||
currentArgumentStartIndex = currentArgumentEndIndex + 1;
|
||||
}
|
||||
sb.append(s);
|
||||
} while (p != -1);
|
||||
sb.append(')');
|
||||
sb.append(map(returnType, defaultPackage));
|
||||
return new Method(methodName, sb.toString());
|
||||
stringBuilder.append(argumentDescriptor);
|
||||
} while (currentArgumentEndIndex != -1);
|
||||
stringBuilder.append(')').append(getDescriptorInternal(returnType, defaultPackage));
|
||||
return new Method(methodName, stringBuilder.toString());
|
||||
}
|
||||
|
||||
private static String map(final String type, final boolean defaultPackage) {
|
||||
/**
|
||||
* Returns the descriptor corresponding to the given type name.
|
||||
*
|
||||
* @param type a Java type name.
|
||||
* @param defaultPackage true if unqualified class names belong to the default package, or false
|
||||
* if they correspond to java.lang classes. For instance "Object" means "Object" if this
|
||||
* option is true, or "java.lang.Object" otherwise.
|
||||
* @return the descriptor corresponding to the given type name.
|
||||
*/
|
||||
private static String getDescriptorInternal(final String type, final boolean defaultPackage) {
|
||||
if ("".equals(type)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int index = 0;
|
||||
while ((index = type.indexOf("[]", index) + 1) > 0) {
|
||||
sb.append('[');
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int arrayBracketsIndex = 0;
|
||||
while ((arrayBracketsIndex = type.indexOf("[]", arrayBracketsIndex) + 1) > 0) {
|
||||
stringBuilder.append('[');
|
||||
}
|
||||
|
||||
String t = type.substring(0, type.length() - sb.length() * 2);
|
||||
String desc = DESCRIPTORS.get(t);
|
||||
if (desc != null) {
|
||||
sb.append(desc);
|
||||
String elementType = type.substring(0, type.length() - stringBuilder.length() * 2);
|
||||
String descriptor = PRIMITIVE_TYPE_DESCRIPTORS.get(elementType);
|
||||
if (descriptor != null) {
|
||||
stringBuilder.append(descriptor);
|
||||
} else {
|
||||
sb.append('L');
|
||||
if (t.indexOf('.') < 0) {
|
||||
stringBuilder.append('L');
|
||||
if (elementType.indexOf('.') < 0) {
|
||||
if (!defaultPackage) {
|
||||
sb.append("java/lang/");
|
||||
stringBuilder.append("java/lang/");
|
||||
}
|
||||
sb.append(t);
|
||||
stringBuilder.append(elementType);
|
||||
} else {
|
||||
sb.append(t.replace('.', '/'));
|
||||
stringBuilder.append(elementType.replace('.', '/'));
|
||||
}
|
||||
sb.append(';');
|
||||
stringBuilder.append(';');
|
||||
}
|
||||
return sb.toString();
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the method described by this object.
|
||||
*
|
||||
* @return the name of the method described by this object.
|
||||
*/
|
||||
* Returns the name of the method described by this object.
|
||||
*
|
||||
* @return the name of the method described by this object.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the descriptor of the method described by this object.
|
||||
*
|
||||
* @return the descriptor of the method described by this object.
|
||||
*/
|
||||
* Returns the descriptor of the method described by this object.
|
||||
*
|
||||
* @return the descriptor of the method described by this object.
|
||||
*/
|
||||
public String getDescriptor() {
|
||||
return desc;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the return type of the method described by this object.
|
||||
*
|
||||
* @return the return type of the method described by this object.
|
||||
*/
|
||||
* Returns the return type of the method described by this object.
|
||||
*
|
||||
* @return the return type of the method described by this object.
|
||||
*/
|
||||
public Type getReturnType() {
|
||||
return Type.getReturnType(desc);
|
||||
return Type.getReturnType(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument types of the method described by this object.
|
||||
*
|
||||
* @return the argument types of the method described by this object.
|
||||
*/
|
||||
* Returns the argument types of the method described by this object.
|
||||
*
|
||||
* @return the argument types of the method described by this object.
|
||||
*/
|
||||
public Type[] getArgumentTypes() {
|
||||
return Type.getArgumentTypes(desc);
|
||||
return Type.getArgumentTypes(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + desc;
|
||||
return name + descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof Method)) {
|
||||
public boolean equals(final Object other) {
|
||||
if (!(other instanceof Method)) {
|
||||
return false;
|
||||
}
|
||||
Method other = (Method) o;
|
||||
return name.equals(other.name) && desc.equals(other.desc);
|
||||
Method otherMethod = (Method) other;
|
||||
return name.equals(otherMethod.name) && descriptor.equals(otherMethod.descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode() ^ desc.hashCode();
|
||||
return name.hashCode() ^ descriptor.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
|
|
@ -67,188 +66,258 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
import jdk.internal.org.objectweb.asm.TypePath;
|
||||
|
||||
/**
|
||||
* A {@link LocalVariablesSorter} for type mapping.
|
||||
* A {@link MethodVisitor} that remaps types with a {@link Remapper}.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class MethodRemapper extends MethodVisitor {
|
||||
|
||||
/** The remapper used to remap the types in the visited field. */
|
||||
protected final Remapper remapper;
|
||||
|
||||
public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, mv, remapper);
|
||||
/**
|
||||
* Constructs a new {@link MethodRemapper}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #MethodRemapper(int,MethodVisitor,Remapper)} version.
|
||||
*
|
||||
* @param methodVisitor the method visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited method.
|
||||
*/
|
||||
public MethodRemapper(final MethodVisitor methodVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM7, methodVisitor, remapper);
|
||||
}
|
||||
|
||||
protected MethodRemapper(final int api, final MethodVisitor mv,
|
||||
final Remapper remapper) {
|
||||
super(api, mv);
|
||||
/**
|
||||
* Constructs a new {@link MethodRemapper}.
|
||||
*
|
||||
* @param api the ASM API version supported by this remapper. Must be one of {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5} or {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM6}.
|
||||
* @param methodVisitor the method visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited method.
|
||||
*/
|
||||
protected MethodRemapper(
|
||||
final int api, final MethodVisitor methodVisitor, final Remapper remapper) {
|
||||
super(api, methodVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotationDefault() {
|
||||
AnnotationVisitor av = super.visitAnnotationDefault();
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
AnnotationVisitor annotationVisitor = super.visitAnnotationDefault();
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
|
||||
visible);
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitAnnotation(remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitParameterAnnotation(int parameter,
|
||||
String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitParameterAnnotation(parameter,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitParameterAnnotation(
|
||||
final int parameter, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitParameterAnnotation(parameter, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack,
|
||||
Object[] stack) {
|
||||
super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
|
||||
remapEntries(nStack, stack));
|
||||
public void visitFrame(
|
||||
final int type,
|
||||
final int numLocal,
|
||||
final Object[] local,
|
||||
final int numStack,
|
||||
final Object[] stack) {
|
||||
super.visitFrame(
|
||||
type,
|
||||
numLocal,
|
||||
remapFrameTypes(numLocal, local),
|
||||
numStack,
|
||||
remapFrameTypes(numStack, stack));
|
||||
}
|
||||
|
||||
private Object[] remapEntries(int n, Object[] entries) {
|
||||
if (entries != null) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (entries[i] instanceof String) {
|
||||
Object[] newEntries = new Object[n];
|
||||
if (i > 0) {
|
||||
System.arraycopy(entries, 0, newEntries, 0, i);
|
||||
}
|
||||
do {
|
||||
Object t = entries[i];
|
||||
newEntries[i++] = t instanceof String ? remapper
|
||||
.mapType((String) t) : t;
|
||||
} while (i < n);
|
||||
return newEntries;
|
||||
private Object[] remapFrameTypes(final int numTypes, final Object[] frameTypes) {
|
||||
if (frameTypes == null) {
|
||||
return frameTypes;
|
||||
}
|
||||
Object[] remappedFrameTypes = null;
|
||||
for (int i = 0; i < numTypes; ++i) {
|
||||
if (frameTypes[i] instanceof String) {
|
||||
if (remappedFrameTypes == null) {
|
||||
remappedFrameTypes = new Object[numTypes];
|
||||
System.arraycopy(frameTypes, 0, remappedFrameTypes, 0, numTypes);
|
||||
}
|
||||
remappedFrameTypes[i] = remapper.mapType((String) frameTypes[i]);
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
return remappedFrameTypes == null ? frameTypes : remappedFrameTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name,
|
||||
String desc) {
|
||||
super.visitFieldInsn(opcode, remapper.mapType(owner),
|
||||
remapper.mapFieldName(owner, name, desc),
|
||||
remapper.mapDesc(desc));
|
||||
public void visitFieldInsn(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
super.visitFieldInsn(
|
||||
opcode,
|
||||
remapper.mapType(owner),
|
||||
remapper.mapFieldName(owner, name, descriptor),
|
||||
remapper.mapDesc(descriptor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
public void visitMethodInsn(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
if (api >= Opcodes.ASM5) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor);
|
||||
return;
|
||||
}
|
||||
doVisitMethodInsn(opcode, owner, name, desc,
|
||||
opcode == Opcodes.INVOKEINTERFACE);
|
||||
doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc, final boolean itf) {
|
||||
public void visitMethodInsn(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
if (api < Opcodes.ASM5) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
return;
|
||||
}
|
||||
doVisitMethodInsn(opcode, owner, name, desc, itf);
|
||||
doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
}
|
||||
|
||||
private void doVisitMethodInsn(int opcode, String owner, String name,
|
||||
String desc, boolean itf) {
|
||||
// Calling super.visitMethodInsn requires to call the correct version
|
||||
// depending on this.api (otherwise infinite loops can occur). To
|
||||
// simplify and to make it easier to automatically remove the backward
|
||||
// compatibility code, we inline the code of the overridden method here.
|
||||
// IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
|
||||
// LocalVariableSorter.
|
||||
private void doVisitMethodInsn(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
// Calling super.visitMethodInsn requires to call the correct version depending on this.api
|
||||
// (otherwise infinite loops can occur). To simplify and to make it easier to automatically
|
||||
// remove the backward compatibility code, we inline the code of the overridden method here.
|
||||
if (mv != null) {
|
||||
mv.visitMethodInsn(opcode, remapper.mapType(owner),
|
||||
remapper.mapMethodName(owner, name, desc),
|
||||
remapper.mapMethodDesc(desc), itf);
|
||||
mv.visitMethodInsn(
|
||||
opcode,
|
||||
remapper.mapType(owner),
|
||||
remapper.mapMethodName(owner, name, descriptor),
|
||||
remapper.mapMethodDesc(descriptor),
|
||||
isInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
|
||||
Object... bsmArgs) {
|
||||
for (int i = 0; i < bsmArgs.length; i++) {
|
||||
bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
|
||||
public void visitInvokeDynamicInsn(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final Handle bootstrapMethodHandle,
|
||||
final Object... bootstrapMethodArguments) {
|
||||
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArguments.length];
|
||||
for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
|
||||
remappedBootstrapMethodArguments[i] = remapper.mapValue(bootstrapMethodArguments[i]);
|
||||
}
|
||||
super.visitInvokeDynamicInsn(
|
||||
remapper.mapInvokeDynamicMethodName(name, desc),
|
||||
remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
|
||||
bsmArgs);
|
||||
remapper.mapInvokeDynamicMethodName(name, descriptor),
|
||||
remapper.mapMethodDesc(descriptor),
|
||||
(Handle) remapper.mapValue(bootstrapMethodHandle),
|
||||
remappedBootstrapMethodArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
public void visitTypeInsn(final int opcode, final String type) {
|
||||
super.visitTypeInsn(opcode, remapper.mapType(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object cst) {
|
||||
super.visitLdcInsn(remapper.mapValue(cst));
|
||||
public void visitLdcInsn(final Object value) {
|
||||
super.visitLdcInsn(remapper.mapValue(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMultiANewArrayInsn(String desc, int dims) {
|
||||
super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
|
||||
public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
|
||||
super.visitMultiANewArrayInsn(remapper.mapDesc(descriptor), numDimensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitInsnAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitInsnAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTryCatchBlock(Label start, Label end, Label handler,
|
||||
String type) {
|
||||
super.visitTryCatchBlock(start, end, handler, type == null ? null
|
||||
: remapper.mapType(type));
|
||||
public void visitTryCatchBlock(
|
||||
final Label start, final Label end, final Label handler, final String type) {
|
||||
super.visitTryCatchBlock(start, end, handler, type == null ? null : remapper.mapType(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitTryCatchAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTryCatchAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(String name, String desc, String signature,
|
||||
Label start, Label end, int index) {
|
||||
super.visitLocalVariable(name, remapper.mapDesc(desc),
|
||||
remapper.mapSignature(signature, true), start, end, index);
|
||||
public void visitLocalVariable(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Label start,
|
||||
final Label end,
|
||||
final int index) {
|
||||
super.visitLocalVariable(
|
||||
name,
|
||||
remapper.mapDesc(descriptor),
|
||||
remapper.mapSignature(signature, true),
|
||||
start,
|
||||
end,
|
||||
index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
||||
TypePath typePath, Label[] start, Label[] end, int[] index,
|
||||
String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
|
||||
typePath, start, end, index, remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new AnnotationRemapper(av, remapper);
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(
|
||||
final int typeRef,
|
||||
final TypePath typePath,
|
||||
final Label[] start,
|
||||
final Label[] end,
|
||||
final int[] index,
|
||||
final String descriptor,
|
||||
final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitLocalVariableAnnotation(
|
||||
typeRef, typePath, start, end, index, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new AnnotationRemapper(api, annotationVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,12 +56,10 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Attribute;
|
||||
import jdk.internal.org.objectweb.asm.ByteVector;
|
||||
import jdk.internal.org.objectweb.asm.ClassReader;
|
||||
|
|
@ -69,25 +67,30 @@ import jdk.internal.org.objectweb.asm.ClassWriter;
|
|||
import jdk.internal.org.objectweb.asm.Label;
|
||||
|
||||
/**
|
||||
* ModuleHashes attribute.
|
||||
* This attribute is specific to the OpenJDK and may change in the future.
|
||||
* A ModuleHashes attribute. This attribute is specific to the OpenJDK and may change in the future.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public final class ModuleHashesAttribute extends Attribute {
|
||||
|
||||
/** The name of the hashing algorithm. */
|
||||
public String algorithm;
|
||||
|
||||
/** A list of module names. */
|
||||
public List<String> modules;
|
||||
|
||||
/** The hash of the modules in {@link #modules}. The two lists must have the same size. */
|
||||
public List<byte[]> hashes;
|
||||
|
||||
/**
|
||||
* Creates an attribute with a hashing algorithm, a list of module names,
|
||||
* and a list of the same length of hashes.
|
||||
* @param algorithm the hashing algorithm name.
|
||||
* @param modules a list of module name
|
||||
* @param hashes a list of hash, one for each module name.
|
||||
*/
|
||||
public ModuleHashesAttribute(final String algorithm,
|
||||
final List<String> modules, final List<byte[]> hashes) {
|
||||
* Constructs a new {@link ModuleHashesAttribute}.
|
||||
*
|
||||
* @param algorithm the name of the hashing algorithm.
|
||||
* @param modules a list of module names.
|
||||
* @param hashes the hash of the modules in 'modules'. The two lists must have the same size.
|
||||
*/
|
||||
public ModuleHashesAttribute(
|
||||
final String algorithm, final List<String> modules, final List<byte[]> hashes) {
|
||||
super("ModuleHashes");
|
||||
this.algorithm = algorithm;
|
||||
this.modules = modules;
|
||||
|
|
@ -95,61 +98,72 @@ public final class ModuleHashesAttribute extends Attribute {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an empty attribute that can be used as prototype
|
||||
* to be passed as argument of the method
|
||||
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
|
||||
*/
|
||||
* Constructs an empty {@link ModuleHashesAttribute}. This object can be passed as a prototype to
|
||||
* the {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)} method.
|
||||
*/
|
||||
public ModuleHashesAttribute() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
|
||||
int codeOff, Label[] labels) {
|
||||
String hashAlgorithm = cr.readUTF8(off, buf);
|
||||
protected Attribute read(
|
||||
final ClassReader classReader,
|
||||
final int offset,
|
||||
final int length,
|
||||
final char[] charBuffer,
|
||||
final int codeAttributeOffset,
|
||||
final Label[] labels) {
|
||||
int currentOffset = offset;
|
||||
|
||||
int count = cr.readUnsignedShort(off + 2);
|
||||
ArrayList<String> modules = new ArrayList<String>(count);
|
||||
ArrayList<byte[]> hashes = new ArrayList<byte[]>(count);
|
||||
off += 4;
|
||||
String hashAlgorithm = classReader.readUTF8(currentOffset, charBuffer);
|
||||
currentOffset += 2;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
String module = cr.readModule(off, buf);
|
||||
int hashLength = cr.readUnsignedShort(off + 2);
|
||||
off += 4;
|
||||
int numModules = classReader.readUnsignedShort(currentOffset);
|
||||
currentOffset += 2;
|
||||
|
||||
ArrayList<String> moduleList = new ArrayList<String>(numModules);
|
||||
ArrayList<byte[]> hashList = new ArrayList<byte[]>(numModules);
|
||||
|
||||
for (int i = 0; i < numModules; ++i) {
|
||||
String module = classReader.readModule(currentOffset, charBuffer);
|
||||
currentOffset += 2;
|
||||
moduleList.add(module);
|
||||
|
||||
int hashLength = classReader.readUnsignedShort(currentOffset);
|
||||
currentOffset += 2;
|
||||
byte[] hash = new byte[hashLength];
|
||||
for (int j = 0; j < hashLength; j++) {
|
||||
hash[j] = (byte) (cr.readByte(off + j) & 0xff);
|
||||
for (int j = 0; j < hashLength; ++j) {
|
||||
hash[j] = (byte) (classReader.readByte(currentOffset) & 0xFF);
|
||||
currentOffset += 1;
|
||||
}
|
||||
off += hashLength;
|
||||
|
||||
modules.add(module);
|
||||
hashes.add(hash);
|
||||
hashList.add(hash);
|
||||
}
|
||||
return new ModuleHashesAttribute(hashAlgorithm, modules, hashes);
|
||||
return new ModuleHashesAttribute(hashAlgorithm, moduleList, hashList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len,
|
||||
int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector();
|
||||
int index = cw.newUTF8(algorithm);
|
||||
v.putShort(index);
|
||||
|
||||
int count = (modules == null)? 0: modules.size();
|
||||
v.putShort(count);
|
||||
|
||||
for(int i = 0; i < count; i++) {
|
||||
String module = modules.get(i);
|
||||
v.putShort(cw.newModule(module));
|
||||
|
||||
byte[] hash = hashes.get(i);
|
||||
v.putShort(hash.length);
|
||||
for(byte b: hash) {
|
||||
v.putByte(b);
|
||||
protected ByteVector write(
|
||||
final ClassWriter classWriter,
|
||||
final byte[] code,
|
||||
final int codeLength,
|
||||
final int maxStack,
|
||||
final int maxLocals) {
|
||||
ByteVector byteVector = new ByteVector();
|
||||
byteVector.putShort(classWriter.newUTF8(algorithm));
|
||||
if (modules == null) {
|
||||
byteVector.putShort(0);
|
||||
} else {
|
||||
int numModules = modules.size();
|
||||
byteVector.putShort(numModules);
|
||||
for (int i = 0; i < numModules; ++i) {
|
||||
String module = modules.get(i);
|
||||
byte[] hash = hashes.get(i);
|
||||
byteVector
|
||||
.putShort(classWriter.newModule(module))
|
||||
.putShort(hash.length)
|
||||
.putByteArray(hash, 0, hash.length);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
return byteVector;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,80 +56,97 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A {@link ModuleVisitor} adapter for type remapping.
|
||||
* A {@link ModuleVisitor} that remaps types with a {@link Remapper}.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public class ModuleRemapper extends ModuleVisitor {
|
||||
private final Remapper remapper;
|
||||
|
||||
public ModuleRemapper(final ModuleVisitor mv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, mv, remapper);
|
||||
/** The remapper used to remap the types in the visited module. */
|
||||
protected final Remapper remapper;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleRemapper}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #ModuleRemapper(int,ModuleVisitor,Remapper)} version.
|
||||
*
|
||||
* @param moduleVisitor the module visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited module.
|
||||
*/
|
||||
public ModuleRemapper(final ModuleVisitor moduleVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM7, moduleVisitor, remapper);
|
||||
}
|
||||
|
||||
protected ModuleRemapper(final int api, final ModuleVisitor mv,
|
||||
final Remapper remapper) {
|
||||
super(api, mv);
|
||||
/**
|
||||
* Constructs a new {@link ModuleRemapper}.
|
||||
*
|
||||
* @param api the ASM API version supported by this remapper. Must be one of {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5} or {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM6}.
|
||||
* @param moduleVisitor the module visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited module.
|
||||
*/
|
||||
protected ModuleRemapper(
|
||||
final int api, final ModuleVisitor moduleVisitor, final Remapper remapper) {
|
||||
super(api, moduleVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMainClass(String mainClass) {
|
||||
public void visitMainClass(final String mainClass) {
|
||||
super.visitMainClass(remapper.mapType(mainClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPackage(String packaze) {
|
||||
public void visitPackage(final String packaze) {
|
||||
super.visitPackage(remapper.mapPackageName(packaze));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
public void visitRequire(final String module, final int access, final String version) {
|
||||
super.visitRequire(remapper.mapModuleName(module), access, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
String[] newModules = null;
|
||||
public void visitExport(final String packaze, final int access, final String... modules) {
|
||||
String[] remappedModules = null;
|
||||
if (modules != null) {
|
||||
newModules = new String[modules.length];
|
||||
for (int i = 0 ; i < modules.length; i++) {
|
||||
newModules[i] = remapper.mapModuleName(modules[i]);
|
||||
remappedModules = new String[modules.length];
|
||||
for (int i = 0; i < modules.length; ++i) {
|
||||
remappedModules[i] = remapper.mapModuleName(modules[i]);
|
||||
}
|
||||
}
|
||||
super.visitExport(remapper.mapPackageName(packaze), access, newModules);
|
||||
super.visitExport(remapper.mapPackageName(packaze), access, remappedModules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOpen(String packaze, int access, String... modules) {
|
||||
String[] newModules = null;
|
||||
public void visitOpen(final String packaze, final int access, final String... modules) {
|
||||
String[] remappedModules = null;
|
||||
if (modules != null) {
|
||||
newModules = new String[modules.length];
|
||||
for (int i = 0 ; i < modules.length; i++) {
|
||||
newModules[i] = remapper.mapModuleName(modules[i]);
|
||||
remappedModules = new String[modules.length];
|
||||
for (int i = 0; i < modules.length; ++i) {
|
||||
remappedModules[i] = remapper.mapModuleName(modules[i]);
|
||||
}
|
||||
}
|
||||
super.visitOpen(remapper.mapPackageName(packaze), access, newModules);
|
||||
super.visitOpen(remapper.mapPackageName(packaze), access, remappedModules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUse(String service) {
|
||||
public void visitUse(final String service) {
|
||||
super.visitUse(remapper.mapType(service));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProvide(String service, String... providers) {
|
||||
String[] newProviders = new String[providers.length];
|
||||
for (int i = 0 ; i < providers.length; i++) {
|
||||
newProviders[i] = remapper.mapType(providers[i]);
|
||||
public void visitProvide(final String service, final String... providers) {
|
||||
String[] remappedProviders = new String[providers.length];
|
||||
for (int i = 0; i < providers.length; ++i) {
|
||||
remappedProviders[i] = remapper.mapType(providers[i]);
|
||||
}
|
||||
super.visitProvide(remapper.mapType(service), newProviders);
|
||||
super.visitProvide(remapper.mapType(service), remappedProviders);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Attribute;
|
||||
|
|
@ -66,70 +65,79 @@ import jdk.internal.org.objectweb.asm.ClassWriter;
|
|||
import jdk.internal.org.objectweb.asm.Label;
|
||||
|
||||
/**
|
||||
* ModuleResolution_attribute.
|
||||
* This attribute is specific to the OpenJDK and may change in the future.
|
||||
* A ModuleResolution attribute. This attribute is specific to the OpenJDK and may change in the
|
||||
* future.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public final class ModuleResolutionAttribute extends Attribute {
|
||||
/**
|
||||
* Resolution state of a module meaning that the module is not available
|
||||
* from the class-path by default.
|
||||
*/
|
||||
* The resolution state of a module meaning that the module is not available from the class-path
|
||||
* by default.
|
||||
*/
|
||||
public static final int RESOLUTION_DO_NOT_RESOLVE_BY_DEFAULT = 1;
|
||||
|
||||
/**
|
||||
* Resolution state of a module meaning the module is marked as deprecated.
|
||||
*/
|
||||
/** The resolution state of a module meaning the module is marked as deprecated. */
|
||||
public static final int RESOLUTION_WARN_DEPRECATED = 2;
|
||||
|
||||
/**
|
||||
* Resolution state of a module meaning the module is marked as deprecated
|
||||
* and will be removed in a future release.
|
||||
*/
|
||||
* The resolution state of a module meaning the module is marked as deprecated and will be removed
|
||||
* in a future release.
|
||||
*/
|
||||
public static final int RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL = 4;
|
||||
|
||||
/**
|
||||
* Resolution state of a module meaning the module is not yet standardized,
|
||||
* so in incubating mode.
|
||||
*/
|
||||
* The resolution state of a module meaning the module is not yet standardized, so in incubating
|
||||
* mode.
|
||||
*/
|
||||
public static final int RESOLUTION_WARN_INCUBATING = 8;
|
||||
|
||||
/**
|
||||
* The resolution state of the module. Must be one of {@link #RESOLUTION_WARN_DEPRECATED}, {@link
|
||||
* #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and {@link #RESOLUTION_WARN_INCUBATING}.
|
||||
*/
|
||||
public int resolution;
|
||||
|
||||
/**
|
||||
* Creates an attribute with a resolution state value.
|
||||
* @param resolution the resolution state among
|
||||
* {@link #RESOLUTION_WARN_DEPRECATED},
|
||||
* {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and
|
||||
* {@link #RESOLUTION_WARN_INCUBATING}.
|
||||
*/
|
||||
* Constructs a new {@link ModuleResolutionAttribute}.
|
||||
*
|
||||
* @param resolution the resolution state of the module. Must be one of {@link
|
||||
* #RESOLUTION_WARN_DEPRECATED}, {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and {@link
|
||||
* #RESOLUTION_WARN_INCUBATING}.
|
||||
*/
|
||||
public ModuleResolutionAttribute(final int resolution) {
|
||||
super("ModuleResolution");
|
||||
this.resolution = resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty attribute that can be used as prototype
|
||||
* to be passed as argument of the method
|
||||
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
|
||||
*/
|
||||
* Constructs an empty {@link ModuleResolutionAttribute}. This object can be passed as a prototype
|
||||
* to the {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)} method.
|
||||
*/
|
||||
public ModuleResolutionAttribute() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
|
||||
int codeOff, Label[] labels) {
|
||||
int resolution = cr.readUnsignedShort(off);
|
||||
return new ModuleResolutionAttribute(resolution);
|
||||
protected Attribute read(
|
||||
final ClassReader classReader,
|
||||
final int offset,
|
||||
final int length,
|
||||
final char[] charBuffer,
|
||||
final int codeOffset,
|
||||
final Label[] labels) {
|
||||
return new ModuleResolutionAttribute(classReader.readUnsignedShort(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len,
|
||||
int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector();
|
||||
v.putShort(resolution);
|
||||
return v;
|
||||
protected ByteVector write(
|
||||
final ClassWriter classWriter,
|
||||
final byte[] code,
|
||||
final int codeLength,
|
||||
final int maxStack,
|
||||
final int maxLocals) {
|
||||
ByteVector byteVector = new ByteVector();
|
||||
byteVector.putShort(resolution);
|
||||
return byteVector;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Attribute;
|
||||
|
|
@ -66,45 +65,53 @@ import jdk.internal.org.objectweb.asm.ClassWriter;
|
|||
import jdk.internal.org.objectweb.asm.Label;
|
||||
|
||||
/**
|
||||
* ModuleTarget attribute.
|
||||
* This attribute is specific to the OpenJDK and may change in the future.
|
||||
* A ModuleTarget attribute. This attribute is specific to the OpenJDK and may change in the future.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public final class ModuleTargetAttribute extends Attribute {
|
||||
|
||||
/** The name of the platform on which the module can run. */
|
||||
public String platform;
|
||||
|
||||
/**
|
||||
* Creates an attribute with a platform name.
|
||||
* @param platform the platform name on which the module can run.
|
||||
*/
|
||||
* Constructs a new {@link ModuleTargetAttribute}.
|
||||
*
|
||||
* @param platform the name of the platform on which the module can run.
|
||||
*/
|
||||
public ModuleTargetAttribute(final String platform) {
|
||||
super("ModuleTarget");
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty attribute that can be used as prototype
|
||||
* to be passed as argument of the method
|
||||
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
|
||||
*/
|
||||
* Constructs an empty {@link ModuleTargetAttribute}. This object can be passed as a prototype to
|
||||
* the {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)} method.
|
||||
*/
|
||||
public ModuleTargetAttribute() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
|
||||
int codeOff, Label[] labels) {
|
||||
String platform = cr.readUTF8(off, buf);
|
||||
return new ModuleTargetAttribute(platform);
|
||||
protected Attribute read(
|
||||
final ClassReader classReader,
|
||||
final int offset,
|
||||
final int length,
|
||||
final char[] charBuffer,
|
||||
final int codeOffset,
|
||||
final Label[] labels) {
|
||||
return new ModuleTargetAttribute(classReader.readUTF8(offset, charBuffer));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw, byte[] code, int len,
|
||||
int maxStack, int maxLocals) {
|
||||
ByteVector v = new ByteVector();
|
||||
int index = (platform == null)? 0: cw.newUTF8(platform);
|
||||
v.putShort(index);
|
||||
return v;
|
||||
protected ByteVector write(
|
||||
final ClassWriter classWriter,
|
||||
final byte[] code,
|
||||
final int codeLength,
|
||||
final int maxStack,
|
||||
final int maxLocals) {
|
||||
ByteVector byteVector = new ByteVector();
|
||||
byteVector.putShort(platform == null ? 0 : classWriter.newUTF8(platform));
|
||||
return byteVector;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,234 +56,305 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ConstantDynamic;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
import jdk.internal.org.objectweb.asm.signature.SignatureReader;
|
||||
import jdk.internal.org.objectweb.asm.signature.SignatureVisitor;
|
||||
import jdk.internal.org.objectweb.asm.signature.SignatureWriter;
|
||||
|
||||
/**
|
||||
* A class responsible for remapping types and names. Subclasses can override
|
||||
* the following methods:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #map(String)} - map type</li>
|
||||
* <li>{@link #mapFieldName(String, String, String)} - map field name</li>
|
||||
* <li>{@link #mapMethodName(String, String, String)} - map method name</li>
|
||||
* </ul>
|
||||
* A class responsible for remapping types and names.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public abstract class Remapper {
|
||||
|
||||
public String mapDesc(String desc) {
|
||||
Type t = Type.getType(desc);
|
||||
switch (t.getSort()) {
|
||||
case Type.ARRAY:
|
||||
String s = mapDesc(t.getElementType().getDescriptor());
|
||||
for (int i = 0; i < t.getDimensions(); ++i) {
|
||||
s = '[' + s;
|
||||
}
|
||||
return s;
|
||||
case Type.OBJECT:
|
||||
String newType = map(t.getInternalName());
|
||||
if (newType != null) {
|
||||
return 'L' + newType + ';';
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
/**
|
||||
* Returns the given descriptor, remapped with {@link #map(String)}.
|
||||
*
|
||||
* @param descriptor a type descriptor.
|
||||
* @return the given descriptor, with its [array element type] internal name remapped with {@link
|
||||
* #map(String)} (if the descriptor corresponds to an array or object type, otherwise the
|
||||
* descriptor is returned as is).
|
||||
*/
|
||||
public String mapDesc(final String descriptor) {
|
||||
return mapType(Type.getType(descriptor)).getDescriptor();
|
||||
}
|
||||
|
||||
private Type mapType(Type t) {
|
||||
switch (t.getSort()) {
|
||||
case Type.ARRAY:
|
||||
String s = mapDesc(t.getElementType().getDescriptor());
|
||||
for (int i = 0; i < t.getDimensions(); ++i) {
|
||||
s = '[' + s;
|
||||
}
|
||||
return Type.getType(s);
|
||||
case Type.OBJECT:
|
||||
s = map(t.getInternalName());
|
||||
return s != null ? Type.getObjectType(s) : t;
|
||||
case Type.METHOD:
|
||||
return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
|
||||
/**
|
||||
* Returns the given {@link Type}, remapped with {@link #map(String)} or {@link
|
||||
* #mapMethodDesc(String)}.
|
||||
*
|
||||
* @param type a type, which can be a method type.
|
||||
* @return the given type, with its [array element type] internal name remapped with {@link
|
||||
* #map(String)} (if the type is an array or object type, otherwise the type is returned as
|
||||
* is) or, of the type is a method type, with its descriptor remapped with {@link
|
||||
* #mapMethodDesc(String)}.
|
||||
*/
|
||||
private Type mapType(final Type type) {
|
||||
switch (type.getSort()) {
|
||||
case Type.ARRAY:
|
||||
StringBuilder remappedDescriptor = new StringBuilder();
|
||||
for (int i = 0; i < type.getDimensions(); ++i) {
|
||||
remappedDescriptor.append('[');
|
||||
}
|
||||
remappedDescriptor.append(mapType(type.getElementType()).getDescriptor());
|
||||
return Type.getType(remappedDescriptor.toString());
|
||||
case Type.OBJECT:
|
||||
String remappedInternalName = map(type.getInternalName());
|
||||
return remappedInternalName != null ? Type.getObjectType(remappedInternalName) : type;
|
||||
case Type.METHOD:
|
||||
return Type.getMethodType(mapMethodDesc(type.getDescriptor()));
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public String mapType(String type) {
|
||||
if (type == null) {
|
||||
/**
|
||||
* Returns the given internal name, remapped with {@link #map(String)}.
|
||||
*
|
||||
* @param internalName the internal name (or array type descriptor) of some (array) class.
|
||||
* @return the given internal name, remapped with {@link #map(String)}.
|
||||
*/
|
||||
public String mapType(final String internalName) {
|
||||
if (internalName == null) {
|
||||
return null;
|
||||
}
|
||||
return mapType(Type.getObjectType(type)).getInternalName();
|
||||
return mapType(Type.getObjectType(internalName)).getInternalName();
|
||||
}
|
||||
|
||||
public String[] mapTypes(String[] types) {
|
||||
String[] newTypes = null;
|
||||
boolean needMapping = false;
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
String type = types[i];
|
||||
String newType = map(type);
|
||||
if (newType != null && newTypes == null) {
|
||||
newTypes = new String[types.length];
|
||||
if (i > 0) {
|
||||
System.arraycopy(types, 0, newTypes, 0, i);
|
||||
/**
|
||||
* Returns the given internal names, remapped with {@link #map(String)}.
|
||||
*
|
||||
* @param internalNames the internal names (or array type descriptors) of some (array) classes.
|
||||
* @return the given internal name, remapped with {@link #map(String)}.
|
||||
*/
|
||||
public String[] mapTypes(final String[] internalNames) {
|
||||
String[] remappedInternalNames = null;
|
||||
for (int i = 0; i < internalNames.length; ++i) {
|
||||
String internalName = internalNames[i];
|
||||
String remappedInternalName = mapType(internalName);
|
||||
if (remappedInternalName != null) {
|
||||
if (remappedInternalNames == null) {
|
||||
remappedInternalNames = new String[internalNames.length];
|
||||
System.arraycopy(internalNames, 0, remappedInternalNames, 0, internalNames.length);
|
||||
}
|
||||
needMapping = true;
|
||||
}
|
||||
if (needMapping) {
|
||||
newTypes[i] = newType == null ? type : newType;
|
||||
remappedInternalNames[i] = remappedInternalName;
|
||||
}
|
||||
}
|
||||
return needMapping ? newTypes : types;
|
||||
return remappedInternalNames != null ? remappedInternalNames : internalNames;
|
||||
}
|
||||
|
||||
public String mapMethodDesc(String desc) {
|
||||
if ("()V".equals(desc)) {
|
||||
return desc;
|
||||
/**
|
||||
* Returns the given method descriptor, with its argument and return type descriptors remapped
|
||||
* with {@link #mapDesc(String)}.
|
||||
*
|
||||
* @param methodDescriptor a method descriptor.
|
||||
* @return the given method descriptor, with its argument and return type descriptors remapped
|
||||
* with {@link #mapDesc(String)}.
|
||||
*/
|
||||
public String mapMethodDesc(final String methodDescriptor) {
|
||||
if ("()V".equals(methodDescriptor)) {
|
||||
return methodDescriptor;
|
||||
}
|
||||
|
||||
Type[] args = Type.getArgumentTypes(desc);
|
||||
StringBuilder sb = new StringBuilder("(");
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
sb.append(mapDesc(args[i].getDescriptor()));
|
||||
StringBuilder stringBuilder = new StringBuilder("(");
|
||||
for (Type argumentType : Type.getArgumentTypes(methodDescriptor)) {
|
||||
stringBuilder.append(mapType(argumentType).getDescriptor());
|
||||
}
|
||||
Type returnType = Type.getReturnType(desc);
|
||||
Type returnType = Type.getReturnType(methodDescriptor);
|
||||
if (returnType == Type.VOID_TYPE) {
|
||||
sb.append(")V");
|
||||
return sb.toString();
|
||||
stringBuilder.append(")V");
|
||||
} else {
|
||||
stringBuilder.append(')').append(mapType(returnType).getDescriptor());
|
||||
}
|
||||
sb.append(')').append(mapDesc(returnType.getDescriptor()));
|
||||
return sb.toString();
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public Object mapValue(Object value) {
|
||||
/**
|
||||
* Returns the given value, remapped with this remapper. Possible values are {@link Boolean},
|
||||
* {@link Byte}, {@link Short}, {@link Character}, {@link Integer}, {@link Long}, {@link Double},
|
||||
* {@link Float}, {@link String}, {@link Type}, {@link Handle}, {@link ConstantDynamic} or arrays
|
||||
* of primitive types .
|
||||
*
|
||||
* @param value an object. Only {@link Type}, {@link Handle} and {@link ConstantDynamic} values
|
||||
* are remapped.
|
||||
* @return the given value, remapped with this remapper.
|
||||
*/
|
||||
public Object mapValue(final Object value) {
|
||||
if (value instanceof Type) {
|
||||
return mapType((Type) value);
|
||||
}
|
||||
if (value instanceof Handle) {
|
||||
Handle h = (Handle) value;
|
||||
return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
|
||||
h.getOwner(), h.getName(), h.getDesc()),
|
||||
mapMethodDesc(h.getDesc()), h.isInterface());
|
||||
Handle handle = (Handle) value;
|
||||
return new Handle(
|
||||
handle.getTag(),
|
||||
mapType(handle.getOwner()),
|
||||
mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
|
||||
handle.getTag() <= Opcodes.H_PUTSTATIC
|
||||
? mapDesc(handle.getDesc())
|
||||
: mapMethodDesc(handle.getDesc()),
|
||||
handle.isInterface());
|
||||
}
|
||||
if (value instanceof ConstantDynamic) {
|
||||
ConstantDynamic constantDynamic = (ConstantDynamic) value;
|
||||
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
|
||||
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArgumentCount];
|
||||
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
|
||||
remappedBootstrapMethodArguments[i] =
|
||||
mapValue(constantDynamic.getBootstrapMethodArgument(i));
|
||||
}
|
||||
String descriptor = constantDynamic.getDescriptor();
|
||||
return new ConstantDynamic(
|
||||
mapInvokeDynamicMethodName(constantDynamic.getName(), descriptor),
|
||||
mapDesc(descriptor),
|
||||
(Handle) mapValue(constantDynamic.getBootstrapMethod()),
|
||||
remappedBootstrapMethodArguments);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signature
|
||||
* signature for mapper
|
||||
* @param typeSignature
|
||||
* true if signature is a FieldTypeSignature, such as the
|
||||
* signature parameter of the ClassVisitor.visitField or
|
||||
* MethodVisitor.visitLocalVariable methods
|
||||
* @return signature rewritten as a string
|
||||
*/
|
||||
public String mapSignature(String signature, boolean typeSignature) {
|
||||
* Returns the given signature, remapped with the {@link SignatureVisitor} returned by {@link
|
||||
* #createSignatureRemapper(SignatureVisitor)}.
|
||||
*
|
||||
* @param signature a <i>JavaTypeSignature</i>, <i>ClassSignature</i> or <i>MethodSignature</i>.
|
||||
* @param typeSignature whether the given signature is a <i>JavaTypeSignature</i>.
|
||||
* @return signature the given signature, remapped with the {@link SignatureVisitor} returned by
|
||||
* {@link #createSignatureRemapper(SignatureVisitor)}.
|
||||
*/
|
||||
public String mapSignature(final String signature, final boolean typeSignature) {
|
||||
if (signature == null) {
|
||||
return null;
|
||||
}
|
||||
SignatureReader r = new SignatureReader(signature);
|
||||
SignatureWriter w = new SignatureWriter();
|
||||
SignatureVisitor a = createSignatureRemapper(w);
|
||||
SignatureReader signatureReader = new SignatureReader(signature);
|
||||
SignatureWriter signatureWriter = new SignatureWriter();
|
||||
SignatureVisitor signatureRemapper = createSignatureRemapper(signatureWriter);
|
||||
if (typeSignature) {
|
||||
r.acceptType(a);
|
||||
signatureReader.acceptType(signatureRemapper);
|
||||
} else {
|
||||
r.accept(a);
|
||||
signatureReader.accept(signatureRemapper);
|
||||
}
|
||||
return w.toString();
|
||||
return signatureWriter.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #createSignatureRemapper} instead.
|
||||
*/
|
||||
* Constructs a new remapper for signatures. The default implementation of this method returns a
|
||||
* new {@link SignatureRemapper}.
|
||||
*
|
||||
* @param signatureVisitor the SignatureVisitor the remapper must delegate to.
|
||||
* @return the newly created remapper.
|
||||
* @deprecated use {@link #createSignatureRemapper} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected SignatureVisitor createRemappingSignatureAdapter(
|
||||
SignatureVisitor v) {
|
||||
return new SignatureRemapper(v, this);
|
||||
}
|
||||
|
||||
protected SignatureVisitor createSignatureRemapper(
|
||||
SignatureVisitor v) {
|
||||
return createRemappingSignatureAdapter(v);
|
||||
final SignatureVisitor signatureVisitor) {
|
||||
return createSignatureRemapper(signatureVisitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map method name to the new name. Subclasses can override.
|
||||
*
|
||||
* @param owner
|
||||
* owner of the method.
|
||||
* @param name
|
||||
* name of the method.
|
||||
* @param desc
|
||||
* descriptor of the method.
|
||||
* @return new name of the method
|
||||
*/
|
||||
public String mapMethodName(String owner, String name, String desc) {
|
||||
* Constructs a new remapper for signatures. The default implementation of this method returns a
|
||||
* new {@link SignatureRemapper}.
|
||||
*
|
||||
* @param signatureVisitor the SignatureVisitor the remapper must delegate to.
|
||||
* @return the newly created remapper.
|
||||
*/
|
||||
protected SignatureVisitor createSignatureRemapper(final SignatureVisitor signatureVisitor) {
|
||||
return new SignatureRemapper(signatureVisitor, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps an inner class name to its new name. The default implementation of this method provides a
|
||||
* strategy that will work for inner classes produced by Java, but not necessarily other
|
||||
* languages. Subclasses can override.
|
||||
*
|
||||
* @param name the fully-qualified internal name of the inner class.
|
||||
* @param ownerName the internal name of the owner class of the inner class.
|
||||
* @param innerName the internal name of the inner class.
|
||||
* @return the new inner name of the inner class.
|
||||
*/
|
||||
public String mapInnerClassName(
|
||||
final String name, final String ownerName, final String innerName) {
|
||||
final String remappedInnerName = this.mapType(name);
|
||||
if (remappedInnerName.contains("$")) {
|
||||
return remappedInnerName.substring(remappedInnerName.lastIndexOf('$') + 1);
|
||||
} else {
|
||||
return innerName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a method name to its new name. The default implementation of this method returns the given
|
||||
* name, unchanged. Subclasses can override.
|
||||
*
|
||||
* @param owner the internal name of the owner class of the method.
|
||||
* @param name the name of the method.
|
||||
* @param descriptor the descriptor of the method.
|
||||
* @return the new name of the method.
|
||||
*/
|
||||
public String mapMethodName(final String owner, final String name, final String descriptor) {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map invokedynamic method name to the new name. Subclasses can override.
|
||||
*
|
||||
* @param name
|
||||
* name of the invokedynamic.
|
||||
* @param desc
|
||||
* descriptor of the invokedynamic.
|
||||
* @return new invokdynamic name.
|
||||
*/
|
||||
public String mapInvokeDynamicMethodName(String name, String desc) {
|
||||
* Maps an invokedynamic or a constant dynamic method name to its new name. The default
|
||||
* implementation of this method returns the given name, unchanged. Subclasses can override.
|
||||
*
|
||||
* @param name the name of the method.
|
||||
* @param descriptor the descriptor of the method.
|
||||
* @return the new name of the method.
|
||||
*/
|
||||
public String mapInvokeDynamicMethodName(final String name, final String descriptor) {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map field name to the new name. Subclasses can override.
|
||||
*
|
||||
* @param owner
|
||||
* owner of the field.
|
||||
* @param name
|
||||
* name of the field
|
||||
* @param desc
|
||||
* descriptor of the field
|
||||
* @return new name of the field.
|
||||
*/
|
||||
public String mapFieldName(String owner, String name, String desc) {
|
||||
* Maps a field name to its new name. The default implementation of this method returns the given
|
||||
* name, unchanged. Subclasses can override.
|
||||
*
|
||||
* @param owner the internal name of the owner class of the field.
|
||||
* @param name the name of the field.
|
||||
* @param descriptor the descriptor of the field.
|
||||
* @return the new name of the field.
|
||||
*/
|
||||
public String mapFieldName(final String owner, final String name, final String descriptor) {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map package name to the new name. Subclasses can override.
|
||||
*
|
||||
* @param name name of the package
|
||||
* @return new name of the package
|
||||
*/
|
||||
public String mapPackageName(String name) {
|
||||
String fakeName = map(name + ".FakeClassName");
|
||||
int index;
|
||||
return fakeName == null || (index = fakeName.lastIndexOf('.')) == -1 ? name: fakeName.substring(0, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map module name to the new name. Subclasses can override.
|
||||
*
|
||||
* @param name name of the module
|
||||
* @return new name of the module
|
||||
*/
|
||||
public String mapModuleName(String name) {
|
||||
* Maps a package name to its new name. The default implementation of this method returns the
|
||||
* given name, unchanged. Subclasses can override.
|
||||
*
|
||||
* @param name the fully qualified name of the package (using dots).
|
||||
* @return the new name of the package.
|
||||
*/
|
||||
public String mapPackageName(final String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map type name to the new name. Subclasses can override.
|
||||
*
|
||||
* @param typeName
|
||||
* the type name
|
||||
* @return new name, default implementation is the identity.
|
||||
*/
|
||||
public String map(String typeName) {
|
||||
return typeName;
|
||||
* Maps a module name to its new name. The default implementation of this method returns the given
|
||||
* name, unchanged. Subclasses can override.
|
||||
*
|
||||
* @param name the fully qualified name (using dots) of a module.
|
||||
* @return the new name of the module.
|
||||
*/
|
||||
public String mapModuleName(final String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the internal name of a class to its new name. The default implementation of this method
|
||||
* returns the given name, unchanged. Subclasses can override.
|
||||
*
|
||||
* @param internalName the internal name of a class.
|
||||
* @return the new internal name.
|
||||
*/
|
||||
public String map(final String internalName) {
|
||||
return internalName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
|
|
@ -73,38 +72,44 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor {
|
|||
|
||||
protected final Remapper remapper;
|
||||
|
||||
public RemappingAnnotationAdapter(final AnnotationVisitor av,
|
||||
final Remapper remapper) {
|
||||
this(Opcodes.ASM6, av, remapper);
|
||||
public RemappingAnnotationAdapter(
|
||||
final AnnotationVisitor annotationVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
protected RemappingAnnotationAdapter(final int api,
|
||||
final AnnotationVisitor av, final Remapper remapper) {
|
||||
super(api, av);
|
||||
protected RemappingAnnotationAdapter(
|
||||
final int api, final AnnotationVisitor annotationVisitor, final Remapper remapper) {
|
||||
super(api, annotationVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(String name, Object value) {
|
||||
public void visit(final String name, final Object value) {
|
||||
av.visit(name, remapper.mapValue(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(String name, String desc, String value) {
|
||||
av.visitEnum(name, remapper.mapDesc(desc), value);
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
av.visitEnum(name, remapper.mapDesc(descriptor), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc) {
|
||||
AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
|
||||
return v == null ? null : (v == av ? this
|
||||
: new RemappingAnnotationAdapter(v, remapper));
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
AnnotationVisitor annotationVisitor = av.visitAnnotation(name, remapper.mapDesc(descriptor));
|
||||
return annotationVisitor == null
|
||||
? null
|
||||
: (annotationVisitor == av
|
||||
? this
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
AnnotationVisitor v = av.visitArray(name);
|
||||
return v == null ? null : (v == av ? this
|
||||
: new RemappingAnnotationAdapter(v, remapper));
|
||||
public AnnotationVisitor visitArray(final String name) {
|
||||
AnnotationVisitor annotationVisitor = av.visitArray(name);
|
||||
return annotationVisitor == null
|
||||
? null
|
||||
: (annotationVisitor == av
|
||||
? this
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
|
|
@ -80,93 +79,119 @@ public class RemappingClassAdapter extends ClassVisitor {
|
|||
|
||||
protected String className;
|
||||
|
||||
public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, cv, remapper);
|
||||
public RemappingClassAdapter(final ClassVisitor classVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, classVisitor, remapper);
|
||||
}
|
||||
|
||||
protected RemappingClassAdapter(final int api, final ClassVisitor cv,
|
||||
final Remapper remapper) {
|
||||
super(api, cv);
|
||||
protected RemappingClassAdapter(
|
||||
final int api, final ClassVisitor classVisitor, final Remapper remapper) {
|
||||
super(api, classVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature,
|
||||
String superName, String[] interfaces) {
|
||||
public void visit(
|
||||
final int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces) {
|
||||
this.className = name;
|
||||
super.visit(version, access, remapper.mapType(name), remapper
|
||||
.mapSignature(signature, false), remapper.mapType(superName),
|
||||
super.visit(
|
||||
version,
|
||||
access,
|
||||
remapper.mapType(name),
|
||||
remapper.mapSignature(signature, false),
|
||||
remapper.mapType(superName),
|
||||
interfaces == null ? null : remapper.mapTypes(interfaces));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleVisitor visitModule(String name, int flags, String version) {
|
||||
public ModuleVisitor visitModule(final String name, final int flags, final String version) {
|
||||
throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
|
||||
visible);
|
||||
return av == null ? null : createRemappingAnnotationAdapter(av);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitAnnotation(remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null ? null : createRemappingAnnotationAdapter(annotationVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? null : createRemappingAnnotationAdapter(av);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null ? null : createRemappingAnnotationAdapter(annotationVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc,
|
||||
String signature, Object value) {
|
||||
FieldVisitor fv = super.visitField(access,
|
||||
remapper.mapFieldName(className, name, desc),
|
||||
remapper.mapDesc(desc), remapper.mapSignature(signature, true),
|
||||
remapper.mapValue(value));
|
||||
return fv == null ? null : createRemappingFieldAdapter(fv);
|
||||
public FieldVisitor visitField(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
FieldVisitor fieldVisitor =
|
||||
super.visitField(
|
||||
access,
|
||||
remapper.mapFieldName(className, name, descriptor),
|
||||
remapper.mapDesc(descriptor),
|
||||
remapper.mapSignature(signature, true),
|
||||
remapper.mapValue(value));
|
||||
return fieldVisitor == null ? null : createRemappingFieldAdapter(fieldVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions) {
|
||||
String newDesc = remapper.mapMethodDesc(desc);
|
||||
MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
|
||||
className, name, desc), newDesc, remapper.mapSignature(
|
||||
signature, false),
|
||||
exceptions == null ? null : remapper.mapTypes(exceptions));
|
||||
return mv == null ? null : createRemappingMethodAdapter(access,
|
||||
newDesc, mv);
|
||||
public MethodVisitor visitMethod(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
String newDescriptor = remapper.mapMethodDesc(descriptor);
|
||||
MethodVisitor methodVisitor =
|
||||
super.visitMethod(
|
||||
access,
|
||||
remapper.mapMethodName(className, name, descriptor),
|
||||
newDescriptor,
|
||||
remapper.mapSignature(signature, false),
|
||||
exceptions == null ? null : remapper.mapTypes(exceptions));
|
||||
return methodVisitor == null
|
||||
? null
|
||||
: createRemappingMethodAdapter(access, newDescriptor, methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName,
|
||||
String innerName, int access) {
|
||||
// TODO should innerName be changed?
|
||||
super.visitInnerClass(remapper.mapType(name), outerName == null ? null
|
||||
: remapper.mapType(outerName), innerName, access);
|
||||
public void visitInnerClass(
|
||||
final String name, final String outerName, final String innerName, final int access) {
|
||||
super.visitInnerClass(
|
||||
remapper.mapType(name),
|
||||
outerName == null ? null : remapper.mapType(outerName),
|
||||
innerName,
|
||||
access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(String owner, String name, String desc) {
|
||||
super.visitOuterClass(remapper.mapType(owner), name == null ? null
|
||||
: remapper.mapMethodName(owner, name, desc),
|
||||
desc == null ? null : remapper.mapMethodDesc(desc));
|
||||
public void visitOuterClass(final String owner, final String name, final String descriptor) {
|
||||
super.visitOuterClass(
|
||||
remapper.mapType(owner),
|
||||
name == null ? null : remapper.mapMethodName(owner, name, descriptor),
|
||||
descriptor == null ? null : remapper.mapMethodDesc(descriptor));
|
||||
}
|
||||
|
||||
protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
|
||||
return new RemappingFieldAdapter(fv, remapper);
|
||||
protected FieldVisitor createRemappingFieldAdapter(final FieldVisitor fieldVisitor) {
|
||||
return new RemappingFieldAdapter(fieldVisitor, remapper);
|
||||
}
|
||||
|
||||
protected MethodVisitor createRemappingMethodAdapter(int access,
|
||||
String newDesc, MethodVisitor mv) {
|
||||
return new RemappingMethodAdapter(access, newDesc, mv, remapper);
|
||||
protected MethodVisitor createRemappingMethodAdapter(
|
||||
final int access, final String newDescriptor, final MethodVisitor methodVisitior) {
|
||||
return new RemappingMethodAdapter(access, newDescriptor, methodVisitior, remapper);
|
||||
}
|
||||
|
||||
protected AnnotationVisitor createRemappingAnnotationAdapter(
|
||||
AnnotationVisitor av) {
|
||||
protected AnnotationVisitor createRemappingAnnotationAdapter(final AnnotationVisitor av) {
|
||||
return new RemappingAnnotationAdapter(av, remapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
|
|
@ -75,28 +74,31 @@ public class RemappingFieldAdapter extends FieldVisitor {
|
|||
|
||||
private final Remapper remapper;
|
||||
|
||||
public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, fv, remapper);
|
||||
public RemappingFieldAdapter(final FieldVisitor fieldVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, fieldVisitor, remapper);
|
||||
}
|
||||
|
||||
protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
|
||||
final Remapper remapper) {
|
||||
super(api, fv);
|
||||
protected RemappingFieldAdapter(
|
||||
final int api, final FieldVisitor fieldVisitor, final Remapper remapper) {
|
||||
super(api, fieldVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
|
||||
visible);
|
||||
return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor = fv.visitAnnotation(remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? null
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? null
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
|
|
@ -77,105 +76,130 @@ public class RemappingMethodAdapter extends LocalVariablesSorter {
|
|||
|
||||
protected final Remapper remapper;
|
||||
|
||||
public RemappingMethodAdapter(final int access, final String desc,
|
||||
final MethodVisitor mv, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, access, desc, mv, remapper);
|
||||
public RemappingMethodAdapter(
|
||||
final int access,
|
||||
final String descriptor,
|
||||
final MethodVisitor methodVisitor,
|
||||
final Remapper remapper) {
|
||||
this(Opcodes.ASM6, access, descriptor, methodVisitor, remapper);
|
||||
}
|
||||
|
||||
protected RemappingMethodAdapter(final int api, final int access,
|
||||
final String desc, final MethodVisitor mv, final Remapper remapper) {
|
||||
super(api, access, desc, mv);
|
||||
protected RemappingMethodAdapter(
|
||||
final int api,
|
||||
final int access,
|
||||
final String descriptor,
|
||||
final MethodVisitor methodVisitor,
|
||||
final Remapper remapper) {
|
||||
super(api, access, descriptor, methodVisitor);
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotationDefault() {
|
||||
AnnotationVisitor av = super.visitAnnotationDefault();
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
AnnotationVisitor annotationVisitor = super.visitAnnotationDefault();
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
|
||||
visible);
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitAnnotation(remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTypeAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitParameterAnnotation(int parameter,
|
||||
String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitParameterAnnotation(parameter,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitParameterAnnotation(
|
||||
final int parameter, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitParameterAnnotation(parameter, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack,
|
||||
Object[] stack) {
|
||||
super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
|
||||
remapEntries(nStack, stack));
|
||||
public void visitFrame(
|
||||
final int type,
|
||||
final int numLocal,
|
||||
final Object[] local,
|
||||
final int numStack,
|
||||
final Object[] stack) {
|
||||
super.visitFrame(
|
||||
type, numLocal, remapEntries(numLocal, local), numStack, remapEntries(numStack, stack));
|
||||
}
|
||||
|
||||
private Object[] remapEntries(int n, Object[] entries) {
|
||||
if (entries != null) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (entries[i] instanceof String) {
|
||||
Object[] newEntries = new Object[n];
|
||||
if (i > 0) {
|
||||
System.arraycopy(entries, 0, newEntries, 0, i);
|
||||
}
|
||||
do {
|
||||
Object t = entries[i];
|
||||
newEntries[i++] = t instanceof String ? remapper
|
||||
.mapType((String) t) : t;
|
||||
} while (i < n);
|
||||
return newEntries;
|
||||
private Object[] remapEntries(final int numTypes, final Object[] entries) {
|
||||
if (entries == null) {
|
||||
return entries;
|
||||
}
|
||||
Object[] remappedEntries = null;
|
||||
for (int i = 0; i < numTypes; ++i) {
|
||||
if (entries[i] instanceof String) {
|
||||
if (remappedEntries == null) {
|
||||
remappedEntries = new Object[numTypes];
|
||||
System.arraycopy(entries, 0, remappedEntries, 0, numTypes);
|
||||
}
|
||||
remappedEntries[i] = remapper.mapType((String) entries[i]);
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
return remappedEntries == null ? entries : remappedEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name,
|
||||
String desc) {
|
||||
super.visitFieldInsn(opcode, remapper.mapType(owner),
|
||||
remapper.mapFieldName(owner, name, desc),
|
||||
remapper.mapDesc(desc));
|
||||
public void visitFieldInsn(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
super.visitFieldInsn(
|
||||
opcode,
|
||||
remapper.mapType(owner),
|
||||
remapper.mapFieldName(owner, name, descriptor),
|
||||
remapper.mapDesc(descriptor));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
public void visitMethodInsn(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
if (api >= Opcodes.ASM5) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor);
|
||||
return;
|
||||
}
|
||||
doVisitMethodInsn(opcode, owner, name, desc,
|
||||
opcode == Opcodes.INVOKEINTERFACE);
|
||||
doVisitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc, final boolean itf) {
|
||||
public void visitMethodInsn(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
if (api < Opcodes.ASM5) {
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
return;
|
||||
}
|
||||
doVisitMethodInsn(opcode, owner, name, desc, itf);
|
||||
doVisitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
}
|
||||
|
||||
private void doVisitMethodInsn(int opcode, String owner, String name,
|
||||
String desc, boolean itf) {
|
||||
private void doVisitMethodInsn(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
// Calling super.visitMethodInsn requires to call the correct version
|
||||
// depending on this.api (otherwise infinite loops can occur). To
|
||||
// simplify and to make it easier to automatically remove the backward
|
||||
|
|
@ -183,75 +207,103 @@ public class RemappingMethodAdapter extends LocalVariablesSorter {
|
|||
// IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
|
||||
// LocalVariableSorter.
|
||||
if (mv != null) {
|
||||
mv.visitMethodInsn(opcode, remapper.mapType(owner),
|
||||
remapper.mapMethodName(owner, name, desc),
|
||||
remapper.mapMethodDesc(desc), itf);
|
||||
mv.visitMethodInsn(
|
||||
opcode,
|
||||
remapper.mapType(owner),
|
||||
remapper.mapMethodName(owner, name, descriptor),
|
||||
remapper.mapMethodDesc(descriptor),
|
||||
isInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
|
||||
Object... bsmArgs) {
|
||||
for (int i = 0; i < bsmArgs.length; i++) {
|
||||
bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
|
||||
public void visitInvokeDynamicInsn(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final Handle bootstrapMethodHandle,
|
||||
final Object... bootstrapMethodArguments) {
|
||||
for (int i = 0; i < bootstrapMethodArguments.length; i++) {
|
||||
bootstrapMethodArguments[i] = remapper.mapValue(bootstrapMethodArguments[i]);
|
||||
}
|
||||
super.visitInvokeDynamicInsn(
|
||||
remapper.mapInvokeDynamicMethodName(name, desc),
|
||||
remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
|
||||
bsmArgs);
|
||||
remapper.mapInvokeDynamicMethodName(name, descriptor),
|
||||
remapper.mapMethodDesc(descriptor),
|
||||
(Handle) remapper.mapValue(bootstrapMethodHandle),
|
||||
bootstrapMethodArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
public void visitTypeInsn(final int opcode, final String type) {
|
||||
super.visitTypeInsn(opcode, remapper.mapType(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object cst) {
|
||||
super.visitLdcInsn(remapper.mapValue(cst));
|
||||
public void visitLdcInsn(final Object value) {
|
||||
super.visitLdcInsn(remapper.mapValue(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMultiANewArrayInsn(String desc, int dims) {
|
||||
super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
|
||||
public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
|
||||
super.visitMultiANewArrayInsn(remapper.mapDesc(descriptor), numDimensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitInsnAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitInsnAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTryCatchBlock(Label start, Label end, Label handler,
|
||||
String type) {
|
||||
super.visitTryCatchBlock(start, end, handler, type == null ? null
|
||||
: remapper.mapType(type));
|
||||
public void visitTryCatchBlock(
|
||||
final Label start, final Label end, final Label handler, final String type) {
|
||||
super.visitTryCatchBlock(start, end, handler, type == null ? null : remapper.mapType(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
|
||||
remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitTryCatchAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitTryCatchAnnotation(typeRef, typePath, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(String name, String desc, String signature,
|
||||
Label start, Label end, int index) {
|
||||
super.visitLocalVariable(name, remapper.mapDesc(desc),
|
||||
remapper.mapSignature(signature, true), start, end, index);
|
||||
public void visitLocalVariable(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Label start,
|
||||
final Label end,
|
||||
final int index) {
|
||||
super.visitLocalVariable(
|
||||
name,
|
||||
remapper.mapDesc(descriptor),
|
||||
remapper.mapSignature(signature, true),
|
||||
start,
|
||||
end,
|
||||
index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
||||
TypePath typePath, Label[] start, Label[] end, int[] index,
|
||||
String desc, boolean visible) {
|
||||
AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
|
||||
typePath, start, end, index, remapper.mapDesc(desc), visible);
|
||||
return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(
|
||||
final int typeRef,
|
||||
final TypePath typePath,
|
||||
final Label[] start,
|
||||
final Label[] end,
|
||||
final int[] index,
|
||||
final String descriptor,
|
||||
final boolean visible) {
|
||||
AnnotationVisitor annotationVisitor =
|
||||
super.visitLocalVariableAnnotation(
|
||||
typeRef, typePath, start, end, index, remapper.mapDesc(descriptor), visible);
|
||||
return annotationVisitor == null
|
||||
? annotationVisitor
|
||||
: new RemappingAnnotationAdapter(annotationVisitor, remapper);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
|
@ -71,116 +70,118 @@ import jdk.internal.org.objectweb.asm.signature.SignatureVisitor;
|
|||
@Deprecated
|
||||
public class RemappingSignatureAdapter extends SignatureVisitor {
|
||||
|
||||
private final SignatureVisitor v;
|
||||
private final SignatureVisitor signatureVisitor;
|
||||
|
||||
private final Remapper remapper;
|
||||
|
||||
private String className;
|
||||
|
||||
public RemappingSignatureAdapter(final SignatureVisitor v,
|
||||
final Remapper remapper) {
|
||||
this(Opcodes.ASM6, v, remapper);
|
||||
public RemappingSignatureAdapter(
|
||||
final SignatureVisitor signatureVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, signatureVisitor, remapper);
|
||||
}
|
||||
|
||||
protected RemappingSignatureAdapter(final int api,
|
||||
final SignatureVisitor v, final Remapper remapper) {
|
||||
protected RemappingSignatureAdapter(
|
||||
final int api, final SignatureVisitor signatureVisitor, final Remapper remapper) {
|
||||
super(api);
|
||||
this.v = v;
|
||||
this.signatureVisitor = signatureVisitor;
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
public void visitClassType(final String name) {
|
||||
className = name;
|
||||
v.visitClassType(remapper.mapType(name));
|
||||
signatureVisitor.visitClassType(remapper.mapType(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name) {
|
||||
public void visitInnerClassType(final String name) {
|
||||
String remappedOuter = remapper.mapType(className) + '$';
|
||||
className = className + '$' + name;
|
||||
String remappedName = remapper.mapType(className);
|
||||
int index = remappedName.startsWith(remappedOuter) ? remappedOuter
|
||||
.length() : remappedName.lastIndexOf('$') + 1;
|
||||
v.visitInnerClassType(remappedName.substring(index));
|
||||
int index =
|
||||
remappedName.startsWith(remappedOuter)
|
||||
? remappedOuter.length()
|
||||
: remappedName.lastIndexOf('$') + 1;
|
||||
signatureVisitor.visitInnerClassType(remappedName.substring(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
v.visitFormalTypeParameter(name);
|
||||
public void visitFormalTypeParameter(final String name) {
|
||||
signatureVisitor.visitFormalTypeParameter(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name) {
|
||||
v.visitTypeVariable(name);
|
||||
public void visitTypeVariable(final String name) {
|
||||
signatureVisitor.visitTypeVariable(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
v.visitArrayType();
|
||||
signatureVisitor.visitArrayType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
v.visitBaseType(descriptor);
|
||||
public void visitBaseType(final char descriptor) {
|
||||
signatureVisitor.visitBaseType(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitClassBound() {
|
||||
v.visitClassBound();
|
||||
signatureVisitor.visitClassBound();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
v.visitExceptionType();
|
||||
signatureVisitor.visitExceptionType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterface() {
|
||||
v.visitInterface();
|
||||
signatureVisitor.visitInterface();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
v.visitInterfaceBound();
|
||||
signatureVisitor.visitInterfaceBound();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
v.visitParameterType();
|
||||
signatureVisitor.visitParameterType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitReturnType() {
|
||||
v.visitReturnType();
|
||||
signatureVisitor.visitReturnType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
v.visitSuperclass();
|
||||
signatureVisitor.visitSuperclass();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
v.visitTypeArgument();
|
||||
signatureVisitor.visitTypeArgument();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
v.visitTypeArgument(wildcard);
|
||||
public SignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
signatureVisitor.visitTypeArgument(wildcard);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
v.visitEnd();
|
||||
signatureVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,252 +63,240 @@ import java.io.DataOutput;
|
|||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import java.util.Comparator;
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
import jdk.internal.org.objectweb.asm.FieldVisitor;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A {@link ClassVisitor} that adds a serial version unique identifier to a
|
||||
* class if missing. Here is typical usage of this class:
|
||||
* A {@link ClassVisitor} that adds a serial version unique identifier to a class if missing. A
|
||||
* typical usage of this class is:
|
||||
*
|
||||
* <pre>
|
||||
* ClassWriter cw = new ClassWriter(...);
|
||||
* ClassVisitor sv = new SerialVersionUIDAdder(cw);
|
||||
* ClassVisitor ca = new MyClassAdapter(sv);
|
||||
* new ClassReader(orginalClass).accept(ca, false);
|
||||
* ClassWriter classWriter = new ClassWriter(...);
|
||||
* ClassVisitor svuidAdder = new SerialVersionUIDAdder(classWriter);
|
||||
* ClassVisitor classVisitor = new MyClassAdapter(svuidAdder);
|
||||
* new ClassReader(orginalClass).accept(classVisitor, 0);
|
||||
* </pre>
|
||||
*
|
||||
* The SVUID algorithm can be found <a href=
|
||||
* "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
|
||||
* >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
|
||||
* <p>The SVUID algorithm can be found at <a href=
|
||||
* "https://docs.oracle.com/javase/10/docs/specs/serialization/class.html#stream-unique-identifiers"
|
||||
* >https://docs.oracle.com/javase/10/docs/specs/serialization/class.html#stream-unique-identifiers</a>:
|
||||
*
|
||||
* <pre>
|
||||
* The serialVersionUID is computed using the signature of a stream of bytes
|
||||
* that reflect the class definition. The National Institute of Standards and
|
||||
* Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
|
||||
* signature for the stream. The first two 32-bit quantities are used to form a
|
||||
* 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
|
||||
* types to a sequence of bytes. The values input to the stream are defined by
|
||||
* the Java Virtual Machine (VM) specification for classes.
|
||||
* <p>The serialVersionUID is computed using the signature of a stream of bytes that reflect the
|
||||
* class definition. The National Institute of Standards and Technology (NIST) Secure Hash Algorithm
|
||||
* (SHA-1) is used to compute a signature for the stream. The first two 32-bit quantities are used
|
||||
* to form a 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data types to a
|
||||
* sequence of bytes. The values input to the stream are defined by the Java Virtual Machine (VM)
|
||||
* specification for classes.
|
||||
*
|
||||
* The sequence of items in the stream is as follows:
|
||||
* <p>The sequence of items in the stream is as follows:
|
||||
*
|
||||
* 1. The class name written using UTF encoding.
|
||||
* 2. The class modifiers written as a 32-bit integer.
|
||||
* 3. The name of each interface sorted by name written using UTF encoding.
|
||||
* 4. For each field of the class sorted by field name (except private static
|
||||
* and private transient fields):
|
||||
* 1. The name of the field in UTF encoding.
|
||||
* 2. The modifiers of the field written as a 32-bit integer.
|
||||
* 3. The descriptor of the field in UTF encoding
|
||||
* 5. If a class initializer exists, write out the following:
|
||||
* 1. The name of the method, <clinit>, in UTF encoding.
|
||||
* 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
|
||||
* written as a 32-bit integer.
|
||||
* 3. The descriptor of the method, ()V, in UTF encoding.
|
||||
* 6. For each non-private constructor sorted by method name and signature:
|
||||
* 1. The name of the method, <init>, in UTF encoding.
|
||||
* 2. The modifiers of the method written as a 32-bit integer.
|
||||
* 3. The descriptor of the method in UTF encoding.
|
||||
* 7. For each non-private method sorted by method name and signature:
|
||||
* 1. The name of the method in UTF encoding.
|
||||
* 2. The modifiers of the method written as a 32-bit integer.
|
||||
* 3. The descriptor of the method in UTF encoding.
|
||||
* 8. The SHA-1 algorithm is executed on the stream of bytes produced by
|
||||
* DataOutputStream and produces five 32-bit values sha[0..4].
|
||||
*
|
||||
* 9. The hash value is assembled from the first and second 32-bit values of
|
||||
* the SHA-1 message digest. If the result of the message digest, the five
|
||||
* 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
|
||||
* sha, the hash value would be computed as follows:
|
||||
*
|
||||
* long hash = ((sha[0] >>> 24) & 0xFF) |
|
||||
* ((sha[0] >>> 16) & 0xFF) << 8 |
|
||||
* ((sha[0] >>> 8) & 0xFF) << 16 |
|
||||
* ((sha[0] >>> 0) & 0xFF) << 24 |
|
||||
* ((sha[1] >>> 24) & 0xFF) << 32 |
|
||||
* ((sha[1] >>> 16) & 0xFF) << 40 |
|
||||
* ((sha[1] >>> 8) & 0xFF) << 48 |
|
||||
* ((sha[1] >>> 0) & 0xFF) << 56;
|
||||
* </pre>
|
||||
* <ol>
|
||||
* <li>The class name written using UTF encoding.
|
||||
* <li>The class modifiers written as a 32-bit integer.
|
||||
* <li>The name of each interface sorted by name written using UTF encoding.
|
||||
* <li>For each field of the class sorted by field name (except private static and private
|
||||
* transient fields):
|
||||
* <ol>
|
||||
* <li>The name of the field in UTF encoding.
|
||||
* <li>The modifiers of the field written as a 32-bit integer.
|
||||
* <li>The descriptor of the field in UTF encoding
|
||||
* </ol>
|
||||
* <li>If a class initializer exists, write out the following:
|
||||
* <ol>
|
||||
* <li>The name of the method, <clinit>, in UTF encoding.
|
||||
* <li>The modifier of the method, STATIC, written as a 32-bit integer.
|
||||
* <li>The descriptor of the method, ()V, in UTF encoding.
|
||||
* </ol>
|
||||
* <li>For each non-private constructor sorted by method name and signature:
|
||||
* <ol>
|
||||
* <li>The name of the method, <init>, in UTF encoding.
|
||||
* <li>The modifiers of the method written as a 32-bit integer.
|
||||
* <li>The descriptor of the method in UTF encoding.
|
||||
* </ol>
|
||||
* <li>For each non-private method sorted by method name and signature:
|
||||
* <ol>
|
||||
* <li>The name of the method in UTF encoding.
|
||||
* <li>The modifiers of the method written as a 32-bit integer.
|
||||
* <li>The descriptor of the method in UTF encoding.
|
||||
* </ol>
|
||||
* <li>The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and
|
||||
* produces five 32-bit values sha[0..4].
|
||||
* <li>The hash value is assembled from the first and second 32-bit values of the SHA-1 message
|
||||
* digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an
|
||||
* array of five int values named sha, the hash value would be computed as follows: long hash
|
||||
* = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) << 8
|
||||
* | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF)
|
||||
* << 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16)
|
||||
* & 0xFF) << 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1]
|
||||
* >>> 0) & 0xFF) << 56;
|
||||
* </ol>
|
||||
*
|
||||
* @author Rajendra Inamdar, Vishal Vishnoi
|
||||
*/
|
||||
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
|
||||
public class SerialVersionUIDAdder extends ClassVisitor {
|
||||
|
||||
/**
|
||||
* Flag that indicates if we need to compute SVUID.
|
||||
*/
|
||||
private boolean computeSVUID;
|
||||
/** The JVM name of static initializer methods. */
|
||||
private static final String CLINIT = "<clinit>";
|
||||
|
||||
/**
|
||||
* Set to true if the class already has SVUID.
|
||||
*/
|
||||
private boolean hasSVUID;
|
||||
/** A flag that indicates if we need to compute SVUID. */
|
||||
private boolean computeSvuid;
|
||||
|
||||
/**
|
||||
* Classes access flags.
|
||||
*/
|
||||
/** Whether the class already has a SVUID. */
|
||||
private boolean hasSvuid;
|
||||
|
||||
/** The class access flags. */
|
||||
private int access;
|
||||
|
||||
/**
|
||||
* Internal name of the class
|
||||
*/
|
||||
/** The internal name of the class. */
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Interfaces implemented by the class.
|
||||
*/
|
||||
/** The interfaces implemented by the class. */
|
||||
private String[] interfaces;
|
||||
|
||||
/**
|
||||
* Collection of fields. (except private static and private transient
|
||||
* fields)
|
||||
*/
|
||||
/** The fields of the class that are needed to compute the SVUID. */
|
||||
private Collection<Item> svuidFields;
|
||||
|
||||
/**
|
||||
* Set to true if the class has static initializer.
|
||||
*/
|
||||
/** Whether the class has a static initializer. */
|
||||
private boolean hasStaticInitializer;
|
||||
|
||||
/**
|
||||
* Collection of non-private constructors.
|
||||
*/
|
||||
/** The constructors of the class that are needed to compute the SVUID. */
|
||||
private Collection<Item> svuidConstructors;
|
||||
|
||||
/**
|
||||
* Collection of non-private methods.
|
||||
*/
|
||||
/** The methods of the class that are needed to compute the SVUID. */
|
||||
private Collection<Item> svuidMethods;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
|
||||
* this constructor</i>. Instead, they must use the
|
||||
* {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
|
||||
*
|
||||
* @param cv
|
||||
* a {@link ClassVisitor} to which this visitor will delegate
|
||||
* calls.
|
||||
* @throws IllegalStateException
|
||||
* If a subclass calls this constructor.
|
||||
*/
|
||||
public SerialVersionUIDAdder(final ClassVisitor cv) {
|
||||
this(Opcodes.ASM6, cv);
|
||||
* Constructs a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the {@link #SerialVersionUIDAdder(int, ClassVisitor)}
|
||||
* version.
|
||||
*
|
||||
* @param classVisitor a {@link ClassVisitor} to which this visitor will delegate calls.
|
||||
* @throws IllegalStateException If a subclass calls this constructor.
|
||||
*/
|
||||
public SerialVersionUIDAdder(final ClassVisitor classVisitor) {
|
||||
this(Opcodes.ASM7, classVisitor);
|
||||
if (getClass() != SerialVersionUIDAdder.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SerialVersionUIDAdder}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param cv
|
||||
* a {@link ClassVisitor} to which this visitor will delegate
|
||||
* calls.
|
||||
*/
|
||||
protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
|
||||
super(api, cv);
|
||||
svuidFields = new ArrayList<Item>();
|
||||
svuidConstructors = new ArrayList<Item>();
|
||||
svuidMethods = new ArrayList<Item>();
|
||||
* Constructs a new {@link SerialVersionUIDAdder}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param classVisitor a {@link ClassVisitor} to which this visitor will delegate calls.
|
||||
*/
|
||||
protected SerialVersionUIDAdder(final int api, final ClassVisitor classVisitor) {
|
||||
super(api, classVisitor);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Overridden methods
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Visit class header and get class name, access , and interfaces
|
||||
* information (step 1,2, and 3) for SVUID computation.
|
||||
*/
|
||||
@Override
|
||||
public void visit(final int version, final int access, final String name,
|
||||
final String signature, final String superName,
|
||||
public void visit(
|
||||
final int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces) {
|
||||
computeSVUID = (access & Opcodes.ACC_ENUM) == 0;
|
||||
// Get the class name, access flags, and interfaces information (step 1, 2 and 3) for SVUID
|
||||
// computation.
|
||||
computeSvuid = (access & Opcodes.ACC_ENUM) == 0;
|
||||
|
||||
if (computeSVUID) {
|
||||
if (computeSvuid) {
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
this.interfaces = new String[interfaces.length];
|
||||
System.arraycopy(interfaces, 0, this.interfaces, 0,
|
||||
interfaces.length);
|
||||
this.svuidFields = new ArrayList<Item>();
|
||||
this.svuidConstructors = new ArrayList<Item>();
|
||||
this.svuidMethods = new ArrayList<Item>();
|
||||
System.arraycopy(interfaces, 0, this.interfaces, 0, interfaces.length);
|
||||
}
|
||||
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
/*
|
||||
* Visit the methods and get constructor and method information (step 5 and
|
||||
* 7). Also determine if there is a class initializer (step 6).
|
||||
*/
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access, final String name,
|
||||
final String desc, final String signature, final String[] exceptions) {
|
||||
if (computeSVUID) {
|
||||
if ("<clinit>".equals(name)) {
|
||||
public MethodVisitor visitMethod(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
// Get constructor and method information (step 5 and 7). Also determine if there is a class
|
||||
// initializer (step 6).
|
||||
if (computeSvuid) {
|
||||
if (CLINIT.equals(name)) {
|
||||
hasStaticInitializer = true;
|
||||
}
|
||||
/*
|
||||
* Remembers non private constructors and methods for SVUID
|
||||
* computation For constructor and method modifiers, only the
|
||||
* ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
|
||||
* ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
|
||||
* are used.
|
||||
*/
|
||||
int mods = access
|
||||
& (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
|
||||
| Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
|
||||
| Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
|
||||
| Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
|
||||
// Collect the non private constructors and methods. Only the ACC_PUBLIC, ACC_PRIVATE,
|
||||
// ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and
|
||||
// ACC_STRICT flags are used.
|
||||
int mods =
|
||||
access
|
||||
& (Opcodes.ACC_PUBLIC
|
||||
| Opcodes.ACC_PRIVATE
|
||||
| Opcodes.ACC_PROTECTED
|
||||
| Opcodes.ACC_STATIC
|
||||
| Opcodes.ACC_FINAL
|
||||
| Opcodes.ACC_SYNCHRONIZED
|
||||
| Opcodes.ACC_NATIVE
|
||||
| Opcodes.ACC_ABSTRACT
|
||||
| Opcodes.ACC_STRICT);
|
||||
|
||||
// all non private methods
|
||||
if ((access & Opcodes.ACC_PRIVATE) == 0) {
|
||||
if ("<init>".equals(name)) {
|
||||
svuidConstructors.add(new Item(name, mods, desc));
|
||||
} else if (!"<clinit>".equals(name)) {
|
||||
svuidMethods.add(new Item(name, mods, desc));
|
||||
svuidConstructors.add(new Item(name, mods, descriptor));
|
||||
} else if (!CLINIT.equals(name)) {
|
||||
svuidMethods.add(new Item(name, mods, descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.visitMethod(access, name, desc, signature, exceptions);
|
||||
return super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets class field information for step 4 of the algorithm. Also determines
|
||||
* if the class already has a SVUID.
|
||||
*/
|
||||
@Override
|
||||
public FieldVisitor visitField(final int access, final String name,
|
||||
final String desc, final String signature, final Object value) {
|
||||
if (computeSVUID) {
|
||||
public FieldVisitor visitField(
|
||||
final int access,
|
||||
final String name,
|
||||
final String desc,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
// Get the class field information for step 4 of the algorithm. Also determine if the class
|
||||
// already has a SVUID.
|
||||
if (computeSvuid) {
|
||||
if ("serialVersionUID".equals(name)) {
|
||||
// since the class already has SVUID, we won't be computing it.
|
||||
computeSVUID = false;
|
||||
hasSVUID = true;
|
||||
// Since the class already has SVUID, we won't be computing it.
|
||||
computeSvuid = false;
|
||||
hasSvuid = true;
|
||||
}
|
||||
/*
|
||||
* Remember field for SVUID computation For field modifiers, only
|
||||
* the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
|
||||
* ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
|
||||
* computing serialVersionUID values.
|
||||
*/
|
||||
// Collect the non private fields. Only the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED,
|
||||
// ACC_STATIC, ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when computing
|
||||
// serialVersionUID values.
|
||||
if ((access & Opcodes.ACC_PRIVATE) == 0
|
||||
|| (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
|
||||
int mods = access
|
||||
& (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
|
||||
| Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
|
||||
| Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
|
||||
int mods =
|
||||
access
|
||||
& (Opcodes.ACC_PUBLIC
|
||||
| Opcodes.ACC_PRIVATE
|
||||
| Opcodes.ACC_PROTECTED
|
||||
| Opcodes.ACC_STATIC
|
||||
| Opcodes.ACC_FINAL
|
||||
| Opcodes.ACC_VOLATILE
|
||||
| Opcodes.ACC_TRANSIENT);
|
||||
svuidFields.add(new Item(name, mods, desc));
|
||||
}
|
||||
}
|
||||
|
|
@ -316,175 +304,150 @@ public class SerialVersionUIDAdder extends ClassVisitor {
|
|||
return super.visitField(access, name, desc, signature, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a bizarre special case. Nested classes (static classes declared
|
||||
* inside another class) that are protected have their access bit set to
|
||||
* public in their class files to deal with some odd reflection situation.
|
||||
* Our SVUID computation must do as the JVM does and ignore access bits in
|
||||
* the class file in favor of the access bits InnerClass attribute.
|
||||
*/
|
||||
@Override
|
||||
public void visitInnerClass(final String aname, final String outerName,
|
||||
final String innerName, final int attr_access) {
|
||||
if ((name != null) && name.equals(aname)) {
|
||||
this.access = attr_access;
|
||||
public void visitInnerClass(
|
||||
final String innerClassName,
|
||||
final String outerName,
|
||||
final String innerName,
|
||||
final int innerClassAccess) {
|
||||
// Handles a bizarre special case. Nested classes (static classes declared inside another class)
|
||||
// that are protected have their access bit set to public in their class files to deal with some
|
||||
// odd reflection situation. Our SVUID computation must do as the JVM does and ignore access
|
||||
// bits in the class file in favor of the access bits of the InnerClass attribute.
|
||||
if ((name != null) && name.equals(innerClassName)) {
|
||||
this.access = innerClassAccess;
|
||||
}
|
||||
super.visitInnerClass(aname, outerName, innerName, attr_access);
|
||||
super.visitInnerClass(innerClassName, outerName, innerName, innerClassAccess);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the SVUID if class doesn't have one
|
||||
*/
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// compute SVUID and add it to the class
|
||||
if (computeSVUID && !hasSVUID) {
|
||||
// Add the SVUID field to the class if it doesn't have one.
|
||||
if (computeSvuid && !hasSvuid) {
|
||||
try {
|
||||
addSVUID(computeSVUID());
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Error while computing SVUID for "
|
||||
+ name, e);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Error while computing SVUID for " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
super.visitEnd();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if the class already has a SVUID field. The result of this
|
||||
* method is only valid when visitEnd is or has been called.
|
||||
*
|
||||
* @return true if the class already has a SVUID field.
|
||||
*/
|
||||
* Returns true if the class already has a SVUID field. The result of this method is only valid
|
||||
* when visitEnd has been called.
|
||||
*
|
||||
* @return true if the class already has a SVUID field.
|
||||
*/
|
||||
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
|
||||
public boolean hasSVUID() {
|
||||
return hasSVUID;
|
||||
return hasSvuid;
|
||||
}
|
||||
|
||||
protected void addSVUID(long svuid) {
|
||||
FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
|
||||
+ Opcodes.ACC_STATIC, "serialVersionUID", "J", null, svuid);
|
||||
if (fv != null) {
|
||||
fv.visitEnd();
|
||||
/**
|
||||
* Adds a final static serialVersionUID field to the class, with the given value.
|
||||
*
|
||||
* @param svuid the serialVersionUID field value.
|
||||
*/
|
||||
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
|
||||
protected void addSVUID(final long svuid) {
|
||||
FieldVisitor fieldVisitor =
|
||||
super.visitField(
|
||||
Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, svuid);
|
||||
if (fieldVisitor != null) {
|
||||
fieldVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the value of SVUID.
|
||||
*
|
||||
* @return Returns the serial version UID
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
* Computes and returns the value of SVUID.
|
||||
*
|
||||
* @return the serial version UID.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
|
||||
protected long computeSVUID() throws IOException {
|
||||
ByteArrayOutputStream bos;
|
||||
DataOutputStream dos = null;
|
||||
ByteArrayOutputStream byteArrayOutputStream = null;
|
||||
DataOutputStream dataOutputStream = null;
|
||||
long svuid = 0;
|
||||
|
||||
try {
|
||||
bos = new ByteArrayOutputStream();
|
||||
dos = new DataOutputStream(bos);
|
||||
byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
dataOutputStream = new DataOutputStream(byteArrayOutputStream);
|
||||
|
||||
/*
|
||||
* 1. The class name written using UTF encoding.
|
||||
*/
|
||||
dos.writeUTF(name.replace('/', '.'));
|
||||
// 1. The class name written using UTF encoding.
|
||||
dataOutputStream.writeUTF(name.replace('/', '.'));
|
||||
|
||||
/*
|
||||
* 2. The class modifiers written as a 32-bit integer.
|
||||
*/
|
||||
int access = this.access;
|
||||
if ((access & Opcodes.ACC_INTERFACE) != 0) {
|
||||
access = (svuidMethods.size() > 0) ? (access | Opcodes.ACC_ABSTRACT)
|
||||
: (access & ~Opcodes.ACC_ABSTRACT);
|
||||
// 2. The class modifiers written as a 32-bit integer.
|
||||
int mods = access;
|
||||
if ((mods & Opcodes.ACC_INTERFACE) != 0) {
|
||||
mods =
|
||||
svuidMethods.isEmpty() ? (mods & ~Opcodes.ACC_ABSTRACT) : (mods | Opcodes.ACC_ABSTRACT);
|
||||
}
|
||||
dos.writeInt(access
|
||||
& (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
|
||||
| Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
|
||||
dataOutputStream.writeInt(
|
||||
mods
|
||||
& (Opcodes.ACC_PUBLIC
|
||||
| Opcodes.ACC_FINAL
|
||||
| Opcodes.ACC_INTERFACE
|
||||
| Opcodes.ACC_ABSTRACT));
|
||||
|
||||
/*
|
||||
* 3. The name of each interface sorted by name written using UTF
|
||||
* encoding.
|
||||
*/
|
||||
// 3. The name of each interface sorted by name written using UTF encoding.
|
||||
Arrays.sort(interfaces);
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
dos.writeUTF(interfaces[i].replace('/', '.'));
|
||||
for (String interfaceName : interfaces) {
|
||||
dataOutputStream.writeUTF(interfaceName.replace('/', '.'));
|
||||
}
|
||||
|
||||
/*
|
||||
* 4. For each field of the class sorted by field name (except
|
||||
* private static and private transient fields):
|
||||
*
|
||||
* 1. The name of the field in UTF encoding. 2. The modifiers of the
|
||||
* field written as a 32-bit integer. 3. The descriptor of the field
|
||||
* in UTF encoding
|
||||
*
|
||||
* Note that field signatures are not dot separated. Method and
|
||||
* constructor signatures are dot separated. Go figure...
|
||||
*/
|
||||
writeItems(svuidFields, dos, false);
|
||||
// 4. For each field of the class sorted by field name (except private static and private
|
||||
// transient fields):
|
||||
// 1. The name of the field in UTF encoding.
|
||||
// 2. The modifiers of the field written as a 32-bit integer.
|
||||
// 3. The descriptor of the field in UTF encoding.
|
||||
// Note that field signatures are not dot separated. Method and constructor signatures are dot
|
||||
// separated. Go figure...
|
||||
writeItems(svuidFields, dataOutputStream, false);
|
||||
|
||||
/*
|
||||
* 5. If a class initializer exists, write out the following: 1. The
|
||||
* name of the method, <clinit>, in UTF encoding. 2. The modifier of
|
||||
* the method, java.lang.reflect.Modifier.STATIC, written as a
|
||||
* 32-bit integer. 3. The descriptor of the method, ()V, in UTF
|
||||
* encoding.
|
||||
*/
|
||||
// 5. If a class initializer exists, write out the following:
|
||||
// 1. The name of the method, <clinit>, in UTF encoding.
|
||||
// 2. The modifier of the method, ACC_STATIC, written as a 32-bit integer.
|
||||
// 3. The descriptor of the method, ()V, in UTF encoding.
|
||||
if (hasStaticInitializer) {
|
||||
dos.writeUTF("<clinit>");
|
||||
dos.writeInt(Opcodes.ACC_STATIC);
|
||||
dos.writeUTF("()V");
|
||||
} // if..
|
||||
dataOutputStream.writeUTF(CLINIT);
|
||||
dataOutputStream.writeInt(Opcodes.ACC_STATIC);
|
||||
dataOutputStream.writeUTF("()V");
|
||||
}
|
||||
|
||||
/*
|
||||
* 6. For each non-private constructor sorted by method name and
|
||||
* signature: 1. The name of the method, <init>, in UTF encoding. 2.
|
||||
* The modifiers of the method written as a 32-bit integer. 3. The
|
||||
* descriptor of the method in UTF encoding.
|
||||
*/
|
||||
writeItems(svuidConstructors, dos, true);
|
||||
// 6. For each non-private constructor sorted by method name and signature:
|
||||
// 1. The name of the method, <init>, in UTF encoding.
|
||||
// 2. The modifiers of the method written as a 32-bit integer.
|
||||
// 3. The descriptor of the method in UTF encoding.
|
||||
writeItems(svuidConstructors, dataOutputStream, true);
|
||||
|
||||
/*
|
||||
* 7. For each non-private method sorted by method name and
|
||||
* signature: 1. The name of the method in UTF encoding. 2. The
|
||||
* modifiers of the method written as a 32-bit integer. 3. The
|
||||
* descriptor of the method in UTF encoding.
|
||||
*/
|
||||
writeItems(svuidMethods, dos, true);
|
||||
// 7. For each non-private method sorted by method name and signature:
|
||||
// 1. The name of the method in UTF encoding.
|
||||
// 2. The modifiers of the method written as a 32-bit integer.
|
||||
// 3. The descriptor of the method in UTF encoding.
|
||||
writeItems(svuidMethods, dataOutputStream, true);
|
||||
|
||||
dos.flush();
|
||||
dataOutputStream.flush();
|
||||
|
||||
/*
|
||||
* 8. The SHA-1 algorithm is executed on the stream of bytes
|
||||
* produced by DataOutputStream and produces five 32-bit values
|
||||
* sha[0..4].
|
||||
*/
|
||||
byte[] hashBytes = computeSHAdigest(bos.toByteArray());
|
||||
// 8. The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and
|
||||
// produces five 32-bit values sha[0..4].
|
||||
byte[] hashBytes = computeSHAdigest(byteArrayOutputStream.toByteArray());
|
||||
|
||||
/*
|
||||
* 9. The hash value is assembled from the first and second 32-bit
|
||||
* values of the SHA-1 message digest. If the result of the message
|
||||
* digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
|
||||
* five int values named sha, the hash value would be computed as
|
||||
* follows:
|
||||
*
|
||||
* long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
|
||||
* << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
|
||||
* 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
|
||||
* 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
|
||||
* 56;
|
||||
*/
|
||||
// 9. The hash value is assembled from the first and second 32-bit values of the SHA-1 message
|
||||
// digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an
|
||||
// array of five int values named sha, the hash value would be computed as follows:
|
||||
for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
|
||||
svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
|
||||
}
|
||||
} finally {
|
||||
// close the stream (if open)
|
||||
if (dos != null) {
|
||||
dos.close();
|
||||
if (dataOutputStream != null) {
|
||||
dataOutputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -492,82 +455,67 @@ public class SerialVersionUIDAdder extends ClassVisitor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the SHA-1 message digest of the given value.
|
||||
*
|
||||
* @param value
|
||||
* the value whose SHA message digest must be computed.
|
||||
* @return the SHA-1 message digest of the given value.
|
||||
*/
|
||||
* Returns the SHA-1 message digest of the given value.
|
||||
*
|
||||
* @param value the value whose SHA message digest must be computed.
|
||||
* @return the SHA-1 message digest of the given value.
|
||||
*/
|
||||
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
|
||||
protected byte[] computeSHAdigest(final byte[] value) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA").digest(value);
|
||||
} catch (Exception e) {
|
||||
throw new UnsupportedOperationException(e.toString());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the items in the collection and writes it to the data output stream
|
||||
*
|
||||
* @param itemCollection
|
||||
* collection of items
|
||||
* @param dos
|
||||
* a <code>DataOutputStream</code> value
|
||||
* @param dotted
|
||||
* a <code>boolean</code> value
|
||||
* @exception IOException
|
||||
* if an error occurs
|
||||
*/
|
||||
private static void writeItems(final Collection<Item> itemCollection,
|
||||
final DataOutput dos, final boolean dotted) throws IOException {
|
||||
int size = itemCollection.size();
|
||||
Item[] items = itemCollection.toArray(new Item[size]);
|
||||
Arrays.sort(items);
|
||||
for (int i = 0; i < size; i++) {
|
||||
dos.writeUTF(items[i].name);
|
||||
dos.writeInt(items[i].access);
|
||||
dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
|
||||
: items[i].desc);
|
||||
* Sorts the items in the collection and writes it to the given output stream.
|
||||
*
|
||||
* @param itemCollection a collection of items.
|
||||
* @param dataOutputStream where the items must be written.
|
||||
* @param dotted whether package names must use dots, instead of slashes.
|
||||
* @exception IOException if an error occurs.
|
||||
*/
|
||||
private static void writeItems(
|
||||
final Collection<Item> itemCollection,
|
||||
final DataOutput dataOutputStream,
|
||||
final boolean dotted)
|
||||
throws IOException {
|
||||
Item[] items = itemCollection.toArray(new Item[0]);
|
||||
Arrays.sort(
|
||||
items,
|
||||
new Comparator<Item>() {
|
||||
@Override
|
||||
public int compare(final Item item1, final Item item2) {
|
||||
int result = item1.name.compareTo(item2.name);
|
||||
if (result == 0) {
|
||||
result = item1.descriptor.compareTo(item2.descriptor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
for (Item item : items) {
|
||||
dataOutputStream.writeUTF(item.name);
|
||||
dataOutputStream.writeInt(item.access);
|
||||
dataOutputStream.writeUTF(dotted ? item.descriptor.replace('/', '.') : item.descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Inner classes
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
private static class Item implements Comparable<Item> {
|
||||
private static final class Item {
|
||||
|
||||
final String name;
|
||||
|
||||
final int access;
|
||||
final String descriptor;
|
||||
|
||||
final String desc;
|
||||
|
||||
Item(final String name, final int access, final String desc) {
|
||||
Item(final String name, final int access, final String descriptor) {
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int compareTo(final Item other) {
|
||||
int retVal = name.compareTo(other.name);
|
||||
if (retVal == 0) {
|
||||
retVal = desc.compareTo(other.desc);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (o instanceof Item) {
|
||||
return compareTo((Item) o) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (name + desc).hashCode();
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,133 +56,149 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
/**
|
||||
* A {@link SignatureVisitor} adapter for type mapping.
|
||||
* A {@link SignatureVisitor} that remaps types with a {@link Remapper}.
|
||||
*
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public class SignatureRemapper extends SignatureVisitor {
|
||||
|
||||
private final SignatureVisitor v;
|
||||
private final SignatureVisitor signatureVisitor;
|
||||
|
||||
private final Remapper remapper;
|
||||
|
||||
private Stack<String> classNames = new Stack<String>();
|
||||
private ArrayList<String> classNames = new ArrayList<String>();
|
||||
|
||||
public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) {
|
||||
this(Opcodes.ASM6, v, remapper);
|
||||
/**
|
||||
* Constructs a new {@link SignatureRemapper}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #SignatureRemapper(int,SignatureVisitor,Remapper)} version.
|
||||
*
|
||||
* @param signatureVisitor the signature visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited signature.
|
||||
*/
|
||||
public SignatureRemapper(final SignatureVisitor signatureVisitor, final Remapper remapper) {
|
||||
this(Opcodes.ASM7, signatureVisitor, remapper);
|
||||
}
|
||||
|
||||
protected SignatureRemapper(final int api, final SignatureVisitor v,
|
||||
final Remapper remapper) {
|
||||
/**
|
||||
* Constructs a new {@link SignatureRemapper}.
|
||||
*
|
||||
* @param api the ASM API version supported by this remapper. Must be one of {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM4}, {@link jdk.internal.org.objectweb.asm.Opcodes#ASM5} or {@link
|
||||
* jdk.internal.org.objectweb.asm.Opcodes#ASM6}.
|
||||
* @param signatureVisitor the signature visitor this remapper must deleted to.
|
||||
* @param remapper the remapper to use to remap the types in the visited signature.
|
||||
*/
|
||||
protected SignatureRemapper(
|
||||
final int api, final SignatureVisitor signatureVisitor, final Remapper remapper) {
|
||||
super(api);
|
||||
this.v = v;
|
||||
this.signatureVisitor = signatureVisitor;
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(String name) {
|
||||
classNames.push(name);
|
||||
v.visitClassType(remapper.mapType(name));
|
||||
public void visitClassType(final String name) {
|
||||
classNames.add(name);
|
||||
signatureVisitor.visitClassType(remapper.mapType(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(String name) {
|
||||
String outerClassName = classNames.pop();
|
||||
public void visitInnerClassType(final String name) {
|
||||
String outerClassName = classNames.remove(classNames.size() - 1);
|
||||
String className = outerClassName + '$' + name;
|
||||
classNames.push(className);
|
||||
classNames.add(className);
|
||||
String remappedOuter = remapper.mapType(outerClassName) + '$';
|
||||
String remappedName = remapper.mapType(className);
|
||||
int index = remappedName.startsWith(remappedOuter) ? remappedOuter
|
||||
.length() : remappedName.lastIndexOf('$') + 1;
|
||||
v.visitInnerClassType(remappedName.substring(index));
|
||||
int index =
|
||||
remappedName.startsWith(remappedOuter)
|
||||
? remappedOuter.length()
|
||||
: remappedName.lastIndexOf('$') + 1;
|
||||
signatureVisitor.visitInnerClassType(remappedName.substring(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
v.visitFormalTypeParameter(name);
|
||||
public void visitFormalTypeParameter(final String name) {
|
||||
signatureVisitor.visitFormalTypeParameter(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(String name) {
|
||||
v.visitTypeVariable(name);
|
||||
public void visitTypeVariable(final String name) {
|
||||
signatureVisitor.visitTypeVariable(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
v.visitArrayType();
|
||||
signatureVisitor.visitArrayType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(char descriptor) {
|
||||
v.visitBaseType(descriptor);
|
||||
public void visitBaseType(final char descriptor) {
|
||||
signatureVisitor.visitBaseType(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitClassBound() {
|
||||
v.visitClassBound();
|
||||
signatureVisitor.visitClassBound();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
v.visitExceptionType();
|
||||
signatureVisitor.visitExceptionType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterface() {
|
||||
v.visitInterface();
|
||||
signatureVisitor.visitInterface();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
v.visitInterfaceBound();
|
||||
signatureVisitor.visitInterfaceBound();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
v.visitParameterType();
|
||||
signatureVisitor.visitParameterType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitReturnType() {
|
||||
v.visitReturnType();
|
||||
signatureVisitor.visitReturnType();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
v.visitSuperclass();
|
||||
signatureVisitor.visitSuperclass();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
v.visitTypeArgument();
|
||||
signatureVisitor.visitTypeArgument();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
v.visitTypeArgument(wildcard);
|
||||
public SignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
signatureVisitor.visitTypeArgument(wildcard);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
v.visitEnd();
|
||||
classNames.pop();
|
||||
signatureVisitor.visitEnd();
|
||||
classNames.remove(classNames.size() - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import java.util.Collections;
|
||||
|
|
@ -71,34 +70,57 @@ public class SimpleRemapper extends Remapper {
|
|||
|
||||
private final Map<String, String> mapping;
|
||||
|
||||
public SimpleRemapper(Map<String, String> mapping) {
|
||||
/**
|
||||
* Constructs a new {@link SimpleRemapper} with the given mapping.
|
||||
*
|
||||
* @param mapping a map specifying a remapping as follows:
|
||||
* <ul>
|
||||
* <li>for method names, the key is the owner, name and descriptor of the method (in the
|
||||
* form <owner>.<name><descriptor>), and the value is the new method
|
||||
* name.
|
||||
* <li>for invokedynamic method names, the key is the name and descriptor of the method (in
|
||||
* the form .<name><descriptor>), and the value is the new method name.
|
||||
* <li>for field names, the key is the owner and name of the field (in the form
|
||||
* <owner>.<name>), and the value is the new field name.
|
||||
* <li>for internal names, the key is the old internal name, and the value is the new
|
||||
* internal name.
|
||||
* </ul>
|
||||
*/
|
||||
public SimpleRemapper(final Map<String, String> mapping) {
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public SimpleRemapper(String oldName, String newName) {
|
||||
/**
|
||||
* Constructs a new {@link SimpleRemapper} with the given mapping.
|
||||
*
|
||||
* @param oldName the key corresponding to a method, field or internal name (see {@link
|
||||
* #SimpleRemapper(Map)} for the format of these keys).
|
||||
* @param newName the new method, field or internal name.
|
||||
*/
|
||||
public SimpleRemapper(final String oldName, final String newName) {
|
||||
this.mapping = Collections.singletonMap(oldName, newName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapMethodName(String owner, String name, String desc) {
|
||||
String s = map(owner + '.' + name + desc);
|
||||
return s == null ? name : s;
|
||||
public String mapMethodName(final String owner, final String name, final String descriptor) {
|
||||
String remappedName = map(owner + '.' + name + descriptor);
|
||||
return remappedName == null ? name : remappedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapInvokeDynamicMethodName(String name, String desc) {
|
||||
String s = map('.' + name + desc);
|
||||
return s == null ? name : s;
|
||||
public String mapInvokeDynamicMethodName(final String name, final String descriptor) {
|
||||
String remappedName = map('.' + name + descriptor);
|
||||
return remappedName == null ? name : remappedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapFieldName(String owner, String name, String desc) {
|
||||
String s = map(owner + '.' + name);
|
||||
return s == null ? name : s;
|
||||
public String mapFieldName(final String owner, final String name, final String descriptor) {
|
||||
String remappedName = map(owner + '.' + name);
|
||||
return remappedName == null ? name : remappedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String map(String key) {
|
||||
public String map(final String key) {
|
||||
return mapping.get(key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,64 +63,93 @@ import jdk.internal.org.objectweb.asm.MethodVisitor;
|
|||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A {@link ClassVisitor} that merges clinit methods into a single one.
|
||||
* A {@link ClassVisitor} that merges <clinit> methods into a single one. All the existing
|
||||
* <clinit> methods are renamed, and a new one is created, which calls all the renamed
|
||||
* methods.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class StaticInitMerger extends ClassVisitor {
|
||||
|
||||
private String name;
|
||||
/** The internal name of the visited class. */
|
||||
private String owner;
|
||||
|
||||
private MethodVisitor clinit;
|
||||
/** The prefix to use to rename the existing <clinit> methods. */
|
||||
private final String renamedClinitMethodPrefix;
|
||||
|
||||
private final String prefix;
|
||||
/** The number of <clinit> methods visited so far. */
|
||||
private int numClinitMethods;
|
||||
|
||||
private int counter;
|
||||
/** The MethodVisitor for the merged <clinit> method. */
|
||||
private MethodVisitor mergedClinitVisitor;
|
||||
|
||||
public StaticInitMerger(final String prefix, final ClassVisitor cv) {
|
||||
this(Opcodes.ASM6, prefix, cv);
|
||||
/**
|
||||
* Constructs a new {@link StaticInitMerger}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #StaticInitMerger(int, String, ClassVisitor)} version.
|
||||
*
|
||||
* @param prefix the prefix to use to rename the existing <clinit> methods.
|
||||
* @param classVisitor the class visitor to which this visitor must delegate method calls. May be
|
||||
* null.
|
||||
*/
|
||||
public StaticInitMerger(final String prefix, final ClassVisitor classVisitor) {
|
||||
this(Opcodes.ASM7, prefix, classVisitor);
|
||||
}
|
||||
|
||||
protected StaticInitMerger(final int api, final String prefix,
|
||||
final ClassVisitor cv) {
|
||||
super(api, cv);
|
||||
this.prefix = prefix;
|
||||
/**
|
||||
* Constructs a new {@link StaticInitMerger}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param prefix the prefix to use to rename the existing <clinit> methods.
|
||||
* @param classVisitor the class visitor to which this visitor must delegate method calls. May be
|
||||
* null.
|
||||
*/
|
||||
protected StaticInitMerger(final int api, final String prefix, final ClassVisitor classVisitor) {
|
||||
super(api, classVisitor);
|
||||
this.renamedClinitMethodPrefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(final int version, final int access, final String name,
|
||||
final String signature, final String superName,
|
||||
public void visit(
|
||||
final int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces) {
|
||||
cv.visit(version, access, name, signature, superName, interfaces);
|
||||
this.name = name;
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
this.owner = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access, final String name,
|
||||
final String desc, final String signature, final String[] exceptions) {
|
||||
MethodVisitor mv;
|
||||
public MethodVisitor visitMethod(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
MethodVisitor methodVisitor;
|
||||
if ("<clinit>".equals(name)) {
|
||||
int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
|
||||
String n = prefix + counter++;
|
||||
mv = cv.visitMethod(a, n, desc, signature, exceptions);
|
||||
int newAccess = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
|
||||
String newName = renamedClinitMethodPrefix + numClinitMethods++;
|
||||
methodVisitor = super.visitMethod(newAccess, newName, descriptor, signature, exceptions);
|
||||
|
||||
if (clinit == null) {
|
||||
clinit = cv.visitMethod(a, name, desc, null, null);
|
||||
if (mergedClinitVisitor == null) {
|
||||
mergedClinitVisitor = super.visitMethod(newAccess, name, descriptor, null, null);
|
||||
}
|
||||
clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc,
|
||||
false);
|
||||
mergedClinitVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, owner, newName, descriptor, false);
|
||||
} else {
|
||||
mv = cv.visitMethod(access, name, desc, signature, exceptions);
|
||||
methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||
}
|
||||
return mv;
|
||||
return methodVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (clinit != null) {
|
||||
clinit.visitInsn(Opcodes.RETURN);
|
||||
clinit.visitMaxs(0, 0);
|
||||
if (mergedClinitVisitor != null) {
|
||||
mergedClinitVisitor.visitInsn(Opcodes.RETURN);
|
||||
mergedClinitVisitor.visitMaxs(0, 0);
|
||||
}
|
||||
cv.visitEnd();
|
||||
super.visitEnd();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,17 +70,13 @@ import jdk.internal.org.objectweb.asm.Label;
|
|||
public interface TableSwitchGenerator {
|
||||
|
||||
/**
|
||||
* Generates the code for a switch case.
|
||||
*
|
||||
* @param key
|
||||
* the switch case key.
|
||||
* @param end
|
||||
* a label that corresponds to the end of the switch statement.
|
||||
*/
|
||||
* Generates the code for a switch case.
|
||||
*
|
||||
* @param key the switch case key.
|
||||
* @param end a label that corresponds to the end of the switch statement.
|
||||
*/
|
||||
void generateCase(int key, Label end);
|
||||
|
||||
/**
|
||||
* Generates the code for the default switch case.
|
||||
*/
|
||||
/** Generates the code for the default switch case. */
|
||||
void generateDefault();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,65 +56,89 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.commons;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.tree.MethodNode;
|
||||
import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
|
||||
|
||||
/**
|
||||
* A {@link MethodVisitor} adapter to sort the exception handlers. The handlers
|
||||
* are sorted in a method innermost-to-outermost. This allows the programmer to
|
||||
* add handlers without worrying about ordering them correctly with respect to
|
||||
* existing, in-code handlers.
|
||||
* A {@link MethodVisitor} adapter to sort the exception handlers. The handlers are sorted in a
|
||||
* method innermost-to-outermost. This allows the programmer to add handlers without worrying about
|
||||
* ordering them correctly with respect to existing, in-code handlers.
|
||||
*
|
||||
* Behavior is only defined for properly-nested handlers. If any "try" blocks
|
||||
* overlap (something that isn't possible in Java code) then this may not do
|
||||
* what you want. In fact, this adapter just sorts by the length of the "try"
|
||||
* block, taking advantage of the fact that a given try block must be larger
|
||||
* than any block it contains).
|
||||
* <p>Behavior is only defined for properly-nested handlers. If any "try" blocks overlap (something
|
||||
* that isn't possible in Java code) then this may not do what you want. In fact, this adapter just
|
||||
* sorts by the length of the "try" block, taking advantage of the fact that a given try block must
|
||||
* be larger than any block it contains).
|
||||
*
|
||||
* @author Adrian Sampson
|
||||
*/
|
||||
public class TryCatchBlockSorter extends MethodNode {
|
||||
|
||||
public TryCatchBlockSorter(final MethodVisitor mv, final int access,
|
||||
final String name, final String desc, final String signature,
|
||||
/**
|
||||
* Constructs a new {@link TryCatchBlockSorter}.
|
||||
*
|
||||
* @param methodVisitor the method visitor to which this visitor must delegate method calls. May
|
||||
* be {@literal null}.
|
||||
* @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the method is synthetic and/or deprecated.
|
||||
* @param name the method's name.
|
||||
* @param descriptor the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param signature the method's signature. May be {@literal null} if the method parameters,
|
||||
* return type and exceptions do not use generic types.
|
||||
* @param exceptions the internal names of the method's exception classes (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
|
||||
*/
|
||||
public TryCatchBlockSorter(
|
||||
final MethodVisitor methodVisitor,
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
|
||||
this(Opcodes.ASM7, methodVisitor, access, name, descriptor, signature, exceptions);
|
||||
if (getClass() != TryCatchBlockSorter.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
|
||||
final int access, final String name, final String desc,
|
||||
final String signature, final String[] exceptions) {
|
||||
super(api, access, name, desc, signature, exceptions);
|
||||
this.mv = mv;
|
||||
protected TryCatchBlockSorter(
|
||||
final int api,
|
||||
final MethodVisitor methodVisitor,
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
super(api, access, name, descriptor, signature, exceptions);
|
||||
this.mv = methodVisitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Compares TryCatchBlockNodes by the length of their "try" block.
|
||||
Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
|
||||
// Sort the TryCatchBlockNode elements by the length of their "try" block.
|
||||
Collections.sort(
|
||||
tryCatchBlocks,
|
||||
new Comparator<TryCatchBlockNode>() {
|
||||
|
||||
public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) {
|
||||
int len1 = blockLength(t1);
|
||||
int len2 = blockLength(t2);
|
||||
return len1 - len2;
|
||||
}
|
||||
@Override
|
||||
public int compare(
|
||||
final TryCatchBlockNode tryCatchBlockNode1,
|
||||
final TryCatchBlockNode tryCatchBlockNode2) {
|
||||
return blockLength(tryCatchBlockNode1) - blockLength(tryCatchBlockNode2);
|
||||
}
|
||||
|
||||
private int blockLength(TryCatchBlockNode block) {
|
||||
int startidx = instructions.indexOf(block.start);
|
||||
int endidx = instructions.indexOf(block.end);
|
||||
return endidx - startidx;
|
||||
}
|
||||
};
|
||||
Collections.sort(tryCatchBlocks, comp);
|
||||
// Updates the 'target' of each try catch block annotation.
|
||||
private int blockLength(final TryCatchBlockNode tryCatchBlockNode) {
|
||||
int startIndex = instructions.indexOf(tryCatchBlockNode.start);
|
||||
int endIndex = instructions.indexOf(tryCatchBlockNode.end);
|
||||
return endIndex - startIndex;
|
||||
}
|
||||
});
|
||||
// Update the 'target' of each try catch block annotation.
|
||||
for (int i = 0; i < tryCatchBlocks.size(); ++i) {
|
||||
tryCatchBlocks.get(i).updateIndex(i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,199 +59,225 @@
|
|||
package jdk.internal.org.objectweb.asm.signature;
|
||||
|
||||
/**
|
||||
* A type signature parser to make a signature visitor visit an existing
|
||||
* signature.
|
||||
* A parser for signature literals, as defined in the Java Virtual Machine Specification (JVMS), to
|
||||
* visit them with a SignatureVisitor.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1">JVMS
|
||||
* 4.7.9.1</a>
|
||||
* @author Thomas Hallgren
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class SignatureReader {
|
||||
|
||||
/**
|
||||
* The signature to be read.
|
||||
*/
|
||||
private final String signature;
|
||||
/** The JVMS signature to be read. */
|
||||
private final String signatureValue;
|
||||
|
||||
/**
|
||||
* Constructs a {@link SignatureReader} for the given signature.
|
||||
*
|
||||
* @param signature
|
||||
* A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
|
||||
* <i>FieldTypeSignature</i>.
|
||||
*/
|
||||
* Constructs a {@link SignatureReader} for the given signature.
|
||||
*
|
||||
* @param signature A <i>JavaTypeSignature</i>, <i>ClassSignature</i> or <i>MethodSignature</i>.
|
||||
*/
|
||||
public SignatureReader(final String signature) {
|
||||
this.signature = signature;
|
||||
this.signatureValue = signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit the signature of this
|
||||
* {@link SignatureReader}. This signature is the one specified in the
|
||||
* constructor (see {@link #SignatureReader(String) SignatureReader}). This
|
||||
* method is intended to be called on a {@link SignatureReader} that was
|
||||
* created using a <i>ClassSignature</i> (such as the <code>signature</code>
|
||||
* parameter of the {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit
|
||||
* ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
|
||||
* <code>signature</code> parameter of the
|
||||
* {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitMethod
|
||||
* ClassVisitor.visitMethod} method).
|
||||
*
|
||||
* @param v
|
||||
* the visitor that must visit this signature.
|
||||
*/
|
||||
public void accept(final SignatureVisitor v) {
|
||||
String signature = this.signature;
|
||||
int len = signature.length();
|
||||
int pos;
|
||||
char c;
|
||||
* Makes the given visitor visit the signature of this {@link SignatureReader}. This signature is
|
||||
* the one specified in the constructor (see {@link #SignatureReader}). This method is intended to
|
||||
* be called on a {@link SignatureReader} that was created using a <i>ClassSignature</i> (such as
|
||||
* the <code>signature</code> parameter of the {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit}
|
||||
* method) or a <i>MethodSignature</i> (such as the <code>signature</code> parameter of the {@link
|
||||
* jdk.internal.org.objectweb.asm.ClassVisitor#visitMethod} method).
|
||||
*
|
||||
* @param signatureVistor the visitor that must visit this signature.
|
||||
*/
|
||||
public void accept(final SignatureVisitor signatureVistor) {
|
||||
String signature = this.signatureValue;
|
||||
int length = signature.length();
|
||||
int offset; // Current offset in the parsed signature (parsed from left to right).
|
||||
char currentChar; // The signature character at 'offset', or just before.
|
||||
|
||||
// If the signature starts with '<', it starts with TypeParameters, i.e. a formal type parameter
|
||||
// identifier, followed by one or more pair ':',ReferenceTypeSignature (for its class bound and
|
||||
// interface bounds).
|
||||
if (signature.charAt(0) == '<') {
|
||||
pos = 2;
|
||||
// Invariant: offset points to the second character of a formal type parameter name at the
|
||||
// beginning of each iteration of the loop below.
|
||||
offset = 2;
|
||||
do {
|
||||
int end = signature.indexOf(':', pos);
|
||||
v.visitFormalTypeParameter(signature.substring(pos - 1, end));
|
||||
pos = end + 1;
|
||||
// The formal type parameter name is everything between offset - 1 and the first ':'.
|
||||
int classBoundStartOffset = signature.indexOf(':', offset);
|
||||
signatureVistor.visitFormalTypeParameter(
|
||||
signature.substring(offset - 1, classBoundStartOffset));
|
||||
|
||||
c = signature.charAt(pos);
|
||||
if (c == 'L' || c == '[' || c == 'T') {
|
||||
pos = parseType(signature, pos, v.visitClassBound());
|
||||
// If the character after the ':' class bound marker is not the start of a
|
||||
// ReferenceTypeSignature, it means the class bound is empty (which is a valid case).
|
||||
offset = classBoundStartOffset + 1;
|
||||
currentChar = signature.charAt(offset);
|
||||
if (currentChar == 'L' || currentChar == '[' || currentChar == 'T') {
|
||||
offset = parseType(signature, offset, signatureVistor.visitClassBound());
|
||||
}
|
||||
|
||||
while ((c = signature.charAt(pos++)) == ':') {
|
||||
pos = parseType(signature, pos, v.visitInterfaceBound());
|
||||
// While the character after the class bound or after the last parsed interface bound
|
||||
// is ':', we need to parse another interface bound.
|
||||
while ((currentChar = signature.charAt(offset++)) == ':') {
|
||||
offset = parseType(signature, offset, signatureVistor.visitInterfaceBound());
|
||||
}
|
||||
} while (c != '>');
|
||||
|
||||
// At this point a TypeParameter has been fully parsed, and we need to parse the next one
|
||||
// (note that currentChar is now the first character of the next TypeParameter, and that
|
||||
// offset points to the second character), unless the character just after this
|
||||
// TypeParameter signals the end of the TypeParameters.
|
||||
} while (currentChar != '>');
|
||||
} else {
|
||||
pos = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (signature.charAt(pos) == '(') {
|
||||
pos++;
|
||||
while (signature.charAt(pos) != ')') {
|
||||
pos = parseType(signature, pos, v.visitParameterType());
|
||||
// If the (optional) TypeParameters is followed by '(' this means we are parsing a
|
||||
// MethodSignature, which has JavaTypeSignature type inside parentheses, followed by a Result
|
||||
// type and optional ThrowsSignature types.
|
||||
if (signature.charAt(offset) == '(') {
|
||||
offset++;
|
||||
while (signature.charAt(offset) != ')') {
|
||||
offset = parseType(signature, offset, signatureVistor.visitParameterType());
|
||||
}
|
||||
pos = parseType(signature, pos + 1, v.visitReturnType());
|
||||
while (pos < len) {
|
||||
pos = parseType(signature, pos + 1, v.visitExceptionType());
|
||||
// Use offset + 1 to skip ')'.
|
||||
offset = parseType(signature, offset + 1, signatureVistor.visitReturnType());
|
||||
while (offset < length) {
|
||||
// Use offset + 1 to skip the first character of a ThrowsSignature, i.e. '^'.
|
||||
offset = parseType(signature, offset + 1, signatureVistor.visitExceptionType());
|
||||
}
|
||||
} else {
|
||||
pos = parseType(signature, pos, v.visitSuperclass());
|
||||
while (pos < len) {
|
||||
pos = parseType(signature, pos, v.visitInterface());
|
||||
// Otherwise we are parsing a ClassSignature (by hypothesis on the method input), which has
|
||||
// one or more ClassTypeSignature for the super class and the implemented interfaces.
|
||||
offset = parseType(signature, offset, signatureVistor.visitSuperclass());
|
||||
while (offset < length) {
|
||||
offset = parseType(signature, offset, signatureVistor.visitInterface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit the signature of this
|
||||
* {@link SignatureReader}. This signature is the one specified in the
|
||||
* constructor (see {@link #SignatureReader(String) SignatureReader}). This
|
||||
* method is intended to be called on a {@link SignatureReader} that was
|
||||
* created using a <i>FieldTypeSignature</i>, such as the
|
||||
* <code>signature</code> parameter of the
|
||||
* {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField}
|
||||
* or {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLocalVariable
|
||||
* MethodVisitor.visitLocalVariable} methods.
|
||||
*
|
||||
* @param v
|
||||
* the visitor that must visit this signature.
|
||||
*/
|
||||
public void acceptType(final SignatureVisitor v) {
|
||||
parseType(this.signature, 0, v);
|
||||
* Makes the given visitor visit the signature of this {@link SignatureReader}. This signature is
|
||||
* the one specified in the constructor (see {@link #SignatureReader}). This method is intended to
|
||||
* be called on a {@link SignatureReader} that was created using a <i>JavaTypeSignature</i>, such
|
||||
* as the <code>signature</code> parameter of the {@link
|
||||
* jdk.internal.org.objectweb.asm.ClassVisitor#visitField} or {@link
|
||||
* jdk.internal.org.objectweb.asm.MethodVisitor#visitLocalVariable} methods.
|
||||
*
|
||||
* @param signatureVisitor the visitor that must visit this signature.
|
||||
*/
|
||||
public void acceptType(final SignatureVisitor signatureVisitor) {
|
||||
parseType(signatureValue, 0, signatureVisitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a field type signature and makes the given visitor visit it.
|
||||
*
|
||||
* @param signature
|
||||
* a string containing the signature that must be parsed.
|
||||
* @param pos
|
||||
* index of the first character of the signature to parsed.
|
||||
* @param v
|
||||
* the visitor that must visit this signature.
|
||||
* @return the index of the first character after the parsed signature.
|
||||
*/
|
||||
private static int parseType(final String signature, int pos,
|
||||
final SignatureVisitor v) {
|
||||
char c;
|
||||
int start, end;
|
||||
boolean visited, inner;
|
||||
String name;
|
||||
* Parses a JavaTypeSignature and makes the given visitor visit it.
|
||||
*
|
||||
* @param signature a string containing the signature that must be parsed.
|
||||
* @param startOffset index of the first character of the signature to parsed.
|
||||
* @param signatureVisitor the visitor that must visit this signature.
|
||||
* @return the index of the first character after the parsed signature.
|
||||
*/
|
||||
private static int parseType(
|
||||
final String signature, final int startOffset, final SignatureVisitor signatureVisitor) {
|
||||
int offset = startOffset; // Current offset in the parsed signature.
|
||||
char currentChar = signature.charAt(offset++); // The signature character at 'offset'.
|
||||
|
||||
switch (c = signature.charAt(pos++)) {
|
||||
case 'Z':
|
||||
case 'C':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'J':
|
||||
case 'D':
|
||||
case 'V':
|
||||
v.visitBaseType(c);
|
||||
return pos;
|
||||
// Switch based on the first character of the JavaTypeSignature, which indicates its kind.
|
||||
switch (currentChar) {
|
||||
case 'Z':
|
||||
case 'C':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'J':
|
||||
case 'D':
|
||||
case 'V':
|
||||
// Case of a BaseType or a VoidDescriptor.
|
||||
signatureVisitor.visitBaseType(currentChar);
|
||||
return offset;
|
||||
|
||||
case '[':
|
||||
return parseType(signature, pos, v.visitArrayType());
|
||||
case '[':
|
||||
// Case of an ArrayTypeSignature, a '[' followed by a JavaTypeSignature.
|
||||
return parseType(signature, offset, signatureVisitor.visitArrayType());
|
||||
|
||||
case 'T':
|
||||
end = signature.indexOf(';', pos);
|
||||
v.visitTypeVariable(signature.substring(pos, end));
|
||||
return end + 1;
|
||||
case 'T':
|
||||
// Case of TypeVariableSignature, an identifier between 'T' and ';'.
|
||||
int endOffset = signature.indexOf(';', offset);
|
||||
signatureVisitor.visitTypeVariable(signature.substring(offset, endOffset));
|
||||
return endOffset + 1;
|
||||
|
||||
default: // case 'L':
|
||||
start = pos;
|
||||
visited = false;
|
||||
inner = false;
|
||||
for (;;) {
|
||||
switch (c = signature.charAt(pos++)) {
|
||||
case '.':
|
||||
case ';':
|
||||
if (!visited) {
|
||||
name = signature.substring(start, pos - 1);
|
||||
case 'L':
|
||||
// Case of a ClassTypeSignature, which ends with ';'.
|
||||
// These signatures have a main class type followed by zero or more inner class types
|
||||
// (separated by '.'). Each can have type arguments, inside '<' and '>'.
|
||||
int start = offset; // The start offset of the currently parsed main or inner class name.
|
||||
boolean visited = false; // Whether the currently parsed class name has been visited.
|
||||
boolean inner = false; // Whether we are currently parsing an inner class type.
|
||||
// Parses the signature, one character at a time.
|
||||
while (true) {
|
||||
currentChar = signature.charAt(offset++);
|
||||
if (currentChar == '.' || currentChar == ';') {
|
||||
// If a '.' or ';' is encountered, this means we have fully parsed the main class name
|
||||
// or an inner class name. This name may already have been visited it is was followed by
|
||||
// type arguments between '<' and '>'. If not, we need to visit it here.
|
||||
if (!visited) {
|
||||
String name = signature.substring(start, offset - 1);
|
||||
if (inner) {
|
||||
signatureVisitor.visitInnerClassType(name);
|
||||
} else {
|
||||
signatureVisitor.visitClassType(name);
|
||||
}
|
||||
}
|
||||
// If we reached the end of the ClassTypeSignature return, otherwise start the parsing
|
||||
// of a new class name, which is necessarily an inner class name.
|
||||
if (currentChar == ';') {
|
||||
signatureVisitor.visitEnd();
|
||||
break;
|
||||
}
|
||||
start = offset;
|
||||
visited = false;
|
||||
inner = true;
|
||||
} else if (currentChar == '<') {
|
||||
// If a '<' is encountered, this means we have fully parsed the main class name or an
|
||||
// inner class name, and that we now need to parse TypeArguments. First, we need to
|
||||
// visit the parsed class name.
|
||||
String name = signature.substring(start, offset - 1);
|
||||
if (inner) {
|
||||
v.visitInnerClassType(name);
|
||||
signatureVisitor.visitInnerClassType(name);
|
||||
} else {
|
||||
v.visitClassType(name);
|
||||
signatureVisitor.visitClassType(name);
|
||||
}
|
||||
}
|
||||
if (c == ';') {
|
||||
v.visitEnd();
|
||||
return pos;
|
||||
}
|
||||
start = pos;
|
||||
visited = false;
|
||||
inner = true;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
name = signature.substring(start, pos - 1);
|
||||
if (inner) {
|
||||
v.visitInnerClassType(name);
|
||||
} else {
|
||||
v.visitClassType(name);
|
||||
}
|
||||
visited = true;
|
||||
top: for (;;) {
|
||||
switch (c = signature.charAt(pos)) {
|
||||
case '>':
|
||||
break top;
|
||||
case '*':
|
||||
++pos;
|
||||
v.visitTypeArgument();
|
||||
break;
|
||||
case '+':
|
||||
case '-':
|
||||
pos = parseType(signature, pos + 1,
|
||||
v.visitTypeArgument(c));
|
||||
break;
|
||||
default:
|
||||
pos = parseType(signature, pos,
|
||||
v.visitTypeArgument('='));
|
||||
break;
|
||||
visited = true;
|
||||
// Now, parse the TypeArgument(s), one at a time.
|
||||
while ((currentChar = signature.charAt(offset)) != '>') {
|
||||
switch (currentChar) {
|
||||
case '*':
|
||||
// Unbounded TypeArgument.
|
||||
++offset;
|
||||
signatureVisitor.visitTypeArgument();
|
||||
break;
|
||||
case '+':
|
||||
case '-':
|
||||
// Extends or Super TypeArgument. Use offset + 1 to skip the '+' or '-'.
|
||||
offset =
|
||||
parseType(
|
||||
signature, offset + 1, signatureVisitor.visitTypeArgument(currentChar));
|
||||
break;
|
||||
default:
|
||||
// Instanceof TypeArgument. The '=' is implicit.
|
||||
offset = parseType(signature, offset, signatureVisitor.visitTypeArgument('='));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,23 +61,19 @@ package jdk.internal.org.objectweb.asm.signature;
|
|||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A visitor to visit a generic signature. The methods of this interface must be
|
||||
* called in one of the three following orders (the last one is the only valid
|
||||
* order for a {@link SignatureVisitor} that is returned by a method of this
|
||||
* interface):
|
||||
* A visitor to visit a generic signature. The methods of this interface must be called in one of
|
||||
* the three following orders (the last one is the only valid order for a {@link SignatureVisitor}
|
||||
* that is returned by a method of this interface):
|
||||
*
|
||||
* <ul>
|
||||
* <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
|
||||
* <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
|
||||
* <tt>visitSuperclass</tt> <tt>visitInterface</tt>* )</li>
|
||||
* <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
|
||||
* <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
|
||||
* <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
|
||||
* <tt>visitExceptionType</tt>* )</li>
|
||||
* <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
|
||||
* <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
|
||||
* <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
|
||||
* <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
|
||||
* ) )</li>
|
||||
* <li><i>ClassSignature</i> = ( {@code visitFormalTypeParameter} {@code visitClassBound}? {@code
|
||||
* visitInterfaceBound}* )* ({@code visitSuperclass} {@code visitInterface}* )
|
||||
* <li><i>MethodSignature</i> = ( {@code visitFormalTypeParameter} {@code visitClassBound}? {@code
|
||||
* visitInterfaceBound}* )* ({@code visitParameterType}* {@code visitReturnType} {@code
|
||||
* visitExceptionType}* )
|
||||
* <li><i>TypeSignature</i> = {@code visitBaseType} | {@code visitTypeVariable} | {@code
|
||||
* visitArrayType} | ( {@code visitClassType} {@code visitTypeArgument}* ( {@code
|
||||
* visitInnerClassType} {@code visitTypeArgument}* )* {@code visitEnd} ) )
|
||||
* </ul>
|
||||
*
|
||||
* @author Thomas Hallgren
|
||||
|
|
@ -85,183 +81,154 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public abstract class SignatureVisitor {
|
||||
|
||||
/**
|
||||
* Wildcard for an "extends" type argument.
|
||||
*/
|
||||
public final static char EXTENDS = '+';
|
||||
/** Wildcard for an "extends" type argument. */
|
||||
public static final char EXTENDS = '+';
|
||||
|
||||
/** Wildcard for a "super" type argument. */
|
||||
public static final char SUPER = '-';
|
||||
|
||||
/** Wildcard for a normal type argument. */
|
||||
public static final char INSTANCEOF = '=';
|
||||
|
||||
/**
|
||||
* Wildcard for a "super" type argument.
|
||||
*/
|
||||
public final static char SUPER = '-';
|
||||
|
||||
/**
|
||||
* Wildcard for a normal type argument.
|
||||
*/
|
||||
public final static char INSTANCEOF = '=';
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link SignatureVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Constructs a new {@link SignatureVisitor}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public SignatureVisitor(final int api) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a formal type parameter.
|
||||
*
|
||||
* @param name
|
||||
* the name of the formal parameter.
|
||||
*/
|
||||
public void visitFormalTypeParameter(String name) {
|
||||
}
|
||||
* Visits a formal type parameter.
|
||||
*
|
||||
* @param name the name of the formal parameter.
|
||||
*/
|
||||
public void visitFormalTypeParameter(final String name) {}
|
||||
|
||||
/**
|
||||
* Visits the class bound of the last visited formal type parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the class bound.
|
||||
*/
|
||||
* Visits the class bound of the last visited formal type parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the class bound.
|
||||
*/
|
||||
public SignatureVisitor visitClassBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an interface bound of the last visited formal type parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the interface bound.
|
||||
*/
|
||||
* Visits an interface bound of the last visited formal type parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the interface bound.
|
||||
*/
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the type of the super class.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the super class
|
||||
* type.
|
||||
*/
|
||||
* Visits the type of the super class.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the super class type.
|
||||
*/
|
||||
public SignatureVisitor visitSuperclass() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the type of an interface implemented by the class.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the interface type.
|
||||
*/
|
||||
* Visits the type of an interface implemented by the class.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the interface type.
|
||||
*/
|
||||
public SignatureVisitor visitInterface() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the type of a method parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the parameter type.
|
||||
*/
|
||||
* Visits the type of a method parameter.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the parameter type.
|
||||
*/
|
||||
public SignatureVisitor visitParameterType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the return type of the method.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the return type.
|
||||
*/
|
||||
* Visits the return type of the method.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the return type.
|
||||
*/
|
||||
public SignatureVisitor visitReturnType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the type of a method exception.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the exception type.
|
||||
*/
|
||||
* Visits the type of a method exception.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the exception type.
|
||||
*/
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a signature corresponding to a primitive type.
|
||||
*
|
||||
* @param descriptor
|
||||
* the descriptor of the primitive type, or 'V' for <tt>void</tt>
|
||||
* .
|
||||
*/
|
||||
public void visitBaseType(char descriptor) {
|
||||
}
|
||||
* Visits a signature corresponding to a primitive type.
|
||||
*
|
||||
* @param descriptor the descriptor of the primitive type, or 'V' for {@code void} .
|
||||
*/
|
||||
public void visitBaseType(final char descriptor) {}
|
||||
|
||||
/**
|
||||
* Visits a signature corresponding to a type variable.
|
||||
*
|
||||
* @param name
|
||||
* the name of the type variable.
|
||||
*/
|
||||
public void visitTypeVariable(String name) {
|
||||
}
|
||||
* Visits a signature corresponding to a type variable.
|
||||
*
|
||||
* @param name the name of the type variable.
|
||||
*/
|
||||
public void visitTypeVariable(final String name) {}
|
||||
|
||||
/**
|
||||
* Visits a signature corresponding to an array type.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the array element
|
||||
* type.
|
||||
*/
|
||||
* Visits a signature corresponding to an array type.
|
||||
*
|
||||
* @return a non null visitor to visit the signature of the array element type.
|
||||
*/
|
||||
public SignatureVisitor visitArrayType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the visit of a signature corresponding to a class or interface
|
||||
* type.
|
||||
*
|
||||
* @param name
|
||||
* the internal name of the class or interface.
|
||||
*/
|
||||
public void visitClassType(String name) {
|
||||
}
|
||||
* Starts the visit of a signature corresponding to a class or interface type.
|
||||
*
|
||||
* @param name the internal name of the class or interface.
|
||||
*/
|
||||
public void visitClassType(final String name) {}
|
||||
|
||||
/**
|
||||
* Visits an inner class.
|
||||
*
|
||||
* @param name
|
||||
* the local name of the inner class in its enclosing class.
|
||||
*/
|
||||
public void visitInnerClassType(String name) {
|
||||
}
|
||||
* Visits an inner class.
|
||||
*
|
||||
* @param name the local name of the inner class in its enclosing class.
|
||||
*/
|
||||
public void visitInnerClassType(final String name) {}
|
||||
|
||||
/** Visits an unbounded type argument of the last visited class or inner class type. */
|
||||
public void visitTypeArgument() {}
|
||||
|
||||
/**
|
||||
* Visits an unbounded type argument of the last visited class or inner
|
||||
* class type.
|
||||
*/
|
||||
public void visitTypeArgument() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a type argument of the last visited class or inner class type.
|
||||
*
|
||||
* @param wildcard
|
||||
* '+', '-' or '='.
|
||||
* @return a non null visitor to visit the signature of the type argument.
|
||||
*/
|
||||
public SignatureVisitor visitTypeArgument(char wildcard) {
|
||||
* Visits a type argument of the last visited class or inner class type.
|
||||
*
|
||||
* @param wildcard '+', '-' or '='.
|
||||
* @return a non null visitor to visit the signature of the type argument.
|
||||
*/
|
||||
public SignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the visit of a signature corresponding to a class or interface type.
|
||||
*/
|
||||
public void visitEnd() {
|
||||
}
|
||||
/** Ends the visit of a signature corresponding to a class or interface type. */
|
||||
public void visitEnd() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,55 +61,61 @@ package jdk.internal.org.objectweb.asm.signature;
|
|||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A signature visitor that generates signatures in string format.
|
||||
* A SignatureVisitor that generates signature literals, as defined in the Java Virtual Machine
|
||||
* Specification (JVMS).
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.9.1">JVMS
|
||||
* 4.7.9.1</a>
|
||||
* @author Thomas Hallgren
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class SignatureWriter extends SignatureVisitor {
|
||||
|
||||
/**
|
||||
* Builder used to construct the signature.
|
||||
*/
|
||||
private final StringBuilder buf = new StringBuilder();
|
||||
/** The builder used to construct the visited signature. */
|
||||
private final StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
/**
|
||||
* Indicates if the signature contains formal type parameters.
|
||||
*/
|
||||
/** Whether the visited signature contains formal type parameters. */
|
||||
private boolean hasFormals;
|
||||
|
||||
/**
|
||||
* Indicates if the signature contains method parameter types.
|
||||
*/
|
||||
/** Whether the visited signature contains method parameter types. */
|
||||
private boolean hasParameters;
|
||||
|
||||
/**
|
||||
* Stack used to keep track of class types that have arguments. Each element
|
||||
* of this stack is a boolean encoded in one bit. The top of the stack is
|
||||
* the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
|
||||
* /2.
|
||||
*/
|
||||
* The stack used to keep track of class types that have arguments. Each element of this stack is
|
||||
* a boolean encoded in one bit. The top of the stack is the least significant bit. Pushing false
|
||||
* = *2, pushing true = *2+1, popping = /2.
|
||||
*
|
||||
* <p>Class type arguments must be surrounded with '<' and '>' and, because
|
||||
*
|
||||
* <ol>
|
||||
* <li>class types can be nested (because type arguments can themselves be class types),
|
||||
* <li>SignatureWriter always returns 'this' in each visit* method (to avoid allocating new
|
||||
* SignatureWriter instances),
|
||||
* </ol>
|
||||
*
|
||||
* <p>we need a stack to properly balance these 'parentheses'. A new element is pushed on this
|
||||
* stack for each new visited type, and popped when the visit of this type ends (either is
|
||||
* visitEnd, or because visitInnerClassType is called).
|
||||
*/
|
||||
private int argumentStack;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link SignatureWriter} object.
|
||||
*/
|
||||
/** Constructs a new {@link SignatureWriter}. */
|
||||
public SignatureWriter() {
|
||||
super(Opcodes.ASM6);
|
||||
super(Opcodes.ASM7);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the SignatureVisitor interface
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void visitFormalTypeParameter(final String name) {
|
||||
if (!hasFormals) {
|
||||
hasFormals = true;
|
||||
buf.append('<');
|
||||
stringBuilder.append('<');
|
||||
}
|
||||
buf.append(name);
|
||||
buf.append(':');
|
||||
stringBuilder.append(name);
|
||||
stringBuilder.append(':');
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -119,7 +125,7 @@ public class SignatureWriter extends SignatureVisitor {
|
|||
|
||||
@Override
|
||||
public SignatureVisitor visitInterfaceBound() {
|
||||
buf.append(':');
|
||||
stringBuilder.append(':');
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +145,7 @@ public class SignatureWriter extends SignatureVisitor {
|
|||
endFormals();
|
||||
if (!hasParameters) {
|
||||
hasParameters = true;
|
||||
buf.append('(');
|
||||
stringBuilder.append('(');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
@ -148,68 +154,78 @@ public class SignatureWriter extends SignatureVisitor {
|
|||
public SignatureVisitor visitReturnType() {
|
||||
endFormals();
|
||||
if (!hasParameters) {
|
||||
buf.append('(');
|
||||
stringBuilder.append('(');
|
||||
}
|
||||
buf.append(')');
|
||||
stringBuilder.append(')');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitExceptionType() {
|
||||
buf.append('^');
|
||||
stringBuilder.append('^');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBaseType(final char descriptor) {
|
||||
buf.append(descriptor);
|
||||
stringBuilder.append(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeVariable(final String name) {
|
||||
buf.append('T');
|
||||
buf.append(name);
|
||||
buf.append(';');
|
||||
stringBuilder.append('T');
|
||||
stringBuilder.append(name);
|
||||
stringBuilder.append(';');
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitArrayType() {
|
||||
buf.append('[');
|
||||
stringBuilder.append('[');
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassType(final String name) {
|
||||
buf.append('L');
|
||||
buf.append(name);
|
||||
stringBuilder.append('L');
|
||||
stringBuilder.append(name);
|
||||
// Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
|
||||
// we can tell at this point).
|
||||
argumentStack *= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClassType(final String name) {
|
||||
endArguments();
|
||||
buf.append('.');
|
||||
buf.append(name);
|
||||
stringBuilder.append('.');
|
||||
stringBuilder.append(name);
|
||||
// Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as
|
||||
// we can tell at this point).
|
||||
argumentStack *= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeArgument() {
|
||||
// If the top of the stack is 'false', this means we are visiting the first type argument of the
|
||||
// currently visited type. We therefore need to append a '<', and to replace the top stack
|
||||
// element with 'true' (meaning that the current type does have type arguments).
|
||||
if (argumentStack % 2 == 0) {
|
||||
++argumentStack;
|
||||
buf.append('<');
|
||||
argumentStack |= 1;
|
||||
stringBuilder.append('<');
|
||||
}
|
||||
buf.append('*');
|
||||
stringBuilder.append('*');
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
// If the top of the stack is 'false', this means we are visiting the first type argument of the
|
||||
// currently visited type. We therefore need to append a '<', and to replace the top stack
|
||||
// element with 'true' (meaning that the current type does have type arguments).
|
||||
if (argumentStack % 2 == 0) {
|
||||
++argumentStack;
|
||||
buf.append('<');
|
||||
argumentStack |= 1;
|
||||
stringBuilder.append('<');
|
||||
}
|
||||
if (wildcard != '=') {
|
||||
buf.append(wildcard);
|
||||
stringBuilder.append(wildcard);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
@ -217,39 +233,38 @@ public class SignatureWriter extends SignatureVisitor {
|
|||
@Override
|
||||
public void visitEnd() {
|
||||
endArguments();
|
||||
buf.append(';');
|
||||
stringBuilder.append(';');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signature that was built by this signature writer.
|
||||
*
|
||||
* @return the signature that was built by this signature writer.
|
||||
*/
|
||||
* Returns the signature that was built by this signature writer.
|
||||
*
|
||||
* @return the signature that was built by this signature writer.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return buf.toString();
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Ends the formal type parameters section of the signature.
|
||||
*/
|
||||
/** Ends the formal type parameters section of the signature. */
|
||||
private void endFormals() {
|
||||
if (hasFormals) {
|
||||
hasFormals = false;
|
||||
buf.append('>');
|
||||
stringBuilder.append('>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the type arguments of a class or inner class type.
|
||||
*/
|
||||
/** Ends the type arguments of a class or inner class type. */
|
||||
private void endArguments() {
|
||||
if (argumentStack % 2 != 0) {
|
||||
buf.append('>');
|
||||
// If the top of the stack is 'true', this means that some type arguments have been visited for
|
||||
// the type whose visit is now ending. We therefore need to append a '>', and to pop one element
|
||||
// from the stack.
|
||||
if (argumentStack % 2 == 1) {
|
||||
stringBuilder.append('>');
|
||||
}
|
||||
argumentStack /= 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,293 +61,234 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents a bytecode instruction. <i>An instruction can appear
|
||||
* at most once in at most one {@link InsnList} at a time</i>.
|
||||
* A node that represents a bytecode instruction. <i>An instruction can appear at most once in at
|
||||
* most one {@link InsnList} at a time</i>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The type of {@link InsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link InsnNode} instructions. */
|
||||
public static final int INSN = 0;
|
||||
|
||||
/**
|
||||
* The type of {@link IntInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link IntInsnNode} instructions. */
|
||||
public static final int INT_INSN = 1;
|
||||
|
||||
/**
|
||||
* The type of {@link VarInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link VarInsnNode} instructions. */
|
||||
public static final int VAR_INSN = 2;
|
||||
|
||||
/**
|
||||
* The type of {@link TypeInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link TypeInsnNode} instructions. */
|
||||
public static final int TYPE_INSN = 3;
|
||||
|
||||
/**
|
||||
* The type of {@link FieldInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link FieldInsnNode} instructions. */
|
||||
public static final int FIELD_INSN = 4;
|
||||
|
||||
/**
|
||||
* The type of {@link MethodInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link MethodInsnNode} instructions. */
|
||||
public static final int METHOD_INSN = 5;
|
||||
|
||||
/**
|
||||
* The type of {@link InvokeDynamicInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link InvokeDynamicInsnNode} instructions. */
|
||||
public static final int INVOKE_DYNAMIC_INSN = 6;
|
||||
|
||||
/**
|
||||
* The type of {@link JumpInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link JumpInsnNode} instructions. */
|
||||
public static final int JUMP_INSN = 7;
|
||||
|
||||
/**
|
||||
* The type of {@link LabelNode} "instructions".
|
||||
*/
|
||||
/** The type of {@link LabelNode} "instructions". */
|
||||
public static final int LABEL = 8;
|
||||
|
||||
/**
|
||||
* The type of {@link LdcInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link LdcInsnNode} instructions. */
|
||||
public static final int LDC_INSN = 9;
|
||||
|
||||
/**
|
||||
* The type of {@link IincInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link IincInsnNode} instructions. */
|
||||
public static final int IINC_INSN = 10;
|
||||
|
||||
/**
|
||||
* The type of {@link TableSwitchInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link TableSwitchInsnNode} instructions. */
|
||||
public static final int TABLESWITCH_INSN = 11;
|
||||
|
||||
/**
|
||||
* The type of {@link LookupSwitchInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link LookupSwitchInsnNode} instructions. */
|
||||
public static final int LOOKUPSWITCH_INSN = 12;
|
||||
|
||||
/**
|
||||
* The type of {@link MultiANewArrayInsnNode} instructions.
|
||||
*/
|
||||
/** The type of {@link MultiANewArrayInsnNode} instructions. */
|
||||
public static final int MULTIANEWARRAY_INSN = 13;
|
||||
|
||||
/**
|
||||
* The type of {@link FrameNode} "instructions".
|
||||
*/
|
||||
/** The type of {@link FrameNode} "instructions". */
|
||||
public static final int FRAME = 14;
|
||||
|
||||
/**
|
||||
* The type of {@link LineNumberNode} "instructions".
|
||||
*/
|
||||
/** The type of {@link LineNumberNode} "instructions". */
|
||||
public static final int LINE = 15;
|
||||
|
||||
/**
|
||||
* The opcode of this instruction.
|
||||
*/
|
||||
/** The opcode of this instruction. */
|
||||
protected int opcode;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations of this instruction. This field is
|
||||
* only used for real instructions (i.e. not for labels, frames, or line
|
||||
* number nodes). This list is a list of {@link TypeAnnotationNode} objects.
|
||||
* May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
* The runtime visible type annotations of this instruction. This field is only used for real
|
||||
* instructions (i.e. not for labels, frames, or line number nodes). This list is a list of {@link
|
||||
* TypeAnnotationNode} objects. May be {@literal null}.
|
||||
*/
|
||||
public List<TypeAnnotationNode> visibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations of this instruction. This field is
|
||||
* only used for real instructions (i.e. not for labels, frames, or line
|
||||
* number nodes). This list is a list of {@link TypeAnnotationNode} objects.
|
||||
* May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
* The runtime invisible type annotations of this instruction. This field is only used for real
|
||||
* instructions (i.e. not for labels, frames, or line number nodes). This list is a list of {@link
|
||||
* TypeAnnotationNode} objects. May be {@literal null}.
|
||||
*/
|
||||
public List<TypeAnnotationNode> invisibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* Previous instruction in the list to which this instruction belongs.
|
||||
*/
|
||||
AbstractInsnNode prev;
|
||||
/** The previous instruction in the list to which this instruction belongs. */
|
||||
AbstractInsnNode previousInsn;
|
||||
|
||||
/** The next instruction in the list to which this instruction belongs. */
|
||||
AbstractInsnNode nextInsn;
|
||||
|
||||
/**
|
||||
* Next instruction in the list to which this instruction belongs.
|
||||
*/
|
||||
AbstractInsnNode next;
|
||||
|
||||
/**
|
||||
* Index of this instruction in the list to which it belongs. The value of
|
||||
* this field is correct only when {@link InsnList#cache} is not null. A
|
||||
* value of -1 indicates that this instruction does not belong to any
|
||||
* {@link InsnList}.
|
||||
*/
|
||||
* The index of this instruction in the list to which it belongs. The value of this field is
|
||||
* correct only when {@link InsnList#cache} is not null. A value of -1 indicates that this
|
||||
* instruction does not belong to any {@link InsnList}.
|
||||
*/
|
||||
int index;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AbstractInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the instruction to be constructed.
|
||||
*/
|
||||
* Constructs a new {@link AbstractInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the instruction to be constructed.
|
||||
*/
|
||||
protected AbstractInsnNode(final int opcode) {
|
||||
this.opcode = opcode;
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the opcode of this instruction.
|
||||
*
|
||||
* @return the opcode of this instruction.
|
||||
*/
|
||||
* Returns the opcode of this instruction.
|
||||
*
|
||||
* @return the opcode of this instruction.
|
||||
*/
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this instruction.
|
||||
*
|
||||
* @return the type of this instruction, i.e. one the constants defined in
|
||||
* this class.
|
||||
*/
|
||||
* Returns the type of this instruction.
|
||||
*
|
||||
* @return the type of this instruction, i.e. one the constants defined in this class.
|
||||
*/
|
||||
public abstract int getType();
|
||||
|
||||
/**
|
||||
* Returns the previous instruction in the list to which this instruction
|
||||
* belongs, if any.
|
||||
*
|
||||
* @return the previous instruction in the list to which this instruction
|
||||
* belongs, if any. May be <tt>null</tt>.
|
||||
*/
|
||||
* Returns the previous instruction in the list to which this instruction belongs, if any.
|
||||
*
|
||||
* @return the previous instruction in the list to which this instruction belongs, if any. May be
|
||||
* {@literal null}.
|
||||
*/
|
||||
public AbstractInsnNode getPrevious() {
|
||||
return prev;
|
||||
return previousInsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next instruction in the list to which this instruction
|
||||
* belongs, if any.
|
||||
*
|
||||
* @return the next instruction in the list to which this instruction
|
||||
* belongs, if any. May be <tt>null</tt>.
|
||||
*/
|
||||
* Returns the next instruction in the list to which this instruction belongs, if any.
|
||||
*
|
||||
* @return the next instruction in the list to which this instruction belongs, if any. May be
|
||||
* {@literal null}.
|
||||
*/
|
||||
public AbstractInsnNode getNext() {
|
||||
return next;
|
||||
return nextInsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given code visitor visit this instruction.
|
||||
*
|
||||
* @param cv
|
||||
* a code visitor.
|
||||
*/
|
||||
public abstract void accept(final MethodVisitor cv);
|
||||
* Makes the given method visitor visit this instruction.
|
||||
*
|
||||
* @param methodVisitor a method visitor.
|
||||
*/
|
||||
public abstract void accept(MethodVisitor methodVisitor);
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit the annotations of this instruction.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
protected final void acceptAnnotations(final MethodVisitor mv) {
|
||||
int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
|
||||
.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
|
||||
an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
true));
|
||||
* Makes the given visitor visit the annotations of this instruction.
|
||||
*
|
||||
* @param methodVisitor a method visitor.
|
||||
*/
|
||||
protected final void acceptAnnotations(final MethodVisitor methodVisitor) {
|
||||
if (visibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
methodVisitor.visitInsnAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
|
||||
.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
|
||||
an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
false));
|
||||
if (invisibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
methodVisitor.visitInsnAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this instruction.
|
||||
*
|
||||
* @param labels
|
||||
* a map from LabelNodes to cloned LabelNodes.
|
||||
* @return a copy of this instruction. The returned instruction does not
|
||||
* belong to any {@link InsnList}.
|
||||
*/
|
||||
public abstract AbstractInsnNode clone(
|
||||
final Map<LabelNode, LabelNode> labels);
|
||||
* Returns a copy of this instruction.
|
||||
*
|
||||
* @param clonedLabels a map from LabelNodes to cloned LabelNodes.
|
||||
* @return a copy of this instruction. The returned instruction does not belong to any {@link
|
||||
* InsnList}.
|
||||
*/
|
||||
public abstract AbstractInsnNode clone(Map<LabelNode, LabelNode> clonedLabels);
|
||||
|
||||
/**
|
||||
* Returns the clone of the given label.
|
||||
*
|
||||
* @param label
|
||||
* a label.
|
||||
* @param map
|
||||
* a map from LabelNodes to cloned LabelNodes.
|
||||
* @return the clone of the given label.
|
||||
*/
|
||||
static LabelNode clone(final LabelNode label,
|
||||
final Map<LabelNode, LabelNode> map) {
|
||||
return map.get(label);
|
||||
* Returns the clone of the given label.
|
||||
*
|
||||
* @param label a label.
|
||||
* @param clonedLabels a map from LabelNodes to cloned LabelNodes.
|
||||
* @return the clone of the given label.
|
||||
*/
|
||||
static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return clonedLabels.get(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the clones of the given labels.
|
||||
*
|
||||
* @param labels
|
||||
* a list of labels.
|
||||
* @param map
|
||||
* a map from LabelNodes to cloned LabelNodes.
|
||||
* @return the clones of the given labels.
|
||||
*/
|
||||
static LabelNode[] clone(final List<LabelNode> labels,
|
||||
final Map<LabelNode, LabelNode> map) {
|
||||
* Returns the clones of the given labels.
|
||||
*
|
||||
* @param labels a list of labels.
|
||||
* @param clonedLabels a map from LabelNodes to cloned LabelNodes.
|
||||
* @return the clones of the given labels.
|
||||
*/
|
||||
static LabelNode[] clone(
|
||||
final List<LabelNode> labels, final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
LabelNode[] clones = new LabelNode[labels.size()];
|
||||
for (int i = 0; i < clones.length; ++i) {
|
||||
clones[i] = map.get(labels.get(i));
|
||||
for (int i = 0, n = clones.length; i < n; ++i) {
|
||||
clones[i] = clonedLabels.get(labels.get(i));
|
||||
}
|
||||
return clones;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the annotations of the given instruction into this instruction.
|
||||
*
|
||||
* @param insn
|
||||
* the source instruction.
|
||||
* @return this instruction.
|
||||
*/
|
||||
protected final AbstractInsnNode cloneAnnotations(
|
||||
final AbstractInsnNode insn) {
|
||||
if (insn.visibleTypeAnnotations != null) {
|
||||
* Clones the annotations of the given instruction into this instruction.
|
||||
*
|
||||
* @param insnNode the source instruction.
|
||||
* @return this instruction.
|
||||
*/
|
||||
protected final AbstractInsnNode cloneAnnotations(final AbstractInsnNode insnNode) {
|
||||
if (insnNode.visibleTypeAnnotations != null) {
|
||||
this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
|
||||
for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
|
||||
TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
|
||||
TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
|
||||
src.typePath, src.desc);
|
||||
src.accept(ann);
|
||||
this.visibleTypeAnnotations.add(ann);
|
||||
for (int i = 0, n = insnNode.visibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode sourceAnnotation = insnNode.visibleTypeAnnotations.get(i);
|
||||
TypeAnnotationNode cloneAnnotation =
|
||||
new TypeAnnotationNode(
|
||||
sourceAnnotation.typeRef, sourceAnnotation.typePath, sourceAnnotation.desc);
|
||||
sourceAnnotation.accept(cloneAnnotation);
|
||||
this.visibleTypeAnnotations.add(cloneAnnotation);
|
||||
}
|
||||
}
|
||||
if (insn.invisibleTypeAnnotations != null) {
|
||||
if (insnNode.invisibleTypeAnnotations != null) {
|
||||
this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
|
||||
for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
|
||||
TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
|
||||
TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
|
||||
src.typePath, src.desc);
|
||||
src.accept(ann);
|
||||
this.invisibleTypeAnnotations.add(ann);
|
||||
for (int i = 0, n = insnNode.invisibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode sourceAnnotation = insnNode.invisibleTypeAnnotations.get(i);
|
||||
TypeAnnotationNode cloneAnnotation =
|
||||
new TypeAnnotationNode(
|
||||
sourceAnnotation.typeRef, sourceAnnotation.typePath, sourceAnnotation.desc);
|
||||
sourceAnnotation.accept(cloneAnnotation);
|
||||
this.invisibleTypeAnnotations.add(cloneAnnotation);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
|
|
@ -71,63 +70,52 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public class AnnotationNode extends AnnotationVisitor {
|
||||
|
||||
/**
|
||||
* The class descriptor of the annotation class.
|
||||
*/
|
||||
/** The class descriptor of the annotation class. */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* The name value pairs of this annotation. Each name value pair is stored
|
||||
* as two consecutive elements in the list. The name is a {@link String},
|
||||
* and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
|
||||
* {@link Short}, {@link Integer}, {@link Long}, {@link Float},
|
||||
* {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or a
|
||||
* two elements String array (for enumeration values), an
|
||||
* {@link AnnotationNode}, or a {@link List} of values of one of the
|
||||
* preceding types. The list may be <tt>null</tt> if there is no name value
|
||||
* pair.
|
||||
*/
|
||||
* The name value pairs of this annotation. Each name value pair is stored as two consecutive
|
||||
* elements in the list. The name is a {@link String}, and the value may be a {@link Byte}, {@link
|
||||
* Boolean}, {@link Character}, {@link Short}, {@link Integer}, {@link Long}, {@link Float},
|
||||
* {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or a two elements String
|
||||
* array (for enumeration values), an {@link AnnotationNode}, or a {@link List} of values of one
|
||||
* of the preceding types. The list may be {@literal null} if there is no name value pair.
|
||||
*/
|
||||
public List<Object> values;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the
|
||||
* {@link #AnnotationNode(int, String)} version.
|
||||
*
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
* @throws IllegalStateException
|
||||
* If a subclass calls this constructor.
|
||||
*/
|
||||
public AnnotationNode(final String desc) {
|
||||
this(Opcodes.ASM6, desc);
|
||||
* Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #AnnotationNode(int, String)} version.
|
||||
*
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
* @throws IllegalStateException If a subclass calls this constructor.
|
||||
*/
|
||||
public AnnotationNode(final String descriptor) {
|
||||
this(Opcodes.ASM7, descriptor);
|
||||
if (getClass() != AnnotationNode.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationNode}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
*/
|
||||
public AnnotationNode(final int api, final String desc) {
|
||||
* Constructs a new {@link AnnotationNode}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
*/
|
||||
public AnnotationNode(final int api, final String descriptor) {
|
||||
super(api);
|
||||
this.desc = desc;
|
||||
this.desc = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationNode} to visit an array value.
|
||||
*
|
||||
* @param values
|
||||
* where the visited values must be stored.
|
||||
*/
|
||||
* Constructs a new {@link AnnotationNode} to visit an array value.
|
||||
*
|
||||
* @param values where the visited values must be stored.
|
||||
*/
|
||||
AnnotationNode(final List<Object> values) {
|
||||
super(Opcodes.ASM6);
|
||||
super(Opcodes.ASM7);
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
|
|
@ -144,88 +132,46 @@ public class AnnotationNode extends AnnotationVisitor {
|
|||
values.add(name);
|
||||
}
|
||||
if (value instanceof byte[]) {
|
||||
byte[] v = (byte[]) value;
|
||||
ArrayList<Byte> l = new ArrayList<Byte>(v.length);
|
||||
for (byte b : v) {
|
||||
l.add(b);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((byte[]) value));
|
||||
} else if (value instanceof boolean[]) {
|
||||
boolean[] v = (boolean[]) value;
|
||||
ArrayList<Boolean> l = new ArrayList<Boolean>(v.length);
|
||||
for (boolean b : v) {
|
||||
l.add(b);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((boolean[]) value));
|
||||
} else if (value instanceof short[]) {
|
||||
short[] v = (short[]) value;
|
||||
ArrayList<Short> l = new ArrayList<Short>(v.length);
|
||||
for (short s : v) {
|
||||
l.add(s);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((short[]) value));
|
||||
} else if (value instanceof char[]) {
|
||||
char[] v = (char[]) value;
|
||||
ArrayList<Character> l = new ArrayList<Character>(v.length);
|
||||
for (char c : v) {
|
||||
l.add(c);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((char[]) value));
|
||||
} else if (value instanceof int[]) {
|
||||
int[] v = (int[]) value;
|
||||
ArrayList<Integer> l = new ArrayList<Integer>(v.length);
|
||||
for (int i : v) {
|
||||
l.add(i);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((int[]) value));
|
||||
} else if (value instanceof long[]) {
|
||||
long[] v = (long[]) value;
|
||||
ArrayList<Long> l = new ArrayList<Long>(v.length);
|
||||
for (long lng : v) {
|
||||
l.add(lng);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((long[]) value));
|
||||
} else if (value instanceof float[]) {
|
||||
float[] v = (float[]) value;
|
||||
ArrayList<Float> l = new ArrayList<Float>(v.length);
|
||||
for (float f : v) {
|
||||
l.add(f);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((float[]) value));
|
||||
} else if (value instanceof double[]) {
|
||||
double[] v = (double[]) value;
|
||||
ArrayList<Double> l = new ArrayList<Double>(v.length);
|
||||
for (double d : v) {
|
||||
l.add(d);
|
||||
}
|
||||
values.add(l);
|
||||
values.add(Util.asArrayList((double[]) value));
|
||||
} else {
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(final String name, final String desc,
|
||||
final String value) {
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
if (values == null) {
|
||||
values = new ArrayList<Object>(this.desc != null ? 2 : 1);
|
||||
}
|
||||
if (this.desc != null) {
|
||||
values.add(name);
|
||||
}
|
||||
values.add(new String[] { desc, value });
|
||||
values.add(new String[] {descriptor, value});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String name,
|
||||
final String desc) {
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
if (values == null) {
|
||||
values = new ArrayList<Object>(this.desc != null ? 2 : 1);
|
||||
}
|
||||
if (this.desc != null) {
|
||||
values.add(name);
|
||||
}
|
||||
AnnotationNode annotation = new AnnotationNode(desc);
|
||||
AnnotationNode annotation = new AnnotationNode(descriptor);
|
||||
values.add(annotation);
|
||||
return annotation;
|
||||
}
|
||||
|
|
@ -245,6 +191,7 @@ public class AnnotationNode extends AnnotationVisitor {
|
|||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
@ -252,68 +199,62 @@ public class AnnotationNode extends AnnotationVisitor {
|
|||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks that this annotation node is compatible with the given ASM API
|
||||
* version. This methods checks that this node, and all its nodes
|
||||
* recursively, do not contain elements that were introduced in more recent
|
||||
* versions of the ASM API than the given version.
|
||||
*
|
||||
* @param api
|
||||
* an ASM API version. Must be one of {@link Opcodes#ASM4},
|
||||
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Checks that this annotation node is compatible with the given ASM API version. This method
|
||||
* checks that this node, and all its children recursively, do not contain elements that were
|
||||
* introduced in more recent versions of the ASM API than the given version.
|
||||
*
|
||||
* @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
|
||||
* {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public void check(final int api) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this annotation.
|
||||
*
|
||||
* @param av
|
||||
* an annotation visitor. Maybe <tt>null</tt>.
|
||||
*/
|
||||
public void accept(final AnnotationVisitor av) {
|
||||
if (av != null) {
|
||||
* Makes the given visitor visit this annotation.
|
||||
*
|
||||
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
|
||||
*/
|
||||
public void accept(final AnnotationVisitor annotationVisitor) {
|
||||
if (annotationVisitor != null) {
|
||||
if (values != null) {
|
||||
for (int i = 0; i < values.size(); i += 2) {
|
||||
for (int i = 0, n = values.size(); i < n; i += 2) {
|
||||
String name = (String) values.get(i);
|
||||
Object value = values.get(i + 1);
|
||||
accept(av, name, value);
|
||||
accept(annotationVisitor, name, value);
|
||||
}
|
||||
}
|
||||
av.visitEnd();
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit a given annotation value.
|
||||
*
|
||||
* @param av
|
||||
* an annotation visitor. Maybe <tt>null</tt>.
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param value
|
||||
* the actual value.
|
||||
*/
|
||||
static void accept(final AnnotationVisitor av, final String name,
|
||||
final Object value) {
|
||||
if (av != null) {
|
||||
* Makes the given visitor visit a given annotation value.
|
||||
*
|
||||
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
|
||||
* @param name the value name.
|
||||
* @param value the actual value.
|
||||
*/
|
||||
static void accept(
|
||||
final AnnotationVisitor annotationVisitor, final String name, final Object value) {
|
||||
if (annotationVisitor != null) {
|
||||
if (value instanceof String[]) {
|
||||
String[] typeconst = (String[]) value;
|
||||
av.visitEnum(name, typeconst[0], typeconst[1]);
|
||||
String[] typeValue = (String[]) value;
|
||||
annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
|
||||
} else if (value instanceof AnnotationNode) {
|
||||
AnnotationNode an = (AnnotationNode) value;
|
||||
an.accept(av.visitAnnotation(name, an.desc));
|
||||
AnnotationNode annotationValue = (AnnotationNode) value;
|
||||
annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
|
||||
} else if (value instanceof List) {
|
||||
AnnotationVisitor v = av.visitArray(name);
|
||||
if (v != null) {
|
||||
List<?> array = (List<?>) value;
|
||||
for (int j = 0; j < array.size(); ++j) {
|
||||
accept(v, null, array.get(j));
|
||||
AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
|
||||
if (arrayAnnotationVisitor != null) {
|
||||
List<?> arrayValue = (List<?>) value;
|
||||
for (int i = 0, n = arrayValue.size(); i < n; ++i) {
|
||||
accept(arrayAnnotationVisitor, null, arrayValue.get(i));
|
||||
}
|
||||
v.visitEnd();
|
||||
arrayAnnotationVisitor.visitEnd();
|
||||
}
|
||||
} else {
|
||||
av.visit(name, value);
|
||||
annotationVisitor.visit(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,9 +59,7 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Attribute;
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
|
|
@ -79,167 +77,111 @@ import jdk.internal.org.objectweb.asm.TypePath;
|
|||
public class ClassNode extends ClassVisitor {
|
||||
|
||||
/**
|
||||
* The class version.
|
||||
*/
|
||||
* The class version. The minor version is stored in the 16 most significant bits, and the major
|
||||
* version in the 16 least significant bits.
|
||||
*/
|
||||
public int version;
|
||||
|
||||
/**
|
||||
* The class's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This
|
||||
* field also indicates if the class is deprecated.
|
||||
*/
|
||||
* The class's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This field also indicates if
|
||||
* the class is deprecated.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* The internal name of the class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}).
|
||||
*/
|
||||
/** The internal name of this class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName}). */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The signature of the class. May be <tt>null</tt>.
|
||||
*/
|
||||
/** The signature of this class. May be {@literal null}. */
|
||||
public String signature;
|
||||
|
||||
/**
|
||||
* The internal of name of the super class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). For
|
||||
* interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
|
||||
* only for the {@link Object} class.
|
||||
*/
|
||||
* The internal of name of the super class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName}).
|
||||
* For interfaces, the super class is {@link Object}. May be {@literal null}, but only for the
|
||||
* {@link Object} class.
|
||||
*/
|
||||
public String superName;
|
||||
|
||||
/**
|
||||
* The internal names of the class's interfaces (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). This
|
||||
* list is a list of {@link String} objects.
|
||||
*/
|
||||
* The internal names of the interfaces directly implemented by this class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName}).
|
||||
*/
|
||||
public List<String> interfaces;
|
||||
|
||||
/**
|
||||
* The name of the source file from which this class was compiled. May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
/** The name of the source file from which this class was compiled. May be {@literal null}. */
|
||||
public String sourceFile;
|
||||
|
||||
/**
|
||||
* Debug information to compute the correspondence between source and
|
||||
* compiled elements of the class. May be <tt>null</tt>.
|
||||
*/
|
||||
* The correspondence between source and compiled elements of this class. May be {@literal null}.
|
||||
*/
|
||||
public String sourceDebug;
|
||||
|
||||
/**
|
||||
* Module information. May be <tt>null</tt>.
|
||||
*/
|
||||
/** The module stored in this class. May be {@literal null}. */
|
||||
public ModuleNode module;
|
||||
|
||||
/**
|
||||
* The internal name of the enclosing class of the class. May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
/** The internal name of the enclosing class of this class. May be {@literal null}. */
|
||||
public String outerClass;
|
||||
|
||||
/**
|
||||
* The name of the method that contains the class, or <tt>null</tt> if the
|
||||
* class is not enclosed in a method.
|
||||
*/
|
||||
* The name of the method that contains this class, or {@literal null} if this class is not
|
||||
* enclosed in a method.
|
||||
*/
|
||||
public String outerMethod;
|
||||
|
||||
/**
|
||||
* The descriptor of the method that contains the class, or <tt>null</tt> if
|
||||
* the class is not enclosed in a method.
|
||||
*/
|
||||
* The descriptor of the method that contains this class, or {@literal null} if this class is not
|
||||
* enclosed in a method.
|
||||
*/
|
||||
public String outerMethodDesc;
|
||||
|
||||
/**
|
||||
* The runtime visible annotations of this class. This list is a list of
|
||||
* {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
/** The runtime visible annotations of this class. May be {@literal null}. */
|
||||
public List<AnnotationNode> visibleAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible annotations of this class. This list is a list of
|
||||
* {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
/** The runtime invisible annotations of this class. May be {@literal null}. */
|
||||
public List<AnnotationNode> invisibleAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations of this class. This list is a list
|
||||
* of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
/** The runtime visible type annotations of this class. May be {@literal null}. */
|
||||
public List<TypeAnnotationNode> visibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations of this class. This list is a list
|
||||
* of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
/** The runtime invisible type annotations of this class. May be {@literal null}. */
|
||||
public List<TypeAnnotationNode> invisibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The non standard attributes of this class. This list is a list of
|
||||
* {@link Attribute} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.Attribute
|
||||
*/
|
||||
/** The non standard attributes of this class. May be {@literal null}. */
|
||||
public List<Attribute> attrs;
|
||||
|
||||
/**
|
||||
* Informations about the inner classes of this class. This list is a list
|
||||
* of {@link InnerClassNode} objects.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.InnerClassNode
|
||||
*/
|
||||
/** The inner classes of this class. */
|
||||
public List<InnerClassNode> innerClasses;
|
||||
|
||||
/**
|
||||
* The fields of this class. This list is a list of {@link FieldNode}
|
||||
* objects.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.FieldNode
|
||||
*/
|
||||
/** The internal name of the nest host class of this class. May be {@literal null}. */
|
||||
public String nestHostClass;
|
||||
|
||||
/** The internal names of the nest members of this class. May be {@literal null}. */
|
||||
public List<String> nestMembers;
|
||||
|
||||
/** The fields of this class. */
|
||||
public List<FieldNode> fields;
|
||||
|
||||
/**
|
||||
* The methods of this class. This list is a list of {@link MethodNode}
|
||||
* objects.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.MethodNode
|
||||
*/
|
||||
/** The methods of this class. */
|
||||
public List<MethodNode> methods;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ClassNode}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the {@link #ClassNode(int)}
|
||||
* version.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If a subclass calls this constructor.
|
||||
*/
|
||||
* Constructs a new {@link ClassNode}. <i>Subclasses must not use this constructor</i>. Instead,
|
||||
* they must use the {@link #ClassNode(int)} version.
|
||||
*
|
||||
* @throws IllegalStateException If a subclass calls this constructor.
|
||||
*/
|
||||
public ClassNode() {
|
||||
this(Opcodes.ASM6);
|
||||
this(Opcodes.ASM7);
|
||||
if (getClass() != ClassNode.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ClassNode}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Constructs a new {@link ClassNode}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public ClassNode(final int api) {
|
||||
super(api);
|
||||
this.interfaces = new ArrayList<String>();
|
||||
|
|
@ -248,22 +190,24 @@ public class ClassNode extends ClassVisitor {
|
|||
this.methods = new ArrayList<MethodNode>();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the ClassVisitor abstract class
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void visit(final int version, final int access, final String name,
|
||||
final String signature, final String superName,
|
||||
public void visit(
|
||||
final int version,
|
||||
final int access,
|
||||
final String name,
|
||||
final String signature,
|
||||
final String superName,
|
||||
final String[] interfaces) {
|
||||
this.version = version;
|
||||
this.access = access;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
this.superName = superName;
|
||||
if (interfaces != null) {
|
||||
this.interfaces.addAll(Arrays.asList(interfaces));
|
||||
}
|
||||
this.interfaces = Util.asArrayList(interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -273,214 +217,245 @@ public class ClassNode extends ClassVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ModuleVisitor visitModule(final String name, final int access,
|
||||
final String version) {
|
||||
return module = new ModuleNode(name, access, version);
|
||||
public ModuleVisitor visitModule(final String name, final int access, final String version) {
|
||||
module = new ModuleNode(name, access, version);
|
||||
return module;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(final String owner, final String name,
|
||||
final String desc) {
|
||||
public void visitNestHost(final String nestHost) {
|
||||
this.nestHostClass = nestHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(final String owner, final String name, final String descriptor) {
|
||||
outerClass = owner;
|
||||
outerMethod = name;
|
||||
outerMethodDesc = desc;
|
||||
outerMethodDesc = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc,
|
||||
final boolean visible) {
|
||||
AnnotationNode an = new AnnotationNode(desc);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationNode annotation = new AnnotationNode(descriptor);
|
||||
if (visible) {
|
||||
if (visibleAnnotations == null) {
|
||||
visibleAnnotations = new ArrayList<AnnotationNode>(1);
|
||||
}
|
||||
visibleAnnotations.add(an);
|
||||
visibleAnnotations.add(annotation);
|
||||
} else {
|
||||
if (invisibleAnnotations == null) {
|
||||
invisibleAnnotations = new ArrayList<AnnotationNode>(1);
|
||||
}
|
||||
invisibleAnnotations.add(an);
|
||||
invisibleAnnotations.add(annotation);
|
||||
}
|
||||
return an;
|
||||
return annotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
|
||||
if (visible) {
|
||||
if (visibleTypeAnnotations == null) {
|
||||
visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
|
||||
}
|
||||
visibleTypeAnnotations.add(an);
|
||||
visibleTypeAnnotations.add(typeAnnotation);
|
||||
} else {
|
||||
if (invisibleTypeAnnotations == null) {
|
||||
invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
|
||||
}
|
||||
invisibleTypeAnnotations.add(an);
|
||||
invisibleTypeAnnotations.add(typeAnnotation);
|
||||
}
|
||||
return an;
|
||||
return typeAnnotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(final Attribute attr) {
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (attrs == null) {
|
||||
attrs = new ArrayList<Attribute>(1);
|
||||
}
|
||||
attrs.add(attr);
|
||||
attrs.add(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(final String name, final String outerName,
|
||||
final String innerName, final int access) {
|
||||
InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
|
||||
access);
|
||||
innerClasses.add(icn);
|
||||
public void visitNestMember(final String nestMember) {
|
||||
if (nestMembers == null) {
|
||||
nestMembers = new ArrayList<String>();
|
||||
}
|
||||
nestMembers.add(nestMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(final int access, final String name,
|
||||
final String desc, final String signature, final Object value) {
|
||||
FieldNode fn = new FieldNode(access, name, desc, signature, value);
|
||||
fields.add(fn);
|
||||
return fn;
|
||||
public void visitInnerClass(
|
||||
final String name, final String outerName, final String innerName, final int access) {
|
||||
InnerClassNode innerClass = new InnerClassNode(name, outerName, innerName, access);
|
||||
innerClasses.add(innerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access, final String name,
|
||||
final String desc, final String signature, final String[] exceptions) {
|
||||
MethodNode mn = new MethodNode(access, name, desc, signature,
|
||||
exceptions);
|
||||
methods.add(mn);
|
||||
return mn;
|
||||
public FieldVisitor visitField(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
FieldNode field = new FieldNode(access, name, descriptor, signature, value);
|
||||
fields.add(field);
|
||||
return field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
MethodNode method = new MethodNode(access, name, descriptor, signature, exceptions);
|
||||
methods.add(method);
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Accept method
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks that this class node is compatible with the given ASM API version.
|
||||
* This methods checks that this node, and all its nodes recursively, do not
|
||||
* contain elements that were introduced in more recent versions of the ASM
|
||||
* API than the given version.
|
||||
*
|
||||
* @param api
|
||||
* an ASM API version. Must be one of {@link Opcodes#ASM4},
|
||||
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Checks that this class node is compatible with the given ASM API version. This method checks
|
||||
* that this node, and all its children recursively, do not contain elements that were introduced
|
||||
* in more recent versions of the ASM API than the given version.
|
||||
*
|
||||
* @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
|
||||
* {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public void check(final int api) {
|
||||
if (api < Opcodes.ASM6) {
|
||||
if (module != null) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (api < Opcodes.ASM7 && (nestHostClass != null || nestMembers != null)) {
|
||||
throw new UnsupportedClassVersionException();
|
||||
}
|
||||
if (api < Opcodes.ASM6 && module != null) {
|
||||
throw new UnsupportedClassVersionException();
|
||||
}
|
||||
if (api < Opcodes.ASM5) {
|
||||
if (visibleTypeAnnotations != null
|
||||
&& visibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) {
|
||||
throw new UnsupportedClassVersionException();
|
||||
}
|
||||
if (invisibleTypeAnnotations != null
|
||||
&& invisibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) {
|
||||
throw new UnsupportedClassVersionException();
|
||||
}
|
||||
}
|
||||
// checks attributes
|
||||
int i, n;
|
||||
n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
visibleAnnotations.get(i).check(api);
|
||||
// Check the annotations.
|
||||
if (visibleAnnotations != null) {
|
||||
for (int i = visibleAnnotations.size() - 1; i >= 0; --i) {
|
||||
visibleAnnotations.get(i).check(api);
|
||||
}
|
||||
}
|
||||
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
invisibleAnnotations.get(i).check(api);
|
||||
if (invisibleAnnotations != null) {
|
||||
for (int i = invisibleAnnotations.size() - 1; i >= 0; --i) {
|
||||
invisibleAnnotations.get(i).check(api);
|
||||
}
|
||||
}
|
||||
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
visibleTypeAnnotations.get(i).check(api);
|
||||
if (visibleTypeAnnotations != null) {
|
||||
for (int i = visibleTypeAnnotations.size() - 1; i >= 0; --i) {
|
||||
visibleTypeAnnotations.get(i).check(api);
|
||||
}
|
||||
}
|
||||
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
|
||||
.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
invisibleTypeAnnotations.get(i).check(api);
|
||||
if (invisibleTypeAnnotations != null) {
|
||||
for (int i = invisibleTypeAnnotations.size() - 1; i >= 0; --i) {
|
||||
invisibleTypeAnnotations.get(i).check(api);
|
||||
}
|
||||
}
|
||||
for (FieldNode f : fields) {
|
||||
f.check(api);
|
||||
for (int i = fields.size() - 1; i >= 0; --i) {
|
||||
fields.get(i).check(api);
|
||||
}
|
||||
for (MethodNode m : methods) {
|
||||
m.check(api);
|
||||
for (int i = methods.size() - 1; i >= 0; --i) {
|
||||
methods.get(i).check(api);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given class visitor visit this class.
|
||||
*
|
||||
* @param cv
|
||||
* a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor cv) {
|
||||
// visits header
|
||||
String[] interfaces = new String[this.interfaces.size()];
|
||||
this.interfaces.toArray(interfaces);
|
||||
cv.visit(version, access, name, signature, superName, interfaces);
|
||||
// visits source
|
||||
* Makes the given class visitor visit this class.
|
||||
*
|
||||
* @param classVisitor a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor classVisitor) {
|
||||
// Visit the header.
|
||||
String[] interfacesArray = new String[this.interfaces.size()];
|
||||
this.interfaces.toArray(interfacesArray);
|
||||
classVisitor.visit(version, access, name, signature, superName, interfacesArray);
|
||||
// Visit the source.
|
||||
if (sourceFile != null || sourceDebug != null) {
|
||||
cv.visitSource(sourceFile, sourceDebug);
|
||||
classVisitor.visitSource(sourceFile, sourceDebug);
|
||||
}
|
||||
// visits module
|
||||
// Visit the module.
|
||||
if (module != null) {
|
||||
module.accept(cv);
|
||||
module.accept(classVisitor);
|
||||
}
|
||||
// visits outer class
|
||||
// Visit the nest host class.
|
||||
if (nestHostClass != null) {
|
||||
classVisitor.visitNestHost(nestHostClass);
|
||||
}
|
||||
// Visit the outer class.
|
||||
if (outerClass != null) {
|
||||
cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
|
||||
classVisitor.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
|
||||
}
|
||||
// visits attributes
|
||||
int i, n;
|
||||
n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
AnnotationNode an = visibleAnnotations.get(i);
|
||||
an.accept(cv.visitAnnotation(an.desc, true));
|
||||
// Visit the annotations.
|
||||
if (visibleAnnotations != null) {
|
||||
for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) {
|
||||
AnnotationNode annotation = visibleAnnotations.get(i);
|
||||
annotation.accept(classVisitor.visitAnnotation(annotation.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
AnnotationNode an = invisibleAnnotations.get(i);
|
||||
an.accept(cv.visitAnnotation(an.desc, false));
|
||||
if (invisibleAnnotations != null) {
|
||||
for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) {
|
||||
AnnotationNode annotation = invisibleAnnotations.get(i);
|
||||
annotation.accept(classVisitor.visitAnnotation(annotation.desc, false));
|
||||
}
|
||||
}
|
||||
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
|
||||
an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
true));
|
||||
if (visibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
classVisitor.visitTypeAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
|
||||
.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
|
||||
an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
false));
|
||||
if (invisibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
classVisitor.visitTypeAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
|
||||
}
|
||||
}
|
||||
n = attrs == null ? 0 : attrs.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
cv.visitAttribute(attrs.get(i));
|
||||
// Visit the non standard attributes.
|
||||
if (attrs != null) {
|
||||
for (int i = 0, n = attrs.size(); i < n; ++i) {
|
||||
classVisitor.visitAttribute(attrs.get(i));
|
||||
}
|
||||
}
|
||||
// visits inner classes
|
||||
for (i = 0; i < innerClasses.size(); ++i) {
|
||||
innerClasses.get(i).accept(cv);
|
||||
// Visit the nest members.
|
||||
if (nestMembers != null) {
|
||||
for (int i = 0, n = nestMembers.size(); i < n; ++i) {
|
||||
classVisitor.visitNestMember(nestMembers.get(i));
|
||||
}
|
||||
}
|
||||
// visits fields
|
||||
for (i = 0; i < fields.size(); ++i) {
|
||||
fields.get(i).accept(cv);
|
||||
// Visit the inner classes.
|
||||
for (int i = 0, n = innerClasses.size(); i < n; ++i) {
|
||||
innerClasses.get(i).accept(classVisitor);
|
||||
}
|
||||
// visits methods
|
||||
for (i = 0; i < methods.size(); ++i) {
|
||||
methods.get(i).accept(cv);
|
||||
// Visit the fields.
|
||||
for (int i = 0, n = fields.size(); i < n; ++i) {
|
||||
fields.get(i).accept(classVisitor);
|
||||
}
|
||||
// visits end
|
||||
cv.visitEnd();
|
||||
// Visit the methods.
|
||||
for (int i = 0, n = methods.size(); i < n; ++i) {
|
||||
methods.get(i).accept(classVisitor);
|
||||
}
|
||||
classVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,63 +59,52 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents a field instruction. A field instruction is an
|
||||
* instruction that loads or stores the value of a field of an object.
|
||||
* A node that represents a field instruction. A field instruction is an instruction that loads or
|
||||
* stores the value of a field of an object.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class FieldInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The internal name of the field's owner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}).
|
||||
*/
|
||||
* The internal name of the field's owner class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName}).
|
||||
*/
|
||||
public String owner;
|
||||
|
||||
/**
|
||||
* The field's name.
|
||||
*/
|
||||
/** The field's name. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
/** The field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the type instruction to be constructed. This
|
||||
* opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
|
||||
* @param owner
|
||||
* the internal name of the field's owner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName()
|
||||
* getInternalName}).
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
public FieldInsnNode(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
* Constructs a new {@link FieldInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the type instruction to be constructed. This opcode must be
|
||||
* GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
|
||||
* @param owner the internal name of the field's owner class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName}).
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
public FieldInsnNode(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
super(opcode);
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.desc = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode
|
||||
* the new instruction opcode. This opcode must be GETSTATIC,
|
||||
* PUTSTATIC, GETFIELD or PUTFIELD.
|
||||
*/
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode the new instruction opcode. This opcode must be GETSTATIC, PUTSTATIC, GETFIELD or
|
||||
* PUTFIELD.
|
||||
*/
|
||||
public void setOpcode(final int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
|
@ -126,14 +115,13 @@ public class FieldInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitFieldInsn(opcode, owner, name, desc);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitFieldInsn(opcode, owner, name, desc);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return new FieldInsnNode(opcode, owner, name, desc)
|
||||
.cloneAnnotations(this);
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new FieldInsnNode(opcode, owner, name, desc).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Attribute;
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
|
|
@ -76,261 +75,217 @@ import jdk.internal.org.objectweb.asm.TypePath;
|
|||
public class FieldNode extends FieldVisitor {
|
||||
|
||||
/**
|
||||
* The field's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This
|
||||
* field also indicates if the field is synthetic and/or deprecated.
|
||||
*/
|
||||
* The field's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This field also indicates if
|
||||
* the field is synthetic and/or deprecated.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* The field's name.
|
||||
*/
|
||||
/** The field's name. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
/** The field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* The field's signature. May be <tt>null</tt>.
|
||||
*/
|
||||
/** The field's signature. May be {@literal null}. */
|
||||
public String signature;
|
||||
|
||||
/**
|
||||
* The field's initial value. This field, which may be <tt>null</tt> if the
|
||||
* field does not have an initial value, must be an {@link Integer}, a
|
||||
* {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
|
||||
*/
|
||||
* The field's initial value. This field, which may be {@literal null} if the field does not have
|
||||
* an initial value, must be an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}
|
||||
* or a {@link String}.
|
||||
*/
|
||||
public Object value;
|
||||
|
||||
/**
|
||||
* The runtime visible annotations of this field. This list is a list of
|
||||
* {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
/** The runtime visible annotations of this field. May be {@literal null}. */
|
||||
public List<AnnotationNode> visibleAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible annotations of this field. This list is a list of
|
||||
* {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
/** The runtime invisible annotations of this field. May be {@literal null}. */
|
||||
public List<AnnotationNode> invisibleAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations of this field. This list is a list
|
||||
* of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
/** The runtime visible type annotations of this field. May be {@literal null}. */
|
||||
public List<TypeAnnotationNode> visibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations of this field. This list is a list
|
||||
* of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
/** The runtime invisible type annotations of this field. May be {@literal null}. */
|
||||
public List<TypeAnnotationNode> invisibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The non standard attributes of this field. This list is a list of
|
||||
* {@link Attribute} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.Attribute
|
||||
*/
|
||||
/** The non standard attributes of this field. * May be {@literal null}. */
|
||||
public List<Attribute> attrs;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the
|
||||
* {@link #FieldNode(int, int, String, String, String, Object)} version.
|
||||
*
|
||||
* @param access
|
||||
* the field's access flags (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Opcodes}). This parameter also
|
||||
* indicates if the field is synthetic and/or deprecated.
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type
|
||||
* Type}).
|
||||
* @param signature
|
||||
* the field's signature.
|
||||
* @param value
|
||||
* the field's initial value. This parameter, which may be
|
||||
* <tt>null</tt> if the field does not have an initial value,
|
||||
* must be an {@link Integer}, a {@link Float}, a {@link Long}, a
|
||||
* {@link Double} or a {@link String}.
|
||||
* @throws IllegalStateException
|
||||
* If a subclass calls this constructor.
|
||||
*/
|
||||
public FieldNode(final int access, final String name, final String desc,
|
||||
final String signature, final Object value) {
|
||||
this(Opcodes.ASM6, access, name, desc, signature, value);
|
||||
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this constructor</i>. Instead,
|
||||
* they must use the {@link #FieldNode(int, int, String, String, String, Object)} version.
|
||||
*
|
||||
* @param access the field's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This parameter
|
||||
* also indicates if the field is synthetic and/or deprecated.
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param signature the field's signature.
|
||||
* @param value the field's initial value. This parameter, which may be {@literal null} if the
|
||||
* field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
|
||||
* Long}, a {@link Double} or a {@link String}.
|
||||
* @throws IllegalStateException If a subclass calls this constructor.
|
||||
*/
|
||||
public FieldNode(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
this(Opcodes.ASM7, access, name, descriptor, signature, value);
|
||||
if (getClass() != FieldNode.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
|
||||
* constructor</i>.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
||||
* @param access
|
||||
* the field's access flags (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Opcodes}). This parameter also
|
||||
* indicates if the field is synthetic and/or deprecated.
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type
|
||||
* Type}).
|
||||
* @param signature
|
||||
* the field's signature.
|
||||
* @param value
|
||||
* the field's initial value. This parameter, which may be
|
||||
* <tt>null</tt> if the field does not have an initial value,
|
||||
* must be an {@link Integer}, a {@link Float}, a {@link Long}, a
|
||||
* {@link Double} or a {@link String}.
|
||||
*/
|
||||
public FieldNode(final int api, final int access, final String name,
|
||||
final String desc, final String signature, final Object value) {
|
||||
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this constructor</i>.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM4}
|
||||
* or {@link Opcodes#ASM5}.
|
||||
* @param access the field's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). This parameter
|
||||
* also indicates if the field is synthetic and/or deprecated.
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param signature the field's signature.
|
||||
* @param value the field's initial value. This parameter, which may be {@literal null} if the
|
||||
* field does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
|
||||
* Long}, a {@link Double} or a {@link String}.
|
||||
*/
|
||||
public FieldNode(
|
||||
final int api,
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
super(api);
|
||||
this.access = access;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.desc = descriptor;
|
||||
this.signature = signature;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the FieldVisitor abstract class
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc,
|
||||
final boolean visible) {
|
||||
AnnotationNode an = new AnnotationNode(desc);
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
AnnotationNode annotation = new AnnotationNode(descriptor);
|
||||
if (visible) {
|
||||
if (visibleAnnotations == null) {
|
||||
visibleAnnotations = new ArrayList<AnnotationNode>(1);
|
||||
}
|
||||
visibleAnnotations.add(an);
|
||||
visibleAnnotations.add(annotation);
|
||||
} else {
|
||||
if (invisibleAnnotations == null) {
|
||||
invisibleAnnotations = new ArrayList<AnnotationNode>(1);
|
||||
}
|
||||
invisibleAnnotations.add(an);
|
||||
invisibleAnnotations.add(annotation);
|
||||
}
|
||||
return an;
|
||||
return annotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor);
|
||||
if (visible) {
|
||||
if (visibleTypeAnnotations == null) {
|
||||
visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
|
||||
}
|
||||
visibleTypeAnnotations.add(an);
|
||||
visibleTypeAnnotations.add(typeAnnotation);
|
||||
} else {
|
||||
if (invisibleTypeAnnotations == null) {
|
||||
invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
|
||||
}
|
||||
invisibleTypeAnnotations.add(an);
|
||||
invisibleTypeAnnotations.add(typeAnnotation);
|
||||
}
|
||||
return an;
|
||||
return typeAnnotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(final Attribute attr) {
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (attrs == null) {
|
||||
attrs = new ArrayList<Attribute>(1);
|
||||
}
|
||||
attrs.add(attr);
|
||||
attrs.add(attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Accept methods
|
||||
// ------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks that this field node is compatible with the given ASM API version.
|
||||
* This methods checks that this node, and all its nodes recursively, do not
|
||||
* contain elements that were introduced in more recent versions of the ASM
|
||||
* API than the given version.
|
||||
*
|
||||
* @param api
|
||||
* an ASM API version. Must be one of {@link Opcodes#ASM4},
|
||||
* {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
* Checks that this field node is compatible with the given ASM API version. This method checks
|
||||
* that this node, and all its children recursively, do not contain elements that were introduced
|
||||
* in more recent versions of the ASM API than the given version.
|
||||
*
|
||||
* @param api an ASM API version. Must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5},
|
||||
* {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
*/
|
||||
public void check(final int api) {
|
||||
if (api == Opcodes.ASM4) {
|
||||
if (visibleTypeAnnotations != null
|
||||
&& visibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) {
|
||||
throw new UnsupportedClassVersionException();
|
||||
}
|
||||
if (invisibleTypeAnnotations != null
|
||||
&& invisibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) {
|
||||
throw new UnsupportedClassVersionException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given class visitor visit this field.
|
||||
*
|
||||
* @param cv
|
||||
* a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor cv) {
|
||||
FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
|
||||
if (fv == null) {
|
||||
* Makes the given class visitor visit this field.
|
||||
*
|
||||
* @param classVisitor a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor classVisitor) {
|
||||
FieldVisitor fieldVisitor = classVisitor.visitField(access, name, desc, signature, value);
|
||||
if (fieldVisitor == null) {
|
||||
return;
|
||||
}
|
||||
int i, n;
|
||||
n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
AnnotationNode an = visibleAnnotations.get(i);
|
||||
an.accept(fv.visitAnnotation(an.desc, true));
|
||||
// Visit the annotations.
|
||||
if (visibleAnnotations != null) {
|
||||
for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) {
|
||||
AnnotationNode annotation = visibleAnnotations.get(i);
|
||||
annotation.accept(fieldVisitor.visitAnnotation(annotation.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
AnnotationNode an = invisibleAnnotations.get(i);
|
||||
an.accept(fv.visitAnnotation(an.desc, false));
|
||||
if (invisibleAnnotations != null) {
|
||||
for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) {
|
||||
AnnotationNode annotation = invisibleAnnotations.get(i);
|
||||
annotation.accept(fieldVisitor.visitAnnotation(annotation.desc, false));
|
||||
}
|
||||
}
|
||||
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
|
||||
an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
true));
|
||||
if (visibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
fieldVisitor.visitTypeAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
|
||||
.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
|
||||
an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
false));
|
||||
if (invisibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
fieldVisitor.visitTypeAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
|
||||
}
|
||||
}
|
||||
n = attrs == null ? 0 : attrs.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
fv.visitAttribute(attrs.get(i));
|
||||
// Visit the non standard attributes.
|
||||
if (attrs != null) {
|
||||
for (int i = 0, n = attrs.size(); i < n; ++i) {
|
||||
fieldVisitor.visitAttribute(attrs.get(i));
|
||||
}
|
||||
}
|
||||
fv.visitEnd();
|
||||
fieldVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,51 +59,45 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A node that represents a stack map frame. These nodes are pseudo instruction
|
||||
* nodes in order to be inserted in an instruction list. In fact these nodes
|
||||
* must(*) be inserted <i>just before</i> any instruction node <b>i</b> that
|
||||
* follows an unconditionnal branch instruction such as GOTO or THROW, that is
|
||||
* the target of a jump instruction, or that starts an exception handler block.
|
||||
* The stack map frame types must describe the values of the local variables and
|
||||
* of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
|
||||
* A node that represents a stack map frame. These nodes are pseudo instruction nodes in order to be
|
||||
* inserted in an instruction list. In fact these nodes must(*) be inserted <i>just before</i> any
|
||||
* instruction node <b>i</b> that follows an unconditionnal branch instruction such as GOTO or
|
||||
* THROW, that is the target of a jump instruction, or that starts an exception handler block. The
|
||||
* stack map frame types must describe the values of the local variables and of the operand stack
|
||||
* elements <i>just before</i> <b>i</b> is executed. <br>
|
||||
* <br>
|
||||
* (*) this is mandatory only for classes whose version is greater than or equal
|
||||
* to {@link Opcodes#V1_6 V1_6}.
|
||||
* (*) this is mandatory only for classes whose version is greater than or equal to {@link
|
||||
* Opcodes#V1_6}.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class FrameNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
|
||||
* frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
|
||||
* {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
|
||||
* {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
|
||||
*/
|
||||
* The type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or {@link
|
||||
* Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
|
||||
* {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
|
||||
*/
|
||||
public int type;
|
||||
|
||||
/**
|
||||
* The types of the local variables of this stack map frame. Elements of
|
||||
* this list can be Integer, String or LabelNode objects (for primitive,
|
||||
* reference and uninitialized types respectively - see
|
||||
* {@link MethodVisitor}).
|
||||
*/
|
||||
* The types of the local variables of this stack map frame. Elements of this list can be Integer,
|
||||
* String or LabelNode objects (for primitive, reference and uninitialized types respectively -
|
||||
* see {@link MethodVisitor}).
|
||||
*/
|
||||
public List<Object> local;
|
||||
|
||||
/**
|
||||
* The types of the operand stack elements of this stack map frame. Elements
|
||||
* of this list can be Integer, String or LabelNode objects (for primitive,
|
||||
* reference and uninitialized types respectively - see
|
||||
* {@link MethodVisitor}).
|
||||
*/
|
||||
* The types of the operand stack elements of this stack map frame. Elements of this list can be
|
||||
* Integer, String or LabelNode objects (for primitive, reference and uninitialized types
|
||||
* respectively - see {@link MethodVisitor}).
|
||||
*/
|
||||
public List<Object> stack;
|
||||
|
||||
private FrameNode() {
|
||||
|
|
@ -111,50 +105,47 @@ public class FrameNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FrameNode}.
|
||||
*
|
||||
* @param type
|
||||
* the type of this frame. Must be {@link Opcodes#F_NEW} for
|
||||
* expanded frames, or {@link Opcodes#F_FULL},
|
||||
* {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
|
||||
* {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
|
||||
* {@link Opcodes#F_SAME1} for compressed frames.
|
||||
* @param nLocal
|
||||
* number of local variables of this stack map frame.
|
||||
* @param local
|
||||
* the types of the local variables of this stack map frame.
|
||||
* Elements of this list can be Integer, String or LabelNode
|
||||
* objects (for primitive, reference and uninitialized types
|
||||
* respectively - see {@link MethodVisitor}).
|
||||
* @param nStack
|
||||
* number of operand stack elements of this stack map frame.
|
||||
* @param stack
|
||||
* the types of the operand stack elements of this stack map
|
||||
* frame. Elements of this list can be Integer, String or
|
||||
* LabelNode objects (for primitive, reference and uninitialized
|
||||
* types respectively - see {@link MethodVisitor}).
|
||||
*/
|
||||
public FrameNode(final int type, final int nLocal, final Object[] local,
|
||||
final int nStack, final Object[] stack) {
|
||||
* Constructs a new {@link FrameNode}.
|
||||
*
|
||||
* @param type the type of this frame. Must be {@link Opcodes#F_NEW} for expanded frames, or
|
||||
* {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link
|
||||
* Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
|
||||
* @param numLocal number of local variables of this stack map frame.
|
||||
* @param local the types of the local variables of this stack map frame. Elements of this list
|
||||
* can be Integer, String or LabelNode objects (for primitive, reference and uninitialized
|
||||
* types respectively - see {@link MethodVisitor}).
|
||||
* @param numStack number of operand stack elements of this stack map frame.
|
||||
* @param stack the types of the operand stack elements of this stack map frame. Elements of this
|
||||
* list can be Integer, String or LabelNode objects (for primitive, reference and
|
||||
* uninitialized types respectively - see {@link MethodVisitor}).
|
||||
*/
|
||||
public FrameNode(
|
||||
final int type,
|
||||
final int numLocal,
|
||||
final Object[] local,
|
||||
final int numStack,
|
||||
final Object[] stack) {
|
||||
super(-1);
|
||||
this.type = type;
|
||||
switch (type) {
|
||||
case Opcodes.F_NEW:
|
||||
case Opcodes.F_FULL:
|
||||
this.local = asList(nLocal, local);
|
||||
this.stack = asList(nStack, stack);
|
||||
break;
|
||||
case Opcodes.F_APPEND:
|
||||
this.local = asList(nLocal, local);
|
||||
break;
|
||||
case Opcodes.F_CHOP:
|
||||
this.local = Arrays.asList(new Object[nLocal]);
|
||||
break;
|
||||
case Opcodes.F_SAME:
|
||||
break;
|
||||
case Opcodes.F_SAME1:
|
||||
this.stack = asList(1, stack);
|
||||
break;
|
||||
case Opcodes.F_NEW:
|
||||
case Opcodes.F_FULL:
|
||||
this.local = Util.asArrayList(numLocal, local);
|
||||
this.stack = Util.asArrayList(numStack, stack);
|
||||
break;
|
||||
case Opcodes.F_APPEND:
|
||||
this.local = Util.asArrayList(numLocal, local);
|
||||
break;
|
||||
case Opcodes.F_CHOP:
|
||||
this.local = Util.asArrayList(numLocal);
|
||||
break;
|
||||
case Opcodes.F_SAME:
|
||||
break;
|
||||
case Opcodes.F_SAME1:
|
||||
this.stack = Util.asArrayList(1, stack);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,77 +154,66 @@ public class FrameNode extends AbstractInsnNode {
|
|||
return FRAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this stack map frame.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
switch (type) {
|
||||
case Opcodes.F_NEW:
|
||||
case Opcodes.F_FULL:
|
||||
mv.visitFrame(type, local.size(), asArray(local), stack.size(),
|
||||
asArray(stack));
|
||||
break;
|
||||
case Opcodes.F_APPEND:
|
||||
mv.visitFrame(type, local.size(), asArray(local), 0, null);
|
||||
break;
|
||||
case Opcodes.F_CHOP:
|
||||
mv.visitFrame(type, local.size(), null, 0, null);
|
||||
break;
|
||||
case Opcodes.F_SAME:
|
||||
mv.visitFrame(type, 0, null, 0, null);
|
||||
break;
|
||||
case Opcodes.F_SAME1:
|
||||
mv.visitFrame(type, 0, null, 1, asArray(stack));
|
||||
break;
|
||||
case Opcodes.F_NEW:
|
||||
case Opcodes.F_FULL:
|
||||
methodVisitor.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack));
|
||||
break;
|
||||
case Opcodes.F_APPEND:
|
||||
methodVisitor.visitFrame(type, local.size(), asArray(local), 0, null);
|
||||
break;
|
||||
case Opcodes.F_CHOP:
|
||||
methodVisitor.visitFrame(type, local.size(), null, 0, null);
|
||||
break;
|
||||
case Opcodes.F_SAME:
|
||||
methodVisitor.visitFrame(type, 0, null, 0, null);
|
||||
break;
|
||||
case Opcodes.F_SAME1:
|
||||
methodVisitor.visitFrame(type, 0, null, 1, asArray(stack));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
FrameNode clone = new FrameNode();
|
||||
clone.type = type;
|
||||
if (local != null) {
|
||||
clone.local = new ArrayList<Object>();
|
||||
for (int i = 0; i < local.size(); ++i) {
|
||||
Object l = local.get(i);
|
||||
if (l instanceof LabelNode) {
|
||||
l = labels.get(l);
|
||||
for (int i = 0, n = local.size(); i < n; ++i) {
|
||||
Object localElement = local.get(i);
|
||||
if (localElement instanceof LabelNode) {
|
||||
localElement = clonedLabels.get(localElement);
|
||||
}
|
||||
clone.local.add(l);
|
||||
clone.local.add(localElement);
|
||||
}
|
||||
}
|
||||
if (stack != null) {
|
||||
clone.stack = new ArrayList<Object>();
|
||||
for (int i = 0; i < stack.size(); ++i) {
|
||||
Object s = stack.get(i);
|
||||
if (s instanceof LabelNode) {
|
||||
s = labels.get(s);
|
||||
for (int i = 0, n = stack.size(); i < n; ++i) {
|
||||
Object stackElement = stack.get(i);
|
||||
if (stackElement instanceof LabelNode) {
|
||||
stackElement = clonedLabels.get(stackElement);
|
||||
}
|
||||
clone.stack.add(s);
|
||||
clone.stack.add(stackElement);
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
private static List<Object> asList(final int n, final Object[] o) {
|
||||
return Arrays.asList(o).subList(0, n);
|
||||
}
|
||||
|
||||
private static Object[] asArray(final List<Object> l) {
|
||||
Object[] objs = new Object[l.size()];
|
||||
for (int i = 0; i < objs.length; ++i) {
|
||||
Object o = l.get(i);
|
||||
private static Object[] asArray(final List<Object> list) {
|
||||
Object[] array = new Object[list.size()];
|
||||
for (int i = 0, n = array.length; i < n; ++i) {
|
||||
Object o = list.get(i);
|
||||
if (o instanceof LabelNode) {
|
||||
o = ((LabelNode) o).getLabel();
|
||||
}
|
||||
objs[i] = o;
|
||||
array[i] = o;
|
||||
}
|
||||
return objs;
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
|
|
@ -70,24 +69,18 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public class IincInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* Index of the local variable to be incremented.
|
||||
*/
|
||||
/** Index of the local variable to be incremented. */
|
||||
public int var;
|
||||
|
||||
/**
|
||||
* Amount to increment the local variable by.
|
||||
*/
|
||||
/** Amount to increment the local variable by. */
|
||||
public int incr;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link IincInsnNode}.
|
||||
*
|
||||
* @param var
|
||||
* index of the local variable to be incremented.
|
||||
* @param incr
|
||||
* increment amount to increment the local variable by.
|
||||
*/
|
||||
* Constructs a new {@link IincInsnNode}.
|
||||
*
|
||||
* @param var index of the local variable to be incremented.
|
||||
* @param incr increment amount to increment the local variable by.
|
||||
*/
|
||||
public IincInsnNode(final int var, final int incr) {
|
||||
super(Opcodes.IINC);
|
||||
this.var = var;
|
||||
|
|
@ -100,13 +93,13 @@ public class IincInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitIincInsn(var, incr);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitIincInsn(var, incr);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new IincInsnNode(var, incr).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,51 +67,38 @@ import jdk.internal.org.objectweb.asm.ClassVisitor;
|
|||
*/
|
||||
public class InnerClassNode {
|
||||
|
||||
/**
|
||||
* The internal name of an inner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}).
|
||||
*/
|
||||
/** The internal name of an inner class (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()}). */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The internal name of the class to which the inner class belongs (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
* The internal name of the class to which the inner class belongs (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
|
||||
*/
|
||||
public String outerName;
|
||||
|
||||
/**
|
||||
* The (simple) name of the inner class inside its enclosing class. May be
|
||||
* <tt>null</tt> for anonymous inner classes.
|
||||
*/
|
||||
* The (simple) name of the inner class inside its enclosing class. May be {@literal null} for
|
||||
* anonymous inner classes.
|
||||
*/
|
||||
public String innerName;
|
||||
|
||||
/**
|
||||
* The access flags of the inner class as originally declared in the
|
||||
* enclosing class.
|
||||
*/
|
||||
/** The access flags of the inner class as originally declared in the enclosing class. */
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link InnerClassNode}.
|
||||
*
|
||||
* @param name
|
||||
* the internal name of an inner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName()
|
||||
* getInternalName}).
|
||||
* @param outerName
|
||||
* the internal name of the class to which the inner class
|
||||
* belongs (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName()
|
||||
* getInternalName}). May be <tt>null</tt>.
|
||||
* @param innerName
|
||||
* the (simple) name of the inner class inside its enclosing
|
||||
* class. May be <tt>null</tt> for anonymous inner classes.
|
||||
* @param access
|
||||
* the access flags of the inner class as originally declared in
|
||||
* the enclosing class.
|
||||
*/
|
||||
public InnerClassNode(final String name, final String outerName,
|
||||
final String innerName, final int access) {
|
||||
* Constructs a new {@link InnerClassNode}.
|
||||
*
|
||||
* @param name the internal name of an inner class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
|
||||
* @param outerName the internal name of the class to which the inner class belongs (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}). May be {@literal null}.
|
||||
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
|
||||
* {@literal null} for anonymous inner classes.
|
||||
* @param access the access flags of the inner class as originally declared in the enclosing
|
||||
* class.
|
||||
*/
|
||||
public InnerClassNode(
|
||||
final String name, final String outerName, final String innerName, final int access) {
|
||||
this.name = name;
|
||||
this.outerName = outerName;
|
||||
this.innerName = innerName;
|
||||
|
|
@ -119,12 +106,11 @@ public class InnerClassNode {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes the given class visitor visit this inner class.
|
||||
*
|
||||
* @param cv
|
||||
* a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor cv) {
|
||||
cv.visitInnerClass(name, outerName, innerName, access);
|
||||
* Makes the given class visitor visit this inner class.
|
||||
*
|
||||
* @param classVisitor a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor classVisitor) {
|
||||
classVisitor.visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,77 +60,66 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A doubly linked list of {@link AbstractInsnNode} objects. <i>This
|
||||
* implementation is not thread safe</i>.
|
||||
* A doubly linked list of {@link AbstractInsnNode} objects. <i>This implementation is not thread
|
||||
* safe</i>.
|
||||
*/
|
||||
public class InsnList {
|
||||
|
||||
/**
|
||||
* The number of instructions in this list.
|
||||
*/
|
||||
/** The number of instructions in this list. */
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* The first instruction in this list. May be <tt>null</tt>.
|
||||
*/
|
||||
private AbstractInsnNode first;
|
||||
/** The first instruction in this list. May be {@literal null}. */
|
||||
private AbstractInsnNode firstInsn;
|
||||
|
||||
/** The last instruction in this list. May be {@literal null}. */
|
||||
private AbstractInsnNode lastInsn;
|
||||
|
||||
/**
|
||||
* The last instruction in this list. May be <tt>null</tt>.
|
||||
*/
|
||||
private AbstractInsnNode last;
|
||||
|
||||
/**
|
||||
* A cache of the instructions of this list. This cache is used to improve
|
||||
* the performance of the {@link #get} method.
|
||||
*/
|
||||
* A cache of the instructions of this list. This cache is used to improve the performance of the
|
||||
* {@link #get} method.
|
||||
*/
|
||||
AbstractInsnNode[] cache;
|
||||
|
||||
/**
|
||||
* Returns the number of instructions in this list.
|
||||
*
|
||||
* @return the number of instructions in this list.
|
||||
*/
|
||||
* Returns the number of instructions in this list.
|
||||
*
|
||||
* @return the number of instructions in this list.
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first instruction in this list.
|
||||
*
|
||||
* @return the first instruction in this list, or <tt>null</tt> if the list
|
||||
* is empty.
|
||||
*/
|
||||
* Returns the first instruction in this list.
|
||||
*
|
||||
* @return the first instruction in this list, or {@literal null} if the list is empty.
|
||||
*/
|
||||
public AbstractInsnNode getFirst() {
|
||||
return first;
|
||||
return firstInsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last instruction in this list.
|
||||
*
|
||||
* @return the last instruction in this list, or <tt>null</tt> if the list
|
||||
* is empty.
|
||||
*/
|
||||
* Returns the last instruction in this list.
|
||||
*
|
||||
* @return the last instruction in this list, or {@literal null} if the list is empty.
|
||||
*/
|
||||
public AbstractInsnNode getLast() {
|
||||
return last;
|
||||
return lastInsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instruction whose index is given. This method builds a cache
|
||||
* of the instructions in this list to avoid scanning the whole list each
|
||||
* time it is called. Once the cache is built, this method run in constant
|
||||
* time. This cache is invalidated by all the methods that modify the list.
|
||||
*
|
||||
* @param index
|
||||
* the index of the instruction that must be returned.
|
||||
* @return the instruction whose index is given.
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if (index < 0 || index >= size()).
|
||||
*/
|
||||
* Returns the instruction whose index is given. This method builds a cache of the instructions in
|
||||
* this list to avoid scanning the whole list each time it is called. Once the cache is built,
|
||||
* this method runs in constant time. This cache is invalidated by all the methods that modify the
|
||||
* list.
|
||||
*
|
||||
* @param index the index of the instruction that must be returned.
|
||||
* @return the instruction whose index is given.
|
||||
* @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
|
||||
*/
|
||||
public AbstractInsnNode get(final int index) {
|
||||
if (index < 0 || index >= size) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
|
@ -142,457 +131,425 @@ public class InsnList {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the given instruction belongs to this list. This
|
||||
* method always scans the instructions of this list until it finds the
|
||||
* given instruction or reaches the end of the list.
|
||||
*
|
||||
* @param insn
|
||||
* an instruction.
|
||||
* @return <tt>true</tt> if the given instruction belongs to this list.
|
||||
*/
|
||||
public boolean contains(final AbstractInsnNode insn) {
|
||||
AbstractInsnNode i = first;
|
||||
while (i != null && i != insn) {
|
||||
i = i.next;
|
||||
* Returns {@literal true} if the given instruction belongs to this list. This method always scans
|
||||
* the instructions of this list until it finds the given instruction or reaches the end of the
|
||||
* list.
|
||||
*
|
||||
* @param insnNode an instruction.
|
||||
* @return {@literal true} if the given instruction belongs to this list.
|
||||
*/
|
||||
public boolean contains(final AbstractInsnNode insnNode) {
|
||||
AbstractInsnNode currentInsn = firstInsn;
|
||||
while (currentInsn != null && currentInsn != insnNode) {
|
||||
currentInsn = currentInsn.nextInsn;
|
||||
}
|
||||
return i != null;
|
||||
return currentInsn != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the given instruction in this list. This method
|
||||
* builds a cache of the instruction indexes to avoid scanning the whole
|
||||
* list each time it is called. Once the cache is built, this method run in
|
||||
* constant time. The cache is invalidated by all the methods that modify
|
||||
* the list.
|
||||
*
|
||||
* @param insn
|
||||
* an instruction <i>of this list</i>.
|
||||
* @return the index of the given instruction in this list. <i>The result of
|
||||
* this method is undefined if the given instruction does not belong
|
||||
* to this list</i>. Use {@link #contains contains} to test if an
|
||||
* instruction belongs to an instruction list or not.
|
||||
*/
|
||||
public int indexOf(final AbstractInsnNode insn) {
|
||||
* Returns the index of the given instruction in this list. This method builds a cache of the
|
||||
* instruction indexes to avoid scanning the whole list each time it is called. Once the cache is
|
||||
* built, this method run in constant time. The cache is invalidated by all the methods that
|
||||
* modify the list.
|
||||
*
|
||||
* @param insnNode an instruction <i>of this list</i>.
|
||||
* @return the index of the given instruction in this list. <i>The result of this method is
|
||||
* undefined if the given instruction does not belong to this list</i>. Use {@link #contains }
|
||||
* to test if an instruction belongs to an instruction list or not.
|
||||
*/
|
||||
public int indexOf(final AbstractInsnNode insnNode) {
|
||||
if (cache == null) {
|
||||
cache = toArray();
|
||||
}
|
||||
return insn.index;
|
||||
return insnNode.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit all of the instructions in this list.
|
||||
*
|
||||
* @param mv
|
||||
* the method visitor that must visit the instructions.
|
||||
*/
|
||||
public void accept(final MethodVisitor mv) {
|
||||
AbstractInsnNode insn = first;
|
||||
while (insn != null) {
|
||||
insn.accept(mv);
|
||||
insn = insn.next;
|
||||
* Makes the given visitor visit all the instructions in this list.
|
||||
*
|
||||
* @param methodVisitor the method visitor that must visit the instructions.
|
||||
*/
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
AbstractInsnNode currentInsn = firstInsn;
|
||||
while (currentInsn != null) {
|
||||
currentInsn.accept(methodVisitor);
|
||||
currentInsn = currentInsn.nextInsn;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the instructions in this list.
|
||||
*
|
||||
* @return an iterator over the instructions in this list.
|
||||
*/
|
||||
* Returns an iterator over the instructions in this list.
|
||||
*
|
||||
* @return an iterator over the instructions in this list.
|
||||
*/
|
||||
public ListIterator<AbstractInsnNode> iterator() {
|
||||
return iterator(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the instructions in this list.
|
||||
*
|
||||
* @param index
|
||||
* index of instruction for the iterator to start at
|
||||
*
|
||||
* @return an iterator over the instructions in this list.
|
||||
*/
|
||||
* Returns an iterator over the instructions in this list.
|
||||
*
|
||||
* @param index index of instruction for the iterator to start at.
|
||||
* @return an iterator over the instructions in this list.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator<AbstractInsnNode> iterator(int index) {
|
||||
public ListIterator<AbstractInsnNode> iterator(final int index) {
|
||||
return new InsnListIterator(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the instructions in this list.
|
||||
*
|
||||
* @return an array containing all of the instructions in this list.
|
||||
*/
|
||||
* Returns an array containing all the instructions in this list.
|
||||
*
|
||||
* @return an array containing all the instructions in this list.
|
||||
*/
|
||||
public AbstractInsnNode[] toArray() {
|
||||
int i = 0;
|
||||
AbstractInsnNode elem = first;
|
||||
AbstractInsnNode[] insns = new AbstractInsnNode[size];
|
||||
while (elem != null) {
|
||||
insns[i] = elem;
|
||||
elem.index = i++;
|
||||
elem = elem.next;
|
||||
int currentInsnIndex = 0;
|
||||
AbstractInsnNode currentInsn = firstInsn;
|
||||
AbstractInsnNode[] insnNodeArray = new AbstractInsnNode[size];
|
||||
while (currentInsn != null) {
|
||||
insnNodeArray[currentInsnIndex] = currentInsn;
|
||||
currentInsn.index = currentInsnIndex++;
|
||||
currentInsn = currentInsn.nextInsn;
|
||||
}
|
||||
return insns;
|
||||
return insnNodeArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an instruction of this list with another instruction.
|
||||
*
|
||||
* @param location
|
||||
* an instruction <i>of this list</i>.
|
||||
* @param insn
|
||||
* another instruction, <i>which must not belong to any
|
||||
* {@link InsnList}</i>.
|
||||
*/
|
||||
public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
|
||||
AbstractInsnNode next = location.next;
|
||||
insn.next = next;
|
||||
if (next != null) {
|
||||
next.prev = insn;
|
||||
* Replaces an instruction of this list with another instruction.
|
||||
*
|
||||
* @param oldInsnNode an instruction <i>of this list</i>.
|
||||
* @param newInsnNode another instruction, <i>which must not belong to any {@link InsnList}</i>.
|
||||
*/
|
||||
public void set(final AbstractInsnNode oldInsnNode, final AbstractInsnNode newInsnNode) {
|
||||
AbstractInsnNode nextInsn = oldInsnNode.nextInsn;
|
||||
newInsnNode.nextInsn = nextInsn;
|
||||
if (nextInsn != null) {
|
||||
nextInsn.previousInsn = newInsnNode;
|
||||
} else {
|
||||
last = insn;
|
||||
lastInsn = newInsnNode;
|
||||
}
|
||||
AbstractInsnNode prev = location.prev;
|
||||
insn.prev = prev;
|
||||
if (prev != null) {
|
||||
prev.next = insn;
|
||||
AbstractInsnNode previousInsn = oldInsnNode.previousInsn;
|
||||
newInsnNode.previousInsn = previousInsn;
|
||||
if (previousInsn != null) {
|
||||
previousInsn.nextInsn = newInsnNode;
|
||||
} else {
|
||||
first = insn;
|
||||
firstInsn = newInsnNode;
|
||||
}
|
||||
if (cache != null) {
|
||||
int index = location.index;
|
||||
cache[index] = insn;
|
||||
insn.index = index;
|
||||
int index = oldInsnNode.index;
|
||||
cache[index] = newInsnNode;
|
||||
newInsnNode.index = index;
|
||||
} else {
|
||||
insn.index = 0; // insn now belongs to an InsnList
|
||||
newInsnNode.index = 0; // newInnsnNode now belongs to an InsnList.
|
||||
}
|
||||
location.index = -1; // i no longer belongs to an InsnList
|
||||
location.prev = null;
|
||||
location.next = null;
|
||||
oldInsnNode.index = -1; // oldInsnNode no longer belongs to an InsnList.
|
||||
oldInsnNode.previousInsn = null;
|
||||
oldInsnNode.nextInsn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given instruction to the end of this list.
|
||||
*
|
||||
* @param insn
|
||||
* an instruction, <i>which must not belong to any
|
||||
* {@link InsnList}</i>.
|
||||
*/
|
||||
public void add(final AbstractInsnNode insn) {
|
||||
* Adds the given instruction to the end of this list.
|
||||
*
|
||||
* @param insnNode an instruction, <i>which must not belong to any {@link InsnList}</i>.
|
||||
*/
|
||||
public void add(final AbstractInsnNode insnNode) {
|
||||
++size;
|
||||
if (last == null) {
|
||||
first = insn;
|
||||
last = insn;
|
||||
if (lastInsn == null) {
|
||||
firstInsn = insnNode;
|
||||
lastInsn = insnNode;
|
||||
} else {
|
||||
last.next = insn;
|
||||
insn.prev = last;
|
||||
lastInsn.nextInsn = insnNode;
|
||||
insnNode.previousInsn = lastInsn;
|
||||
}
|
||||
last = insn;
|
||||
lastInsn = insnNode;
|
||||
cache = null;
|
||||
insn.index = 0; // insn now belongs to an InsnList
|
||||
insnNode.index = 0; // insnNode now belongs to an InsnList.
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given instructions to the end of this list.
|
||||
*
|
||||
* @param insns
|
||||
* an instruction list, which is cleared during the process. This
|
||||
* list must be different from 'this'.
|
||||
*/
|
||||
public void add(final InsnList insns) {
|
||||
if (insns.size == 0) {
|
||||
* Adds the given instructions to the end of this list.
|
||||
*
|
||||
* @param insnList an instruction list, which is cleared during the process. This list must be
|
||||
* different from 'this'.
|
||||
*/
|
||||
public void add(final InsnList insnList) {
|
||||
if (insnList.size == 0) {
|
||||
return;
|
||||
}
|
||||
size += insns.size;
|
||||
if (last == null) {
|
||||
first = insns.first;
|
||||
last = insns.last;
|
||||
size += insnList.size;
|
||||
if (lastInsn == null) {
|
||||
firstInsn = insnList.firstInsn;
|
||||
lastInsn = insnList.lastInsn;
|
||||
} else {
|
||||
AbstractInsnNode elem = insns.first;
|
||||
last.next = elem;
|
||||
elem.prev = last;
|
||||
last = insns.last;
|
||||
AbstractInsnNode firstInsnListElement = insnList.firstInsn;
|
||||
lastInsn.nextInsn = firstInsnListElement;
|
||||
firstInsnListElement.previousInsn = lastInsn;
|
||||
lastInsn = insnList.lastInsn;
|
||||
}
|
||||
cache = null;
|
||||
insns.removeAll(false);
|
||||
insnList.removeAll(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given instruction at the begining of this list.
|
||||
*
|
||||
* @param insn
|
||||
* an instruction, <i>which must not belong to any
|
||||
* {@link InsnList}</i>.
|
||||
*/
|
||||
public void insert(final AbstractInsnNode insn) {
|
||||
* Inserts the given instruction at the beginning of this list.
|
||||
*
|
||||
* @param insnNode an instruction, <i>which must not belong to any {@link InsnList}</i>.
|
||||
*/
|
||||
public void insert(final AbstractInsnNode insnNode) {
|
||||
++size;
|
||||
if (first == null) {
|
||||
first = insn;
|
||||
last = insn;
|
||||
if (firstInsn == null) {
|
||||
firstInsn = insnNode;
|
||||
lastInsn = insnNode;
|
||||
} else {
|
||||
first.prev = insn;
|
||||
insn.next = first;
|
||||
firstInsn.previousInsn = insnNode;
|
||||
insnNode.nextInsn = firstInsn;
|
||||
}
|
||||
first = insn;
|
||||
firstInsn = insnNode;
|
||||
cache = null;
|
||||
insn.index = 0; // insn now belongs to an InsnList
|
||||
insnNode.index = 0; // insnNode now belongs to an InsnList.
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given instructions at the begining of this list.
|
||||
*
|
||||
* @param insns
|
||||
* an instruction list, which is cleared during the process. This
|
||||
* list must be different from 'this'.
|
||||
*/
|
||||
public void insert(final InsnList insns) {
|
||||
if (insns.size == 0) {
|
||||
* Inserts the given instructions at the beginning of this list.
|
||||
*
|
||||
* @param insnList an instruction list, which is cleared during the process. This list must be
|
||||
* different from 'this'.
|
||||
*/
|
||||
public void insert(final InsnList insnList) {
|
||||
if (insnList.size == 0) {
|
||||
return;
|
||||
}
|
||||
size += insns.size;
|
||||
if (first == null) {
|
||||
first = insns.first;
|
||||
last = insns.last;
|
||||
size += insnList.size;
|
||||
if (firstInsn == null) {
|
||||
firstInsn = insnList.firstInsn;
|
||||
lastInsn = insnList.lastInsn;
|
||||
} else {
|
||||
AbstractInsnNode elem = insns.last;
|
||||
first.prev = elem;
|
||||
elem.next = first;
|
||||
first = insns.first;
|
||||
AbstractInsnNode lastInsnListElement = insnList.lastInsn;
|
||||
firstInsn.previousInsn = lastInsnListElement;
|
||||
lastInsnListElement.nextInsn = firstInsn;
|
||||
firstInsn = insnList.firstInsn;
|
||||
}
|
||||
cache = null;
|
||||
insns.removeAll(false);
|
||||
insnList.removeAll(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given instruction after the specified instruction.
|
||||
*
|
||||
* @param location
|
||||
* an instruction <i>of this list</i> after which insn must be
|
||||
* inserted.
|
||||
* @param insn
|
||||
* the instruction to be inserted, <i>which must not belong to
|
||||
* any {@link InsnList}</i>.
|
||||
*/
|
||||
public void insert(final AbstractInsnNode location,
|
||||
final AbstractInsnNode insn) {
|
||||
* Inserts the given instruction after the specified instruction.
|
||||
*
|
||||
* @param previousInsn an instruction <i>of this list</i> after which insnNode must be inserted.
|
||||
* @param insnNode the instruction to be inserted, <i>which must not belong to any {@link
|
||||
* InsnList}</i>.
|
||||
*/
|
||||
public void insert(final AbstractInsnNode previousInsn, final AbstractInsnNode insnNode) {
|
||||
++size;
|
||||
AbstractInsnNode next = location.next;
|
||||
if (next == null) {
|
||||
last = insn;
|
||||
AbstractInsnNode nextInsn = previousInsn.nextInsn;
|
||||
if (nextInsn == null) {
|
||||
lastInsn = insnNode;
|
||||
} else {
|
||||
next.prev = insn;
|
||||
nextInsn.previousInsn = insnNode;
|
||||
}
|
||||
location.next = insn;
|
||||
insn.next = next;
|
||||
insn.prev = location;
|
||||
previousInsn.nextInsn = insnNode;
|
||||
insnNode.nextInsn = nextInsn;
|
||||
insnNode.previousInsn = previousInsn;
|
||||
cache = null;
|
||||
insn.index = 0; // insn now belongs to an InsnList
|
||||
insnNode.index = 0; // insnNode now belongs to an InsnList.
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given instructions after the specified instruction.
|
||||
*
|
||||
* @param location
|
||||
* an instruction <i>of this list</i> after which the
|
||||
* instructions must be inserted.
|
||||
* @param insns
|
||||
* the instruction list to be inserted, which is cleared during
|
||||
* the process. This list must be different from 'this'.
|
||||
*/
|
||||
public void insert(final AbstractInsnNode location, final InsnList insns) {
|
||||
if (insns.size == 0) {
|
||||
* Inserts the given instructions after the specified instruction.
|
||||
*
|
||||
* @param previousInsn an instruction <i>of this list</i> after which the instructions must be
|
||||
* inserted.
|
||||
* @param insnList the instruction list to be inserted, which is cleared during the process. This
|
||||
* list must be different from 'this'.
|
||||
*/
|
||||
public void insert(final AbstractInsnNode previousInsn, final InsnList insnList) {
|
||||
if (insnList.size == 0) {
|
||||
return;
|
||||
}
|
||||
size += insns.size;
|
||||
AbstractInsnNode ifirst = insns.first;
|
||||
AbstractInsnNode ilast = insns.last;
|
||||
AbstractInsnNode next = location.next;
|
||||
if (next == null) {
|
||||
last = ilast;
|
||||
size += insnList.size;
|
||||
AbstractInsnNode firstInsnListElement = insnList.firstInsn;
|
||||
AbstractInsnNode lastInsnListElement = insnList.lastInsn;
|
||||
AbstractInsnNode nextInsn = previousInsn.nextInsn;
|
||||
if (nextInsn == null) {
|
||||
lastInsn = lastInsnListElement;
|
||||
} else {
|
||||
next.prev = ilast;
|
||||
nextInsn.previousInsn = lastInsnListElement;
|
||||
}
|
||||
location.next = ifirst;
|
||||
ilast.next = next;
|
||||
ifirst.prev = location;
|
||||
previousInsn.nextInsn = firstInsnListElement;
|
||||
lastInsnListElement.nextInsn = nextInsn;
|
||||
firstInsnListElement.previousInsn = previousInsn;
|
||||
cache = null;
|
||||
insns.removeAll(false);
|
||||
insnList.removeAll(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given instruction before the specified instruction.
|
||||
*
|
||||
* @param location
|
||||
* an instruction <i>of this list</i> before which insn must be
|
||||
* inserted.
|
||||
* @param insn
|
||||
* the instruction to be inserted, <i>which must not belong to
|
||||
* any {@link InsnList}</i>.
|
||||
*/
|
||||
public void insertBefore(final AbstractInsnNode location,
|
||||
final AbstractInsnNode insn) {
|
||||
* Inserts the given instruction before the specified instruction.
|
||||
*
|
||||
* @param nextInsn an instruction <i>of this list</i> before which insnNode must be inserted.
|
||||
* @param insnNode the instruction to be inserted, <i>which must not belong to any {@link
|
||||
* InsnList}</i>.
|
||||
*/
|
||||
public void insertBefore(final AbstractInsnNode nextInsn, final AbstractInsnNode insnNode) {
|
||||
++size;
|
||||
AbstractInsnNode prev = location.prev;
|
||||
if (prev == null) {
|
||||
first = insn;
|
||||
AbstractInsnNode previousInsn = nextInsn.previousInsn;
|
||||
if (previousInsn == null) {
|
||||
firstInsn = insnNode;
|
||||
} else {
|
||||
prev.next = insn;
|
||||
previousInsn.nextInsn = insnNode;
|
||||
}
|
||||
location.prev = insn;
|
||||
insn.next = location;
|
||||
insn.prev = prev;
|
||||
nextInsn.previousInsn = insnNode;
|
||||
insnNode.nextInsn = nextInsn;
|
||||
insnNode.previousInsn = previousInsn;
|
||||
cache = null;
|
||||
insn.index = 0; // insn now belongs to an InsnList
|
||||
insnNode.index = 0; // insnNode now belongs to an InsnList.
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given instructions before the specified instruction.
|
||||
*
|
||||
* @param location
|
||||
* an instruction <i>of this list</i> before which the
|
||||
* instructions must be inserted.
|
||||
* @param insns
|
||||
* the instruction list to be inserted, which is cleared during
|
||||
* the process. This list must be different from 'this'.
|
||||
*/
|
||||
public void insertBefore(final AbstractInsnNode location,
|
||||
final InsnList insns) {
|
||||
if (insns.size == 0) {
|
||||
* Inserts the given instructions before the specified instruction.
|
||||
*
|
||||
* @param nextInsn an instruction <i>of this list</i> before which the instructions must be
|
||||
* inserted.
|
||||
* @param insnList the instruction list to be inserted, which is cleared during the process. This
|
||||
* list must be different from 'this'.
|
||||
*/
|
||||
public void insertBefore(final AbstractInsnNode nextInsn, final InsnList insnList) {
|
||||
if (insnList.size == 0) {
|
||||
return;
|
||||
}
|
||||
size += insns.size;
|
||||
AbstractInsnNode ifirst = insns.first;
|
||||
AbstractInsnNode ilast = insns.last;
|
||||
AbstractInsnNode prev = location.prev;
|
||||
if (prev == null) {
|
||||
first = ifirst;
|
||||
size += insnList.size;
|
||||
AbstractInsnNode firstInsnListElement = insnList.firstInsn;
|
||||
AbstractInsnNode lastInsnListElement = insnList.lastInsn;
|
||||
AbstractInsnNode previousInsn = nextInsn.previousInsn;
|
||||
if (previousInsn == null) {
|
||||
firstInsn = firstInsnListElement;
|
||||
} else {
|
||||
prev.next = ifirst;
|
||||
previousInsn.nextInsn = firstInsnListElement;
|
||||
}
|
||||
location.prev = ilast;
|
||||
ilast.next = location;
|
||||
ifirst.prev = prev;
|
||||
nextInsn.previousInsn = lastInsnListElement;
|
||||
lastInsnListElement.nextInsn = nextInsn;
|
||||
firstInsnListElement.previousInsn = previousInsn;
|
||||
cache = null;
|
||||
insns.removeAll(false);
|
||||
insnList.removeAll(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given instruction from this list.
|
||||
*
|
||||
* @param insn
|
||||
* the instruction <i>of this list</i> that must be removed.
|
||||
*/
|
||||
public void remove(final AbstractInsnNode insn) {
|
||||
* Removes the given instruction from this list.
|
||||
*
|
||||
* @param insnNode the instruction <i>of this list</i> that must be removed.
|
||||
*/
|
||||
public void remove(final AbstractInsnNode insnNode) {
|
||||
--size;
|
||||
AbstractInsnNode next = insn.next;
|
||||
AbstractInsnNode prev = insn.prev;
|
||||
if (next == null) {
|
||||
if (prev == null) {
|
||||
first = null;
|
||||
last = null;
|
||||
AbstractInsnNode nextInsn = insnNode.nextInsn;
|
||||
AbstractInsnNode previousInsn = insnNode.previousInsn;
|
||||
if (nextInsn == null) {
|
||||
if (previousInsn == null) {
|
||||
firstInsn = null;
|
||||
lastInsn = null;
|
||||
} else {
|
||||
prev.next = null;
|
||||
last = prev;
|
||||
previousInsn.nextInsn = null;
|
||||
lastInsn = previousInsn;
|
||||
}
|
||||
} else {
|
||||
if (prev == null) {
|
||||
first = next;
|
||||
next.prev = null;
|
||||
if (previousInsn == null) {
|
||||
firstInsn = nextInsn;
|
||||
nextInsn.previousInsn = null;
|
||||
} else {
|
||||
prev.next = next;
|
||||
next.prev = prev;
|
||||
previousInsn.nextInsn = nextInsn;
|
||||
nextInsn.previousInsn = previousInsn;
|
||||
}
|
||||
}
|
||||
cache = null;
|
||||
insn.index = -1; // insn no longer belongs to an InsnList
|
||||
insn.prev = null;
|
||||
insn.next = null;
|
||||
insnNode.index = -1; // insnNode no longer belongs to an InsnList.
|
||||
insnNode.previousInsn = null;
|
||||
insnNode.nextInsn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the instructions of this list.
|
||||
*
|
||||
* @param mark
|
||||
* if the instructions must be marked as no longer belonging to
|
||||
* any {@link InsnList}.
|
||||
*/
|
||||
* Removes all the instructions of this list.
|
||||
*
|
||||
* @param mark if the instructions must be marked as no longer belonging to any {@link InsnList}.
|
||||
*/
|
||||
void removeAll(final boolean mark) {
|
||||
if (mark) {
|
||||
AbstractInsnNode insn = first;
|
||||
while (insn != null) {
|
||||
AbstractInsnNode next = insn.next;
|
||||
insn.index = -1; // insn no longer belongs to an InsnList
|
||||
insn.prev = null;
|
||||
insn.next = null;
|
||||
insn = next;
|
||||
AbstractInsnNode currentInsn = firstInsn;
|
||||
while (currentInsn != null) {
|
||||
AbstractInsnNode next = currentInsn.nextInsn;
|
||||
currentInsn.index = -1; // currentInsn no longer belongs to an InsnList.
|
||||
currentInsn.previousInsn = null;
|
||||
currentInsn.nextInsn = null;
|
||||
currentInsn = next;
|
||||
}
|
||||
}
|
||||
size = 0;
|
||||
first = null;
|
||||
last = null;
|
||||
firstInsn = null;
|
||||
lastInsn = null;
|
||||
cache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the instructions of this list.
|
||||
*/
|
||||
/** Removes all the instructions of this list. */
|
||||
public void clear() {
|
||||
removeAll(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all labels in the instruction list. This method should be called
|
||||
* before reusing same instructions list between several
|
||||
* <code>ClassWriter</code>s.
|
||||
*/
|
||||
* Resets all the labels in the instruction list. This method should be called before reusing an
|
||||
* instruction list between several <code>ClassWriter</code>s.
|
||||
*/
|
||||
public void resetLabels() {
|
||||
AbstractInsnNode insn = first;
|
||||
while (insn != null) {
|
||||
if (insn instanceof LabelNode) {
|
||||
((LabelNode) insn).resetLabel();
|
||||
AbstractInsnNode currentInsn = firstInsn;
|
||||
while (currentInsn != null) {
|
||||
if (currentInsn instanceof LabelNode) {
|
||||
((LabelNode) currentInsn).resetLabel();
|
||||
}
|
||||
insn = insn.next;
|
||||
currentInsn = currentInsn.nextInsn;
|
||||
}
|
||||
}
|
||||
|
||||
// this class is not generified because it will create bridges
|
||||
// Note: this class is not generified because it would create bridges.
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final class InsnListIterator implements ListIterator {
|
||||
|
||||
AbstractInsnNode next;
|
||||
AbstractInsnNode nextInsn;
|
||||
|
||||
AbstractInsnNode prev;
|
||||
AbstractInsnNode previousInsn;
|
||||
|
||||
AbstractInsnNode remove;
|
||||
|
||||
InsnListIterator(int index) {
|
||||
InsnListIterator(final int index) {
|
||||
if (index == size()) {
|
||||
next = null;
|
||||
prev = getLast();
|
||||
nextInsn = null;
|
||||
previousInsn = getLast();
|
||||
} else {
|
||||
next = get(index);
|
||||
prev = next.prev;
|
||||
nextInsn = get(index);
|
||||
previousInsn = nextInsn.previousInsn;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
return nextInsn != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
if (next == null) {
|
||||
if (nextInsn == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
AbstractInsnNode result = next;
|
||||
prev = result;
|
||||
next = result.next;
|
||||
AbstractInsnNode result = nextInsn;
|
||||
previousInsn = result;
|
||||
nextInsn = result.nextInsn;
|
||||
remove = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (remove != null) {
|
||||
if (remove == next) {
|
||||
next = next.next;
|
||||
if (remove == nextInsn) {
|
||||
nextInsn = nextInsn.nextInsn;
|
||||
} else {
|
||||
prev = prev.prev;
|
||||
previousInsn = previousInsn.previousInsn;
|
||||
}
|
||||
InsnList.this.remove(remove);
|
||||
remove = null;
|
||||
|
|
@ -601,57 +558,63 @@ public class InsnList {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return prev != null;
|
||||
return previousInsn != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object previous() {
|
||||
AbstractInsnNode result = prev;
|
||||
next = result;
|
||||
prev = result.prev;
|
||||
AbstractInsnNode result = previousInsn;
|
||||
nextInsn = result;
|
||||
previousInsn = result.previousInsn;
|
||||
remove = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
if (next == null) {
|
||||
if (nextInsn == null) {
|
||||
return size();
|
||||
}
|
||||
if (cache == null) {
|
||||
cache = toArray();
|
||||
}
|
||||
return next.index;
|
||||
return nextInsn.index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
if (prev == null) {
|
||||
if (previousInsn == null) {
|
||||
return -1;
|
||||
}
|
||||
if (cache == null) {
|
||||
cache = toArray();
|
||||
}
|
||||
return prev.index;
|
||||
return previousInsn.index;
|
||||
}
|
||||
|
||||
public void add(Object o) {
|
||||
if (next != null) {
|
||||
InsnList.this.insertBefore(next, (AbstractInsnNode) o);
|
||||
} else if (prev != null) {
|
||||
InsnList.this.insert(prev, (AbstractInsnNode) o);
|
||||
@Override
|
||||
public void add(final Object o) {
|
||||
if (nextInsn != null) {
|
||||
InsnList.this.insertBefore(nextInsn, (AbstractInsnNode) o);
|
||||
} else if (previousInsn != null) {
|
||||
InsnList.this.insert(previousInsn, (AbstractInsnNode) o);
|
||||
} else {
|
||||
InsnList.this.add((AbstractInsnNode) o);
|
||||
}
|
||||
prev = (AbstractInsnNode) o;
|
||||
previousInsn = (AbstractInsnNode) o;
|
||||
remove = null;
|
||||
}
|
||||
|
||||
public void set(Object o) {
|
||||
@Override
|
||||
public void set(final Object o) {
|
||||
if (remove != null) {
|
||||
InsnList.this.set(remove, (AbstractInsnNode) o);
|
||||
if (remove == prev) {
|
||||
prev = (AbstractInsnNode) o;
|
||||
if (remove == previousInsn) {
|
||||
previousInsn = (AbstractInsnNode) o;
|
||||
} else {
|
||||
next = (AbstractInsnNode) o;
|
||||
nextInsn = (AbstractInsnNode) o;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
|
|
@ -70,25 +69,19 @@ import jdk.internal.org.objectweb.asm.MethodVisitor;
|
|||
public class InsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* Constructs a new {@link InsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the instruction to be constructed. This opcode
|
||||
* must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
|
||||
* ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
|
||||
* FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
|
||||
* LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
|
||||
* IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
|
||||
* SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
|
||||
* DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
|
||||
* IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
|
||||
* FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
|
||||
* IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
|
||||
* L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
|
||||
* LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
|
||||
* DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
|
||||
* or MONITOREXIT.
|
||||
*/
|
||||
* Constructs a new {@link InsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the instruction to be constructed. This opcode must be NOP,
|
||||
* ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5,
|
||||
* LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
|
||||
* FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, DASTORE,
|
||||
* AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2,
|
||||
* SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
|
||||
* FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR,
|
||||
* LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I,
|
||||
* D2L, D2F, I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
|
||||
* DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or MONITOREXIT.
|
||||
*/
|
||||
public InsnNode(final int opcode) {
|
||||
super(opcode);
|
||||
}
|
||||
|
|
@ -98,20 +91,14 @@ public class InsnNode extends AbstractInsnNode {
|
|||
return INSN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this instruction.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitInsn(opcode);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitInsn(opcode);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new InsnNode(opcode).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
|
|
@ -69,32 +68,26 @@ import jdk.internal.org.objectweb.asm.MethodVisitor;
|
|||
*/
|
||||
public class IntInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The operand of this instruction.
|
||||
*/
|
||||
/** The operand of this instruction. */
|
||||
public int operand;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link IntInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the instruction to be constructed. This opcode
|
||||
* must be BIPUSH, SIPUSH or NEWARRAY.
|
||||
* @param operand
|
||||
* the operand of the instruction to be constructed.
|
||||
*/
|
||||
* Constructs a new {@link IntInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the instruction to be constructed. This opcode must be BIPUSH,
|
||||
* SIPUSH or NEWARRAY.
|
||||
* @param operand the operand of the instruction to be constructed.
|
||||
*/
|
||||
public IntInsnNode(final int opcode, final int operand) {
|
||||
super(opcode);
|
||||
this.operand = operand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode
|
||||
* the new instruction opcode. This opcode must be BIPUSH, SIPUSH
|
||||
* or NEWARRAY.
|
||||
*/
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode the new instruction opcode. This opcode must be BIPUSH, SIPUSH or NEWARRAY.
|
||||
*/
|
||||
public void setOpcode(final int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
|
@ -105,13 +98,13 @@ public class IntInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitIntInsn(opcode, operand);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitIntInsn(opcode, operand);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new IntInsnNode(opcode, operand).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
|
@ -71,45 +70,39 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public class InvokeDynamicInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* Invokedynamic name.
|
||||
*/
|
||||
/** The method's name. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* Invokedynamic descriptor.
|
||||
*/
|
||||
/** The method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* Bootstrap method
|
||||
*/
|
||||
/** The bootstrap method. */
|
||||
public Handle bsm;
|
||||
|
||||
/**
|
||||
* Bootstrap constant arguments
|
||||
*/
|
||||
/** The bootstrap method constant arguments. */
|
||||
public Object[] bsmArgs;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link InvokeDynamicInsnNode}.
|
||||
*
|
||||
* @param name
|
||||
* invokedynamic name.
|
||||
* @param desc
|
||||
* invokedynamic descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param bsm
|
||||
* the bootstrap method.
|
||||
* @param bsmArgs
|
||||
* the boostrap constant arguments.
|
||||
*/
|
||||
public InvokeDynamicInsnNode(final String name, final String desc,
|
||||
final Handle bsm, final Object... bsmArgs) {
|
||||
* Constructs a new {@link InvokeDynamicInsnNode}.
|
||||
*
|
||||
* @param name the method's name.
|
||||
* @param descriptor the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param bootstrapMethodHandle the bootstrap method.
|
||||
* @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
|
||||
* an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
|
||||
* jdk.internal.org.objectweb.asm.Type} or {@link Handle} value. This method is allowed to modify the
|
||||
* content of the array so a caller should expect that this array may change.
|
||||
*/
|
||||
public InvokeDynamicInsnNode(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final Handle bootstrapMethodHandle,
|
||||
final Object... bootstrapMethodArguments) { // NOPMD(ArrayIsStoredDirectly): public field.
|
||||
super(Opcodes.INVOKEDYNAMIC);
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.bsm = bsm;
|
||||
this.bsmArgs = bsmArgs;
|
||||
this.desc = descriptor;
|
||||
this.bsm = bootstrapMethodHandle;
|
||||
this.bsmArgs = bootstrapMethodArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -118,14 +111,13 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
|
||||
.cloneAnnotations(this);
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,50 +59,43 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents a jump instruction. A jump instruction is an
|
||||
* instruction that may jump to another instruction.
|
||||
* A node that represents a jump instruction. A jump instruction is an instruction that may jump to
|
||||
* another instruction.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class JumpInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The operand of this instruction. This operand is a label that designates
|
||||
* the instruction to which this instruction may jump.
|
||||
*/
|
||||
* The operand of this instruction. This operand is a label that designates the instruction to
|
||||
* which this instruction may jump.
|
||||
*/
|
||||
public LabelNode label;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link JumpInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the type instruction to be constructed. This
|
||||
* opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
|
||||
* IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
|
||||
* IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
|
||||
* @param label
|
||||
* the operand of the instruction to be constructed. This operand
|
||||
* is a label that designates the instruction to which the jump
|
||||
* instruction may jump.
|
||||
*/
|
||||
* Constructs a new {@link JumpInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the type instruction to be constructed. This opcode must be IFEQ,
|
||||
* IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT,
|
||||
* IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
|
||||
* @param label the operand of the instruction to be constructed. This operand is a label that
|
||||
* designates the instruction to which the jump instruction may jump.
|
||||
*/
|
||||
public JumpInsnNode(final int opcode, final LabelNode label) {
|
||||
super(opcode);
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode
|
||||
* the new instruction opcode. This opcode must be IFEQ, IFNE,
|
||||
* IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
|
||||
* IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO,
|
||||
* JSR, IFNULL or IFNONNULL.
|
||||
*/
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT,
|
||||
* IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
|
||||
* IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
|
||||
*/
|
||||
public void setOpcode(final int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
|
@ -113,14 +106,13 @@ public class JumpInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitJumpInsn(opcode, label.getLabel());
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitJumpInsn(opcode, label.getLabel());
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return new JumpInsnNode(opcode, clone(label, labels))
|
||||
.cloneAnnotations(this);
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new JumpInsnNode(opcode, clone(label, clonedLabels)).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,16 +59,13 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* An {@link AbstractInsnNode} that encapsulates a {@link Label}.
|
||||
*/
|
||||
/** An {@link AbstractInsnNode} that encapsulates a {@link Label}. */
|
||||
public class LabelNode extends AbstractInsnNode {
|
||||
|
||||
private Label label;
|
||||
private Label value;
|
||||
|
||||
public LabelNode() {
|
||||
super(-1);
|
||||
|
|
@ -76,7 +73,7 @@ public class LabelNode extends AbstractInsnNode {
|
|||
|
||||
public LabelNode(final Label label) {
|
||||
super(-1);
|
||||
this.label = label;
|
||||
this.value = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -84,24 +81,30 @@ public class LabelNode extends AbstractInsnNode {
|
|||
return LABEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label encapsulated by this node. A new label is created and associated with this
|
||||
* node if it was created without an encapsulated label.
|
||||
*
|
||||
* @return the label encapsulated by this node.
|
||||
*/
|
||||
public Label getLabel() {
|
||||
if (label == null) {
|
||||
label = new Label();
|
||||
if (value == null) {
|
||||
value = new Label();
|
||||
}
|
||||
return label;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor cv) {
|
||||
cv.visitLabel(getLabel());
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitLabel(getLabel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return labels.get(this);
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return clonedLabels.get(this);
|
||||
}
|
||||
|
||||
public void resetLabel() {
|
||||
label = null;
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
|
|
@ -71,23 +70,21 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
public class LdcInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The constant to be loaded on the stack. This parameter must be a non null
|
||||
* {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a
|
||||
* {@link String} or a {@link jdk.internal.org.objectweb.asm.Type}.
|
||||
*/
|
||||
* The constant to be loaded on the stack. This parameter must be a non null {@link Integer}, a
|
||||
* {@link Float}, a {@link Long}, a {@link Double}, a {@link String} or a {@link
|
||||
* jdk.internal.org.objectweb.asm.Type}.
|
||||
*/
|
||||
public Object cst;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LdcInsnNode}.
|
||||
*
|
||||
* @param cst
|
||||
* the constant to be loaded on the stack. This parameter must be
|
||||
* a non null {@link Integer}, a {@link Float}, a {@link Long}, a
|
||||
* {@link Double} or a {@link String}.
|
||||
*/
|
||||
public LdcInsnNode(final Object cst) {
|
||||
* Constructs a new {@link LdcInsnNode}.
|
||||
*
|
||||
* @param value the constant to be loaded on the stack. This parameter must be a non null {@link
|
||||
* Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
|
||||
*/
|
||||
public LdcInsnNode(final Object value) {
|
||||
super(Opcodes.LDC);
|
||||
this.cst = cst;
|
||||
this.cst = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -96,13 +93,13 @@ public class LdcInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitLdcInsn(cst);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitLdcInsn(cst);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new LdcInsnNode(cst).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,37 +59,29 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents a line number declaration. These nodes are pseudo
|
||||
* instruction nodes in order to be inserted in an instruction list.
|
||||
* A node that represents a line number declaration. These nodes are pseudo instruction nodes in
|
||||
* order to be inserted in an instruction list.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class LineNumberNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* A line number. This number refers to the source file from which the class
|
||||
* was compiled.
|
||||
*/
|
||||
/** A line number. This number refers to the source file from which the class was compiled. */
|
||||
public int line;
|
||||
|
||||
/**
|
||||
* The first instruction corresponding to this line number.
|
||||
*/
|
||||
/** The first instruction corresponding to this line number. */
|
||||
public LabelNode start;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LineNumberNode}.
|
||||
*
|
||||
* @param line
|
||||
* a line number. This number refers to the source file from
|
||||
* which the class was compiled.
|
||||
* @param start
|
||||
* the first instruction corresponding to this line number.
|
||||
*/
|
||||
* Constructs a new {@link LineNumberNode}.
|
||||
*
|
||||
* @param line a line number. This number refers to the source file from which the class was
|
||||
* compiled.
|
||||
* @param start the first instruction corresponding to this line number.
|
||||
*/
|
||||
public LineNumberNode(final int line, final LabelNode start) {
|
||||
super(-1);
|
||||
this.line = line;
|
||||
|
|
@ -102,12 +94,12 @@ public class LineNumberNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitLineNumber(line, start.getLabel());
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitLineNumber(line, start.getLabel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return new LineNumberNode(line, clone(start, labels));
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new LineNumberNode(line, clone(start, clonedLabels));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,18 +56,13 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.TypePath;
|
||||
import jdk.internal.org.objectweb.asm.TypeReference;
|
||||
|
||||
/**
|
||||
* A node that represents a type annotation on a local or resource variable.
|
||||
|
|
@ -77,110 +72,99 @@ import jdk.internal.org.objectweb.asm.TypeReference;
|
|||
public class LocalVariableAnnotationNode extends TypeAnnotationNode {
|
||||
|
||||
/**
|
||||
* The fist instructions corresponding to the continuous ranges that make
|
||||
* the scope of this local variable (inclusive). Must not be <tt>null</tt>.
|
||||
*/
|
||||
* The fist instructions corresponding to the continuous ranges that make the scope of this local
|
||||
* variable (inclusive). Must not be {@literal null}.
|
||||
*/
|
||||
public List<LabelNode> start;
|
||||
|
||||
/**
|
||||
* The last instructions corresponding to the continuous ranges that make
|
||||
* the scope of this local variable (exclusive). This list must have the
|
||||
* same size as the 'start' list. Must not be <tt>null</tt>.
|
||||
*/
|
||||
* The last instructions corresponding to the continuous ranges that make the scope of this local
|
||||
* variable (exclusive). This list must have the same size as the 'start' list. Must not be
|
||||
* {@literal null}.
|
||||
*/
|
||||
public List<LabelNode> end;
|
||||
|
||||
/**
|
||||
* The local variable's index in each range. This list must have the same
|
||||
* size as the 'start' list. Must not be <tt>null</tt>.
|
||||
*/
|
||||
* The local variable's index in each range. This list must have the same size as the 'start'
|
||||
* list. Must not be {@literal null}.
|
||||
*/
|
||||
public List<Integer> index;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
|
||||
* not use this constructor</i>. Instead, they must use the
|
||||
* {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)}
|
||||
* version.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. See {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param start
|
||||
* the fist instructions corresponding to the continuous ranges
|
||||
* that make the scope of this local variable (inclusive).
|
||||
* @param end
|
||||
* the last instructions corresponding to the continuous ranges
|
||||
* that make the scope of this local variable (exclusive). This
|
||||
* array must have the same size as the 'start' array.
|
||||
* @param index
|
||||
* the local variable's index in each range. This array must have
|
||||
* the same size as the 'start' array.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
*/
|
||||
public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
|
||||
LabelNode[] start, LabelNode[] end, int[] index, String desc) {
|
||||
this(Opcodes.ASM6, typeRef, typePath, start, end, index, desc);
|
||||
* Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the {@link #LocalVariableAnnotationNode(int, TypePath,
|
||||
* LabelNode[], LabelNode[], int[], String)} version.
|
||||
*
|
||||
* @param typeRef a reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param start the fist instructions corresponding to the continuous ranges that make the scope
|
||||
* of this local variable (inclusive).
|
||||
* @param end the last instructions corresponding to the continuous ranges that make the scope of
|
||||
* this local variable (exclusive). This array must have the same size as the 'start' array.
|
||||
* @param index the local variable's index in each range. This array must have the same size as
|
||||
* the 'start' array.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
*/
|
||||
public LocalVariableAnnotationNode(
|
||||
final int typeRef,
|
||||
final TypePath typePath,
|
||||
final LabelNode[] start,
|
||||
final LabelNode[] end,
|
||||
final int[] index,
|
||||
final String descriptor) {
|
||||
this(Opcodes.ASM7, typeRef, typePath, start, end, index, descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LocalVariableAnnotationNode}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. See {@link TypeReference}.
|
||||
* @param start
|
||||
* the fist instructions corresponding to the continuous ranges
|
||||
* that make the scope of this local variable (inclusive).
|
||||
* @param end
|
||||
* the last instructions corresponding to the continuous ranges
|
||||
* that make the scope of this local variable (exclusive). This
|
||||
* array must have the same size as the 'start' array.
|
||||
* @param index
|
||||
* the local variable's index in each range. This array must have
|
||||
* the same size as the 'start' array.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
*/
|
||||
public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
|
||||
LabelNode[] start, LabelNode[] end, int[] index, String desc) {
|
||||
super(api, typeRef, typePath, desc);
|
||||
this.start = new ArrayList<LabelNode>(start.length);
|
||||
this.start.addAll(Arrays.asList(start));
|
||||
this.end = new ArrayList<LabelNode>(end.length);
|
||||
this.end.addAll(Arrays.asList(end));
|
||||
this.index = new ArrayList<Integer>(index.length);
|
||||
for (int i : index) {
|
||||
this.index.add(i);
|
||||
}
|
||||
* Constructs a new {@link LocalVariableAnnotationNode}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param typeRef a reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}.
|
||||
* @param start the fist instructions corresponding to the continuous ranges that make the scope
|
||||
* of this local variable (inclusive).
|
||||
* @param end the last instructions corresponding to the continuous ranges that make the scope of
|
||||
* this local variable (exclusive). This array must have the same size as the 'start' array.
|
||||
* @param index the local variable's index in each range. This array must have the same size as
|
||||
* the 'start' array.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
*/
|
||||
public LocalVariableAnnotationNode(
|
||||
final int api,
|
||||
final int typeRef,
|
||||
final TypePath typePath,
|
||||
final LabelNode[] start,
|
||||
final LabelNode[] end,
|
||||
final int[] index,
|
||||
final String descriptor) {
|
||||
super(api, typeRef, typePath, descriptor);
|
||||
this.start = Util.asArrayList(start);
|
||||
this.end = Util.asArrayList(end);
|
||||
this.index = Util.asArrayList(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this type annotation.
|
||||
*
|
||||
* @param mv
|
||||
* the visitor that must visit this annotation.
|
||||
* @param visible
|
||||
* <tt>true</tt> if the annotation is visible at runtime.
|
||||
*/
|
||||
public void accept(final MethodVisitor mv, boolean visible) {
|
||||
Label[] start = new Label[this.start.size()];
|
||||
Label[] end = new Label[this.end.size()];
|
||||
int[] index = new int[this.index.size()];
|
||||
for (int i = 0; i < start.length; ++i) {
|
||||
start[i] = this.start.get(i).getLabel();
|
||||
end[i] = this.end.get(i).getLabel();
|
||||
index[i] = this.index.get(i);
|
||||
* Makes the given visitor visit this type annotation.
|
||||
*
|
||||
* @param methodVisitor the visitor that must visit this annotation.
|
||||
* @param visible {@literal true} if the annotation is visible at runtime.
|
||||
*/
|
||||
public void accept(final MethodVisitor methodVisitor, final boolean visible) {
|
||||
Label[] startLabels = new Label[this.start.size()];
|
||||
Label[] endLabels = new Label[this.end.size()];
|
||||
int[] indices = new int[this.index.size()];
|
||||
for (int i = 0, n = startLabels.length; i < n; ++i) {
|
||||
startLabels[i] = this.start.get(i).getLabel();
|
||||
endLabels[i] = this.end.get(i).getLabel();
|
||||
indices[i] = this.index.get(i);
|
||||
}
|
||||
accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
|
||||
index, desc, visible));
|
||||
accept(
|
||||
methodVisitor.visitLocalVariableAnnotation(
|
||||
typeRef, typePath, startLabels, endLabels, indices, desc, visible));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,61 +67,44 @@ import jdk.internal.org.objectweb.asm.MethodVisitor;
|
|||
*/
|
||||
public class LocalVariableNode {
|
||||
|
||||
/**
|
||||
* The name of a local variable.
|
||||
*/
|
||||
/** The name of a local variable. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The type descriptor of this local variable.
|
||||
*/
|
||||
/** The type descriptor of this local variable. */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* The signature of this local variable. May be <tt>null</tt>.
|
||||
*/
|
||||
/** The signature of this local variable. May be {@literal null}. */
|
||||
public String signature;
|
||||
|
||||
/**
|
||||
* The first instruction corresponding to the scope of this local variable
|
||||
* (inclusive).
|
||||
*/
|
||||
/** The first instruction corresponding to the scope of this local variable (inclusive). */
|
||||
public LabelNode start;
|
||||
|
||||
/**
|
||||
* The last instruction corresponding to the scope of this local variable
|
||||
* (exclusive).
|
||||
*/
|
||||
/** The last instruction corresponding to the scope of this local variable (exclusive). */
|
||||
public LabelNode end;
|
||||
|
||||
/**
|
||||
* The local variable's index.
|
||||
*/
|
||||
/** The local variable's index. */
|
||||
public int index;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LocalVariableNode}.
|
||||
*
|
||||
* @param name
|
||||
* the name of a local variable.
|
||||
* @param desc
|
||||
* the type descriptor of this local variable.
|
||||
* @param signature
|
||||
* the signature of this local variable. May be <tt>null</tt>.
|
||||
* @param start
|
||||
* the first instruction corresponding to the scope of this local
|
||||
* variable (inclusive).
|
||||
* @param end
|
||||
* the last instruction corresponding to the scope of this local
|
||||
* variable (exclusive).
|
||||
* @param index
|
||||
* the local variable's index.
|
||||
*/
|
||||
public LocalVariableNode(final String name, final String desc,
|
||||
final String signature, final LabelNode start, final LabelNode end,
|
||||
* Constructs a new {@link LocalVariableNode}.
|
||||
*
|
||||
* @param name the name of a local variable.
|
||||
* @param descriptor the type descriptor of this local variable.
|
||||
* @param signature the signature of this local variable. May be {@literal null}.
|
||||
* @param start the first instruction corresponding to the scope of this local variable
|
||||
* (inclusive).
|
||||
* @param end the last instruction corresponding to the scope of this local variable (exclusive).
|
||||
* @param index the local variable's index.
|
||||
*/
|
||||
public LocalVariableNode(
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final LabelNode start,
|
||||
final LabelNode end,
|
||||
final int index) {
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.desc = descriptor;
|
||||
this.signature = signature;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
|
@ -129,13 +112,12 @@ public class LocalVariableNode {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this local variable declaration.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitLocalVariable(name, desc, signature, start.getLabel(),
|
||||
end.getLabel(), index);
|
||||
* Makes the given visitor visit this local variable declaration.
|
||||
*
|
||||
* @param methodVisitor a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitLocalVariable(
|
||||
name, desc, signature, start.getLabel(), end.getLabel(), index);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,11 +58,8 @@
|
|||
*/
|
||||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
|
@ -74,48 +71,28 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public class LookupSwitchInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* Beginning of the default handler block.
|
||||
*/
|
||||
/** Beginning of the default handler block. */
|
||||
public LabelNode dflt;
|
||||
|
||||
/**
|
||||
* The values of the keys. This list is a list of {@link Integer} objects.
|
||||
*/
|
||||
/** The values of the keys. */
|
||||
public List<Integer> keys;
|
||||
|
||||
/**
|
||||
* Beginnings of the handler blocks. This list is a list of
|
||||
* {@link LabelNode} objects.
|
||||
*/
|
||||
/** Beginnings of the handler blocks. */
|
||||
public List<LabelNode> labels;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LookupSwitchInsnNode}.
|
||||
*
|
||||
* @param dflt
|
||||
* beginning of the default handler block.
|
||||
* @param keys
|
||||
* the values of the keys.
|
||||
* @param labels
|
||||
* beginnings of the handler blocks. <tt>labels[i]</tt> is the
|
||||
* beginning of the handler block for the <tt>keys[i]</tt> key.
|
||||
*/
|
||||
public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys,
|
||||
final LabelNode[] labels) {
|
||||
* Constructs a new {@link LookupSwitchInsnNode}.
|
||||
*
|
||||
* @param dflt beginning of the default handler block.
|
||||
* @param keys the values of the keys.
|
||||
* @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
|
||||
* handler block for the {@code keys[i]} key.
|
||||
*/
|
||||
public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys, final LabelNode[] labels) {
|
||||
super(Opcodes.LOOKUPSWITCH);
|
||||
this.dflt = dflt;
|
||||
this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
|
||||
this.labels = new ArrayList<LabelNode>(labels == null ? 0
|
||||
: labels.length);
|
||||
if (keys != null) {
|
||||
for (int i = 0; i < keys.length; ++i) {
|
||||
this.keys.add(keys[i]);
|
||||
}
|
||||
}
|
||||
if (labels != null) {
|
||||
this.labels.addAll(Arrays.asList(labels));
|
||||
}
|
||||
this.keys = Util.asArrayList(keys);
|
||||
this.labels = Util.asArrayList(labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -124,23 +101,23 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
int[] keys = new int[this.keys.size()];
|
||||
for (int i = 0; i < keys.length; ++i) {
|
||||
keys[i] = this.keys.get(i).intValue();
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
int[] keysArray = new int[this.keys.size()];
|
||||
for (int i = 0, n = keysArray.length; i < n; ++i) {
|
||||
keysArray[i] = this.keys.get(i).intValue();
|
||||
}
|
||||
Label[] labels = new Label[this.labels.size()];
|
||||
for (int i = 0; i < labels.length; ++i) {
|
||||
labels[i] = this.labels.get(i).getLabel();
|
||||
Label[] labelsArray = new Label[this.labels.size()];
|
||||
for (int i = 0, n = labelsArray.length; i < n; ++i) {
|
||||
labelsArray[i] = this.labels.get(i).getLabel();
|
||||
}
|
||||
mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
|
||||
acceptAnnotations(mv);
|
||||
methodVisitor.visitLookupSwitchInsn(dflt.getLabel(), keysArray, labelsArray);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
|
||||
labels), null, clone(this.labels, labels));
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
LookupSwitchInsnNode clone =
|
||||
new LookupSwitchInsnNode(clone(dflt, clonedLabels), null, clone(labels, clonedLabels));
|
||||
clone.keys.addAll(keys);
|
||||
return clone.cloneAnnotations(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,95 +59,81 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* A node that represents a method instruction. A method instruction is an
|
||||
* instruction that invokes a method.
|
||||
* A node that represents a method instruction. A method instruction is an instruction that invokes
|
||||
* a method.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class MethodInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The internal name of the method's owner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}).
|
||||
*/
|
||||
* The internal name of the method's owner class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
|
||||
*
|
||||
* <p>For methods of arrays, e.g., {@code clone()}, the array type descriptor.
|
||||
*/
|
||||
public String owner;
|
||||
|
||||
/**
|
||||
* The method's name.
|
||||
*/
|
||||
/** The method's name. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
/** The method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* If the method's owner class if an interface.
|
||||
*/
|
||||
/** Whether the method's owner class if an interface. */
|
||||
public boolean itf;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MethodInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the type instruction to be constructed. This
|
||||
* opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
|
||||
* INVOKEINTERFACE.
|
||||
* @param owner
|
||||
* the internal name of the method's owner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName()
|
||||
* getInternalName}).
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
* Constructs a new {@link MethodInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the type instruction to be constructed. This opcode must be
|
||||
* INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
|
||||
* @param owner the internal name of the method's owner class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
|
||||
* @param name the method's name.
|
||||
* @param descriptor the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @deprecated use {@link #MethodInsnNode(int, String, String, String, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MethodInsnNode(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
|
||||
public MethodInsnNode(
|
||||
final int opcode, final String owner, final String name, final String descriptor) {
|
||||
this(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MethodInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the type instruction to be constructed. This
|
||||
* opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
|
||||
* INVOKEINTERFACE.
|
||||
* @param owner
|
||||
* the internal name of the method's owner class (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type#getInternalName()
|
||||
* getInternalName}).
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param itf
|
||||
* if the method's owner class is an interface.
|
||||
*/
|
||||
public MethodInsnNode(final int opcode, final String owner,
|
||||
final String name, final String desc, final boolean itf) {
|
||||
* Constructs a new {@link MethodInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the type instruction to be constructed. This opcode must be
|
||||
* INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
|
||||
* @param owner the internal name of the method's owner class (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type#getInternalName()}).
|
||||
* @param name the method's name.
|
||||
* @param descriptor the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param isInterface if the method's owner class is an interface.
|
||||
*/
|
||||
public MethodInsnNode(
|
||||
final int opcode,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
super(opcode);
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.itf = itf;
|
||||
this.desc = descriptor;
|
||||
this.itf = isInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode
|
||||
* the new instruction opcode. This opcode must be INVOKEVIRTUAL,
|
||||
* INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
|
||||
*/
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode the new instruction opcode. This opcode must be INVOKEVIRTUAL, INVOKESPECIAL,
|
||||
* INVOKESTATIC or INVOKEINTERFACE.
|
||||
*/
|
||||
public void setOpcode(final int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
|
@ -158,13 +144,13 @@ public class MethodInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return new MethodInsnNode(opcode, owner, name, desc, itf);
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new MethodInsnNode(opcode, owner, name, desc, itf).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
||||
|
||||
/**
|
||||
|
|
@ -68,31 +67,31 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
|||
* @author Remi Forax
|
||||
*/
|
||||
public class ModuleExportNode {
|
||||
/**
|
||||
* The package name.
|
||||
*/
|
||||
|
||||
/** The internal name of the exported package. */
|
||||
public String packaze;
|
||||
|
||||
/**
|
||||
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
*/
|
||||
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). Valid values are {@code
|
||||
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* A list of modules that can access to this exported package.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
* The list of modules that can access this exported package, specified with fully qualified names
|
||||
* (using dots). May be {@literal null}.
|
||||
*/
|
||||
public List<String> modules;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleExportNode}.
|
||||
*
|
||||
* @param packaze
|
||||
* the parameter's name.
|
||||
* @param modules
|
||||
* a list of modules that can access to this exported package.
|
||||
*/
|
||||
* Constructs a new {@link ModuleExportNode}.
|
||||
*
|
||||
* @param packaze the internal name of the exported package.
|
||||
* @param access the package access flags, one or more of {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
* @param modules a list of modules that can access this exported package, specified with fully
|
||||
* qualified names (using dots).
|
||||
*/
|
||||
public ModuleExportNode(final String packaze, final int access, final List<String> modules) {
|
||||
this.packaze = packaze;
|
||||
this.access = access;
|
||||
|
|
@ -100,12 +99,12 @@ public class ModuleExportNode {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes the given module visitor visit this export declaration.
|
||||
*
|
||||
* @param mv
|
||||
* a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor mv) {
|
||||
mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
|
||||
* Makes the given module visitor visit this export declaration.
|
||||
*
|
||||
* @param moduleVisitor a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor moduleVisitor) {
|
||||
moduleVisitor.visitExport(
|
||||
packaze, access, modules == null ? null : modules.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
|
@ -71,82 +70,86 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
* @author Remi Forax
|
||||
*/
|
||||
public class ModuleNode extends ModuleVisitor {
|
||||
/**
|
||||
* Module name
|
||||
*/
|
||||
|
||||
/** The fully qualified name (using dots) of this module. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* Module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
|
||||
* and {@code ACC_MANDATED}.
|
||||
*/
|
||||
* The module's access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* Version of the module.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
/** The version of this module. May be {@literal null}. */
|
||||
public String version;
|
||||
|
||||
/**
|
||||
* Name of the main class in internal form
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
/** The internal name of the main class of this module. May be {@literal null}. */
|
||||
public String mainClass;
|
||||
|
||||
/**
|
||||
* A list of packages that are declared by the current module.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
/** The internal name of the packages declared by this module. May be {@literal null}. */
|
||||
public List<String> packages;
|
||||
|
||||
/**
|
||||
* A list of modules can are required by the current module.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
/** The dependencies of this module. May be {@literal null}. */
|
||||
public List<ModuleRequireNode> requires;
|
||||
|
||||
/**
|
||||
* A list of packages that are exported by the current module.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
/** The packages exported by this module. May be {@literal null}. */
|
||||
public List<ModuleExportNode> exports;
|
||||
|
||||
/**
|
||||
* A list of packages that are opened by the current module.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
/** The packages opened by this module. May be {@literal null}. */
|
||||
public List<ModuleOpenNode> opens;
|
||||
|
||||
/**
|
||||
* A list of classes in their internal forms that are used
|
||||
* as a service by the current module. May be <tt>null</tt>.
|
||||
*/
|
||||
/** The internal names of the services used by this module. May be {@literal null}. */
|
||||
public List<String> uses;
|
||||
|
||||
/**
|
||||
* A list of services along with their implementations provided
|
||||
* by the current module. May be <tt>null</tt>.
|
||||
*/
|
||||
/** The services provided by this module. May be {@literal null}. */
|
||||
public List<ModuleProvideNode> provides;
|
||||
|
||||
public ModuleNode(final String name, final int access,
|
||||
final String version) {
|
||||
super(Opcodes.ASM6);
|
||||
/**
|
||||
* Constructs a {@link ModuleNode}. <i>Subclasses must not use this constructor</i>. Instead, they
|
||||
* must use the {@link #ModuleNode(int,String,int,String,List,List,List,List,List)} version.
|
||||
*
|
||||
* @param name the fully qualified name (using dots) of the module.
|
||||
* @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
* @param version the module version, or {@literal null}.
|
||||
* @throws IllegalStateException If a subclass calls this constructor.
|
||||
*/
|
||||
public ModuleNode(final String name, final int access, final String version) {
|
||||
super(Opcodes.ASM7);
|
||||
if (getClass() != ModuleNode.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public ModuleNode(final int api,
|
||||
final String name,
|
||||
final int access,
|
||||
final String version,
|
||||
final List<ModuleRequireNode> requires,
|
||||
final List<ModuleExportNode> exports,
|
||||
final List<ModuleOpenNode> opens,
|
||||
final List<String> uses,
|
||||
final List<ModuleProvideNode> provides) {
|
||||
// TODO(forax): why is there no 'mainClass' and 'packages' parameters in this constructor?
|
||||
/**
|
||||
* Constructs a {@link ModuleNode}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
|
||||
* or {@link Opcodes#ASM7}.
|
||||
* @param name the fully qualified name (using dots) of the module.
|
||||
* @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
* @param version the module version, or {@literal null}.
|
||||
* @param requires The dependencies of this module. May be {@literal null}.
|
||||
* @param exports The packages exported by this module. May be {@literal null}.
|
||||
* @param opens The packages opened by this module. May be {@literal null}.
|
||||
* @param uses The internal names of the services used by this module. May be {@literal null}.
|
||||
* @param provides The services provided by this module. May be {@literal null}.
|
||||
*/
|
||||
public ModuleNode(
|
||||
final int api,
|
||||
final String name,
|
||||
final int access,
|
||||
final String version,
|
||||
final List<ModuleRequireNode> requires,
|
||||
final List<ModuleExportNode> exports,
|
||||
final List<ModuleOpenNode> opens,
|
||||
final List<String> uses,
|
||||
final List<ModuleProvideNode> provides) {
|
||||
super(api);
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
|
|
@ -156,18 +159,15 @@ public class ModuleNode extends ModuleVisitor {
|
|||
this.opens = opens;
|
||||
this.uses = uses;
|
||||
this.provides = provides;
|
||||
if (getClass() != ModuleNode.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMainClass(String mainClass) {
|
||||
public void visitMainClass(final String mainClass) {
|
||||
this.mainClass = mainClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPackage(String packaze) {
|
||||
public void visitPackage(final String packaze) {
|
||||
if (packages == null) {
|
||||
packages = new ArrayList<String>(5);
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ public class ModuleNode extends ModuleVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
public void visitRequire(final String module, final int access, final String version) {
|
||||
if (requires == null) {
|
||||
requires = new ArrayList<ModuleRequireNode>(5);
|
||||
}
|
||||
|
|
@ -183,37 +183,23 @@ public class ModuleNode extends ModuleVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
public void visitExport(final String packaze, final int access, final String... modules) {
|
||||
if (exports == null) {
|
||||
exports = new ArrayList<ModuleExportNode>(5);
|
||||
}
|
||||
List<String> moduleList = null;
|
||||
if (modules != null) {
|
||||
moduleList = new ArrayList<String>(modules.length);
|
||||
for (int i = 0; i < modules.length; i++) {
|
||||
moduleList.add(modules[i]);
|
||||
}
|
||||
}
|
||||
exports.add(new ModuleExportNode(packaze, access, moduleList));
|
||||
exports.add(new ModuleExportNode(packaze, access, Util.asArrayList(modules)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOpen(String packaze, int access, String... modules) {
|
||||
public void visitOpen(final String packaze, final int access, final String... modules) {
|
||||
if (opens == null) {
|
||||
opens = new ArrayList<ModuleOpenNode>(5);
|
||||
}
|
||||
List<String> moduleList = null;
|
||||
if (modules != null) {
|
||||
moduleList = new ArrayList<String>(modules.length);
|
||||
for (int i = 0; i < modules.length; i++) {
|
||||
moduleList.add(modules[i]);
|
||||
}
|
||||
}
|
||||
opens.add(new ModuleOpenNode(packaze, access, moduleList));
|
||||
opens.add(new ModuleOpenNode(packaze, access, Util.asArrayList(modules)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUse(String service) {
|
||||
public void visitUse(final String service) {
|
||||
if (uses == null) {
|
||||
uses = new ArrayList<String>(5);
|
||||
}
|
||||
|
|
@ -221,59 +207,59 @@ public class ModuleNode extends ModuleVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitProvide(String service, String... providers) {
|
||||
public void visitProvide(final String service, final String... providers) {
|
||||
if (provides == null) {
|
||||
provides = new ArrayList<ModuleProvideNode>(5);
|
||||
}
|
||||
ArrayList<String> providerList =
|
||||
new ArrayList<String>(providers.length);
|
||||
for (int i = 0; i < providers.length; i++) {
|
||||
providerList.add(providers[i]);
|
||||
}
|
||||
provides.add(new ModuleProvideNode(service, providerList));
|
||||
provides.add(new ModuleProvideNode(service, Util.asArrayList(providers)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
public void accept(final ClassVisitor cv) {
|
||||
ModuleVisitor mv = cv.visitModule(name, access, version);
|
||||
if (mv == null) {
|
||||
/**
|
||||
* Makes the given class visitor visit this module.
|
||||
*
|
||||
* @param classVisitor a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor classVisitor) {
|
||||
ModuleVisitor moduleVisitor = classVisitor.visitModule(name, access, version);
|
||||
if (moduleVisitor == null) {
|
||||
return;
|
||||
}
|
||||
if (mainClass != null) {
|
||||
mv.visitMainClass(mainClass);
|
||||
moduleVisitor.visitMainClass(mainClass);
|
||||
}
|
||||
if (packages != null) {
|
||||
for (int i = 0; i < packages.size(); i++) {
|
||||
mv.visitPackage(packages.get(i));
|
||||
for (int i = 0, n = packages.size(); i < n; i++) {
|
||||
moduleVisitor.visitPackage(packages.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (requires != null) {
|
||||
for (int i = 0; i < requires.size(); i++) {
|
||||
requires.get(i).accept(mv);
|
||||
for (int i = 0, n = requires.size(); i < n; i++) {
|
||||
requires.get(i).accept(moduleVisitor);
|
||||
}
|
||||
}
|
||||
if (exports != null) {
|
||||
for (int i = 0; i < exports.size(); i++) {
|
||||
exports.get(i).accept(mv);
|
||||
for (int i = 0, n = exports.size(); i < n; i++) {
|
||||
exports.get(i).accept(moduleVisitor);
|
||||
}
|
||||
}
|
||||
if (opens != null) {
|
||||
for (int i = 0; i < opens.size(); i++) {
|
||||
opens.get(i).accept(mv);
|
||||
for (int i = 0, n = opens.size(); i < n; i++) {
|
||||
opens.get(i).accept(moduleVisitor);
|
||||
}
|
||||
}
|
||||
if (uses != null) {
|
||||
for (int i = 0; i < uses.size(); i++) {
|
||||
mv.visitUse(uses.get(i));
|
||||
for (int i = 0, n = uses.size(); i < n; i++) {
|
||||
moduleVisitor.visitUse(uses.get(i));
|
||||
}
|
||||
}
|
||||
if (provides != null) {
|
||||
for (int i = 0; i < provides.size(); i++) {
|
||||
provides.get(i).accept(mv);
|
||||
for (int i = 0, n = provides.size(); i < n; i++) {
|
||||
provides.get(i).accept(moduleVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,40 +59,39 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents an opened package with its name and the module that can access to it.
|
||||
* A node that represents an opened package with its name and the module that can access it.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public class ModuleOpenNode {
|
||||
/**
|
||||
* The package name.
|
||||
*/
|
||||
|
||||
/** The internal name of the opened package. */
|
||||
public String packaze;
|
||||
|
||||
/**
|
||||
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
*/
|
||||
* The access flag of the opened package, valid values are among {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* A list of modules that can access to this exported package.
|
||||
* May be <tt>null</tt>.
|
||||
*/
|
||||
* The fully qualified names (using dots) of the modules that can use deep reflection to the
|
||||
* classes of the open package, or {@literal null}.
|
||||
*/
|
||||
public List<String> modules;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleOpenNode}.
|
||||
*
|
||||
* @param packaze
|
||||
* the parameter's name.
|
||||
* @param modules
|
||||
* a list of modules that can access to this open package.
|
||||
*/
|
||||
* Constructs a new {@link ModuleOpenNode}.
|
||||
*
|
||||
* @param packaze the internal name of the opened package.
|
||||
* @param access the access flag of the opened package, valid values are among {@code
|
||||
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param modules the fully qualified names (using dots) of the modules that can use deep
|
||||
* reflection to the classes of the open package, or {@literal null}.
|
||||
*/
|
||||
public ModuleOpenNode(final String packaze, final int access, final List<String> modules) {
|
||||
this.packaze = packaze;
|
||||
this.access = access;
|
||||
|
|
@ -100,12 +99,12 @@ public class ModuleOpenNode {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes the given module visitor visit this open declaration.
|
||||
*
|
||||
* @param mv
|
||||
* a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor mv) {
|
||||
mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
|
||||
* Makes the given module visitor visit this opened package.
|
||||
*
|
||||
* @param moduleVisitor a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor moduleVisitor) {
|
||||
moduleVisitor.visitOpen(
|
||||
packaze, access, modules == null ? null : modules.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
||||
|
||||
/**
|
||||
|
|
@ -68,36 +67,31 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
|||
* @author Remi Forax
|
||||
*/
|
||||
public class ModuleProvideNode {
|
||||
/**
|
||||
* The service name (in its internal form).
|
||||
*/
|
||||
|
||||
/** The internal name of the service. */
|
||||
public String service;
|
||||
|
||||
/**
|
||||
* The service provider names (in their internal form).
|
||||
*/
|
||||
/** The internal names of the implementations of the service (there is at least one provider). */
|
||||
public List<String> providers;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleProvideNode}.
|
||||
*
|
||||
* @param service
|
||||
* the service name (in its internal form).
|
||||
* @param providers
|
||||
* the service provider names (in their internal form).
|
||||
*/
|
||||
* Constructs a new {@link ModuleProvideNode}.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
* @param providers the internal names of the implementations of the service (there is at least
|
||||
* one provider).
|
||||
*/
|
||||
public ModuleProvideNode(final String service, final List<String> providers) {
|
||||
this.service = service;
|
||||
this.providers = providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given module visitor visit this require declaration.
|
||||
*
|
||||
* @param mv
|
||||
* a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor mv) {
|
||||
mv.visitProvide(service, providers.toArray(new String[0]));
|
||||
* Makes the given module visitor visit this require declaration.
|
||||
*
|
||||
* @param moduleVisitor a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor moduleVisitor) {
|
||||
moduleVisitor.visitProvide(service, providers.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,51 +66,39 @@ import jdk.internal.org.objectweb.asm.ModuleVisitor;
|
|||
* @author Remi Forax
|
||||
*/
|
||||
public class ModuleRequireNode {
|
||||
/**
|
||||
* The name of the required module.
|
||||
*/
|
||||
|
||||
/** The fully qualified name (using dots) of the dependence. */
|
||||
public String module;
|
||||
|
||||
/**
|
||||
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* Valid values are <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
|
||||
* <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>.
|
||||
*/
|
||||
* The access flag of the dependence among {@code ACC_TRANSITIVE}, {@code ACC_STATIC_PHASE},
|
||||
* {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* Version at compile time of the required module or null.
|
||||
*/
|
||||
/** The module version at compile time, or {@literal null}. */
|
||||
public String version;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ModuleRequireNode}.
|
||||
*
|
||||
* @param module
|
||||
* the name of the required module.
|
||||
* @param access
|
||||
* The access flags. Valid values are
|
||||
* <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
|
||||
* <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>
|
||||
* (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* @param version
|
||||
* Version of the required module at compile time,
|
||||
* null if not defined.
|
||||
*/
|
||||
public ModuleRequireNode(final String module, final int access,
|
||||
final String version) {
|
||||
* Constructs a new {@link ModuleRequireNode}.
|
||||
*
|
||||
* @param module the fully qualified name (using dots) of the dependence.
|
||||
* @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
|
||||
* ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param version the module version at compile time, or {@literal null}.
|
||||
*/
|
||||
public ModuleRequireNode(final String module, final int access, final String version) {
|
||||
this.module = module;
|
||||
this.access = access;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given module visitor visit this require directive.
|
||||
*
|
||||
* @param mv
|
||||
* a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor mv) {
|
||||
mv.visitRequire(module, access, version);
|
||||
* Makes the given module visitor visit this require directive.
|
||||
*
|
||||
* @param moduleVisitor a module visitor.
|
||||
*/
|
||||
public void accept(final ModuleVisitor moduleVisitor) {
|
||||
moduleVisitor.visitRequire(module, access, version);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
|
|
@ -70,28 +69,22 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public class MultiANewArrayInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* An array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
/** An array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* Number of dimensions of the array to allocate.
|
||||
*/
|
||||
/** Number of dimensions of the array to allocate. */
|
||||
public int dims;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MultiANewArrayInsnNode}.
|
||||
*
|
||||
* @param desc
|
||||
* an array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param dims
|
||||
* number of dimensions of the array to allocate.
|
||||
*/
|
||||
public MultiANewArrayInsnNode(final String desc, final int dims) {
|
||||
* Constructs a new {@link MultiANewArrayInsnNode}.
|
||||
*
|
||||
* @param descriptor an array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
* @param numDimensions the number of dimensions of the array to allocate.
|
||||
*/
|
||||
public MultiANewArrayInsnNode(final String descriptor, final int numDimensions) {
|
||||
super(Opcodes.MULTIANEWARRAY);
|
||||
this.desc = desc;
|
||||
this.dims = dims;
|
||||
this.desc = descriptor;
|
||||
this.dims = numDimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -100,14 +93,13 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitMultiANewArrayInsn(desc, dims);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitMultiANewArrayInsn(desc, dims);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,45 +61,39 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents a parameter access and name.
|
||||
* A node that represents a parameter of a method.
|
||||
*
|
||||
* @author Remi Forax
|
||||
*/
|
||||
public class ParameterNode {
|
||||
/**
|
||||
* The parameter's name.
|
||||
*/
|
||||
|
||||
/** The parameter's name. */
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The parameter's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
|
||||
* <tt>ACC_MANDATED</tt>.
|
||||
*/
|
||||
* The parameter's access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}). Valid values are {@code
|
||||
* ACC_FINAL}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ParameterNode}.
|
||||
*
|
||||
* @param access
|
||||
* The parameter's access flags. Valid values are
|
||||
* <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
|
||||
* <tt>ACC_MANDATED</tt> (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* @param name
|
||||
* the parameter's name.
|
||||
*/
|
||||
* Constructs a new {@link ParameterNode}.
|
||||
*
|
||||
* @param access The parameter's access flags. Valid values are {@code ACC_FINAL}, {@code
|
||||
* ACC_SYNTHETIC} or/and {@code ACC_MANDATED} (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
|
||||
* @param name the parameter's name.
|
||||
*/
|
||||
public ParameterNode(final String name, final int access) {
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this parameter declaration.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitParameter(name, access);
|
||||
* Makes the given visitor visit this parameter declaration.
|
||||
*
|
||||
* @param methodVisitor a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitParameter(name, access);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,11 +58,8 @@
|
|||
*/
|
||||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
|
@ -74,50 +71,34 @@ import jdk.internal.org.objectweb.asm.Opcodes;
|
|||
*/
|
||||
public class TableSwitchInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The minimum key value.
|
||||
*/
|
||||
/** The minimum key value. */
|
||||
public int min;
|
||||
|
||||
/**
|
||||
* The maximum key value.
|
||||
*/
|
||||
/** The maximum key value. */
|
||||
public int max;
|
||||
|
||||
/**
|
||||
* Beginning of the default handler block.
|
||||
*/
|
||||
/** Beginning of the default handler block. */
|
||||
public LabelNode dflt;
|
||||
|
||||
/**
|
||||
* Beginnings of the handler blocks. This list is a list of
|
||||
* {@link LabelNode} objects.
|
||||
*/
|
||||
/** Beginnings of the handler blocks. This list is a list of {@link LabelNode} objects. */
|
||||
public List<LabelNode> labels;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link TableSwitchInsnNode}.
|
||||
*
|
||||
* @param min
|
||||
* the minimum key value.
|
||||
* @param max
|
||||
* the maximum key value.
|
||||
* @param dflt
|
||||
* beginning of the default handler block.
|
||||
* @param labels
|
||||
* beginnings of the handler blocks. <tt>labels[i]</tt> is the
|
||||
* beginning of the handler block for the <tt>min + i</tt> key.
|
||||
*/
|
||||
public TableSwitchInsnNode(final int min, final int max,
|
||||
final LabelNode dflt, final LabelNode... labels) {
|
||||
* Constructs a new {@link TableSwitchInsnNode}.
|
||||
*
|
||||
* @param min the minimum key value.
|
||||
* @param max the maximum key value.
|
||||
* @param dflt beginning of the default handler block.
|
||||
* @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the
|
||||
* handler block for the {@code min + i} key.
|
||||
*/
|
||||
public TableSwitchInsnNode(
|
||||
final int min, final int max, final LabelNode dflt, final LabelNode... labels) {
|
||||
super(Opcodes.TABLESWITCH);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.dflt = dflt;
|
||||
this.labels = new ArrayList<LabelNode>();
|
||||
if (labels != null) {
|
||||
this.labels.addAll(Arrays.asList(labels));
|
||||
}
|
||||
this.labels = Util.asArrayList(labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -126,18 +107,18 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
Label[] labels = new Label[this.labels.size()];
|
||||
for (int i = 0; i < labels.length; ++i) {
|
||||
labels[i] = this.labels.get(i).getLabel();
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
Label[] labelsArray = new Label[this.labels.size()];
|
||||
for (int i = 0, n = labelsArray.length; i < n; ++i) {
|
||||
labelsArray[i] = this.labels.get(i).getLabel();
|
||||
}
|
||||
mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
|
||||
acceptAnnotations(mv);
|
||||
methodVisitor.visitTableSwitchInsn(min, max, dflt.getLabel(), labelsArray);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
|
||||
this.labels, labels)).cloneAnnotations(this);
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new TableSwitchInsnNode(min, max, clone(dflt, clonedLabels), clone(labels, clonedLabels))
|
||||
.cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
|
|
@ -69,63 +68,40 @@ import jdk.internal.org.objectweb.asm.MethodVisitor;
|
|||
*/
|
||||
public class TryCatchBlockNode {
|
||||
|
||||
/**
|
||||
* Beginning of the exception handler's scope (inclusive).
|
||||
*/
|
||||
/** The beginning of the exception handler's scope (inclusive). */
|
||||
public LabelNode start;
|
||||
|
||||
/**
|
||||
* End of the exception handler's scope (exclusive).
|
||||
*/
|
||||
/** The end of the exception handler's scope (exclusive). */
|
||||
public LabelNode end;
|
||||
|
||||
/**
|
||||
* Beginning of the exception handler's code.
|
||||
*/
|
||||
/** The beginning of the exception handler's code. */
|
||||
public LabelNode handler;
|
||||
|
||||
/**
|
||||
* Internal name of the type of exceptions handled by the handler. May be
|
||||
* <tt>null</tt> to catch any exceptions (for "finally" blocks).
|
||||
*/
|
||||
* The internal name of the type of exceptions handled by the handler. May be {@literal null} to
|
||||
* catch any exceptions (for "finally" blocks).
|
||||
*/
|
||||
public String type;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations on the exception handler type. This
|
||||
* list is a list of {@link TypeAnnotationNode} objects. May be
|
||||
* <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
/** The runtime visible type annotations on the exception handler type. May be {@literal null}. */
|
||||
public List<TypeAnnotationNode> visibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations on the exception handler type.
|
||||
* This list is a list of {@link TypeAnnotationNode} objects. May be
|
||||
* <tt>null</tt>.
|
||||
*
|
||||
* @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
* The runtime invisible type annotations on the exception handler type. May be {@literal null}.
|
||||
*/
|
||||
public List<TypeAnnotationNode> invisibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link TryCatchBlockNode}.
|
||||
*
|
||||
* @param start
|
||||
* beginning of the exception handler's scope (inclusive).
|
||||
* @param end
|
||||
* end of the exception handler's scope (exclusive).
|
||||
* @param handler
|
||||
* beginning of the exception handler's code.
|
||||
* @param type
|
||||
* internal name of the type of exceptions handled by the
|
||||
* handler, or <tt>null</tt> to catch any exceptions (for
|
||||
* "finally" blocks).
|
||||
*/
|
||||
public TryCatchBlockNode(final LabelNode start, final LabelNode end,
|
||||
final LabelNode handler, final String type) {
|
||||
* Constructs a new {@link TryCatchBlockNode}.
|
||||
*
|
||||
* @param start the beginning of the exception handler's scope (inclusive).
|
||||
* @param end the end of the exception handler's scope (exclusive).
|
||||
* @param handler the beginning of the exception handler's code.
|
||||
* @param type the internal name of the type of exceptions handled by the handler, or {@literal
|
||||
* null} to catch any exceptions (for "finally" blocks).
|
||||
*/
|
||||
public TryCatchBlockNode(
|
||||
final LabelNode start, final LabelNode end, final LabelNode handler, final String type) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.handler = handler;
|
||||
|
|
@ -133,50 +109,49 @@ public class TryCatchBlockNode {
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates the index of this try catch block in the method's list of try
|
||||
* catch block nodes. This index maybe stored in the 'target' field of the
|
||||
* type annotations of this block.
|
||||
*
|
||||
* @param index
|
||||
* the new index of this try catch block in the method's list of
|
||||
* try catch block nodes.
|
||||
*/
|
||||
* Updates the index of this try catch block in the method's list of try catch block nodes. This
|
||||
* index maybe stored in the 'target' field of the type annotations of this block.
|
||||
*
|
||||
* @param index the new index of this try catch block in the method's list of try catch block
|
||||
* nodes.
|
||||
*/
|
||||
public void updateIndex(final int index) {
|
||||
int newTypeRef = 0x42000000 | (index << 8);
|
||||
if (visibleTypeAnnotations != null) {
|
||||
for (TypeAnnotationNode tan : visibleTypeAnnotations) {
|
||||
tan.typeRef = newTypeRef;
|
||||
for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
|
||||
visibleTypeAnnotations.get(i).typeRef = newTypeRef;
|
||||
}
|
||||
}
|
||||
if (invisibleTypeAnnotations != null) {
|
||||
for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
|
||||
tan.typeRef = newTypeRef;
|
||||
for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
|
||||
invisibleTypeAnnotations.get(i).typeRef = newTypeRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given visitor visit this try catch block.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
|
||||
handler == null ? null : handler.getLabel(), type);
|
||||
int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
|
||||
.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
|
||||
an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
|
||||
an.desc, true));
|
||||
* Makes the given visitor visit this try catch block.
|
||||
*
|
||||
* @param methodVisitor a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitTryCatchBlock(
|
||||
start.getLabel(), end.getLabel(), handler == null ? null : handler.getLabel(), type);
|
||||
if (visibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
methodVisitor.visitTryCatchAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
|
||||
.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
|
||||
an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
|
||||
an.desc, false));
|
||||
if (invisibleTypeAnnotations != null) {
|
||||
for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) {
|
||||
TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i);
|
||||
typeAnnotation.accept(
|
||||
methodVisitor.visitTryCatchAnnotation(
|
||||
typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,69 +60,56 @@ package jdk.internal.org.objectweb.asm.tree;
|
|||
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.TypePath;
|
||||
import jdk.internal.org.objectweb.asm.TypeReference;
|
||||
|
||||
/**
|
||||
* A node that represents a type annotationn.
|
||||
* A node that represents a type annotation.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class TypeAnnotationNode extends AnnotationNode {
|
||||
|
||||
/**
|
||||
* A reference to the annotated type. See {@link TypeReference}.
|
||||
*/
|
||||
/** A reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}. */
|
||||
public int typeRef;
|
||||
|
||||
/**
|
||||
* The path to the annotated type argument, wildcard bound, array element
|
||||
* type, or static outer type within the referenced type. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
*/
|
||||
* The path to the annotated type argument, wildcard bound, array element type, or static outer
|
||||
* type within the referenced type. May be {@literal null} if the annotation targets 'typeRef' as
|
||||
* a whole.
|
||||
*/
|
||||
public TypePath typePath;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the
|
||||
* {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. See {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
* @throws IllegalStateException
|
||||
* If a subclass calls this constructor.
|
||||
*/
|
||||
public TypeAnnotationNode(final int typeRef, final TypePath typePath,
|
||||
final String desc) {
|
||||
this(Opcodes.ASM6, typeRef, typePath, desc);
|
||||
* Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this constructor</i>.
|
||||
* Instead, they must use the {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
|
||||
*
|
||||
* @param typeRef a reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
* @throws IllegalStateException If a subclass calls this constructor.
|
||||
*/
|
||||
public TypeAnnotationNode(final int typeRef, final TypePath typePath, final String descriptor) {
|
||||
this(Opcodes.ASM7, typeRef, typePath, descriptor);
|
||||
if (getClass() != TypeAnnotationNode.class) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationNode}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. See {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param desc
|
||||
* the class descriptor of the annotation class.
|
||||
*/
|
||||
public TypeAnnotationNode(final int api, final int typeRef,
|
||||
final TypePath typePath, final String desc) {
|
||||
super(api, desc);
|
||||
* Constructs a new {@link AnnotationNode}.
|
||||
*
|
||||
* @param api the ASM API version implemented by this visitor. Must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}.
|
||||
* @param typeRef a reference to the annotated type. See {@link jdk.internal.org.objectweb.asm.TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor the class descriptor of the annotation class.
|
||||
*/
|
||||
public TypeAnnotationNode(
|
||||
final int api, final int typeRef, final TypePath typePath, final String descriptor) {
|
||||
super(api, descriptor);
|
||||
this.typeRef = typeRef;
|
||||
this.typePath = typePath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,45 +59,41 @@
|
|||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
||||
/**
|
||||
* A node that represents a type instruction. A type instruction is an
|
||||
* instruction that takes a type descriptor as parameter.
|
||||
* A node that represents a type instruction. A type instruction is an instruction that takes a type
|
||||
* descriptor as parameter.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class TypeInsnNode extends AbstractInsnNode {
|
||||
|
||||
/**
|
||||
* The operand of this instruction. This operand is an internal name (see
|
||||
* {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
* The operand of this instruction. This operand is an internal name (see {@link
|
||||
* jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link TypeInsnNode}.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the type instruction to be constructed. This
|
||||
* opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
|
||||
* @param desc
|
||||
* the operand of the instruction to be constructed. This operand
|
||||
* is an internal name (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
public TypeInsnNode(final int opcode, final String desc) {
|
||||
* Constructs a new {@link TypeInsnNode}.
|
||||
*
|
||||
* @param opcode the opcode of the type instruction to be constructed. This opcode must be NEW,
|
||||
* ANEWARRAY, CHECKCAST or INSTANCEOF.
|
||||
* @param descriptor the operand of the instruction to be constructed. This operand is an internal
|
||||
* name (see {@link jdk.internal.org.objectweb.asm.Type}).
|
||||
*/
|
||||
public TypeInsnNode(final int opcode, final String descriptor) {
|
||||
super(opcode);
|
||||
this.desc = desc;
|
||||
this.desc = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode
|
||||
* the new instruction opcode. This opcode must be NEW,
|
||||
* ANEWARRAY, CHECKCAST or INSTANCEOF.
|
||||
*/
|
||||
* Sets the opcode of this instruction.
|
||||
*
|
||||
* @param opcode the new instruction opcode. This opcode must be NEW, ANEWARRAY, CHECKCAST or
|
||||
* INSTANCEOF.
|
||||
*/
|
||||
public void setOpcode(final int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
|
@ -108,13 +104,13 @@ public class TypeInsnNode extends AbstractInsnNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(final MethodVisitor mv) {
|
||||
mv.visitTypeInsn(opcode, desc);
|
||||
acceptAnnotations(mv);
|
||||
public void accept(final MethodVisitor methodVisitor) {
|
||||
methodVisitor.visitTypeInsn(opcode, desc);
|
||||
acceptAnnotations(methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
|
||||
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
|
||||
return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
/**
|
||||
* Exception thrown in {@link AnnotationNode#check}, {@link ClassNode#check}, {@link
|
||||
* FieldNode#check} and {@link MethodNode#check} when these nodes (or their children, recursively)
|
||||
* contain elements that were introduced in more recent versions of the ASM API than version passed
|
||||
* to these methods.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class UnsupportedClassVersionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -3502347765891805831L;
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package jdk.internal.org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility methods to convert an array of primitive or object values to a mutable ArrayList, not
|
||||
* baked by the array (unlike {@link java.util.Arrays#asList}).
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
final class Util {
|
||||
|
||||
private Util() {}
|
||||
|
||||
static <T> List<T> asArrayList(final int length) {
|
||||
List<T> list = new ArrayList<T>(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
list.add(null);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static <T> List<T> asArrayList(final T[] array) {
|
||||
if (array == null) {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
ArrayList<T> list = new ArrayList<T>(array.length);
|
||||
for (T t : array) {
|
||||
list.add(t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static List<Byte> asArrayList(final byte[] byteArray) {
|
||||
if (byteArray == null) {
|
||||
return new ArrayList<Byte>();
|
||||
}
|
||||
ArrayList<Byte> byteList = new ArrayList<Byte>(byteArray.length);
|
||||
for (byte b : byteArray) {
|
||||
byteList.add(b);
|
||||
}
|
||||
return byteList;
|
||||
}
|
||||
|
||||
static List<Boolean> asArrayList(final boolean[] booleanArray) {
|
||||
if (booleanArray == null) {
|
||||
return new ArrayList<Boolean>();
|
||||
}
|
||||
ArrayList<Boolean> booleanList = new ArrayList<Boolean>(booleanArray.length);
|
||||
for (boolean b : booleanArray) {
|
||||
booleanList.add(b);
|
||||
}
|
||||
return booleanList;
|
||||
}
|
||||
|
||||
static List<Short> asArrayList(final short[] shortArray) {
|
||||
if (shortArray == null) {
|
||||
return new ArrayList<Short>();
|
||||
}
|
||||
ArrayList<Short> shortList = new ArrayList<Short>(shortArray.length);
|
||||
for (short s : shortArray) {
|
||||
shortList.add(s);
|
||||
}
|
||||
return shortList;
|
||||
}
|
||||
|
||||
static List<Character> asArrayList(final char[] charArray) {
|
||||
if (charArray == null) {
|
||||
return new ArrayList<Character>();
|
||||
}
|
||||
ArrayList<Character> charList = new ArrayList<Character>(charArray.length);
|
||||
for (char c : charArray) {
|
||||
charList.add(c);
|
||||
}
|
||||
return charList;
|
||||
}
|
||||
|
||||
static List<Integer> asArrayList(final int[] intArray) {
|
||||
if (intArray == null) {
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
ArrayList<Integer> intList = new ArrayList<Integer>(intArray.length);
|
||||
for (int i : intArray) {
|
||||
intList.add(i);
|
||||
}
|
||||
return intList;
|
||||
}
|
||||
|
||||
static List<Float> asArrayList(final float[] floatArray) {
|
||||
if (floatArray == null) {
|
||||
return new ArrayList<Float>();
|
||||
}
|
||||
ArrayList<Float> floatList = new ArrayList<Float>(floatArray.length);
|
||||
for (float f : floatArray) {
|
||||
floatList.add(f);
|
||||
}
|
||||
return floatList;
|
||||
}
|
||||
|
||||
static List<Long> asArrayList(final long[] longArray) {
|
||||
if (longArray == null) {
|
||||
return new ArrayList<Long>();
|
||||
}
|
||||
ArrayList<Long> longList = new ArrayList<Long>(longArray.length);
|
||||
for (long l : longArray) {
|
||||
longList.add(l);
|
||||
}
|
||||
return longList;
|
||||
}
|
||||
|
||||
static List<Double> asArrayList(final double[] doubleArray) {
|
||||
if (doubleArray == null) {
|
||||
return new ArrayList<Double>();
|
||||
}
|
||||
ArrayList<Double> doubleList = new ArrayList<Double>(doubleArray.length);
|
||||
for (double d : doubleArray) {
|
||||
doubleList.add(d);
|
||||
}
|
||||
return doubleList;
|
||||
}
|
||||
|
||||
static <T> List<T> asArrayList(final int length, final T[] array) {
|
||||
List<T> list = new ArrayList<T>(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
list.add(array[i]); // NOPMD(UseArraysAsList): we convert a part of the array.
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue