1
2
3
4 package joeq.Compiler.Quad;
5
6 import java.util.HashMap;
7 import java.util.Iterator;
8 import java.util.LinkedList;
9 import joeq.Class.PrimordialClassLoader;
10 import joeq.Class.jq_Array;
11 import joeq.Class.jq_Class;
12 import joeq.Class.jq_InstanceField;
13 import joeq.Class.jq_InstanceMethod;
14 import joeq.Class.jq_Method;
15 import joeq.Class.jq_NameAndDesc;
16 import joeq.Class.jq_Primitive;
17 import joeq.Class.jq_Reference;
18 import joeq.Class.jq_StaticField;
19 import joeq.Class.jq_StaticMethod;
20 import joeq.Class.jq_TryCatchBC;
21 import joeq.Class.jq_Type;
22 import joeq.Compiler.CompilationState;
23 import joeq.Compiler.BytecodeAnalysis.BytecodeVisitor;
24 import joeq.Compiler.Quad.Operand.AConstOperand;
25 import joeq.Compiler.Quad.Operand.ConditionOperand;
26 import joeq.Compiler.Quad.Operand.DConstOperand;
27 import joeq.Compiler.Quad.Operand.FConstOperand;
28 import joeq.Compiler.Quad.Operand.FieldOperand;
29 import joeq.Compiler.Quad.Operand.IConstOperand;
30 import joeq.Compiler.Quad.Operand.LConstOperand;
31 import joeq.Compiler.Quad.Operand.MethodOperand;
32 import joeq.Compiler.Quad.Operand.PConstOperand;
33 import joeq.Compiler.Quad.Operand.RegisterOperand;
34 import joeq.Compiler.Quad.Operand.TargetOperand;
35 import joeq.Compiler.Quad.Operand.TypeOperand;
36 import joeq.Compiler.Quad.Operand.UnnecessaryGuardOperand;
37 import joeq.Compiler.Quad.Operator.ALength;
38 import joeq.Compiler.Quad.Operator.ALoad;
39 import joeq.Compiler.Quad.Operator.AStore;
40 import joeq.Compiler.Quad.Operator.Binary;
41 import joeq.Compiler.Quad.Operator.BoundsCheck;
42 import joeq.Compiler.Quad.Operator.CheckCast;
43 import joeq.Compiler.Quad.Operator.Getfield;
44 import joeq.Compiler.Quad.Operator.Getstatic;
45 import joeq.Compiler.Quad.Operator.Goto;
46 import joeq.Compiler.Quad.Operator.InstanceOf;
47 import joeq.Compiler.Quad.Operator.IntIfCmp;
48 import joeq.Compiler.Quad.Operator.Invoke;
49 import joeq.Compiler.Quad.Operator.Jsr;
50 import joeq.Compiler.Quad.Operator.LookupSwitch;
51 import joeq.Compiler.Quad.Operator.MemLoad;
52 import joeq.Compiler.Quad.Operator.MemStore;
53 import joeq.Compiler.Quad.Operator.Monitor;
54 import joeq.Compiler.Quad.Operator.Move;
55 import joeq.Compiler.Quad.Operator.New;
56 import joeq.Compiler.Quad.Operator.NewArray;
57 import joeq.Compiler.Quad.Operator.NullCheck;
58 import joeq.Compiler.Quad.Operator.Putfield;
59 import joeq.Compiler.Quad.Operator.Putstatic;
60 import joeq.Compiler.Quad.Operator.Ret;
61 import joeq.Compiler.Quad.Operator.Return;
62 import joeq.Compiler.Quad.Operator.Special;
63 import joeq.Compiler.Quad.Operator.StoreCheck;
64 import joeq.Compiler.Quad.Operator.TableSwitch;
65 import joeq.Compiler.Quad.Operator.Unary;
66 import joeq.Compiler.Quad.Operator.ZeroCheck;
67 import joeq.Compiler.Quad.RegisterFactory.Register;
68 import joeq.Main.jq;
69 import joeq.Memory.Address;
70 import joeq.Memory.HeapAddress;
71 import joeq.Memory.StackAddress;
72 import joeq.Runtime.Reflection;
73 import joeq.UTF.Utf8;
74 import jwutil.strings.Strings;
75 import jwutil.util.Assert;
76
77 /***
78 * Converts stack-based Java bytecode to Quad intermediate format.
79 * This utilizes the ControlFlowGraph in the BytecodeAnalysis package to build
80 * up a control flow graph, then iterates over the graph to generate the Quad
81 * code.
82 *
83 * @see BytecodeVisitor
84 * @see joeq.Compiler.BytecodeAnalysis.ControlFlowGraph
85 * @author John Whaley <jwhaley@alum.mit.edu>
86 * @version $Id: BytecodeToQuad.java 2465 2006-06-07 23:03:17Z joewhaley $
87 */
88 public class BytecodeToQuad extends BytecodeVisitor {
89
90 private ControlFlowGraph quad_cfg;
91 private BasicBlock quad_bb;
92 private joeq.Compiler.BytecodeAnalysis.ControlFlowGraph bc_cfg;
93 private joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb;
94 private BasicBlock[] quad_bbs;
95 private RegisterFactory rf;
96
97 private boolean[] visited;
98 private LinkedList regenerate;
99
100 private HashMap quad2bci = new HashMap();
101
102 public static boolean ALWAYS_TRACE = false;
103
104 /*** Initializes the conversion from bytecode to quad format for the given method.
105 * @param method the method to convert. */
106 public BytecodeToQuad(jq_Method method) {
107 this(CompilationState.DEFAULT, method);
108 }
109
110 /*** Initializes the conversion from bytecode to quad format for the given method.
111 * @param method the method to convert. */
112 public BytecodeToQuad(CompilationState state, jq_Method method) {
113 super(state, method);
114 TRACE = ALWAYS_TRACE;
115 }
116
117 /*** Returns a string with the name of the pass and the method being converted.
118 * @return a string with the name of the pass and the method being converted. */
119 public String toString() {
120 return "BC2Q/"+Strings.left(method.getName().toString(), 10);
121 }
122 /*** Perform conversion process from bytecode to quad.
123 * @return the control flow graph of the resulting quad representation. */
124 public ControlFlowGraph convert() {
125 bc_cfg = joeq.Compiler.BytecodeAnalysis.ControlFlowGraph.computeCFG(method);
126
127
128 this.rf = new RegisterFactory(method);
129
130
131 jq_TryCatchBC[] exs = method.getExceptionTable();
132 this.quad_cfg = new ControlFlowGraph(method, bc_cfg.getExit().getNumberOfPredecessors(),
133 exs.length, this.rf);
134 quad_bbs = new BasicBlock[bc_cfg.getNumberOfBasicBlocks()];
135 quad_bbs[0] = this.quad_cfg.entry();
136 quad_bbs[1] = this.quad_cfg.exit();
137 for (int i=2; i<quad_bbs.length; ++i) {
138 joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb = bc_cfg.getBasicBlock(i);
139 int n_pred = bc_bb.getNumberOfPredecessors();
140 int n_succ = bc_bb.getNumberOfSuccessors();
141 int n_inst = bc_bb.getEnd() - bc_bb.getStart() + 1;
142 quad_bbs[i] = BasicBlock.createBasicBlock(i, n_pred, n_succ, n_inst);
143 }
144 this.quad_cfg.updateBBcounter(quad_bbs.length);
145
146
147 for (int i=exs.length-1; i>=0; --i) {
148 jq_TryCatchBC ex = exs[i];
149 joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb = bc_cfg.getBasicBlockByBytecodeIndex(ex.getStartPC());
150 Assert._assert(bc_bb.getStart() < ex.getEndPC());
151 BasicBlock ex_handler = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(ex.getHandlerPC()).id];
152 ex_handler.setExceptionHandlerEntry();
153 int numOfProtectedBlocks = (ex.getEndPC()==method.getBytecode().length?quad_bbs.length:bc_cfg.getBasicBlockByBytecodeIndex(ex.getEndPC()).id) - bc_bb.id;
154 ExceptionHandler eh = new ExceptionHandler(ex.getExceptionType(), numOfProtectedBlocks, ex_handler);
155 quad_cfg.addExceptionHandler(eh);
156 ExceptionHandlerList ehs = new ExceptionHandlerList(eh, null);
157 BasicBlock bb = quad_bbs[bc_bb.id];
158 bb.addExceptionHandler_first(ehs);
159 for (;;) {
160 bc_bb = bc_cfg.getBasicBlock(bc_bb.id+1);
161 bb = quad_bbs[bc_bb.id];
162 if (bc_bb.getStart() >= ex.getEndPC()) break;
163 ehs = bb.addExceptionHandler(ehs);
164 }
165 }
166 this.start_states = new AbstractState[quad_bbs.length];
167 for (int i=0; i<quad_bbs.length; ++i) {
168 joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb = bc_cfg.getBasicBlock(i);
169 BasicBlock bb = quad_bbs[i];
170 for (int j=0; j<bc_bb.getNumberOfPredecessors(); ++j) {
171 bb.addPredecessor(quad_bbs[bc_bb.getPredecessor(j).id]);
172 }
173 for (int j=0; j<bc_bb.getNumberOfSuccessors(); ++j) {
174 bb.addSuccessor(quad_bbs[bc_bb.getSuccessor(j).id]);
175 }
176
177
178 }
179
180
181 this.start_states[2] = allocateInitialState();
182 this.current_state = allocateEmptyState();
183
184 regenerate = new LinkedList();
185 visited = new boolean[quad_bbs.length];
186
187 joeq.Compiler.BytecodeAnalysis.ControlFlowGraph.RPOBasicBlockIterator rpo = bc_cfg.reversePostOrderIterator();
188 joeq.Compiler.BytecodeAnalysis.BasicBlock first_bb = rpo.nextBB();
189 Assert._assert(first_bb == bc_cfg.getEntry());
190 while (rpo.hasNext()) {
191 joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb = rpo.nextBB();
192 visited[bc_bb.id] = true;
193 this.traverseBB(bc_bb);
194 }
195 while (!regenerate.isEmpty()) {
196 if (TRACE) out.println("Blocks to regenerate: "+regenerate);
197 joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb =
198 (joeq.Compiler.BytecodeAnalysis.BasicBlock)regenerate.removeFirst();
199 visited[bc_bb.id] = true;
200 this.traverseBB(bc_bb);
201 }
202 if (quad_cfg.removeUnreachableBasicBlocks()) {
203 if (TRACE) out.println("Unreachable code in "+method);
204 }
205
206 return this.quad_cfg;
207 }
208
209 private boolean endBasicBlock;
210 private boolean endsWithRET;
211
212 /***
213 * @param bc_bb */
214 public void traverseBB(joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb) {
215 if (start_states[bc_bb.id] == null) {
216
217 if (TRACE) out.println("Basic block "+bc_bb+" is unreachable!");
218 return;
219 }
220 if (bc_bb.getStart() == -1) {
221 return;
222 }
223 if (TRACE) out.println("Visiting "+bc_bb);
224 this.quad_bb = quad_bbs[bc_bb.id];
225 for (Iterator i = this.quad_bb.iterator(); i.hasNext(); ) {
226 Object o = i.next();
227 Object old = this.quad2bci.remove(o);
228 if (old == null) {
229
230
231 }
232 }
233 this.quad_bb.removeAllQuads();
234 this.bc_bb = bc_bb;
235 this.current_state.overwriteWith(start_states[bc_bb.id]);
236 if (this.quad_bb.isExceptionHandlerEntry()) {
237
238 jq_Type type = ((RegisterOperand)this.current_state.peekStack(0)).getType();
239 RegisterOperand t = getStackRegister(type, 0);
240 this.quad_bb.appendQuad(Special.create(quad_cfg.getNewQuadID(), Special.GET_EXCEPTION.INSTANCE, t));
241 }
242 if (TRACE) this.current_state.dumpState();
243 this.endBasicBlock = false;
244 this.endsWithRET = false;
245 for (i_end=bc_bb.getStart()-1; ; ) {
246 i_start = i_end+1;
247 if (isEndOfBB()) break;
248 this.visitBytecode();
249 }
250 saveStackIntoRegisters();
251 if (!endsWithRET) {
252 for (int i=0; i<bc_bb.getNumberOfSuccessors(); ++i) {
253 this.mergeStateWith(bc_bb.getSuccessor(i));
254 }
255 }
256 if (TRACE) out.println("Finished visiting "+bc_bb);
257 }
258
259 private boolean isEndOfBB() {
260 return i_start > bc_bb.getEnd() || endBasicBlock;
261 }
262
263 private void mergeStateWith(joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb) {
264 if (start_states[bc_bb.id] == null) {
265 if (TRACE) out.println("Copying current state to "+bc_bb);
266 start_states[bc_bb.id] = current_state.copy();
267 } else {
268 if (TRACE) out.println("Merging current state with "+bc_bb);
269 if (start_states[bc_bb.id].merge(current_state, rf)) {
270 if (TRACE) out.println("in set of "+bc_bb+" changed");
271 if (visited[bc_bb.id]) {
272 if (TRACE) out.println("must regenerate code for "+bc_bb);
273 if (!regenerate.contains(bc_bb)) {
274 regenerate.add(bc_bb);
275 start_states[bc_bb.id].rebuildStack();
276 }
277 visited[bc_bb.id] = false;
278 }
279 }
280 }
281 }
282 private void mergeStateWith(joeq.Compiler.BytecodeAnalysis.ExceptionHandler eh) {
283 joeq.Compiler.BytecodeAnalysis.BasicBlock bc_bb = eh.getEntry();
284 if (start_states[bc_bb.id] == null) {
285 if (TRACE) out.println("Copying exception state to "+bc_bb);
286 start_states[bc_bb.id] = current_state.copyExceptionHandler(eh.getExceptionType(), rf);
287 } else {
288 if (TRACE) out.println("Merging exception state with "+bc_bb);
289 if (start_states[bc_bb.id].mergeExceptionHandler(current_state, eh.getExceptionType(), rf)) {
290 if (TRACE) out.println("in set of exception handler "+bc_bb+" changed");
291 if (visited[bc_bb.id]) {
292 if (TRACE) out.println("must regenerate code for "+bc_bb);
293 if (!regenerate.contains(bc_bb)) {
294 regenerate.add(bc_bb);
295 start_states[bc_bb.id].rebuildStack();
296 }
297 visited[bc_bb.id] = false;
298 }
299 }
300 }
301 }
302
303 private void saveStackIntoRegisters() {
304 for (int i=0; i<current_state.getStackSize(); ++i) {
305 Operand op = current_state.peekStack(i);
306 if (op instanceof DummyOperand) continue;
307 if (op instanceof RegisterOperand) {
308 RegisterOperand rop = (RegisterOperand)op;
309 Register r = rf.getOrCreateStack(current_state.getStackSize()-i-1, rop.getType());
310 if (rop.getRegister() == r)
311 continue;
312 }
313 jq_Type type = getTypeOf(op);
314 RegisterOperand t = getStackRegister(type, i);
315 Quad q = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type), t, op);
316 appendQuad(q);
317 current_state.pokeStack(i, t.copy());
318 }
319 }
320
321 public boolean isLocal(Operand op, int index, jq_Type type) {
322 if (op instanceof RegisterOperand) {
323 Register r = ((RegisterOperand)op).getRegister();
324 if (r.isTemp()) return false;
325 return rf.getOrCreateLocal(index, type) == r;
326 }
327 return false;
328 }
329
330 private void replaceLocalsOnStack(int index, jq_Type type) {
331 for (int i=0; i<current_state.getStackSize(); ++i) {
332 Operand op = current_state.peekStack(i);
333 if (isLocal(op, index, type)) {
334 RegisterOperand rop = (RegisterOperand)op;
335 RegisterOperand t = getStackRegister(type, i);
336 t.setFlags(rop.getFlags()); t.scratchObject = rop.scratchObject;
337 Quad q = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type), t, rop);
338 appendQuad(q);
339 current_state.pokeStack(i, t.copy());
340 }
341 }
342 }
343
344 void appendQuad(Quad q) {
345 if (TRACE) out.println(q.toString());
346 quad_bb.appendQuad(q);
347 quad2bci.put(q, new Integer(i_start));
348 }
349
350 /***
351 * return quad->bytecode map, may be incomplete
352 * @return Map<Quad, Integer>
353 */
354 java.util.Map getQuadToBytecodeMap() {
355 return quad2bci;
356 }
357
358 RegisterOperand getStackRegister(jq_Type type, int i) {
359 if (current_state.getStackSize()-i-1 < 0) {
360 System.out.println("Error in "+method+" offset "+i_start);
361 current_state.dumpState();
362 }
363 return new RegisterOperand(rf.getOrCreateStack(current_state.getStackSize()-i-1, type), type);
364 }
365
366 RegisterOperand getStackRegister(jq_Type type) {
367 return getStackRegister(type, -1);
368 }
369
370 RegisterOperand makeLocal(int i, jq_Type type) {
371 return new RegisterOperand(rf.getOrCreateLocal(i, type), type);
372 }
373
374 RegisterOperand makeLocal(int i, RegisterOperand rop) {
375 jq_Type type = rop.getType();
376 return new RegisterOperand(rf.getOrCreateLocal(i, type), type, rop.getFlags());
377 }
378
379 static boolean hasGuard(RegisterOperand rop) { return rop.scratchObject != null; }
380 static void setGuard(RegisterOperand rop, Operand guard) { rop.scratchObject = guard; }
381
382 static Operand getGuard(Operand op) {
383 if (op instanceof RegisterOperand) {
384 RegisterOperand rop = (RegisterOperand)op;
385 return (Operand)rop.scratchObject;
386 }
387 Assert._assert(op instanceof AConstOperand);
388 return new UnnecessaryGuardOperand();
389 }
390
391 Operand currentGuard;
392
393 void setCurrentGuard(Operand guard) { currentGuard = guard; }
394 void clearCurrentGuard() { currentGuard = null; }
395 Operand getCurrentGuard() { if (currentGuard == null) return null; return currentGuard.copy(); }
396
397 private AbstractState[] start_states;
398 private AbstractState current_state;
399
400 public void visitNOP() {
401 super.visitNOP();
402
403 }
404 public void visitACONST(Object s) {
405 super.visitACONST(s);
406 current_state.push_A(new AConstOperand(s));
407 }
408 public void visitICONST(int c) {
409 super.visitICONST(c);
410 current_state.push_I(new IConstOperand(c));
411 }
412 public void visitLCONST(long c) {
413 super.visitLCONST(c);
414 current_state.push_L(new LConstOperand(c));
415 }
416 public void visitFCONST(float c) {
417 super.visitFCONST(c);
418 current_state.push_F(new FConstOperand(c));
419 }
420 public void visitDCONST(double c) {
421 super.visitDCONST(c);
422 current_state.push_D(new DConstOperand(c));
423 }
424 public void visitILOAD(int i) {
425 super.visitILOAD(i);
426 current_state.push_I(current_state.getLocal_I(i));
427 }
428 public void visitLLOAD(int i) {
429 super.visitLLOAD(i);
430 current_state.push_L(current_state.getLocal_L(i));
431 }
432 public void visitFLOAD(int i) {
433 super.visitFLOAD(i);
434 current_state.push_F(current_state.getLocal_F(i));
435 }
436 public void visitDLOAD(int i) {
437 super.visitDLOAD(i);
438 current_state.push_D(current_state.getLocal_D(i));
439 }
440 public void visitALOAD(int i) {
441 super.visitALOAD(i);
442
443 current_state.push(current_state.getLocal(i));
444 }
445 private void STOREhelper(int i, jq_Type type) {
446 replaceLocalsOnStack(i, type);
447 Operand op1 = current_state.pop(type);
448 Operand local_value;
449 RegisterOperand op0;
450 if (op1 instanceof RegisterOperand) {
451
452 local_value = op0 = makeLocal(i, (RegisterOperand)op1);
453 } else {
454
455 local_value = op1;
456 op0 = makeLocal(i, type);
457 }
458 if (type.getReferenceSize() == 8) current_state.setLocalDual(i, local_value);
459 else current_state.setLocal(i, local_value);
460 Quad q = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type), op0, op1);
461 appendQuad(q);
462 }
463 public void visitISTORE(int i) {
464 super.visitISTORE(i);
465 STOREhelper(i, jq_Primitive.INT);
466 }
467 public void visitLSTORE(int i) {
468 super.visitLSTORE(i);
469 STOREhelper(i, jq_Primitive.LONG);
470 }
471 public void visitFSTORE(int i) {
472 super.visitFSTORE(i);
473 STOREhelper(i, jq_Primitive.FLOAT);
474 }
475 public void visitDSTORE(int i) {
476 super.visitDSTORE(i);
477 STOREhelper(i, jq_Primitive.DOUBLE);
478 }
479 public void visitASTORE(int i) {
480 super.visitASTORE(i);
481 Operand op1 = current_state.peekStack(0);
482 STOREhelper(i, getTypeOf(op1));
483 }
484 private void ALOADhelper(ALoad operator, jq_Type t) {
485 Operand index = current_state.pop_I();
486 Operand ref = current_state.pop_A();
487 clearCurrentGuard();
488 if (performNullCheck(ref)) {
489 if (TRACE) System.out.println("Null check triggered on "+ref);
490 return;
491 }
492 if (performBoundsCheck(ref, index)) {
493 if (TRACE) System.out.println("Bounds check triggered on "+ref+" "+index);
494 return;
495 }
496 if (t.isReferenceType()) {
497
498 t = getArrayElementTypeOf(ref);
499 Assert._assert(!t.isAddressType());
500 }
501 RegisterOperand r = getStackRegister(t);
502 Quad q = ALoad.create(quad_cfg.getNewQuadID(), operator, r, ref, index, getCurrentGuard());
503 appendQuad(q);
504 current_state.push(r.copy(), t);
505 }
506 public void visitIALOAD() {
507 super.visitIALOAD();
508 ALOADhelper(ALoad.ALOAD_I.INSTANCE, jq_Primitive.INT);
509 }
510 public void visitLALOAD() {
511 super.visitLALOAD();
512 ALOADhelper(ALoad.ALOAD_L.INSTANCE, jq_Primitive.LONG);
513 }
514 public void visitFALOAD() {
515 super.visitFALOAD();
516 ALOADhelper(ALoad.ALOAD_F.INSTANCE, jq_Primitive.FLOAT);
517 }
518 public void visitDALOAD() {
519 super.visitDALOAD();
520 ALOADhelper(ALoad.ALOAD_D.INSTANCE, jq_Primitive.DOUBLE);
521 }
522 public void visitAALOAD() {
523 super.visitAALOAD();
524 Operand index = current_state.pop_I();
525 Operand ref = current_state.pop_A();
526 clearCurrentGuard();
527 if (performNullCheck(ref)) {
528 if (TRACE) System.out.println("Null check triggered on "+ref);
529 return;
530 }
531 if (performBoundsCheck(ref, index)) {
532 if (TRACE) System.out.println("Bounds check triggered on "+ref+" "+index);
533 return;
534 }
535 jq_Type t = getArrayElementTypeOf(ref);
536 ALoad operator = t.isAddressType()?(ALoad)ALoad.ALOAD_P.INSTANCE:ALoad.ALOAD_A.INSTANCE;
537 RegisterOperand r = getStackRegister(t);
538 Quad q = ALoad.create(quad_cfg.getNewQuadID(), operator, r, ref, index, getCurrentGuard());
539 appendQuad(q);
540 current_state.push(r.copy(), t);
541 }
542 public void visitBALOAD() {
543 super.visitBALOAD();
544 ALOADhelper(ALoad.ALOAD_B.INSTANCE, jq_Primitive.BYTE);
545 }
546 public void visitCALOAD() {
547 super.visitCALOAD();
548 ALOADhelper(ALoad.ALOAD_C.INSTANCE, jq_Primitive.CHAR);
549 }
550 public void visitSALOAD() {
551 super.visitSALOAD();
552 ALOADhelper(ALoad.ALOAD_S.INSTANCE, jq_Primitive.SHORT);
553 }
554 private void ASTOREhelper(AStore operator, jq_Type t) {
555 Operand val = current_state.pop(t);
556 Operand index = current_state.pop_I();
557 Operand ref = current_state.pop_A();
558 clearCurrentGuard();
559 if (performNullCheck(ref)) {
560 if (TRACE) System.out.println("Null check triggered on "+ref);
561 return;
562 }
563 if (performBoundsCheck(ref, index)) {
564 if (TRACE) System.out.println("Bounds check triggered on "+ref+" "+index);
565 return;
566 }
567 if (t.isReferenceType() && ref instanceof RegisterOperand) {
568
569 if (performCheckStore((RegisterOperand)ref, val)) return;
570 Assert._assert(!t.isAddressType());
571 }
572 Quad q = AStore.create(quad_cfg.getNewQuadID(), operator, val, ref, index, getCurrentGuard());
573 appendQuad(q);
574 }
575 public void visitIASTORE() {
576 super.visitIASTORE();
577 ASTOREhelper(AStore.ASTORE_I.INSTANCE, jq_Primitive.INT);
578 }
579 public void visitLASTORE() {
580 super.visitLASTORE();
581 ASTOREhelper(AStore.ASTORE_L.INSTANCE, jq_Primitive.LONG);
582 }
583 public void visitFASTORE() {
584 super.visitFASTORE();
585 ASTOREhelper(AStore.ASTORE_F.INSTANCE, jq_Primitive.FLOAT);
586 }
587 public void visitDASTORE() {
588 super.visitDASTORE();
589 ASTOREhelper(AStore.ASTORE_D.INSTANCE, jq_Primitive.DOUBLE);
590 }
591 public void visitAASTORE() {
592
593 Operand val = current_state.pop();
594 Operand index = current_state.pop_I();
595 Operand ref = current_state.pop_A();
596 clearCurrentGuard();
597 if (performNullCheck(ref)) {
598 if (TRACE) System.out.println("Null check triggered on "+ref);
599 return;
600 }
601 if (performBoundsCheck(ref, index)) {
602 if (TRACE) System.out.println("Bounds check triggered on "+ref+" "+index);
603 return;
604 }
605 jq_Type arrayElemType = getArrayElementTypeOf(ref);
606 AStore operator = arrayElemType.isAddressType()?(AStore)AStore.ASTORE_P.INSTANCE:AStore.ASTORE_A.INSTANCE;
607 if (ref instanceof RegisterOperand) {
608
609 if (performCheckStore((RegisterOperand)ref, val)) return;
610 }
611 Quad q = AStore.create(quad_cfg.getNewQuadID(), operator, val, ref, index, getCurrentGuard());
612 appendQuad(q);
613 }
614 public void visitBASTORE() {
615 super.visitBASTORE();
616 ASTOREhelper(AStore.ASTORE_B.INSTANCE, jq_Primitive.BYTE);
617 }
618 public void visitCASTORE() {
619 super.visitCASTORE();
620 ASTOREhelper(AStore.ASTORE_C.INSTANCE, jq_Primitive.CHAR);
621 }
622 public void visitSASTORE() {
623 super.visitSASTORE();
624 ASTOREhelper(AStore.ASTORE_S.INSTANCE, jq_Primitive.SHORT);
625 }
626 public void visitPOP() {
627 super.visitPOP();
628 current_state.pop();
629 }
630 public void visitPOP2() {
631 super.visitPOP2();
632 current_state.pop(); current_state.pop();
633 }
634 public void visitDUP() {
635 super.visitDUP();
636 Operand op = current_state.pop();
637 int d = current_state.getStackSize();
638 jq_Type type = getTypeOf(op);
639 RegisterOperand t = new RegisterOperand(rf.getOrCreateStack(d+1, type), type);
640 Quad q = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type), t, op);
641 appendQuad(q);
642 current_state.push(op.copy(), type);
643 current_state.push(t.copy(), type);
644 }
645 private void do_DUP_x1() {
646 Operand op1 = current_state.pop();
647 Operand op2 = current_state.pop();
648 int d = current_state.getStackSize();
649 jq_Type type1 = getTypeOf(op1);
650 jq_Type type2 = getTypeOf(op2);
651 RegisterOperand t1 = new RegisterOperand(rf.getOrCreateStack(d+2, type1), type1);
652 Quad q1 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type1), t1, op1);
653 appendQuad(q1);
654 RegisterOperand t2 = new RegisterOperand(rf.getOrCreateStack(d+1, type2), type2);
655 Quad q2 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type2), t2, op2);
656 appendQuad(q2);
657 RegisterOperand t3 = new RegisterOperand(rf.getOrCreateStack(d, type1), type1);
658 Quad q3 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type1), t3, t1.copy());
659 appendQuad(q3);
660 current_state.push(t3.copy(), type1);
661 current_state.push(t2.copy(), type2);
662 current_state.push(t1.copy(), type1);
663 }
664 public void visitDUP_x1() {
665 super.visitDUP_x1();
666 do_DUP_x1();
667 }
668 public void visitDUP_x2() {
669 super.visitDUP_x2();
670 Operand op1 = current_state.pop();
671 Operand op2 = current_state.pop();
672 Operand op3 = current_state.pop();
673 int d = current_state.getStackSize();
674 jq_Type type1 = getTypeOf(op1);
675 RegisterOperand t1 = new RegisterOperand(rf.getOrCreateStack(d+3, type1), type1);
676 Quad q1 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type1), t1, op1);
677 appendQuad(q1);
678 RegisterOperand t2 = null; jq_Type type2 = null;
679 if (op2 != DummyOperand.DUMMY) {
680 type2 = getTypeOf(op2);
681 t2 = new RegisterOperand(rf.getOrCreateStack(d+2, type2), type2);
682 Quad q2 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type2), t2, op2);
683 appendQuad(q2);
684 }
685 jq_Type type3 = getTypeOf(op3);
686 RegisterOperand t3 = new RegisterOperand(rf.getOrCreateStack(d+1, type3), type3);
687 Quad q3 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type3), t3, op3);
688 appendQuad(q3);
689 RegisterOperand t4 = new RegisterOperand(rf.getOrCreateStack(d, type1), type1);
690 Quad q4 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type1), t4, t1.copy());
691 appendQuad(q4);
692 current_state.push(t4.copy(), type1);
693 current_state.push(t3.copy(), type3);
694 if (op2 != DummyOperand.DUMMY)
695 current_state.push(t2.copy(), type2);
696 current_state.push(t1.copy(), type1);
697 }
698 public void visitDUP2() {
699 super.visitDUP2();
700 Operand op1 = current_state.pop();
701 Operand op2 = current_state.pop();
702 int d = current_state.getStackSize();
703 RegisterOperand t1 = null; jq_Type type1 = null;
704 if (op1 != DummyOperand.DUMMY) {
705 type1 = getTypeOf(op1);
706 t1 = new RegisterOperand(rf.getOrCreateStack(d+3, type1), type1);
707 Quad q1 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type1), t1, op1);
708 appendQuad(q1);
709 }
710 jq_Type type2 = getTypeOf(op2);
711 RegisterOperand t2 = new RegisterOperand(rf.getOrCreateStack(d+2, type2), type2);
712 Quad q2 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(type2), t2, op2);
713 appendQuad(q2);
714 current_state.push(t2.copy(), type2);
715 if (op1 != DummyOperand.DUMMY)
716 current_state.push(t1.copy(), type1);
717 current_state.push(op2.copy(), type2);
718 if (op1 != DummyOperand.DUMMY)
719 current_state.push(op1.copy(), type1);
720 }
721 public void visitDUP2_x1() {
722 super.visitDUP2_x1();
723
724 Operand op1 = current_state.pop();
725 Operand op2 = current_state.pop();
726 Operand op3 = current_state.pop();
727 current_state.push(op2);
728 current_state.push(op1);
729 current_state.push(op3);
730 current_state.push(op2.copy());
731 current_state.push(op1.copy());
732 }
733 public void visitDUP2_x2() {
734 super.visitDUP2_x2();
735
736 Operand op1 = current_state.pop();
737 Operand op2 = current_state.pop();
738 Operand op3 = current_state.pop();
739 Operand op4 = current_state.pop();
740 current_state.push(op2);
741 current_state.push(op1);
742 current_state.push(op4);
743 current_state.push(op3);
744 current_state.push(op2.copy());
745 current_state.push(op1.copy());
746 }
747 public void visitSWAP() {
748 super.visitSWAP();
749 do_DUP_x1();
750 current_state.pop();
751 }
752 private void BINOPhelper(Binary operator, jq_Type tr, jq_Type t1, jq_Type t2, boolean zero_check) {
753 Operand op2 = current_state.pop(t2);
754 Operand op1 = current_state.pop(t1);
755 if (zero_check && performZeroCheck(op2)) {
756 if (TRACE) System.out.println("Zero check triggered on "+op2);
757 return;
758 }
759 RegisterOperand r = getStackRegister(tr);
760 Quad q = Binary.create(quad_cfg.getNewQuadID(), operator, r, op1, op2);
761 appendQuad(q);
762 current_state.push(r.copy(), tr);
763 }
764 public void visitIBINOP(byte op) {
765 super.visitIBINOP(op);
766 Binary operator=null; boolean zero_check = false;
767 switch (op) {
768 case BINOP_ADD: operator = Binary.ADD_I.INSTANCE; break;
769 case BINOP_SUB: operator = Binary.SUB_I.INSTANCE; break;
770 case BINOP_MUL: operator = Binary.MUL_I.INSTANCE; break;
771 case BINOP_DIV: operator = Binary.DIV_I.INSTANCE; zero_check = true; break;
772 case BINOP_REM: operator = Binary.REM_I.INSTANCE; zero_check = true; break;
773 case BINOP_AND: operator = Binary.AND_I.INSTANCE; break;
774 case BINOP_OR: operator = Binary.OR_I.INSTANCE; break;
775 case BINOP_XOR: operator = Binary.XOR_I.INSTANCE; break;
776 default: Assert.UNREACHABLE(); break;
777 }
778 BINOPhelper(operator, jq_Primitive.INT, jq_Primitive.INT, jq_Primitive.INT, zero_check);
779 }
780 public void visitLBINOP(byte op) {
781 super.visitLBINOP(op);
782 Binary operator=null; boolean zero_check = false;
783 switch (op) {
784 case BINOP_ADD: operator = Binary.ADD_L.INSTANCE; break;
785 case BINOP_SUB: operator = Binary.SUB_L.INSTANCE; break;
786 case BINOP_MUL: operator = Binary.MUL_L.INSTANCE; break;
787 case BINOP_DIV: operator = Binary.DIV_L.INSTANCE; zero_check = true; break;
788 case BINOP_REM: operator = Binary.REM_L.INSTANCE; zero_check = true; break;
789 case BINOP_AND: operator = Binary.AND_L.INSTANCE; break;
790 case BINOP_OR: operator = Binary.OR_L.INSTANCE; break;
791 case BINOP_XOR: operator = Binary.XOR_L.INSTANCE; break;
792 default: Assert.UNREACHABLE(); break;
793 }
794 BINOPhelper(operator, jq_Primitive.LONG, jq_Primitive.LONG, jq_Primitive.LONG, zero_check);
795 }
796 public void visitFBINOP(byte op) {
797 super.visitFBINOP(op);
798 Binary operator=null;
799 switch (op) {
800 case BINOP_ADD: operator = Binary.ADD_F.INSTANCE; break;
801 case BINOP_SUB: operator = Binary.SUB_F.INSTANCE; break;
802 case BINOP_MUL: operator = Binary.MUL_F.INSTANCE; break;
803 case BINOP_DIV: operator = Binary.DIV_F.INSTANCE; break;
804 case BINOP_REM: operator = Binary.REM_F.INSTANCE; break;
805 default: Assert.UNREACHABLE(); break;
806 }
807 BINOPhelper(operator, jq_Primitive.FLOAT, jq_Primitive.FLOAT, jq_Primitive.FLOAT, false);
808 }
809 public void visitDBINOP(byte op) {
810 super.visitDBINOP(op);
811 Binary operator=null;
812 switch (op) {
813 case BINOP_ADD: operator = Binary.ADD_D.INSTANCE; break;
814 case BINOP_SUB: operator = Binary.SUB_D.INSTANCE; break;
815 case BINOP_MUL: operator = Binary.MUL_D.INSTANCE; break;
816 case BINOP_DIV: operator = Binary.DIV_D.INSTANCE; break;
817 case BINOP_REM: operator = Binary.REM_D.INSTANCE; break;
818 default: Assert.UNREACHABLE(); break;
819 }
820 BINOPhelper(operator, jq_Primitive.DOUBLE, jq_Primitive.DOUBLE, jq_Primitive.DOUBLE, false);
821 }
822 public void UNOPhelper(Unary operator, jq_Type tr, jq_Type t1) {
823 Operand op1 = current_state.pop(t1);
824 RegisterOperand r = getStackRegister(tr);
825 Quad q = Unary.create(quad_cfg.getNewQuadID(), operator, r, op1);
826 appendQuad(q);
827 current_state.push(r.copy(), tr);
828 }
829 public void visitIUNOP(byte op) {
830 super.visitIUNOP(op);
831 Unary operator=null;
832 switch (op) {
833 case UNOP_NEG: operator = Unary.NEG_I.INSTANCE; break;
834 default: Assert.UNREACHABLE(); break;
835 }
836 UNOPhelper(operator, jq_Primitive.INT, jq_Primitive.INT);
837 }
838 public void visitLUNOP(byte op) {
839 super.visitLUNOP(op);
840 Unary operator=null;
841 switch (op) {
842 case UNOP_NEG: operator = Unary.NEG_L.INSTANCE; break;
843 default: Assert.UNREACHABLE(); break;
844 }
845 UNOPhelper(operator, jq_Primitive.LONG, jq_Primitive.LONG);
846 }
847 public void visitFUNOP(byte op) {
848 super.visitFUNOP(op);
849 Unary operator=null;
850 switch (op) {
851 case UNOP_NEG: operator = Unary.NEG_F.INSTANCE; break;
852 default: Assert.UNREACHABLE(); break;
853 }
854 UNOPhelper(operator, jq_Primitive.FLOAT, jq_Primitive.FLOAT);
855 }
856 public void visitDUNOP(byte op) {
857 super.visitDUNOP(op);
858 Unary operator=null;
859 switch (op) {
860 case UNOP_NEG: operator = Unary.NEG_D.INSTANCE; break;
861 default: Assert.UNREACHABLE(); break;
862 }
863 UNOPhelper(operator, jq_Primitive.DOUBLE, jq_Primitive.DOUBLE);
864 }
865 public void visitISHIFT(byte op) {
866 super.visitISHIFT(op);
867 Binary operator=null;
868 switch (op) {
869 case SHIFT_LEFT: operator = Binary.SHL_I.INSTANCE; break;
870 case SHIFT_RIGHT: operator = Binary.SHR_I.INSTANCE; break;
871 case SHIFT_URIGHT: operator = Binary.USHR_I.INSTANCE; break;
872 default: Assert.UNREACHABLE(); break;
873 }
874 BINOPhelper(operator, jq_Primitive.INT, jq_Primitive.INT, jq_Primitive.INT, false);
875 }
876 public void visitLSHIFT(byte op) {
877 super.visitLSHIFT(op);
878 Binary operator=null;
879 switch (op) {
880 case SHIFT_LEFT: operator = Binary.SHL_L.INSTANCE; break;
881 case SHIFT_RIGHT: operator = Binary.SHR_L.INSTANCE; break;
882 case SHIFT_URIGHT: operator = Binary.USHR_L.INSTANCE; break;
883 default: Assert.UNREACHABLE(); break;
884 }
885 BINOPhelper(operator, jq_Primitive.LONG, jq_Primitive.LONG, jq_Primitive.INT, false);
886 }
887 public void visitIINC(int i, int v) {
888 super.visitIINC(i, v);
889 Operand op1 = current_state.getLocal_I(i);
890 replaceLocalsOnStack(i, jq_Primitive.INT);
891 RegisterOperand op0 = makeLocal(i, jq_Primitive.INT);
892 Quad q = Binary.create(quad_cfg.getNewQuadID(), Binary.ADD_I.INSTANCE, op0, op1, new IConstOperand(v));
893 appendQuad(q);
894 current_state.setLocal(i, op0.copy());
895 }
896 public void visitI2L() {
897 super.visitI2L();
898 UNOPhelper(Unary.INT_2LONG.INSTANCE, jq_Primitive.LONG, jq_Primitive.INT);
899 }
900 public void visitI2F() {
901 super.visitI2F();
902 UNOPhelper(Unary.INT_2FLOAT.INSTANCE, jq_Primitive.FLOAT, jq_Primitive.INT);
903 }
904 public void visitI2D() {
905 super.visitI2D();
906 UNOPhelper(Unary.INT_2DOUBLE.INSTANCE, jq_Primitive.DOUBLE, jq_Primitive.INT);
907 }
908 public void visitL2I() {
909 super.visitL2I();
910 UNOPhelper(Unary.LONG_2INT.INSTANCE, jq_Primitive.INT, jq_Primitive.LONG);
911 }
912 public void visitL2F() {
913 super.visitL2F();
914 UNOPhelper(Unary.LONG_2FLOAT.INSTANCE, jq_Primitive.FLOAT, jq_Primitive.LONG);
915 }
916 public void visitL2D() {
917 super.visitL2D();
918 UNOPhelper(Unary.LONG_2DOUBLE.INSTANCE, jq_Primitive.DOUBLE, jq_Primitive.LONG);
919 }
920 public void visitF2I() {
921 super.visitF2I();
922 UNOPhelper(Unary.FLOAT_2INT.INSTANCE, jq_Primitive.INT, jq_Primitive.FLOAT);
923 }
924 public void visitF2L() {
925 super.visitF2L();
926 UNOPhelper(Unary.FLOAT_2LONG.INSTANCE, jq_Primitive.LONG, jq_Primitive.FLOAT);
927 }
928 public void visitF2D() {
929 super.visitF2D();
930 UNOPhelper(Unary.FLOAT_2DOUBLE.INSTANCE, jq_Primitive.DOUBLE, jq_Primitive.FLOAT);
931 }
932 public void visitD2I() {
933 super.visitD2I();
934 UNOPhelper(Unary.DOUBLE_2INT.INSTANCE, jq_Primitive.INT, jq_Primitive.DOUBLE);
935 }
936 public void visitD2L() {
937 super.visitD2L();
938 UNOPhelper(Unary.DOUBLE_2LONG.INSTANCE, jq_Primitive.LONG, jq_Primitive.DOUBLE);
939 }
940 public void visitD2F() {
941 super.visitD2F();
942 UNOPhelper(Unary.DOUBLE_2FLOAT.INSTANCE, jq_Primitive.FLOAT, jq_Primitive.DOUBLE);
943 }
944 public void visitI2B() {
945 super.visitI2B();
946 UNOPhelper(Unary.INT_2BYTE.INSTANCE, jq_Primitive.BYTE, jq_Primitive.INT);
947 }
948 public void visitI2C() {
949 super.visitI2C();
950 UNOPhelper(Unary.INT_2CHAR.INSTANCE, jq_Primitive.CHAR, jq_Primitive.INT);
951 }
952 public void visitI2S() {
953 super.visitI2S();
954 UNOPhelper(Unary.INT_2SHORT.INSTANCE, jq_Primitive.SHORT, jq_Primitive.INT);
955 }
956 public void visitLCMP2() {
957 super.visitLCMP2();
958 BINOPhelper(Binary.CMP_L.INSTANCE, jq_Primitive.INT, jq_Primitive.LONG, jq_Primitive.LONG, false);
959 }
960 public void visitFCMP2(byte op) {
961 super.visitFCMP2(op);
962 Binary o = op==CMP_L?(Binary)Binary.CMP_FL.INSTANCE:(Binary)Binary.CMP_FG.INSTANCE;
963 BINOPhelper(o, jq_Primitive.INT, jq_Primitive.FLOAT, jq_Primitive.FLOAT, false);
964 }
965 public void visitDCMP2(byte op) {
966 super.visitDCMP2(op);
967 Binary o = op==CMP_L?(Binary)Binary.CMP_DL.INSTANCE:(Binary)Binary.CMP_DG.INSTANCE;
968 BINOPhelper(o, jq_Primitive.INT, jq_Primitive.DOUBLE, jq_Primitive.DOUBLE, false);
969 }
970 public void visitIF(byte op, int target) {
971 super.visitIF(op, target);
972 Operand op0 = current_state.pop_I();
973 saveStackIntoRegisters();
974 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(target).id];
975 ConditionOperand cond = new ConditionOperand(op);
976 Quad q = IntIfCmp.create(quad_cfg.getNewQuadID(), IntIfCmp.IFCMP_I.INSTANCE, op0, new IConstOperand(0), cond, new TargetOperand(target_bb));
977 appendQuad(q);
978 }
979 public void visitIFREF(byte op, int target) {
980 super.visitIFREF(op, target);
981
982 Operand op0 = current_state.pop();
983 saveStackIntoRegisters();
984 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(target).id];
985 ConditionOperand cond = new ConditionOperand(op);
986 jq_Type t = getTypeOf(op0);
987 IntIfCmp operator = t.isAddressType()?(IntIfCmp)IntIfCmp.IFCMP_P.INSTANCE:IntIfCmp.IFCMP_A.INSTANCE;
988 Operand op1 = t.isAddressType()?(Operand)new PConstOperand(null):new AConstOperand(null);
989 Quad q = IntIfCmp.create(quad_cfg.getNewQuadID(), operator, op0, op1, cond, new TargetOperand(target_bb));
990 appendQuad(q);
991 }
992 public void visitIFCMP(byte op, int target) {
993 super.visitIFCMP(op, target);
994 Operand op1 = current_state.pop_I();
995 Operand op0 = current_state.pop_I();
996 saveStackIntoRegisters();
997 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(target).id];
998 ConditionOperand cond = new ConditionOperand(op);
999 Quad q = IntIfCmp.create(quad_cfg.getNewQuadID(), IntIfCmp.IFCMP_I.INSTANCE, op0, op1, cond, new TargetOperand(target_bb));
1000 appendQuad(q);
1001 }
1002 public void visitIFREFCMP(byte op, int target) {
1003 super.visitIFREFCMP(op, target);
1004
1005 Operand op1 = current_state.pop();
1006
1007 Operand op0 = current_state.pop();
1008 saveStackIntoRegisters();
1009 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(target).id];
1010 ConditionOperand cond = new ConditionOperand(op);
1011 jq_Type t1 = getTypeOf(op1);
1012 jq_Type t0 = getTypeOf(op0);
1013 IntIfCmp operator;
1014 if (t1.isAddressType()) {
1015 if (!t0.isAddressType() && t0 != jq_Reference.jq_NullType.NULL_TYPE) {
1016 Assert.UNREACHABLE("comparing address type "+op1+" with non-address type "+op0);
1017 }
1018 operator = IntIfCmp.IFCMP_P.INSTANCE;
1019 } else if (t0.isAddressType()) {
1020 if (t1 != jq_Reference.jq_NullType.NULL_TYPE) {
1021 Assert.UNREACHABLE("comparing address type "+op0+" with non-address type "+op1);
1022 }
1023 operator = IntIfCmp.IFCMP_P.INSTANCE;
1024 } else {
1025 operator = IntIfCmp.IFCMP_A.INSTANCE;
1026 }
1027 Quad q = IntIfCmp.create(quad_cfg.getNewQuadID(), operator, op0, op1, cond, new TargetOperand(target_bb));
1028 appendQuad(q);
1029 }
1030 public void visitGOTO(int target) {
1031 super.visitGOTO(target);
1032 saveStackIntoRegisters();
1033 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(target).id];
1034 Quad q = Goto.create(quad_cfg.getNewQuadID(), Goto.GOTO.INSTANCE, new TargetOperand(target_bb));
1035 appendQuad(q);
1036 }
1037 java.util.Map jsr_states = new java.util.HashMap();
1038 void setJSRState(joeq.Compiler.BytecodeAnalysis.BasicBlock bb, AbstractState s) {
1039 jsr_states.put(bb, s.copyAfterJSR());
1040 }
1041 AbstractState getJSRState(joeq.Compiler.BytecodeAnalysis.BasicBlock bb) {
1042 return (AbstractState)jsr_states.get(bb);
1043 }
1044 public void visitJSR(int target) {
1045 super.visitJSR(target);
1046 joeq.Compiler.BytecodeAnalysis.BasicBlock target_bcbb = bc_cfg.getBasicBlockByBytecodeIndex(target);
1047 BasicBlock target_bb = quad_bbs[target_bcbb.id];
1048 BasicBlock successor_bb = quad_bbs[bc_bb.id+1];
1049 joeq.Compiler.BytecodeAnalysis.JSRInfo jsrinfo = bc_cfg.getJSRInfo(target_bcbb);
1050 if (jsrinfo == null) {
1051 if (TRACE) out.println("jsr with no ret! converting to GOTO.");
1052
1053
1054 current_state.push_A(new AConstOperand(null));
1055 saveStackIntoRegisters();
1056 Quad q = Goto.create(quad_cfg.getNewQuadID(), Goto.GOTO.INSTANCE, new TargetOperand(target_bb));
1057 appendQuad(q);
1058 return;
1059 }
1060 Assert._assert(quad_bbs[jsrinfo.entry_block.id] == target_bb);
1061 BasicBlock last_bb = quad_bbs[jsrinfo.exit_block.id];
1062 JSRInfo q_jsrinfo = new JSRInfo(target_bb, last_bb, jsrinfo.changedLocals);
1063 this.quad_cfg.addJSRInfo(q_jsrinfo);
1064 saveStackIntoRegisters();
1065 RegisterOperand op0 = getStackRegister(jq_ReturnAddressType.INSTANCE);
1066 Quad q = Jsr.create(quad_cfg.getNewQuadID(), Jsr.JSR.INSTANCE, op0, new TargetOperand(target_bb), new TargetOperand(successor_bb));
1067 appendQuad(q);
1068 joeq.Compiler.BytecodeAnalysis.BasicBlock next_bb = bc_cfg.getBasicBlock(bc_bb.id+1);
1069 joeq.Compiler.BytecodeAnalysis.BasicBlock ret_bb = jsrinfo.exit_block;
1070 setJSRState(next_bb, current_state);
1071
1072
1073
1074 if (visited[ret_bb.id]) {
1075 if (TRACE) out.println("marking ret bb "+ret_bb+" for regeneration.");
1076 if (!regenerate.contains(ret_bb)) {
1077 regenerate.add(ret_bb);
1078 start_states[ret_bb.id].rebuildStack();
1079 }
1080 visited[ret_bb.id] = false;
1081 }
1082 current_state.push(op0.copy());
1083 }
1084 public void visitRET(int i) {
1085 super.visitRET(i);
1086 saveStackIntoRegisters();
1087 RegisterOperand op0 = makeLocal(i, jq_ReturnAddressType.INSTANCE);
1088 Quad q = Ret.create(quad_cfg.getNewQuadID(), Ret.RET.INSTANCE, op0);
1089 appendQuad(q);
1090 current_state.setLocal(i, null);
1091 endsWithRET = true;
1092
1093 joeq.Compiler.BytecodeAnalysis.JSRInfo jsrinfo = bc_cfg.getJSRInfo(bc_bb);
1094
1095 for (int j=0; j<bc_bb.getNumberOfSuccessors(); ++j) {
1096 joeq.Compiler.BytecodeAnalysis.BasicBlock caller_next = bc_bb.getSuccessor(j);
1097 AbstractState caller_state = getJSRState(caller_next);
1098 if (caller_state == null) {
1099 if (TRACE) out.println("haven't seen jsr call from "+caller_next+" yet.");
1100 Assert._assert(!visited[caller_next.id]);
1101 if (!regenerate.contains(caller_next)) {
1102 regenerate.add(caller_next);
1103 }
1104 continue;
1105 }
1106 caller_state.mergeAfterJSR(jsrinfo.changedLocals, current_state);
1107 if (start_states[caller_next.id] == null) {
1108 if (TRACE) out.println("Copying jsr state to "+caller_next);
1109 start_states[caller_next.id] = caller_state.copy();
1110 if (visited[caller_next.id]) {
1111 if (TRACE) out.println("must regenerate code for "+caller_next);
1112 if (!regenerate.contains(caller_next)) {
1113 regenerate.add(caller_next);
1114 start_states[caller_next.id].rebuildStack();
1115 }
1116 visited[caller_next.id] = false;
1117 }
1118 } else {
1119 if (TRACE) out.println("Merging jsr state with "+caller_next);
1120 if (start_states[caller_next.id].merge(caller_state, rf)) {
1121 if (TRACE) out.println("in set of "+caller_next+" changed");
1122 if (visited[caller_next.id]) {
1123 if (TRACE) out.println("must regenerate code for "+caller_next);
1124 if (!regenerate.contains(caller_next)) {
1125 regenerate.add(caller_next);
1126 start_states[caller_next.id].rebuildStack();
1127 }
1128 visited[caller_next.id] = false;
1129 }
1130 }
1131 }
1132 }
1133 }
1134 public void visitTABLESWITCH(int default_target, int low, int high, int[] targets) {
1135 super.visitTABLESWITCH(default_target, low, high, targets);
1136 Operand op0 = current_state.pop_I();
1137 saveStackIntoRegisters();
1138 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(default_target).id];
1139 Assert._assert(high-low+1 == targets.length);
1140 Quad q = TableSwitch.create(quad_cfg.getNewQuadID(), TableSwitch.TABLESWITCH.INSTANCE, op0, new IConstOperand(low),
1141 new TargetOperand(target_bb), targets.length);
1142 for (int i = 0; i < targets.length; ++i) {
1143 target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(targets[i]).id];
1144 TableSwitch.setTarget(q, i, target_bb);
1145 }
1146 appendQuad(q);
1147 }
1148 public void visitLOOKUPSWITCH(int default_target, int[] values, int[] targets) {
1149 super.visitLOOKUPSWITCH(default_target, values, targets);
1150 Operand op0 = current_state.pop_I();
1151 saveStackIntoRegisters();
1152 BasicBlock target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(default_target).id];
1153 Quad q = LookupSwitch.create(quad_cfg.getNewQuadID(), LookupSwitch.LOOKUPSWITCH.INSTANCE, op0, new TargetOperand(target_bb), values.length);
1154 for (int i = 0; i < values.length; ++i) {
1155 LookupSwitch.setMatch(q, i, values[i]);
1156 target_bb = quad_bbs[bc_cfg.getBasicBlockByBytecodeIndex(targets[i]).id];
1157 LookupSwitch.setTarget(q, i, target_bb);
1158 }
1159 appendQuad(q);
1160 }
1161 public void visitIRETURN() {
1162 super.visitIRETURN();
1163 Operand op0 = current_state.pop_I();
1164 Quad q = Return.create(quad_cfg.getNewQuadID(), Return.RETURN_I.INSTANCE, op0);
1165 appendQuad(q);
1166 current_state.clearStack();
1167 }
1168 public void visitLRETURN() {
1169 super.visitLRETURN();
1170 Operand op0 = current_state.pop_L();
1171 Quad q = Return.create(quad_cfg.getNewQuadID(), Return.RETURN_L.INSTANCE, op0);
1172 appendQuad(q);
1173 current_state.clearStack();
1174 }
1175 public void visitFRETURN() {
1176 super.visitFRETURN();
1177 Operand op0 = current_state.pop_F();
1178 Quad q = Return.create(quad_cfg.getNewQuadID(), Return.RETURN_F.INSTANCE, op0);
1179 appendQuad(q);
1180 current_state.clearStack();
1181 }
1182 public void visitDRETURN() {
1183 super.visitDRETURN();
1184 Operand op0 = current_state.pop_D();
1185 Quad q = Return.create(quad_cfg.getNewQuadID(), Return.RETURN_D.INSTANCE, op0);
1186 appendQuad(q);
1187 current_state.clearStack();
1188 }
1189 public void visitARETURN() {
1190 super.visitARETURN();
1191
1192 Operand op0 = current_state.pop();
1193 jq_Type t = getTypeOf(op0);
1194 Return operator;
1195 if (method.getReturnType().isAddressType()) {
1196 operator = Return.RETURN_P.INSTANCE;
1197 Assert._assert(t.isAddressType() ||
1198 t == jq_Reference.jq_NullType.NULL_TYPE ||
1199 state.isSubtype(t, Address._class) != NO, t.toString());
1200 } else {
1201 operator = t.isAddressType()?(Return)Return.RETURN_P.INSTANCE:Return.RETURN_A.INSTANCE;
1202 }
1203 Quad q = Return.create(quad_cfg.getNewQuadID(), operator, op0);
1204 appendQuad(q);
1205 current_state.clearStack();
1206 }
1207 public void visitVRETURN() {
1208 super.visitVRETURN();
1209 Quad q = Return.create(quad_cfg.getNewQuadID(), Return.RETURN_V.INSTANCE);
1210 appendQuad(q);
1211 current_state.clearStack();
1212 }
1213 private void GETSTATIChelper(jq_StaticField f, Getstatic oper1, Getstatic oper2) {
1214 f = tryResolve(f);
1215 boolean dynlink = state.needsDynamicLink(method, f);
1216 Getstatic operator = dynlink?oper1:oper2;
1217 jq_Type t = f.getType();
1218 RegisterOperand op0 = getStackRegister(t);
1219 Quad q = Getstatic.create(quad_cfg.getNewQuadID(), operator, op0, new FieldOperand(f));
1220 appendQuad(q);
1221 current_state.push(op0.copy(), t);
1222 }
1223 public void visitIGETSTATIC(jq_StaticField f) {
1224 super.visitIGETSTATIC(f);
1225 GETSTATIChelper(f, Getstatic.GETSTATIC_I_DYNLINK.INSTANCE, Getstatic.GETSTATIC_I.INSTANCE);
1226 }
1227 public void visitLGETSTATIC(jq_StaticField f) {
1228 super.visitLGETSTATIC(f);
1229 GETSTATIChelper(f, Getstatic.GETSTATIC_L_DYNLINK.INSTANCE, Getstatic.GETSTATIC_L.INSTANCE);
1230 }
1231 public void visitFGETSTATIC(jq_StaticField f) {
1232 super.visitFGETSTATIC(f);
1233 GETSTATIChelper(f, Getstatic.GETSTATIC_F_DYNLINK.INSTANCE, Getstatic.GETSTATIC_F.INSTANCE);
1234 }
1235 public void visitDGETSTATIC(jq_StaticField f) {
1236 super.visitDGETSTATIC(f);
1237 GETSTATIChelper(f, Getstatic.GETSTATIC_D_DYNLINK.INSTANCE, Getstatic.GETSTATIC_D.INSTANCE);
1238 }
1239 public void visitAGETSTATIC(jq_StaticField f) {
1240 super.visitAGETSTATIC(f);
1241 Getstatic operator1 = f.getType().isAddressType()?(Getstatic)Getstatic.GETSTATIC_P_DYNLINK.INSTANCE:Getstatic.GETSTATIC_A_DYNLINK.INSTANCE;
1242 Getstatic operator2 = f.getType().isAddressType()?(Getstatic)Getstatic.GETSTATIC_P.INSTANCE:Getstatic.GETSTATIC_A.INSTANCE;
1243 GETSTATIChelper(f, operator1, operator2);
1244 }
1245 public void visitZGETSTATIC(jq_StaticField f) {
1246 super.visitZGETSTATIC(f);
1247 GETSTATIChelper(f, Getstatic.GETSTATIC_Z_DYNLINK.INSTANCE, Getstatic.GETSTATIC_Z.INSTANCE);
1248 }
1249 public void visitBGETSTATIC(jq_StaticField f) {
1250 super.visitBGETSTATIC(f);
1251 GETSTATIChelper(f, Getstatic.GETSTATIC_B_DYNLINK.INSTANCE, Getstatic.GETSTATIC_B.INSTANCE);
1252 }
1253 public void visitCGETSTATIC(jq_StaticField f) {
1254 super.visitCGETSTATIC(f);
1255 GETSTATIChelper(f, Getstatic.GETSTATIC_C_DYNLINK.INSTANCE, Getstatic.GETSTATIC_C.INSTANCE);
1256 }
1257 public void visitSGETSTATIC(jq_StaticField f) {
1258 super.visitSGETSTATIC(f);
1259 GETSTATIChelper(f, Getstatic.GETSTATIC_S_DYNLINK.INSTANCE, Getstatic.GETSTATIC_S.INSTANCE);
1260 }
1261 private void PUTSTATIChelper(jq_StaticField f, Putstatic oper1, Putstatic oper2) {
1262 f = tryResolve(f);
1263 boolean dynlink = state.needsDynamicLink(method, f);
1264 Putstatic operator = dynlink?oper1:oper2;
1265 jq_Type t = f.getType();
1266 Operand op0 = current_state.pop(t);
1267 Quad q = Putstatic.create(quad_cfg.getNewQuadID(), operator, op0, new FieldOperand(f));
1268 appendQuad(q);
1269 }
1270 public void visitIPUTSTATIC(jq_StaticField f) {
1271 super.visitIPUTSTATIC(f);
1272 PUTSTATIChelper(f, Putstatic.PUTSTATIC_I_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_I.INSTANCE);
1273 }
1274 public void visitLPUTSTATIC(jq_StaticField f) {
1275 super.visitLPUTSTATIC(f);
1276 PUTSTATIChelper(f, Putstatic.PUTSTATIC_L_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_L.INSTANCE);
1277 }
1278 public void visitFPUTSTATIC(jq_StaticField f) {
1279 super.visitFPUTSTATIC(f);
1280 PUTSTATIChelper(f, Putstatic.PUTSTATIC_F_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_F.INSTANCE);
1281 }
1282 public void visitDPUTSTATIC(jq_StaticField f) {
1283 super.visitDPUTSTATIC(f);
1284 PUTSTATIChelper(f, Putstatic.PUTSTATIC_D_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_D.INSTANCE);
1285 }
1286 public void visitAPUTSTATIC(jq_StaticField f) {
1287 super.visitAPUTSTATIC(f);
1288 Putstatic operator1 = f.getType().isAddressType()?(Putstatic)Putstatic.PUTSTATIC_P_DYNLINK.INSTANCE:Putstatic.PUTSTATIC_A_DYNLINK.INSTANCE;
1289 Putstatic operator2 = f.getType().isAddressType()?(Putstatic)Putstatic.PUTSTATIC_P.INSTANCE:Putstatic.PUTSTATIC_A.INSTANCE;
1290 PUTSTATIChelper(f, operator1, operator2);
1291 }
1292 public void visitZPUTSTATIC(jq_StaticField f) {
1293 super.visitZPUTSTATIC(f);
1294 PUTSTATIChelper(f, Putstatic.PUTSTATIC_Z_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_Z.INSTANCE);
1295 }
1296 public void visitBPUTSTATIC(jq_StaticField f) {
1297 super.visitBPUTSTATIC(f);
1298 PUTSTATIChelper(f, Putstatic.PUTSTATIC_B_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_B.INSTANCE);
1299 }
1300 public void visitCPUTSTATIC(jq_StaticField f) {
1301 super.visitCPUTSTATIC(f);
1302 PUTSTATIChelper(f, Putstatic.PUTSTATIC_C_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_C.INSTANCE);
1303 }
1304 public void visitSPUTSTATIC(jq_StaticField f) {
1305 super.visitSPUTSTATIC(f);
1306 PUTSTATIChelper(f, Putstatic.PUTSTATIC_S_DYNLINK.INSTANCE, Putstatic.PUTSTATIC_S.INSTANCE);
1307 }
1308 private void GETFIELDhelper(jq_InstanceField f, Getfield oper1, Getfield oper2) {
1309 f = tryResolve(f);
1310 boolean dynlink = state.needsDynamicLink(method, f);
1311 Operand op1 = current_state.pop_A();
1312 clearCurrentGuard();
1313 if (performNullCheck(op1)) {
1314 if (TRACE) System.out.println("Null check triggered on "+op1);
1315 return;
1316 }
1317 jq_Type t = f.getType();
1318 RegisterOperand op0 = getStackRegister(t);
1319 Getfield operator = dynlink?oper1:oper2;
1320 Quad q = Getfield.create(quad_cfg.getNewQuadID(), operator, op0, op1, new FieldOperand(f), getCurrentGuard());
1321 appendQuad(q);
1322 current_state.push(op0.copy(), t);
1323 }
1324 public void visitIGETFIELD(jq_InstanceField f) {
1325 super.visitIGETFIELD(f);
1326 GETFIELDhelper(f, Getfield.GETFIELD_I_DYNLINK.INSTANCE, Getfield.GETFIELD_I.INSTANCE);
1327 }
1328 public void visitLGETFIELD(jq_InstanceField f) {
1329 super.visitLGETFIELD(f);
1330 GETFIELDhelper(f, Getfield.GETFIELD_L_DYNLINK.INSTANCE, Getfield.GETFIELD_L.INSTANCE);
1331 }
1332 public void visitFGETFIELD(jq_InstanceField f) {
1333 super.visitFGETFIELD(f);
1334 GETFIELDhelper(f, Getfield.GETFIELD_F_DYNLINK.INSTANCE, Getfield.GETFIELD_F.INSTANCE);
1335 }
1336 public void visitDGETFIELD(jq_InstanceField f) {
1337 super.visitDGETFIELD(f);
1338 GETFIELDhelper(f, Getfield.GETFIELD_D_DYNLINK.INSTANCE, Getfield.GETFIELD_D.INSTANCE);
1339 }
1340 public void visitAGETFIELD(jq_InstanceField f) {
1341 super.visitAGETFIELD(f);
1342 Getfield operator1 = f.getType().isAddressType()?(Getfield)Getfield.GETFIELD_P_DYNLINK.INSTANCE:Getfield.GETFIELD_A_DYNLINK.INSTANCE;
1343 Getfield operator2 = f.getType().isAddressType()?(Getfield)Getfield.GETFIELD_P.INSTANCE:Getfield.GETFIELD_A.INSTANCE;
1344 GETFIELDhelper(f, operator1, operator2);
1345 }
1346 public void visitBGETFIELD(jq_InstanceField f) {
1347 super.visitBGETFIELD(f);
1348 GETFIELDhelper(f, Getfield.GETFIELD_B_DYNLINK.INSTANCE, Getfield.GETFIELD_B.INSTANCE);
1349 }
1350 public void visitCGETFIELD(jq_InstanceField f) {
1351 super.visitCGETFIELD(f);
1352 GETFIELDhelper(f, Getfield.GETFIELD_C_DYNLINK.INSTANCE, Getfield.GETFIELD_C.INSTANCE);
1353 }
1354 public void visitSGETFIELD(jq_InstanceField f) {
1355 super.visitSGETFIELD(f);
1356 GETFIELDhelper(f, Getfield.GETFIELD_S_DYNLINK.INSTANCE, Getfield.GETFIELD_S.INSTANCE);
1357 }
1358 public void visitZGETFIELD(jq_InstanceField f) {
1359 super.visitZGETFIELD(f);
1360 GETFIELDhelper(f, Getfield.GETFIELD_Z_DYNLINK.INSTANCE, Getfield.GETFIELD_Z.INSTANCE);
1361 }
1362 private void PUTFIELDhelper(jq_InstanceField f, Putfield oper1, Putfield oper2) {
1363 f = tryResolve(f);
1364 boolean dynlink = state.needsDynamicLink(method, f);
1365 Operand op0 = current_state.pop(f.getType());
1366 Operand op1 = current_state.pop_A();
1367 clearCurrentGuard();
1368 if (performNullCheck(op1)) {
1369 if (TRACE) System.out.println("Null check triggered on "+op1);
1370 return;
1371 }
1372 Putfield operator = dynlink?oper1:oper2;
1373 Quad q = Putfield.create(quad_cfg.getNewQuadID(), operator, op1, new FieldOperand(f), op0, getCurrentGuard());
1374 appendQuad(q);
1375 }
1376 public void visitIPUTFIELD(jq_InstanceField f) {
1377 super.visitIPUTFIELD(f);
1378 PUTFIELDhelper(f, Putfield.PUTFIELD_I_DYNLINK.INSTANCE, Putfield.PUTFIELD_I.INSTANCE);
1379 }
1380 public void visitLPUTFIELD(jq_InstanceField f) {
1381 super.visitLPUTFIELD(f);
1382 PUTFIELDhelper(f, Putfield.PUTFIELD_L_DYNLINK.INSTANCE, Putfield.PUTFIELD_L.INSTANCE);
1383 }
1384 public void visitFPUTFIELD(jq_InstanceField f) {
1385 super.visitFPUTFIELD(f);
1386 PUTFIELDhelper(f, Putfield.PUTFIELD_F_DYNLINK.INSTANCE, Putfield.PUTFIELD_F.INSTANCE);
1387 }
1388 public void visitDPUTFIELD(jq_InstanceField f) {
1389 super.visitDPUTFIELD(f);
1390 PUTFIELDhelper(f, Putfield.PUTFIELD_D_DYNLINK.INSTANCE, Putfield.PUTFIELD_D.INSTANCE);
1391 }
1392 public void visitAPUTFIELD(jq_InstanceField f) {
1393 super.visitAPUTFIELD(f);
1394 Putfield operator1 = f.getType().isAddressType()?(Putfield)Putfield.PUTFIELD_P_DYNLINK.INSTANCE:Putfield.PUTFIELD_A_DYNLINK.INSTANCE;
1395 Putfield operator2 = f.getType().isAddressType()?(Putfield)Putfield.PUTFIELD_P.INSTANCE:Putfield.PUTFIELD_A.INSTANCE;
1396 PUTFIELDhelper(f, operator1, operator2);
1397 }
1398 public void visitBPUTFIELD(jq_InstanceField f) {
1399 super.visitBPUTFIELD(f);
1400 PUTFIELDhelper(f, Putfield.PUTFIELD_B_DYNLINK.INSTANCE, Putfield.PUTFIELD_B.INSTANCE);
1401 }
1402 public void visitCPUTFIELD(jq_InstanceField f) {
1403 super.visitCPUTFIELD(f);
1404 PUTFIELDhelper(f, Putfield.PUTFIELD_C_DYNLINK.INSTANCE, Putfield.PUTFIELD_C.INSTANCE);
1405 }
1406 public void visitSPUTFIELD(jq_InstanceField f) {
1407 super.visitSPUTFIELD(f);
1408 PUTFIELDhelper(f, Putfield.PUTFIELD_S_DYNLINK.INSTANCE, Putfield.PUTFIELD_S.INSTANCE);
1409 }
1410 public void visitZPUTFIELD(jq_InstanceField f) {
1411 super.visitZPUTFIELD(f);
1412 PUTFIELDhelper(f, Putfield.PUTFIELD_Z_DYNLINK.INSTANCE, Putfield.PUTFIELD_Z.INSTANCE);
1413 }
1414 public static final Utf8 peek = Utf8.get("peek");
1415 public static final Utf8 peek1 = Utf8.get("peek1");
1416 public static final Utf8 peek2 = Utf8.get("peek2");
1417 public static final Utf8 peek4 = Utf8.get("peek4");
1418 public static final Utf8 peek8 = Utf8.get("peek8");
1419 public static final Utf8 poke = Utf8.get("poke");
1420 public static final Utf8 poke1 = Utf8.get("poke1");
1421 public static final Utf8 poke2 = Utf8.get("poke2");
1422 public static final Utf8 poke4 = Utf8.get("poke4");
1423 public static final Utf8 poke8 = Utf8.get("poke8");
1424 public static final Utf8 offset = Utf8.get("offset");
1425 public static final Utf8 align = Utf8.get("align");
1426 public static final Utf8 difference = Utf8.get("difference");
1427 public static final Utf8 isNull = Utf8.get("isNull");
1428 public static final Utf8 addressOf = Utf8.get("addressOf");
1429 public static final Utf8 address32 = Utf8.get("address32");
1430 public static final Utf8 asObject = Utf8.get("asObject");
1431 public static final Utf8 asReferenceType = Utf8.get("asReferenceType");
1432 public static final Utf8 to32BitValue = Utf8.get("to32BitValue");
1433 public static final Utf8 stringRep = Utf8.get("stringRep");
1434 public static final Utf8 getNull = Utf8.get("getNull");
1435 public static final Utf8 size = Utf8.get("size");
1436 public static final Utf8 getBasePointer = Utf8.get("getBasePointer");
1437 public static final Utf8 getStackPointer = Utf8.get("getStackPointer");
1438 public static final Utf8 alloca = Utf8.get("alloca");
1439 public static final Utf8 atomicAdd = Utf8.get("atomicAdd");
1440 public static final Utf8 atomicSub = Utf8.get("atomicSub");
1441 public static final Utf8 atomicCas4 = Utf8.get("atomicCas4");
1442 public static final Utf8 atomicCas8 = Utf8.get("atomicCas8");
1443 public static final Utf8 atomicAnd = Utf8.get("atomicAnd");
1444 public static final Utf8 min = Utf8.get("min");
1445 public static final Utf8 max = Utf8.get("max");
1446 private void ADDRESShelper(jq_Method m, Invoke oper) {
1447 Utf8 name = m.getName();
1448 Quad q;
1449 if (name == poke) {
1450 Operand val = current_state.pop_P();
1451 Operand loc = current_state.pop_P();
1452 q = MemStore.create(quad_cfg.getNewQuadID(), MemStore.POKE_P.INSTANCE, loc, val);
1453 } else if (name == poke1) {
1454 Operand val = current_state.pop_I();
1455 Operand loc = current_state.pop_P();
1456 q = MemStore.create(quad_cfg.getNewQuadID(), MemStore.POKE_1.INSTANCE, loc, val);
1457 } else if (name == poke2) {
1458 Operand val = current_state.pop_I();
1459 Operand loc = current_state.pop_P();
1460 q = MemStore.create(quad_cfg.getNewQuadID(), MemStore.POKE_2.INSTANCE, loc, val);
1461 } else if (name == poke4) {
1462 Operand val = current_state.pop_I();
1463 Operand loc = current_state.pop_P();
1464 q = MemStore.create(quad_cfg.getNewQuadID(), MemStore.POKE_4.INSTANCE, loc, val);
1465 } else if (name == poke8) {
1466 Operand val = current_state.pop_L();
1467 Operand loc = current_state.pop_P();
1468 q = MemStore.create(quad_cfg.getNewQuadID(), MemStore.POKE_8.INSTANCE, loc, val);
1469 } else if (name == peek) {
1470 Operand loc = current_state.pop_P();
1471 RegisterOperand res = getStackRegister(Address._class);
1472 q = MemLoad.create(quad_cfg.getNewQuadID(), MemLoad.PEEK_P.INSTANCE, res, loc);
1473 current_state.push_P(res.copy());
1474 } else if (name == peek1) {
1475 Operand loc = current_state.pop_P();
1476 RegisterOperand res = getStackRegister(jq_Primitive.BYTE);
1477 q = MemLoad.create(quad_cfg.getNewQuadID(), MemLoad.PEEK_1.INSTANCE, res, loc);
1478 current_state.push_I(res.copy());
1479 } else if (name == peek2) {
1480 Operand loc = current_state.pop_P();
1481 RegisterOperand res = getStackRegister(jq_Primitive.SHORT);
1482 q = MemLoad.create(quad_cfg.getNewQuadID(), MemLoad.PEEK_2.INSTANCE, res, loc);
1483 current_state.push_I(res.copy());
1484 } else if (name == peek4) {
1485 Operand loc = current_state.pop_P();
1486 RegisterOperand res = getStackRegister(jq_Primitive.INT);
1487 q = MemLoad.create(quad_cfg.getNewQuadID(), MemLoad.PEEK_4.INSTANCE, res, loc);
1488 current_state.push_I(res.copy());
1489 } else if (name == peek8) {
1490 Operand loc = current_state.pop_P();
1491 RegisterOperand res = getStackRegister(jq_Primitive.LONG);
1492 q = MemLoad.create(quad_cfg.getNewQuadID(), MemLoad.PEEK_8.INSTANCE, res, loc);
1493 current_state.push_L(res.copy());
1494 } else if (name == offset) {
1495 Operand val = current_state.pop_I();
1496 Operand loc = current_state.pop_P();
1497 RegisterOperand res = getStackRegister(Address._class);
1498 q = Binary.create(quad_cfg.getNewQuadID(), Binary.ADD_P.INSTANCE, res, loc, val);
1499 current_state.push_P(res.copy());
1500 } else if (name == align) {
1501 Operand val = current_state.pop_I();
1502 Operand loc = current_state.pop_P();
1503 RegisterOperand res = getStackRegister(Address._class);
1504 q = Binary.create(quad_cfg.getNewQuadID(), Binary.ALIGN_P.INSTANCE, res, loc, val);
1505 current_state.push_P(res.copy());
1506 } else if (name == difference) {
1507 Operand val = current_state.pop_P();
1508 Operand loc = current_state.pop_P();
1509 RegisterOperand res = getStackRegister(jq_Primitive.INT);
1510 q = Binary.create(quad_cfg.getNewQuadID(), Binary.SUB_P.INSTANCE, res, loc, val);
1511 current_state.push_I(res.copy());
1512 } else if (name == alloca) {
1513 Operand amt = current_state.pop_I();
1514 RegisterOperand res = getStackRegister(StackAddress._class);
1515 q = Special.create(quad_cfg.getNewQuadID(), Special.ALLOCA.INSTANCE, res, amt);
1516 current_state.push_P(res.copy());
1517 } else if (name == isNull) {
1518 Operand loc = current_state.pop_P();
1519 RegisterOperand res = getStackRegister(jq_Primitive.BOOLEAN);
1520 q = Unary.create(quad_cfg.getNewQuadID(), Unary.ISNULL_P.INSTANCE, res, loc);
1521 current_state.push_I(res.copy());
1522 } else if (name == addressOf) {
1523 Operand loc = current_state.pop_A();
1524 RegisterOperand res = getStackRegister(Address._class);
1525 q = Unary.create(quad_cfg.getNewQuadID(), Unary.OBJECT_2ADDRESS.INSTANCE, res, loc);
1526 current_state.push_P(res.copy());
1527 } else if (name == address32) {
1528 Operand loc = current_state.pop_I();
1529 RegisterOperand res = getStackRegister(Address._class);
1530 q = Unary.create(quad_cfg.getNewQuadID(), Unary.INT_2ADDRESS.INSTANCE, res, loc);
1531 current_state.push_P(res.copy());
1532 } else if (name == asObject) {
1533 Operand loc = current_state.pop_P();
1534 RegisterOperand res = getStackRegister(PrimordialClassLoader.getJavaLangObject());
1535 q = Unary.create(quad_cfg.getNewQuadID(), Unary.ADDRESS_2OBJECT.INSTANCE, res, loc);
1536 current_state.push_A(res.copy());
1537 } else if (name == asReferenceType) {
1538 Operand loc = current_state.pop_P();
1539 RegisterOperand res = getStackRegister(jq_Reference._class);
1540 q = Unary.create(quad_cfg.getNewQuadID(), Unary.ADDRESS_2OBJECT.INSTANCE, res, loc);
1541 current_state.push_A(res.copy());
1542 } else if (name == to32BitValue) {
1543 Operand loc = current_state.pop_P();
1544 RegisterOperand res = getStackRegister(jq_Primitive.INT);
1545 q = Unary.create(quad_cfg.getNewQuadID(), Unary.ADDRESS_2INT.INSTANCE, res, loc);
1546 current_state.push_I(res.copy());
1547 } else if (name == stringRep) {
1548 Operand loc = current_state.pop_P();
1549 RegisterOperand res = getStackRegister(jq_Primitive.INT);
1550 q = Unary.create(quad_cfg.getNewQuadID(), Unary.ADDRESS_2INT.INSTANCE, res, loc);
1551 current_state.push_I(res.copy());
1552 appendQuad(q);
1553
1554 jq_Class k = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("Ljwutil/strings/Strings;");
1555 jq_StaticMethod sm = k.getOrCreateStaticMethod("hex8", "(I)Ljava/lang/String;");
1556 INVOKEhelper(Invoke.INVOKESTATIC_A.INSTANCE, sm, sm.getReturnType(), false);
1557 return;
1558 } else if (name == getNull) {
1559 PConstOperand p = new PConstOperand(null);
1560 current_state.push_P(p);
1561 return;
1562 } else if (name == size) {
1563 IConstOperand p = new IConstOperand(HeapAddress.size());
1564 current_state.push_I(p);
1565 return;
1566 } else if (name == getBasePointer) {
1567 RegisterOperand res = getStackRegister(StackAddress._class);
1568 q = Special.create(quad_cfg.getNewQuadID(), Special.GET_BASE_POINTER.INSTANCE, res);
1569 current_state.push_P(res.copy());
1570 } else if (name == getStackPointer) {
1571 RegisterOperand res = getStackRegister(StackAddress._class);
1572 q = Special.create(quad_cfg.getNewQuadID(), Special.GET_STACK_POINTER.INSTANCE, res);
1573 current_state.push_P(res.copy());
1574 } else if (name == atomicAdd) {
1575 Operand val = current_state.pop_I();
1576 Operand loc = current_state.pop_P();
1577 q = Special.create(quad_cfg.getNewQuadID(), Special.ATOMICADD_I.INSTANCE, loc, val);
1578 } else if (name == atomicSub) {
1579 Operand val = current_state.pop_I();
1580 Operand loc = current_state.pop_P();
1581 q = Special.create(quad_cfg.getNewQuadID(), Special.ATOMICSUB_I.INSTANCE, loc, val);
1582 } else if (name == atomicAnd) {
1583 Operand val = current_state.pop_I();
1584 Operand loc = current_state.pop_P();
1585 q = Special.create(quad_cfg.getNewQuadID(), Special.ATOMICAND_I.INSTANCE, loc, val);
1586 } else if (name == atomicCas4) {
1587 Operand val2 = current_state.pop_I();
1588 Operand val1 = current_state.pop_I();
1589 Operand loc = current_state.pop_P();
1590 RegisterOperand res = getStackRegister(jq_Primitive.INT);
1591 q = Special.create(quad_cfg.getNewQuadID(), Special.ATOMICCAS4.INSTANCE, res, loc, val1, val2);
1592 current_state.push_I(res.copy());
1593 } else if (name == atomicCas8) {
1594 Operand val2 = current_state.pop_L();
1595 Operand val1 = current_state.pop_L();
1596 Operand loc = current_state.pop_P();
1597 RegisterOperand res = getStackRegister(jq_Primitive.LONG);
1598 q = Special.create(quad_cfg.getNewQuadID(), Special.ATOMICCAS8.INSTANCE, res, loc, val1, val2);
1599 current_state.push_L(res.copy());
1600 } else {
1601
1602 INVOKEhelper(oper, m, m.getReturnType(), false);
1603 return;
1604 }
1605 appendQuad(q);
1606 mergeStateWithAllExHandlers(false);
1607 }
1608 private void UNSAFEhelper(jq_Method m, Invoke oper) {
1609 if (_unsafe.handleMethod(this, quad_cfg, current_state, m, oper)) {
1610 mergeStateWithAllExHandlers(false);
1611 if (_unsafe.endsBB(m)) {
1612 endBasicBlock = true;
1613 }
1614 } else {
1615
1616 INVOKEhelper(oper, m, m.getReturnType(), false);
1617 return;
1618 }
1619 }
1620 private void INVOKEhelper(Invoke oper, jq_Method f, jq_Type returnType, boolean instance_call) {
1621 jq_Type[] paramTypes = f.getParamTypes();
1622 RegisterOperand result;
1623 if (returnType == jq_Primitive.VOID) result = null;
1624 else result = getStackRegister(returnType, f.getParamWords()-1);
1625 Quad q = Invoke.create(quad_cfg.getNewQuadID(), oper, result, new MethodOperand(f), paramTypes.length);
1626 Operand op = null;
1627 for (int i = paramTypes.length; --i >= 0; ) {
1628 jq_Type ptype = paramTypes[i];
1629 op = current_state.pop(ptype);
1630 RegisterOperand rop;
1631 if (op instanceof RegisterOperand) rop = (RegisterOperand)op;
1632 else {
1633 rop = getStackRegister(ptype);
1634 Quad q2 = Move.create(quad_cfg.getNewQuadID(), Move.getMoveOp(ptype), (RegisterOperand) rop.copy(), op);
1635 appendQuad(q2);
1636 }
1637 Invoke.setParam(q, i, rop);
1638 }
1639 clearCurrentGuard();
1640 if (instance_call && performNullCheck(op)) {
1641 if (TRACE) System.out.println("Null check triggered on "+op);
1642 return;
1643 }
1644 appendQuad(q);
1645 mergeStateWithAllExHandlers(false);
1646 if (result != null) current_state.push(result.copy(), returnType);
1647 }
1648 public void visitIINVOKE(byte op, jq_Method f) {
1649 super.visitIINVOKE(op, f);
1650 if (_unsafe.isUnsafe(f)) {
1651 UNSAFEhelper(f, Invoke.INVOKESTATIC_I.INSTANCE);
1652 return;
1653 }
1654 if (f.getDeclaringClass().isAddressType()) {
1655 ADDRESShelper(f, f.isStatic()?(Invoke)Invoke.INVOKESTATIC_I.INSTANCE:Invoke.INVOKEVIRTUAL_I.INSTANCE);
1656 return;
1657 }
1658 f = (jq_Method) tryResolve(f);
1659 boolean dynlink = state.needsDynamicLink(method, f);
1660 Invoke oper;
1661 boolean instance_call;
1662 switch (op) {
1663 case INVOKE_VIRTUAL:
1664 instance_call = true;
1665 if (dynlink)
1666 oper = Invoke.INVOKEVIRTUAL_I_DYNLINK.INSTANCE;
1667 else {
1668 oper = Invoke.INVOKEVIRTUAL_I.INSTANCE;
1669 }
1670
1671
1672 break;
1673 case INVOKE_STATIC:
1674 instance_call = false;
1675 if (dynlink)
1676 oper = Invoke.INVOKESTATIC_I_DYNLINK.INSTANCE;
1677 else {
1678 oper = Invoke.INVOKESTATIC_I.INSTANCE;
1679 }
1680 break;
1681 case INVOKE_SPECIAL:
1682 instance_call = true;
1683 Assert._assert(f instanceof jq_InstanceMethod);
1684 if (dynlink)
1685 oper = Invoke.INVOKESPECIAL_I_DYNLINK.INSTANCE;
1686 else {
1687 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1688 oper = Invoke.INVOKESTATIC_I.INSTANCE;
1689 }
1690 break;
1691 case INVOKE_INTERFACE:
1692 instance_call = true;
1693 oper = Invoke.INVOKEINTERFACE_I.INSTANCE;
1694 break;
1695 default:
1696 throw new InternalError();
1697 }
1698 INVOKEhelper(oper, f, jq_Primitive.INT, instance_call);
1699 }
1700 public void visitLINVOKE(byte op, jq_Method f) {
1701 super.visitLINVOKE(op, f);
1702 if (_unsafe.isUnsafe(f)) {
1703 UNSAFEhelper(f, Invoke.INVOKESTATIC_L.INSTANCE);
1704 return;
1705 }
1706 if (f.getDeclaringClass().isAddressType()) {
1707 ADDRESShelper(f, f.isStatic()?(Invoke)Invoke.INVOKESTATIC_L.INSTANCE:Invoke.INVOKEVIRTUAL_L.INSTANCE);
1708 return;
1709 }
1710 f = (jq_Method) tryResolve(f);
1711 boolean dynlink = state.needsDynamicLink(method, f);
1712 Invoke oper;
1713 boolean instance_call;
1714 switch (op) {
1715 case INVOKE_VIRTUAL:
1716 instance_call = true;
1717 if (dynlink)
1718 oper = Invoke.INVOKEVIRTUAL_L_DYNLINK.INSTANCE;
1719 else {
1720 oper = Invoke.INVOKEVIRTUAL_L.INSTANCE;
1721 }
1722 break;
1723 case INVOKE_STATIC:
1724 instance_call = false;
1725 if (dynlink)
1726 oper = Invoke.INVOKESTATIC_L_DYNLINK.INSTANCE;
1727 else {
1728 oper = Invoke.INVOKESTATIC_L.INSTANCE;
1729 }
1730 break;
1731 case INVOKE_SPECIAL:
1732 instance_call = true;
1733 Assert._assert(f instanceof jq_InstanceMethod);
1734 if (dynlink)
1735 oper = Invoke.INVOKESPECIAL_L_DYNLINK.INSTANCE;
1736 else {
1737 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1738 oper = Invoke.INVOKESTATIC_L.INSTANCE;
1739 }
1740 break;
1741 case INVOKE_INTERFACE:
1742 instance_call = true;
1743 oper = Invoke.INVOKEINTERFACE_L.INSTANCE;
1744 break;
1745 default:
1746 throw new InternalError();
1747 }
1748 INVOKEhelper(oper, f, jq_Primitive.LONG, instance_call);
1749 }
1750 public void visitFINVOKE(byte op, jq_Method f) {
1751 super.visitFINVOKE(op, f);
1752 if (_unsafe.isUnsafe(f)) {
1753 UNSAFEhelper(f, Invoke.INVOKESTATIC_F.INSTANCE);
1754 return;
1755 }
1756 if (f.getDeclaringClass().isAddressType()) {
1757 ADDRESShelper(f, f.isStatic()?(Invoke)Invoke.INVOKESTATIC_F.INSTANCE:Invoke.INVOKEVIRTUAL_F.INSTANCE);
1758 return;
1759 }
1760 f = (jq_Method) tryResolve(f);
1761 boolean dynlink = state.needsDynamicLink(method, f);
1762 Invoke oper;
1763 boolean instance_call;
1764 switch (op) {
1765 case INVOKE_VIRTUAL:
1766 instance_call = true;
1767 if (dynlink)
1768 oper = Invoke.INVOKEVIRTUAL_F_DYNLINK.INSTANCE;
1769 else {
1770 oper = Invoke.INVOKEVIRTUAL_F.INSTANCE;
1771 }
1772 break;
1773 case INVOKE_STATIC:
1774 instance_call = false;
1775 if (dynlink)
1776 oper = Invoke.INVOKESTATIC_F_DYNLINK.INSTANCE;
1777 else {
1778 oper = Invoke.INVOKESTATIC_F.INSTANCE;
1779 }
1780 break;
1781 case INVOKE_SPECIAL:
1782 instance_call = true;
1783 Assert._assert(f instanceof jq_InstanceMethod);
1784 if (dynlink)
1785 oper = Invoke.INVOKESPECIAL_F_DYNLINK.INSTANCE;
1786 else {
1787 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1788 oper = Invoke.INVOKESTATIC_F.INSTANCE;
1789 }
1790 break;
1791 case INVOKE_INTERFACE:
1792 instance_call = true;
1793 oper = Invoke.INVOKEINTERFACE_F.INSTANCE;
1794 break;
1795 default:
1796 throw new InternalError();
1797 }
1798 INVOKEhelper(oper, f, jq_Primitive.FLOAT, instance_call);
1799 }
1800 public void visitDINVOKE(byte op, jq_Method f) {
1801 super.visitDINVOKE(op, f);
1802 if (_unsafe.isUnsafe(f)) {
1803 UNSAFEhelper(f, Invoke.INVOKESTATIC_D.INSTANCE);
1804 return;
1805 }
1806 if (f.getDeclaringClass().isAddressType()) {
1807 ADDRESShelper(f, f.isStatic()?(Invoke)Invoke.INVOKESTATIC_D.INSTANCE:Invoke.INVOKEVIRTUAL_D.INSTANCE);
1808 return;
1809 }
1810 f = (jq_Method) tryResolve(f);
1811 boolean dynlink = state.needsDynamicLink(method, f);
1812 Invoke oper;
1813 boolean instance_call;
1814 switch (op) {
1815 case INVOKE_VIRTUAL:
1816 instance_call = true;
1817 if (dynlink)
1818 oper = Invoke.INVOKEVIRTUAL_D_DYNLINK.INSTANCE;
1819 else {
1820 oper = Invoke.INVOKEVIRTUAL_D.INSTANCE;
1821 }
1822 break;
1823 case INVOKE_STATIC:
1824 instance_call = false;
1825 if (dynlink)
1826 oper = Invoke.INVOKESTATIC_D_DYNLINK.INSTANCE;
1827 else {
1828 oper = Invoke.INVOKESTATIC_D.INSTANCE;
1829 }
1830 break;
1831 case INVOKE_SPECIAL:
1832 instance_call = true;
1833 Assert._assert(f instanceof jq_InstanceMethod);
1834 if (dynlink)
1835 oper = Invoke.INVOKESPECIAL_D_DYNLINK.INSTANCE;
1836 else {
1837 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1838 oper = Invoke.INVOKESTATIC_D.INSTANCE;
1839 }
1840 break;
1841 case INVOKE_INTERFACE:
1842 instance_call = true;
1843 oper = Invoke.INVOKEINTERFACE_D.INSTANCE;
1844 break;
1845 default:
1846 throw new InternalError();
1847 }
1848 INVOKEhelper(oper, f, jq_Primitive.DOUBLE, instance_call);
1849 }
1850 public void visitAINVOKE(byte op, jq_Method f) {
1851 super.visitAINVOKE(op, f);
1852 if (_unsafe.isUnsafe(f)) {
1853 UNSAFEhelper(f, f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKESTATIC_P.INSTANCE:Invoke.INVOKESTATIC_A.INSTANCE);
1854 return;
1855 }
1856 if (f.getDeclaringClass().isAddressType()) {
1857 Invoke oper;
1858 if (f.isStatic()) {
1859 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKESTATIC_P.INSTANCE:Invoke.INVOKESTATIC_A.INSTANCE;
1860 } else {
1861 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKEVIRTUAL_P.INSTANCE:Invoke.INVOKEVIRTUAL_A.INSTANCE;
1862 }
1863 ADDRESShelper(f, oper);
1864 return;
1865 }
1866 f = (jq_Method) tryResolve(f);
1867 boolean dynlink = state.needsDynamicLink(method, f);
1868 Invoke oper;
1869 boolean instance_call;
1870 switch (op) {
1871 case INVOKE_VIRTUAL:
1872 instance_call = true;
1873 if (dynlink)
1874 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKEVIRTUAL_P_DYNLINK.INSTANCE:Invoke.INVOKEVIRTUAL_A_DYNLINK.INSTANCE;
1875 else {
1876 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKEVIRTUAL_P.INSTANCE:Invoke.INVOKEVIRTUAL_A.INSTANCE;
1877 }
1878 break;
1879 case INVOKE_STATIC:
1880 instance_call = false;
1881 if (dynlink)
1882 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKESTATIC_P_DYNLINK.INSTANCE:Invoke.INVOKESTATIC_A_DYNLINK.INSTANCE;
1883 else {
1884 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKESTATIC_P.INSTANCE:Invoke.INVOKESTATIC_A.INSTANCE;
1885 }
1886 break;
1887 case INVOKE_SPECIAL:
1888 instance_call = true;
1889 Assert._assert(f instanceof jq_InstanceMethod);
1890 if (dynlink)
1891 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKESPECIAL_P_DYNLINK.INSTANCE:Invoke.INVOKESPECIAL_A_DYNLINK.INSTANCE;
1892 else {
1893 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1894 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKESTATIC_P.INSTANCE:Invoke.INVOKESTATIC_A.INSTANCE;
1895 }
1896 break;
1897 case INVOKE_INTERFACE:
1898 instance_call = true;
1899 oper = f.getReturnType().isAddressType()?(Invoke)Invoke.INVOKEINTERFACE_P.INSTANCE:Invoke.INVOKEINTERFACE_A.INSTANCE;
1900 break;
1901 default:
1902 throw new InternalError();
1903 }
1904 INVOKEhelper(oper, f, f.getReturnType(), instance_call);
1905 }
1906 public void visitVINVOKE(byte op, jq_Method f) {
1907 super.visitVINVOKE(op, f);
1908 if (_unsafe.isUnsafe(f)) {
1909 UNSAFEhelper(f, Invoke.INVOKESTATIC_V.INSTANCE);
1910 return;
1911 }
1912 if (f.getDeclaringClass().isAddressType()) {
1913 ADDRESShelper(f, f.isStatic()?(Invoke)Invoke.INVOKESTATIC_V.INSTANCE:Invoke.INVOKEVIRTUAL_V.INSTANCE);
1914 return;
1915 }
1916 f = (jq_Method) tryResolve(f);
1917 boolean dynlink = state.needsDynamicLink(method, f);
1918 Invoke oper;
1919 boolean instance_call;
1920 switch (op) {
1921 case INVOKE_VIRTUAL:
1922 instance_call = true;
1923 if (dynlink)
1924 oper = Invoke.INVOKEVIRTUAL_V_DYNLINK.INSTANCE;
1925 else {
1926 oper = Invoke.INVOKEVIRTUAL_V.INSTANCE;
1927 }
1928 break;
1929 case INVOKE_STATIC:
1930 instance_call = false;
1931 if (dynlink)
1932 oper = Invoke.INVOKESTATIC_V_DYNLINK.INSTANCE;
1933 else {
1934 oper = Invoke.INVOKESTATIC_V.INSTANCE;
1935 }
1936 break;
1937 case INVOKE_SPECIAL:
1938 instance_call = true;
1939 Assert._assert(f instanceof jq_InstanceMethod);
1940 if (dynlink)
1941 oper = Invoke.INVOKESPECIAL_V_DYNLINK.INSTANCE;
1942 else {
1943 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1944 oper = Invoke.INVOKESTATIC_V.INSTANCE;
1945 }
1946 break;
1947 case INVOKE_INTERFACE:
1948 instance_call = true;
1949 oper = Invoke.INVOKEINTERFACE_V.INSTANCE;
1950 break;
1951 default:
1952 throw new InternalError();
1953 }
1954 INVOKEhelper(oper, f, f.getReturnType(), instance_call);
1955 }
1956 public void visitNEW(jq_Type f) {
1957 super.visitNEW(f);
1958 RegisterOperand res = getStackRegister(f);
1959 Quad q = New.create(quad_cfg.getNewQuadID(), New.NEW.INSTANCE, res, new TypeOperand(f));
1960 appendQuad(q);
1961 current_state.push_A(res.copy());
1962 }
1963 public void visitNEWARRAY(jq_Array f) {
1964 super.visitNEWARRAY(f);
1965 Operand size = current_state.pop_I();
1966 RegisterOperand res = getStackRegister(f);
1967 Quad q = NewArray.create(quad_cfg.getNewQuadID(), NewArray.NEWARRAY.INSTANCE, res, size, new TypeOperand(f));
1968 appendQuad(q);
1969 mergeStateWithAllExHandlers(false);
1970 current_state.push_A(res.copy());
1971 }
1972 public void visitCHECKCAST(jq_Type f) {
1973 super.visitCHECKCAST(f);
1974 Operand op = current_state.pop();
1975 RegisterOperand res = getStackRegister(f);
1976 if (!f.isAddressType()) {
1977 Quad q = CheckCast.create(quad_cfg.getNewQuadID(), CheckCast.CHECKCAST.INSTANCE, res, op, new TypeOperand(f));
1978 appendQuad(q);
1979 mergeStateWithAllExHandlers(false);
1980 current_state.push_A(res.copy());
1981 } else {
1982 current_state.push_P(res);
1983 }
1984 }
1985 public void visitINSTANCEOF(jq_Type f) {
1986 super.visitINSTANCEOF(f);
1987 Assert._assert(!f.isAddressType(), method.toString());
1988 Operand op = current_state.pop_A();
1989 RegisterOperand res = getStackRegister(jq_Primitive.BOOLEAN);
1990 Quad q = InstanceOf.create(quad_cfg.getNewQuadID(), InstanceOf.INSTANCEOF.INSTANCE, res, op, new TypeOperand(f));
1991 appendQuad(q);
1992 current_state.push_I(res.copy());
1993 }
1994 public void visitARRAYLENGTH() {
1995 super.visitARRAYLENGTH();
1996 Operand op = current_state.pop_A();
1997 clearCurrentGuard();
1998 if (performNullCheck(op)) {
1999 if (TRACE) System.out.println("Null check triggered on "+op);
2000 return;
2001 }
2002 RegisterOperand res = getStackRegister(jq_Primitive.INT);
2003 Quad q = ALength.create(quad_cfg.getNewQuadID(), ALength.ARRAYLENGTH.INSTANCE, res, op);
2004 appendQuad(q);
2005 current_state.push_I(res.copy());
2006 }
2007 public void visitATHROW() {
2008 super.visitATHROW();
2009 Operand op0 = current_state.pop_A();
2010 Quad q = Return.create(quad_cfg.getNewQuadID(), Return.THROW_A.INSTANCE, op0);
2011 appendQuad(q);
2012 current_state.clearStack();
2013 }
2014 public void visitMONITOR(byte op) {
2015 super.visitMONITOR(op);
2016 Operand op0 = current_state.pop_A();
2017 Monitor oper = op==MONITOR_ENTER ? (Monitor)Monitor.MONITORENTER.INSTANCE : (Monitor)Monitor.MONITOREXIT.INSTANCE;
2018 Quad q = Monitor.create(quad_cfg.getNewQuadID(), oper, op0);
2019 appendQuad(q);
2020 mergeStateWithAllExHandlers(false);
2021 }
2022 public void visitMULTINEWARRAY(jq_Type f, char dim) {
2023 super.visitMULTINEWARRAY(f, dim);
2024 RegisterOperand result = getStackRegister(f, dim-1);
2025 Quad q = Invoke.create(quad_cfg.getNewQuadID(), Invoke.INVOKESTATIC_A.INSTANCE, result, new MethodOperand(joeq.Runtime.Arrays._multinewarray), dim+2);
2026 RegisterOperand rop = new RegisterOperand(rf.getOrCreateStack(current_state.getStackSize(), jq_Primitive.INT), jq_Primitive.INT);
2027 Quad q2 = Move.create(quad_cfg.getNewQuadID(), Move.MOVE_I.INSTANCE, rop, new IConstOperand(dim));
2028 appendQuad(q2);
2029 Invoke.setParam(q, 0, (RegisterOperand) rop.copy());
2030 rop = new RegisterOperand(rf.getOrCreateStack(current_state.getStackSize()+1, jq_Type._class), jq_Type._class);
2031 q2 = Move.create(quad_cfg.getNewQuadID(), Move.MOVE_A.INSTANCE, rop, new AConstOperand(f));
2032 appendQuad(q2);
2033 Invoke.setParam(q, 1, (RegisterOperand) rop.copy());
2034 for (int i=0; i<dim; ++i) {
2035 Operand op = current_state.pop_I();
2036 if (op instanceof RegisterOperand) rop = (RegisterOperand)op;
2037 else {
2038 rop = getStackRegister(jq_Primitive.INT);
2039 q2 = Move.create(quad_cfg.getNewQuadID(), Move.MOVE_I.INSTANCE, (RegisterOperand) rop.copy(), op);
2040 appendQuad(q2);
2041 }
2042 Invoke.setParam(q, i+2, rop);
2043 }
2044 appendQuad(q);
2045 mergeStateWithAllExHandlers(false);
2046 current_state.push(result.copy(), f);
2047 }
2048
2049 public static final boolean ELIM_NULL_CHECKS = true;
2050
2051 boolean performNullCheck(Operand op) {
2052 if (op instanceof AConstOperand) {
2053 Object val = ((AConstOperand)op).getValue();
2054 if (val != null) {
2055 setCurrentGuard(new UnnecessaryGuardOperand());
2056 return false;
2057 } else {
2058 Quad q = NullCheck.create(quad_cfg.getNewQuadID(), NullCheck.NULL_CHECK.INSTANCE, null, op.copy());
2059 appendQuad(q);
2060 if (false) {
2061 endBasicBlock = true;
2062 mergeStateWithNullPtrExHandler(true);
2063 return true;
2064 } else {
2065 mergeStateWithNullPtrExHandler(false);
2066 return false;
2067 }
2068 }
2069 }
2070 RegisterOperand rop = (RegisterOperand)op;
2071 if (ELIM_NULL_CHECKS) {
2072 if (hasGuard(rop)) {
2073 Operand guard = getGuard(rop);
2074 setCurrentGuard(guard);
2075 return false;
2076 }
2077 }
2078 RegisterOperand guard = makeGuardReg();
2079 Quad q = NullCheck.create(quad_cfg.getNewQuadID(), NullCheck.NULL_CHECK.INSTANCE, guard, rop.copy());
2080 appendQuad(q);
2081 mergeStateWithNullPtrExHandler(false);
2082 setCurrentGuard(guard);
2083 setGuard(rop, guard);
2084
2085 jq_Type type = rop.getType();
2086 if (type.isAddressType()) {
2087
2088 return false;
2089 }
2090 int number = getLocalNumber(rop.getRegister(), type);
2091 if (isLocal(rop, number, type)) {
2092 Operand op2 = current_state.getLocal_A(number);
2093 if (op2 instanceof RegisterOperand) {
2094 setGuard((RegisterOperand)op2, guard);
2095 }
2096 current_state.setLocal(number, op2);
2097 replaceLocalsOnStack(number, type);
2098 }
2099 return false;
2100 }
2101
2102 boolean performBoundsCheck(Operand ref, Operand index) {
2103 Quad q = BoundsCheck.create(quad_cfg.getNewQuadID(), BoundsCheck.BOUNDS_CHECK.INSTANCE, ref.copy(), index.copy(), getCurrentGuard());
2104 appendQuad(q);
2105 mergeStateWithArrayBoundsExHandler(false);
2106 return false;
2107 }
2108
2109 boolean performCheckStore(RegisterOperand ref, Operand elem) {
2110 jq_Type type = getTypeOf(elem);
2111 if (type == jq_Reference.jq_NullType.NULL_TYPE) return false;
2112 jq_Type arrayElemType = getArrayElementTypeOf(ref);
2113 if (arrayElemType.isAddressType()) {
2114 if (type.isAddressType() || type == jq_Reference.jq_NullType.NULL_TYPE)
2115 return false;
2116 Assert.UNREACHABLE("Storing non-address value into address array! Array: "+ref+" Type: "+type);
2117 }
2118 if (type.isAddressType()) {
2119 Assert.UNREACHABLE("Storing address value into non-address array! Array: "+ref+" Type: "+type);
2120 }
2121 if (ref.isExactType()) {
2122 if (state.isSubtype(type, arrayElemType) == YES)
2123 return false;
2124 }
2125 jq_Type arrayElemType2 = arrayElemType;
2126 if (arrayElemType.isArrayType()) {
2127 arrayElemType2 = ((jq_Array)arrayElemType).getInnermostElementType();
2128 }
2129 if (arrayElemType2.isLoaded() && arrayElemType2.isFinal()) {
2130 if (arrayElemType == type)
2131 return false;
2132 }
2133 Quad q = StoreCheck.create(quad_cfg.getNewQuadID(), StoreCheck.ASTORE_CHECK.INSTANCE, ref.copy(), elem.copy(), getCurrentGuard());
2134 appendQuad(q);
2135 mergeStateWithObjArrayStoreExHandler(false);
2136 return false;
2137 }
2138
2139 boolean performZeroCheck(Operand op) {
2140 if (op instanceof IConstOperand) {
2141 int val = ((IConstOperand)op).getValue();
2142 if (val != 0) {
2143 setCurrentGuard(new UnnecessaryGuardOperand());
2144 return false;
2145 } else {
2146 Quad q = ZeroCheck.create(quad_cfg.getNewQuadID(), ZeroCheck.ZERO_CHECK_I.INSTANCE, null, op.copy());
2147 appendQuad(q);
2148 if (false) {
2149 endBasicBlock = true;
2150 mergeStateWithArithExHandler(true);
2151 return true;
2152 } else {
2153 mergeStateWithArithExHandler(false);
2154 return false;
2155 }
2156 }
2157 }
2158 if (op instanceof LConstOperand) {
2159 long val = ((LConstOperand)op).getValue();
2160 if (val != 0) {
2161 setCurrentGuard(new UnnecessaryGuardOperand());
2162 return false;
2163 } else {
2164 Quad q = ZeroCheck.create(quad_cfg.getNewQuadID(), ZeroCheck.ZERO_CHECK_L.INSTANCE, null, op.copy());
2165 appendQuad(q);
2166 if (false) {
2167 endBasicBlock = true;
2168 mergeStateWithArithExHandler(true);
2169 return true;
2170 } else {
2171 mergeStateWithArithExHandler(false);
2172 return false;
2173 }
2174 }
2175 }
2176 RegisterOperand rop = (RegisterOperand)op;
2177 if (hasGuard(rop)) {
2178 Operand guard = getGuard(rop);
2179 setCurrentGuard(guard);
2180 return false;
2181 }
2182 RegisterOperand guard = makeGuardReg();
2183 ZeroCheck oper = null;
2184 if (rop.getType() == jq_Primitive.LONG) oper = ZeroCheck.ZERO_CHECK_L.INSTANCE;
2185 else if (rop.getType().isIntLike()) oper = ZeroCheck.ZERO_CHECK_I.INSTANCE;
2186 else Assert.UNREACHABLE("Zero check on "+rop+" type "+rop.getType());
2187 Quad q = ZeroCheck.create(quad_cfg.getNewQuadID(), oper, guard, rop.copy());
2188 appendQuad(q);
2189 mergeStateWithArithExHandler(false);
2190 setCurrentGuard(guard);
2191 setGuard(rop, guard);
2192
2193 jq_Type type = rop.getType();
2194 int number = getLocalNumber(rop.getRegister(), type);
2195 if (isLocal(rop, number, type)) {
2196 Operand op2 = null;
2197 if (type == jq_Primitive.LONG)
2198 op2 = current_state.getLocal_L(number);
2199 else if (type.isIntLike())
2200 op2 = current_state.getLocal_I(number);
2201 else
2202 Assert.UNREACHABLE("Unknown type for local "+number+" "+rop+": "+type);
2203 if (TRACE) System.out.println(rop+" is a local variable of type "+type+": currently "+op2);
2204 if (op2 instanceof RegisterOperand) {
2205 setGuard((RegisterOperand)op2, guard);
2206 }
2207 current_state.setLocal(number, op2);
2208 replaceLocalsOnStack(number, type);
2209 }
2210 return false;
2211 }
2212
2213 static jq_Type getTypeOf(Operand op) {
2214 if (op instanceof IConstOperand) return jq_Primitive.INT;
2215 if (op instanceof FConstOperand) return jq_Primitive.FLOAT;
2216 if (op instanceof LConstOperand) return jq_Primitive.LONG;
2217 if (op instanceof DConstOperand) return jq_Primitive.DOUBLE;
2218 if (op instanceof PConstOperand) return Address._class;
2219 if (op instanceof AConstOperand) {
2220 Object val = ((AConstOperand)op).getValue();
2221 if (val == null) return jq_Reference.jq_NullType.NULL_TYPE;
2222 return Reflection.getTypeOf(val);
2223 }
2224 Assert._assert(op instanceof RegisterOperand, op.toString() + " is not a RegisterOperand");
2225 return ((RegisterOperand)op).getType();
2226 }
2227 static jq_Type getArrayElementTypeOf(Operand op) {
2228 if (op instanceof RegisterOperand) {
2229 return ((jq_Array)((RegisterOperand)op).getType()).getElementType();
2230 } else if (op instanceof AConstOperand && ((AConstOperand)op).getValue() == null) {
2231
2232 return PrimordialClassLoader.getJavaLangObject();
2233 } else {
2234 Assert.UNREACHABLE(op.toString());
2235 return null;
2236 }
2237 }
2238
2239 void mergeStateWithAllExHandlers(boolean cfgEdgeToExit) {
2240 joeq.Compiler.BytecodeAnalysis.ExceptionHandlerIterator i =
2241 bc_bb.getExceptionHandlers();
2242 while (i.hasNext()) {
2243 joeq.Compiler.BytecodeAnalysis.ExceptionHandler eh = i.nextEH();
2244 mergeStateWith(eh);
2245 }
2246 }
2247 void mergeStateWithNullPtrExHandler(boolean cfgEdgeToExit) {
2248 joeq.Compiler.BytecodeAnalysis.ExceptionHandlerIterator i =
2249 bc_bb.getExceptionHandlers();
2250 while (i.hasNext()) {
2251 joeq.Compiler.BytecodeAnalysis.ExceptionHandler eh = i.nextEH();
2252 jq_Class k = eh.getExceptionType();
2253 if (k == PrimordialClassLoader.getJavaLangNullPointerException() ||
2254 k == PrimordialClassLoader.getJavaLangRuntimeException() ||
2255 k == PrimordialClassLoader.getJavaLangException() ||
2256 k == PrimordialClassLoader.getJavaLangThrowable() ||
2257 k == null) {
2258 mergeStateWith(eh);
2259 break;
2260 }
2261 }
2262 }
2263 void mergeStateWithArithExHandler(boolean cfgEdgeToExit) {
2264 joeq.Compiler.BytecodeAnalysis.ExceptionHandlerIterator i =
2265 bc_bb.getExceptionHandlers();
2266 while (i.hasNext()) {
2267 joeq.Compiler.BytecodeAnalysis.ExceptionHandler eh = i.nextEH();
2268 jq_Class k = eh.getExceptionType();
2269 if (k == PrimordialClassLoader.getJavaLangArithmeticException() ||
2270 k == PrimordialClassLoader.getJavaLangRuntimeException() ||
2271 k == PrimordialClassLoader.getJavaLangException() ||
2272 k == PrimordialClassLoader.getJavaLangThrowable() ||
2273 k == null) {
2274 mergeStateWith(eh);
2275 break;
2276 }
2277 }
2278 }
2279 void mergeStateWithArrayBoundsExHandler(boolean cfgEdgeToExit) {
2280 joeq.Compiler.BytecodeAnalysis.ExceptionHandlerIterator i =
2281 bc_bb.getExceptionHandlers();
2282 while (i.hasNext()) {
2283 joeq.Compiler.BytecodeAnalysis.ExceptionHandler eh = i.nextEH();
2284 jq_Class k = eh.getExceptionType();
2285 if (k == PrimordialClassLoader.getJavaLangArrayIndexOutOfBoundsException() ||
2286 k == PrimordialClassLoader.getJavaLangIndexOutOfBoundsException() ||
2287 k == PrimordialClassLoader.getJavaLangRuntimeException() ||
2288 k == PrimordialClassLoader.getJavaLangException() ||
2289 k == PrimordialClassLoader.getJavaLangThrowable() ||
2290 k == null) {
2291 mergeStateWith(eh);
2292 break;
2293 }
2294 }
2295 }
2296 void mergeStateWithObjArrayStoreExHandler(boolean cfgEdgeToExit) {
2297 joeq.Compiler.BytecodeAnalysis.ExceptionHandlerIterator i =
2298 bc_bb.getExceptionHandlers();
2299 while (i.hasNext()) {
2300 joeq.Compiler.BytecodeAnalysis.ExceptionHandler eh = i.nextEH();
2301 jq_Class k = eh.getExceptionType();
2302 if (k == PrimordialClassLoader.getJavaLangArrayStoreException() ||
2303 k == PrimordialClassLoader.getJavaLangRuntimeException() ||
2304 k == PrimordialClassLoader.getJavaLangException() ||
2305 k == PrimordialClassLoader.getJavaLangThrowable() ||
2306 k == null) {
2307 mergeStateWith(eh);
2308 break;
2309 }
2310 }
2311 }
2312
2313 RegisterOperand makeGuardReg() {
2314 return RegisterFactory.makeGuardReg();
2315 }
2316
2317 int getLocalNumber(Register r, jq_Type t) {
2318 return r.getNumber();
2319 }
2320
2321 static class DummyOperand implements Operand {
2322 private DummyOperand() {}
2323 static final DummyOperand DUMMY = new DummyOperand();
2324 public Quad getQuad() { throw new InternalError(); }
2325 public void attachToQuad(Quad q) { throw new InternalError(); }
2326 public Operand copy() { return DUMMY; }
2327 public boolean isSimilar(Operand that) { return that == DUMMY; }
2328 public String toString() { return "<dummy>"; }
2329 }
2330
2331 AbstractState allocateEmptyState() {
2332
2333 AbstractState s = new AbstractState(method.getMaxStack()+1, method.getMaxLocals());
2334 return s;
2335 }
2336
2337 AbstractState allocateInitialState() {
2338
2339 AbstractState s = new AbstractState(method.getMaxStack()+1, method.getMaxLocals());
2340 jq_Type[] paramTypes = method.getParamTypes();
2341 for (int i=0, j=-1; i<paramTypes.length; ++i) {
2342 jq_Type paramType = paramTypes[i];
2343 ++j;
2344 s.locals[j] = this.makeLocal(j, paramType);
2345 if (paramType.getReferenceSize() == 8) {
2346 s.locals[++j] = DummyOperand.DUMMY;
2347 }
2348 }
2349 return s;
2350 }
2351
2352 /*** Class used to store the abstract state of the bytecode-to-quad converter. */
2353 public class AbstractState {
2354
2355 private int stackptr;
2356 private Operand[] stack;
2357 private Operand[] locals;
2358
2359 private AbstractState(int nstack, int nlocals) {
2360 this.stack = new Operand[nstack]; this.locals = new Operand[nlocals];
2361 }
2362
2363 AbstractState copy() {
2364 AbstractState that = new AbstractState(this.stack.length, this.locals.length);
2365 System.arraycopy(this.stack, 0, that.stack, 0, this.stackptr);
2366 System.arraycopy(this.locals, 0, that.locals, 0, this.locals.length);
2367 that.stackptr = this.stackptr;
2368 return that;
2369 }
2370
2371 AbstractState copyFull() {
2372 AbstractState that = new AbstractState(this.stack.length, this.locals.length);
2373 for (int i=0; i<stackptr; ++i) {
2374 that.stack[i] = this.stack[i].copy();
2375 }
2376 for (int i=0; i<this.locals.length; ++i) {
2377 if (this.locals[i] != null)
2378 that.locals[i] = this.locals[i].copy();
2379 }
2380 that.stackptr = this.stackptr;
2381 return that;
2382 }
2383
2384 AbstractState copyAfterJSR() {
2385 AbstractState that = new AbstractState(this.stack.length, this.locals.length);
2386 for (int i=0; i<this.locals.length; ++i) {
2387 if (this.locals[i] != null)
2388 that.locals[i] = this.locals[i].copy();
2389 }
2390 return that;
2391 }
2392
2393 AbstractState copyExceptionHandler(jq_Class exType, RegisterFactory rf) {
2394 if (exType == null) exType = PrimordialClassLoader.getJavaLangThrowable();
2395 AbstractState that = new AbstractState(this.stack.length, this.locals.length);
2396 that.stackptr = 1;
2397 RegisterOperand ex = new RegisterOperand(rf.getOrCreateStack(0, exType), exType);
2398 that.stack[0] = ex;
2399 for (int i=0; i<this.locals.length; ++i) {
2400 if (this.locals[i] != null)
2401 that.locals[i] = this.locals[i].copy();
2402 }
2403 return that;
2404 }
2405
2406 void overwriteWith(AbstractState that) {
2407 Assert._assert(this.stack.length == that.stack.length);
2408 Assert._assert(this.locals.length == that.locals.length);
2409 System.arraycopy(that.stack, 0, this.stack, 0, that.stackptr);
2410 System.arraycopy(that.locals, 0, this.locals, 0, that.locals.length);
2411 this.stackptr = that.stackptr;
2412 }
2413
2414 void rebuildStack() {
2415 for (int i = 0; i < stackptr; ++i) {
2416 if (TRACE) System.out.println("Rebuilding stack: "+stack[i]);
2417 stack[i] = stack[i].copy();
2418 }
2419 }
2420
2421 void mergeAfterJSR(boolean[] changedLocals, AbstractState that) {
2422 for (int j=0; j<this.locals.length; ++j) {
2423 if (!changedLocals[j]) continue;
2424 if (TRACE) System.out.println("local "+j+" changed in jsr to "+that.locals[j]);
2425 if (that.locals[j] == null) this.locals[j] = null;
2426 else this.locals[j] = that.locals[j].copy();
2427 }
2428 this.stackptr = that.stackptr;
2429 for (int i=0; i<stackptr; ++i) {
2430 this.stack[i] = that.stack[i].copy();
2431 }
2432 }
2433 boolean merge(AbstractState that, RegisterFactory rf) {
2434 if (this.stackptr != that.stackptr) throw new VerifyError(this.stackptr+" != "+that.stackptr);
2435 Assert._assert(this.locals.length == that.locals.length);
2436 boolean change = false;
2437 for (int i=0; i<this.stackptr; ++i) {
2438 Operand o = meet(this.stack[i], that.stack[i], true, i);
2439 if (o != this.stack[i] && (o == null || !o.isSimilar(this.stack[i]))) change = true;
2440 this.stack[i] = o;
2441 }
2442 for (int i=0; i<this.locals.length; ++i) {
2443 Operand o = meet(this.locals[i], that.locals[i], false, i);
2444 if (o != this.locals[i] && (o == null || !o.isSimilar(this.locals[i]))) change = true;
2445 this.locals[i] = o;
2446 }
2447 return change;
2448 }
2449
2450 boolean mergeExceptionHandler(AbstractState that, jq_Class exType, RegisterFactory rf) {
2451 if (exType == null) exType = PrimordialClassLoader.getJavaLangThrowable();
2452 Assert._assert(this.locals.length == that.locals.length);
2453 Assert._assert(this.stackptr == 1);
2454 boolean change = false;
2455 RegisterOperand ex = new RegisterOperand(rf.getOrCreateStack(0, exType), exType);
2456 Operand o = meet(this.stack[0], ex, true, 0);
2457 if (o != this.stack[0] && (o == null || !o.isSimilar(this.stack[0]))) change = true;
2458 this.stack[0] = o;
2459 for (int i=0; i<this.locals.length; ++i) {
2460 o = meet(this.locals[i], that.locals[i], false, i);
2461 if (o != this.locals[i] && (o == null || !o.isSimilar(this.locals[i]))) change = true;
2462 this.locals[i] = o;
2463 }
2464 return change;
2465 }
2466
2467 Operand meet(Operand op1, Operand op2, boolean stack, int index) {
2468 if (TRACE) System.out.println("Meeting "+op1+" with "+op2+", "+(stack?"S":"L")+index);
2469 if (op1 == op2) {
2470
2471 return op1;
2472 }
2473 if ((op1 == null) || (op2 == null)) {
2474
2475 return null;
2476 }
2477 if (Operand.Util.isConstant(op1)) {
2478 if (op1.isSimilar(op2)) {
2479
2480 return op1;
2481 }
2482 if (op2 instanceof DummyOperand) {
2483 return null;
2484 }
2485 jq_Type type = state.findCommonSuperclass(getTypeOf(op1), getTypeOf(op2));
2486 if (type != null) {
2487
2488 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, type):rf.getOrCreateLocal(index, type), type);
2489 return res;
2490 } else {
2491
2492 return null;
2493 }
2494 }
2495 if (op1 instanceof RegisterOperand) {
2496 if (op2 instanceof DummyOperand) {
2497
2498 return null;
2499 }
2500 RegisterOperand rop1 = (RegisterOperand)op1;
2501 jq_Type t1 = rop1.getType();
2502 if (t1 == jq_ReturnAddressType.INSTANCE) {
2503
2504 if (op2 instanceof RegisterOperand &&
2505 ((RegisterOperand)op2).getType() == jq_ReturnAddressType.INSTANCE) {
2506 return op1;
2507 }
2508 return null;
2509 }
2510 if (op2 instanceof RegisterOperand) {
2511
2512 RegisterOperand rop2 = (RegisterOperand)op2;
2513 jq_Type t2 = rop2.getType();
2514
2515 if (t1 == t2) {
2516
2517 if (rop1.hasMoreConservativeFlags(rop2)) {
2518
2519 if ((rop1.scratchObject == null) ||
2520 ((Operand)rop1.scratchObject).isSimilar((Operand)rop2.scratchObject)) {
2521
2522 return rop1;
2523 }
2524
2525 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2526 res.setFlags(rop1.getFlags());
2527 return res;
2528 }
2529
2530 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2531 if ((rop1.scratchObject == null) ||
2532 ((Operand)rop1.scratchObject).isSimilar((Operand)rop2.scratchObject)) {
2533
2534 res.scratchObject = rop1.scratchObject;
2535 }
2536 res.setFlags(rop1.getFlags());
2537 res.meetFlags(rop2.getFlags());
2538 return res;
2539 }
2540 if (t2 == jq_ReturnAddressType.INSTANCE) {
2541
2542 return null;
2543 }
2544 if (state.isSubtype(t2, t1) == YES) {
2545
2546 if (!rop1.isExactType() && rop1.hasMoreConservativeFlags(rop2)) {
2547
2548 if ((rop1.scratchObject == null) ||
2549 ((Operand)rop1.scratchObject).isSimilar((Operand)rop2.scratchObject)) {
2550
2551 return rop1;
2552 }
2553
2554 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2555 res.setFlags(rop1.getFlags());
2556 return res;
2557 }
2558
2559 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2560 if ((rop1.scratchObject == null) ||
2561 ((Operand)rop1.scratchObject).isSimilar((Operand)rop2.scratchObject)) {
2562
2563 res.scratchObject = rop1.scratchObject;
2564 }
2565 res.setFlags(rop1.getFlags());
2566 res.meetFlags(rop2.getFlags());
2567 res.clearExactType();
2568 return res;
2569 }
2570 if ((t2 = state.findCommonSuperclass(t1, t2)) != null) {
2571
2572 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t2):rf.getOrCreateLocal(index, t2), t2);
2573 if (rop1.scratchObject != null) {
2574 if (((Operand)rop1.scratchObject).isSimilar((Operand)rop2.scratchObject)) {
2575
2576 res.scratchObject = rop1.scratchObject;
2577 }
2578 }
2579 res.setFlags(rop1.getFlags());
2580 res.meetFlags(rop2.getFlags());
2581 res.clearExactType();
2582 return res;
2583 }
2584
2585 return null;
2586 }
2587
2588 jq_Type t2 = getTypeOf(op2);
2589 if (t1 == t2) {
2590
2591 if ((rop1.scratchObject == null) || (t2 != jq_Reference.jq_NullType.NULL_TYPE)) {
2592
2593 return rop1;
2594 }
2595
2596 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2597 res.setFlags(rop1.getFlags());
2598 return res;
2599 }
2600 Assert._assert(t2 != jq_ReturnAddressType.INSTANCE);
2601 if (state.isSubtype(t2, t1) == YES) {
2602
2603 if (!rop1.isExactType()) {
2604 if ((rop1.scratchObject == null) || (t2 != jq_Reference.jq_NullType.NULL_TYPE)) {
2605
2606 return rop1;
2607 }
2608
2609 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2610 res.setFlags(rop1.getFlags());
2611 return res;
2612 }
2613 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t1):rf.getOrCreateLocal(index, t1), t1);
2614 if (t2 != jq_Reference.jq_NullType.NULL_TYPE) {
2615
2616 res.scratchObject = rop1.scratchObject;
2617 }
2618 res.setFlags(rop1.getFlags());
2619 res.clearExactType();
2620 return res;
2621 }
2622 if ((t2 = state.findCommonSuperclass(t1, t2)) != null) {
2623
2624 RegisterOperand res = new RegisterOperand(stack?rf.getOrCreateStack(index, t2):rf.getOrCreateLocal(index, t2), t2);
2625 if (t2 != jq_Reference.jq_NullType.NULL_TYPE) {
2626
2627 res.scratchObject = rop1.scratchObject;
2628 }
2629 res.setFlags(rop1.getFlags());
2630 res.clearExactType();
2631 return res;
2632 }
2633
2634 return null;
2635 }
2636
2637 if (op1.isSimilar(op2)) {
2638 return op1;
2639 } else {
2640 return null;
2641 }
2642 }
2643
2644 int getStackSize() { return this.stackptr; }
2645
2646 void push_I(Operand op) { Assert._assert(getTypeOf(op).isIntLike()); push(op); }
2647 void push_F(Operand op) { Assert._assert(getTypeOf(op) == jq_Primitive.FLOAT); push(op); }
2648 void push_L(Operand op) { Assert._assert(getTypeOf(op) == jq_Primitive.LONG); push(op); pushDummy(); }
2649 void push_D(Operand op) { Assert._assert(getTypeOf(op) == jq_Primitive.DOUBLE); push(op); pushDummy(); }
2650 void push_A(Operand op) { Assert._assert(getTypeOf(op).isReferenceType() && !getTypeOf(op).isAddressType()); push(op); }
2651 void push_P(Operand op) { Assert._assert(getTypeOf(op).isAddressType()); push(op); }
2652 void push(Operand op, jq_Type t) {
2653 Assert._assert(state.isSubtype(getTypeOf(op), t) == YES);
2654 push(op); if (t.getReferenceSize() == 8) pushDummy();
2655 }
2656 void pushDummy() { push(DummyOperand.DUMMY); }
2657 void push(Operand op) {
2658 if (TRACE) System.out.println("Pushing "+op+" on stack "+(this.stackptr));
2659 this.stack[this.stackptr++] = op;
2660 }
2661
2662 Operand pop_I() { Operand op = pop(); Assert._assert(getTypeOf(op).isIntLike()); return op; }
2663 Operand pop_F() { Operand op = pop(); Assert._assert(getTypeOf(op) == jq_Primitive.FLOAT); return op; }
2664 Operand pop_L() { popDummy(); Operand op = pop(); Assert._assert(getTypeOf(op) == jq_Primitive.LONG); return op; }
2665 Operand pop_D() { popDummy(); Operand op = pop(); Assert._assert(getTypeOf(op) == jq_Primitive.DOUBLE); return op; }
2666 Operand pop_A() { Operand op = pop(); Assert._assert(getTypeOf(op).isReferenceType() && !getTypeOf(op).isAddressType()); return op; }
2667 Operand pop_P() {
2668 Operand op = pop();
2669 if (op instanceof AConstOperand) {
2670 op = new PConstOperand(null);
2671 }
2672 Assert._assert(getTypeOf(op).isAddressType() ||
2673 state.isSubtype(getTypeOf(op), Address._class) != NO);
2674 return op;
2675 }
2676 void popDummy() { Operand op = pop(); Assert._assert(op == DummyOperand.DUMMY); }
2677 Operand pop(jq_Type t) {
2678 if (t.getReferenceSize() == 8) popDummy();
2679 Operand op = pop();
2680 if (t.isAddressType()) {
2681 if (op instanceof AConstOperand) {
2682 op = new PConstOperand(null);
2683 }
2684 jq_Type t2 = getTypeOf(op);
2685 Assert._assert(t2 == jq_Reference.jq_NullType.NULL_TYPE ||
2686 t2.isAddressType() ||
2687 state.isSubtype(t2, Address._class) != NO);
2688 }
2689
2690 return op;
2691 }
2692 Operand pop() {
2693 if (TRACE) System.out.println("Popping "+this.stack[this.stackptr-1]+" from stack "+(this.stackptr-1));
2694 return this.stack[--this.stackptr];
2695 }
2696
2697 Operand peekStack(int i) { return this.stack[this.stackptr-i-1]; }
2698 void pokeStack(int i, Operand op) { this.stack[this.stackptr-i-1] = op; }
2699 void clearStack() { this.stackptr = 0; }
2700
2701 Operand getLocal_I(int i) { Operand op = getLocal(i); Assert._assert(getTypeOf(op).isIntLike()); return op; }
2702 Operand getLocal_F(int i) { Operand op = getLocal(i); Assert._assert(getTypeOf(op) == jq_Primitive.FLOAT); return op; }
2703 Operand getLocal_L(int i) {
2704 Operand op = getLocal(i);
2705 Assert._assert(getTypeOf(op) == jq_Primitive.LONG);
2706 Assert._assert(getLocal(i+1) == DummyOperand.DUMMY);
2707 return op;
2708 }
2709 Operand getLocal_D(int i) {
2710 Operand op = getLocal(i);
2711 Assert._assert(getTypeOf(op) == jq_Primitive.DOUBLE);
2712 Assert._assert(getLocal(i+1) == DummyOperand.DUMMY);
2713 return op;
2714 }
2715 Operand getLocal_A(int i) {
2716 Operand op = getLocal(i);
2717 Assert._assert(getTypeOf(op).isReferenceType());
2718 Assert._assert(!getTypeOf(op).isAddressType());
2719 return op;
2720 }
2721 Operand getLocal(int i) {
2722 return this.locals[i].copy();
2723 }
2724 void setLocal(int i, Operand op) {
2725 this.locals[i] = op;
2726 }
2727 void setLocalDual(int i, Operand op) {
2728 this.locals[i] = op; this.locals[i+1] = DummyOperand.DUMMY;
2729 }
2730 void dumpState() {
2731 System.out.print("Locals:");
2732 for (int i=0; i<this.locals.length; ++i) {
2733 if (this.locals[i] != null)
2734 System.out.print(" L"+i+":"+this.locals[i]);
2735 }
2736 System.out.print("\nStack: ");
2737 for (int i=0; i<this.stackptr; ++i) {
2738 System.out.print(" S"+i+":"+this.stack[i]);
2739 }
2740 System.out.println();
2741 }
2742 }
2743
2744 public static class jq_ReturnAddressType extends jq_Reference {
2745 public static final jq_ReturnAddressType INSTANCE = new jq_ReturnAddressType();
2746 public static jq_ReturnAddressType create(BasicBlock bb) {
2747 return new jq_ReturnAddressType(bb);
2748 }
2749 private BasicBlock returnTarget;
2750 private jq_ReturnAddressType() { super(Utf8.get("L&ReturnAddress;"), PrimordialClassLoader.loader); }
2751 private jq_ReturnAddressType(BasicBlock returnTarget) {
2752 super(Utf8.get("L&ReturnAddress;"), PrimordialClassLoader.loader);
2753 this.returnTarget = returnTarget;
2754 }
2755 public boolean isAddressType() { return false; }
2756 public String getJDKName() { return desc.toString(); }
2757 public String getJDKDesc() { return getJDKName(); }
2758 public jq_Class[] getInterfaces() { Assert.UNREACHABLE(); return null; }
2759 public jq_Class getInterface(Utf8 desc) { Assert.UNREACHABLE(); return null; }
2760 public boolean implementsInterface(jq_Class k) { Assert.UNREACHABLE(); return false; }
2761 public jq_InstanceMethod getVirtualMethod(jq_NameAndDesc nd) { Assert.UNREACHABLE(); return null; }
2762 public String getName() { return "<retaddr>"; }
2763 public String shortName() { return "<retaddr>"; }
2764 public boolean isClassType() { Assert.UNREACHABLE(); return false; }
2765 public boolean isArrayType() { Assert.UNREACHABLE(); return false; }
2766 public boolean isFinal() { Assert.UNREACHABLE(); return false; }
2767 public jq_Reference getDirectPrimarySupertype() { Assert.UNREACHABLE(); return null; }
2768 public int getDepth() { Assert.UNREACHABLE(); return 0; }
2769 public void load() { Assert.UNREACHABLE(); }
2770 public void verify() { Assert.UNREACHABLE(); }
2771 public void prepare() { Assert.UNREACHABLE(); }
2772 public void sf_initialize() { Assert.UNREACHABLE(); }
2773 public void compile() { Assert.UNREACHABLE(); }
2774 public void cls_initialize() { Assert.UNREACHABLE(); }
2775 public String toString() { return "<retaddr> (target="+returnTarget+")"; }
2776 public boolean equals(Object rat) {
2777 if (!(rat instanceof jq_ReturnAddressType)) return false;
2778 BasicBlock rt = ((jq_ReturnAddressType)rat).returnTarget;
2779 if (rt == null)
2780 return returnTarget == null;
2781 if (returnTarget == null)
2782 return false;
2783 return ((jq_ReturnAddressType)rat).returnTarget.equals(this.returnTarget);
2784 }
2785 public int hashCode() {
2786 if (returnTarget == null) return 0;
2787 return returnTarget.hashCode();
2788 }
2789 }
2790 static interface UnsafeHelper {
2791 public boolean isUnsafe(jq_Method m);
2792 public boolean endsBB(jq_Method m);
2793 public boolean handleMethod(BytecodeToQuad b2q, ControlFlowGraph quad_cfg, BytecodeToQuad.AbstractState current_state, jq_Method m, Operator.Invoke oper);
2794 }
2795
2796 private static UnsafeHelper _unsafe;
2797 static {
2798
2799 _unsafe = null;
2800 boolean nullVM = jq.nullVM;
2801 if (!nullVM) {
2802 _unsafe = attemptDelegate("joeq.Compiler.Quad.B2QUnsafeHandler");
2803 }
2804 if (_unsafe == null) {
2805 _unsafe = new joeq.Compiler.Quad.B2QUnsafeIgnorer();
2806 }
2807 }
2808
2809 private static UnsafeHelper attemptDelegate(String s) {
2810
2811 try {
2812 Class c = Class.forName(s);
2813 return (UnsafeHelper)c.newInstance();
2814 } catch (java.lang.ClassNotFoundException x) {
2815
2816 } catch (java.lang.InstantiationException x) {
2817
2818 } catch (java.lang.IllegalAccessException x) {
2819
2820 }
2821 return null;
2822 }
2823 }