KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > evaluation > Processor


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
6  *
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)
10  * any later version.
11  *
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
15  * more details.
16  *
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
20  */

21 package proguard.evaluation;
22
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.CodeAttribute;
25 import proguard.classfile.constant.*;
26 import proguard.classfile.constant.visitor.ConstantVisitor;
27 import proguard.classfile.instruction.*;
28 import proguard.classfile.instruction.visitor.InstructionVisitor;
29 import proguard.classfile.util.*;
30 import proguard.evaluation.value.*;
31
32 /**
33  * This InstructionVisitor executes the instructions that it visits on a given
34  * local variable frame and stack.
35  *
36  * @author Eric Lafortune
37  */

38 public class Processor
39 extends SimplifiedVisitor
40 implements InstructionVisitor,
41              ConstantVisitor
42 {
43     private Variables variables;
44     private Stack stack;
45     private ValueFactory valueFactory;
46     private BranchUnit branchUnit;
47     private InvocationUnit invocationUnit;
48
49     // Fields acting as parameters for the ConstantVisitor methods.
50
private boolean handleClassConstantAsClassValue;
51     private Value cpValue;
52
53
54     /**
55      * Creates a new processor that operates on the given environment.
56      * @param variables the local variable frame.
57      * @param stack the local stack.
58      * @param branchUnit the class that can affect the program counter.
59      * @param invocationUnit the class that can access other program members.
60      */

61     public Processor(Variables variables,
62                      Stack stack,
63                      ValueFactory valueFactory,
64                      BranchUnit branchUnit,
65                      InvocationUnit invocationUnit)
66     {
67         this.variables = variables;
68         this.stack = stack;
69         this.valueFactory = valueFactory;
70         this.branchUnit = branchUnit;
71         this.invocationUnit = invocationUnit;
72     }
73
74
75     // Implementations for InstructionVisitor.
76

77     public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
78     {
79         switch (simpleInstruction.opcode)
80         {
81             case InstructionConstants.OP_NOP:
82                 break;
83
84             case InstructionConstants.OP_ACONST_NULL:
85                 stack.push(valueFactory.createReferenceValueNull());
86                 break;
87
88             case InstructionConstants.OP_ICONST_M1:
89             case InstructionConstants.OP_ICONST_0:
90             case InstructionConstants.OP_ICONST_1:
91             case InstructionConstants.OP_ICONST_2:
92             case InstructionConstants.OP_ICONST_3:
93             case InstructionConstants.OP_ICONST_4:
94             case InstructionConstants.OP_ICONST_5:
95             case InstructionConstants.OP_BIPUSH:
96             case InstructionConstants.OP_SIPUSH:
97                 stack.push(valueFactory.createIntegerValue(simpleInstruction.constant));
98                 break;
99
100             case InstructionConstants.OP_LCONST_0:
101             case InstructionConstants.OP_LCONST_1:
102                 stack.push(valueFactory.createLongValue(simpleInstruction.constant));
103                 break;
104
105             case InstructionConstants.OP_FCONST_0:
106             case InstructionConstants.OP_FCONST_1:
107             case InstructionConstants.OP_FCONST_2:
108                 stack.push(valueFactory.createFloatValue((float)simpleInstruction.constant));
109                 break;
110
111             case InstructionConstants.OP_DCONST_0:
112             case InstructionConstants.OP_DCONST_1:
113                 stack.push(valueFactory.createDoubleValue((double)simpleInstruction.constant));
114                 break;
115
116             case InstructionConstants.OP_IALOAD:
117             case InstructionConstants.OP_BALOAD:
118             case InstructionConstants.OP_CALOAD:
119             case InstructionConstants.OP_SALOAD:
120                 stack.ipop();
121                 stack.apop();
122                 stack.push(valueFactory.createIntegerValue());
123                 break;
124
125             case InstructionConstants.OP_LALOAD:
126                 stack.ipop();
127                 stack.apop();
128                 stack.push(valueFactory.createLongValue());
129                 break;
130
131             case InstructionConstants.OP_FALOAD:
132                 stack.ipop();
133                 stack.apop();
134                 stack.push(valueFactory.createFloatValue());
135                 break;
136
137             case InstructionConstants.OP_DALOAD:
138                 stack.ipop();
139                 stack.apop();
140                 stack.push(valueFactory.createDoubleValue());
141                 break;
142
143             case InstructionConstants.OP_AALOAD:
144             {
145                 IntegerValue arrayIndex = stack.ipop();
146                 ReferenceValue arrayReference = stack.apop();
147                 stack.push(arrayReference.arrayLoad(arrayIndex, valueFactory));
148                 break;
149             }
150
151             case InstructionConstants.OP_IASTORE:
152             case InstructionConstants.OP_BASTORE:
153             case InstructionConstants.OP_CASTORE:
154             case InstructionConstants.OP_SASTORE:
155                 stack.ipop();
156                 stack.ipop();
157                 stack.apop();
158                 break;
159
160             case InstructionConstants.OP_LASTORE:
161                 stack.lpop();
162                 stack.ipop();
163                 stack.apop();
164                 break;
165
166             case InstructionConstants.OP_FASTORE:
167                 stack.fpop();
168                 stack.ipop();
169                 stack.apop();
170                 break;
171
172             case InstructionConstants.OP_DASTORE:
173                 stack.dpop();
174                 stack.ipop();
175                 stack.apop();
176                 break;
177
178             case InstructionConstants.OP_AASTORE:
179                 stack.apop();
180                 stack.ipop();
181                 stack.apop();
182                 break;
183
184             case InstructionConstants.OP_POP:
185                 stack.pop1();
186                 break;
187
188             case InstructionConstants.OP_POP2:
189                 stack.pop2();
190                 break;
191
192             case InstructionConstants.OP_DUP:
193                 stack.dup();
194                 break;
195
196             case InstructionConstants.OP_DUP_X1:
197                 stack.dup_x1();
198                 break;
199
200             case InstructionConstants.OP_DUP_X2:
201                 stack.dup_x2();
202                 break;
203
204             case InstructionConstants.OP_DUP2:
205                 stack.dup2();
206                 break;
207
208             case InstructionConstants.OP_DUP2_X1:
209                 stack.dup2_x1();
210                 break;
211
212             case InstructionConstants.OP_DUP2_X2:
213                 stack.dup2_x2();
214                 break;
215
216             case InstructionConstants.OP_SWAP:
217                 stack.swap();
218                 break;
219
220             case InstructionConstants.OP_IADD:
221                 stack.push(stack.ipop().add(stack.ipop()));
222                 break;
223
224             case InstructionConstants.OP_LADD:
225                 stack.push(stack.lpop().add(stack.lpop()));
226                 break;
227
228             case InstructionConstants.OP_FADD:
229                 stack.push(stack.fpop().add(stack.fpop()));
230                 break;
231
232             case InstructionConstants.OP_DADD:
233                 stack.push(stack.dpop().add(stack.dpop()));
234                 break;
235
236             case InstructionConstants.OP_ISUB:
237                 stack.push(stack.ipop().subtractFrom(stack.ipop()));
238                 break;
239
240             case InstructionConstants.OP_LSUB:
241                 stack.push(stack.lpop().subtractFrom(stack.lpop()));
242                 break;
243
244             case InstructionConstants.OP_FSUB:
245                 stack.push(stack.fpop().subtractFrom(stack.fpop()));
246                 break;
247
248             case InstructionConstants.OP_DSUB:
249                 stack.push(stack.dpop().subtractFrom(stack.dpop()));
250                 break;
251
252             case InstructionConstants.OP_IMUL:
253                 stack.push(stack.ipop().multiply(stack.ipop()));
254                 break;
255
256             case InstructionConstants.OP_LMUL:
257                 stack.push(stack.lpop().multiply(stack.lpop()));
258                 break;
259
260             case InstructionConstants.OP_FMUL:
261                 stack.push(stack.fpop().multiply(stack.fpop()));
262                 break;
263
264             case InstructionConstants.OP_DMUL:
265                 stack.push(stack.dpop().multiply(stack.dpop()));
266                 break;
267
268             case InstructionConstants.OP_IDIV:
269                 try
270                 {
271                     stack.push(stack.ipop().divideOf(stack.ipop()));
272                 }
273                 catch (ArithmeticException JavaDoc ex)
274                 {
275                     stack.push(valueFactory.createIntegerValue());
276                     // TODO: Forward ArithmeticExceptions.
277
//stack.clear();
278
//stack.push(valueFactory.createReference(false));
279
//branchUnit.throwException();
280
}
281                 break;
282
283             case InstructionConstants.OP_LDIV:
284                 try
285                 {
286                     stack.push(stack.lpop().divideOf(stack.lpop()));
287                 }
288                 catch (ArithmeticException JavaDoc ex)
289                 {
290                     stack.push(valueFactory.createLongValue());
291                     // TODO: Forward ArithmeticExceptions.
292
//stack.clear();
293
//stack.push(valueFactory.createReference(false));
294
//branchUnit.throwException();
295
}
296                 break;
297
298             case InstructionConstants.OP_FDIV:
299                 stack.push(stack.fpop().divideOf(stack.fpop()));
300                 break;
301
302             case InstructionConstants.OP_DDIV:
303                 stack.push(stack.dpop().divideOf(stack.dpop()));
304                 break;
305
306             case InstructionConstants.OP_IREM:
307                 try
308                 {
309                     stack.push(stack.ipop().remainderOf(stack.ipop()));
310                 }
311                 catch (ArithmeticException JavaDoc ex)
312                 {
313                     stack.push(valueFactory.createIntegerValue());
314                     // TODO: Forward ArithmeticExceptions.
315
//stack.clear();
316
//stack.push(valueFactory.createReference(false));
317
//branchUnit.throwException();
318
}
319                 break;
320
321             case InstructionConstants.OP_LREM:
322                 try
323                 {
324                     stack.push(stack.lpop().remainderOf(stack.lpop()));
325                 }
326                 catch (ArithmeticException JavaDoc ex)
327                 {
328                     stack.push(valueFactory.createLongValue());
329                     // TODO: Forward ArithmeticExceptions.
330
//stack.clear();
331
//stack.push(valueFactory.createReference(false));
332
//branchUnit.throwException();
333
}
334                 break;
335
336             case InstructionConstants.OP_FREM:
337                 stack.push(stack.fpop().remainderOf(stack.fpop()));
338                 break;
339
340             case InstructionConstants.OP_DREM:
341                 stack.push(stack.dpop().remainderOf(stack.dpop()));
342                 break;
343
344             case InstructionConstants.OP_INEG:
345                 stack.push(stack.ipop().negate());
346                 break;
347
348             case InstructionConstants.OP_LNEG:
349                 stack.push(stack.lpop().negate());
350                 break;
351
352             case InstructionConstants.OP_FNEG:
353                 stack.push(stack.fpop().negate());
354                 break;
355
356             case InstructionConstants.OP_DNEG:
357                 stack.push(stack.dpop().negate());
358                 break;
359
360             case InstructionConstants.OP_ISHL:
361                 stack.push(stack.ipop().shiftLeftOf(stack.ipop()));
362                 break;
363
364             case InstructionConstants.OP_LSHL:
365                 stack.push(stack.ipop().shiftLeftOf(stack.lpop()));
366                 break;
367
368             case InstructionConstants.OP_ISHR:
369                 stack.push(stack.ipop().shiftRightOf(stack.ipop()));
370                 break;
371
372             case InstructionConstants.OP_LSHR:
373                 stack.push(stack.ipop().shiftRightOf(stack.lpop()));
374                 break;
375
376             case InstructionConstants.OP_IUSHR:
377                 stack.push(stack.ipop().unsignedShiftRightOf(stack.ipop()));
378                 break;
379
380             case InstructionConstants.OP_LUSHR:
381                 stack.push(stack.ipop().unsignedShiftRightOf(stack.lpop()));
382                 break;
383
384             case InstructionConstants.OP_IAND:
385                 stack.push(stack.ipop().and(stack.ipop()));
386                 break;
387
388             case InstructionConstants.OP_LAND:
389                 stack.push(stack.lpop().and(stack.lpop()));
390                 break;
391
392             case InstructionConstants.OP_IOR:
393                 stack.push(stack.ipop().or(stack.ipop()));
394                 break;
395
396             case InstructionConstants.OP_LOR:
397                 stack.push(stack.lpop().or(stack.lpop()));
398                 break;
399
400             case InstructionConstants.OP_IXOR:
401                 stack.push(stack.ipop().xor(stack.ipop()));
402                 break;
403
404             case InstructionConstants.OP_LXOR:
405                 stack.push(stack.lpop().xor(stack.lpop()));
406                 break;
407
408             case InstructionConstants.OP_I2L:
409                 stack.push(stack.ipop().convertToLong(valueFactory));
410                 break;
411
412             case InstructionConstants.OP_I2F:
413                 stack.push(stack.ipop().convertToFloat(valueFactory));
414                 break;
415
416             case InstructionConstants.OP_I2D:
417                 stack.push(stack.ipop().convertToDouble(valueFactory));
418                 break;
419
420             case InstructionConstants.OP_L2I:
421                 stack.push(stack.lpop().convertToInteger(valueFactory));
422                 break;
423
424             case InstructionConstants.OP_L2F:
425                 stack.push(stack.lpop().convertToFloat(valueFactory));
426                 break;
427
428             case InstructionConstants.OP_L2D:
429                 stack.push(stack.lpop().convertToDouble(valueFactory));
430                 break;
431
432             case InstructionConstants.OP_F2I:
433                 stack.push(stack.fpop().convertToInteger(valueFactory));
434                 break;
435
436             case InstructionConstants.OP_F2L:
437                 stack.push(stack.fpop().convertToLong(valueFactory));
438                 break;
439
440             case InstructionConstants.OP_F2D:
441                 stack.push(stack.fpop().convertToDouble(valueFactory));
442                 break;
443
444             case InstructionConstants.OP_D2I:
445                 stack.push(stack.dpop().convertToInteger(valueFactory));
446                 break;
447
448             case InstructionConstants.OP_D2L:
449                 stack.push(stack.dpop().convertToLong(valueFactory));
450                 break;
451
452             case InstructionConstants.OP_D2F:
453                 stack.push(stack.dpop().convertToFloat(valueFactory));
454                 break;
455
456             case InstructionConstants.OP_I2B:
457                 stack.push(stack.ipop().convertToByte(valueFactory));
458                 break;
459
460             case InstructionConstants.OP_I2C:
461                 stack.push(stack.ipop().convertToCharacter(valueFactory));
462                 break;
463
464             case InstructionConstants.OP_I2S:
465                 stack.push(stack.ipop().convertToShort(valueFactory));
466                 break;
467
468             case InstructionConstants.OP_LCMP:
469 // stack.push(stack.lpop().compareReverse(stack.lpop()));
470

471                 LongValue longValue1 = stack.lpop();
472                 LongValue longValue2 = stack.lpop();
473                 stack.push(longValue2.compare(longValue1, valueFactory));
474                 break;
475
476             case InstructionConstants.OP_FCMPL:
477                 FloatValue floatValue1 = stack.fpop();
478                 FloatValue floatValue2 = stack.fpop();
479                 stack.push(floatValue2.compare(floatValue1, valueFactory));
480                 break;
481
482             case InstructionConstants.OP_FCMPG:
483                 stack.push(stack.fpop().compareReverse(stack.fpop(), valueFactory));
484                 break;
485
486             case InstructionConstants.OP_DCMPL:
487                 DoubleValue doubleValue1 = stack.dpop();
488                 DoubleValue doubleValue2 = stack.dpop();
489                 stack.push(doubleValue2.compare(doubleValue1, valueFactory));
490                 break;
491
492             case InstructionConstants.OP_DCMPG:
493                 stack.push(stack.dpop().compareReverse(stack.dpop(), valueFactory));
494                 break;
495
496             case InstructionConstants.OP_IRETURN:
497                 invocationUnit.exitMethod(clazz, method, stack.ipop());
498                 branchUnit.returnFromMethod();
499                 break;
500
501             case InstructionConstants.OP_LRETURN:
502                 invocationUnit.exitMethod(clazz, method, stack.lpop());
503                 branchUnit.returnFromMethod();
504                 break;
505
506             case InstructionConstants.OP_FRETURN:
507                 invocationUnit.exitMethod(clazz, method, stack.fpop());
508                 branchUnit.returnFromMethod();
509                 break;
510
511             case InstructionConstants.OP_DRETURN:
512                 invocationUnit.exitMethod(clazz, method, stack.dpop());
513                 branchUnit.returnFromMethod();
514                 break;
515
516             case InstructionConstants.OP_ARETURN:
517                 invocationUnit.exitMethod(clazz, method, stack.apop());
518                 branchUnit.returnFromMethod();
519                 break;
520
521             case InstructionConstants.OP_RETURN:
522                 branchUnit.returnFromMethod();
523                 break;
524
525             case InstructionConstants.OP_NEWARRAY:
526                 IntegerValue arrayLength = stack.ipop();
527                 stack.push(valueFactory.createArrayReferenceValue(String.valueOf(InstructionUtil.internalTypeFromArrayType((byte)simpleInstruction.constant)),
528                                                                   null,
529                                                                   arrayLength));
530                 break;
531
532             case InstructionConstants.OP_ARRAYLENGTH:
533                 stack.apop();
534                 stack.push(valueFactory.createIntegerValue());
535                 break;
536
537             case InstructionConstants.OP_ATHROW:
538                 ReferenceValue exceptionReferenceValue = stack.apop();
539                 stack.clear();
540                 stack.push(exceptionReferenceValue);
541                 branchUnit.throwException();
542                 break;
543
544             case InstructionConstants.OP_MONITORENTER:
545             case InstructionConstants.OP_MONITOREXIT:
546                 stack.apop();
547                 break;
548
549             default:
550                 throw new IllegalArgumentException JavaDoc("Unknown simple instruction ["+simpleInstruction.opcode+"]");
551         }
552     }
553
554
555     public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
556     {
557         int constantIndex = constantInstruction.constantIndex;
558
559         switch (constantInstruction.opcode)
560         {
561             case InstructionConstants.OP_LDC:
562             case InstructionConstants.OP_LDC_W:
563             case InstructionConstants.OP_LDC2_W:
564                 stack.push(cpValue(clazz, constantIndex, true));
565                 break;
566
567             case InstructionConstants.OP_GETSTATIC:
568             case InstructionConstants.OP_PUTSTATIC:
569             case InstructionConstants.OP_GETFIELD:
570             case InstructionConstants.OP_PUTFIELD:
571             case InstructionConstants.OP_INVOKEVIRTUAL:
572             case InstructionConstants.OP_INVOKESPECIAL:
573             case InstructionConstants.OP_INVOKESTATIC:
574             case InstructionConstants.OP_INVOKEINTERFACE:
575                 invocationUnit.invokeMember(clazz, method, codeAttribute, offset, constantInstruction, stack);
576                 break;
577
578             case InstructionConstants.OP_NEW:
579                 stack.push(cpValue(clazz, constantIndex).referenceValue());
580                 break;
581
582             case InstructionConstants.OP_ANEWARRAY:
583             {
584                 ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue();
585
586                 stack.push(valueFactory.createArrayReferenceValue(referenceValue.internalType(),
587                                                                   referenceValue.getReferencedClass(),
588                                                                   stack.ipop()));
589                 break;
590             }
591
592             case InstructionConstants.OP_CHECKCAST:
593                 // TODO: Check cast.
594
ReferenceValue castValue = stack.apop();
595                 ReferenceValue castResultValue =
596                     castValue.isNull() == Value.ALWAYS ? castValue :
597                     castValue.isNull() == Value.NEVER ? cpValue(clazz, constantIndex).referenceValue() :
598                                                          cpValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
599                 stack.push(castResultValue);
600                 break;
601
602             case InstructionConstants.OP_INSTANCEOF:
603             {
604                 ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue();
605
606                 int instanceOf = stack.apop().instanceOf(referenceValue.getType(),
607                                                          referenceValue.getReferencedClass());
608
609                 stack.push(instanceOf == Value.NEVER ? valueFactory.createIntegerValue(0) :
610                            instanceOf == Value.ALWAYS ? valueFactory.createIntegerValue(1) :
611                                                         valueFactory.createIntegerValue());
612                 break;
613             }
614
615             case InstructionConstants.OP_MULTIANEWARRAY:
616             {
617                 int dimensionCount = constantInstruction.constant;
618                 for (int dimension = 0; dimension < dimensionCount; dimension++)
619                 {
620                     // TODO: Use array lengths.
621
IntegerValue arrayLength = stack.ipop();
622                 }
623
624                 stack.push(cpValue(clazz, constantIndex).referenceValue());
625                 break;
626             }
627
628             default:
629                 throw new IllegalArgumentException JavaDoc("Unknown constant pool instruction ["+constantInstruction.opcode+"]");
630         }
631     }
632
633
634     public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
635     {
636         int variableIndex = variableInstruction.variableIndex;
637
638         switch (variableInstruction.opcode)
639         {
640             case InstructionConstants.OP_ILOAD:
641             case InstructionConstants.OP_ILOAD_0:
642             case InstructionConstants.OP_ILOAD_1:
643             case InstructionConstants.OP_ILOAD_2:
644             case InstructionConstants.OP_ILOAD_3:
645                 stack.push(variables.iload(variableIndex));
646                 break;
647
648             case InstructionConstants.OP_LLOAD:
649             case InstructionConstants.OP_LLOAD_0:
650             case InstructionConstants.OP_LLOAD_1:
651             case InstructionConstants.OP_LLOAD_2:
652             case InstructionConstants.OP_LLOAD_3:
653                 stack.push(variables.lload(variableIndex));
654                 break;
655
656             case InstructionConstants.OP_FLOAD:
657             case InstructionConstants.OP_FLOAD_0:
658             case InstructionConstants.OP_FLOAD_1:
659             case InstructionConstants.OP_FLOAD_2:
660             case InstructionConstants.OP_FLOAD_3:
661                 stack.push(variables.fload(variableIndex));
662                 break;
663
664             case InstructionConstants.OP_DLOAD:
665             case InstructionConstants.OP_DLOAD_0:
666             case InstructionConstants.OP_DLOAD_1:
667             case InstructionConstants.OP_DLOAD_2:
668             case InstructionConstants.OP_DLOAD_3:
669                 stack.push(variables.dload(variableIndex));
670                 break;
671
672             case InstructionConstants.OP_ALOAD:
673             case InstructionConstants.OP_ALOAD_0:
674             case InstructionConstants.OP_ALOAD_1:
675             case InstructionConstants.OP_ALOAD_2:
676             case InstructionConstants.OP_ALOAD_3:
677                 stack.push(variables.aload(variableIndex));
678                 break;
679
680             case InstructionConstants.OP_ISTORE:
681             case InstructionConstants.OP_ISTORE_0:
682             case InstructionConstants.OP_ISTORE_1:
683             case InstructionConstants.OP_ISTORE_2:
684             case InstructionConstants.OP_ISTORE_3:
685                 variables.store(variableIndex, stack.ipop());
686                 break;
687
688             case InstructionConstants.OP_LSTORE:
689             case InstructionConstants.OP_LSTORE_0:
690             case InstructionConstants.OP_LSTORE_1:
691             case InstructionConstants.OP_LSTORE_2:
692             case InstructionConstants.OP_LSTORE_3:
693                 variables.store(variableIndex, stack.lpop());
694                 break;
695
696             case InstructionConstants.OP_FSTORE:
697             case InstructionConstants.OP_FSTORE_0:
698             case InstructionConstants.OP_FSTORE_1:
699             case InstructionConstants.OP_FSTORE_2:
700             case InstructionConstants.OP_FSTORE_3:
701                 variables.store(variableIndex, stack.fpop());
702                 break;
703
704             case InstructionConstants.OP_DSTORE:
705             case InstructionConstants.OP_DSTORE_0:
706             case InstructionConstants.OP_DSTORE_1:
707             case InstructionConstants.OP_DSTORE_2:
708             case InstructionConstants.OP_DSTORE_3:
709                 variables.store(variableIndex, stack.dpop());
710                 break;
711
712             case InstructionConstants.OP_ASTORE:
713             case InstructionConstants.OP_ASTORE_0:
714             case InstructionConstants.OP_ASTORE_1:
715             case InstructionConstants.OP_ASTORE_2:
716             case InstructionConstants.OP_ASTORE_3:
717                 // The operand on the stack can be a reference or a return
718
// address, so we'll relax the pop operation.
719
//variables.store(variableIndex, stack.apop());
720
variables.store(variableIndex, stack.pop());
721                 break;
722
723             case InstructionConstants.OP_IINC:
724                 variables.store(variableIndex,
725                                 variables.iload(variableIndex).add(
726                                 valueFactory.createIntegerValue(variableInstruction.constant)));
727                 break;
728
729             case InstructionConstants.OP_RET:
730                 // The return address should be in the last offset of the
731
// given instruction offset variable (even though there may
732
// be other offsets).
733
InstructionOffsetValue instructionOffsetValue = variables.oload(variableIndex);
734                 branchUnit.branch(clazz,
735                                   codeAttribute,
736                                   offset,
737                                   instructionOffsetValue.instructionOffset(instructionOffsetValue.instructionOffsetCount()-1));
738                 break;
739
740             default:
741                 throw new IllegalArgumentException JavaDoc("Unknown variable instruction ["+variableInstruction.opcode+"]");
742         }
743     }
744
745
746     public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
747     {
748         int branchTarget = offset + branchInstruction.branchOffset;
749
750         switch (branchInstruction.opcode)
751         {
752             case InstructionConstants.OP_IFEQ:
753                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
754                     stack.ipop().equal(valueFactory.createIntegerValue(0)));
755                 break;
756
757             case InstructionConstants.OP_IFNE:
758                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
759                     stack.ipop().notEqual(valueFactory.createIntegerValue(0)));
760                 break;
761
762             case InstructionConstants.OP_IFLT:
763                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
764                     stack.ipop().lessThan(valueFactory.createIntegerValue(0)));
765                 break;
766
767             case InstructionConstants.OP_IFGE:
768                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
769                     stack.ipop().greaterThanOrEqual(valueFactory.createIntegerValue(0)));
770                 break;
771
772             case InstructionConstants.OP_IFGT:
773                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
774                     stack.ipop().greaterThan(valueFactory.createIntegerValue(0)));
775                 break;
776
777             case InstructionConstants.OP_IFLE:
778                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
779                     stack.ipop().lessThanOrEqual(valueFactory.createIntegerValue(0)));
780                 break;
781
782
783             case InstructionConstants.OP_IFICMPEQ:
784                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
785                     stack.ipop().equal(stack.ipop()));
786                 break;
787
788             case InstructionConstants.OP_IFICMPNE:
789                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
790                     stack.ipop().notEqual(stack.ipop()));
791                 break;
792
793             case InstructionConstants.OP_IFICMPLT:
794                 // Note that the stack entries are popped in reverse order.
795
branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
796                     stack.ipop().greaterThan(stack.ipop()));
797                 break;
798
799             case InstructionConstants.OP_IFICMPGE:
800                 // Note that the stack entries are popped in reverse order.
801
branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
802                     stack.ipop().lessThanOrEqual(stack.ipop()));
803                 break;
804
805             case InstructionConstants.OP_IFICMPGT:
806                 // Note that the stack entries are popped in reverse order.
807
branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
808                     stack.ipop().lessThan(stack.ipop()));
809                 break;
810
811             case InstructionConstants.OP_IFICMPLE:
812                 // Note that the stack entries are popped in reverse order.
813
branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
814                     stack.ipop().greaterThanOrEqual(stack.ipop()));
815                 break;
816
817             case InstructionConstants.OP_IFACMPEQ:
818                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
819                     stack.apop().equal(stack.apop()));
820                 break;
821
822             case InstructionConstants.OP_IFACMPNE:
823                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
824                     stack.apop().notEqual(stack.apop()));
825                 break;
826
827             case InstructionConstants.OP_GOTO:
828             case InstructionConstants.OP_GOTO_W:
829                 branchUnit.branch(clazz, codeAttribute, offset, branchTarget);
830                 break;
831
832
833             case InstructionConstants.OP_JSR:
834             case InstructionConstants.OP_JSR_W:
835                 stack.push(new InstructionOffsetValue(offset +
836                                                       branchInstruction.length(offset)));
837                 branchUnit.branch(clazz, codeAttribute, offset, branchTarget);
838                 break;
839
840             case InstructionConstants.OP_IFNULL:
841                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
842                     stack.apop().isNull());
843                 break;
844
845             case InstructionConstants.OP_IFNONNULL:
846                 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
847                     stack.apop().isNotNull());
848                 break;
849
850             default:
851                 throw new IllegalArgumentException JavaDoc("Unknown branch instruction ["+branchInstruction.opcode+"]");
852         }
853     }
854
855
856     public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
857     {
858         IntegerValue indexValue = stack.ipop();
859
860         // If there is no definite branch in any of the cases below,
861
// branch to the default offset.
862
branchUnit.branch(clazz, codeAttribute,
863                           offset,
864                           offset + tableSwitchInstruction.defaultOffset);
865
866         for (int index = 0; index < tableSwitchInstruction.jumpOffsets.length; index++)
867         {
868             int conditional = indexValue.equal(valueFactory.createIntegerValue(
869                 tableSwitchInstruction.lowCase + index));
870             branchUnit.branchConditionally(clazz, codeAttribute,
871                                            offset,
872                                            offset + tableSwitchInstruction.jumpOffsets[index],
873                                            conditional);
874
875             // If this branch is always taken, we can skip the rest.
876
if (conditional == Value.ALWAYS)
877             {
878                 break;
879             }
880         }
881     }
882
883
884     public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
885     {
886         IntegerValue indexValue = stack.ipop();
887
888         // If there is no definite branch in any of the cases below,
889
// branch to the default offset.
890
branchUnit.branch(clazz, codeAttribute,
891                           offset,
892                           offset + lookUpSwitchInstruction.defaultOffset);
893
894         for (int index = 0; index < lookUpSwitchInstruction.jumpOffsets.length; index++)
895         {
896             int conditional = indexValue.equal(valueFactory.createIntegerValue(
897                 lookUpSwitchInstruction.cases[index]));
898             branchUnit.branchConditionally(clazz, codeAttribute,
899                                            offset,
900                                            offset + lookUpSwitchInstruction.jumpOffsets[index],
901                                            conditional);
902
903             // If this branch is always taken, we can skip the rest.
904
if (conditional == Value.ALWAYS)
905             {
906                 break;
907             }
908         }
909     }
910
911
912     // Implementations for ConstantVisitor.
913

