Label.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*** 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ASM: a very small and fast Java bytecode manipulation framework 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2000-2007 INRIA, France Telecom 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * modification, are permitted provided that the following conditions 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are met: 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * documentation and/or other materials provided with the distribution. 14a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) * 3. Neither the name of the copyright holders nor the names of its 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 18bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * THE POSSIBILITY OF SUCH DAMAGE. 29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 30a3f7b4e666c476898878fa745f637129375cd889Ben Murdochpackage org.mockito.asm; 31a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/** 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * A label represents a position in the bytecode of a method. Labels are used 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for jump, goto, and switch instructions, and for try catch blocks. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @author Eric Bruneton 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochpublic class Label { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if this label is only used for debug attributes. Such a label 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * is not the start of a basic block, the target of a jump instruction, or 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * an exception handler. It can be safely ignored in control flow graph 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * analysis algorithms (for optimization purposes). 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static final int DEBUG = 1; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if the position of this label is known. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final int RESOLVED = 2; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if this label has been updated, after instruction resizing. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final int RESIZED = 4; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if this basic block has been pushed in the basic block stack. 60a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * See {@link MethodWriter#visitMaxs visitMaxs}. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static final int PUSHED = 8; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if this label is the target of a jump instruction, or the start 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of an exception handler. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final int TARGET = 16; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if a stack map frame must be stored for this label. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static final int STORE = 32; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Indicates if this label corresponds to a reachable basic block. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static final int REACHABLE = 64; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Indicates if this basic block ends with a JSR instruction. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static final int JSR = 128; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Indicates if this basic block ends with a RET instruction. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static final int RET = 256; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Indicates if this basic block is the start of a subroutine. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static final int SUBROUTINE = 512; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Indicates if this subroutine basic block has been visited. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static final int VISITED = 1024; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Field used to associate user information to a label. Warning: this field 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * is used by the ASM tree package. In order to use it with the ASM tree 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * package you must override the {@link 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * org.mockito.asm.tree.MethodNode#getLabelNode} method. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public Object info; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Flags that indicate the status of this label. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #DEBUG 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #RESOLVED 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #RESIZED 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #PUSHED 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #TARGET 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #STORE 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #REACHABLE 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see #JSR 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @see #RET 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The line number corresponding to this label, if known. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int line; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The position of this label in the code, if known. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int position; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Number of forward references to this label, times two. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private int referenceCount; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Informations about forward references. Each forward reference is 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * described by two consecutive integers in this array: the first one is the 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * position of the first byte of the bytecode instruction that contains the 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * forward reference, while the second is the position of the first byte of 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the forward reference itself. In fact the sign of the first integer 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * indicates if this reference uses 2 or 4 bytes, and its absolute value 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * gives the position of the bytecode instruction. This array is also used 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as a bitset to store the subroutines to which a basic block belongs. This 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * information is needed in {@linked MethodWriter#visitMaxs}, after all 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * forward references have been resolved. Hence the same array can be used 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * for both purposes without problems. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private int[] srcAndRefPositions; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ------------------------------------------------------------------------ 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Fields for the control flow and data flow graph analysis algorithms (used 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to compute the maximum stack size or the stack map frames). A control 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * flow graph contains one node per "basic block", and one edge per "jump" 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * from one basic block to another. Each node (i.e., each basic block) is 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * represented by the Label object that corresponds to the first instruction 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * of this basic block. Each node also stores the list of its successors in 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the graph, as a linked list of Edge objects. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The control flow analysis algorithms used to compute the maximum stack 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * size or the stack map frames are similar and use two steps. The first 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * step, during the visit of each instruction, builds information about the 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * state of the local variables and the operand stack at the end of each 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * basic block, called the "output frame", <i>relatively</i> to the frame 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * state at the beginning of the basic block, which is called the "input 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * frame", and which is <i>unknown</i> during this step. The second step, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * computes information about the input frame of each basic block, from the 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * input state of the first basic block (known from the method signature), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and by the using the previously computed relative output frames. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The algorithm used to compute the maximum stack size only computes the 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * relative output and absolute input stack heights, while the algorithm 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used to compute stack map frames computes relative output frames and 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * absolute input frames. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Start of the output stack relatively to the input stack. The exact 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * semantics of this field depends on the algorithm that is used. 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When only the maximum stack size is computed, this field is the number of 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * elements in the input stack. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When the stack map frames are completely computed, this field is the 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * offset of the first output stack element relatively to the top of the 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * input stack. This offset is always negative or null. A null offset means 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that the output stack must be appended to the input stack. A -n offset 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * means that the first n output stack elements must replace the top n input 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * stack elements, and that the other elements must be appended to the input 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * stack. 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int inputStackTop; 1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /** 2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Maximum height reached by the output stack, relatively to the top of the 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * input stack. This maximum is always positive or null. 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int outputStackMax; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Information about the input and output stack map frames of this basic 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * option is used. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Frame frame; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The successor of this label, in the order they are visited. This linked 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * list does not include labels used for debug info only. If 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * does not contain successive labels that denote the same bytecode position 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (in this case only the first label appears in this list). 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Label successor; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The successors of this node in the control flow graph. These successors 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are stored in a linked list of {@link Edge Edge} objects, linked to each 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * other by their {@link Edge#next} field. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Edge successors; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The next basic block in the basic block stack. This stack is used in the 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * main loop of the fix point algorithm used in the second step of the 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * control flow analysis algorithms. 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see MethodWriter#visitMaxs 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Label next; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ------------------------------------------------------------------------ 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Constructor 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ------------------------------------------------------------------------ 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Constructs a new label. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public Label() { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ------------------------------------------------------------------------ 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Methods to compute offsets and to manage forward references 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ------------------------------------------------------------------------ 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the offset corresponding to this label. This offset is computed 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from the start of the method's bytecode. <i>This method is intended for 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * {@link Attribute} sub classes, and is normally not needed by class 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * generators or adapters.</i> 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @return the offset corresponding to this label. 2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @throws IllegalStateException if this label is not resolved yet. 2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */ 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public int getOffset() { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & RESOLVED) == 0) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new IllegalStateException("Label offset position has not been resolved yet"); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return position; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Puts a reference to this label in the bytecode of a method. If the 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * position of the label is known, the offset is computed and written 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * directly. Otherwise, a null offset is written and a new forward reference 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is declared for this label. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param owner the code writer that calls this method. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param out the bytecode of the method. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param source the position of first byte of the bytecode instruction that 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contains this label. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param wideOffset <tt>true</tt> if the reference must be stored in 4 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * bytes, or <tt>false</tt> if it must be stored with 2 bytes. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @throws IllegalArgumentException if this label has not been created by 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * the given code writer. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void put( 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) final MethodWriter owner, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final ByteVector out, 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch final int source, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final boolean wideOffset) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & RESOLVED) == 0) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wideOffset) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addReference(-1 - source, out.length); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.putInt(-1); 292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch addReference(source, out.length); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.putShort(-1); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wideOffset) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.putInt(position - source); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out.putShort(position - source); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adds a forward reference to this label. This method must be called only 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * for a true forward reference, i.e. only if this label is not resolved 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * yet. For backward references, the offset of the reference can be, and 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * must be, computed and stored directly. 310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param sourcePosition the position of the referencing instruction. This 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * position will be used to compute the offset of this forward 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * reference. 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param referencePosition the position where the offset for this forward 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * reference must be stored. 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private void addReference( 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final int sourcePosition, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final int referencePosition) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (srcAndRefPositions == null) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcAndRefPositions = new int[6]; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (referenceCount >= srcAndRefPositions.length) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int[] a = new int[srcAndRefPositions.length + 6]; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) System.arraycopy(srcAndRefPositions, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) a, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcAndRefPositions.length); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcAndRefPositions = a; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcAndRefPositions[referenceCount++] = sourcePosition; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcAndRefPositions[referenceCount++] = referencePosition; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Resolves all forward references to this label. This method must be called 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * when this label is added to the bytecode of the method, i.e. when its 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * position becomes known. This method fills in the blanks that where left 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the bytecode by each forward reference previously added to this label. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param owner the code writer that calls this method. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param position the position of this label in the bytecode. 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param data the bytecode of the method. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return <tt>true</tt> if a blank that was left for this label was to 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * small to store the offset. In such a case the corresponding jump 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instruction is replaced with a pseudo instruction (using unused 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * opcodes) using an unsigned two bytes offset. These pseudo 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instructions will need to be replaced with true instructions with 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * wider offsets (4 bytes instead of 2). This is done in 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * {@link MethodWriter#resizeInstructions}. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @throws IllegalArgumentException if this label has already been resolved, 3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * or if it has not been created by the given code writer. 3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */ 3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) boolean resolve( 3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) final MethodWriter owner, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final int position, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) final byte[] data) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean needUpdate = false; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.status |= RESOLVED; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.position = position; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) while (i < referenceCount) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source = srcAndRefPositions[i++]; 3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int reference = srcAndRefPositions[i++]; 3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int offset; 3697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (source >= 0) { 3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) offset = position - source; 3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { 3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) /* 3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * changes the opcode of the jump instruction, in order to 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * be able to find it later (see resizeInstructions in 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MethodWriter). These temporary opcodes are similar to 376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * jump instruction opcodes, except that the 2 bytes offset 3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * is unsigned (and can therefore represent values from 0 to 3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * 65535, which is sufficient since the size of a method is 3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * limited to 65535 bytes). 3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */ 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int opcode = data[reference - 1] & 0xFF; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opcode <= Opcodes.JSR) { 3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // changes IFEQ ... JSR to opcodes 202 to 217 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data[reference - 1] = (byte) (opcode + 49); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changes IFNULL and IFNONNULL to opcodes 218 and 219 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[reference - 1] = (byte) (opcode + 20); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needUpdate = true; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[reference++] = (byte) (offset >>> 8); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[reference] = (byte) offset; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset = position + source + 1; 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data[reference++] = (byte) (offset >>> 24); 396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data[reference++] = (byte) (offset >>> 16); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[reference++] = (byte) (offset >>> 8); 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data[reference] = (byte) offset; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return needUpdate; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the first label of the series to which this label belongs. For an 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * isolated label or for the first label in a series of successive labels, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this method returns the label itself. For other labels it returns the 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * first label of the series. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return the first label of the series to which this label belongs. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Label getFirst() { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !ClassReader.FRAMES || frame == null ? this : frame.owner; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ------------------------------------------------------------------------ 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Methods related to subroutines 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ------------------------------------------------------------------------ 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true is this basic block belongs to the given subroutine. 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param id a subroutine id. 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return true is this basic block belongs to the given subroutine. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean inSubroutine(final long id) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & Label.VISITED) != 0) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if this basic block and the given one belong to a common 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * subroutine. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param block another basic block. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return true if this basic block and the given one belong to a common 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * subroutine. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean inSameSubroutine(final Label block) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < srcAndRefPositions.length; ++i) { 4437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Marks this basic block as belonging to the given subroutine. 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param id a subroutine id. 454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * @param nbSubroutines the total number of subroutines in the method. 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void addToSubroutine(final long id, final int nbSubroutines) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & VISITED) == 0) { 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status |= VISITED; 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1]; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srcAndRefPositions[(int) (id >>> 32)] |= (int) id; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Finds the basic blocks that belong to a given subroutine, and marks these 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * blocks as belonging to this subroutine. This recursive method follows the 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * control flow graph to find all the blocks that are reachable from the 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * current block WITHOUT following any JSR target. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param JSR a JSR block that jumps to this subroutine. If this JSR is not 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * null it is added to the successor of the RET blocks found in the 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * subroutine. 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param id the id of this subroutine. 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param nbSubroutines the total number of subroutines in the method. 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) 47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) { 47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (JSR != null) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & VISITED) != 0) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status |= VISITED; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // adds JSR to the successors of this block, if it is a RET block 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & RET) != 0) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inSameSubroutine(JSR)) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Edge e = new Edge(); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.info = inputStackTop; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.successor = JSR.successors.successor; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.next = successors; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) successors = e; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if this block already belongs to subroutine 'id', returns 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inSubroutine(id)) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // marks this block as belonging to subroutine 'id' 499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch addToSubroutine(id, nbSubroutines); 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // calls this method recursively on each successor, except JSR targets 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Edge e = successors; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e != null) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if this block is a JSR block, then 'successors.next' leads 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the JSR target (see {@link #visitJumpInsn}) and must therefore 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not be followed 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((status & Label.JSR) == 0 || e != successors.next) { 5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch e.successor.visitSubroutine(JSR, id, nbSubroutines); 5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch e = e.next; 5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // ------------------------------------------------------------------------ 5157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Overriden Object methods 516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // ------------------------------------------------------------------------ 5177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch /** 5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Returns a string representation of this label. 5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 5217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * @return a string representation of this label. 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public String toString() { 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "L" + System.identityHashCode(this); 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)