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