914     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
915     {
916         cpValue = valueFactory.createIntegerValue(integerConstant.getValue());
917     }
918
919     public void visitLongConstant(Clazz clazz, LongConstant longConstant)
920     {
921         cpValue = valueFactory.createLongValue(longConstant.getValue());
922     }
923
924     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
925     {
926         cpValue = valueFactory.createFloatValue(floatConstant.getValue());
927     }
928
929     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
930     {
931         cpValue = valueFactory.createDoubleValue(doubleConstant.getValue());
932     }
933
934     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
935     {
936         cpValue = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING,
937                                                     null,
938                                                     false);
939     }
940
941     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
942     {
943         cpValue = handleClassConstantAsClassValue ?
944             valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS,
945                                               null,
946                                               false) :
947             valueFactory.createReferenceValue(classConstant.getName(clazz),
948                                               classConstant.referencedClass,
949                                               false);
950     }
951
952
953     // Small utility methods.
954

955     /**
956      * Returns the Value of the constant pool element at the given index.
957      */

958     private Value cpValue(Clazz clazz,
959                           int constantIndex)
960     {
961         return cpValue(clazz, constantIndex, false);
962     }
963
964
965     /**
966      * Returns the Value of the constant pool element at the given index.
967      */

968     private Value cpValue(Clazz clazz,
969                           int constantIndex,
970                           boolean handleClassConstantAsClassValue)
971     {
972         this.handleClassConstantAsClassValue = handleClassConstantAsClassValue;
973
974         // Visit the constant pool entry to get its return value.
975
clazz.constantPoolEntryAccept(constantIndex, this);
976
977         return cpValue;
978     }
979 }
980
Popular Tags