rlm@10
|
1 /***
|
rlm@10
|
2 * ASM: a very small and fast Java bytecode manipulation framework
|
rlm@10
|
3 * Copyright (c) 2000-2005 INRIA, France Telecom
|
rlm@10
|
4 * All rights reserved.
|
rlm@10
|
5 *
|
rlm@10
|
6 * Redistribution and use in source and binary forms, with or without
|
rlm@10
|
7 * modification, are permitted provided that the following conditions
|
rlm@10
|
8 * are met:
|
rlm@10
|
9 * 1. Redistributions of source code must retain the above copyright
|
rlm@10
|
10 * notice, this list of conditions and the following disclaimer.
|
rlm@10
|
11 * 2. Redistributions in binary form must reproduce the above copyright
|
rlm@10
|
12 * notice, this list of conditions and the following disclaimer in the
|
rlm@10
|
13 * documentation and/or other materials provided with the distribution.
|
rlm@10
|
14 * 3. Neither the name of the copyright holders nor the names of its
|
rlm@10
|
15 * contributors may be used to endorse or promote products derived from
|
rlm@10
|
16 * this software without specific prior written permission.
|
rlm@10
|
17 *
|
rlm@10
|
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
rlm@10
|
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
rlm@10
|
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
rlm@10
|
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
rlm@10
|
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
rlm@10
|
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
rlm@10
|
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
rlm@10
|
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
rlm@10
|
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
rlm@10
|
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
rlm@10
|
28 * THE POSSIBILITY OF SUCH DAMAGE.
|
rlm@10
|
29 */
|
rlm@10
|
30 package clojure.asm.commons;
|
rlm@10
|
31
|
rlm@10
|
32 import java.util.ArrayList;
|
rlm@10
|
33 import java.util.HashMap;
|
rlm@10
|
34 import java.util.List;
|
rlm@10
|
35 import java.util.Map;
|
rlm@10
|
36
|
rlm@10
|
37 import clojure.asm.Label;
|
rlm@10
|
38 import clojure.asm.MethodAdapter;
|
rlm@10
|
39 import clojure.asm.MethodVisitor;
|
rlm@10
|
40 import clojure.asm.Opcodes;
|
rlm@10
|
41 import clojure.asm.Type;
|
rlm@10
|
42
|
rlm@10
|
43 /**
|
rlm@10
|
44 * A {@link MethodAdapter} that keeps track of stack map frame changes between
|
rlm@10
|
45 * {@link #visitFrame(int,int,Object[],int,Object[]) visitFrame} calls. This
|
rlm@10
|
46 * adapter must be used with the
|
rlm@10
|
47 * {@link clojure.asm.ClassReader#EXPAND_FRAMES} option. Each visit<i>XXX</i>
|
rlm@10
|
48 * instruction delegates to the next visitor in the chain, if any, and then
|
rlm@10
|
49 * simulates the effect of this instruction on the stack map frame, represented
|
rlm@10
|
50 * by {@link #locals} and {@link #stack}. The next visitor in the chain can get
|
rlm@10
|
51 * the state of the stack map frame <i>before</i> each instruction by reading
|
rlm@10
|
52 * the value of these fields in its visit<i>XXX</i> methods (this requires a
|
rlm@10
|
53 * reference to the AnalyzerAdapter that is before it in the chain).
|
rlm@10
|
54 *
|
rlm@10
|
55 * @author Eric Bruneton
|
rlm@10
|
56 */
|
rlm@10
|
57 public class AnalyzerAdapter extends MethodAdapter{
|
rlm@10
|
58
|
rlm@10
|
59 /**
|
rlm@10
|
60 * <code>List</code> of the local variable slots for current execution
|
rlm@10
|
61 * frame. Primitive types are represented by {@link Opcodes#TOP},
|
rlm@10
|
62 * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
|
rlm@10
|
63 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
|
rlm@10
|
64 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a
|
rlm@10
|
65 * two elements, the second one being TOP). Reference types are represented
|
rlm@10
|
66 * by String objects (representing internal names, or type descriptors for
|
rlm@10
|
67 * array types), and uninitialized types by Label objects (this label
|
rlm@10
|
68 * designates the NEW instruction that created this uninitialized value).
|
rlm@10
|
69 * This field is <tt>null</tt> for unreacheable instructions.
|
rlm@10
|
70 */
|
rlm@10
|
71 public List locals;
|
rlm@10
|
72
|
rlm@10
|
73 /**
|
rlm@10
|
74 * <code>List</code> of the operand stack slots for current execution
|
rlm@10
|
75 * frame. Primitive types are represented by {@link Opcodes#TOP},
|
rlm@10
|
76 * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
|
rlm@10
|
77 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
|
rlm@10
|
78 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a
|
rlm@10
|
79 * two elements, the second one being TOP). Reference types are represented
|
rlm@10
|
80 * by String objects (representing internal names, or type descriptors for
|
rlm@10
|
81 * array types), and uninitialized types by Label objects (this label
|
rlm@10
|
82 * designates the NEW instruction that created this uninitialized value).
|
rlm@10
|
83 * This field is <tt>null</tt> for unreacheable instructions.
|
rlm@10
|
84 */
|
rlm@10
|
85 public List stack;
|
rlm@10
|
86
|
rlm@10
|
87 /**
|
rlm@10
|
88 * The labels that designate the next instruction to be visited. May be
|
rlm@10
|
89 * <tt>null</tt>.
|
rlm@10
|
90 */
|
rlm@10
|
91 private List labels;
|
rlm@10
|
92
|
rlm@10
|
93 /**
|
rlm@10
|
94 * Information about uninitialized types in the current execution frame.
|
rlm@10
|
95 * This map associates internal names to Label objects. Each label
|
rlm@10
|
96 * designates a NEW instruction that created the currently uninitialized
|
rlm@10
|
97 * types, and the associated internal name represents the NEW operand, i.e.
|
rlm@10
|
98 * the final, initialized type value.
|
rlm@10
|
99 */
|
rlm@10
|
100 private Map uninitializedTypes;
|
rlm@10
|
101
|
rlm@10
|
102 /**
|
rlm@10
|
103 * The maximum stack size of this method.
|
rlm@10
|
104 */
|
rlm@10
|
105 private int maxStack;
|
rlm@10
|
106
|
rlm@10
|
107 /**
|
rlm@10
|
108 * The maximum number of local variables of this method.
|
rlm@10
|
109 */
|
rlm@10
|
110 private int maxLocals;
|
rlm@10
|
111
|
rlm@10
|
112 /**
|
rlm@10
|
113 * Creates a new {@link AnalyzerAdapter}.
|
rlm@10
|
114 *
|
rlm@10
|
115 * @param owner the owner's class name.
|
rlm@10
|
116 * @param access the method's access flags (see {@link Opcodes}).
|
rlm@10
|
117 * @param name the method's name.
|
rlm@10
|
118 * @param desc the method's descriptor (see {@link Type Type}).
|
rlm@10
|
119 * @param mv the method visitor to which this adapter delegates calls. May
|
rlm@10
|
120 * be <tt>null</tt>.
|
rlm@10
|
121 */
|
rlm@10
|
122 public AnalyzerAdapter(
|
rlm@10
|
123 final String owner,
|
rlm@10
|
124 final int access,
|
rlm@10
|
125 final String name,
|
rlm@10
|
126 final String desc,
|
rlm@10
|
127 final MethodVisitor mv){
|
rlm@10
|
128 super(mv);
|
rlm@10
|
129 locals = new ArrayList();
|
rlm@10
|
130 stack = new ArrayList();
|
rlm@10
|
131 uninitializedTypes = new HashMap();
|
rlm@10
|
132
|
rlm@10
|
133 if((access & Opcodes.ACC_STATIC) == 0)
|
rlm@10
|
134 {
|
rlm@10
|
135 if(name.equals("<init>"))
|
rlm@10
|
136 {
|
rlm@10
|
137 locals.add(Opcodes.UNINITIALIZED_THIS);
|
rlm@10
|
138 }
|
rlm@10
|
139 else
|
rlm@10
|
140 {
|
rlm@10
|
141 locals.add(owner);
|
rlm@10
|
142 }
|
rlm@10
|
143 }
|
rlm@10
|
144 Type[] types = Type.getArgumentTypes(desc);
|
rlm@10
|
145 for(int i = 0; i < types.length; ++i)
|
rlm@10
|
146 {
|
rlm@10
|
147 Type type = types[i];
|
rlm@10
|
148 switch(type.getSort())
|
rlm@10
|
149 {
|
rlm@10
|
150 case Type.BOOLEAN:
|
rlm@10
|
151 case Type.CHAR:
|
rlm@10
|
152 case Type.BYTE:
|
rlm@10
|
153 case Type.SHORT:
|
rlm@10
|
154 case Type.INT:
|
rlm@10
|
155 locals.add(Opcodes.INTEGER);
|
rlm@10
|
156 break;
|
rlm@10
|
157 case Type.FLOAT:
|
rlm@10
|
158 locals.add(Opcodes.FLOAT);
|
rlm@10
|
159 break;
|
rlm@10
|
160 case Type.LONG:
|
rlm@10
|
161 locals.add(Opcodes.LONG);
|
rlm@10
|
162 locals.add(Opcodes.TOP);
|
rlm@10
|
163 break;
|
rlm@10
|
164 case Type.DOUBLE:
|
rlm@10
|
165 locals.add(Opcodes.DOUBLE);
|
rlm@10
|
166 locals.add(Opcodes.TOP);
|
rlm@10
|
167 break;
|
rlm@10
|
168 case Type.ARRAY:
|
rlm@10
|
169 locals.add(types[i].getDescriptor());
|
rlm@10
|
170 break;
|
rlm@10
|
171 // case Type.OBJECT:
|
rlm@10
|
172 default:
|
rlm@10
|
173 locals.add(types[i].getInternalName());
|
rlm@10
|
174 }
|
rlm@10
|
175 }
|
rlm@10
|
176 }
|
rlm@10
|
177
|
rlm@10
|
178 public void visitFrame(
|
rlm@10
|
179 final int type,
|
rlm@10
|
180 final int nLocal,
|
rlm@10
|
181 final Object[] local,
|
rlm@10
|
182 final int nStack,
|
rlm@10
|
183 final Object[] stack){
|
rlm@10
|
184 if(type != Opcodes.F_NEW)
|
rlm@10
|
185 { // uncompressed frame
|
rlm@10
|
186 throw new IllegalStateException("ClassReader.accept() should be called with EXPAND_FRAMES flag");
|
rlm@10
|
187 }
|
rlm@10
|
188
|
rlm@10
|
189 if(mv != null)
|
rlm@10
|
190 {
|
rlm@10
|
191 mv.visitFrame(type, nLocal, local, nStack, stack);
|
rlm@10
|
192 }
|
rlm@10
|
193
|
rlm@10
|
194 if(this.locals != null)
|
rlm@10
|
195 {
|
rlm@10
|
196 this.locals.clear();
|
rlm@10
|
197 this.stack.clear();
|
rlm@10
|
198 }
|
rlm@10
|
199 else
|
rlm@10
|
200 {
|
rlm@10
|
201 this.locals = new ArrayList();
|
rlm@10
|
202 this.stack = new ArrayList();
|
rlm@10
|
203 }
|
rlm@10
|
204 visitFrameTypes(nLocal, local, this.locals);
|
rlm@10
|
205 visitFrameTypes(nStack, stack, this.stack);
|
rlm@10
|
206 maxStack = Math.max(maxStack, this.stack.size());
|
rlm@10
|
207 }
|
rlm@10
|
208
|
rlm@10
|
209 private void visitFrameTypes(
|
rlm@10
|
210 final int n,
|
rlm@10
|
211 final Object[] types,
|
rlm@10
|
212 final List result){
|
rlm@10
|
213 for(int i = 0; i < n; ++i)
|
rlm@10
|
214 {
|
rlm@10
|
215 Object type = types[i];
|
rlm@10
|
216 result.add(type);
|
rlm@10
|
217 if(type == Opcodes.LONG || type == Opcodes.DOUBLE)
|
rlm@10
|
218 {
|
rlm@10
|
219 result.add(Opcodes.TOP);
|
rlm@10
|
220 }
|
rlm@10
|
221 }
|
rlm@10
|
222 }
|
rlm@10
|
223
|
rlm@10
|
224 public void visitInsn(final int opcode){
|
rlm@10
|
225 if(mv != null)
|
rlm@10
|
226 {
|
rlm@10
|
227 mv.visitInsn(opcode);
|
rlm@10
|
228 }
|
rlm@10
|
229 execute(opcode, 0, null);
|
rlm@10
|
230 if((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
|
rlm@10
|
231 || opcode == Opcodes.ATHROW)
|
rlm@10
|
232 {
|
rlm@10
|
233 this.locals = null;
|
rlm@10
|
234 this.stack = null;
|
rlm@10
|
235 }
|
rlm@10
|
236 }
|
rlm@10
|
237
|
rlm@10
|
238 public void visitIntInsn(final int opcode, final int operand){
|
rlm@10
|
239 if(mv != null)
|
rlm@10
|
240 {
|
rlm@10
|
241 mv.visitIntInsn(opcode, operand);
|
rlm@10
|
242 }
|
rlm@10
|
243 execute(opcode, operand, null);
|
rlm@10
|
244 }
|
rlm@10
|
245
|
rlm@10
|
246 public void visitVarInsn(final int opcode, final int var){
|
rlm@10
|
247 if(mv != null)
|
rlm@10
|
248 {
|
rlm@10
|
249 mv.visitVarInsn(opcode, var);
|
rlm@10
|
250 }
|
rlm@10
|
251 execute(opcode, var, null);
|
rlm@10
|
252 }
|
rlm@10
|
253
|
rlm@10
|
254 public void visitTypeInsn(final int opcode, final String desc){
|
rlm@10
|
255 if(opcode == Opcodes.NEW)
|
rlm@10
|
256 {
|
rlm@10
|
257 if(labels == null)
|
rlm@10
|
258 {
|
rlm@10
|
259 Label l = new Label();
|
rlm@10
|
260 labels = new ArrayList(3);
|
rlm@10
|
261 labels.add(l);
|
rlm@10
|
262 if(mv != null)
|
rlm@10
|
263 {
|
rlm@10
|
264 mv.visitLabel(l);
|
rlm@10
|
265 }
|
rlm@10
|
266 }
|
rlm@10
|
267 for(int i = 0; i < labels.size(); ++i)
|
rlm@10
|
268 {
|
rlm@10
|
269 uninitializedTypes.put(labels.get(i), desc);
|
rlm@10
|
270 }
|
rlm@10
|
271 }
|
rlm@10
|
272 if(mv != null)
|
rlm@10
|
273 {
|
rlm@10
|
274 mv.visitTypeInsn(opcode, desc);
|
rlm@10
|
275 }
|
rlm@10
|
276 execute(opcode, 0, desc);
|
rlm@10
|
277 }
|
rlm@10
|
278
|
rlm@10
|
279 public void visitFieldInsn(
|
rlm@10
|
280 final int opcode,
|
rlm@10
|
281 final String owner,
|
rlm@10
|
282 final String name,
|
rlm@10
|
283 final String desc){
|
rlm@10
|
284 if(mv != null)
|
rlm@10
|
285 {
|
rlm@10
|
286 mv.visitFieldInsn(opcode, owner, name, desc);
|
rlm@10
|
287 }
|
rlm@10
|
288 execute(opcode, 0, desc);
|
rlm@10
|
289 }
|
rlm@10
|
290
|
rlm@10
|
291 public void visitMethodInsn(
|
rlm@10
|
292 final int opcode,
|
rlm@10
|
293 final String owner,
|
rlm@10
|
294 final String name,
|
rlm@10
|
295 final String desc){
|
rlm@10
|
296 if(mv != null)
|
rlm@10
|
297 {
|
rlm@10
|
298 mv.visitMethodInsn(opcode, owner, name, desc);
|
rlm@10
|
299 }
|
rlm@10
|
300 pop(desc);
|
rlm@10
|
301 if(opcode != Opcodes.INVOKESTATIC)
|
rlm@10
|
302 {
|
rlm@10
|
303 Object t = pop();
|
rlm@10
|
304 if(opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<')
|
rlm@10
|
305 {
|
rlm@10
|
306 Object u;
|
rlm@10
|
307 if(t == Opcodes.UNINITIALIZED_THIS)
|
rlm@10
|
308 {
|
rlm@10
|
309 u = owner;
|
rlm@10
|
310 }
|
rlm@10
|
311 else
|
rlm@10
|
312 {
|
rlm@10
|
313 u = uninitializedTypes.get(t);
|
rlm@10
|
314 }
|
rlm@10
|
315 for(int i = 0; i < locals.size(); ++i)
|
rlm@10
|
316 {
|
rlm@10
|
317 if(locals.get(i) == t)
|
rlm@10
|
318 {
|
rlm@10
|
319 locals.set(i, u);
|
rlm@10
|
320 }
|
rlm@10
|
321 }
|
rlm@10
|
322 for(int i = 0; i < stack.size(); ++i)
|
rlm@10
|
323 {
|
rlm@10
|
324 if(stack.get(i) == t)
|
rlm@10
|
325 {
|
rlm@10
|
326 stack.set(i, u);
|
rlm@10
|
327 }
|
rlm@10
|
328 }
|
rlm@10
|
329 }
|
rlm@10
|
330 }
|
rlm@10
|
331 pushDesc(desc);
|
rlm@10
|
332 labels = null;
|
rlm@10
|
333 }
|
rlm@10
|
334
|
rlm@10
|
335 public void visitJumpInsn(final int opcode, final Label label){
|
rlm@10
|
336 if(mv != null)
|
rlm@10
|
337 {
|
rlm@10
|
338 mv.visitJumpInsn(opcode, label);
|
rlm@10
|
339 }
|
rlm@10
|
340 execute(opcode, 0, null);
|
rlm@10
|
341 if(opcode == Opcodes.GOTO)
|
rlm@10
|
342 {
|
rlm@10
|
343 this.locals = null;
|
rlm@10
|
344 this.stack = null;
|
rlm@10
|
345 }
|
rlm@10
|
346 }
|
rlm@10
|
347
|
rlm@10
|
348 public void visitLabel(final Label label){
|
rlm@10
|
349 if(mv != null)
|
rlm@10
|
350 {
|
rlm@10
|
351 mv.visitLabel(label);
|
rlm@10
|
352 }
|
rlm@10
|
353 if(labels == null)
|
rlm@10
|
354 {
|
rlm@10
|
355 labels = new ArrayList(3);
|
rlm@10
|
356 }
|
rlm@10
|
357 labels.add(label);
|
rlm@10
|
358 }
|
rlm@10
|
359
|
rlm@10
|
360 public void visitLdcInsn(final Object cst){
|
rlm@10
|
361 if(mv != null)
|
rlm@10
|
362 {
|
rlm@10
|
363 mv.visitLdcInsn(cst);
|
rlm@10
|
364 }
|
rlm@10
|
365 if(cst instanceof Integer)
|
rlm@10
|
366 {
|
rlm@10
|
367 push(Opcodes.INTEGER);
|
rlm@10
|
368 }
|
rlm@10
|
369 else if(cst instanceof Long)
|
rlm@10
|
370 {
|
rlm@10
|
371 push(Opcodes.LONG);
|
rlm@10
|
372 push(Opcodes.TOP);
|
rlm@10
|
373 }
|
rlm@10
|
374 else if(cst instanceof Float)
|
rlm@10
|
375 {
|
rlm@10
|
376 push(Opcodes.FLOAT);
|
rlm@10
|
377 }
|
rlm@10
|
378 else if(cst instanceof Double)
|
rlm@10
|
379 {
|
rlm@10
|
380 push(Opcodes.DOUBLE);
|
rlm@10
|
381 push(Opcodes.TOP);
|
rlm@10
|
382 }
|
rlm@10
|
383 else if(cst instanceof String)
|
rlm@10
|
384 {
|
rlm@10
|
385 push("java/lang/String");
|
rlm@10
|
386 }
|
rlm@10
|
387 else if(cst instanceof Type)
|
rlm@10
|
388 {
|
rlm@10
|
389 push("java/lang/Class");
|
rlm@10
|
390 }
|
rlm@10
|
391 else
|
rlm@10
|
392 {
|
rlm@10
|
393 throw new IllegalArgumentException();
|
rlm@10
|
394 }
|
rlm@10
|
395 labels = null;
|
rlm@10
|
396 }
|
rlm@10
|
397
|
rlm@10
|
398 public void visitIincInsn(final int var, final int increment){
|
rlm@10
|
399 if(mv != null)
|
rlm@10
|
400 {
|
rlm@10
|
401 mv.visitIincInsn(var, increment);
|
rlm@10
|
402 }
|
rlm@10
|
403 execute(Opcodes.IINC, var, null);
|
rlm@10
|
404 }
|
rlm@10
|
405
|
rlm@10
|
406 public void visitTableSwitchInsn(
|
rlm@10
|
407 final int min,
|
rlm@10
|
408 final int max,
|
rlm@10
|
409 final Label dflt,
|
rlm@10
|
410 final Label labels[]){
|
rlm@10
|
411 if(mv != null)
|
rlm@10
|
412 {
|
rlm@10
|
413 mv.visitTableSwitchInsn(min, max, dflt, labels);
|
rlm@10
|
414 }
|
rlm@10
|
415 execute(Opcodes.TABLESWITCH, 0, null);
|
rlm@10
|
416 this.locals = null;
|
rlm@10
|
417 this.stack = null;
|
rlm@10
|
418 }
|
rlm@10
|
419
|
rlm@10
|
420 public void visitLookupSwitchInsn(
|
rlm@10
|
421 final Label dflt,
|
rlm@10
|
422 final int keys[],
|
rlm@10
|
423 final Label labels[]){
|
rlm@10
|
424 if(mv != null)
|
rlm@10
|
425 {
|
rlm@10
|
426 mv.visitLookupSwitchInsn(dflt, keys, labels);
|
rlm@10
|
427 }
|
rlm@10
|
428 execute(Opcodes.LOOKUPSWITCH, 0, null);
|
rlm@10
|
429 this.locals = null;
|
rlm@10
|
430 this.stack = null;
|
rlm@10
|
431 }
|
rlm@10
|
432
|
rlm@10
|
433 public void visitMultiANewArrayInsn(final String desc, final int dims){
|
rlm@10
|
434 if(mv != null)
|
rlm@10
|
435 {
|
rlm@10
|
436 mv.visitMultiANewArrayInsn(desc, dims);
|
rlm@10
|
437 }
|
rlm@10
|
438 execute(Opcodes.MULTIANEWARRAY, dims, desc);
|
rlm@10
|
439 }
|
rlm@10
|
440
|
rlm@10
|
441 public void visitMaxs(final int maxStack, final int maxLocals){
|
rlm@10
|
442 if(mv != null)
|
rlm@10
|
443 {
|
rlm@10
|
444 this.maxStack = Math.max(this.maxStack, maxStack);
|
rlm@10
|
445 this.maxLocals = Math.max(this.maxLocals, maxLocals);
|
rlm@10
|
446 mv.visitMaxs(this.maxStack, this.maxLocals);
|
rlm@10
|
447 }
|
rlm@10
|
448 }
|
rlm@10
|
449
|
rlm@10
|
450 // ------------------------------------------------------------------------
|
rlm@10
|
451
|
rlm@10
|
452 private Object get(final int local){
|
rlm@10
|
453 maxLocals = Math.max(maxLocals, local);
|
rlm@10
|
454 return local < locals.size() ? locals.get(local) : Opcodes.TOP;
|
rlm@10
|
455 }
|
rlm@10
|
456
|
rlm@10
|
457 private void set(final int local, final Object type){
|
rlm@10
|
458 maxLocals = Math.max(maxLocals, local);
|
rlm@10
|
459 while(local >= locals.size())
|
rlm@10
|
460 {
|
rlm@10
|
461 locals.add(Opcodes.TOP);
|
rlm@10
|
462 }
|
rlm@10
|
463 locals.set(local, type);
|
rlm@10
|
464 }
|
rlm@10
|
465
|
rlm@10
|
466 private void push(final Object type){
|
rlm@10
|
467 stack.add(type);
|
rlm@10
|
468 maxStack = Math.max(maxStack, stack.size());
|
rlm@10
|
469 }
|
rlm@10
|
470
|
rlm@10
|
471 private void pushDesc(final String desc){
|
rlm@10
|
472 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
|
rlm@10
|
473 switch(desc.charAt(index))
|
rlm@10
|
474 {
|
rlm@10
|
475 case'V':
|
rlm@10
|
476 return;
|
rlm@10
|
477 case'Z':
|
rlm@10
|
478 case'C':
|
rlm@10
|
479 case'B':
|
rlm@10
|
480 case'S':
|
rlm@10
|
481 case'I':
|
rlm@10
|
482 push(Opcodes.INTEGER);
|
rlm@10
|
483 return;
|
rlm@10
|
484 case'F':
|
rlm@10
|
485 push(Opcodes.FLOAT);
|
rlm@10
|
486 return;
|
rlm@10
|
487 case'J':
|
rlm@10
|
488 push(Opcodes.LONG);
|
rlm@10
|
489 push(Opcodes.TOP);
|
rlm@10
|
490 return;
|
rlm@10
|
491 case'D':
|
rlm@10
|
492 push(Opcodes.DOUBLE);
|
rlm@10
|
493 push(Opcodes.TOP);
|
rlm@10
|
494 return;
|
rlm@10
|
495 case'[':
|
rlm@10
|
496 if(index == 0)
|
rlm@10
|
497 {
|
rlm@10
|
498 push(desc);
|
rlm@10
|
499 }
|
rlm@10
|
500 else
|
rlm@10
|
501 {
|
rlm@10
|
502 push(desc.substring(index, desc.length()));
|
rlm@10
|
503 }
|
rlm@10
|
504 break;
|
rlm@10
|
505 // case 'L':
|
rlm@10
|
506 default:
|
rlm@10
|
507 if(index == 0)
|
rlm@10
|
508 {
|
rlm@10
|
509 push(desc.substring(1, desc.length() - 1));
|
rlm@10
|
510 }
|
rlm@10
|
511 else
|
rlm@10
|
512 {
|
rlm@10
|
513 push(desc.substring(index + 1, desc.length() - 1));
|
rlm@10
|
514 }
|
rlm@10
|
515 return;
|
rlm@10
|
516 }
|
rlm@10
|
517 }
|
rlm@10
|
518
|
rlm@10
|
519 private Object pop(){
|
rlm@10
|
520 return stack.remove(stack.size() - 1);
|
rlm@10
|
521 }
|
rlm@10
|
522
|
rlm@10
|
523 private void pop(final int n){
|
rlm@10
|
524 int size = stack.size();
|
rlm@10
|
525 int end = size - n;
|
rlm@10
|
526 for(int i = size - 1; i >= end; --i)
|
rlm@10
|
527 {
|
rlm@10
|
528 stack.remove(i);
|
rlm@10
|
529 }
|
rlm@10
|
530 }
|
rlm@10
|
531
|
rlm@10
|
532 private void pop(final String desc){
|
rlm@10
|
533 char c = desc.charAt(0);
|
rlm@10
|
534 if(c == '(')
|
rlm@10
|
535 {
|
rlm@10
|
536 int n = 0;
|
rlm@10
|
537 Type[] types = Type.getArgumentTypes(desc);
|
rlm@10
|
538 for(int i = 0; i < types.length; ++i)
|
rlm@10
|
539 {
|
rlm@10
|
540 n += types[i].getSize();
|
rlm@10
|
541 }
|
rlm@10
|
542 pop(n);
|
rlm@10
|
543 }
|
rlm@10
|
544 else if(c == 'J' || c == 'D')
|
rlm@10
|
545 {
|
rlm@10
|
546 pop(2);
|
rlm@10
|
547 }
|
rlm@10
|
548 else
|
rlm@10
|
549 {
|
rlm@10
|
550 pop(1);
|
rlm@10
|
551 }
|
rlm@10
|
552 }
|
rlm@10
|
553
|
rlm@10
|
554 private void execute(final int opcode, final int iarg, final String sarg){
|
rlm@10
|
555 if(this.locals == null)
|
rlm@10
|
556 {
|
rlm@10
|
557 return;
|
rlm@10
|
558 }
|
rlm@10
|
559 Object t1, t2, t3, t4;
|
rlm@10
|
560 switch(opcode)
|
rlm@10
|
561 {
|
rlm@10
|
562 case Opcodes.NOP:
|
rlm@10
|
563 case Opcodes.INEG:
|
rlm@10
|
564 case Opcodes.LNEG:
|
rlm@10
|
565 case Opcodes.FNEG:
|
rlm@10
|
566 case Opcodes.DNEG:
|
rlm@10
|
567 case Opcodes.I2B:
|
rlm@10
|
568 case Opcodes.I2C:
|
rlm@10
|
569 case Opcodes.I2S:
|
rlm@10
|
570 case Opcodes.GOTO:
|
rlm@10
|
571 case Opcodes.RETURN:
|
rlm@10
|
572 break;
|
rlm@10
|
573 case Opcodes.ACONST_NULL:
|
rlm@10
|
574 push(Opcodes.NULL);
|
rlm@10
|
575 break;
|
rlm@10
|
576 case Opcodes.ICONST_M1:
|
rlm@10
|
577 case Opcodes.ICONST_0:
|
rlm@10
|
578 case Opcodes.ICONST_1:
|
rlm@10
|
579 case Opcodes.ICONST_2:
|
rlm@10
|
580 case Opcodes.ICONST_3:
|
rlm@10
|
581 case Opcodes.ICONST_4:
|
rlm@10
|
582 case Opcodes.ICONST_5:
|
rlm@10
|
583 case Opcodes.BIPUSH:
|
rlm@10
|
584 case Opcodes.SIPUSH:
|
rlm@10
|
585 push(Opcodes.INTEGER);
|
rlm@10
|
586 break;
|
rlm@10
|
587 case Opcodes.LCONST_0:
|
rlm@10
|
588 case Opcodes.LCONST_1:
|
rlm@10
|
589 push(Opcodes.LONG);
|
rlm@10
|
590 push(Opcodes.TOP);
|
rlm@10
|
591 break;
|
rlm@10
|
592 case Opcodes.FCONST_0:
|
rlm@10
|
593 case Opcodes.FCONST_1:
|
rlm@10
|
594 case Opcodes.FCONST_2:
|
rlm@10
|
595 push(Opcodes.FLOAT);
|
rlm@10
|
596 break;
|
rlm@10
|
597 case Opcodes.DCONST_0:
|
rlm@10
|
598 case Opcodes.DCONST_1:
|
rlm@10
|
599 push(Opcodes.DOUBLE);
|
rlm@10
|
600 push(Opcodes.TOP);
|
rlm@10
|
601 break;
|
rlm@10
|
602 case Opcodes.ILOAD:
|
rlm@10
|
603 case Opcodes.FLOAD:
|
rlm@10
|
604 case Opcodes.ALOAD:
|
rlm@10
|
605 push(get(iarg));
|
rlm@10
|
606 break;
|
rlm@10
|
607 case Opcodes.LLOAD:
|
rlm@10
|
608 case Opcodes.DLOAD:
|
rlm@10
|
609 push(get(iarg));
|
rlm@10
|
610 push(Opcodes.TOP);
|
rlm@10
|
611 break;
|
rlm@10
|
612 case Opcodes.IALOAD:
|
rlm@10
|
613 case Opcodes.BALOAD:
|
rlm@10
|
614 case Opcodes.CALOAD:
|
rlm@10
|
615 case Opcodes.SALOAD:
|
rlm@10
|
616 pop(2);
|
rlm@10
|
617 push(Opcodes.INTEGER);
|
rlm@10
|
618 break;
|
rlm@10
|
619 case Opcodes.LALOAD:
|
rlm@10
|
620 case Opcodes.D2L:
|
rlm@10
|
621 pop(2);
|
rlm@10
|
622 push(Opcodes.LONG);
|
rlm@10
|
623 push(Opcodes.TOP);
|
rlm@10
|
624 break;
|
rlm@10
|
625 case Opcodes.FALOAD:
|
rlm@10
|
626 pop(2);
|
rlm@10
|
627 push(Opcodes.FLOAT);
|
rlm@10
|
628 break;
|
rlm@10
|
629 case Opcodes.DALOAD:
|
rlm@10
|
630 case Opcodes.L2D:
|
rlm@10
|
631 pop(2);
|
rlm@10
|
632 push(Opcodes.DOUBLE);
|
rlm@10
|
633 push(Opcodes.TOP);
|
rlm@10
|
634 break;
|
rlm@10
|
635 case Opcodes.AALOAD:
|
rlm@10
|
636 pop(1);
|
rlm@10
|
637 t1 = pop();
|
rlm@10
|
638 pushDesc(((String) t1).substring(1));
|
rlm@10
|
639 break;
|
rlm@10
|
640 case Opcodes.ISTORE:
|
rlm@10
|
641 case Opcodes.FSTORE:
|
rlm@10
|
642 case Opcodes.ASTORE:
|
rlm@10
|
643 t1 = pop();
|
rlm@10
|
644 set(iarg, t1);
|
rlm@10
|
645 if(iarg > 0)
|
rlm@10
|
646 {
|
rlm@10
|
647 t2 = get(iarg - 1);
|
rlm@10
|
648 if(t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE)
|
rlm@10
|
649 {
|
rlm@10
|
650 set(iarg - 1, Opcodes.TOP);
|
rlm@10
|
651 }
|
rlm@10
|
652 }
|
rlm@10
|
653 break;
|
rlm@10
|
654 case Opcodes.LSTORE:
|
rlm@10
|
655 case Opcodes.DSTORE:
|
rlm@10
|
656 pop(1);
|
rlm@10
|
657 t1 = pop();
|
rlm@10
|
658 set(iarg, t1);
|
rlm@10
|
659 set(iarg + 1, Opcodes.TOP);
|
rlm@10
|
660 if(iarg > 0)
|
rlm@10
|
661 {
|
rlm@10
|
662 t2 = get(iarg - 1);
|
rlm@10
|
663 if(t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE)
|
rlm@10
|
664 {
|
rlm@10
|
665 set(iarg - 1, Opcodes.TOP);
|
rlm@10
|
666 }
|
rlm@10
|
667 }
|
rlm@10
|
668 break;
|
rlm@10
|
669 case Opcodes.IASTORE:
|
rlm@10
|
670 case Opcodes.BASTORE:
|
rlm@10
|
671 case Opcodes.CASTORE:
|
rlm@10
|
672 case Opcodes.SASTORE:
|
rlm@10
|
673 case Opcodes.FASTORE:
|
rlm@10
|
674 case Opcodes.AASTORE:
|
rlm@10
|
675 pop(3);
|
rlm@10
|
676 break;
|
rlm@10
|
677 case Opcodes.LASTORE:
|
rlm@10
|
678 case Opcodes.DASTORE:
|
rlm@10
|
679 pop(4);
|
rlm@10
|
680 break;
|
rlm@10
|
681 case Opcodes.POP:
|
rlm@10
|
682 case Opcodes.IFEQ:
|
rlm@10
|
683 case Opcodes.IFNE:
|
rlm@10
|
684 case Opcodes.IFLT:
|
rlm@10
|
685 case Opcodes.IFGE:
|
rlm@10
|
686 case Opcodes.IFGT:
|
rlm@10
|
687 case Opcodes.IFLE:
|
rlm@10
|
688 case Opcodes.IRETURN:
|
rlm@10
|
689 case Opcodes.FRETURN:
|
rlm@10
|
690 case Opcodes.ARETURN:
|
rlm@10
|
691 case Opcodes.TABLESWITCH:
|
rlm@10
|
692 case Opcodes.LOOKUPSWITCH:
|
rlm@10
|
693 case Opcodes.ATHROW:
|
rlm@10
|
694 case Opcodes.MONITORENTER:
|
rlm@10
|
695 case Opcodes.MONITOREXIT:
|
rlm@10
|
696 case Opcodes.IFNULL:
|
rlm@10
|
697 case Opcodes.IFNONNULL:
|
rlm@10
|
698 pop(1);
|
rlm@10
|
699 break;
|
rlm@10
|
700 case Opcodes.POP2:
|
rlm@10
|
701 case Opcodes.IF_ICMPEQ:
|
rlm@10
|
702 case Opcodes.IF_ICMPNE:
|
rlm@10
|
703 case Opcodes.IF_ICMPLT:
|
rlm@10
|
704 case Opcodes.IF_ICMPGE:
|
rlm@10
|
705 case Opcodes.IF_ICMPGT:
|
rlm@10
|
706 case Opcodes.IF_ICMPLE:
|
rlm@10
|
707 case Opcodes.IF_ACMPEQ:
|
rlm@10
|
708 case Opcodes.IF_ACMPNE:
|
rlm@10
|
709 case Opcodes.LRETURN:
|
rlm@10
|
710 case Opcodes.DRETURN:
|
rlm@10
|
711 pop(2);
|
rlm@10
|
712 break;
|
rlm@10
|
713 case Opcodes.DUP:
|
rlm@10
|
714 t1 = pop();
|
rlm@10
|
715 push(t1);
|
rlm@10
|
716 push(t1);
|
rlm@10
|
717 break;
|
rlm@10
|
718 case Opcodes.DUP_X1:
|
rlm@10
|
719 t1 = pop();
|
rlm@10
|
720 t2 = pop();
|
rlm@10
|
721 push(t1);
|
rlm@10
|
722 push(t2);
|
rlm@10
|
723 push(t1);
|
rlm@10
|
724 break;
|
rlm@10
|
725 case Opcodes.DUP_X2:
|
rlm@10
|
726 t1 = pop();
|
rlm@10
|
727 t2 = pop();
|
rlm@10
|
728 t3 = pop();
|
rlm@10
|
729 push(t1);
|
rlm@10
|
730 push(t3);
|
rlm@10
|
731 push(t2);
|
rlm@10
|
732 push(t1);
|
rlm@10
|
733 break;
|
rlm@10
|
734 case Opcodes.DUP2:
|
rlm@10
|
735 t1 = pop();
|
rlm@10
|
736 t2 = pop();
|
rlm@10
|
737 push(t2);
|
rlm@10
|
738 push(t1);
|
rlm@10
|
739 push(t2);
|
rlm@10
|
740 push(t1);
|
rlm@10
|
741 break;
|
rlm@10
|
742 case Opcodes.DUP2_X1:
|
rlm@10
|
743 t1 = pop();
|
rlm@10
|
744 t2 = pop();
|
rlm@10
|
745 t3 = pop();
|
rlm@10
|
746 push(t2);
|
rlm@10
|
747 push(t1);
|
rlm@10
|
748 push(t3);
|
rlm@10
|
749 push(t2);
|
rlm@10
|
750 push(t1);
|
rlm@10
|
751 break;
|
rlm@10
|
752 case Opcodes.DUP2_X2:
|
rlm@10
|
753 t1 = pop();
|
rlm@10
|
754 t2 = pop();
|
rlm@10
|
755 t3 = pop();
|
rlm@10
|
756 t4 = pop();
|
rlm@10
|
757 push(t2);
|
rlm@10
|
758 push(t1);
|
rlm@10
|
759 push(t4);
|
rlm@10
|
760 push(t3);
|
rlm@10
|
761 push(t2);
|
rlm@10
|
762 push(t1);
|
rlm@10
|
763 break;
|
rlm@10
|
764 case Opcodes.SWAP:
|
rlm@10
|
765 t1 = pop();
|
rlm@10
|
766 t2 = pop();
|
rlm@10
|
767 push(t1);
|
rlm@10
|
768 push(t2);
|
rlm@10
|
769 break;
|
rlm@10
|
770 case Opcodes.IADD:
|
rlm@10
|
771 case Opcodes.ISUB:
|
rlm@10
|
772 case Opcodes.IMUL:
|
rlm@10
|
773 case Opcodes.IDIV:
|
rlm@10
|
774 case Opcodes.IREM:
|
rlm@10
|
775 case Opcodes.IAND:
|
rlm@10
|
776 case Opcodes.IOR:
|
rlm@10
|
777 case Opcodes.IXOR:
|
rlm@10
|
778 case Opcodes.ISHL:
|
rlm@10
|
779 case Opcodes.ISHR:
|
rlm@10
|
780 case Opcodes.IUSHR:
|
rlm@10
|
781 case Opcodes.L2I:
|
rlm@10
|
782 case Opcodes.D2I:
|
rlm@10
|
783 case Opcodes.FCMPL:
|
rlm@10
|
784 case Opcodes.FCMPG:
|
rlm@10
|
785 pop(2);
|
rlm@10
|
786 push(Opcodes.INTEGER);
|
rlm@10
|
787 break;
|
rlm@10
|
788 case Opcodes.LADD:
|
rlm@10
|
789 case Opcodes.LSUB:
|
rlm@10
|
790 case Opcodes.LMUL:
|
rlm@10
|
791 case Opcodes.LDIV:
|
rlm@10
|
792 case Opcodes.LREM:
|
rlm@10
|
793 case Opcodes.LAND:
|
rlm@10
|
794 case Opcodes.LOR:
|
rlm@10
|
795 case Opcodes.LXOR:
|
rlm@10
|
796 pop(4);
|
rlm@10
|
797 push(Opcodes.LONG);
|
rlm@10
|
798 push(Opcodes.TOP);
|
rlm@10
|
799 break;
|
rlm@10
|
800 case Opcodes.FADD:
|
rlm@10
|
801 case Opcodes.FSUB:
|
rlm@10
|
802 case Opcodes.FMUL:
|
rlm@10
|
803 case Opcodes.FDIV:
|
rlm@10
|
804 case Opcodes.FREM:
|
rlm@10
|
805 case Opcodes.L2F:
|
rlm@10
|
806 case Opcodes.D2F:
|
rlm@10
|
807 pop(2);
|
rlm@10
|
808 push(Opcodes.FLOAT);
|
rlm@10
|
809 break;
|
rlm@10
|
810 case Opcodes.DADD:
|
rlm@10
|
811 case Opcodes.DSUB:
|
rlm@10
|
812 case Opcodes.DMUL:
|
rlm@10
|
813 case Opcodes.DDIV:
|
rlm@10
|
814 case Opcodes.DREM:
|
rlm@10
|
815 pop(4);
|
rlm@10
|
816 push(Opcodes.DOUBLE);
|
rlm@10
|
817 push(Opcodes.TOP);
|
rlm@10
|
818 break;
|
rlm@10
|
819 case Opcodes.LSHL:
|
rlm@10
|
820 case Opcodes.LSHR:
|
rlm@10
|
821 case Opcodes.LUSHR:
|
rlm@10
|
822 pop(3);
|
rlm@10
|
823 push(Opcodes.LONG);
|
rlm@10
|
824 push(Opcodes.TOP);
|
rlm@10
|
825 break;
|
rlm@10
|
826 case Opcodes.IINC:
|
rlm@10
|
827 set(iarg, Opcodes.INTEGER);
|
rlm@10
|
828 break;
|
rlm@10
|
829 case Opcodes.I2L:
|
rlm@10
|
830 case Opcodes.F2L:
|
rlm@10
|
831 pop(1);
|
rlm@10
|
832 push(Opcodes.LONG);
|
rlm@10
|
833 push(Opcodes.TOP);
|
rlm@10
|
834 break;
|
rlm@10
|
835 case Opcodes.I2F:
|
rlm@10
|
836 pop(1);
|
rlm@10
|
837 push(Opcodes.FLOAT);
|
rlm@10
|
838 break;
|
rlm@10
|
839 case Opcodes.I2D:
|
rlm@10
|
840 case Opcodes.F2D:
|
rlm@10
|
841 pop(1);
|
rlm@10
|
842 push(Opcodes.DOUBLE);
|
rlm@10
|
843 push(Opcodes.TOP);
|
rlm@10
|
844 break;
|
rlm@10
|
845 case Opcodes.F2I:
|
rlm@10
|
846 case Opcodes.ARRAYLENGTH:
|
rlm@10
|
847 case Opcodes.INSTANCEOF:
|
rlm@10
|
848 pop(1);
|
rlm@10
|
849 push(Opcodes.INTEGER);
|
rlm@10
|
850 break;
|
rlm@10
|
851 case Opcodes.LCMP:
|
rlm@10
|
852 case Opcodes.DCMPL:
|
rlm@10
|
853 case Opcodes.DCMPG:
|
rlm@10
|
854 pop(4);
|
rlm@10
|
855 push(Opcodes.INTEGER);
|
rlm@10
|
856 break;
|
rlm@10
|
857 case Opcodes.JSR:
|
rlm@10
|
858 case Opcodes.RET:
|
rlm@10
|
859 throw new RuntimeException("JSR/RET are not supported");
|
rlm@10
|
860 case Opcodes.GETSTATIC:
|
rlm@10
|
861 pushDesc(sarg);
|
rlm@10
|
862 break;
|
rlm@10
|
863 case Opcodes.PUTSTATIC:
|
rlm@10
|
864 pop(sarg);
|
rlm@10
|
865 break;
|
rlm@10
|
866 case Opcodes.GETFIELD:
|
rlm@10
|
867 pop(1);
|
rlm@10
|
868 pushDesc(sarg);
|
rlm@10
|
869 break;
|
rlm@10
|
870 case Opcodes.PUTFIELD:
|
rlm@10
|
871 pop(sarg);
|
rlm@10
|
872 pop();
|
rlm@10
|
873 break;
|
rlm@10
|
874 case Opcodes.NEW:
|
rlm@10
|
875 push(labels.get(0));
|
rlm@10
|
876 break;
|
rlm@10
|
877 case Opcodes.NEWARRAY:
|
rlm@10
|
878 pop();
|
rlm@10
|
879 switch(iarg)
|
rlm@10
|
880 {
|
rlm@10
|
881 case Opcodes.T_BOOLEAN:
|
rlm@10
|
882 pushDesc("[Z");
|
rlm@10
|
883 break;
|
rlm@10
|
884 case Opcodes.T_CHAR:
|
rlm@10
|
885 pushDesc("[C");
|
rlm@10
|
886 break;
|
rlm@10
|
887 case Opcodes.T_BYTE:
|
rlm@10
|
888 pushDesc("[B");
|
rlm@10
|
889 break;
|
rlm@10
|
890 case Opcodes.T_SHORT:
|
rlm@10
|
891 pushDesc("[S");
|
rlm@10
|
892 break;
|
rlm@10
|
893 case Opcodes.T_INT:
|
rlm@10
|
894 pushDesc("[I");
|
rlm@10
|
895 break;
|
rlm@10
|
896 case Opcodes.T_FLOAT:
|
rlm@10
|
897 pushDesc("[F");
|
rlm@10
|
898 break;
|
rlm@10
|
899 case Opcodes.T_DOUBLE:
|
rlm@10
|
900 pushDesc("[D");
|
rlm@10
|
901 break;
|
rlm@10
|
902 // case Opcodes.T_LONG:
|
rlm@10
|
903 default:
|
rlm@10
|
904 pushDesc("[J");
|
rlm@10
|
905 break;
|
rlm@10
|
906 }
|
rlm@10
|
907 break;
|
rlm@10
|
908 case Opcodes.ANEWARRAY:
|
rlm@10
|
909 pop();
|
rlm@10
|
910 if(sarg.charAt(0) == '[')
|
rlm@10
|
911 {
|
rlm@10
|
912 pushDesc("[" + sarg);
|
rlm@10
|
913 }
|
rlm@10
|
914 else
|
rlm@10
|
915 {
|
rlm@10
|
916 pushDesc("[L" + sarg + ";");
|
rlm@10
|
917 }
|
rlm@10
|
918 break;
|
rlm@10
|
919 case Opcodes.CHECKCAST:
|
rlm@10
|
920 pop();
|
rlm@10
|
921 if(sarg.charAt(0) == '[')
|
rlm@10
|
922 {
|
rlm@10
|
923 pushDesc(sarg);
|
rlm@10
|
924 }
|
rlm@10
|
925 else
|
rlm@10
|
926 {
|
rlm@10
|
927 push(sarg);
|
rlm@10
|
928 }
|
rlm@10
|
929 break;
|
rlm@10
|
930 // case Opcodes.MULTIANEWARRAY:
|
rlm@10
|
931 default:
|
rlm@10
|
932 pop(iarg);
|
rlm@10
|
933 pushDesc(sarg);
|
rlm@10
|
934 break;
|
rlm@10
|
935 }
|
rlm@10
|
936 labels = null;
|
rlm@10
|
937 }
|
rlm@10
|
938 }
|