Mercurial > hg > blitz_condensed
comparison src/com/go/trove/classfile/CodeDisassembler.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
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: 1.1 $-->, <!--$$JustDate:--> 00/12/27 <!-- $--> | |
62 */ | |
63 public class CodeDisassembler { | |
64 private final MethodInfo mMethod; | |
65 private final String mEnclosingClassName; | |
66 private final String 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 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 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.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.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.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 className = field.getParentClass().getClassName(); | |
530 if (mEnclosingClassName.equals(className)) { | |
531 className = null; | |
532 } | |
533 String 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 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.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.class; | |
806 break; | |
807 case Opcode.ALOAD_1: case Opcode.ASTORE_1: | |
808 index = 1; | |
809 clazz = Object.class; | |
810 break; | |
811 case Opcode.ALOAD_2: case Opcode.ASTORE_2: | |
812 index = 2; | |
813 clazz = Object.class; | |
814 break; | |
815 case Opcode.ALOAD_3: case Opcode.ASTORE_3: | |
816 index = 3; | |
817 clazz = Object.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.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 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 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 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.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.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 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(handler.getStartLocation().getLocation()); | |
1197 mLabels.put(labelKey, labelKey); | |
1198 labelKey = new Integer(handler.getEndLocation().getLocation()); | |
1199 mLabels.put(labelKey, labelKey); | |
1200 labelKey = new Integer(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(mAddress + readShort()); | |
1240 mLabels.put(labelKey, labelKey); | |
1241 break; | |
1242 | |
1243 case Opcode.GOTO_W: | |
1244 case Opcode.JSR_W: | |
1245 labelKey = new Integer(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(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(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(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 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 typeClass = type.getClassArg(); | |
1498 Class 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 labelKey = new Integer(mAddress); | |
1542 Object 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 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 labelKey = new Integer(address); | |
1576 Object 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 } |