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.commons; 60 61 import java.util.ArrayList; 62 import java.util.HashMap; 63 import java.util.List; 64 import java.util.Map; 65 66 import jdk.internal.org.objectweb.asm.Handle; 67 import jdk.internal.org.objectweb.asm.Label; 68 import jdk.internal.org.objectweb.asm.MethodVisitor; 69 import jdk.internal.org.objectweb.asm.Opcodes; 70 import jdk.internal.org.objectweb.asm.Type; 71 72 /** 73 * A {@link MethodVisitor} that keeps track of stack map frame changes between 74 * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This 75 * adapter must be used with the 76 * {@link jdk.internal.org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each visit<i>X</i> 77 * instruction delegates to the next visitor in the chain, if any, and then 78 * simulates the effect of this instruction on the stack map frame, represented 79 * by {@link #locals} and {@link #stack}. The next visitor in the chain can get 80 * the state of the stack map frame <i>before</i> each instruction by reading 81 * the value of these fields in its visit<i>X</i> methods (this requires a 82 * reference to the AnalyzerAdapter that is before it in the chain). 83 * If this adapter is used with a class that does not contain stack map table 84 * attributes (i.e., pre Java 6 classes) then this adapter may not be able to 85 * compute the stack map frame for each instruction. In this case no exception 86 * is thrown but the {@link #locals} and {@link #stack} fields will be null for 87 * these instructions. 88 * 89 * @author Eric Bruneton 90 */ 91 public class AnalyzerAdapter extends MethodVisitor { 92 93 /** 94 * <code>List</code> of the local variable slots for current execution 95 * frame. Primitive types are represented by {@link Opcodes#TOP}, 96 * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, 97 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or 98 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a 99 * two elements, the second one being TOP). Reference types are represented 100 * by String objects (representing internal names), and uninitialized types 101 * by Label objects (this label designates the NEW instruction that created 102 * this uninitialized value). This field is <tt>null</tt> for unreacheable 103 * instructions. 104 */ 105 public List<Object> locals; 106 107 /** 108 * <code>List</code> of the operand stack slots for current execution 109 * frame. Primitive types are represented by {@link Opcodes#TOP}, 110 * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, 111 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or 112 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a 113 * two elements, the second one being TOP). Reference types are represented 114 * by String objects (representing internal names), and uninitialized types 115 * by Label objects (this label designates the NEW instruction that created 116 * this uninitialized value). This field is <tt>null</tt> for unreacheable 117 * instructions. 118 */ 119 public List<Object> stack; 120 121 /** 122 * The labels that designate the next instruction to be visited. May be 123 * <tt>null</tt>. 124 */ 125 private List<Label> labels; 126 127 /** 128 * Information about uninitialized types in the current execution frame. 129 * This map associates internal names to Label objects. Each label 130 * designates a NEW instruction that created the currently uninitialized 131 * types, and the associated internal name represents the NEW operand, i.e. 132 * the final, initialized type value. 133 */ 134 public Map<Object,Object> uninitializedTypes; 135 136 /** 137 * The maximum stack size of this method. 138 */ 139 private int maxStack; 140 141 /** 142 * The maximum number of local variables of this method. 143 */ 144 private int maxLocals; 145 146 /** 147 * The owner's class name. 148 */ 149 private String owner; 150 151 /** 152 * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this 153 * constructor</i>. Instead, they must use the 154 * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)} 155 * version. 156 * 157 * @param owner the owner's class name. 158 * @param access the method's access flags (see {@link Opcodes}). 159 * @param name the method's name. 160 * @param desc the method's descriptor (see {@link Type Type}). 161 * @param mv the method visitor to which this adapter delegates calls. May 162 * be <tt>null</tt>. 163 */ 164 public AnalyzerAdapter( 165 final String owner, 166 final int access, 167 final String name, 168 final String desc, 169 final MethodVisitor mv) 170 { 171 this(Opcodes.ASM4, owner, access, name, desc, mv); 172 } 173 174 /** 175 * Creates a new {@link AnalyzerAdapter}. 176 * 177 * @param api the ASM API version implemented by this visitor. Must be one 178 * of {@link Opcodes#ASM4}. 179 * @param owner the owner's class name. 180 * @param access the method's access flags (see {@link Opcodes}). 181 * @param name the method's name. 182 * @param desc the method's descriptor (see {@link Type Type}). 183 * @param mv the method visitor to which this adapter delegates calls. May 184 * be <tt>null</tt>. 185 */ 186 protected AnalyzerAdapter( 187 final int api, 188 final String owner, 189 final int access, 190 final String name, 191 final String desc, 192 final MethodVisitor mv) 193 { 194 super(api, mv); 195 this.owner = owner; 196 locals = new ArrayList<Object>(); 197 stack = new ArrayList<Object>(); 198 uninitializedTypes = new HashMap<Object, Object>(); 199 200 if ((access & Opcodes.ACC_STATIC) == 0) { 201 if ("<init>".equals(name)) { 202 locals.add(Opcodes.UNINITIALIZED_THIS); 203 } else { 204 locals.add(owner); 205 } 206 } 207 Type[] types = Type.getArgumentTypes(desc); 208 for (int i = 0; i < types.length; ++i) { 209 Type type = types[i]; 210 switch (type.getSort()) { 211 case Type.BOOLEAN: 212 case Type.CHAR: 213 case Type.BYTE: 214 case Type.SHORT: 215 case Type.INT: 216 locals.add(Opcodes.INTEGER); 217 break; 218 case Type.FLOAT: 219 locals.add(Opcodes.FLOAT); 220 break; 221 case Type.LONG: 222 locals.add(Opcodes.LONG); 223 locals.add(Opcodes.TOP); 224 break; 225 case Type.DOUBLE: 226 locals.add(Opcodes.DOUBLE); 227 locals.add(Opcodes.TOP); 228 break; 229 case Type.ARRAY: 230 locals.add(types[i].getDescriptor()); 231 break; 232 // case Type.OBJECT: 233 default: 234 locals.add(types[i].getInternalName()); 235 } 236 } 237 } 238 239 @Override 240 public void visitFrame( 241 final int type, 242 final int nLocal, 243 final Object[] local, 244 final int nStack, 245 final Object[] stack) 246 { 247 if (type != Opcodes.F_NEW) { // uncompressed frame 248 throw new IllegalStateException("ClassReader.accept() should be called with EXPAND_FRAMES flag"); 249 } 250 251 if (mv != null) { 252 mv.visitFrame(type, nLocal, local, nStack, stack); 253 } 254 255 if (this.locals != null) { 256 this.locals.clear(); 257 this.stack.clear(); 258 } else { 259 this.locals = new ArrayList<Object>(); 260 this.stack = new ArrayList<Object>(); 261 } 262 visitFrameTypes(nLocal, local, this.locals); 263 visitFrameTypes(nStack, stack, this.stack); 264 maxStack = Math.max(maxStack, this.stack.size()); 265 } 266 267 private static void visitFrameTypes( 268 final int n, 269 final Object[] types, 270 final List<Object> result) 271 { 272 for (int i = 0; i < n; ++i) { 273 Object type = types[i]; 274 result.add(type); 275 if (type == Opcodes.LONG || type == Opcodes.DOUBLE) { 276 result.add(Opcodes.TOP); 277 } 278 } 279 } 280 281 @Override 282 public void visitInsn(final int opcode) { 283 if (mv != null) { 284 mv.visitInsn(opcode); 285 } 286 execute(opcode, 0, null); 287 if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) 288 || opcode == Opcodes.ATHROW) 289 { 290 this.locals = null; 291 this.stack = null; 292 } 293 } 294 295 @Override 296 public void visitIntInsn(final int opcode, final int operand) { 297 if (mv != null) { 298 mv.visitIntInsn(opcode, operand); 299 } 300 execute(opcode, operand, null); 301 } 302 303 @Override 304 public void visitVarInsn(final int opcode, final int var) { 305 if (mv != null) { 306 mv.visitVarInsn(opcode, var); 307 } 308 execute(opcode, var, null); 309 } 310 311 @Override 312 public void visitTypeInsn(final int opcode, final String type) { 313 if (opcode == Opcodes.NEW) { 314 if (labels == null) { 315 Label l = new Label(); 316 labels = new ArrayList<Label>(3); 317 labels.add(l); 318 if (mv != null) { 319 mv.visitLabel(l); 320 } 321 } 322 for (int i = 0; i < labels.size(); ++i) { 323 uninitializedTypes.put(labels.get(i), type); 324 } 325 } 326 if (mv != null) { 327 mv.visitTypeInsn(opcode, type); 328 } 329 execute(opcode, 0, type); 330 } 331 332 @Override 333 public void visitFieldInsn( 334 final int opcode, 335 final String owner, 336 final String name, 337 final String desc) 338 { 339 if (mv != null) { 340 mv.visitFieldInsn(opcode, owner, name, desc); 341 } 342 execute(opcode, 0, desc); 343 } 344 345 @Override 346 public void visitMethodInsn( 347 final int opcode, 348 final String owner, 349 final String name, 350 final String desc) 351 { 352 if (mv != null) { 353 mv.visitMethodInsn(opcode, owner, name, desc); 354 } 355 if (this.locals == null) { 356 labels = null; 357 return; 358 } 359 pop(desc); 360 if (opcode != Opcodes.INVOKESTATIC) { 361 Object t = pop(); 362 if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') { 363 Object u; 364 if (t == Opcodes.UNINITIALIZED_THIS) { 365 u = this.owner; 366 } else { 367 u = uninitializedTypes.get(t); 368 } 369 for (int i = 0; i < locals.size(); ++i) { 370 if (locals.get(i) == t) { 371 locals.set(i, u); 372 } 373 } 374 for (int i = 0; i < stack.size(); ++i) { 375 if (stack.get(i) == t) { 376 stack.set(i, u); 377 } 378 } 379 } 380 } 381 pushDesc(desc); 382 labels = null; 383 } 384 385 @Override 386 public void visitInvokeDynamicInsn( 387 String name, 388 String desc, 389 Handle bsm, 390 Object... bsmArgs) 391 { 392 if (mv != null) { 393 mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); 394 } 395 if (this.locals == null) { 396 labels = null; 397 return; 398 } 399 pop(desc); 400 pushDesc(desc); 401 labels = null; 402 } 403 404 @Override 405 public void visitJumpInsn(final int opcode, final Label label) { 406 if (mv != null) { 407 mv.visitJumpInsn(opcode, label); 408 } 409 execute(opcode, 0, null); 410 if (opcode == Opcodes.GOTO) { 411 this.locals = null; 412 this.stack = null; 413 } 414 } 415 416 @Override 417 public void visitLabel(final Label label) { 418 if (mv != null) { 419 mv.visitLabel(label); 420 } 421 if (labels == null) { 422 labels = new ArrayList<Label>(3); 423 } 424 labels.add(label); 425 } 426 427 @Override 428 public void visitLdcInsn(final Object cst) { 429 if (mv != null) { 430 mv.visitLdcInsn(cst); 431 } 432 if (this.locals == null) { 433 labels = null; 434 return; 435 } 436 if (cst instanceof Integer) { 437 push(Opcodes.INTEGER); 438 } else if (cst instanceof Long) { 439 push(Opcodes.LONG); 440 push(Opcodes.TOP); 441 } else if (cst instanceof Float) { 442 push(Opcodes.FLOAT); 443 } else if (cst instanceof Double) { 444 push(Opcodes.DOUBLE); 445 push(Opcodes.TOP); 446 } else if (cst instanceof String) { 447 push("java/lang/String"); 448 } else if (cst instanceof Type) { 449 int sort = ((Type) cst).getSort(); 450 if (sort == Type.OBJECT || sort == Type.ARRAY) { 451 push("java/lang/Class"); 452 } else if (sort == Type.METHOD) { 453 push("java/lang/invoke/MethodType"); 454 } else { 455 throw new IllegalArgumentException(); 456 } 457 } else if (cst instanceof Handle) { 458 push("java/lang/invoke/MethodHandle"); 459 } else { 460 throw new IllegalArgumentException(); 461 } 462 labels = null; 463 } 464 465 @Override 466 public void visitIincInsn(final int var, final int increment) { 467 if (mv != null) { 468 mv.visitIincInsn(var, increment); 469 } 470 execute(Opcodes.IINC, var, null); 471 } 472 473 @Override 474 public void visitTableSwitchInsn( 475 final int min, 476 final int max, 477 final Label dflt, 478 final Label... labels) 479 { 480 if (mv != null) { 481 mv.visitTableSwitchInsn(min, max, dflt, labels); 482 } 483 execute(Opcodes.TABLESWITCH, 0, null); 484 this.locals = null; 485 this.stack = null; 486 } 487 488 @Override 489 public void visitLookupSwitchInsn( 490 final Label dflt, 491 final int[] keys, 492 final Label[] labels) 493 { 494 if (mv != null) { 495 mv.visitLookupSwitchInsn(dflt, keys, labels); 496 } 497 execute(Opcodes.LOOKUPSWITCH, 0, null); 498 this.locals = null; 499 this.stack = null; 500 } 501 502 @Override 503 public void visitMultiANewArrayInsn(final String desc, final int dims) { 504 if (mv != null) { 505 mv.visitMultiANewArrayInsn(desc, dims); 506 } 507 execute(Opcodes.MULTIANEWARRAY, dims, desc); 508 } 509 510 @Override 511 public void visitMaxs(final int maxStack, final int maxLocals) { 512 if (mv != null) { 513 this.maxStack = Math.max(this.maxStack, maxStack); 514 this.maxLocals = Math.max(this.maxLocals, maxLocals); 515 mv.visitMaxs(this.maxStack, this.maxLocals); 516 } 517 } 518 519 // ------------------------------------------------------------------------ 520 521 private Object get(final int local) { 522 maxLocals = Math.max(maxLocals, local); 523 return local < locals.size() ? locals.get(local) : Opcodes.TOP; 524 } 525 526 private void set(final int local, final Object type) { 527 maxLocals = Math.max(maxLocals, local); 528 while (local >= locals.size()) { 529 locals.add(Opcodes.TOP); 530 } 531 locals.set(local, type); 532 } 533 534 private void push(final Object type) { 535 stack.add(type); 536 maxStack = Math.max(maxStack, stack.size()); 537 } 538 539 private void pushDesc(final String desc) { 540 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; 541 switch (desc.charAt(index)) { 542 case 'V': 543 return; 544 case 'Z': 545 case 'C': 546 case 'B': 547 case 'S': 548 case 'I': 549 push(Opcodes.INTEGER); 550 return; 551 case 'F': 552 push(Opcodes.FLOAT); 553 return; 554 case 'J': 555 push(Opcodes.LONG); 556 push(Opcodes.TOP); 557 return; 558 case 'D': 559 push(Opcodes.DOUBLE); 560 push(Opcodes.TOP); 561 return; 562 case '[': 563 if (index == 0) { 564 push(desc); 565 } else { 566 push(desc.substring(index, desc.length())); 567 } 568 break; 569 // case 'L': 570 default: 571 if (index == 0) { 572 push(desc.substring(1, desc.length() - 1)); 573 } else { 574 push(desc.substring(index + 1, desc.length() - 1)); 575 } 576 } 577 } 578 579 private Object pop() { 580 return stack.remove(stack.size() - 1); 581 } 582 583 private void pop(final int n) { 584 int size = stack.size(); 585 int end = size - n; 586 for (int i = size - 1; i >= end; --i) { 587 stack.remove(i); 588 } 589 } 590 591 private void pop(final String desc) { 592 char c = desc.charAt(0); 593 if (c == '(') { 594 int n = 0; 595 Type[] types = Type.getArgumentTypes(desc); 596 for (int i = 0; i < types.length; ++i) { 597 n += types[i].getSize(); 598 } 599 pop(n); 600 } else if (c == 'J' || c == 'D') { 601 pop(2); 602 } else { 603 pop(1); 604 } 605 } 606 607 private void execute(final int opcode, final int iarg, final String sarg) { 608 if (this.locals == null) { 609 labels = null; 610 return; 611 } 612 Object t1, t2, t3, t4; 613 switch (opcode) { 614 case Opcodes.NOP: 615 case Opcodes.INEG: 616 case Opcodes.LNEG: 617 case Opcodes.FNEG: 618 case Opcodes.DNEG: 619 case Opcodes.I2B: 620 case Opcodes.I2C: 621 case Opcodes.I2S: 622 case Opcodes.GOTO: 623 case Opcodes.RETURN: 624 break; 625 case Opcodes.ACONST_NULL: 626 push(Opcodes.NULL); 627 break; 628 case Opcodes.ICONST_M1: 629 case Opcodes.ICONST_0: 630 case Opcodes.ICONST_1: 631 case Opcodes.ICONST_2: 632 case Opcodes.ICONST_3: 633 case Opcodes.ICONST_4: 634 case Opcodes.ICONST_5: 635 case Opcodes.BIPUSH: 636 case Opcodes.SIPUSH: 637 push(Opcodes.INTEGER); 638 break; 639 case Opcodes.LCONST_0: 640 case Opcodes.LCONST_1: 641 push(Opcodes.LONG); 642 push(Opcodes.TOP); 643 break; 644 case Opcodes.FCONST_0: 645 case Opcodes.FCONST_1: 646 case Opcodes.FCONST_2: 647 push(Opcodes.FLOAT); 648 break; 649 case Opcodes.DCONST_0: 650 case Opcodes.DCONST_1: 651 push(Opcodes.DOUBLE); 652 push(Opcodes.TOP); 653 break; 654 case Opcodes.ILOAD: 655 case Opcodes.FLOAD: 656 case Opcodes.ALOAD: 657 push(get(iarg)); 658 break; 659 case Opcodes.LLOAD: 660 case Opcodes.DLOAD: 661 push(get(iarg)); 662 push(Opcodes.TOP); 663 break; 664 case Opcodes.IALOAD: 665 case Opcodes.BALOAD: 666 case Opcodes.CALOAD: 667 case Opcodes.SALOAD: 668 pop(2); 669 push(Opcodes.INTEGER); 670 break; 671 case Opcodes.LALOAD: 672 case Opcodes.D2L: 673 pop(2); 674 push(Opcodes.LONG); 675 push(Opcodes.TOP); 676 break; 677 case Opcodes.FALOAD: 678 pop(2); 679 push(Opcodes.FLOAT); 680 break; 681 case Opcodes.DALOAD: 682 case Opcodes.L2D: 683 pop(2); 684 push(Opcodes.DOUBLE); 685 push(Opcodes.TOP); 686 break; 687 case Opcodes.AALOAD: 688 pop(1); 689 t1 = pop(); 690 if (t1 instanceof String) { 691 pushDesc(((String) t1).substring(1)); 692 } else { 693 push("java/lang/Object"); 694 } 695 break; 696 case Opcodes.ISTORE: 697 case Opcodes.FSTORE: 698 case Opcodes.ASTORE: 699 t1 = pop(); 700 set(iarg, t1); 701 if (iarg > 0) { 702 t2 = get(iarg - 1); 703 if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { 704 set(iarg - 1, Opcodes.TOP); 705 } 706 } 707 break; 708 case Opcodes.LSTORE: 709 case Opcodes.DSTORE: 710 pop(1); 711 t1 = pop(); 712 set(iarg, t1); 713 set(iarg + 1, Opcodes.TOP); 714 if (iarg > 0) { 715 t2 = get(iarg - 1); 716 if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { 717 set(iarg - 1, Opcodes.TOP); 718 } 719 } 720 break; 721 case Opcodes.IASTORE: 722 case Opcodes.BASTORE: 723 case Opcodes.CASTORE: 724 case Opcodes.SASTORE: 725 case Opcodes.FASTORE: 726 case Opcodes.AASTORE: 727 pop(3); 728 break; 729 case Opcodes.LASTORE: 730 case Opcodes.DASTORE: 731 pop(4); 732 break; 733 case Opcodes.POP: 734 case Opcodes.IFEQ: 735 case Opcodes.IFNE: 736 case Opcodes.IFLT: 737 case Opcodes.IFGE: 738 case Opcodes.IFGT: 739 case Opcodes.IFLE: 740 case Opcodes.IRETURN: 741 case Opcodes.FRETURN: 742 case Opcodes.ARETURN: 743 case Opcodes.TABLESWITCH: 744 case Opcodes.LOOKUPSWITCH: 745 case Opcodes.ATHROW: 746 case Opcodes.MONITORENTER: 747 case Opcodes.MONITOREXIT: 748 case Opcodes.IFNULL: 749 case Opcodes.IFNONNULL: 750 pop(1); 751 break; 752 case Opcodes.POP2: 753 case Opcodes.IF_ICMPEQ: 754 case Opcodes.IF_ICMPNE: 755 case Opcodes.IF_ICMPLT: 756 case Opcodes.IF_ICMPGE: 757 case Opcodes.IF_ICMPGT: 758 case Opcodes.IF_ICMPLE: 759 case Opcodes.IF_ACMPEQ: 760 case Opcodes.IF_ACMPNE: 761 case Opcodes.LRETURN: 762 case Opcodes.DRETURN: 763 pop(2); 764 break; 765 case Opcodes.DUP: 766 t1 = pop(); 767 push(t1); 768 push(t1); 769 break; 770 case Opcodes.DUP_X1: 771 t1 = pop(); 772 t2 = pop(); 773 push(t1); 774 push(t2); 775 push(t1); 776 break; 777 case Opcodes.DUP_X2: 778 t1 = pop(); 779 t2 = pop(); 780 t3 = pop(); 781 push(t1); 782 push(t3); 783 push(t2); 784 push(t1); 785 break; 786 case Opcodes.DUP2: 787 t1 = pop(); 788 t2 = pop(); 789 push(t2); 790 push(t1); 791 push(t2); 792 push(t1); 793 break; 794 case Opcodes.DUP2_X1: 795 t1 = pop(); 796 t2 = pop(); 797 t3 = pop(); 798 push(t2); 799 push(t1); 800 push(t3); 801 push(t2); 802 push(t1); 803 break; 804 case Opcodes.DUP2_X2: 805 t1 = pop(); 806 t2 = pop(); 807 t3 = pop(); 808 t4 = pop(); 809 push(t2); 810 push(t1); 811 push(t4); 812 push(t3); 813 push(t2); 814 push(t1); 815 break; 816 case Opcodes.SWAP: 817 t1 = pop(); 818 t2 = pop(); 819 push(t1); 820 push(t2); 821 break; 822 case Opcodes.IADD: 823 case Opcodes.ISUB: 824 case Opcodes.IMUL: 825 case Opcodes.IDIV: 826 case Opcodes.IREM: 827 case Opcodes.IAND: 828 case Opcodes.IOR: 829 case Opcodes.IXOR: 830 case Opcodes.ISHL: 831 case Opcodes.ISHR: 832 case Opcodes.IUSHR: 833 case Opcodes.L2I: 834 case Opcodes.D2I: 835 case Opcodes.FCMPL: 836 case Opcodes.FCMPG: 837 pop(2); 838 push(Opcodes.INTEGER); 839 break; 840 case Opcodes.LADD: 841 case Opcodes.LSUB: 842 case Opcodes.LMUL: 843 case Opcodes.LDIV: 844 case Opcodes.LREM: 845 case Opcodes.LAND: 846 case Opcodes.LOR: 847 case Opcodes.LXOR: 848 pop(4); 849 push(Opcodes.LONG); 850 push(Opcodes.TOP); 851 break; 852 case Opcodes.FADD: 853 case Opcodes.FSUB: 854 case Opcodes.FMUL: 855 case Opcodes.FDIV: 856 case Opcodes.FREM: 857 case Opcodes.L2F: 858 case Opcodes.D2F: 859 pop(2); 860 push(Opcodes.FLOAT); 861 break; 862 case Opcodes.DADD: 863 case Opcodes.DSUB: 864 case Opcodes.DMUL: 865 case Opcodes.DDIV: 866 case Opcodes.DREM: 867 pop(4); 868 push(Opcodes.DOUBLE); 869 push(Opcodes.TOP); 870 break; 871 case Opcodes.LSHL: 872 case Opcodes.LSHR: 873 case Opcodes.LUSHR: 874 pop(3); 875 push(Opcodes.LONG); 876 push(Opcodes.TOP); 877 break; 878 case Opcodes.IINC: 879 set(iarg, Opcodes.INTEGER); 880 break; 881 case Opcodes.I2L: 882 case Opcodes.F2L: 883 pop(1); 884 push(Opcodes.LONG); 885 push(Opcodes.TOP); 886 break; 887 case Opcodes.I2F: 888 pop(1); 889 push(Opcodes.FLOAT); 890 break; 891 case Opcodes.I2D: 892 case Opcodes.F2D: 893 pop(1); 894 push(Opcodes.DOUBLE); 895 push(Opcodes.TOP); 896 break; 897 case Opcodes.F2I: 898 case Opcodes.ARRAYLENGTH: 899 case Opcodes.INSTANCEOF: 900 pop(1); 901 push(Opcodes.INTEGER); 902 break; 903 case Opcodes.LCMP: 904 case Opcodes.DCMPL: 905 case Opcodes.DCMPG: 906 pop(4); 907 push(Opcodes.INTEGER); 908 break; 909 case Opcodes.JSR: 910 case Opcodes.RET: 911 throw new RuntimeException("JSR/RET are not supported"); 912 case Opcodes.GETSTATIC: 913 pushDesc(sarg); 914 break; 915 case Opcodes.PUTSTATIC: 916 pop(sarg); 917 break; 918 case Opcodes.GETFIELD: 919 pop(1); 920 pushDesc(sarg); 921 break; 922 case Opcodes.PUTFIELD: 923 pop(sarg); 924 pop(); 925 break; 926 case Opcodes.NEW: 927 push(labels.get(0)); 928 break; 929 case Opcodes.NEWARRAY: 930 pop(); 931 switch (iarg) { 932 case Opcodes.T_BOOLEAN: 933 pushDesc("[Z"); 934 break; 935 case Opcodes.T_CHAR: 936 pushDesc("[C"); 937 break; 938 case Opcodes.T_BYTE: 939 pushDesc("[B"); 940 break; 941 case Opcodes.T_SHORT: 942 pushDesc("[S"); 943 break; 944 case Opcodes.T_INT: 945 pushDesc("[I"); 946 break; 947 case Opcodes.T_FLOAT: 948 pushDesc("[F"); 949 break; 950 case Opcodes.T_DOUBLE: 951 pushDesc("[D"); 952 break; 953 // case Opcodes.T_LONG: 954 default: 955 pushDesc("[J"); 956 break; 957 } 958 break; 959 case Opcodes.ANEWARRAY: 960 pop(); 961 pushDesc("[" + Type.getObjectType(sarg)); 962 break; 963 case Opcodes.CHECKCAST: 964 pop(); 965 pushDesc(Type.getObjectType(sarg).getDescriptor()); 966 break; 967 // case Opcodes.MULTIANEWARRAY: 968 default: 969 pop(iarg); 970 pushDesc(sarg); 971 break; 972 } 973 labels = null; 974 } 975 }