1
/* $Id: Processor.java,v 1.12 2004/12/11 16:35:23 eric Exp $
3
* ProGuard -- shrinking, optimization, and obfuscation of Java class files.
5
* Copyright (c) 2002-2004 Eric Lafortune (eric@graphics.cornell.edu)
7
* This program is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by the Free
9
* Software Foundation; either version 2 of the License, or (at your option)
12
* This program is distributed in the hope that it will be useful, but WITHOUT
13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
* You should have received a copy of the GNU General Public License along
18
* with this program; if not, write to the Free Software Foundation, Inc.,
19
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
package proguard.optimize.evaluation;
23
import proguard.classfile.*;
24
import proguard.classfile.attribute.*;
25
import proguard.classfile.instruction.*;
26
import proguard.classfile.util.ClassUtil;
27
import proguard.classfile.visitor.*;
28
import proguard.optimize.evaluation.value.*;
31
* This InstructionVisitor executes the instructions that it visits on a given
32
* local variable frame and stack.
34
* @author Eric Lafortune
36
public class Processor
37
implements InstructionVisitor,
40
private Variables variables;
42
private BranchUnit branchUnit;
44
// Fields acting as return parameters for the CpInfoVisitor methods.
45
private int parameterCount;
46
private Value cpValue;
47
private ClassFile referencedClassFile;
48
private int referencedTypeDimensionCount;
52
* Creates a new processor that operates on the given environment.
53
* @param variables the local variable frame.
54
* @param stack the local stack.
55
* @param branchUnit the class that can affect the program counter.
57
public Processor(Variables variables,
59
BranchUnit branchUnit)
61
this.variables = variables;
63
this.branchUnit = branchUnit;
67
// Implementations for InstructionVisitor.
69
public void visitSimpleInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, SimpleInstruction simpleInstruction)
71
switch (simpleInstruction.opcode)
73
case InstructionConstants.OP_NOP:
76
case InstructionConstants.OP_ACONST_NULL:
77
stack.push(ReferenceValueFactory.createNull());
80
case InstructionConstants.OP_ICONST_M1:
81
case InstructionConstants.OP_ICONST_0:
82
case InstructionConstants.OP_ICONST_1:
83
case InstructionConstants.OP_ICONST_2:
84
case InstructionConstants.OP_ICONST_3:
85
case InstructionConstants.OP_ICONST_4:
86
case InstructionConstants.OP_ICONST_5:
87
case InstructionConstants.OP_BIPUSH:
88
case InstructionConstants.OP_SIPUSH:
89
stack.push(IntegerValueFactory.create(simpleInstruction.constant));
92
case InstructionConstants.OP_LCONST_0:
93
case InstructionConstants.OP_LCONST_1:
94
stack.push(LongValueFactory.create(simpleInstruction.constant));
97
case InstructionConstants.OP_FCONST_0:
98
case InstructionConstants.OP_FCONST_1:
99
case InstructionConstants.OP_FCONST_2:
100
stack.push(FloatValueFactory.create((float)simpleInstruction.constant));
103
case InstructionConstants.OP_DCONST_0:
104
case InstructionConstants.OP_DCONST_1:
105
stack.push(DoubleValueFactory.create((double)simpleInstruction.constant));
108
case InstructionConstants.OP_IALOAD:
109
case InstructionConstants.OP_BALOAD:
110
case InstructionConstants.OP_CALOAD:
111
case InstructionConstants.OP_SALOAD:
114
stack.push(IntegerValueFactory.create());
117
case InstructionConstants.OP_LALOAD:
120
stack.push(LongValueFactory.create());
123
case InstructionConstants.OP_FALOAD:
126
stack.push(FloatValueFactory.create());
129
case InstructionConstants.OP_DALOAD:
132
stack.push(DoubleValueFactory.create());
135
case InstructionConstants.OP_AALOAD:
138
stack.push(ReferenceValueFactory.create(true));
141
case InstructionConstants.OP_IASTORE:
142
case InstructionConstants.OP_BASTORE:
143
case InstructionConstants.OP_CASTORE:
144
case InstructionConstants.OP_SASTORE:
150
case InstructionConstants.OP_LASTORE:
156
case InstructionConstants.OP_FASTORE:
162
case InstructionConstants.OP_DASTORE:
168
case InstructionConstants.OP_AASTORE:
174
case InstructionConstants.OP_POP:
178
case InstructionConstants.OP_POP2:
182
case InstructionConstants.OP_DUP:
186
case InstructionConstants.OP_DUP_X1:
190
case InstructionConstants.OP_DUP_X2:
194
case InstructionConstants.OP_DUP2:
198
case InstructionConstants.OP_DUP2_X1:
202
case InstructionConstants.OP_DUP2_X2:
206
case InstructionConstants.OP_SWAP:
210
case InstructionConstants.OP_IADD:
211
stack.push(stack.ipop().add(stack.ipop()));
214
case InstructionConstants.OP_LADD:
215
stack.push(stack.lpop().add(stack.lpop()));
218
case InstructionConstants.OP_FADD:
219
stack.push(stack.fpop().add(stack.fpop()));
222
case InstructionConstants.OP_DADD:
223
stack.push(stack.dpop().add(stack.dpop()));
226
case InstructionConstants.OP_ISUB:
227
stack.push(stack.ipop().subtractFrom(stack.ipop()));
230
case InstructionConstants.OP_LSUB:
231
stack.push(stack.lpop().subtractFrom(stack.lpop()));
234
case InstructionConstants.OP_FSUB:
235
stack.push(stack.fpop().subtractFrom(stack.fpop()));
238
case InstructionConstants.OP_DSUB:
239
stack.push(stack.dpop().subtractFrom(stack.dpop()));
242
case InstructionConstants.OP_IMUL:
243
stack.push(stack.ipop().multiply(stack.ipop()));
246
case InstructionConstants.OP_LMUL:
247
stack.push(stack.lpop().multiply(stack.lpop()));
250
case InstructionConstants.OP_FMUL:
251
stack.push(stack.fpop().multiply(stack.fpop()));
254
case InstructionConstants.OP_DMUL:
255
stack.push(stack.dpop().multiply(stack.dpop()));
258
case InstructionConstants.OP_IDIV:
261
stack.push(stack.ipop().divideOf(stack.ipop()));
263
catch (ArithmeticException ex)
265
stack.push(IntegerValueFactory.create());
266
// TODO: Forward ArithmeticExceptions.
268
//stack.push(ReferenceValueFactory.create(false));
269
//branchUnit.throwException();
273
case InstructionConstants.OP_LDIV:
274
stack.push(stack.lpop().divideOf(stack.lpop()));
277
case InstructionConstants.OP_FDIV:
278
stack.push(stack.fpop().divideOf(stack.fpop()));
281
case InstructionConstants.OP_DDIV:
282
stack.push(stack.dpop().divideOf(stack.dpop()));
285
case InstructionConstants.OP_IREM:
288
stack.push(stack.ipop().remainderOf(stack.ipop()));
290
catch (ArithmeticException ex)
292
stack.push(IntegerValueFactory.create());
293
// TODO: Forward ArithmeticExceptions.
295
//stack.push(ReferenceValueFactory.create(false));
296
//branchUnit.throwException();
300
case InstructionConstants.OP_LREM:
301
stack.push(stack.lpop().remainderOf(stack.lpop()));
304
case InstructionConstants.OP_FREM:
305
stack.push(stack.fpop().remainderOf(stack.fpop()));
308
case InstructionConstants.OP_DREM:
309
stack.push(stack.dpop().remainderOf(stack.dpop()));
312
case InstructionConstants.OP_INEG:
313
stack.push(stack.ipop().negate());
316
case InstructionConstants.OP_LNEG:
317
stack.push(stack.lpop().negate());
320
case InstructionConstants.OP_FNEG:
321
stack.push(stack.fpop().negate());
324
case InstructionConstants.OP_DNEG:
325
stack.push(stack.dpop().negate());
328
case InstructionConstants.OP_ISHL:
329
stack.push(stack.ipop().shiftLeftOf(stack.ipop()));
332
case InstructionConstants.OP_LSHL:
333
stack.push(stack.ipop().shiftLeftOf(stack.lpop()));
336
case InstructionConstants.OP_ISHR:
337
stack.push(stack.ipop().shiftRightOf(stack.ipop()));
340
case InstructionConstants.OP_LSHR:
341
stack.push(stack.ipop().shiftRightOf(stack.lpop()));
344
case InstructionConstants.OP_IUSHR:
345
stack.push(stack.ipop().unsignedShiftRightOf(stack.ipop()));
348
case InstructionConstants.OP_LUSHR:
349
stack.push(stack.ipop().unsignedShiftRightOf(stack.lpop()));
352
case InstructionConstants.OP_IAND:
353
stack.push(stack.ipop().and(stack.ipop()));
356
case InstructionConstants.OP_LAND:
357
stack.push(stack.lpop().and(stack.lpop()));
360
case InstructionConstants.OP_IOR:
361
stack.push(stack.ipop().or(stack.ipop()));
364
case InstructionConstants.OP_LOR:
365
stack.push(stack.lpop().or(stack.lpop()));
368
case InstructionConstants.OP_IXOR:
369
stack.push(stack.ipop().xor(stack.ipop()));
372
case InstructionConstants.OP_LXOR:
373
stack.push(stack.lpop().xor(stack.lpop()));
376
case InstructionConstants.OP_I2L:
377
stack.push(stack.ipop().convertToLong());
380
case InstructionConstants.OP_I2F:
381
stack.push(stack.ipop().convertToFloat());
384
case InstructionConstants.OP_I2D:
385
stack.push(stack.ipop().convertToDouble());
388
case InstructionConstants.OP_L2I:
389
stack.push(stack.lpop().convertToInteger());
392
case InstructionConstants.OP_L2F:
393
stack.push(stack.lpop().convertToFloat());
396
case InstructionConstants.OP_L2D:
397
stack.push(stack.lpop().convertToDouble());
400
case InstructionConstants.OP_F2I:
401
stack.push(stack.fpop().convertToInteger());
404
case InstructionConstants.OP_F2L:
405
stack.push(stack.fpop().convertToLong());
408
case InstructionConstants.OP_F2D:
409
stack.push(stack.fpop().convertToDouble());
412
case InstructionConstants.OP_D2I:
413
stack.push(stack.dpop().convertToInteger());
416
case InstructionConstants.OP_D2L:
417
stack.push(stack.dpop().convertToLong());
420
case InstructionConstants.OP_D2F:
421
stack.push(stack.dpop().convertToFloat());
424
case InstructionConstants.OP_I2B:
425
stack.push(stack.ipop().convertToByte());
428
case InstructionConstants.OP_I2C:
429
stack.push(stack.ipop().convertToCharacter());
432
case InstructionConstants.OP_I2S:
433
stack.push(stack.ipop().convertToShort());
436
case InstructionConstants.OP_LCMP:
437
stack.push(stack.lpop().compareReverse(stack.lpop()));
440
case InstructionConstants.OP_FCMPL:
441
FloatValue floatValue1 = stack.fpop();
442
FloatValue floatValue2 = stack.fpop();
443
stack.push(floatValue2.compare(floatValue1));
446
case InstructionConstants.OP_FCMPG:
447
stack.push(stack.fpop().compareReverse(stack.fpop()));
450
case InstructionConstants.OP_DCMPL:
451
DoubleValue doubleValue1 = stack.dpop();
452
DoubleValue doubleValue2 = stack.dpop();
453
stack.push(doubleValue2.compare(doubleValue1));
456
case InstructionConstants.OP_DCMPG:
457
stack.push(stack.dpop().compareReverse(stack.dpop()));
460
case InstructionConstants.OP_IRETURN:
461
branchUnit.returnFromMethod(stack.ipop());
464
case InstructionConstants.OP_LRETURN:
465
branchUnit.returnFromMethod(stack.lpop());
468
case InstructionConstants.OP_FRETURN:
469
branchUnit.returnFromMethod(stack.fpop());
472
case InstructionConstants.OP_DRETURN:
473
branchUnit.returnFromMethod(stack.dpop());
476
case InstructionConstants.OP_ARETURN:
477
branchUnit.returnFromMethod(stack.apop());
480
case InstructionConstants.OP_RETURN:
481
branchUnit.returnFromMethod(null);
484
case InstructionConstants.OP_NEWARRAY:
486
stack.push(ReferenceValueFactory.create(false));
489
case InstructionConstants.OP_ARRAYLENGTH:
491
stack.push(IntegerValueFactory.create());
494
case InstructionConstants.OP_ATHROW:
495
ReferenceValue exceptionReferenceValue = stack.apop();
497
stack.push(exceptionReferenceValue);
498
branchUnit.throwException();
501
case InstructionConstants.OP_MONITORENTER:
502
case InstructionConstants.OP_MONITOREXIT:
507
throw new IllegalArgumentException("Unknown simple instruction ["+simpleInstruction.opcode+"]");
512
public void visitCpInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, CpInstruction cpInstruction)
514
int cpIndex = cpInstruction.cpIndex;
516
switch (cpInstruction.opcode)
518
case InstructionConstants.OP_LDC:
519
case InstructionConstants.OP_LDC_W:
520
case InstructionConstants.OP_LDC2_W:
521
case InstructionConstants.OP_GETSTATIC:
522
stack.push(cpValue(classFile, cpIndex));
525
case InstructionConstants.OP_PUTSTATIC:
529
case InstructionConstants.OP_GETFIELD:
531
stack.push(cpValue(classFile, cpIndex));
534
case InstructionConstants.OP_PUTFIELD:
539
case InstructionConstants.OP_INVOKEVIRTUAL:
540
case InstructionConstants.OP_INVOKESPECIAL:
541
case InstructionConstants.OP_INVOKESTATIC:
542
case InstructionConstants.OP_INVOKEINTERFACE:
543
Value cpValue = cpValue(classFile, cpIndex);
544
int parameterCount = parameterCount(classFile, cpIndex);
546
for (int counter = 0; counter < parameterCount; counter++)
550
if (cpInstruction.opcode != InstructionConstants.OP_INVOKESTATIC)
560
case InstructionConstants.OP_NEW:
561
stack.push(cpValue(classFile, cpIndex));
564
case InstructionConstants.OP_ANEWARRAY:
566
stack.push(ReferenceValueFactory.create(referencedClassFile(classFile, cpIndex),
571
case InstructionConstants.OP_CHECKCAST:
573
stack.push(stack.apop());
576
case InstructionConstants.OP_INSTANCEOF:
577
int instanceOf = stack.apop().instanceOf(referencedClassFile(classFile, cpIndex),
578
referencedTypeDimensionCount(classFile, cpIndex));
580
stack.push(instanceOf == Value.NEVER ? IntegerValueFactory.create(0) :
581
instanceOf == Value.ALWAYS ? IntegerValueFactory.create(1) :
582
IntegerValueFactory.create());
585
case InstructionConstants.OP_MULTIANEWARRAY:
586
int dimensionCount = cpInstruction.constant;
587
for (int dimension = 0; dimension < dimensionCount; dimension++)
591
stack.push(cpValue(classFile, cpIndex));
595
throw new IllegalArgumentException("Unknown constant pool instruction ["+cpInstruction.opcode+"]");
600
public void visitVariableInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, VariableInstruction variableInstruction)
602
int variableIndex = variableInstruction.variableIndex;
604
switch (variableInstruction.opcode)
606
case InstructionConstants.OP_ILOAD:
607
case InstructionConstants.OP_ILOAD_0:
608
case InstructionConstants.OP_ILOAD_1:
609
case InstructionConstants.OP_ILOAD_2:
610
case InstructionConstants.OP_ILOAD_3:
611
stack.push(variables.iload(variableIndex));
614
case InstructionConstants.OP_LLOAD:
615
case InstructionConstants.OP_LLOAD_0:
616
case InstructionConstants.OP_LLOAD_1:
617
case InstructionConstants.OP_LLOAD_2:
618
case InstructionConstants.OP_LLOAD_3:
619
stack.push(variables.lload(variableIndex));
622
case InstructionConstants.OP_FLOAD:
623
case InstructionConstants.OP_FLOAD_0:
624
case InstructionConstants.OP_FLOAD_1:
625
case InstructionConstants.OP_FLOAD_2:
626
case InstructionConstants.OP_FLOAD_3:
627
stack.push(variables.fload(variableIndex));
630
case InstructionConstants.OP_DLOAD:
631
case InstructionConstants.OP_DLOAD_0:
632
case InstructionConstants.OP_DLOAD_1:
633
case InstructionConstants.OP_DLOAD_2:
634
case InstructionConstants.OP_DLOAD_3:
635
stack.push(variables.dload(variableIndex));
638
case InstructionConstants.OP_ALOAD:
639
case InstructionConstants.OP_ALOAD_0:
640
case InstructionConstants.OP_ALOAD_1:
641
case InstructionConstants.OP_ALOAD_2:
642
case InstructionConstants.OP_ALOAD_3:
643
stack.push(variables.aload(variableIndex));
646
case InstructionConstants.OP_ISTORE:
647
case InstructionConstants.OP_ISTORE_0:
648
case InstructionConstants.OP_ISTORE_1:
649
case InstructionConstants.OP_ISTORE_2:
650
case InstructionConstants.OP_ISTORE_3:
651
variables.store(variableIndex, stack.ipop());
654
case InstructionConstants.OP_LSTORE:
655
case InstructionConstants.OP_LSTORE_0:
656
case InstructionConstants.OP_LSTORE_1:
657
case InstructionConstants.OP_LSTORE_2:
658
case InstructionConstants.OP_LSTORE_3:
659
variables.store(variableIndex, stack.lpop());
662
case InstructionConstants.OP_FSTORE:
663
case InstructionConstants.OP_FSTORE_0:
664
case InstructionConstants.OP_FSTORE_1:
665
case InstructionConstants.OP_FSTORE_2:
666
case InstructionConstants.OP_FSTORE_3:
667
variables.store(variableIndex, stack.fpop());
670
case InstructionConstants.OP_DSTORE:
671
case InstructionConstants.OP_DSTORE_0:
672
case InstructionConstants.OP_DSTORE_1:
673
case InstructionConstants.OP_DSTORE_2:
674
case InstructionConstants.OP_DSTORE_3:
675
variables.store(variableIndex, stack.dpop());
678
case InstructionConstants.OP_ASTORE:
679
case InstructionConstants.OP_ASTORE_0:
680
case InstructionConstants.OP_ASTORE_1:
681
case InstructionConstants.OP_ASTORE_2:
682
case InstructionConstants.OP_ASTORE_3:
683
// The operand on the stack can be a reference or a return
684
// address, so we'll relax the pop operation.
685
//variables.store(variableIndex, stack.apop());
686
variables.store(variableIndex, stack.pop());
689
case InstructionConstants.OP_IINC:
690
variables.store(variableIndex,
691
variables.iload(variableIndex).add(
692
IntegerValueFactory.create(variableInstruction.constant)));
695
case InstructionConstants.OP_RET:
696
// The return address should be in the last offset of the
697
// given instruction offset variable (even though there may
698
// be other offsets).
699
InstructionOffsetValue instructionOffsetValue = variables.oload(variableIndex);
700
branchUnit.branch(classFile,
703
instructionOffsetValue.instructionOffset(instructionOffsetValue.instructionOffsetCount()-1));
707
throw new IllegalArgumentException("Unknown variable instruction ["+variableInstruction.opcode+"]");
712
public void visitBranchInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, BranchInstruction branchInstruction)
714
int branchTarget = offset + branchInstruction.branchOffset;
716
switch (branchInstruction.opcode)
718
case InstructionConstants.OP_IFEQ:
719
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
720
stack.ipop().equal(IntegerValueFactory.create(0)));
723
case InstructionConstants.OP_IFNE:
724
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
725
stack.ipop().notEqual(IntegerValueFactory.create(0)));
728
case InstructionConstants.OP_IFLT:
729
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
730
stack.ipop().lessThan(IntegerValueFactory.create(0)));
733
case InstructionConstants.OP_IFGE:
734
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
735
stack.ipop().greaterThanOrEqual(IntegerValueFactory.create(0)));
738
case InstructionConstants.OP_IFGT:
739
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
740
stack.ipop().greaterThan(IntegerValueFactory.create(0)));
743
case InstructionConstants.OP_IFLE:
744
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
745
stack.ipop().lessThanOrEqual(IntegerValueFactory.create(0)));
749
case InstructionConstants.OP_IFICMPEQ:
750
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
751
stack.ipop().equal(stack.ipop()));
754
case InstructionConstants.OP_IFICMPNE:
755
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
756
stack.ipop().notEqual(stack.ipop()));
760
case InstructionConstants.OP_IFICMPLT:
761
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
762
-stack.ipop().lessThan(stack.ipop()));
765
case InstructionConstants.OP_IFICMPGE:
766
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
767
-stack.ipop().greaterThanOrEqual(stack.ipop()));
770
case InstructionConstants.OP_IFICMPGT:
771
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
772
-stack.ipop().greaterThan(stack.ipop()));
775
case InstructionConstants.OP_IFICMPLE:
776
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
777
-stack.ipop().lessThanOrEqual(stack.ipop()));
780
case InstructionConstants.OP_IFACMPEQ:
781
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
782
stack.apop().equal(stack.apop()));
785
case InstructionConstants.OP_IFACMPNE:
786
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
787
stack.apop().notEqual(stack.apop()));
790
case InstructionConstants.OP_GOTO:
791
case InstructionConstants.OP_GOTO_W:
792
branchUnit.branch(classFile, codeAttrInfo, offset, branchTarget);
796
case InstructionConstants.OP_JSR:
797
case InstructionConstants.OP_JSR_W:
798
stack.push(InstructionOffsetValueFactory.create(offset +
799
branchInstruction.length(offset)));
800
branchUnit.branch(classFile, codeAttrInfo, offset, branchTarget);
803
case InstructionConstants.OP_IFNULL:
804
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
805
stack.apop().isNull());
808
case InstructionConstants.OP_IFNONNULL:
809
branchUnit.branchConditionally(classFile, codeAttrInfo, offset, branchTarget,
810
stack.apop().isNotNull());
814
throw new IllegalArgumentException("Unknown branch instruction ["+branchInstruction.opcode+"]");
819
public void visitTableSwitchInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, TableSwitchInstruction tableSwitchInstruction)
821
IntegerValue indexValue = stack.ipop();
823
// If there is no definite branch in any of the cases below,
824
// branch to the default offset.
825
branchUnit.branch(classFile, codeAttrInfo,
827
offset + tableSwitchInstruction.defaultOffset);
829
for (int index = 0; index < tableSwitchInstruction.jumpOffsetCount; index++)
831
int conditional = indexValue.equal(IntegerValueFactory.create(
832
tableSwitchInstruction.lowCase + index));
833
branchUnit.branchConditionally(classFile, codeAttrInfo,
835
offset + tableSwitchInstruction.jumpOffsets[index],
838
// If this branch is always taken, we can skip the rest.
839
if (conditional == Value.ALWAYS)
847
public void visitLookUpSwitchInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
849
IntegerValue indexValue = stack.ipop();
851
// If there is no definite branch in any of the cases below,
852
// branch to the default offset.
853
branchUnit.branch(classFile, codeAttrInfo,
855
offset + lookUpSwitchInstruction.defaultOffset);
857
for (int index = 0; index < lookUpSwitchInstruction.jumpOffsetCount; index++)
859
int conditional = indexValue.equal(IntegerValueFactory.create(
860
lookUpSwitchInstruction.cases[index]));
861
branchUnit.branchConditionally(classFile, codeAttrInfo,
863
offset + lookUpSwitchInstruction.jumpOffsets[index],
866
// If this branch is always taken, we can skip the rest.
867
if (conditional == Value.ALWAYS)
875
// Implementations for CpInfoVisitor.
877
public void visitUtf8CpInfo(ClassFile classFile, Utf8CpInfo utf8CpInfo) {}
878
public void visitNameAndTypeCpInfo(ClassFile classFile, NameAndTypeCpInfo nameAndTypeCpInfo) {}
881
public void visitIntegerCpInfo(ClassFile classFile, IntegerCpInfo integerCpInfo)
883
cpValue = IntegerValueFactory.create(integerCpInfo.getValue());
886
public void visitLongCpInfo(ClassFile classFile, LongCpInfo longCpInfo)
888
cpValue = LongValueFactory.create(longCpInfo.getValue());
891
public void visitFloatCpInfo(ClassFile classFile, FloatCpInfo floatCpInfo)
893
cpValue = FloatValueFactory.create(floatCpInfo.getValue());
896
public void visitDoubleCpInfo(ClassFile classFile, DoubleCpInfo doubleCpInfo)
898
cpValue = DoubleValueFactory.create(doubleCpInfo.getValue());
901
public void visitStringCpInfo(ClassFile classFile, StringCpInfo stringCpInfo)
903
cpValue = ReferenceValueFactory.create(false);
906
public void visitFieldrefCpInfo(ClassFile classFile, FieldrefCpInfo fieldrefCpInfo)
908
cpValue = ValueFactory.create(fieldrefCpInfo.getType(classFile));
911
public void visitInterfaceMethodrefCpInfo(ClassFile classFile, InterfaceMethodrefCpInfo interfaceMethodrefCpInfo)
913
visitRefCpInfo(classFile, interfaceMethodrefCpInfo);
916
public void visitMethodrefCpInfo(ClassFile classFile, MethodrefCpInfo methodrefCpInfo)
918
visitRefCpInfo(classFile, methodrefCpInfo);
921
private void visitRefCpInfo(ClassFile classFile, RefCpInfo methodrefCpInfo)
923
String type = methodrefCpInfo.getType(classFile);
925
parameterCount = ClassUtil.internalMethodParameterCount(type);
926
cpValue = ValueFactory.create(ClassUtil.internalMethodReturnType(type));
929
public void visitClassCpInfo(ClassFile classFile, ClassCpInfo classCpInfo)
931
String className = classCpInfo.getName(classFile);
933
referencedClassFile = classCpInfo.referencedClassFile;
934
referencedTypeDimensionCount = ClassUtil.internalArrayTypeDimensionCount(className);
936
cpValue = ReferenceValueFactory.create(referencedClassFile,
937
referencedTypeDimensionCount,
942
// Small utility methods.
945
* Returns the Value of the constant pool element at the given index.
946
* The element can be a constant, a field, a method,...
948
private Value cpValue(ClassFile classFile, int cpIndex)
950
// Visit the constant pool entry to get its return value.
951
classFile.constantPoolEntryAccept(cpIndex, this);
958
* Returns the class file referenced by the class constant pool entry at the
961
private ClassFile referencedClassFile(ClassFile classFile, int cpIndex)
963
// Visit the constant pool entry to get its referenced class file.
964
classFile.constantPoolEntryAccept(cpIndex, this);
966
return referencedClassFile;
971
* Returns the dimensionality of the class constant pool entry at the given
974
private int referencedTypeDimensionCount(ClassFile classFile, int cpIndex)
976
// Visit the constant pool entry to get its referenced class file.
977
//classFile.constantPoolEntryAccept(this, cpIndex);
979
// We'll return the value that was just computed.
980
return referencedTypeDimensionCount;
985
* Returns the number of parameters of the method reference at the given
986
* constant pool index. This method must be invoked right after the
987
* cpValue(ClassFile,int) method.
989
private int parameterCount(ClassFile classFile, int methodRefCpIndex)
991
// Visit the method ref constant pool entry to get its parameter count.
992
//classFile.constantPoolEntryAccept(this, methodRefCpIndex);
994
// We'll return the value that was just computed.
995
return parameterCount;