KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > classfile > CodeDisassembler


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.classfile;
54
55 import java.util.*;
56
57 /******************************************************************************
58  *
59  * @author Brian S O'Neill
60  * @version
61  * <!--$$Revision:--> 16 <!-- $-->, <!--$$JustDate:--> 00/12/27 <!-- $-->
62  */

63 public class CodeDisassembler {
64     private final MethodInfo mMethod;
65     private final String JavaDoc mEnclosingClassName;
66     private final String JavaDoc mSuperClassName;
67     private final CodeAttr mCode;
68     private final ConstantPool mCp;
69     private final byte[] mByteCodes;
70     private final ExceptionHandler[] mExceptionHandlers;
71
72     // Current CodeAssembler in use for disassembly.
73
private CodeAssembler mAssembler;
74
75     // List of all the LocalVariable objects in use.
76
private Vector mLocals;
77
78     // True if the method being decompiled still has a "this" reference.
79
private boolean mHasThis;
80
81     // Maps Integer address keys to itself, but to Label objects after first
82
// needed.
83
private Map mLabels;
84
85     // Maps Integer catch locations to Lists of ExceptionHandler objects.
86
private Map mCatchLocations;
87
88     // Current address being decompiled.
89
private int mAddress;
90
91     public CodeDisassembler(MethodInfo method) {
92         mMethod = method;
93         mEnclosingClassName = method.getClassFile().getClassName();
94         mSuperClassName = method.getClassFile().getSuperClassName();
95         mCode = method.getCodeAttr();
96         mCp = mCode.getConstantPool();
97         CodeBuffer buffer = mCode.getCodeBuffer();
98         mByteCodes = buffer.getByteCodes();
99         mExceptionHandlers = buffer.getExceptionHandlers();
100     }
101
102     /**
103      * Disassemble the MethodInfo into the given assembler.
104      *
105      * @see CodeAssemblerPrinter
106      */

107     public synchronized void disassemble(CodeAssembler assembler) {
108         mAssembler = assembler;
109         mLocals = new Vector();
110         mHasThis = !mMethod.getAccessFlags().isStatic();
111
112         gatherLabels();
113
114         // Gather the local variables of the parameters.
115
LocalVariable[] paramVars = assembler.getParameters();
116         for (int i=0; i<paramVars.length; i++) {
117             LocalVariable paramVar = paramVars[i];
118             int number = paramVar.getNumber();
119             if (number >= mLocals.size()) {
120                 mLocals.setSize(number + 1);
121             }
122             mLocals.setElementAt(paramVar, number);
123         }
124
125         Location currentLoc = new Location() {
126             public int getLocation() {
127                 return mAddress;
128             }
129
130             public int compareTo(Object JavaDoc obj) {
131                 if (this == obj) {
132                     return 0;
133                 }
134                 Location other = (Location)obj;
135                 
136                 int loca = getLocation();
137                 int locb = other.getLocation();
138                 
139                 if (loca < locb) {
140                     return -1;
141                 }
142                 else if (loca > locb) {
143                     return 1;
144                 }
145                 else {
146                     return 0;
147                 }
148             }
149         };
150
151         int currentLine = -1;
152
153         for (mAddress = 0; mAddress < mByteCodes.length; mAddress++) {
154             int nextLine = mCode.getLineNumber(currentLoc);
155             if (nextLine != currentLine) {
156                 if ((currentLine = nextLine) >= 0) {
157                     mAssembler.mapLineNumber(currentLine);
158                 }
159             }
160
161             // Check if a label needs to be created and/or located.
162
locateLabel();
163
164             byte opcode = mByteCodes[mAddress];
165
166             int index;
167             Location loc;
168             Class JavaDoc clazz;
169             ConstantInfo ci;
170
171             switch (opcode) {
172
173             default:
174                 // TODO: raise an error.
175
break;
176
177                 // Opcodes with no operands...
178

179             case Opcode.NOP:
180                 assembler.nop();
181                 break;
182             case Opcode.BREAKPOINT:
183                 assembler.breakpoint();
184                 break;
185
186             case Opcode.ACONST_NULL:
187                 assembler.loadConstant(null);
188                 break;
189             case Opcode.ICONST_M1:
190                 assembler.loadConstant(-1);
191                 break;
192             case Opcode.ICONST_0:
193                 assembler.loadConstant(0);
194                 break;
195             case Opcode.ICONST_1:
196                 assembler.loadConstant(1);
197                 break;
198             case Opcode.ICONST_2:
199                 assembler.loadConstant(2);
200                 break;
201             case Opcode.ICONST_3:
202                 assembler.loadConstant(3);
203                 break;
204             case Opcode.ICONST_4:
205                 assembler.loadConstant(4);
206                 break;
207             case Opcode.ICONST_5:
208                 assembler.loadConstant(5);
209                 break;
210             case Opcode.LCONST_0:
211                 assembler.loadConstant(0L);
212                 break;
213             case Opcode.LCONST_1:
214                 assembler.loadConstant(1L);
215                 break;
216             case Opcode.FCONST_0:
217                 assembler.loadConstant(0f);
218                 break;
219             case Opcode.FCONST_1:
220                 assembler.loadConstant(1f);
221                 break;
222             case Opcode.FCONST_2:
223                 assembler.loadConstant(2f);
224                 break;
225             case Opcode.DCONST_0:
226                 assembler.loadConstant(0d);
227                 break;
228             case Opcode.DCONST_1:
229                 assembler.loadConstant(1d);
230                 break;
231
232             case Opcode.POP:
233                 assembler.pop();
234                 break;
235             case Opcode.POP2:
236                 assembler.pop2();
237                 break;
238             case Opcode.DUP:
239                 assembler.dup();
240                 break;
241             case Opcode.DUP_X1:
242                 assembler.dupX1();
243                 break;
244             case Opcode.DUP_X2:
245                 assembler.dupX2();
246                 break;
247             case Opcode.DUP2:
248                 assembler.dup2();
249                 break;
250             case Opcode.DUP2_X1:
251                 assembler.dup2X2();
252                 break;
253             case Opcode.DUP2_X2:
254                 assembler.dup2X2();
255                 break;
256             case Opcode.SWAP:
257                 assembler.swap();
258                 break;
259
260             case Opcode.IADD: case Opcode.LADD:
261             case Opcode.FADD: case Opcode.DADD:
262             case Opcode.ISUB: case Opcode.LSUB:
263             case Opcode.FSUB: case Opcode.DSUB:
264             case Opcode.IMUL: case Opcode.LMUL:
265             case Opcode.FMUL: case Opcode.DMUL:
266             case Opcode.IDIV: case Opcode.LDIV:
267             case Opcode.FDIV: case Opcode.DDIV:
268             case Opcode.IREM: case Opcode.LREM:
269             case Opcode.FREM: case Opcode.DREM:
270             case Opcode.INEG: case Opcode.LNEG:
271             case Opcode.FNEG: case Opcode.DNEG:
272             case Opcode.ISHL: case Opcode.LSHL:
273             case Opcode.ISHR: case Opcode.LSHR:
274             case Opcode.IUSHR: case Opcode.LUSHR:
275             case Opcode.IAND: case Opcode.LAND:
276             case Opcode.IOR: case Opcode.LOR:
277             case Opcode.IXOR: case Opcode.LXOR:
278             case Opcode.FCMPL: case Opcode.DCMPL:
279             case Opcode.FCMPG: case Opcode.DCMPG:
280             case Opcode.LCMP:
281                 assembler.math(opcode);
282                 break;
283
284             case Opcode.I2L:
285                 assembler.convert(int.class, long.class);
286                 break;
287             case Opcode.I2F:
288                 assembler.convert(int.class, float.class);
289                 break;
290             case Opcode.I2D:
291                 assembler.convert(int.class, double.class);
292                 break;
293             case Opcode.L2I:
294                 assembler.convert(long.class, int.class);
295                 break;
296             case Opcode.L2F:
297                 assembler.convert(long.class, float.class);
298                 break;
299             case Opcode.L2D:
300                 assembler.convert(long.class, double.class);
301                 break;
302             case Opcode.F2I:
303                 assembler.convert(float.class, int.class);
304                 break;
305             case Opcode.F2L:
306                 assembler.convert(float.class, long.class);
307                 break;
308             case Opcode.F2D:
309                 assembler.convert(float.class, double.class);
310                 break;
311             case Opcode.D2I:
312                 assembler.convert(double.class, int.class);
313                 break;
314             case Opcode.D2L:
315                 assembler.convert(double.class, long.class);
316                 break;
317             case Opcode.D2F:
318                 assembler.convert(double.class, float.class);
319                 break;
320             case Opcode.I2B:
321                 assembler.convert(int.class, byte.class);
322                 break;
323             case Opcode.I2C:
324                 assembler.convert(int.class, char.class);
325                 break;
326             case Opcode.I2S:
327                 assembler.convert(int.class, short.class);
328                 break;
329
330             case Opcode.IRETURN:
331                 assembler.returnValue(int.class);
332                 break;
333             case Opcode.LRETURN:
334                 assembler.returnValue(long.class);
335                 break;
336             case Opcode.FRETURN:
337                 assembler.returnValue(float.class);
338                 break;
339             case Opcode.DRETURN:
340                 assembler.returnValue(double.class);
341                 break;
342             case Opcode.ARETURN:
343                 assembler.returnValue(Object JavaDoc.class);
344                 break;
345             case Opcode.RETURN:
346                 assembler.returnVoid();
347                 break;
348
349             case Opcode.IALOAD:
350                 assembler.loadFromArray(int.class);
351                 break;
352             case Opcode.LALOAD:
353                 assembler.loadFromArray(long.class);
354                 break;
355             case Opcode.FALOAD:
356                 assembler.loadFromArray(float.class);
357                 break;
358             case Opcode.DALOAD:
359                 assembler.loadFromArray(double.class);
360                 break;
361             case Opcode.AALOAD:
362                 assembler.loadFromArray(Object JavaDoc.class);
363                 break;
364             case Opcode.BALOAD:
365                 assembler.loadFromArray(byte.class);
366                 break;
367             case Opcode.CALOAD:
368                 assembler.loadFromArray(char.class);
369                 break;
370             case Opcode.SALOAD:
371                 assembler.loadFromArray(short.class);
372                 break;
373
374             case Opcode.IASTORE:
375                 assembler.storeToArray(int.class);
376                 break;
377             case Opcode.LASTORE:
378                 assembler.storeToArray(long.class);
379                 break;
380             case Opcode.FASTORE:
381                 assembler.storeToArray(float.class);
382                 break;
383             case Opcode.DASTORE:
384                 assembler.storeToArray(double.class);
385                 break;
386             case Opcode.AASTORE:
387                 assembler.storeToArray(Object JavaDoc.class);
388                 break;
389             case Opcode.BASTORE:
390                 assembler.storeToArray(byte.class);
391                 break;
392             case Opcode.CASTORE:
393                 assembler.storeToArray(char.class);
394                 break;
395             case Opcode.SASTORE:
396                 assembler.storeToArray(short.class);
397                 break;
398
399             case Opcode.ARRAYLENGTH:
400                 assembler.arrayLength();
401                 break;
402             case Opcode.ATHROW:
403                 assembler.throwObject();
404                 break;
405             case Opcode.MONITORENTER:
406                 assembler.monitorEnter();
407                 break;
408             case Opcode.MONITOREXIT:
409                 assembler.monitorExit();
410                 break;
411
412                 // End opcodes with no operands.
413

414                 // Opcodes that load a constant from the constant pool...
415

416             case Opcode.LDC:
417             case Opcode.LDC_W:
418             case Opcode.LDC2_W:
419                 switch (opcode) {
420                 case Opcode.LDC:
421                     index = readUnsignedByte();
422                     break;
423                 case Opcode.LDC_W:
424                 case Opcode.LDC2_W:
425                     index = readUnsignedShort();
426                     break;
427                 default:
428                     index = 0;
429                     break;
430                 }
431
432                 ci = mCp.getConstant(index);
433
434                 if (ci instanceof ConstantStringInfo) {
435                     assembler.loadConstant
436                         (((ConstantStringInfo)ci).getValue());
437                 }
438                 else if (ci instanceof ConstantIntegerInfo) {
439                     assembler.loadConstant
440                         (((ConstantIntegerInfo)ci).getValue().intValue());
441                 }
442                 else if (ci instanceof ConstantLongInfo) {
443                     assembler.loadConstant
444                         (((ConstantLongInfo)ci).getValue().longValue());
445                 }
446                 else if (ci instanceof ConstantFloatInfo) {
447                     assembler.loadConstant
448                         (((ConstantFloatInfo)ci).getValue().floatValue());
449                 }
450                 else if (ci instanceof ConstantDoubleInfo) {
451                     assembler.loadConstant
452                         (((ConstantDoubleInfo)ci).getValue().doubleValue());
453                 }
454                 else {
455                     // TODO: raise an error.
456
}
457                 break;
458
459             case Opcode.NEW:
460                 ci = mCp.getConstant(readUnsignedShort());
461
462                 if (ci instanceof ConstantClassInfo) {
463                     assembler.newObject
464                         (((ConstantClassInfo)ci).getTypeDescriptor());
465                 }
466                 else {
467                     // TODO: raise an error.
468
}
469                 break;
470             case Opcode.ANEWARRAY:
471                 ci = mCp.getConstant(readUnsignedShort());
472
473                 if (ci instanceof ConstantClassInfo) {
474                     TypeDescriptor type =
475                         ((ConstantClassInfo)ci).getTypeDescriptor();
476                     type = new TypeDescriptor(type, 1);
477                     assembler.newObject(type);
478                 }
479                 else {
480                     // TODO: raise an error.
481
}
482                 break;
483             case Opcode.MULTIANEWARRAY:
484                 ci = mCp.getConstant(readUnsignedShort());
485                 int dims = readUnsignedByte();
486
487                 if (ci instanceof ConstantClassInfo) {
488                     assembler.newObject
489                         (((ConstantClassInfo)ci).getTypeDescriptor());
490                 }
491                 else {
492                     // TODO: raise an error.
493
}
494                 break;
495
496             case Opcode.CHECKCAST:
497                 ci = mCp.getConstant(readUnsignedShort());
498
499                 if (ci instanceof ConstantClassInfo) {
500                     assembler.checkCast
501                         (((ConstantClassInfo)ci).getTypeDescriptor());
502                 }
503                 else {
504                     // TODO: raise an error.
505
}
506                 break;
507             case Opcode.INSTANCEOF:
508                 ci = mCp.getConstant(readUnsignedShort());
509
510                 if (ci instanceof ConstantClassInfo) {
511                     assembler.instanceOf
512                         (((ConstantClassInfo)ci).getTypeDescriptor());
513                 }
514                 else {
515                     // TODO: raise an error.
516
}
517                 break;
518
519             case Opcode.GETSTATIC:
520             case Opcode.PUTSTATIC:
521             case Opcode.GETFIELD:
522             case Opcode.PUTFIELD:
523                 ci = mCp.getConstant(readUnsignedShort());
524                 if (!(ci instanceof ConstantFieldInfo)) {
525                     // TODO: raise an error.
526
break;
527                 }
528                 ConstantFieldInfo field = (ConstantFieldInfo)ci;
529                 String JavaDoc className = field.getParentClass().getClassName();
530                 if (mEnclosingClassName.equals(className)) {
531                     className = null;
532                 }
533                 String JavaDoc fieldName = field.getNameAndType().getName();
534                 Descriptor type = field.getNameAndType().getType();
535                 if (!(type instanceof TypeDescriptor)) {
536                     // TODO: raise an error.
537
break;
538                 }
539
540                 // Implementation note: Although it may seem convenient if the
541
// CodeAssembler had methods that accepted ConstantFieldInfo
542
// objects as parameters, it would cause problems because
543
// ConstantPools are not portable between ClassFiles.
544

545                 switch (opcode) {
546                 case Opcode.GETSTATIC:
547                     if (className == null) {
548                         assembler.loadStaticField
549                             (fieldName, (TypeDescriptor)type);
550                     }
551                     else {
552                         assembler.loadStaticField
553                             (className, fieldName, (TypeDescriptor)type);
554                     }
555                     break;
556                 case Opcode.PUTSTATIC:
557                     if (className == null) {
558                         assembler.storeStaticField
559                             (fieldName, (TypeDescriptor)type);
560                     }
561                     else {
562                         assembler.storeStaticField
563                             (className, fieldName, (TypeDescriptor)type);
564                     }
565                     break;
566                 case Opcode.GETFIELD:
567                     if (className == null) {
568                         assembler.loadField
569                             (fieldName, (TypeDescriptor)type);
570                     }
571                     else {
572                         assembler.loadField
573                             (className, fieldName, (TypeDescriptor)type);
574                     }
575                     break;
576                 case Opcode.PUTFIELD:
577                     if (className == null) {
578                         assembler.storeField
579                             (fieldName, (TypeDescriptor)type);
580                     }
581                     else {
582                         assembler.storeField
583                             (className, fieldName, (TypeDescriptor)type);
584                     }
585                     break;
586                 }
587                 break;
588
589             case Opcode.INVOKEVIRTUAL:
590             case Opcode.INVOKESPECIAL:
591             case Opcode.INVOKESTATIC:
592             case Opcode.INVOKEINTERFACE:
593                 ci = mCp.getConstant(readUnsignedShort());
594
595                 ConstantNameAndTypeInfo nameAndType;
596
597                 if (opcode == Opcode.INVOKEINTERFACE) {
598                     // Read and ignore nargs and padding byte.
599
readShort();
600                     if (!(ci instanceof ConstantInterfaceMethodInfo)) {
601                         // TODO: raise an error.
602
break;
603                     }
604                     ConstantInterfaceMethodInfo method =
605                         (ConstantInterfaceMethodInfo)ci;
606                     className = method.getParentClass().getClassName();
607                     nameAndType = method.getNameAndType();
608                 }
609                 else {
610                     if (!(ci instanceof ConstantMethodInfo)) {
611                         // TODO: raise an error.
612
break;
613                     }
614                     ConstantMethodInfo method =
615                         (ConstantMethodInfo)ci;
616                     className = method.getParentClass().getClassName();
617                     if (mEnclosingClassName.equals(className)) {
618                         className = null;
619                     }
620                     nameAndType = method.getNameAndType();
621                 }
622
623                 String JavaDoc methodName = nameAndType.getName();
624                 type = nameAndType.getType();
625                 if (!(type instanceof MethodDescriptor)) {
626                     // TODO: raise an error.
627
break;
628                 }
629                 TypeDescriptor ret = ((MethodDescriptor)type).getReturnType();
630                 if (ret.getClassArg() == void.class) {
631                     ret = null;
632                 }
633                 TypeDescriptor[] params =
634                     ((MethodDescriptor)type).getParameterTypes();
635                 if (params.length == 0) {
636                     params = null;
637                 }
638
639                 switch (opcode) {
640                 case Opcode.INVOKEVIRTUAL:
641                     if (className == null) {
642                         assembler.invokeVirtual(methodName, ret, params);
643                     }
644                     else {
645                         assembler.invokeVirtual
646                             (className, methodName, ret, params);
647                     }
648                     break;
649                 case Opcode.INVOKESPECIAL:
650                     if ("<init>".equals(methodName)) {
651                         if (className == null) {
652                             assembler.invokeConstructor(params);
653                         }
654                         else {
655                             if (className.equals(mSuperClassName)) {
656                                 assembler.invokeSuperConstructor(params);
657                             }
658                             else {
659                                 assembler.invokeConstructor(className, params);
660                             }
661                         }
662                     }
663                     else {
664                         if (className == null) {
665                             assembler.invokePrivate(methodName, ret, params);
666                         }
667                         else {
668                             assembler.invokeSuper
669                                 (className, methodName, ret, params);
670                         }
671                     }
672                     break;
673                 case Opcode.INVOKESTATIC:
674                     if (className == null) {
675                         assembler.invokeStatic(methodName, ret, params);
676                     }
677                     else {
678                         assembler.invokeStatic
679                             (className, methodName, ret, params);
680                     }
681                     break;
682                 case Opcode.INVOKEINTERFACE:
683                     assembler.invokeInterface
684                         (className, methodName, ret, params);
685                     break;
686                 }
687                 break;
688
689                 // End opcodes that load a constant from the constant pool.
690

691                 // Opcodes that load or store local variables...
692

693             case Opcode.ILOAD: case Opcode.ISTORE:
694             case Opcode.LLOAD: case Opcode.LSTORE:
695             case Opcode.FLOAD: case Opcode.FSTORE:
696             case Opcode.DLOAD: case Opcode.DSTORE:
697             case Opcode.ALOAD: case Opcode.ASTORE:
698             case Opcode.ILOAD_0: case Opcode.ISTORE_0:
699             case Opcode.ILOAD_1: case Opcode.ISTORE_1:
700             case Opcode.ILOAD_2: case Opcode.ISTORE_2:
701             case Opcode.ILOAD_3: case Opcode.ISTORE_3:
702             case Opcode.LLOAD_0: case Opcode.LSTORE_0:
703             case Opcode.LLOAD_1: case Opcode.LSTORE_1:
704             case Opcode.LLOAD_2: case Opcode.LSTORE_2:
705             case Opcode.LLOAD_3: case Opcode.LSTORE_3:
706             case Opcode.FLOAD_0: case Opcode.FSTORE_0:
707             case Opcode.FLOAD_1: case Opcode.FSTORE_1:
708             case Opcode.FLOAD_2: case Opcode.FSTORE_2:
709             case Opcode.FLOAD_3: case Opcode.FSTORE_3:
710             case Opcode.DLOAD_0: case Opcode.DSTORE_0:
711             case Opcode.DLOAD_1: case Opcode.DSTORE_1:
712             case Opcode.DLOAD_2: case Opcode.DSTORE_2:
713             case Opcode.DLOAD_3: case Opcode.DSTORE_3:
714             case Opcode.ALOAD_0: case Opcode.ASTORE_0:
715             case Opcode.ALOAD_1: case Opcode.ASTORE_1:
716             case Opcode.ALOAD_2: case Opcode.ASTORE_2:
717             case Opcode.ALOAD_3: case Opcode.ASTORE_3:
718                 switch (opcode) {
719                 case Opcode.ILOAD: case Opcode.ISTORE:
720                     index = readUnsignedByte();
721                     clazz = int.class;
722                     break;
723                 case Opcode.LLOAD: case Opcode.LSTORE:
724                     index = readUnsignedByte();
725                     clazz = long.class;
726                     break;
727                 case Opcode.FLOAD: case Opcode.FSTORE:
728                     index = readUnsignedByte();
729                     clazz = float.class;
730                     break;
731                 case Opcode.DLOAD: case Opcode.DSTORE:
732                     index = readUnsignedByte();
733                     clazz = double.class;
734                     break;
735                 case Opcode.ALOAD: case Opcode.ASTORE:
736                     index = readUnsignedByte();
737                     clazz = Object JavaDoc.class;
738                     break;
739                 case Opcode.ILOAD_0: case Opcode.ISTORE_0:
740                     index = 0;
741                     clazz = int.class;
742                     break;
743                 case Opcode.ILOAD_1: case Opcode.ISTORE_1:
744                     index = 1;
745                     clazz = int.class;
746                     break;
747                 case Opcode.ILOAD_2: case Opcode.ISTORE_2:
748                     index = 2;
749                     clazz = int.class;
750                     break;
751                 case Opcode.ILOAD_3: case Opcode.ISTORE_3:
752                     index = 3;
753                     clazz = int.class;
754                     break;
755                 case Opcode.LLOAD_0: case Opcode.LSTORE_0:
756                     index = 0;
757                     clazz = long.class;
758                     break;
759                 case Opcode.LLOAD_1: case Opcode.LSTORE_1:
760                     index = 1;
761                     clazz = long.class;
762                     break;
763                 case Opcode.LLOAD_2: case Opcode.LSTORE_2:
764                     index = 2;
765                     clazz = long.class;
766                     break;
767                 case Opcode.LLOAD_3: case Opcode.LSTORE_3:
768                     index = 3;
769                     clazz = long.class;
770                     break;
771                 case Opcode.FLOAD_0: case Opcode.FSTORE_0:
772                     index = 0;
773                     clazz = float.class;
774                     break;
775                 case Opcode.FLOAD_1: case Opcode.FSTORE_1:
776                     index = 1;
777                     clazz = float.class;
778                     break;
779                 case Opcode.FLOAD_2: case Opcode.FSTORE_2:
780                     index = 2;
781                     clazz = float.class;
782                     break;
783                 case Opcode.FLOAD_3: case Opcode.FSTORE_3:
784                     index = 3;
785                     clazz = float.class;
786                     break;
787                 case Opcode.DLOAD_0: case Opcode.DSTORE_0:
788                     index = 0;
789                     clazz = double.class;
790                     break;
791                 case Opcode.DLOAD_1: case Opcode.DSTORE_1:
792                     index = 1;
793                     clazz = double.class;
794                     break;
795                 case Opcode.DLOAD_2: case Opcode.DSTORE_2:
796                     index = 2;
797                     clazz = double.class;
798                     break;
799                 case Opcode.DLOAD_3: case Opcode.DSTORE_3:
800                     index = 3;
801                     clazz = double.class;
802                     break;
803                 case Opcode.ALOAD_0: case Opcode.ASTORE_0:
804                     index = 0;
805                     clazz = Object JavaDoc.class;
806                     break;
807                 case Opcode.ALOAD_1: case Opcode.ASTORE_1:
808                     index = 1;
809                     clazz = Object JavaDoc.class;
810                     break;
811                 case Opcode.ALOAD_2: case Opcode.ASTORE_2:
812                     index = 2;
813                     clazz = Object JavaDoc.class;
814                     break;
815                 case Opcode.ALOAD_3: case Opcode.ASTORE_3:
816                     index = 3;
817                     clazz = Object JavaDoc.class;
818                     break;
819                 default:
820                     index = 0;
821                     clazz = null;
822                     break;
823                 }
824
825                 switch (opcode) {
826                 case Opcode.ILOAD:
827                 case Opcode.LLOAD:
828                 case Opcode.FLOAD:
829                 case Opcode.DLOAD:
830                 case Opcode.ALOAD:
831                 case Opcode.ILOAD_0:
832                 case Opcode.ILOAD_1:
833                 case Opcode.ILOAD_2:
834                 case Opcode.ILOAD_3:
835                 case Opcode.LLOAD_0:
836                 case Opcode.LLOAD_1:
837                 case Opcode.LLOAD_2:
838                 case Opcode.LLOAD_3:
839                 case Opcode.FLOAD_0:
840                 case Opcode.FLOAD_1:
841                 case Opcode.FLOAD_2:
842                 case Opcode.FLOAD_3:
843                 case Opcode.DLOAD_0:
844                 case Opcode.DLOAD_1:
845                 case Opcode.DLOAD_2:
846                 case Opcode.DLOAD_3:
847                 case Opcode.ALOAD_0:
848                 case Opcode.ALOAD_1:
849                 case Opcode.ALOAD_2:
850                 case Opcode.ALOAD_3:
851                     if (index == 0 && mHasThis) {
852                         assembler.loadThis();
853                     }
854                     else {
855                         assembler.loadLocal(getLocalVariable(index, clazz));
856                     }
857                     break;
858                 case Opcode.ISTORE:
859                 case Opcode.LSTORE:
860                 case Opcode.FSTORE:
861                 case Opcode.DSTORE:
862                 case Opcode.ASTORE:
863                 case Opcode.ISTORE_0:
864                 case Opcode.ISTORE_1:
865                 case Opcode.ISTORE_2:
866                 case Opcode.ISTORE_3:
867                 case Opcode.LSTORE_0:
868                 case Opcode.LSTORE_1:
869                 case Opcode.LSTORE_2:
870                 case Opcode.LSTORE_3:
871                 case Opcode.FSTORE_0:
872                 case Opcode.FSTORE_1:
873                 case Opcode.FSTORE_2:
874                 case Opcode.FSTORE_3:
875                 case Opcode.DSTORE_0:
876                 case Opcode.DSTORE_1:
877                 case Opcode.DSTORE_2:
878                 case Opcode.DSTORE_3:
879                 case Opcode.ASTORE_0:
880                 case Opcode.ASTORE_1:
881                 case Opcode.ASTORE_2:
882                 case Opcode.ASTORE_3:
883                     if (index == 0 && mHasThis) {
884                         // The "this" reference just got blown away.
885
mHasThis = false;
886                     }
887                     assembler.storeLocal(getLocalVariable(index, clazz));
888                     break;
889                 }
890                 break;
891
892             case Opcode.RET:
893                 LocalVariable local = getLocalVariable
894                     (readUnsignedByte(), Object JavaDoc.class);
895                 assembler.ret(local);
896                 break;
897
898             case Opcode.IINC:
899                 local = getLocalVariable(readUnsignedByte(), int.class);
900                 assembler.integerIncrement(local, readByte());
901                 break;
902
903                 // End opcodes that load or store local variables.
904

905                 // Opcodes that branch to another address.
906

907             case Opcode.GOTO:
908                 loc = getLabel(mAddress + readShort());
909                 assembler.branch(loc);
910                 break;
911             case Opcode.JSR:
912                 loc = getLabel(mAddress + readShort());
913                 assembler.jsr(loc);
914                 break;
915             case Opcode.GOTO_W:
916                 loc = getLabel(mAddress + readInt());
917                 assembler.branch(loc);
918                 break;
919             case Opcode.JSR_W:
920                 loc = getLabel(mAddress + readInt());
921                 assembler.jsr(loc);
922                 break;
923
924             case Opcode.IFNULL:
925                 loc = getLabel(mAddress + readShort());
926                 assembler.ifNullBranch(loc, true);
927                 break;
928             case Opcode.IFNONNULL:
929                 loc = getLabel(mAddress + readShort());
930                 assembler.ifNullBranch(loc, false);
931                 break;
932
933             case Opcode.IF_ACMPEQ:
934                 loc = getLabel(mAddress + readShort());
935                 assembler.ifEqualBranch(loc, true);
936                 break;
937             case Opcode.IF_ACMPNE:
938                 loc = getLabel(mAddress + readShort());
939                 assembler.ifEqualBranch(loc, false);
940                 break;
941
942             case Opcode.IFEQ:
943             case Opcode.IFNE:
944             case Opcode.IFLT:
945             case Opcode.IFGE:
946             case Opcode.IFGT:
947             case Opcode.IFLE:
948                 loc = getLabel(mAddress + readShort());
949                 String JavaDoc choice;
950                 switch (opcode) {
951                 case Opcode.IFEQ:
952                     choice = "==";
953                     break;
954                 case Opcode.IFNE:
955                     choice = "!=";
956                     break;
957                 case Opcode.IFLT:
958                     choice = "<";
959                     break;
960                 case Opcode.IFGE:
961                     choice = ">=";
962                     break;
963                 case Opcode.IFGT:
964                     choice = ">";
965                     break;
966                 case Opcode.IFLE:
967                     choice = "<=";
968                     break;
969                 default:
970                     choice = null;
971                     break;
972                 }
973                 assembler.ifZeroComparisonBranch(loc, choice);
974                 break;
975
976             case Opcode.IF_ICMPEQ:
977             case Opcode.IF_ICMPNE:
978             case Opcode.IF_ICMPLT:
979             case Opcode.IF_ICMPGE:
980             case Opcode.IF_ICMPGT:
981             case Opcode.IF_ICMPLE:
982                 loc = getLabel(mAddress + readShort());
983                 switch (opcode) {
984                 case Opcode.IF_ICMPEQ:
985                     choice = "==";
986                     break;
987                 case Opcode.IF_ICMPNE:
988                     choice = "!=";
989                     break;
990                 case Opcode.IF_ICMPLT:
991                     choice = "<";
992                     break;
993                 case Opcode.IF_ICMPGE:
994                     choice = ">=";
995                     break;
996                 case Opcode.IF_ICMPGT:
997                     choice = ">";
998                     break;
999                 case Opcode.IF_ICMPLE:
1000                    choice = "<=";
1001                    break;
1002                default:
1003                    choice = null;
1004                    break;
1005                }
1006                assembler.ifComparisonBranch(loc, choice);
1007                break;
1008
1009                // End opcodes that branch to another address.
1010

1011                // Miscellaneous opcodes...
1012

1013            case Opcode.BIPUSH:
1014                assembler.loadConstant(readByte());
1015                break;
1016            case Opcode.SIPUSH:
1017                assembler.loadConstant(readShort());
1018                break;
1019
1020            case Opcode.NEWARRAY:
1021                int atype = readByte();
1022                clazz = null;
1023                switch (atype) {
1024                case 4: // T_BOOLEAN
1025
clazz = boolean.class;
1026                    break;
1027                case 5: // T_CHAR
1028
clazz = char.class;
1029                    break;
1030                case 6: // T_FLOAT
1031
clazz = float.class;
1032                    break;
1033                case 7: // T_DOUBLE
1034
clazz = double.class;
1035                    break;
1036                case 8: // T_BYTE
1037
clazz = byte.class;
1038                    break;
1039                case 9: // T_SHORT
1040
clazz = short.class;
1041                    break;
1042                case 10: // T_INT
1043
clazz = int.class;
1044                    break;
1045                case 11: // T_LONG
1046
clazz = long.class;
1047                    break;
1048                }
1049
1050                if (clazz == null) {
1051                    // TODO: raise an error.
1052
break;
1053                }
1054
1055                assembler.newObject
1056                    (new TypeDescriptor(new TypeDescriptor(clazz), 1));
1057                break;
1058
1059            case Opcode.TABLESWITCH:
1060            case Opcode.LOOKUPSWITCH:
1061                int opcodeAddress = mAddress;
1062                // Read padding until address is 32 bit word aligned.
1063
while (((mAddress + 1) & 3) != 0) {
1064                    ++mAddress;
1065                }
1066                Location defaultLocation = getLabel(opcodeAddress + readInt());
1067                int[] cases;
1068                Location[] locations;
1069                
1070                if (opcode == Opcode.TABLESWITCH) {
1071                    int lowValue = readInt();
1072                    int highValue = readInt();
1073                    int caseCount = highValue - lowValue + 1;
1074                    try {
1075                        cases = new int[caseCount];
1076                    }
1077                    catch (NegativeArraySizeException JavaDoc e) {
1078                        // TODO: raise an error.
1079
break;
1080                    }
1081                    locations = new Location[caseCount];
1082                    for (int i=0; i<caseCount; i++) {
1083                        cases[i] = lowValue + i;
1084                        locations[i] = getLabel(opcodeAddress + readInt());
1085                    }
1086                }
1087                else {
1088                    int caseCount = readInt();
1089                    try {
1090                        cases = new int[caseCount];
1091                    }
1092                    catch (NegativeArraySizeException JavaDoc e) {
1093                        // TODO: raise an error.
1094
break;
1095                    }
1096                    locations = new Location[caseCount];
1097                    for (int i=0; i<caseCount; i++) {
1098                        cases[i] = readInt();
1099                        locations[i] = getLabel(opcodeAddress + readInt());
1100                    }
1101                }
1102
1103                assembler.switchBranch(cases, locations, defaultLocation);
1104                break;
1105
1106            case Opcode.WIDE:
1107                opcode = mByteCodes[++mAddress];
1108                switch (opcode) {
1109
1110                default:
1111                    // TODO: raise an error.
1112
break;
1113
1114                case Opcode.ILOAD: case Opcode.ISTORE:
1115                case Opcode.LLOAD: case Opcode.LSTORE:
1116                case Opcode.FLOAD: case Opcode.FSTORE:
1117                case Opcode.DLOAD: case Opcode.DSTORE:
1118                case Opcode.ALOAD: case Opcode.ASTORE:
1119
1120                    switch (opcode) {
1121                    case Opcode.ILOAD: case Opcode.ISTORE:
1122                        clazz = int.class;
1123                        break;
1124                    case Opcode.LLOAD: case Opcode.LSTORE:
1125                        clazz = long.class;
1126                        break;
1127                    case Opcode.FLOAD: case Opcode.FSTORE:
1128                        clazz = float.class;
1129                        break;
1130                    case Opcode.DLOAD: case Opcode.DSTORE:
1131                        clazz = double.class;
1132                        break;
1133                    case Opcode.ALOAD: case Opcode.ASTORE:
1134                        clazz = Object JavaDoc.class;
1135                        break;
1136                    default:
1137                        clazz = null;
1138                        break;
1139                    }
1140                    
1141                    index = readUnsignedShort();
1142
1143                    switch (opcode) {
1144                    case Opcode.ILOAD:
1145                    case Opcode.LLOAD:
1146                    case Opcode.FLOAD:
1147                    case Opcode.DLOAD:
1148                    case Opcode.ALOAD:
1149                        if (index == 0 && mHasThis) {
1150                            assembler.loadThis();
1151                        }
1152                        else {
1153                            assembler.loadLocal
1154                                (getLocalVariable(index, clazz));
1155                        }
1156                        break;
1157                    case Opcode.ISTORE:
1158                    case Opcode.LSTORE:
1159                    case Opcode.FSTORE:
1160                    case Opcode.DSTORE:
1161                    case Opcode.ASTORE:
1162                        if (index == 0 && mHasThis) {
1163                            // The "this" reference just got blown away.
1164
mHasThis = false;
1165                        }
1166                        assembler.storeLocal(getLocalVariable(index, clazz));
1167                        break;
1168                    }
1169                    break;
1170
1171                case Opcode.RET:
1172                    local = getLocalVariable
1173                        (readUnsignedShort(), Object JavaDoc.class);
1174                    assembler.ret(local);
1175                    break;
1176                    
1177                case Opcode.IINC:
1178                    local = getLocalVariable(readUnsignedShort(), int.class);
1179                    assembler.integerIncrement(local, readShort());
1180                    break;
1181                }
1182
1183                break;
1184            } // end huge switch
1185
} // end for loop
1186
}
1187
1188    private void gatherLabels() {
1189        mLabels = new HashMap();
1190        mCatchLocations = new HashMap(mExceptionHandlers.length * 2 + 1);
1191        Integer JavaDoc labelKey;
1192
1193        // Gather labels for any exception handlers.
1194
for (int i = mExceptionHandlers.length - 1; i >= 0; i--) {
1195            ExceptionHandler handler = mExceptionHandlers[i];
1196            labelKey = new Integer JavaDoc(handler.getStartLocation().getLocation());
1197            mLabels.put(labelKey, labelKey);
1198            labelKey = new Integer JavaDoc(handler.getEndLocation().getLocation());
1199            mLabels.put(labelKey, labelKey);
1200            labelKey = new Integer JavaDoc(handler.getCatchLocation().getLocation());
1201            List list = (List)mCatchLocations.get(labelKey);
1202            if (list == null) {
1203                list = new ArrayList(2);
1204                mCatchLocations.put(labelKey, list);
1205            }
1206            list.add(handler);
1207        }
1208
1209        // Now gather labels that occur within byte code.
1210
for (mAddress = 0; mAddress < mByteCodes.length; mAddress++) {
1211            byte opcode = mByteCodes[mAddress];
1212
1213            switch (opcode) {
1214
1215            default:
1216                // TODO: raise an error.
1217
break;
1218
1219                // Opcodes that use labels.
1220

1221            case Opcode.GOTO:
1222            case Opcode.JSR:
1223            case Opcode.IFNULL:
1224            case Opcode.IFNONNULL:
1225            case Opcode.IF_ACMPEQ:
1226            case Opcode.IF_ACMPNE:
1227            case Opcode.IFEQ:
1228            case Opcode.IFNE:
1229            case Opcode.IFLT:
1230            case Opcode.IFGE:
1231            case Opcode.IFGT:
1232            case Opcode.IFLE:
1233            case Opcode.IF_ICMPEQ:
1234            case Opcode.IF_ICMPNE:
1235            case Opcode.IF_ICMPLT:
1236            case Opcode.IF_ICMPGE:
1237            case Opcode.IF_ICMPGT:
1238            case Opcode.IF_ICMPLE:
1239                labelKey = new Integer JavaDoc(mAddress + readShort());
1240                mLabels.put(labelKey, labelKey);
1241                break;
1242
1243            case Opcode.GOTO_W:
1244            case Opcode.JSR_W:
1245                labelKey = new Integer JavaDoc(mAddress + readInt());
1246                mLabels.put(labelKey, labelKey);
1247                break;
1248
1249            case Opcode.TABLESWITCH:
1250            case Opcode.LOOKUPSWITCH:
1251                int opcodeAddress = mAddress;
1252                // Read padding until address is 32 bit word aligned.
1253
while (((mAddress + 1) & 3) != 0) {
1254                    ++mAddress;
1255                }
1256                
1257                // Read the default location.
1258
labelKey = new Integer JavaDoc(opcodeAddress + readInt());
1259                mLabels.put(labelKey, labelKey);
1260                
1261                if (opcode == Opcode.TABLESWITCH) {
1262                    int lowValue = readInt();
1263                    int highValue = readInt();
1264                    int caseCount = highValue - lowValue + 1;
1265
1266                    for (int i=0; i<caseCount; i++) {
1267                        // Read the branch location.
1268
labelKey = new Integer JavaDoc(opcodeAddress + readInt());
1269                        mLabels.put(labelKey, labelKey);
1270                    }
1271                }
1272                else {
1273                    int caseCount = readInt();
1274
1275                    for (int i=0; i<caseCount; i++) {
1276                        // Skip the case value.
1277
mAddress += 4;
1278                        // Read the branch location.
1279
labelKey = new Integer JavaDoc(opcodeAddress + readInt());
1280                        mLabels.put(labelKey, labelKey);
1281                    }
1282                }
1283                break;
1284
1285                // All other operations are skipped. The amount to skip
1286
// depends on the operand size.
1287

1288                // Opcodes with no operands...
1289

1290            case Opcode.NOP:
1291            case Opcode.BREAKPOINT:
1292            case Opcode.ACONST_NULL:
1293            case Opcode.ICONST_M1:
1294            case Opcode.ICONST_0:
1295            case Opcode.ICONST_1:
1296            case Opcode.ICONST_2:
1297            case Opcode.ICONST_3:
1298            case Opcode.ICONST_4:
1299            case Opcode.ICONST_5:
1300            case Opcode.LCONST_0:
1301            case Opcode.LCONST_1:
1302            case Opcode.FCONST_0:
1303            case Opcode.FCONST_1:
1304            case Opcode.FCONST_2:
1305            case Opcode.DCONST_0:
1306            case Opcode.DCONST_1:
1307            case Opcode.POP:
1308            case Opcode.POP2:
1309            case Opcode.DUP:
1310            case Opcode.DUP_X1:
1311            case Opcode.DUP_X2:
1312            case Opcode.DUP2:
1313            case Opcode.DUP2_X1:
1314            case Opcode.DUP2_X2:
1315            case Opcode.SWAP:
1316            case Opcode.IADD: case Opcode.LADD:
1317            case Opcode.FADD: case Opcode.DADD:
1318            case Opcode.ISUB: case Opcode.LSUB:
1319            case Opcode.FSUB: case Opcode.DSUB:
1320            case Opcode.IMUL: case Opcode.LMUL:
1321            case Opcode.FMUL: case Opcode.DMUL:
1322            case Opcode.IDIV: case Opcode.LDIV:
1323            case Opcode.FDIV: case Opcode.DDIV:
1324            case Opcode.IREM: case Opcode.LREM:
1325            case Opcode.FREM: case Opcode.DREM:
1326            case Opcode.INEG: case Opcode.LNEG:
1327            case Opcode.FNEG: case Opcode.DNEG:
1328            case Opcode.ISHL: case Opcode.LSHL:
1329            case Opcode.ISHR: case Opcode.LSHR:
1330            case Opcode.IUSHR: case Opcode.LUSHR:
1331            case Opcode.IAND: case Opcode.LAND:
1332            case Opcode.IOR: case Opcode.LOR:
1333            case Opcode.IXOR: case Opcode.LXOR:
1334            case Opcode.FCMPL: case Opcode.DCMPL:
1335            case Opcode.FCMPG: case Opcode.DCMPG:
1336            case Opcode.LCMP:
1337            case Opcode.I2L:
1338            case Opcode.I2F:
1339            case Opcode.I2D:
1340            case Opcode.L2I:
1341            case Opcode.L2F:
1342            case Opcode.L2D:
1343            case Opcode.F2I:
1344            case Opcode.F2L:
1345            case Opcode.F2D:
1346            case Opcode.D2I:
1347            case Opcode.D2L:
1348            case Opcode.D2F:
1349            case Opcode.I2B:
1350            case Opcode.I2C:
1351            case Opcode.I2S:
1352            case Opcode.IRETURN:
1353            case Opcode.LRETURN:
1354            case Opcode.FRETURN:
1355            case Opcode.DRETURN:
1356            case Opcode.ARETURN:
1357            case Opcode.RETURN:
1358            case Opcode.IALOAD:
1359            case Opcode.LALOAD:
1360            case Opcode.FALOAD:
1361            case Opcode.DALOAD:
1362            case Opcode.AALOAD:
1363            case Opcode.BALOAD:
1364            case Opcode.CALOAD:
1365            case Opcode.SALOAD:
1366            case Opcode.IASTORE:
1367            case Opcode.LASTORE:
1368            case Opcode.FASTORE:
1369            case Opcode.DASTORE:
1370            case Opcode.AASTORE:
1371            case Opcode.BASTORE:
1372            case Opcode.CASTORE:
1373            case Opcode.SASTORE:
1374            case Opcode.ARRAYLENGTH:
1375            case Opcode.ATHROW:
1376            case Opcode.MONITORENTER:
1377            case Opcode.MONITOREXIT:
1378            case Opcode.ILOAD_0: case Opcode.ISTORE_0:
1379            case Opcode.ILOAD_1: case Opcode.ISTORE_1:
1380            case Opcode.ILOAD_2: case Opcode.ISTORE_2:
1381            case Opcode.ILOAD_3: case Opcode.ISTORE_3:
1382            case Opcode.LLOAD_0: case Opcode.LSTORE_0:
1383            case Opcode.LLOAD_1: case Opcode.LSTORE_1:
1384            case Opcode.LLOAD_2: case Opcode.LSTORE_2:
1385            case Opcode.LLOAD_3: case Opcode.LSTORE_3:
1386            case Opcode.FLOAD_0: case Opcode.FSTORE_0:
1387            case Opcode.FLOAD_1: case Opcode.FSTORE_1:
1388            case Opcode.FLOAD_2: case Opcode.FSTORE_2:
1389            case Opcode.FLOAD_3: case Opcode.FSTORE_3:
1390            case Opcode.DLOAD_0: case Opcode.DSTORE_0:
1391            case Opcode.DLOAD_1: case Opcode.DSTORE_1:
1392            case Opcode.DLOAD_2: case Opcode.DSTORE_2:
1393            case Opcode.DLOAD_3: case Opcode.DSTORE_3:
1394            case Opcode.ALOAD_0: case Opcode.ASTORE_0:
1395            case Opcode.ALOAD_1: case Opcode.ASTORE_1:
1396            case Opcode.ALOAD_2: case Opcode.ASTORE_2:
1397            case Opcode.ALOAD_3: case Opcode.ASTORE_3:
1398                break;
1399
1400                // Opcodes with one operand byte...
1401

1402            case Opcode.LDC:
1403            case Opcode.ILOAD: case Opcode.ISTORE:
1404            case Opcode.LLOAD: case Opcode.LSTORE:
1405            case Opcode.FLOAD: case Opcode.FSTORE:
1406            case Opcode.DLOAD: case Opcode.DSTORE:
1407            case Opcode.ALOAD: case Opcode.ASTORE:
1408            case Opcode.RET:
1409            case Opcode.IINC:
1410            case Opcode.BIPUSH:
1411            case Opcode.NEWARRAY:
1412                mAddress += 1;
1413                break;
1414
1415                // Opcodes with two operand bytes...
1416

1417            case Opcode.LDC_W:
1418            case Opcode.LDC2_W:
1419            case Opcode.NEW:
1420            case Opcode.ANEWARRAY:
1421            case Opcode.CHECKCAST:
1422            case Opcode.INSTANCEOF:
1423            case Opcode.GETSTATIC:
1424            case Opcode.PUTSTATIC:
1425            case Opcode.GETFIELD:
1426            case Opcode.PUTFIELD:
1427            case Opcode.INVOKEVIRTUAL:
1428            case Opcode.INVOKESPECIAL:
1429            case Opcode.INVOKESTATIC:
1430            case Opcode.SIPUSH:
1431                mAddress += 2;
1432                break;
1433
1434                // Opcodes with three operand bytes...
1435

1436            case Opcode.MULTIANEWARRAY:
1437                mAddress += 3;
1438                break;
1439
1440                // Opcodes with four operand bytes...
1441

1442            case Opcode.INVOKEINTERFACE:
1443                mAddress += 4;
1444                break;
1445
1446                // Wide opcode has a variable sized operand.
1447

1448            case Opcode.WIDE:
1449                opcode = mByteCodes[++mAddress];
1450                mAddress += 2;
1451                if (opcode == Opcode.IINC) {
1452                    mAddress += 2;
1453                }
1454                break;
1455            } // end huge switch
1456
} // end for loop
1457
}
1458
1459    private int readByte() {
1460        return mByteCodes[++mAddress];
1461    }
1462
1463    private int readUnsignedByte() {
1464        return mByteCodes[++mAddress] & 0xff;
1465    }
1466
1467    private int readShort() {
1468        return (mByteCodes[++mAddress] << 8) | (mByteCodes[++mAddress] & 0xff);
1469    }
1470
1471    private int readUnsignedShort() {
1472        return
1473            ((mByteCodes[++mAddress] & 0xff) << 8) |
1474            ((mByteCodes[++mAddress] & 0xff) << 0);
1475    }
1476
1477    private int readInt() {
1478        return
1479            (mByteCodes[++mAddress] << 24) |
1480            ((mByteCodes[++mAddress] & 0xff) << 16) |
1481            ((mByteCodes[++mAddress] & 0xff) << 8) |
1482            ((mByteCodes[++mAddress] & 0xff) << 0);
1483    }
1484
1485    private LocalVariable getLocalVariable(int index, Class JavaDoc typeHint) {
1486        TypeDescriptor type = new TypeDescriptor(typeHint);
1487        LocalVariable local;
1488
1489        if (index >= mLocals.size()) {
1490            mLocals.setSize(index + 1);
1491            local = null;
1492        }
1493        else {
1494            local = (LocalVariable)mLocals.elementAt(index);
1495            if (local != null) {
1496                TypeDescriptor localType = local.getType();
1497                Class JavaDoc typeClass = type.getClassArg();
1498                Class JavaDoc localTypeClass = localType.getClassArg();
1499
1500                if (typeClass != null && !typeClass.isPrimitive()) {
1501                    typeClass = null;
1502                }
1503
1504                if (localTypeClass != null && !localTypeClass.isPrimitive()) {
1505                    localTypeClass = null;
1506                }
1507
1508                if (typeClass == null) {
1509                    if (localTypeClass == null) {
1510                        // Both types must represent objects. This is ok.
1511
}
1512                    else {
1513                        // Requesting object type, but existing is primitive.
1514
local = null;
1515                    }
1516                }
1517                else {
1518                    if (localTypeClass == null) {
1519                        // Requesting primitive type, but existing is object.
1520
local = null;
1521                    }
1522                    else {
1523                        // Primitive types must exactly match.
1524
if (typeClass != localTypeClass) {
1525                            local = null;
1526                        }
1527                    }
1528                }
1529            }
1530        }
1531
1532        if (local == null) {
1533            local = mAssembler.createLocalVariable(null, type);
1534            mLocals.setElementAt(local, index);
1535        }
1536
1537        return local;
1538    }
1539
1540    private void locateLabel() {
1541        Integer JavaDoc labelKey = new Integer JavaDoc(mAddress);
1542        Object JavaDoc labelValue = mLabels.get(labelKey);
1543        if (labelValue != null) {
1544            if (labelValue instanceof Label) {
1545                ((Label)labelValue).setLocation();
1546            }
1547            else {
1548                labelValue = mAssembler.createLabel().setLocation();
1549                mLabels.put(labelKey, labelValue);
1550            }
1551        }
1552
1553        List handlers = (List)mCatchLocations.get(labelKey);
1554
1555        if (handlers != null) {
1556            for (int i=0; i<handlers.size(); i++) {
1557                ExceptionHandler handler = (ExceptionHandler)handlers.get(i);
1558                Label start =
1559                    getLabel(handler.getStartLocation().getLocation());
1560                Label end =
1561                    getLabel(handler.getEndLocation().getLocation());
1562                String JavaDoc catchClassName;
1563                if (handler.getCatchType() == null) {
1564                    catchClassName = null;
1565                }
1566                else {
1567                    catchClassName = handler.getCatchType().getClassName();
1568                }
1569                mAssembler.exceptionHandler(start, end, catchClassName);
1570            }
1571        }
1572    }
1573
1574    private Label getLabel(int address) {
1575        Integer JavaDoc labelKey = new Integer JavaDoc(address);
1576        Object JavaDoc labelValue = mLabels.get(labelKey);
1577        // labelValue will never be null unless gatherLabels is broken.
1578
if (!(labelValue instanceof Label)) {
1579            labelValue = mAssembler.createLabel();
1580            mLabels.put(labelKey, labelValue);
1581        }
1582        return (Label)labelValue;
1583    }
1584}
1585
Popular Tags