1 30 31 package oracle.toplink.libraries.asm.tree.analysis; 32 33 import java.util.ArrayList ; 34 import java.util.List ; 35 36 import oracle.toplink.libraries.asm.Constants; 37 import oracle.toplink.libraries.asm.Type; 38 import oracle.toplink.libraries.asm.tree.AbstractInsnNode; 39 import oracle.toplink.libraries.asm.tree.IincInsnNode; 40 import oracle.toplink.libraries.asm.tree.MethodInsnNode; 41 import oracle.toplink.libraries.asm.tree.MultiANewArrayInsnNode; 42 import oracle.toplink.libraries.asm.tree.VarInsnNode; 43 44 52 53 public class Frame { 54 55 58 59 private Value[] locals; 60 61 64 65 private Value[] stack; 66 67 70 71 private int top; 72 73 79 80 public Frame (final int nLocals, final int nStack) { 81 this.locals = new Value[nLocals]; 82 this.stack = new Value[nStack]; 83 } 84 85 90 91 public Frame (final Frame src) { 92 this(src.locals.length, src.stack.length); 93 init(src); 94 } 95 96 102 103 public Frame init (final Frame src) { 104 System.arraycopy(src.locals, 0, locals, 0, locals.length); 105 System.arraycopy(src.stack, 0, stack, 0, src.top); 106 top = src.top; 107 return this; 108 } 109 110 115 116 public int getLocals () { 117 return locals.length; 118 } 119 120 127 128 public Value getLocal (final int i) throws AnalyzerException { 129 if (i >= locals.length) { 130 throw new AnalyzerException("Trying to access an inexistant local variable"); 131 } 132 return locals[i]; 133 } 134 135 142 143 public void setLocal (final int i, final Value value) throws AnalyzerException { 144 if (i >= locals.length) { 145 throw new AnalyzerException("Trying to access an inexistant local variable"); 146 } 147 locals[i] = value; 148 } 149 150 156 157 public int getStackSize () { 158 return top; 159 } 160 161 168 169 public Value getStack (final int i) throws AnalyzerException { 170 if (i >= top) { 171 throw new AnalyzerException("Trying to access an inexistant stack element"); 172 } 173 return stack[i]; 174 } 175 176 179 180 public void clearStack () { 181 top = 0; 182 } 183 184 190 191 public Value pop () throws AnalyzerException { 192 if (top == 0) { 193 throw new AnalyzerException("Cannot pop operand off an empty stack."); 194 } 195 return stack[--top]; 196 } 197 198 204 205 public void push (final Value value) throws AnalyzerException { 206 if (top >= stack.length) { 207 throw new AnalyzerException("Insufficient maximum stack size."); 208 } 209 stack[top++] = value; 210 } 211 212 public void execute ( 213 final AbstractInsnNode insn, 214 final Interpreter interpreter) throws AnalyzerException 215 { 216 Value value1, value2, value3, value4; 217 List values; 218 int var; 219 220 switch (insn.getOpcode()) { 221 case Constants.NOP: 222 break; 223 case Constants.ACONST_NULL: 224 case Constants.ICONST_M1: 225 case Constants.ICONST_0: 226 case Constants.ICONST_1: 227 case Constants.ICONST_2: 228 case Constants.ICONST_3: 229 case Constants.ICONST_4: 230 case Constants.ICONST_5: 231 case Constants.LCONST_0: 232 case Constants.LCONST_1: 233 case Constants.FCONST_0: 234 case Constants.FCONST_1: 235 case Constants.FCONST_2: 236 case Constants.DCONST_0: 237 case Constants.DCONST_1: 238 case Constants.BIPUSH: 239 case Constants.SIPUSH: 240 case Constants.LDC: 241 push(interpreter.newOperation(insn)); 242 break; 243 case Constants.ILOAD: 244 case Constants.LLOAD: 245 case Constants.FLOAD: 246 case Constants.DLOAD: 247 case Constants.ALOAD: 248 push(interpreter.copyOperation(insn, getLocal(((VarInsnNode)insn).var))); 249 break; 250 case Constants.IALOAD: 251 case Constants.LALOAD: 252 case Constants.FALOAD: 253 case Constants.DALOAD: 254 case Constants.AALOAD: 255 case Constants.BALOAD: 256 case Constants.CALOAD: 257 case Constants.SALOAD: 258 value2 = pop(); 259 value1 = pop(); 260 push(interpreter.binaryOperation(insn, value1, value2)); 261 break; 262 case Constants.ISTORE: 263 case Constants.LSTORE: 264 case Constants.FSTORE: 265 case Constants.DSTORE: 266 case Constants.ASTORE: 267 value1 = interpreter.copyOperation(insn, pop()); 268 var = ((VarInsnNode)insn).var; 269 setLocal(var, value1); 270 if (value1.getSize() == 2) { 271 setLocal(var + 1, interpreter.newValue(null)); 272 } 273 if (var > 0 && getLocal(var - 1).getSize() == 2) { 274 setLocal(var - 1, interpreter.newValue(null)); 275 } 276 break; 277 case Constants.IASTORE: 278 case Constants.LASTORE: 279 case Constants.FASTORE: 280 case Constants.DASTORE: 281 case Constants.AASTORE: 282 case Constants.BASTORE: 283 case Constants.CASTORE: 284 case Constants.SASTORE: 285 value3 = pop(); 286 value2 = pop(); 287 value1 = pop(); 288 interpreter.ternaryOperation(insn, value1, value2, value3); 289 break; 290 case Constants.POP: 291 if (pop().getSize() == 2) { 292 throw new AnalyzerException("Illegal use of POP"); 293 } 294 break; 295 case Constants.POP2: 296 if (pop().getSize() == 1) { 297 if (pop().getSize() != 1) { 298 throw new AnalyzerException("Illegal use of POP2"); 299 } 300 } 301 break; 302 case Constants.DUP: 303 value1 = pop(); 304 if (value1.getSize() != 1) { 305 throw new AnalyzerException("Illegal use of DUP"); 306 } 307 push(interpreter.copyOperation(insn, value1)); 308 push(interpreter.copyOperation(insn, value1)); 309 break; 310 case Constants.DUP_X1: 311 value1 = pop(); 312 value2 = pop(); 313 if (value1.getSize() != 1 || value2.getSize() != 1) { 314 throw new AnalyzerException("Illegal use of DUP_X1"); 315 } 316 push(interpreter.copyOperation(insn, value1)); 317 push(interpreter.copyOperation(insn, value2)); 318 push(interpreter.copyOperation(insn, value1)); 319 break; 320 case Constants.DUP_X2: 321 value1 = pop(); 322 if (value1.getSize() == 1) { 323 value2 = pop(); 324 if (value2.getSize() == 1) { 325 value3 = pop(); 326 if (value3.getSize() == 1) { 327 push(interpreter.copyOperation(insn, value1)); 328 push(interpreter.copyOperation(insn, value3)); 329 push(interpreter.copyOperation(insn, value2)); 330 push(interpreter.copyOperation(insn, value1)); 331 break; 332 } 333 } else { 334 push(interpreter.copyOperation(insn, value1)); 335 push(interpreter.copyOperation(insn, value2)); 336 push(interpreter.copyOperation(insn, value1)); 337 break; 338 } 339 } 340 throw new AnalyzerException("Illegal use of DUP_X2"); 341 case Constants.DUP2: 342 value1 = pop(); 343 if (value1.getSize() == 1) { 344 value2 = pop(); 345 if (value2.getSize() == 1) { 346 push(interpreter.copyOperation(insn, value2)); 347 push(interpreter.copyOperation(insn, value1)); 348 push(interpreter.copyOperation(insn, value2)); 349 push(interpreter.copyOperation(insn, value1)); 350 break; 351 } 352 } else { 353 push(interpreter.copyOperation(insn, value1)); 354 push(interpreter.copyOperation(insn, value1)); 355 break; 356 } 357 throw new AnalyzerException("Illegal use of DUP2"); 358 case Constants.DUP2_X1: 359 value1 = pop(); 360 if (value1.getSize() == 1) { 361 value2 = pop(); 362 if (value2.getSize() == 1) { 363 value3 = pop(); 364 if (value3.getSize() == 1) { 365 push(interpreter.copyOperation(insn, value2)); 366 push(interpreter.copyOperation(insn, value1)); 367 push(interpreter.copyOperation(insn, value3)); 368 push(interpreter.copyOperation(insn, value2)); 369 push(interpreter.copyOperation(insn, value1)); 370 break; 371 } 372 } 373 } else { 374 value2 = pop(); 375 if (value2.getSize() == 1) { 376 push(interpreter.copyOperation(insn, value1)); 377 push(interpreter.copyOperation(insn, value2)); 378 push(interpreter.copyOperation(insn, value1)); 379 break; 380 } 381 } 382 throw new AnalyzerException("Illegal use of DUP2_X1"); 383 case Constants.DUP2_X2: 384 value1 = pop(); 385 if (value1.getSize() == 1) { 386 value2 = pop(); 387 if (value2.getSize() == 1) { 388 value3 = pop(); 389 if (value3.getSize() == 1) { 390 value4 = pop(); 391 if (value4.getSize() == 1) { 392 push(interpreter.copyOperation(insn, value2)); 393 push(interpreter.copyOperation(insn, value1)); 394 push(interpreter.copyOperation(insn, value4)); 395 push(interpreter.copyOperation(insn, value3)); 396 push(interpreter.copyOperation(insn, value2)); 397 push(interpreter.copyOperation(insn, value1)); 398 break; 399 } 400 } else { 401 push(interpreter.copyOperation(insn, value2)); 402 push(interpreter.copyOperation(insn, value1)); 403 push(interpreter.copyOperation(insn, value3)); 404 push(interpreter.copyOperation(insn, value2)); 405 push(interpreter.copyOperation(insn, value1)); 406 break; 407 } 408 } 409 } else { 410 value2 = pop(); 411 if (value2.getSize() == 1) { 412 value3 = pop(); 413 if (value3.getSize() == 1) { 414 push(interpreter.copyOperation(insn, value1)); 415 push(interpreter.copyOperation(insn, value3)); 416 push(interpreter.copyOperation(insn, value2)); 417 push(interpreter.copyOperation(insn, value1)); 418 break; 419 } 420 } else { 421 push(interpreter.copyOperation(insn, value1)); 422 push(interpreter.copyOperation(insn, value2)); 423 push(interpreter.copyOperation(insn, value1)); 424 break; 425 } 426 } 427 throw new AnalyzerException("Illegal use of DUP2_X2"); 428 case Constants.SWAP: 429 value2 = pop(); 430 value1 = pop(); 431 if (value1.getSize() != 1 || value2.getSize() != 1) { 432 throw new AnalyzerException("Illegal use of SWAP"); 433 } 434 push(interpreter.copyOperation(insn, value2)); 435 push(interpreter.copyOperation(insn, value1)); 436 break; 437 case Constants.IADD: 438 case Constants.LADD: 439 case Constants.FADD: 440 case Constants.DADD: 441 case Constants.ISUB: 442 case Constants.LSUB: 443 case Constants.FSUB: 444 case Constants.DSUB: 445 case Constants.IMUL: 446 case Constants.LMUL: 447 case Constants.FMUL: 448 case Constants.DMUL: 449 case Constants.IDIV: 450 case Constants.LDIV: 451 case Constants.FDIV: 452 case Constants.DDIV: 453 case Constants.IREM: 454 case Constants.LREM: 455 case Constants.FREM: 456 case Constants.DREM: 457 value2 = pop(); 458 value1 = pop(); 459 push(interpreter.binaryOperation(insn, value1, value2)); 460 break; 461 case Constants.INEG: 462 case Constants.LNEG: 463 case Constants.FNEG: 464 case Constants.DNEG: 465 push(interpreter.unaryOperation(insn, pop())); 466 break; 467 case Constants.ISHL: 468 case Constants.LSHL: 469 case Constants.ISHR: 470 case Constants.LSHR: 471 case Constants.IUSHR: 472 case Constants.LUSHR: 473 case Constants.IAND: 474 case Constants.LAND: 475 case Constants.IOR: 476 case Constants.LOR: 477 case Constants.IXOR: 478 case Constants.LXOR: 479 value2 = pop(); 480 value1 = pop(); 481 push(interpreter.binaryOperation(insn, value1, value2)); 482 break; 483 case Constants.IINC: 484 var = ((IincInsnNode)insn).var; 485 setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); 486 break; 487 case Constants.I2L: 488 case Constants.I2F: 489 case Constants.I2D: 490 case Constants.L2I: 491 case Constants.L2F: 492 case Constants.L2D: 493 case Constants.F2I: 494 case Constants.F2L: 495 case Constants.F2D: 496 case Constants.D2I: 497 case Constants.D2L: 498 case Constants.D2F: 499 case Constants.I2B: 500 case Constants.I2C: 501 case Constants.I2S: 502 push(interpreter.unaryOperation(insn, pop())); 503 break; 504 case Constants.LCMP: 505 case Constants.FCMPL: 506 case Constants.FCMPG: 507 case Constants.DCMPL: 508 case Constants.DCMPG: 509 value2 = pop(); 510 value1 = pop(); 511 push(interpreter.binaryOperation(insn, value1, value2)); 512 break; 513 case Constants.IFEQ: 514 case Constants.IFNE: 515 case Constants.IFLT: 516 case Constants.IFGE: 517 case Constants.IFGT: 518 case Constants.IFLE: 519 interpreter.unaryOperation(insn, pop()); 520 break; 521 case Constants.IF_ICMPEQ: 522 case Constants.IF_ICMPNE: 523 case Constants.IF_ICMPLT: 524 case Constants.IF_ICMPGE: 525 case Constants.IF_ICMPGT: 526 case Constants.IF_ICMPLE: 527 case Constants.IF_ACMPEQ: 528 case Constants.IF_ACMPNE: 529 value2 = pop(); 530 value1 = pop(); 531 interpreter.binaryOperation(insn, value1, value2); 532 break; 533 case Constants.GOTO: 534 break; 535 case Constants.JSR: 536 push(interpreter.newOperation(insn)); 537 break; 538 case Constants.RET: 539 break; 540 case Constants.TABLESWITCH: 541 case Constants.LOOKUPSWITCH: 542 case Constants.IRETURN: 543 case Constants.LRETURN: 544 case Constants.FRETURN: 545 case Constants.DRETURN: 546 case Constants.ARETURN: 547 interpreter.unaryOperation(insn, pop()); 548 break; 549 case Constants.RETURN: 550 break; 551 case Constants.GETSTATIC: 552 push(interpreter.newOperation(insn)); 553 break; 554 case Constants.PUTSTATIC: 555 interpreter.unaryOperation(insn, pop()); 556 break; 557 case Constants.GETFIELD: 558 push(interpreter.unaryOperation(insn, pop())); 559 break; 560 case Constants.PUTFIELD: 561 value2 = pop(); 562 value1 = pop(); 563 interpreter.binaryOperation(insn, value1, value2); 564 break; 565 case Constants.INVOKEVIRTUAL: 566 case Constants.INVOKESPECIAL: 567 case Constants.INVOKESTATIC: 568 case Constants.INVOKEINTERFACE: 569 values = new ArrayList (); 570 String desc = ((MethodInsnNode)insn).desc; 571 for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { 572 values.add(0, pop()); 573 } 574 if (insn.getOpcode() != Constants.INVOKESTATIC) { 575 values.add(0, pop()); 576 } 577 if (Type.getReturnType(desc) == Type.VOID_TYPE) { 578 interpreter.naryOperation(insn, values); 579 } else { 580 push(interpreter.naryOperation(insn, values)); 581 } 582 break; 583 case Constants.NEW: 584 push(interpreter.newOperation(insn)); 585 break; 586 case Constants.NEWARRAY: 587 case Constants.ANEWARRAY: 588 case Constants.ARRAYLENGTH: 589 push(interpreter.unaryOperation(insn, pop())); 590 break; 591 case Constants.ATHROW: 592 interpreter.unaryOperation(insn, pop()); 593 break; 594 case Constants.CHECKCAST: 595 case Constants.INSTANCEOF: 596 push(interpreter.unaryOperation(insn, pop())); 597 break; 598 case Constants.MONITORENTER: 599 case Constants.MONITOREXIT: 600 interpreter.unaryOperation(insn, pop()); 601 break; 602 case Constants.MULTIANEWARRAY: 603 values = new ArrayList (); 604 for (int i = ((MultiANewArrayInsnNode)insn).dims; i > 0; --i) { 605 values.add(0, pop()); 606 } 607 push(interpreter.naryOperation(insn, values)); 608 break; 609 case Constants.IFNULL: 610 case Constants.IFNONNULL: 611 interpreter.unaryOperation(insn, pop()); 612 break; 613 default: 614 throw new RuntimeException ("Illegal opcode"); 615 } 616 } 617 618 627 628 public boolean merge (final Frame frame, final Interpreter interpreter) 629 throws AnalyzerException 630 { 631 if (top != frame.top) { 632 throw new AnalyzerException("Incompatible stack heights"); 633 } 634 boolean changes = false; 635 for (int i = 0; i < locals.length; ++i) { 636 Value v = interpreter.merge(locals[i], frame.locals[i]); 637 if (v != locals[i]) { 638 locals[i] = v; 639 changes |= true; 640 } 641 } 642 for (int i = 0; i < top; ++i) { 643 Value v = interpreter.merge(stack[i], frame.stack[i]); 644 if (v != stack[i]) { 645 stack[i] = v; 646 changes |= true; 647 } 648 } 649 return changes; 650 } 651 652 661 662 public boolean merge (final Frame frame, final boolean[] access) { 663 boolean changes = false; 664 for (int i = 0; i < locals.length; ++i) { 665 if (!access[i] && !locals[i].equals(frame.locals[i])) { 666 locals[i] = frame.locals[i]; 667 changes = true; 668 } 669 } 670 return changes; 671 } 672 673 678 679 public String toString () { 680 StringBuffer b = new StringBuffer (); 681 for (int i = 0; i < locals.length; ++i) { 682 b.append(locals[i]); 683 } 684 b.append(' '); 685 for (int i = 0; i < top; ++i) { 686 b.append(stack[i].toString()); 687 } 688 return b.toString(); 689 } 690 } 691 | Popular Tags |