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