annotate src/clojure/asm/commons/AnalyzerAdapter.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
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 }