|
|
|
@ -64,8 +64,8 @@ package org.springframework.asm; |
|
|
|
* right shift of {@link #DIM_SHIFT}. |
|
|
|
* right shift of {@link #DIM_SHIFT}. |
|
|
|
* <li>the KIND field, stored in 4 bits, indicates the kind of VALUE used. These 4 bits can be |
|
|
|
* <li>the KIND field, stored in 4 bits, indicates the kind of VALUE used. These 4 bits can be |
|
|
|
* retrieved with {@link #KIND_MASK} and, without any shift, must be equal to {@link |
|
|
|
* retrieved with {@link #KIND_MASK} and, without any shift, must be equal to {@link |
|
|
|
* #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND}, {@link #LOCAL_KIND} |
|
|
|
* #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND}, {@link |
|
|
|
* or {@link #STACK_KIND}. |
|
|
|
* #FORWARD_UNINITIALIZED_KIND},{@link #LOCAL_KIND} or {@link #STACK_KIND}. |
|
|
|
* <li>the FLAGS field, stored in 2 bits, contains up to 2 boolean flags. Currently only one flag |
|
|
|
* <li>the FLAGS field, stored in 2 bits, contains up to 2 boolean flags. Currently only one flag |
|
|
|
* is defined, namely {@link #TOP_IF_LONG_OR_DOUBLE_FLAG}. |
|
|
|
* is defined, namely {@link #TOP_IF_LONG_OR_DOUBLE_FLAG}. |
|
|
|
* <li>the VALUE field, stored in the remaining 20 bits, contains either |
|
|
|
* <li>the VALUE field, stored in the remaining 20 bits, contains either |
|
|
|
@ -78,7 +78,10 @@ package org.springframework.asm; |
|
|
|
* <li>the index of a {@link Symbol#TYPE_TAG} {@link Symbol} in the type table of a {@link |
|
|
|
* <li>the index of a {@link Symbol#TYPE_TAG} {@link Symbol} in the type table of a {@link |
|
|
|
* SymbolTable}, if KIND is equal to {@link #REFERENCE_KIND}. |
|
|
|
* SymbolTable}, if KIND is equal to {@link #REFERENCE_KIND}. |
|
|
|
* <li>the index of an {@link Symbol#UNINITIALIZED_TYPE_TAG} {@link Symbol} in the type |
|
|
|
* <li>the index of an {@link Symbol#UNINITIALIZED_TYPE_TAG} {@link Symbol} in the type |
|
|
|
* table of a SymbolTable, if KIND is equal to {@link #UNINITIALIZED_KIND}. |
|
|
|
* table of a {@link SymbolTable}, if KIND is equal to {@link #UNINITIALIZED_KIND}. |
|
|
|
|
|
|
|
* <li>the index of a {@link Symbol#FORWARD_UNINITIALIZED_TYPE_TAG} {@link Symbol} in the |
|
|
|
|
|
|
|
* type table of a {@link SymbolTable}, if KIND is equal to {@link |
|
|
|
|
|
|
|
* #FORWARD_UNINITIALIZED_KIND}. |
|
|
|
* <li>the index of a local variable in the input stack frame, if KIND is equal to {@link |
|
|
|
* <li>the index of a local variable in the input stack frame, if KIND is equal to {@link |
|
|
|
* #LOCAL_KIND}. |
|
|
|
* #LOCAL_KIND}. |
|
|
|
* <li>a position relatively to the top of the stack of the input stack frame, if KIND is |
|
|
|
* <li>a position relatively to the top of the stack of the input stack frame, if KIND is |
|
|
|
@ -88,10 +91,10 @@ package org.springframework.asm; |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>Output frames can contain abstract types of any kind and with a positive or negative array |
|
|
|
* <p>Output frames can contain abstract types of any kind and with a positive or negative array |
|
|
|
* dimension (and even unassigned types, represented by 0 - which does not correspond to any valid |
|
|
|
* dimension (and even unassigned types, represented by 0 - which does not correspond to any valid |
|
|
|
* abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND or |
|
|
|
* abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND, |
|
|
|
* UNINITIALIZED_KIND abstract types of positive or {@literal null} array dimension. In all cases |
|
|
|
* UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND abstract types of positive or {@literal null} |
|
|
|
* the type table contains only internal type names (array type descriptors are forbidden - array |
|
|
|
* array dimension. In all cases the type table contains only internal type names (array type |
|
|
|
* dimensions must be represented through the DIM field). |
|
|
|
* descriptors are forbidden - array dimensions must be represented through the DIM field). |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>The LONG and DOUBLE types are always represented by using two slots (LONG + TOP or DOUBLE + |
|
|
|
* <p>The LONG and DOUBLE types are always represented by using two slots (LONG + TOP or DOUBLE + |
|
|
|
* TOP), for local variables as well as in the operand stack. This is necessary to be able to |
|
|
|
* TOP), for local variables as well as in the operand stack. This is necessary to be able to |
|
|
|
@ -159,8 +162,9 @@ class Frame { |
|
|
|
private static final int CONSTANT_KIND = 1 << KIND_SHIFT; |
|
|
|
private static final int CONSTANT_KIND = 1 << KIND_SHIFT; |
|
|
|
private static final int REFERENCE_KIND = 2 << KIND_SHIFT; |
|
|
|
private static final int REFERENCE_KIND = 2 << KIND_SHIFT; |
|
|
|
private static final int UNINITIALIZED_KIND = 3 << KIND_SHIFT; |
|
|
|
private static final int UNINITIALIZED_KIND = 3 << KIND_SHIFT; |
|
|
|
private static final int LOCAL_KIND = 4 << KIND_SHIFT; |
|
|
|
private static final int FORWARD_UNINITIALIZED_KIND = 4 << KIND_SHIFT; |
|
|
|
private static final int STACK_KIND = 5 << KIND_SHIFT; |
|
|
|
private static final int LOCAL_KIND = 5 << KIND_SHIFT; |
|
|
|
|
|
|
|
private static final int STACK_KIND = 6 << KIND_SHIFT; |
|
|
|
|
|
|
|
|
|
|
|
// Possible flags for the FLAGS field of an abstract type.
|
|
|
|
// Possible flags for the FLAGS field of an abstract type.
|
|
|
|
|
|
|
|
|
|
|
|
@ -220,13 +224,13 @@ class Frame { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* The abstract types that are initialized in the basic block. A constructor invocation on an |
|
|
|
* The abstract types that are initialized in the basic block. A constructor invocation on an |
|
|
|
* UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace <i>every occurrence</i> of this |
|
|
|
* UNINITIALIZED, FORWARD_UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace <i>every |
|
|
|
* type in the local variables and in the operand stack. This cannot be done during the first step |
|
|
|
* occurrence</i> of this type in the local variables and in the operand stack. This cannot be |
|
|
|
* of the algorithm since, during this step, the local variables and the operand stack types are |
|
|
|
* done during the first step of the algorithm since, during this step, the local variables and |
|
|
|
* still abstract. It is therefore necessary to store the abstract types of the constructors which |
|
|
|
* the operand stack types are still abstract. It is therefore necessary to store the abstract |
|
|
|
* are invoked in the basic block, in order to do this replacement during the second step of the |
|
|
|
* types of the constructors which are invoked in the basic block, in order to do this replacement |
|
|
|
* algorithm, where the frames are fully computed. Note that this array can contain abstract types |
|
|
|
* during the second step of the algorithm, where the frames are fully computed. Note that this |
|
|
|
* that are relative to the input locals or to the input stack. |
|
|
|
* array can contain abstract types that are relative to the input locals or to the input stack. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private int[] initializations; |
|
|
|
private int[] initializations; |
|
|
|
|
|
|
|
|
|
|
|
@ -284,8 +288,12 @@ class Frame { |
|
|
|
String descriptor = Type.getObjectType((String) type).getDescriptor(); |
|
|
|
String descriptor = Type.getObjectType((String) type).getDescriptor(); |
|
|
|
return getAbstractTypeFromDescriptor(symbolTable, descriptor, 0); |
|
|
|
return getAbstractTypeFromDescriptor(symbolTable, descriptor, 0); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return UNINITIALIZED_KIND |
|
|
|
Label label = (Label) type; |
|
|
|
| symbolTable.addUninitializedType("", ((Label) type).bytecodeOffset); |
|
|
|
if ((label.flags & Label.FLAG_RESOLVED) != 0) { |
|
|
|
|
|
|
|
return UNINITIALIZED_KIND | symbolTable.addUninitializedType("", label.bytecodeOffset); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return FORWARD_UNINITIALIZED_KIND | symbolTable.addForwardUninitializedType("", label); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -637,12 +645,14 @@ class Frame { |
|
|
|
* @param symbolTable the type table to use to lookup and store type {@link Symbol}. |
|
|
|
* @param symbolTable the type table to use to lookup and store type {@link Symbol}. |
|
|
|
* @param abstractType an abstract type. |
|
|
|
* @param abstractType an abstract type. |
|
|
|
* @return the REFERENCE_KIND abstract type corresponding to abstractType if it is |
|
|
|
* @return the REFERENCE_KIND abstract type corresponding to abstractType if it is |
|
|
|
* UNINITIALIZED_THIS or an UNINITIALIZED_KIND abstract type for one of the types on which a |
|
|
|
* UNINITIALIZED_THIS or an UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND abstract type for |
|
|
|
* constructor is invoked in the basic block. Otherwise returns abstractType. |
|
|
|
* one of the types on which a constructor is invoked in the basic block. Otherwise returns |
|
|
|
|
|
|
|
* abstractType. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private int getInitializedType(final SymbolTable symbolTable, final int abstractType) { |
|
|
|
private int getInitializedType(final SymbolTable symbolTable, final int abstractType) { |
|
|
|
if (abstractType == UNINITIALIZED_THIS |
|
|
|
if (abstractType == UNINITIALIZED_THIS |
|
|
|
|| (abstractType & (DIM_MASK | KIND_MASK)) == UNINITIALIZED_KIND) { |
|
|
|
|| (abstractType & (DIM_MASK | KIND_MASK)) == UNINITIALIZED_KIND |
|
|
|
|
|
|
|
|| (abstractType & (DIM_MASK | KIND_MASK)) == FORWARD_UNINITIALIZED_KIND) { |
|
|
|
for (int i = 0; i < initializationCount; ++i) { |
|
|
|
for (int i = 0; i < initializationCount; ++i) { |
|
|
|
int initializedType = initializations[i]; |
|
|
|
int initializedType = initializations[i]; |
|
|
|
int dim = initializedType & DIM_MASK; |
|
|
|
int dim = initializedType & DIM_MASK; |
|
|
|
@ -1253,11 +1263,12 @@ class Frame { |
|
|
|
* |
|
|
|
* |
|
|
|
* @param symbolTable the type table to use to lookup and store type {@link Symbol}. |
|
|
|
* @param symbolTable the type table to use to lookup and store type {@link Symbol}. |
|
|
|
* @param sourceType the abstract type with which the abstract type array element must be merged. |
|
|
|
* @param sourceType the abstract type with which the abstract type array element must be merged. |
|
|
|
* This type should be of {@link #CONSTANT_KIND}, {@link #REFERENCE_KIND} or {@link |
|
|
|
* This type should be of {@link #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link |
|
|
|
* #UNINITIALIZED_KIND} kind, with positive or {@literal null} array dimensions. |
|
|
|
* #UNINITIALIZED_KIND} or {@link #FORWARD_UNINITIALIZED_KIND} kind, with positive or |
|
|
|
|
|
|
|
* {@literal null} array dimensions. |
|
|
|
* @param dstTypes an array of abstract types. These types should be of {@link #CONSTANT_KIND}, |
|
|
|
* @param dstTypes an array of abstract types. These types should be of {@link #CONSTANT_KIND}, |
|
|
|
* {@link #REFERENCE_KIND} or {@link #UNINITIALIZED_KIND} kind, with positive or {@literal |
|
|
|
* {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND} or {@link #FORWARD_UNINITIALIZED_KIND} |
|
|
|
* null} array dimensions. |
|
|
|
* kind, with positive or {@literal null} array dimensions. |
|
|
|
* @param dstIndex the index of the type that must be merged in dstTypes. |
|
|
|
* @param dstIndex the index of the type that must be merged in dstTypes. |
|
|
|
* @return {@literal true} if the type array has been modified by this operation. |
|
|
|
* @return {@literal true} if the type array has been modified by this operation. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@ -1400,7 +1411,8 @@ class Frame { |
|
|
|
* |
|
|
|
* |
|
|
|
* @param symbolTable the type table to use to lookup and store type {@link Symbol}. |
|
|
|
* @param symbolTable the type table to use to lookup and store type {@link Symbol}. |
|
|
|
* @param abstractType an abstract type, restricted to {@link Frame#CONSTANT_KIND}, {@link |
|
|
|
* @param abstractType an abstract type, restricted to {@link Frame#CONSTANT_KIND}, {@link |
|
|
|
* Frame#REFERENCE_KIND} or {@link Frame#UNINITIALIZED_KIND} types. |
|
|
|
* Frame#REFERENCE_KIND}, {@link Frame#UNINITIALIZED_KIND} or {@link |
|
|
|
|
|
|
|
* Frame#FORWARD_UNINITIALIZED_KIND} types. |
|
|
|
* @param output where the abstract type must be put. |
|
|
|
* @param output where the abstract type must be put. |
|
|
|
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.4">JVMS |
|
|
|
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.4">JVMS |
|
|
|
* 4.7.4</a> |
|
|
|
* 4.7.4</a> |
|
|
|
@ -1422,6 +1434,10 @@ class Frame { |
|
|
|
case UNINITIALIZED_KIND: |
|
|
|
case UNINITIALIZED_KIND: |
|
|
|
output.putByte(ITEM_UNINITIALIZED).putShort((int) symbolTable.getType(typeValue).data); |
|
|
|
output.putByte(ITEM_UNINITIALIZED).putShort((int) symbolTable.getType(typeValue).data); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case FORWARD_UNINITIALIZED_KIND: |
|
|
|
|
|
|
|
output.putByte(ITEM_UNINITIALIZED); |
|
|
|
|
|
|
|
symbolTable.getForwardUninitializedLabel(typeValue).put(output); |
|
|
|
|
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
throw new AssertionError(); |
|
|
|
throw new AssertionError(); |
|
|
|
} |
|
|
|
} |
|
|
|
|