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