• 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  * A position in the bytecode of a method. Labels are used for jump, goto, and switch instructions,
32  * and for try catch blocks. A label designates the <i>instruction</i> that is just after. Note
33  * however that there can be other elements between a label and the instruction it designates (such
34  * as other labels, stack map frames, line numbers, etc.).
35  *
36  * @author Eric Bruneton
37  */
38 public class Label {
39 
40   /**
41    * A flag indicating that a label is only used for debug attributes. Such a label is not the start
42    * of a basic block, the target of a jump instruction, or an exception handler. It can be safely
43    * ignored in control flow graph analysis algorithms (for optimization purposes).
44    */
45   static final int FLAG_DEBUG_ONLY = 1;
46 
47   /**
48    * A flag indicating that a label is the target of a jump instruction, or the start of an
49    * exception handler.
50    */
51   static final int FLAG_JUMP_TARGET = 2;
52 
53   /** A flag indicating that the bytecode offset of a label is known. */
54   static final int FLAG_RESOLVED = 4;
55 
56   /** A flag indicating that a label corresponds to a reachable basic block. */
57   static final int FLAG_REACHABLE = 8;
58 
59   /**
60    * A flag indicating that the basic block corresponding to a label ends with a subroutine call. By
61    * construction in {@link MethodWriter#visitJumpInsn}, labels with this flag set have at least two
62    * outgoing edges:
63    *
64    * <ul>
65    *   <li>the first one corresponds to the instruction that follows the jsr instruction in the
66    *       bytecode, i.e. where execution continues when it returns from the jsr call. This is a
67    *       virtual control flow edge, since execution never goes directly from the jsr to the next
68    *       instruction. Instead, it goes to the subroutine and eventually returns to the instruction
69    *       following the jsr. This virtual edge is used to compute the real outgoing edges of the
70    *       basic blocks ending with a ret instruction, in {@link #addSubroutineRetSuccessors}.
71    *   <li>the second one corresponds to the target of the jsr instruction,
72    * </ul>
73    */
74   static final int FLAG_SUBROUTINE_CALLER = 16;
75 
76   /**
77    * A flag indicating that the basic block corresponding to a label is the start of a subroutine.
78    */
79   static final int FLAG_SUBROUTINE_START = 32;
80 
81   /** A flag indicating that the basic block corresponding to a label is the end of a subroutine. */
82   static final int FLAG_SUBROUTINE_END = 64;
83 
84   /** A flag indicating that this label has at least one associated line number. */
85   static final int FLAG_LINE_NUMBER = 128;
86 
87   /**
88    * The number of elements to add to the {@link #otherLineNumbers} array when it needs to be
89    * resized to store a new source line number.
90    */
91   static final int LINE_NUMBERS_CAPACITY_INCREMENT = 4;
92 
93   /**
94    * The number of elements to add to the {@link #forwardReferences} array when it needs to be
95    * resized to store a new forward reference.
96    */
97   static final int FORWARD_REFERENCES_CAPACITY_INCREMENT = 6;
98 
99   /**
100    * The bit mask to extract the type of a forward reference to this label. The extracted type is
101    * either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link #FORWARD_REFERENCE_TYPE_WIDE}.
102    *
103    * @see #forwardReferences
104    */
105   static final int FORWARD_REFERENCE_TYPE_MASK = 0xF0000000;
106 
107   /**
108    * The type of forward references stored with two bytes in the bytecode. This is the case, for
109    * instance, of a forward reference from an ifnull instruction.
110    */
111   static final int FORWARD_REFERENCE_TYPE_SHORT = 0x10000000;
112 
113   /**
114    * The type of forward references stored in four bytes in the bytecode. This is the case, for
115    * instance, of a forward reference from a lookupswitch instruction.
116    */
117   static final int FORWARD_REFERENCE_TYPE_WIDE = 0x20000000;
118 
119   /**
120    * The type of forward references stored in two bytes in the <i>stack map table</i>. This is the
121    * case of the labels of {@link Frame#ITEM_UNINITIALIZED} stack map frame elements, when the NEW
122    * instruction is after the &lt;init&gt; constructor call (in bytecode offset order).
123    */
124   static final int FORWARD_REFERENCE_TYPE_STACK_MAP = 0x30000000;
125 
126   /**
127    * The bit mask to extract the 'handle' of a forward reference to this label. The extracted handle
128    * is the bytecode offset where the forward reference value is stored (using either 2 or 4 bytes,
129    * as indicated by the {@link #FORWARD_REFERENCE_TYPE_MASK}).
130    *
131    * @see #forwardReferences
132    */
133   static final int FORWARD_REFERENCE_HANDLE_MASK = 0x0FFFFFFF;
134 
135   /**
136    * A sentinel element used to indicate the end of a list of labels.
137    *
138    * @see #nextListElement
139    */
140   static final Label EMPTY_LIST = new Label();
141 
142   /**
143    * A user managed state associated with this label. Warning: this field is used by the ASM tree
144    * package. In order to use it with the ASM tree package you must override the getLabelNode method
145    * in MethodNode.
146    */
147   public Object info;
148 
149   /**
150    * The type and status of this label or its corresponding basic block. Must be zero or more of
151    * {@link #FLAG_DEBUG_ONLY}, {@link #FLAG_JUMP_TARGET}, {@link #FLAG_RESOLVED}, {@link
152    * #FLAG_REACHABLE}, {@link #FLAG_SUBROUTINE_CALLER}, {@link #FLAG_SUBROUTINE_START}, {@link
153    * #FLAG_SUBROUTINE_END}.
154    */
155   short flags;
156 
157   /**
158    * The source line number corresponding to this label, if {@link #FLAG_LINE_NUMBER} is set. If
159    * there are several source line numbers corresponding to this label, the first one is stored in
160    * this field, and the remaining ones are stored in {@link #otherLineNumbers}.
161    */
162   private short lineNumber;
163 
164   /**
165    * The source line numbers corresponding to this label, in addition to {@link #lineNumber}, or
166    * null. The first element of this array is the number n of source line numbers it contains, which
167    * are stored between indices 1 and n (inclusive).
168    */
169   private int[] otherLineNumbers;
170 
171   /**
172    * The offset of this label in the bytecode of its method, in bytes. This value is set if and only
173    * if the {@link #FLAG_RESOLVED} flag is set.
174    */
175   int bytecodeOffset;
176 
177   /**
178    * The forward references to this label. The first element is the number of forward references,
179    * times 2 (this corresponds to the index of the last element actually used in this array). Then,
180    * each forward reference is described with two consecutive integers noted
181    * 'sourceInsnBytecodeOffset' and 'reference':
182    *
183    * <ul>
184    *   <li>'sourceInsnBytecodeOffset' is the bytecode offset of the instruction that contains the
185    *       forward reference,
186    *   <li>'reference' contains the type and the offset in the bytecode where the forward reference
187    *       value must be stored, which can be extracted with {@link #FORWARD_REFERENCE_TYPE_MASK}
188    *       and {@link #FORWARD_REFERENCE_HANDLE_MASK}.
189    * </ul>
190    *
191    * <p>For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is
192    * equal to x, and 'reference' is of type {@link #FORWARD_REFERENCE_TYPE_SHORT} with value x + 1
193    * (because the ifnull instruction uses a 2 bytes bytecode offset operand stored one byte after
194    * the start of the instruction itself). For the default case of a lookupswitch instruction at
195    * bytecode offset x, 'sourceInsnBytecodeOffset' is equal to x, and 'reference' is of type {@link
196    * #FORWARD_REFERENCE_TYPE_WIDE} with value between x + 1 and x + 4 (because the lookupswitch
197    * instruction uses a 4 bytes bytecode offset operand stored one to four bytes after the start of
198    * the instruction itself).
199    */
200   private int[] forwardReferences;
201 
202   // -----------------------------------------------------------------------------------------------
203 
204   // Fields for the control flow and data flow graph analysis algorithms (used to compute the
205   // maximum stack size or the stack map frames). A control flow graph contains one node per "basic
206   // block", and one edge per "jump" from one basic block to another. Each node (i.e., each basic
207   // block) is represented with the Label object that corresponds to the first instruction of this
208   // basic block. Each node also stores the list of its successors in the graph, as a linked list of
209   // Edge objects.
210   //
211   // The control flow analysis algorithms used to compute the maximum stack size or the stack map
212   // frames are similar and use two steps. The first step, during the visit of each instruction,
213   // builds information about the state of the local variables and the operand stack at the end of
214   // each basic block, called the "output frame", <i>relatively</i> to the frame state at the
215   // beginning of the basic block, which is called the "input frame", and which is <i>unknown</i>
216   // during this step. The second step, in {@link MethodWriter#computeAllFrames} and {@link
217   // MethodWriter#computeMaxStackAndLocal}, is a fix point algorithm
218   // that computes information about the input frame of each basic block, from the input state of
219   // the first basic block (known from the method signature), and by the using the previously
220   // computed relative output frames.
221   //
222   // The algorithm used to compute the maximum stack size only computes the relative output and
223   // absolute input stack heights, while the algorithm used to compute stack map frames computes
224   // relative output frames and absolute input frames.
225 
226   /**
227    * The number of elements in the input stack of the basic block corresponding to this label. This
228    * field is computed in {@link MethodWriter#computeMaxStackAndLocal}.
229    */
230   short inputStackSize;
231 
232   /**
233    * The number of elements in the output stack, at the end of the basic block corresponding to this
234    * label. This field is only computed for basic blocks that end with a RET instruction.
235    */
236   short outputStackSize;
237 
238   /**
239    * The maximum height reached by the output stack, relatively to the top of the input stack, in
240    * the basic block corresponding to this label. This maximum is always positive or {@literal
241    * null}.
242    */
243   short outputStackMax;
244 
245   /**
246    * The id of the subroutine to which this basic block belongs, or 0. If the basic block belongs to
247    * several subroutines, this is the id of the "oldest" subroutine that contains it (with the
248    * convention that a subroutine calling another one is "older" than the callee). This field is
249    * computed in {@link MethodWriter#computeMaxStackAndLocal}, if the method contains JSR
250    * instructions.
251    */
252   short subroutineId;
253 
254   /**
255    * The input and output stack map frames of the basic block corresponding to this label. This
256    * field is only used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} or {@link
257    * MethodWriter#COMPUTE_INSERTED_FRAMES} option is used.
258    */
259   Frame frame;
260 
261   /**
262    * The successor of this label, in the order they are visited in {@link MethodVisitor#visitLabel}.
263    * This linked list does not include labels used for debug info only. If the {@link
264    * MethodWriter#COMPUTE_ALL_FRAMES} or {@link MethodWriter#COMPUTE_INSERTED_FRAMES} option is used
265    * then it does not contain either successive labels that denote the same bytecode offset (in this
266    * case only the first label appears in this list).
267    */
268   Label nextBasicBlock;
269 
270   /**
271    * The outgoing edges of the basic block corresponding to this label, in the control flow graph of
272    * its method. These edges are stored in a linked list of {@link Edge} objects, linked to each
273    * other by their {@link Edge#nextEdge} field.
274    */
275   Edge outgoingEdges;
276 
277   /**
278    * The next element in the list of labels to which this label belongs, or {@literal null} if it
279    * does not belong to any list. All lists of labels must end with the {@link #EMPTY_LIST}
280    * sentinel, in order to ensure that this field is null if and only if this label does not belong
281    * to a list of labels. Note that there can be several lists of labels at the same time, but that
282    * a label can belong to at most one list at a time (unless some lists share a common tail, but
283    * this is not used in practice).
284    *
285    * <p>List of labels are used in {@link MethodWriter#computeAllFrames} and {@link
286    * MethodWriter#computeMaxStackAndLocal} to compute stack map frames and the maximum stack size,
287    * respectively, as well as in {@link #markSubroutine} and {@link #addSubroutineRetSuccessors} to
288    * compute the basic blocks belonging to subroutines and their outgoing edges. Outside of these
289    * methods, this field should be null (this property is a precondition and a postcondition of
290    * these methods).
291    */
292   Label nextListElement;
293 
294   // -----------------------------------------------------------------------------------------------
295   // Constructor and accessors
296   // -----------------------------------------------------------------------------------------------
297 
298   /** Constructs a new label. */
Label()299   public Label() {
300     // Nothing to do.
301   }
302 
303   /**
304    * Returns the bytecode offset corresponding to this label. This offset is computed from the start
305    * of the method's bytecode. <i>This method is intended for {@link Attribute} sub classes, and is
306    * normally not needed by class generators or adapters.</i>
307    *
308    * @return the bytecode offset corresponding to this label.
309    * @throws IllegalStateException if this label is not resolved yet.
310    */
getOffset()311   public int getOffset() {
312     if ((flags & FLAG_RESOLVED) == 0) {
313       throw new IllegalStateException("Label offset position has not been resolved yet");
314     }
315     return bytecodeOffset;
316   }
317 
318   /**
319    * Returns the "canonical" {@link Label} instance corresponding to this label's bytecode offset,
320    * if known, otherwise the label itself. The canonical instance is the first label (in the order
321    * of their visit by {@link MethodVisitor#visitLabel}) corresponding to this bytecode offset. It
322    * cannot be known for labels which have not been visited yet.
323    *
324    * <p><i>This method should only be used when the {@link MethodWriter#COMPUTE_ALL_FRAMES} option
325    * is used.</i>
326    *
327    * @return the label itself if {@link #frame} is null, otherwise the Label's frame owner. This
328    *     corresponds to the "canonical" label instance described above thanks to the way the label
329    *     frame is set in {@link MethodWriter#visitLabel}.
330    */
getCanonicalInstance()331   final Label getCanonicalInstance() {
332     return frame == null ? this : frame.owner;
333   }
334 
335   // -----------------------------------------------------------------------------------------------
336   // Methods to manage line numbers
337   // -----------------------------------------------------------------------------------------------
338 
339   /**
340    * Adds a source line number corresponding to this label.
341    *
342    * @param lineNumber a source line number (which should be strictly positive).
343    */
addLineNumber(final int lineNumber)344   final void addLineNumber(final int lineNumber) {
345     if ((flags & FLAG_LINE_NUMBER) == 0) {
346       flags |= FLAG_LINE_NUMBER;
347       this.lineNumber = (short) lineNumber;
348     } else {
349       if (otherLineNumbers == null) {
350         otherLineNumbers = new int[LINE_NUMBERS_CAPACITY_INCREMENT];
351       }
352       int otherLineNumberIndex = ++otherLineNumbers[0];
353       if (otherLineNumberIndex >= otherLineNumbers.length) {
354         int[] newLineNumbers = new int[otherLineNumbers.length + LINE_NUMBERS_CAPACITY_INCREMENT];
355         System.arraycopy(otherLineNumbers, 0, newLineNumbers, 0, otherLineNumbers.length);
356         otherLineNumbers = newLineNumbers;
357       }
358       otherLineNumbers[otherLineNumberIndex] = lineNumber;
359     }
360   }
361 
362   /**
363    * Makes the given visitor visit this label and its source line numbers, if applicable.
364    *
365    * @param methodVisitor a method visitor.
366    * @param visitLineNumbers whether to visit of the label's source line numbers, if any.
367    */
accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers)368   final void accept(final MethodVisitor methodVisitor, final boolean visitLineNumbers) {
369     methodVisitor.visitLabel(this);
370     if (visitLineNumbers && (flags & FLAG_LINE_NUMBER) != 0) {
371       methodVisitor.visitLineNumber(lineNumber & 0xFFFF, this);
372       if (otherLineNumbers != null) {
373         for (int i = 1; i <= otherLineNumbers[0]; ++i) {
374           methodVisitor.visitLineNumber(otherLineNumbers[i], this);
375         }
376       }
377     }
378   }
379 
380   // -----------------------------------------------------------------------------------------------
381   // Methods to compute offsets and to manage forward references
382   // -----------------------------------------------------------------------------------------------
383 
384   /**
385    * Puts a reference to this label in the bytecode of a method. If the bytecode offset of the label
386    * is known, the relative bytecode offset between the label and the instruction referencing it is
387    * computed and written directly. Otherwise, a null relative offset is written and a new forward
388    * reference is declared for this label.
389    *
390    * @param code the bytecode of the method. This is where the reference is appended.
391    * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the
392    *     reference to be appended.
393    * @param wideReference whether the reference must be stored in 4 bytes (instead of 2 bytes).
394    */
put( final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference)395   final void put(
396       final ByteVector code, final int sourceInsnBytecodeOffset, final boolean wideReference) {
397     if ((flags & FLAG_RESOLVED) == 0) {
398       if (wideReference) {
399         addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_WIDE, code.length);
400         code.putInt(-1);
401       } else {
402         addForwardReference(sourceInsnBytecodeOffset, FORWARD_REFERENCE_TYPE_SHORT, code.length);
403         code.putShort(-1);
404       }
405     } else {
406       if (wideReference) {
407         code.putInt(bytecodeOffset - sourceInsnBytecodeOffset);
408       } else {
409         code.putShort(bytecodeOffset - sourceInsnBytecodeOffset);
410       }
411     }
412   }
413 
414   /**
415    * Puts a reference to this label in the <i>stack map table</i> of a method. If the bytecode
416    * offset of the label is known, it is written directly. Otherwise, a null relative offset is
417    * written and a new forward reference is declared for this label.
418    *
419    * @param stackMapTableEntries the stack map table where the label offset must be added.
420    */
put(final ByteVector stackMapTableEntries)421   final void put(final ByteVector stackMapTableEntries) {
422     if ((flags & FLAG_RESOLVED) == 0) {
423       addForwardReference(0, FORWARD_REFERENCE_TYPE_STACK_MAP, stackMapTableEntries.length);
424     }
425     stackMapTableEntries.putShort(bytecodeOffset);
426   }
427 
428   /**
429    * Adds a forward reference to this label. This method must be called only for a true forward
430    * reference, i.e. only if this label is not resolved yet. For backward references, the relative
431    * bytecode offset of the reference can be, and must be, computed and stored directly.
432    *
433    * @param sourceInsnBytecodeOffset the bytecode offset of the instruction that contains the
434    *     reference stored at referenceHandle.
435    * @param referenceType either {@link #FORWARD_REFERENCE_TYPE_SHORT} or {@link
436    *     #FORWARD_REFERENCE_TYPE_WIDE}.
437    * @param referenceHandle the offset in the bytecode where the forward reference value must be
438    *     stored.
439    */
addForwardReference( final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle)440   private void addForwardReference(
441       final int sourceInsnBytecodeOffset, final int referenceType, final int referenceHandle) {
442     if (forwardReferences == null) {
443       forwardReferences = new int[FORWARD_REFERENCES_CAPACITY_INCREMENT];
444     }
445     int lastElementIndex = forwardReferences[0];
446     if (lastElementIndex + 2 >= forwardReferences.length) {
447       int[] newValues = new int[forwardReferences.length + FORWARD_REFERENCES_CAPACITY_INCREMENT];
448       System.arraycopy(forwardReferences, 0, newValues, 0, forwardReferences.length);
449       forwardReferences = newValues;
450     }
451     forwardReferences[++lastElementIndex] = sourceInsnBytecodeOffset;
452     forwardReferences[++lastElementIndex] = referenceType | referenceHandle;
453     forwardReferences[0] = lastElementIndex;
454   }
455 
456   /**
457    * Sets the bytecode offset of this label to the given value and resolves the forward references
458    * to this label, if any. This method must be called when this label is added to the bytecode of
459    * the method, i.e. when its bytecode offset becomes known. This method fills in the blanks that
460    * where left in the bytecode (and optionally in the stack map table) by each forward reference
461    * previously added to this label.
462    *
463    * @param code the bytecode of the method.
464    * @param stackMapTableEntries the 'entries' array of the StackMapTable code attribute of the
465    *     method. Maybe {@literal null}.
466    * @param bytecodeOffset the bytecode offset of this label.
467    * @return {@literal true} if a blank that was left for this label was too small to store the
468    *     offset. In such a case the corresponding jump instruction is replaced with an equivalent
469    *     ASM specific instruction using an unsigned two bytes offset. These ASM specific
470    *     instructions are later replaced with standard bytecode instructions with wider offsets (4
471    *     bytes instead of 2), in ClassReader.
472    */
resolve( final byte[] code, final ByteVector stackMapTableEntries, final int bytecodeOffset)473   final boolean resolve(
474       final byte[] code, final ByteVector stackMapTableEntries, final int bytecodeOffset) {
475     this.flags |= FLAG_RESOLVED;
476     this.bytecodeOffset = bytecodeOffset;
477     if (forwardReferences == null) {
478       return false;
479     }
480     boolean hasAsmInstructions = false;
481     for (int i = forwardReferences[0]; i > 0; i -= 2) {
482       final int sourceInsnBytecodeOffset = forwardReferences[i - 1];
483       final int reference = forwardReferences[i];
484       final int relativeOffset = bytecodeOffset - sourceInsnBytecodeOffset;
485       int handle = reference & FORWARD_REFERENCE_HANDLE_MASK;
486       if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_SHORT) {
487         if (relativeOffset < Short.MIN_VALUE || relativeOffset > Short.MAX_VALUE) {
488           // Change the opcode of the jump instruction, in order to be able to find it later in
489           // ClassReader. These ASM specific opcodes are similar to jump instruction opcodes, except
490           // that the 2 bytes offset is unsigned (and can therefore represent values from 0 to
491           // 65535, which is sufficient since the size of a method is limited to 65535 bytes).
492           int opcode = code[sourceInsnBytecodeOffset] & 0xFF;
493           if (opcode < Opcodes.IFNULL) {
494             // Change IFEQ ... JSR to ASM_IFEQ ... ASM_JSR.
495             code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_OPCODE_DELTA);
496           } else {
497             // Change IFNULL and IFNONNULL to ASM_IFNULL and ASM_IFNONNULL.
498             code[sourceInsnBytecodeOffset] = (byte) (opcode + Constants.ASM_IFNULL_OPCODE_DELTA);
499           }
500           hasAsmInstructions = true;
501         }
502         code[handle++] = (byte) (relativeOffset >>> 8);
503         code[handle] = (byte) relativeOffset;
504       } else if ((reference & FORWARD_REFERENCE_TYPE_MASK) == FORWARD_REFERENCE_TYPE_WIDE) {
505         code[handle++] = (byte) (relativeOffset >>> 24);
506         code[handle++] = (byte) (relativeOffset >>> 16);
507         code[handle++] = (byte) (relativeOffset >>> 8);
508         code[handle] = (byte) relativeOffset;
509       } else {
510         stackMapTableEntries.data[handle++] = (byte) (bytecodeOffset >>> 8);
511         stackMapTableEntries.data[handle] = (byte) bytecodeOffset;
512       }
513     }
514     return hasAsmInstructions;
515   }
516 
517   // -----------------------------------------------------------------------------------------------
518   // Methods related to subroutines
519   // -----------------------------------------------------------------------------------------------
520 
521   /**
522    * Finds the basic blocks that belong to the subroutine starting with the basic block
523    * corresponding to this label, and marks these blocks as belonging to this subroutine. This
524    * method follows the control flow graph to find all the blocks that are reachable from the
525    * current basic block WITHOUT following any jsr target.
526    *
527    * <p>Note: a precondition and postcondition of this method is that all labels must have a null
528    * {@link #nextListElement}.
529    *
530    * @param subroutineId the id of the subroutine starting with the basic block corresponding to
531    *     this label.
532    */
markSubroutine(final short subroutineId)533   final void markSubroutine(final short subroutineId) {
534     // Data flow algorithm: put this basic block in a list of blocks to process (which are blocks
535     // belonging to subroutine subroutineId) and, while there are blocks to process, remove one from
536     // the list, mark it as belonging to the subroutine, and add its successor basic blocks in the
537     // control flow graph to the list of blocks to process (if not already done).
538     Label listOfBlocksToProcess = this;
539     listOfBlocksToProcess.nextListElement = EMPTY_LIST;
540     while (listOfBlocksToProcess != EMPTY_LIST) {
541       // Remove a basic block from the list of blocks to process.
542       Label basicBlock = listOfBlocksToProcess;
543       listOfBlocksToProcess = listOfBlocksToProcess.nextListElement;
544       basicBlock.nextListElement = null;
545 
546       // If it is not already marked as belonging to a subroutine, mark it as belonging to
547       // subroutineId and add its successors to the list of blocks to process (unless already done).
548       if (basicBlock.subroutineId == 0) {
549         basicBlock.subroutineId = subroutineId;
550         listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess);
551       }
552     }
553   }
554 
555   /**
556    * Finds the basic blocks that end a subroutine starting with the basic block corresponding to
557    * this label and, for each one of them, adds an outgoing edge to the basic block following the
558    * given subroutine call. In other words, completes the control flow graph by adding the edges
559    * corresponding to the return from this subroutine, when called from the given caller basic
560    * block.
561    *
562    * <p>Note: a precondition and postcondition of this method is that all labels must have a null
563    * {@link #nextListElement}.
564    *
565    * @param subroutineCaller a basic block that ends with a jsr to the basic block corresponding to
566    *     this label. This label is supposed to correspond to the start of a subroutine.
567    */
addSubroutineRetSuccessors(final Label subroutineCaller)568   final void addSubroutineRetSuccessors(final Label subroutineCaller) {
569     // Data flow algorithm: put this basic block in a list blocks to process (which are blocks
570     // belonging to a subroutine starting with this label) and, while there are blocks to process,
571     // remove one from the list, put it in a list of blocks that have been processed, add a return
572     // edge to the successor of subroutineCaller if applicable, and add its successor basic blocks
573     // in the control flow graph to the list of blocks to process (if not already done).
574     Label listOfProcessedBlocks = EMPTY_LIST;
575     Label listOfBlocksToProcess = this;
576     listOfBlocksToProcess.nextListElement = EMPTY_LIST;
577     while (listOfBlocksToProcess != EMPTY_LIST) {
578       // Move a basic block from the list of blocks to process to the list of processed blocks.
579       Label basicBlock = listOfBlocksToProcess;
580       listOfBlocksToProcess = basicBlock.nextListElement;
581       basicBlock.nextListElement = listOfProcessedBlocks;
582       listOfProcessedBlocks = basicBlock;
583 
584       // Add an edge from this block to the successor of the caller basic block, if this block is
585       // the end of a subroutine and if this block and subroutineCaller do not belong to the same
586       // subroutine.
587       if ((basicBlock.flags & FLAG_SUBROUTINE_END) != 0
588           && basicBlock.subroutineId != subroutineCaller.subroutineId) {
589         basicBlock.outgoingEdges =
590             new Edge(
591                 basicBlock.outputStackSize,
592                 // By construction, the first outgoing edge of a basic block that ends with a jsr
593                 // instruction leads to the jsr continuation block, i.e. where execution continues
594                 // when ret is called (see {@link #FLAG_SUBROUTINE_CALLER}).
595                 subroutineCaller.outgoingEdges.successor,
596                 basicBlock.outgoingEdges);
597       }
598       // Add its successors to the list of blocks to process. Note that {@link #pushSuccessors} does
599       // not push basic blocks which are already in a list. Here this means either in the list of
600       // blocks to process, or in the list of already processed blocks. This second list is
601       // important to make sure we don't reprocess an already processed block.
602       listOfBlocksToProcess = basicBlock.pushSuccessors(listOfBlocksToProcess);
603     }
604     // Reset the {@link #nextListElement} of all the basic blocks that have been processed to null,
605     // so that this method can be called again with a different subroutine or subroutine caller.
606     while (listOfProcessedBlocks != EMPTY_LIST) {
607       Label newListOfProcessedBlocks = listOfProcessedBlocks.nextListElement;
608       listOfProcessedBlocks.nextListElement = null;
609       listOfProcessedBlocks = newListOfProcessedBlocks;
610     }
611   }
612 
613   /**
614    * Adds the successors of this label in the method's control flow graph (except those
615    * corresponding to a jsr target, and those already in a list of labels) to the given list of
616    * blocks to process, and returns the new list.
617    *
618    * @param listOfLabelsToProcess a list of basic blocks to process, linked together with their
619    *     {@link #nextListElement} field.
620    * @return the new list of blocks to process.
621    */
pushSuccessors(final Label listOfLabelsToProcess)622   private Label pushSuccessors(final Label listOfLabelsToProcess) {
623     Label newListOfLabelsToProcess = listOfLabelsToProcess;
624     Edge outgoingEdge = outgoingEdges;
625     while (outgoingEdge != null) {
626       // By construction, the second outgoing edge of a basic block that ends with a jsr instruction
627       // leads to the jsr target (see {@link #FLAG_SUBROUTINE_CALLER}).
628       boolean isJsrTarget =
629           (flags & Label.FLAG_SUBROUTINE_CALLER) != 0 && outgoingEdge == outgoingEdges.nextEdge;
630       if (!isJsrTarget && outgoingEdge.successor.nextListElement == null) {
631         // Add this successor to the list of blocks to process, if it does not already belong to a
632         // list of labels.
633         outgoingEdge.successor.nextListElement = newListOfLabelsToProcess;
634         newListOfLabelsToProcess = outgoingEdge.successor;
635       }
636       outgoingEdge = outgoingEdge.nextEdge;
637     }
638     return newListOfLabelsToProcess;
639   }
640 
641   // -----------------------------------------------------------------------------------------------
642   // Overridden Object methods
643   // -----------------------------------------------------------------------------------------------
644 
645   /**
646    * Returns a string representation of this label.
647    *
648    * @return a string representation of this label.
649    */
650   @Override
toString()651   public String toString() {
652     return "L" + System.identityHashCode(this);
653   }
654 }
655