• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ASM: a very small and fast Java bytecode manipulation framework
2 // Copyright (c) 2000-2011 INRIA, France Telecom
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // 1. Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the distribution.
13 // 3. Neither the name of the copyright holders nor the names of its
14 //    contributors may be used to endorse or promote products derived from
15 //    this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 // THE POSSIBILITY OF SUCH DAMAGE.
28 package org.objectweb.asm;
29 
30 /**
31  * The input and output stack map frames of a basic block.
32  *
33  * <p>Stack map frames are computed in two steps:
34  *
35  * <ul>
36  *   <li>During the visit of each instruction in MethodWriter, the state of the frame at the end of
37  *       the current basic block is updated by simulating the action of the instruction on the
38  *       previous state of this so called "output frame".
39  *   <li>After all instructions have been visited, a fix point algorithm is used in MethodWriter to
40  *       compute the "input frame" of each basic block (i.e. the stack map frame at the beginning of
41  *       the basic block). See {@link MethodWriter#computeAllFrames}.
42  * </ul>
43  *
44  * <p>Output stack map frames are computed relatively to the input frame of the basic block, which
45  * is not yet known when output frames are computed. It is therefore necessary to be able to
46  * represent abstract types such as "the type at position x in the input frame locals" or "the type
47  * at position x from the top of the input frame stack" or even "the type at position x in the input
48  * frame, with y more (or less) array dimensions". This explains the rather complicated type format
49  * used in this class, explained below.
50  *
51  * <p>The local variables and the operand stack of input and output frames contain values called
52  * "abstract types" hereafter. An abstract type is represented with 4 fields named DIM, KIND, FLAGS
53  * and VALUE, packed in a single int value for better performance and memory efficiency:
54  *
55  * <pre>
56  *   =====================================
57  *   |...DIM|KIND|.F|...............VALUE|
58  *   =====================================
59  * </pre>
60  *
61  * <ul>
62  *   <li>the DIM field, stored in the 6 most significant bits, is a signed number of array
63  *       dimensions (from -32 to 31, included). It can be retrieved with {@link #DIM_MASK} and a
64  *       right shift of {@link #DIM_SHIFT}.
65  *   <li>the KIND field, stored in 4 bits, indicates the kind of VALUE used. These 4 bits can be
66  *       retrieved with {@link #KIND_MASK} and, without any shift, must be equal to {@link
67  *       #CONSTANT_KIND}, {@link #REFERENCE_KIND}, {@link #UNINITIALIZED_KIND}, {@link #LOCAL_KIND}
68  *       or {@link #STACK_KIND}.
69  *   <li>the FLAGS field, stored in 2 bits, contains up to 2 boolean flags. Currently only one flag
70  *       is defined, namely {@link #TOP_IF_LONG_OR_DOUBLE_FLAG}.
71  *   <li>the VALUE field, stored in the remaining 20 bits, contains either
72  *       <ul>
73  *         <li>one of the constants {@link #ITEM_TOP}, {@link #ITEM_ASM_BOOLEAN}, {@link
74  *             #ITEM_ASM_BYTE}, {@link #ITEM_ASM_CHAR} or {@link #ITEM_ASM_SHORT}, {@link
75  *             #ITEM_INTEGER}, {@link #ITEM_FLOAT}, {@link #ITEM_LONG}, {@link #ITEM_DOUBLE}, {@link
76  *             #ITEM_NULL} or {@link #ITEM_UNINITIALIZED_THIS}, if KIND is equal to {@link
77  *             #CONSTANT_KIND}.
78  *         <li>the index of a {@link Symbol#TYPE_TAG} {@link Symbol} in the type table of a {@link
79  *             SymbolTable}, if KIND is equal to {@link #REFERENCE_KIND}.
80  *         <li>the index of an {@link Symbol#UNINITIALIZED_TYPE_TAG} {@link Symbol} in the type
81  *             table of a SymbolTable, if KIND is equal to {@link #UNINITIALIZED_KIND}.
82  *         <li>the index of a local variable in the input stack frame, if KIND is equal to {@link
83  *             #LOCAL_KIND}.
84  *         <li>a position relatively to the top of the stack of the input stack frame, if KIND is
85  *             equal to {@link #STACK_KIND},
86  *       </ul>
87  * </ul>
88  *
89  * <p>Output frames can contain abstract types of any kind and with a positive or negative array
90  * dimension (and even unassigned types, represented by 0 - which does not correspond to any valid
91  * abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND or
92  * UNINITIALIZED_KIND abstract types of positive or {@literal null} array dimension. In all cases
93  * the type table contains only internal type names (array type descriptors are forbidden - array
94  * dimensions must be represented through the DIM field).
95  *
96  * <p>The LONG and DOUBLE types are always represented by using two slots (LONG + TOP or DOUBLE +
97  * TOP), for local variables as well as in the operand stack. This is necessary to be able to
98  * simulate DUPx_y instructions, whose effect would be dependent on the concrete types represented
99  * by the abstract types in the stack (which are not always known).
100  *
101  * @author Eric Bruneton
102  */
103 class Frame {
104 
105   // Constants used in the StackMapTable attribute.
106   // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.4.
107 
108   static final int SAME_FRAME = 0;
109   static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64;
110   static final int RESERVED = 128;
111   static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247;
112   static final int CHOP_FRAME = 248;
113   static final int SAME_FRAME_EXTENDED = 251;
114   static final int APPEND_FRAME = 252;
115   static final int FULL_FRAME = 255;
116 
117   static final int ITEM_TOP = 0;
118   static final int ITEM_INTEGER = 1;
119   static final int ITEM_FLOAT = 2;
120   static final int ITEM_DOUBLE = 3;
121   static final int ITEM_LONG = 4;
122   static final int ITEM_NULL = 5;
123   static final int ITEM_UNINITIALIZED_THIS = 6;
124   static final int ITEM_OBJECT = 7;
125   static final int ITEM_UNINITIALIZED = 8;
126   // Additional, ASM specific constants used in abstract types below.
127   private static final int ITEM_ASM_BOOLEAN = 9;
128   private static final int ITEM_ASM_BYTE = 10;
129   private static final int ITEM_ASM_CHAR = 11;
130   private static final int ITEM_ASM_SHORT = 12;
131 
132   // The size and offset in bits of each field of an abstract type.
133 
134   private static final int DIM_SIZE = 6;
135   private static final int KIND_SIZE = 4;
136   private static final int FLAGS_SIZE = 2;
137   private static final int VALUE_SIZE = 32 - DIM_SIZE - KIND_SIZE - FLAGS_SIZE;
138 
139   private static final int DIM_SHIFT = KIND_SIZE + FLAGS_SIZE + VALUE_SIZE;
140   private static final int KIND_SHIFT = FLAGS_SIZE + VALUE_SIZE;
141   private static final int FLAGS_SHIFT = VALUE_SIZE;
142 
143   // Bitmasks to get each field of an abstract type.
144 
145   private static final int DIM_MASK = ((1 << DIM_SIZE) - 1) << DIM_SHIFT;
146   private static final int KIND_MASK = ((1 << KIND_SIZE) - 1) << KIND_SHIFT;
147   private static final int VALUE_MASK = (1 << VALUE_SIZE) - 1;
148 
149   // Constants to manipulate the DIM field of an abstract type.
150 
151   /** The constant to be added to an abstract type to get one with one more array dimension. */
152   private static final int ARRAY_OF = +1 << DIM_SHIFT;
153 
154   /** The constant to be added to an abstract type to get one with one less array dimension. */
155   private static final int ELEMENT_OF = -1 << DIM_SHIFT;
156 
157   // Possible values for the KIND field of an abstract type.
158 
159   private static final int CONSTANT_KIND = 1 << KIND_SHIFT;
160   private static final int REFERENCE_KIND = 2 << KIND_SHIFT;
161   private static final int UNINITIALIZED_KIND = 3 << KIND_SHIFT;
162   private static final int LOCAL_KIND = 4 << KIND_SHIFT;
163   private static final int STACK_KIND = 5 << KIND_SHIFT;
164 
165   // Possible flags for the FLAGS field of an abstract type.
166 
167   /**
168    * A flag used for LOCAL_KIND and STACK_KIND abstract types, indicating that if the resolved,
169    * concrete type is LONG or DOUBLE, TOP should be used instead (because the value has been
170    * partially overridden with an xSTORE instruction).
171    */
172   private static final int TOP_IF_LONG_OR_DOUBLE_FLAG = 1 << FLAGS_SHIFT;
173 
174   // Useful predefined abstract types (all the possible CONSTANT_KIND types).
175 
176   private static final int TOP = CONSTANT_KIND | ITEM_TOP;
177   private static final int BOOLEAN = CONSTANT_KIND | ITEM_ASM_BOOLEAN;
178   private static final int BYTE = CONSTANT_KIND | ITEM_ASM_BYTE;
179   private static final int CHAR = CONSTANT_KIND | ITEM_ASM_CHAR;
180   private static final int SHORT = CONSTANT_KIND | ITEM_ASM_SHORT;
181   private static final int INTEGER = CONSTANT_KIND | ITEM_INTEGER;
182   private static final int FLOAT = CONSTANT_KIND | ITEM_FLOAT;
183   private static final int LONG = CONSTANT_KIND | ITEM_LONG;
184   private static final int DOUBLE = CONSTANT_KIND | ITEM_DOUBLE;
185   private static final int NULL = CONSTANT_KIND | ITEM_NULL;
186   private static final int UNINITIALIZED_THIS = CONSTANT_KIND | ITEM_UNINITIALIZED_THIS;
187 
188   // -----------------------------------------------------------------------------------------------
189   // Instance fields
190   // -----------------------------------------------------------------------------------------------
191 
192   /** The basic block to which these input and output stack map frames correspond. */
193   Label owner;
194 
195   /** The input stack map frame locals. This is an array of abstract types. */
196   private int[] inputLocals;
197 
198   /** The input stack map frame stack. This is an array of abstract types. */
199   private int[] inputStack;
200 
201   /** The output stack map frame locals. This is an array of abstract types. */
202   private int[] outputLocals;
203 
204   /** The output stack map frame stack. This is an array of abstract types. */
205   private int[] outputStack;
206 
207   /**
208    * The start of the output stack, relatively to the input stack. This offset is always negative or
209    * null. A null offset means that the output stack must be appended to the input stack. A -n
210    * offset means that the first n output stack elements must replace the top n input stack
211    * elements, and that the other elements must be appended to the input stack.
212    */
213   private short outputStackStart;
214 
215   /** The index of the top stack element in {@link #outputStack}. */
216   private short outputStackTop;
217 
218   /** The number of types that are initialized in the basic block. See {@link #initializations}. */
219   private int initializationCount;
220 
221   /**
222    * The abstract types that are initialized in the basic block. A constructor invocation on an
223    * UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace <i>every occurrence</i> of this
224    * type in the local variables and in the operand stack. This cannot be done during the first step
225    * of the algorithm since, during this step, the local variables and the operand stack types are
226    * still abstract. It is therefore necessary to store the abstract types of the constructors which
227    * are invoked in the basic block, in order to do this replacement during the second step of the
228    * algorithm, where the frames are fully computed. Note that this array can contain abstract types
229    * that are relative to the input locals or to the input stack.
230    */
231   private int[] initializations;
232 
233   // -----------------------------------------------------------------------------------------------
234   // Constructor
235   // -----------------------------------------------------------------------------------------------
236 
237   /**
238    * Constructs a new Frame.
239    *
240    * @param owner the basic block to which these input and output stack map frames correspond.
241    */
Frame(final Label owner)242   Frame(final Label owner) {
243     this.owner = owner;
244   }
245 
246   /**
247    * Sets this frame to the value of the given frame.
248    *
249    * <p>WARNING: after this method is called the two frames share the same data structures. It is
250    * recommended to discard the given frame to avoid unexpected side effects.
251    *
252    * @param frame The new frame value.
253    */
copyFrom(final Frame frame)254   final void copyFrom(final Frame frame) {
255     inputLocals = frame.inputLocals;
256     inputStack = frame.inputStack;
257     outputStackStart = 0;
258     outputLocals = frame.outputLocals;
259     outputStack = frame.outputStack;
260     outputStackTop = frame.outputStackTop;
261     initializationCount = frame.initializationCount;
262     initializations = frame.initializations;
263   }
264 
265   // -----------------------------------------------------------------------------------------------
266   // Static methods to get abstract types from other type formats
267   // -----------------------------------------------------------------------------------------------
268 
269   /**
270    * Returns the abstract type corresponding to the given public API frame element type.
271    *
272    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
273    * @param type a frame element type described using the same format as in {@link
274    *     MethodVisitor#visitFrame}, i.e. either {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link
275    *     Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL}, or
276    *     {@link Opcodes#UNINITIALIZED_THIS}, or the internal name of a class, or a Label designating
277    *     a NEW instruction (for uninitialized types).
278    * @return the abstract type corresponding to the given frame element type.
279    */
getAbstractTypeFromApiFormat(final SymbolTable symbolTable, final Object type)280   static int getAbstractTypeFromApiFormat(final SymbolTable symbolTable, final Object type) {
281     if (type instanceof Integer) {
282       return CONSTANT_KIND | ((Integer) type).intValue();
283     } else if (type instanceof String) {
284       String descriptor = Type.getObjectType((String) type).getDescriptor();
285       return getAbstractTypeFromDescriptor(symbolTable, descriptor, 0);
286     } else {
287       return UNINITIALIZED_KIND
288           | symbolTable.addUninitializedType("", ((Label) type).bytecodeOffset);
289     }
290   }
291 
292   /**
293    * Returns the abstract type corresponding to the internal name of a class.
294    *
295    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
296    * @param internalName the internal name of a class. This must <i>not</i> be an array type
297    *     descriptor.
298    * @return the abstract type value corresponding to the given internal name.
299    */
getAbstractTypeFromInternalName( final SymbolTable symbolTable, final String internalName)300   static int getAbstractTypeFromInternalName(
301       final SymbolTable symbolTable, final String internalName) {
302     return REFERENCE_KIND | symbolTable.addType(internalName);
303   }
304 
305   /**
306    * Returns the abstract type corresponding to the given type descriptor.
307    *
308    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
309    * @param buffer a string ending with a type descriptor.
310    * @param offset the start offset of the type descriptor in buffer.
311    * @return the abstract type corresponding to the given type descriptor.
312    */
getAbstractTypeFromDescriptor( final SymbolTable symbolTable, final String buffer, final int offset)313   private static int getAbstractTypeFromDescriptor(
314       final SymbolTable symbolTable, final String buffer, final int offset) {
315     String internalName;
316     switch (buffer.charAt(offset)) {
317       case 'V':
318         return 0;
319       case 'Z':
320       case 'C':
321       case 'B':
322       case 'S':
323       case 'I':
324         return INTEGER;
325       case 'F':
326         return FLOAT;
327       case 'J':
328         return LONG;
329       case 'D':
330         return DOUBLE;
331       case 'L':
332         internalName = buffer.substring(offset + 1, buffer.length() - 1);
333         return REFERENCE_KIND | symbolTable.addType(internalName);
334       case '[':
335         int elementDescriptorOffset = offset + 1;
336         while (buffer.charAt(elementDescriptorOffset) == '[') {
337           ++elementDescriptorOffset;
338         }
339         int typeValue;
340         switch (buffer.charAt(elementDescriptorOffset)) {
341           case 'Z':
342             typeValue = BOOLEAN;
343             break;
344           case 'C':
345             typeValue = CHAR;
346             break;
347           case 'B':
348             typeValue = BYTE;
349             break;
350           case 'S':
351             typeValue = SHORT;
352             break;
353           case 'I':
354             typeValue = INTEGER;
355             break;
356           case 'F':
357             typeValue = FLOAT;
358             break;
359           case 'J':
360             typeValue = LONG;
361             break;
362           case 'D':
363             typeValue = DOUBLE;
364             break;
365           case 'L':
366             internalName = buffer.substring(elementDescriptorOffset + 1, buffer.length() - 1);
367             typeValue = REFERENCE_KIND | symbolTable.addType(internalName);
368             break;
369           default:
370             throw new IllegalArgumentException();
371         }
372         return ((elementDescriptorOffset - offset) << DIM_SHIFT) | typeValue;
373       default:
374         throw new IllegalArgumentException();
375     }
376   }
377 
378   // -----------------------------------------------------------------------------------------------
379   // Methods related to the input frame
380   // -----------------------------------------------------------------------------------------------
381 
382   /**
383    * Sets the input frame from the given method description. This method is used to initialize the
384    * first frame of a method, which is implicit (i.e. not stored explicitly in the StackMapTable
385    * attribute).
386    *
387    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
388    * @param access the method's access flags.
389    * @param descriptor the method descriptor.
390    * @param maxLocals the maximum number of local variables of the method.
391    */
setInputFrameFromDescriptor( final SymbolTable symbolTable, final int access, final String descriptor, final int maxLocals)392   final void setInputFrameFromDescriptor(
393       final SymbolTable symbolTable,
394       final int access,
395       final String descriptor,
396       final int maxLocals) {
397     inputLocals = new int[maxLocals];
398     inputStack = new int[0];
399     int inputLocalIndex = 0;
400     if ((access & Opcodes.ACC_STATIC) == 0) {
401       if ((access & Constants.ACC_CONSTRUCTOR) == 0) {
402         inputLocals[inputLocalIndex++] =
403             REFERENCE_KIND | symbolTable.addType(symbolTable.getClassName());
404       } else {
405         inputLocals[inputLocalIndex++] = UNINITIALIZED_THIS;
406       }
407     }
408     for (Type argumentType : Type.getArgumentTypes(descriptor)) {
409       int abstractType =
410           getAbstractTypeFromDescriptor(symbolTable, argumentType.getDescriptor(), 0);
411       inputLocals[inputLocalIndex++] = abstractType;
412       if (abstractType == LONG || abstractType == DOUBLE) {
413         inputLocals[inputLocalIndex++] = TOP;
414       }
415     }
416     while (inputLocalIndex < maxLocals) {
417       inputLocals[inputLocalIndex++] = TOP;
418     }
419   }
420 
421   /**
422    * Sets the input frame from the given public API frame description.
423    *
424    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
425    * @param numLocal the number of local variables.
426    * @param local the local variable types, described using the same format as in {@link
427    *     MethodVisitor#visitFrame}.
428    * @param numStack the number of operand stack elements.
429    * @param stack the operand stack types, described using the same format as in {@link
430    *     MethodVisitor#visitFrame}.
431    */
setInputFrameFromApiFormat( final SymbolTable symbolTable, final int numLocal, final Object[] local, final int numStack, final Object[] stack)432   final void setInputFrameFromApiFormat(
433       final SymbolTable symbolTable,
434       final int numLocal,
435       final Object[] local,
436       final int numStack,
437       final Object[] stack) {
438     int inputLocalIndex = 0;
439     for (int i = 0; i < numLocal; ++i) {
440       inputLocals[inputLocalIndex++] = getAbstractTypeFromApiFormat(symbolTable, local[i]);
441       if (local[i] == Opcodes.LONG || local[i] == Opcodes.DOUBLE) {
442         inputLocals[inputLocalIndex++] = TOP;
443       }
444     }
445     while (inputLocalIndex < inputLocals.length) {
446       inputLocals[inputLocalIndex++] = TOP;
447     }
448     int numStackTop = 0;
449     for (int i = 0; i < numStack; ++i) {
450       if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
451         ++numStackTop;
452       }
453     }
454     inputStack = new int[numStack + numStackTop];
455     int inputStackIndex = 0;
456     for (int i = 0; i < numStack; ++i) {
457       inputStack[inputStackIndex++] = getAbstractTypeFromApiFormat(symbolTable, stack[i]);
458       if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) {
459         inputStack[inputStackIndex++] = TOP;
460       }
461     }
462     outputStackTop = 0;
463     initializationCount = 0;
464   }
465 
getInputStackSize()466   final int getInputStackSize() {
467     return inputStack.length;
468   }
469 
470   // -----------------------------------------------------------------------------------------------
471   // Methods related to the output frame
472   // -----------------------------------------------------------------------------------------------
473 
474   /**
475    * Returns the abstract type stored at the given local variable index in the output frame.
476    *
477    * @param localIndex the index of the local variable whose value must be returned.
478    * @return the abstract type stored at the given local variable index in the output frame.
479    */
getLocal(final int localIndex)480   private int getLocal(final int localIndex) {
481     if (outputLocals == null || localIndex >= outputLocals.length) {
482       // If this local has never been assigned in this basic block, it is still equal to its value
483       // in the input frame.
484       return LOCAL_KIND | localIndex;
485     } else {
486       int abstractType = outputLocals[localIndex];
487       if (abstractType == 0) {
488         // If this local has never been assigned in this basic block, so it is still equal to its
489         // value in the input frame.
490         abstractType = outputLocals[localIndex] = LOCAL_KIND | localIndex;
491       }
492       return abstractType;
493     }
494   }
495 
496   /**
497    * Replaces the abstract type stored at the given local variable index in the output frame.
498    *
499    * @param localIndex the index of the output frame local variable that must be set.
500    * @param abstractType the value that must be set.
501    */
setLocal(final int localIndex, final int abstractType)502   private void setLocal(final int localIndex, final int abstractType) {
503     // Create and/or resize the output local variables array if necessary.
504     if (outputLocals == null) {
505       outputLocals = new int[10];
506     }
507     int outputLocalsLength = outputLocals.length;
508     if (localIndex >= outputLocalsLength) {
509       int[] newOutputLocals = new int[Math.max(localIndex + 1, 2 * outputLocalsLength)];
510       System.arraycopy(outputLocals, 0, newOutputLocals, 0, outputLocalsLength);
511       outputLocals = newOutputLocals;
512     }
513     // Set the local variable.
514     outputLocals[localIndex] = abstractType;
515   }
516 
517   /**
518    * Pushes the given abstract type on the output frame stack.
519    *
520    * @param abstractType an abstract type.
521    */
push(final int abstractType)522   private void push(final int abstractType) {
523     // Create and/or resize the output stack array if necessary.
524     if (outputStack == null) {
525       outputStack = new int[10];
526     }
527     int outputStackLength = outputStack.length;
528     if (outputStackTop >= outputStackLength) {
529       int[] newOutputStack = new int[Math.max(outputStackTop + 1, 2 * outputStackLength)];
530       System.arraycopy(outputStack, 0, newOutputStack, 0, outputStackLength);
531       outputStack = newOutputStack;
532     }
533     // Pushes the abstract type on the output stack.
534     outputStack[outputStackTop++] = abstractType;
535     // Updates the maximum size reached by the output stack, if needed (note that this size is
536     // relative to the input stack size, which is not known yet).
537     short outputStackSize = (short) (outputStackStart + outputStackTop);
538     if (outputStackSize > owner.outputStackMax) {
539       owner.outputStackMax = outputStackSize;
540     }
541   }
542 
543   /**
544    * Pushes the abstract type corresponding to the given descriptor on the output frame stack.
545    *
546    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
547    * @param descriptor a type or method descriptor (in which case its return type is pushed).
548    */
push(final SymbolTable symbolTable, final String descriptor)549   private void push(final SymbolTable symbolTable, final String descriptor) {
550     int typeDescriptorOffset =
551         descriptor.charAt(0) == '(' ? Type.getReturnTypeOffset(descriptor) : 0;
552     int abstractType = getAbstractTypeFromDescriptor(symbolTable, descriptor, typeDescriptorOffset);
553     if (abstractType != 0) {
554       push(abstractType);
555       if (abstractType == LONG || abstractType == DOUBLE) {
556         push(TOP);
557       }
558     }
559   }
560 
561   /**
562    * Pops an abstract type from the output frame stack and returns its value.
563    *
564    * @return the abstract type that has been popped from the output frame stack.
565    */
pop()566   private int pop() {
567     if (outputStackTop > 0) {
568       return outputStack[--outputStackTop];
569     } else {
570       // If the output frame stack is empty, pop from the input stack.
571       return STACK_KIND | -(--outputStackStart);
572     }
573   }
574 
575   /**
576    * Pops the given number of abstract types from the output frame stack.
577    *
578    * @param elements the number of abstract types that must be popped.
579    */
pop(final int elements)580   private void pop(final int elements) {
581     if (outputStackTop >= elements) {
582       outputStackTop -= elements;
583     } else {
584       // If the number of elements to be popped is greater than the number of elements in the output
585       // stack, clear it, and pop the remaining elements from the input stack.
586       outputStackStart -= elements - outputStackTop;
587       outputStackTop = 0;
588     }
589   }
590 
591   /**
592    * Pops as many abstract types from the output frame stack as described by the given descriptor.
593    *
594    * @param descriptor a type or method descriptor (in which case its argument types are popped).
595    */
pop(final String descriptor)596   private void pop(final String descriptor) {
597     char firstDescriptorChar = descriptor.charAt(0);
598     if (firstDescriptorChar == '(') {
599       pop((Type.getArgumentsAndReturnSizes(descriptor) >> 2) - 1);
600     } else if (firstDescriptorChar == 'J' || firstDescriptorChar == 'D') {
601       pop(2);
602     } else {
603       pop(1);
604     }
605   }
606 
607   // -----------------------------------------------------------------------------------------------
608   // Methods to handle uninitialized types
609   // -----------------------------------------------------------------------------------------------
610 
611   /**
612    * Adds an abstract type to the list of types on which a constructor is invoked in the basic
613    * block.
614    *
615    * @param abstractType an abstract type on a which a constructor is invoked.
616    */
addInitializedType(final int abstractType)617   private void addInitializedType(final int abstractType) {
618     // Create and/or resize the initializations array if necessary.
619     if (initializations == null) {
620       initializations = new int[2];
621     }
622     int initializationsLength = initializations.length;
623     if (initializationCount >= initializationsLength) {
624       int[] newInitializations =
625           new int[Math.max(initializationCount + 1, 2 * initializationsLength)];
626       System.arraycopy(initializations, 0, newInitializations, 0, initializationsLength);
627       initializations = newInitializations;
628     }
629     // Store the abstract type.
630     initializations[initializationCount++] = abstractType;
631   }
632 
633   /**
634    * Returns the "initialized" abstract type corresponding to the given abstract type.
635    *
636    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
637    * @param abstractType an abstract type.
638    * @return the REFERENCE_KIND abstract type corresponding to abstractType if it is
639    *     UNINITIALIZED_THIS or an UNINITIALIZED_KIND abstract type for one of the types on which a
640    *     constructor is invoked in the basic block. Otherwise returns abstractType.
641    */
getInitializedType(final SymbolTable symbolTable, final int abstractType)642   private int getInitializedType(final SymbolTable symbolTable, final int abstractType) {
643     if (abstractType == UNINITIALIZED_THIS
644         || (abstractType & (DIM_MASK | KIND_MASK)) == UNINITIALIZED_KIND) {
645       for (int i = 0; i < initializationCount; ++i) {
646         int initializedType = initializations[i];
647         int dim = initializedType & DIM_MASK;
648         int kind = initializedType & KIND_MASK;
649         int value = initializedType & VALUE_MASK;
650         if (kind == LOCAL_KIND) {
651           initializedType = dim + inputLocals[value];
652         } else if (kind == STACK_KIND) {
653           initializedType = dim + inputStack[inputStack.length - value];
654         }
655         if (abstractType == initializedType) {
656           if (abstractType == UNINITIALIZED_THIS) {
657             return REFERENCE_KIND | symbolTable.addType(symbolTable.getClassName());
658           } else {
659             return REFERENCE_KIND
660                 | symbolTable.addType(symbolTable.getType(abstractType & VALUE_MASK).value);
661           }
662         }
663       }
664     }
665     return abstractType;
666   }
667 
668   // -----------------------------------------------------------------------------------------------
669   // Main method, to simulate the execution of each instruction on the output frame
670   // -----------------------------------------------------------------------------------------------
671 
672   /**
673    * Simulates the action of the given instruction on the output stack frame.
674    *
675    * @param opcode the opcode of the instruction.
676    * @param arg the numeric operand of the instruction, if any.
677    * @param argSymbol the Symbol operand of the instruction, if any.
678    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
679    */
execute( final int opcode, final int arg, final Symbol argSymbol, final SymbolTable symbolTable)680   void execute(
681       final int opcode, final int arg, final Symbol argSymbol, final SymbolTable symbolTable) {
682     // Abstract types popped from the stack or read from local variables.
683     int abstractType1;
684     int abstractType2;
685     int abstractType3;
686     int abstractType4;
687     switch (opcode) {
688       case Opcodes.NOP:
689       case Opcodes.INEG:
690       case Opcodes.LNEG:
691       case Opcodes.FNEG:
692       case Opcodes.DNEG:
693       case Opcodes.I2B:
694       case Opcodes.I2C:
695       case Opcodes.I2S:
696       case Opcodes.GOTO:
697       case Opcodes.RETURN:
698         break;
699       case Opcodes.ACONST_NULL:
700         push(NULL);
701         break;
702       case Opcodes.ICONST_M1:
703       case Opcodes.ICONST_0:
704       case Opcodes.ICONST_1:
705       case Opcodes.ICONST_2:
706       case Opcodes.ICONST_3:
707       case Opcodes.ICONST_4:
708       case Opcodes.ICONST_5:
709       case Opcodes.BIPUSH:
710       case Opcodes.SIPUSH:
711       case Opcodes.ILOAD:
712         push(INTEGER);
713         break;
714       case Opcodes.LCONST_0:
715       case Opcodes.LCONST_1:
716       case Opcodes.LLOAD:
717         push(LONG);
718         push(TOP);
719         break;
720       case Opcodes.FCONST_0:
721       case Opcodes.FCONST_1:
722       case Opcodes.FCONST_2:
723       case Opcodes.FLOAD:
724         push(FLOAT);
725         break;
726       case Opcodes.DCONST_0:
727       case Opcodes.DCONST_1:
728       case Opcodes.DLOAD:
729         push(DOUBLE);
730         push(TOP);
731         break;
732       case Opcodes.LDC:
733         switch (argSymbol.tag) {
734           case Symbol.CONSTANT_INTEGER_TAG:
735             push(INTEGER);
736             break;
737           case Symbol.CONSTANT_LONG_TAG:
738             push(LONG);
739             push(TOP);
740             break;
741           case Symbol.CONSTANT_FLOAT_TAG:
742             push(FLOAT);
743             break;
744           case Symbol.CONSTANT_DOUBLE_TAG:
745             push(DOUBLE);
746             push(TOP);
747             break;
748           case Symbol.CONSTANT_CLASS_TAG:
749             push(REFERENCE_KIND | symbolTable.addType("java/lang/Class"));
750             break;
751           case Symbol.CONSTANT_STRING_TAG:
752             push(REFERENCE_KIND | symbolTable.addType("java/lang/String"));
753             break;
754           case Symbol.CONSTANT_METHOD_TYPE_TAG:
755             push(REFERENCE_KIND | symbolTable.addType("java/lang/invoke/MethodType"));
756             break;
757           case Symbol.CONSTANT_METHOD_HANDLE_TAG:
758             push(REFERENCE_KIND | symbolTable.addType("java/lang/invoke/MethodHandle"));
759             break;
760           case Symbol.CONSTANT_DYNAMIC_TAG:
761             push(symbolTable, argSymbol.value);
762             break;
763           default:
764             throw new AssertionError();
765         }
766         break;
767       case Opcodes.ALOAD:
768         push(getLocal(arg));
769         break;
770       case Opcodes.LALOAD:
771       case Opcodes.D2L:
772         pop(2);
773         push(LONG);
774         push(TOP);
775         break;
776       case Opcodes.DALOAD:
777       case Opcodes.L2D:
778         pop(2);
779         push(DOUBLE);
780         push(TOP);
781         break;
782       case Opcodes.AALOAD:
783         pop(1);
784         abstractType1 = pop();
785         push(abstractType1 == NULL ? abstractType1 : ELEMENT_OF + abstractType1);
786         break;
787       case Opcodes.ISTORE:
788       case Opcodes.FSTORE:
789       case Opcodes.ASTORE:
790         abstractType1 = pop();
791         setLocal(arg, abstractType1);
792         if (arg > 0) {
793           int previousLocalType = getLocal(arg - 1);
794           if (previousLocalType == LONG || previousLocalType == DOUBLE) {
795             setLocal(arg - 1, TOP);
796           } else if ((previousLocalType & KIND_MASK) == LOCAL_KIND
797               || (previousLocalType & KIND_MASK) == STACK_KIND) {
798             // The type of the previous local variable is not known yet, but if it later appears
799             // to be LONG or DOUBLE, we should then use TOP instead.
800             setLocal(arg - 1, previousLocalType | TOP_IF_LONG_OR_DOUBLE_FLAG);
801           }
802         }
803         break;
804       case Opcodes.LSTORE:
805       case Opcodes.DSTORE:
806         pop(1);
807         abstractType1 = pop();
808         setLocal(arg, abstractType1);
809         setLocal(arg + 1, TOP);
810         if (arg > 0) {
811           int previousLocalType = getLocal(arg - 1);
812           if (previousLocalType == LONG || previousLocalType == DOUBLE) {
813             setLocal(arg - 1, TOP);
814           } else if ((previousLocalType & KIND_MASK) == LOCAL_KIND
815               || (previousLocalType & KIND_MASK) == STACK_KIND) {
816             // The type of the previous local variable is not known yet, but if it later appears
817             // to be LONG or DOUBLE, we should then use TOP instead.
818             setLocal(arg - 1, previousLocalType | TOP_IF_LONG_OR_DOUBLE_FLAG);
819           }
820         }
821         break;
822       case Opcodes.IASTORE:
823       case Opcodes.BASTORE:
824       case Opcodes.CASTORE:
825       case Opcodes.SASTORE:
826       case Opcodes.FASTORE:
827       case Opcodes.AASTORE:
828         pop(3);
829         break;
830       case Opcodes.LASTORE:
831       case Opcodes.DASTORE:
832         pop(4);
833         break;
834       case Opcodes.POP:
835       case Opcodes.IFEQ:
836       case Opcodes.IFNE:
837       case Opcodes.IFLT:
838       case Opcodes.IFGE:
839       case Opcodes.IFGT:
840       case Opcodes.IFLE:
841       case Opcodes.IRETURN:
842       case Opcodes.FRETURN:
843       case Opcodes.ARETURN:
844       case Opcodes.TABLESWITCH:
845       case Opcodes.LOOKUPSWITCH:
846       case Opcodes.ATHROW:
847       case Opcodes.MONITORENTER:
848       case Opcodes.MONITOREXIT:
849       case Opcodes.IFNULL:
850       case Opcodes.IFNONNULL:
851         pop(1);
852         break;
853       case Opcodes.POP2:
854       case Opcodes.IF_ICMPEQ:
855       case Opcodes.IF_ICMPNE:
856       case Opcodes.IF_ICMPLT:
857       case Opcodes.IF_ICMPGE:
858       case Opcodes.IF_ICMPGT:
859       case Opcodes.IF_ICMPLE:
860       case Opcodes.IF_ACMPEQ:
861       case Opcodes.IF_ACMPNE:
862       case Opcodes.LRETURN:
863       case Opcodes.DRETURN:
864         pop(2);
865         break;
866       case Opcodes.DUP:
867         abstractType1 = pop();
868         push(abstractType1);
869         push(abstractType1);
870         break;
871       case Opcodes.DUP_X1:
872         abstractType1 = pop();
873         abstractType2 = pop();
874         push(abstractType1);
875         push(abstractType2);
876         push(abstractType1);
877         break;
878       case Opcodes.DUP_X2:
879         abstractType1 = pop();
880         abstractType2 = pop();
881         abstractType3 = pop();
882         push(abstractType1);
883         push(abstractType3);
884         push(abstractType2);
885         push(abstractType1);
886         break;
887       case Opcodes.DUP2:
888         abstractType1 = pop();
889         abstractType2 = pop();
890         push(abstractType2);
891         push(abstractType1);
892         push(abstractType2);
893         push(abstractType1);
894         break;
895       case Opcodes.DUP2_X1:
896         abstractType1 = pop();
897         abstractType2 = pop();
898         abstractType3 = pop();
899         push(abstractType2);
900         push(abstractType1);
901         push(abstractType3);
902         push(abstractType2);
903         push(abstractType1);
904         break;
905       case Opcodes.DUP2_X2:
906         abstractType1 = pop();
907         abstractType2 = pop();
908         abstractType3 = pop();
909         abstractType4 = pop();
910         push(abstractType2);
911         push(abstractType1);
912         push(abstractType4);
913         push(abstractType3);
914         push(abstractType2);
915         push(abstractType1);
916         break;
917       case Opcodes.SWAP:
918         abstractType1 = pop();
919         abstractType2 = pop();
920         push(abstractType1);
921         push(abstractType2);
922         break;
923       case Opcodes.IALOAD:
924       case Opcodes.BALOAD:
925       case Opcodes.CALOAD:
926       case Opcodes.SALOAD:
927       case Opcodes.IADD:
928       case Opcodes.ISUB:
929       case Opcodes.IMUL:
930       case Opcodes.IDIV:
931       case Opcodes.IREM:
932       case Opcodes.IAND:
933       case Opcodes.IOR:
934       case Opcodes.IXOR:
935       case Opcodes.ISHL:
936       case Opcodes.ISHR:
937       case Opcodes.IUSHR:
938       case Opcodes.L2I:
939       case Opcodes.D2I:
940       case Opcodes.FCMPL:
941       case Opcodes.FCMPG:
942         pop(2);
943         push(INTEGER);
944         break;
945       case Opcodes.LADD:
946       case Opcodes.LSUB:
947       case Opcodes.LMUL:
948       case Opcodes.LDIV:
949       case Opcodes.LREM:
950       case Opcodes.LAND:
951       case Opcodes.LOR:
952       case Opcodes.LXOR:
953         pop(4);
954         push(LONG);
955         push(TOP);
956         break;
957       case Opcodes.FALOAD:
958       case Opcodes.FADD:
959       case Opcodes.FSUB:
960       case Opcodes.FMUL:
961       case Opcodes.FDIV:
962       case Opcodes.FREM:
963       case Opcodes.L2F:
964       case Opcodes.D2F:
965         pop(2);
966         push(FLOAT);
967         break;
968       case Opcodes.DADD:
969       case Opcodes.DSUB:
970       case Opcodes.DMUL:
971       case Opcodes.DDIV:
972       case Opcodes.DREM:
973         pop(4);
974         push(DOUBLE);
975         push(TOP);
976         break;
977       case Opcodes.LSHL:
978       case Opcodes.LSHR:
979       case Opcodes.LUSHR:
980         pop(3);
981         push(LONG);
982         push(TOP);
983         break;
984       case Opcodes.IINC:
985         setLocal(arg, INTEGER);
986         break;
987       case Opcodes.I2L:
988       case Opcodes.F2L:
989         pop(1);
990         push(LONG);
991         push(TOP);
992         break;
993       case Opcodes.I2F:
994         pop(1);
995         push(FLOAT);
996         break;
997       case Opcodes.I2D:
998       case Opcodes.F2D:
999         pop(1);
1000         push(DOUBLE);
1001         push(TOP);
1002         break;
1003       case Opcodes.F2I:
1004       case Opcodes.ARRAYLENGTH:
1005       case Opcodes.INSTANCEOF:
1006         pop(1);
1007         push(INTEGER);
1008         break;
1009       case Opcodes.LCMP:
1010       case Opcodes.DCMPL:
1011       case Opcodes.DCMPG:
1012         pop(4);
1013         push(INTEGER);
1014         break;
1015       case Opcodes.JSR:
1016       case Opcodes.RET:
1017         throw new IllegalArgumentException("JSR/RET are not supported with computeFrames option");
1018       case Opcodes.GETSTATIC:
1019         push(symbolTable, argSymbol.value);
1020         break;
1021       case Opcodes.PUTSTATIC:
1022         pop(argSymbol.value);
1023         break;
1024       case Opcodes.GETFIELD:
1025         pop(1);
1026         push(symbolTable, argSymbol.value);
1027         break;
1028       case Opcodes.PUTFIELD:
1029         pop(argSymbol.value);
1030         pop();
1031         break;
1032       case Opcodes.INVOKEVIRTUAL:
1033       case Opcodes.INVOKESPECIAL:
1034       case Opcodes.INVOKESTATIC:
1035       case Opcodes.INVOKEINTERFACE:
1036         pop(argSymbol.value);
1037         if (opcode != Opcodes.INVOKESTATIC) {
1038           abstractType1 = pop();
1039           if (opcode == Opcodes.INVOKESPECIAL && argSymbol.name.charAt(0) == '<') {
1040             addInitializedType(abstractType1);
1041           }
1042         }
1043         push(symbolTable, argSymbol.value);
1044         break;
1045       case Opcodes.INVOKEDYNAMIC:
1046         pop(argSymbol.value);
1047         push(symbolTable, argSymbol.value);
1048         break;
1049       case Opcodes.NEW:
1050         push(UNINITIALIZED_KIND | symbolTable.addUninitializedType(argSymbol.value, arg));
1051         break;
1052       case Opcodes.NEWARRAY:
1053         pop();
1054         switch (arg) {
1055           case Opcodes.T_BOOLEAN:
1056             push(ARRAY_OF | BOOLEAN);
1057             break;
1058           case Opcodes.T_CHAR:
1059             push(ARRAY_OF | CHAR);
1060             break;
1061           case Opcodes.T_BYTE:
1062             push(ARRAY_OF | BYTE);
1063             break;
1064           case Opcodes.T_SHORT:
1065             push(ARRAY_OF | SHORT);
1066             break;
1067           case Opcodes.T_INT:
1068             push(ARRAY_OF | INTEGER);
1069             break;
1070           case Opcodes.T_FLOAT:
1071             push(ARRAY_OF | FLOAT);
1072             break;
1073           case Opcodes.T_DOUBLE:
1074             push(ARRAY_OF | DOUBLE);
1075             break;
1076           case Opcodes.T_LONG:
1077             push(ARRAY_OF | LONG);
1078             break;
1079           default:
1080             throw new IllegalArgumentException();
1081         }
1082         break;
1083       case Opcodes.ANEWARRAY:
1084         String arrayElementType = argSymbol.value;
1085         pop();
1086         if (arrayElementType.charAt(0) == '[') {
1087           push(symbolTable, '[' + arrayElementType);
1088         } else {
1089           push(ARRAY_OF | REFERENCE_KIND | symbolTable.addType(arrayElementType));
1090         }
1091         break;
1092       case Opcodes.CHECKCAST:
1093         String castType = argSymbol.value;
1094         pop();
1095         if (castType.charAt(0) == '[') {
1096           push(symbolTable, castType);
1097         } else {
1098           push(REFERENCE_KIND | symbolTable.addType(castType));
1099         }
1100         break;
1101       case Opcodes.MULTIANEWARRAY:
1102         pop(arg);
1103         push(symbolTable, argSymbol.value);
1104         break;
1105       default:
1106         throw new IllegalArgumentException();
1107     }
1108   }
1109 
1110   // -----------------------------------------------------------------------------------------------
1111   // Frame merging methods, used in the second step of the stack map frame computation algorithm
1112   // -----------------------------------------------------------------------------------------------
1113 
1114   /**
1115    * Computes the concrete output type corresponding to a given abstract output type.
1116    *
1117    * @param abstractOutputType an abstract output type.
1118    * @param numStack the size of the input stack, used to resolve abstract output types of
1119    *     STACK_KIND kind.
1120    * @return the concrete output type corresponding to 'abstractOutputType'.
1121    */
getConcreteOutputType(final int abstractOutputType, final int numStack)1122   private int getConcreteOutputType(final int abstractOutputType, final int numStack) {
1123     int dim = abstractOutputType & DIM_MASK;
1124     int kind = abstractOutputType & KIND_MASK;
1125     if (kind == LOCAL_KIND) {
1126       // By definition, a LOCAL_KIND type designates the concrete type of a local variable at
1127       // the beginning of the basic block corresponding to this frame (which is known when
1128       // this method is called, but was not when the abstract type was computed).
1129       int concreteOutputType = dim + inputLocals[abstractOutputType & VALUE_MASK];
1130       if ((abstractOutputType & TOP_IF_LONG_OR_DOUBLE_FLAG) != 0
1131           && (concreteOutputType == LONG || concreteOutputType == DOUBLE)) {
1132         concreteOutputType = TOP;
1133       }
1134       return concreteOutputType;
1135     } else if (kind == STACK_KIND) {
1136       // By definition, a STACK_KIND type designates the concrete type of a local variable at
1137       // the beginning of the basic block corresponding to this frame (which is known when
1138       // this method is called, but was not when the abstract type was computed).
1139       int concreteOutputType = dim + inputStack[numStack - (abstractOutputType & VALUE_MASK)];
1140       if ((abstractOutputType & TOP_IF_LONG_OR_DOUBLE_FLAG) != 0
1141           && (concreteOutputType == LONG || concreteOutputType == DOUBLE)) {
1142         concreteOutputType = TOP;
1143       }
1144       return concreteOutputType;
1145     } else {
1146       return abstractOutputType;
1147     }
1148   }
1149 
1150   /**
1151    * Merges the input frame of the given {@link Frame} with the input and output frames of this
1152    * {@link Frame}. Returns {@literal true} if the given frame has been changed by this operation
1153    * (the input and output frames of this {@link Frame} are never changed).
1154    *
1155    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
1156    * @param dstFrame the {@link Frame} whose input frame must be updated. This should be the frame
1157    *     of a successor, in the control flow graph, of the basic block corresponding to this frame.
1158    * @param catchTypeIndex if 'frame' corresponds to an exception handler basic block, the type
1159    *     table index of the caught exception type, otherwise 0.
1160    * @return {@literal true} if the input frame of 'frame' has been changed by this operation.
1161    */
merge( final SymbolTable symbolTable, final Frame dstFrame, final int catchTypeIndex)1162   final boolean merge(
1163       final SymbolTable symbolTable, final Frame dstFrame, final int catchTypeIndex) {
1164     boolean frameChanged = false;
1165 
1166     // Compute the concrete types of the local variables at the end of the basic block corresponding
1167     // to this frame, by resolving its abstract output types, and merge these concrete types with
1168     // those of the local variables in the input frame of dstFrame.
1169     int numLocal = inputLocals.length;
1170     int numStack = inputStack.length;
1171     if (dstFrame.inputLocals == null) {
1172       dstFrame.inputLocals = new int[numLocal];
1173       frameChanged = true;
1174     }
1175     for (int i = 0; i < numLocal; ++i) {
1176       int concreteOutputType;
1177       if (outputLocals != null && i < outputLocals.length) {
1178         int abstractOutputType = outputLocals[i];
1179         if (abstractOutputType == 0) {
1180           // If the local variable has never been assigned in this basic block, it is equal to its
1181           // value at the beginning of the block.
1182           concreteOutputType = inputLocals[i];
1183         } else {
1184           concreteOutputType = getConcreteOutputType(abstractOutputType, numStack);
1185         }
1186       } else {
1187         // If the local variable has never been assigned in this basic block, it is equal to its
1188         // value at the beginning of the block.
1189         concreteOutputType = inputLocals[i];
1190       }
1191       // concreteOutputType might be an uninitialized type from the input locals or from the input
1192       // stack. However, if a constructor has been called for this class type in the basic block,
1193       // then this type is no longer uninitialized at the end of basic block.
1194       if (initializations != null) {
1195         concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
1196       }
1197       frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputLocals, i);
1198     }
1199 
1200     // If dstFrame is an exception handler block, it can be reached from any instruction of the
1201     // basic block corresponding to this frame, in particular from the first one. Therefore, the
1202     // input locals of dstFrame should be compatible (i.e. merged) with the input locals of this
1203     // frame (and the input stack of dstFrame should be compatible, i.e. merged, with a one
1204     // element stack containing the caught exception type).
1205     if (catchTypeIndex > 0) {
1206       for (int i = 0; i < numLocal; ++i) {
1207         frameChanged |= merge(symbolTable, inputLocals[i], dstFrame.inputLocals, i);
1208       }
1209       if (dstFrame.inputStack == null) {
1210         dstFrame.inputStack = new int[1];
1211         frameChanged = true;
1212       }
1213       frameChanged |= merge(symbolTable, catchTypeIndex, dstFrame.inputStack, 0);
1214       return frameChanged;
1215     }
1216 
1217     // Compute the concrete types of the stack operands at the end of the basic block corresponding
1218     // to this frame, by resolving its abstract output types, and merge these concrete types with
1219     // those of the stack operands in the input frame of dstFrame.
1220     int numInputStack = inputStack.length + outputStackStart;
1221     if (dstFrame.inputStack == null) {
1222       dstFrame.inputStack = new int[numInputStack + outputStackTop];
1223       frameChanged = true;
1224     }
1225     // First, do this for the stack operands that have not been popped in the basic block
1226     // corresponding to this frame, and which are therefore equal to their value in the input
1227     // frame (except for uninitialized types, which may have been initialized).
1228     for (int i = 0; i < numInputStack; ++i) {
1229       int concreteOutputType = inputStack[i];
1230       if (initializations != null) {
1231         concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
1232       }
1233       frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputStack, i);
1234     }
1235     // Then, do this for the stack operands that have pushed in the basic block (this code is the
1236     // same as the one above for local variables).
1237     for (int i = 0; i < outputStackTop; ++i) {
1238       int abstractOutputType = outputStack[i];
1239       int concreteOutputType = getConcreteOutputType(abstractOutputType, numStack);
1240       if (initializations != null) {
1241         concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
1242       }
1243       frameChanged |=
1244           merge(symbolTable, concreteOutputType, dstFrame.inputStack, numInputStack + i);
1245     }
1246     return frameChanged;
1247   }
1248 
1249   /**
1250    * Merges the type at the given index in the given abstract type array with the given type.
1251    * Returns {@literal true} if the type array has been modified by this operation.
1252    *
1253    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
1254    * @param sourceType the abstract type with which the abstract type array element must be merged.
1255    *     This type should be of {@link #CONSTANT_KIND}, {@link #REFERENCE_KIND} or {@link
1256    *     #UNINITIALIZED_KIND} kind, with positive or {@literal null} array dimensions.
1257    * @param dstTypes an array of abstract types. These types should be of {@link #CONSTANT_KIND},
1258    *     {@link #REFERENCE_KIND} or {@link #UNINITIALIZED_KIND} kind, with positive or {@literal
1259    *     null} array dimensions.
1260    * @param dstIndex the index of the type that must be merged in dstTypes.
1261    * @return {@literal true} if the type array has been modified by this operation.
1262    */
merge( final SymbolTable symbolTable, final int sourceType, final int[] dstTypes, final int dstIndex)1263   private static boolean merge(
1264       final SymbolTable symbolTable,
1265       final int sourceType,
1266       final int[] dstTypes,
1267       final int dstIndex) {
1268     int dstType = dstTypes[dstIndex];
1269     if (dstType == sourceType) {
1270       // If the types are equal, merge(sourceType, dstType) = dstType, so there is no change.
1271       return false;
1272     }
1273     int srcType = sourceType;
1274     if ((sourceType & ~DIM_MASK) == NULL) {
1275       if (dstType == NULL) {
1276         return false;
1277       }
1278       srcType = NULL;
1279     }
1280     if (dstType == 0) {
1281       // If dstTypes[dstIndex] has never been assigned, merge(srcType, dstType) = srcType.
1282       dstTypes[dstIndex] = srcType;
1283       return true;
1284     }
1285     int mergedType;
1286     if ((dstType & DIM_MASK) != 0 || (dstType & KIND_MASK) == REFERENCE_KIND) {
1287       // If dstType is a reference type of any array dimension.
1288       if (srcType == NULL) {
1289         // If srcType is the NULL type, merge(srcType, dstType) = dstType, so there is no change.
1290         return false;
1291       } else if ((srcType & (DIM_MASK | KIND_MASK)) == (dstType & (DIM_MASK | KIND_MASK))) {
1292         // If srcType has the same array dimension and the same kind as dstType.
1293         if ((dstType & KIND_MASK) == REFERENCE_KIND) {
1294           // If srcType and dstType are reference types with the same array dimension,
1295           // merge(srcType, dstType) = dim(srcType) | common super class of srcType and dstType.
1296           mergedType =
1297               (srcType & DIM_MASK)
1298                   | REFERENCE_KIND
1299                   | symbolTable.addMergedType(srcType & VALUE_MASK, dstType & VALUE_MASK);
1300         } else {
1301           // If srcType and dstType are array types of equal dimension but different element types,
1302           // merge(srcType, dstType) = dim(srcType) - 1 | java/lang/Object.
1303           int mergedDim = ELEMENT_OF + (srcType & DIM_MASK);
1304           mergedType = mergedDim | REFERENCE_KIND | symbolTable.addType("java/lang/Object");
1305         }
1306       } else if ((srcType & DIM_MASK) != 0 || (srcType & KIND_MASK) == REFERENCE_KIND) {
1307         // If srcType is any other reference or array type,
1308         // merge(srcType, dstType) = min(srcDdim, dstDim) | java/lang/Object
1309         // where srcDim is the array dimension of srcType, minus 1 if srcType is an array type
1310         // with a non reference element type (and similarly for dstDim).
1311         int srcDim = srcType & DIM_MASK;
1312         if (srcDim != 0 && (srcType & KIND_MASK) != REFERENCE_KIND) {
1313           srcDim = ELEMENT_OF + srcDim;
1314         }
1315         int dstDim = dstType & DIM_MASK;
1316         if (dstDim != 0 && (dstType & KIND_MASK) != REFERENCE_KIND) {
1317           dstDim = ELEMENT_OF + dstDim;
1318         }
1319         mergedType =
1320             Math.min(srcDim, dstDim) | REFERENCE_KIND | symbolTable.addType("java/lang/Object");
1321       } else {
1322         // If srcType is any other type, merge(srcType, dstType) = TOP.
1323         mergedType = TOP;
1324       }
1325     } else if (dstType == NULL) {
1326       // If dstType is the NULL type, merge(srcType, dstType) = srcType, or TOP if srcType is not a
1327       // an array type or a reference type.
1328       mergedType =
1329           (srcType & DIM_MASK) != 0 || (srcType & KIND_MASK) == REFERENCE_KIND ? srcType : TOP;
1330     } else {
1331       // If dstType is any other type, merge(srcType, dstType) = TOP whatever srcType.
1332       mergedType = TOP;
1333     }
1334     if (mergedType != dstType) {
1335       dstTypes[dstIndex] = mergedType;
1336       return true;
1337     }
1338     return false;
1339   }
1340 
1341   // -----------------------------------------------------------------------------------------------
1342   // Frame output methods, to generate StackMapFrame attributes
1343   // -----------------------------------------------------------------------------------------------
1344 
1345   /**
1346    * Makes the given {@link MethodWriter} visit the input frame of this {@link Frame}. The visit is
1347    * done with the {@link MethodWriter#visitFrameStart}, {@link MethodWriter#visitAbstractType} and
1348    * {@link MethodWriter#visitFrameEnd} methods.
1349    *
1350    * @param methodWriter the {@link MethodWriter} that should visit the input frame of this {@link
1351    *     Frame}.
1352    */
accept(final MethodWriter methodWriter)1353   final void accept(final MethodWriter methodWriter) {
1354     // Compute the number of locals, ignoring TOP types that are just after a LONG or a DOUBLE, and
1355     // all trailing TOP types.
1356     int[] localTypes = inputLocals;
1357     int numLocal = 0;
1358     int numTrailingTop = 0;
1359     int i = 0;
1360     while (i < localTypes.length) {
1361       int localType = localTypes[i];
1362       i += (localType == LONG || localType == DOUBLE) ? 2 : 1;
1363       if (localType == TOP) {
1364         numTrailingTop++;
1365       } else {
1366         numLocal += numTrailingTop + 1;
1367         numTrailingTop = 0;
1368       }
1369     }
1370     // Compute the stack size, ignoring TOP types that are just after a LONG or a DOUBLE.
1371     int[] stackTypes = inputStack;
1372     int numStack = 0;
1373     i = 0;
1374     while (i < stackTypes.length) {
1375       int stackType = stackTypes[i];
1376       i += (stackType == LONG || stackType == DOUBLE) ? 2 : 1;
1377       numStack++;
1378     }
1379     // Visit the frame and its content.
1380     int frameIndex = methodWriter.visitFrameStart(owner.bytecodeOffset, numLocal, numStack);
1381     i = 0;
1382     while (numLocal-- > 0) {
1383       int localType = localTypes[i];
1384       i += (localType == LONG || localType == DOUBLE) ? 2 : 1;
1385       methodWriter.visitAbstractType(frameIndex++, localType);
1386     }
1387     i = 0;
1388     while (numStack-- > 0) {
1389       int stackType = stackTypes[i];
1390       i += (stackType == LONG || stackType == DOUBLE) ? 2 : 1;
1391       methodWriter.visitAbstractType(frameIndex++, stackType);
1392     }
1393     methodWriter.visitFrameEnd();
1394   }
1395 
1396   /**
1397    * Put the given abstract type in the given ByteVector, using the JVMS verification_type_info
1398    * format used in StackMapTable attributes.
1399    *
1400    * @param symbolTable the type table to use to lookup and store type {@link Symbol}.
1401    * @param abstractType an abstract type, restricted to {@link Frame#CONSTANT_KIND}, {@link
1402    *     Frame#REFERENCE_KIND} or {@link Frame#UNINITIALIZED_KIND} types.
1403    * @param output where the abstract type must be put.
1404    * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.4">JVMS
1405    *     4.7.4</a>
1406    */
putAbstractType( final SymbolTable symbolTable, final int abstractType, final ByteVector output)1407   static void putAbstractType(
1408       final SymbolTable symbolTable, final int abstractType, final ByteVector output) {
1409     int arrayDimensions = (abstractType & Frame.DIM_MASK) >> DIM_SHIFT;
1410     if (arrayDimensions == 0) {
1411       int typeValue = abstractType & VALUE_MASK;
1412       switch (abstractType & KIND_MASK) {
1413         case CONSTANT_KIND:
1414           output.putByte(typeValue);
1415           break;
1416         case REFERENCE_KIND:
1417           output
1418               .putByte(ITEM_OBJECT)
1419               .putShort(symbolTable.addConstantClass(symbolTable.getType(typeValue).value).index);
1420           break;
1421         case UNINITIALIZED_KIND:
1422           output.putByte(ITEM_UNINITIALIZED).putShort((int) symbolTable.getType(typeValue).data);
1423           break;
1424         default:
1425           throw new AssertionError();
1426       }
1427     } else {
1428       // Case of an array type, we need to build its descriptor first.
1429       StringBuilder typeDescriptor = new StringBuilder();
1430       while (arrayDimensions-- > 0) {
1431         typeDescriptor.append('[');
1432       }
1433       if ((abstractType & KIND_MASK) == REFERENCE_KIND) {
1434         typeDescriptor
1435             .append('L')
1436             .append(symbolTable.getType(abstractType & VALUE_MASK).value)
1437             .append(';');
1438       } else {
1439         switch (abstractType & VALUE_MASK) {
1440           case Frame.ITEM_ASM_BOOLEAN:
1441             typeDescriptor.append('Z');
1442             break;
1443           case Frame.ITEM_ASM_BYTE:
1444             typeDescriptor.append('B');
1445             break;
1446           case Frame.ITEM_ASM_CHAR:
1447             typeDescriptor.append('C');
1448             break;
1449           case Frame.ITEM_ASM_SHORT:
1450             typeDescriptor.append('S');
1451             break;
1452           case Frame.ITEM_INTEGER:
1453             typeDescriptor.append('I');
1454             break;
1455           case Frame.ITEM_FLOAT:
1456             typeDescriptor.append('F');
1457             break;
1458           case Frame.ITEM_LONG:
1459             typeDescriptor.append('J');
1460             break;
1461           case Frame.ITEM_DOUBLE:
1462             typeDescriptor.append('D');
1463             break;
1464           default:
1465             throw new AssertionError();
1466         }
1467       }
1468       output
1469           .putByte(ITEM_OBJECT)
1470           .putShort(symbolTable.addConstantClass(typeDescriptor.toString()).index);
1471     }
1472   }
1473 }
1474