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