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