comparison agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 package sun.jvm.hotspot.oops;
26
27 import java.io.*;
28 import java.util.*;
29 import sun.jvm.hotspot.interpreter.*;
30 import sun.jvm.hotspot.runtime.*;
31 import sun.jvm.hotspot.utilities.*;
32
33 /** Minimal port of the VM's oop map generator for interpreted frames */
34
35 public class GenerateOopMap {
36 interface JumpClosure {
37 public void process(GenerateOopMap c, int bcpDelta, int[] data);
38 }
39
40 // Used for debugging this code
41 private static final boolean DEBUG = false;
42
43 // These two should be removed. But requires som code to be cleaned up
44 private static final int MAXARGSIZE = 256; // This should be enough
45 private static final int MAX_LOCAL_VARS = 65536; // 16-bit entry
46 private static final boolean TraceMonitorMismatch = true;
47 private static final boolean TraceOopMapRewrites = true;
48
49 // Commonly used constants
50 static CellTypeState[] epsilonCTS = { CellTypeState.bottom };
51 static CellTypeState refCTS = CellTypeState.ref;
52 static CellTypeState valCTS = CellTypeState.value;
53 static CellTypeState[] vCTS = { CellTypeState.value, CellTypeState.bottom };
54 static CellTypeState[] rCTS = { CellTypeState.ref, CellTypeState.bottom };
55 static CellTypeState[] rrCTS = { CellTypeState.ref, CellTypeState.ref, CellTypeState.bottom };
56 static CellTypeState[] vrCTS = { CellTypeState.value, CellTypeState.ref, CellTypeState.bottom };
57 static CellTypeState[] vvCTS = { CellTypeState.value, CellTypeState.value, CellTypeState.bottom };
58 static CellTypeState[] rvrCTS = { CellTypeState.ref, CellTypeState.value, CellTypeState.ref, CellTypeState.bottom };
59 static CellTypeState[] vvrCTS = { CellTypeState.value, CellTypeState.value, CellTypeState.ref, CellTypeState.bottom };
60 static CellTypeState[] vvvCTS = { CellTypeState.value, CellTypeState.value, CellTypeState.value, CellTypeState.bottom };
61 static CellTypeState[] vvvrCTS = { CellTypeState.value, CellTypeState.value, CellTypeState.value, CellTypeState.ref, CellTypeState.bottom };
62 static CellTypeState[] vvvvCTS = { CellTypeState.value, CellTypeState.value, CellTypeState.value, CellTypeState.value, CellTypeState.bottom };
63
64 /** Specialization of SignatureIterator - compute the effects of a call */
65 static class ComputeCallStack extends SignatureIterator {
66 CellTypeStateList _effect;
67 int _idx;
68
69 void set(CellTypeState state) { _effect.get(_idx++).set(state); }
70 int length() { return _idx; };
71
72 public void doBool () { set(CellTypeState.value); }
73 public void doChar () { set(CellTypeState.value); }
74 public void doFloat () { set(CellTypeState.value); }
75 public void doByte () { set(CellTypeState.value); }
76 public void doShort () { set(CellTypeState.value); }
77 public void doInt () { set(CellTypeState.value); }
78 public void doVoid () { set(CellTypeState.bottom);}
79 public void doObject(int begin, int end) { set(CellTypeState.ref); }
80 public void doArray (int begin, int end) { set(CellTypeState.ref); }
81
82 public void doDouble() { set(CellTypeState.value);
83 set(CellTypeState.value); }
84 public void doLong () { set(CellTypeState.value);
85 set(CellTypeState.value); }
86
87 ComputeCallStack(Symbol signature) {
88 super(signature);
89 }
90
91 // Compute methods
92 int computeForParameters(boolean is_static, CellTypeStateList effect) {
93 _idx = 0;
94 _effect = effect;
95
96 if (!is_static) {
97 effect.get(_idx++).set(CellTypeState.ref);
98 }
99
100 iterateParameters();
101
102 return length();
103 };
104
105 int computeForReturntype(CellTypeStateList effect) {
106 _idx = 0;
107 _effect = effect;
108 iterateReturntype();
109 set(CellTypeState.bottom); // Always terminate with a bottom state, so ppush works
110
111 return length();
112 }
113 }
114
115 /** Specialization of SignatureIterator - in order to set up first stack frame */
116 static class ComputeEntryStack extends SignatureIterator {
117 CellTypeStateList _effect;
118 int _idx;
119
120 void set(CellTypeState state) { _effect.get(_idx++).set(state); }
121 int length() { return _idx; };
122
123 public void doBool () { set(CellTypeState.value); }
124 public void doChar () { set(CellTypeState.value); }
125 public void doFloat () { set(CellTypeState.value); }
126 public void doByte () { set(CellTypeState.value); }
127 public void doShort () { set(CellTypeState.value); }
128 public void doInt () { set(CellTypeState.value); }
129 public void doVoid () { set(CellTypeState.bottom);}
130 public void doObject(int begin, int end) { set(CellTypeState.makeSlotRef(_idx)); }
131 public void doArray (int begin, int end) { set(CellTypeState.makeSlotRef(_idx)); }
132
133 public void doDouble() { set(CellTypeState.value);
134 set(CellTypeState.value); }
135 public void doLong () { set(CellTypeState.value);
136 set(CellTypeState.value); }
137
138 ComputeEntryStack(Symbol signature) {
139 super(signature);
140 }
141
142 // Compute methods
143 int computeForParameters(boolean is_static, CellTypeStateList effect) {
144 _idx = 0;
145 _effect = effect;
146
147 if (!is_static) {
148 effect.get(_idx++).set(CellTypeState.makeSlotRef(0));
149 }
150
151 iterateParameters();
152
153 return length();
154 };
155
156 int computeForReturntype(CellTypeStateList effect) {
157 _idx = 0;
158 _effect = effect;
159 iterateReturntype();
160 set(CellTypeState.bottom); // Always terminate with a bottom state, so ppush works
161
162 return length();
163 }
164 }
165
166 /** Contains maping between jsr targets and there return addresses.
167 One-to-many mapping. */
168 static class RetTableEntry {
169 private static int _init_nof_jsrs; // Default size of jsrs list
170 private int _target_bci; // Target PC address of jump (bytecode index)
171 private List/*<int>*/ _jsrs; // List of return addresses (bytecode index)
172 private RetTableEntry _next; // Link to next entry
173
174 RetTableEntry(int target, RetTableEntry next) {
175 _target_bci = target;
176 _jsrs = new ArrayList(_init_nof_jsrs);
177 _next = next;
178 }
179
180 // Query
181 int targetBci() { return _target_bci; }
182 int nofJsrs() { return _jsrs.size(); }
183 int jsrs(int i) { return ((Integer) _jsrs.get(i)).intValue(); }
184
185 // Update entry
186 void addJsr (int return_bci) { _jsrs.add(new Integer(return_bci)); }
187 void addDelta(int bci, int delta) {
188 if (_target_bci > bci) {
189 _target_bci += delta;
190 }
191
192 for (int k = 0; k < nofJsrs(); k++) {
193 int jsr = jsrs(k);
194 if (jsr > bci) {
195 _jsrs.set(k, new Integer(jsr+delta));
196 }
197 }
198 }
199 RetTableEntry next() { return _next; }
200 }
201
202 static class RetTable {
203 private RetTableEntry _first;
204 private static int _init_nof_entries;
205
206 private void addJsr(int return_bci, int target_bci) {
207 RetTableEntry entry = _first;
208
209 // Scan table for entry
210 for (;(entry != null) && (entry.targetBci() != target_bci); entry = entry.next());
211
212 if (entry == null) {
213 // Allocate new entry and put in list
214 entry = new RetTableEntry(target_bci, _first);
215 _first = entry;
216 }
217
218 // Now "entry" is set. Make sure that the entry is initialized
219 // and has room for the new jsr.
220 entry.addJsr(return_bci);
221 }
222
223 RetTable() {}
224 void computeRetTable(Method method) {
225 BytecodeStream i = new BytecodeStream(method);
226 int bytecode;
227
228 while( (bytecode = i.next()) >= 0) {
229 switch (bytecode) {
230 case Bytecodes._jsr:
231 addJsr(i.nextBCI(), i.dest());
232 break;
233 case Bytecodes._jsr_w:
234 addJsr(i.nextBCI(), i.dest_w());
235 break;
236 }
237 }
238 }
239 void updateRetTable(int bci, int delta) {
240 RetTableEntry cur = _first;
241 while(cur != null) {
242 cur.addDelta(bci, delta);
243 cur = cur.next();
244 }
245 }
246 RetTableEntry findJsrsForTarget(int targBci) {
247 RetTableEntry cur = _first;
248
249 while(cur != null) {
250 if (Assert.ASSERTS_ENABLED) {
251 Assert.that(cur.targetBci() != -1, "sanity check");
252 }
253 if (cur.targetBci() == targBci) {
254 return cur;
255 }
256 cur = cur.next();
257 }
258 throw new RuntimeException("Should not reach here");
259 }
260 }
261
262 static class BasicBlock {
263 private boolean _changed; // Reached a fixpoint or not
264 static final int _dead_basic_block = -2;
265 // Alive but not yet reached by analysis
266 static final int _unreached = -1;
267 // >=0: Alive and has a merged state
268
269 int _bci; // Start of basic block
270 int _end_bci; // Bci of last instruction in basicblock
271 int _max_locals; // Determines split between vars and stack
272 int _max_stack; // Determines split between stack and monitors
273 CellTypeStateList _state; // State (vars, stack) at entry.
274 int _stack_top; // -1 indicates bottom stack value.
275 int _monitor_top; // -1 indicates bottom monitor stack value.
276
277 CellTypeStateList vars() { return _state; }
278 CellTypeStateList stack() { return _state.subList(_max_locals, _state.size()); }
279
280 boolean changed() { return _changed; }
281 void setChanged(boolean s) { _changed = s; }
282
283 // Analysis has reached this basicblock
284 boolean isReachable() { return _stack_top >= 0; }
285
286 // All basicblocks that are unreachable are going to have a _stack_top == _dead_basic_block.
287 // This info. is setup in a pre-parse before the real abstract interpretation starts.
288 boolean isDead() { return _stack_top == _dead_basic_block; }
289 boolean isAlive() { return _stack_top != _dead_basic_block; }
290 void markAsAlive() {
291 if (Assert.ASSERTS_ENABLED) {
292 Assert.that(isDead(), "must be dead");
293 _stack_top = _unreached;
294 }
295 }
296 }
297
298 //----------------------------------------------------------------------
299 // Protected routines for GenerateOopMap
300 //
301
302 // _monitor_top is set to this constant to indicate that a monitor matching
303 // problem was encountered prior to this point in control flow.
304 protected static final int bad_monitors = -1;
305
306 // Main variables
307 Method _method; // The method we are examining
308 RetTable _rt; // Contains the return address mappings
309 int _max_locals; // Cached value of no. of locals
310 int _max_stack; // Cached value of max. stack depth
311 int _max_monitors; // Cached value of max. monitor stack depth
312 boolean _has_exceptions; // True, if exceptions exist for method
313 boolean _got_error; // True, if an error occured during interpretation.
314 String _error_msg; // Error message. Set if _got_error is true.
315 // bool _did_rewriting; // was bytecodes rewritten
316 // bool _did_relocation; // was relocation neccessary
317 boolean _monitor_safe; // The monitors in this method have been determined
318 // to be safe.
319
320 // Working Cell type state
321 int _state_len; // Size of states
322 CellTypeStateList _state; // list of states
323 char[] _state_vec_buf; // Buffer used to print a readable version of a state
324 int _stack_top;
325 int _monitor_top;
326
327 // Timing and statistics
328 // static elapsedTimer _total_oopmap_time; // Holds cumulative oopmap generation time
329 // static long _total_byte_count; // Holds cumulative number of bytes inspected
330
331 // Monitor query logic
332 int _report_for_exit_bci;
333 int _matching_enter_bci;
334
335 // Cell type methods
336 void initState() {
337 _state_len = _max_locals + _max_stack + _max_monitors;
338 _state = new CellTypeStateList(_state_len);
339 _state_vec_buf = new char[Math.max(_max_locals, Math.max(_max_stack, Math.max(_max_monitors, 1)))];
340 }
341 void makeContextUninitialized () {
342 CellTypeStateList vs = vars();
343
344 for (int i = 0; i < _max_locals; i++)
345 vs.get(i).set(CellTypeState.uninit);
346
347 _stack_top = 0;
348 _monitor_top = 0;
349 }
350
351 int methodsigToEffect (Symbol signature, boolean isStatic, CellTypeStateList effect) {
352 ComputeEntryStack ces = new ComputeEntryStack(signature);
353 return ces.computeForParameters(isStatic, effect);
354 }
355
356 boolean mergeStateVectors (CellTypeStateList cts, CellTypeStateList bbts) {
357 int i;
358 int len = _max_locals + _stack_top;
359 boolean change = false;
360
361 for (i = len - 1; i >= 0; i--) {
362 CellTypeState v = cts.get(i).merge(bbts.get(i), i);
363 change = change || !v.equal(bbts.get(i));
364 bbts.get(i).set(v);
365 }
366
367 if (_max_monitors > 0 && _monitor_top != bad_monitors) {
368 // If there are no monitors in the program, or there has been
369 // a monitor matching error before this point in the program,
370 // then we do not merge in the monitor state.
371
372 int base = _max_locals + _max_stack;
373 len = base + _monitor_top;
374 for (i = len - 1; i >= base; i--) {
375 CellTypeState v = cts.get(i).merge(bbts.get(i), i);
376
377 // Can we prove that, when there has been a change, it will already
378 // have been detected at this point? That would make this equal
379 // check here unnecessary.
380 change = change || !v.equal(bbts.get(i));
381 bbts.get(i).set(v);
382 }
383 }
384
385 return change;
386 }
387
388 void copyState (CellTypeStateList dst, CellTypeStateList src) {
389 int len = _max_locals + _stack_top;
390 for (int i = 0; i < len; i++) {
391 if (src.get(i).isNonlockReference()) {
392 dst.get(i).set(CellTypeState.makeSlotRef(i));
393 } else {
394 dst.get(i).set(src.get(i));
395 }
396 }
397 if (_max_monitors > 0 && _monitor_top != bad_monitors) {
398 int base = _max_locals + _max_stack;
399 len = base + _monitor_top;
400 for (int i = base; i < len; i++) {
401 dst.get(i).set(src.get(i));
402 }
403 }
404 }
405
406 void mergeStateIntoBB (BasicBlock bb) {
407 if (Assert.ASSERTS_ENABLED) {
408 Assert.that(bb.isAlive(), "merging state into a dead basicblock");
409 }
410
411 if (_stack_top == bb._stack_top) {
412 if (_monitor_top == bb._monitor_top) {
413 if (mergeStateVectors(_state, bb._state)) {
414 bb.setChanged(true);
415 }
416 } else {
417 if (TraceMonitorMismatch) {
418 reportMonitorMismatch("monitor stack height merge conflict");
419 }
420 // When the monitor stacks are not matched, we set _monitor_top to
421 // bad_monitors. This signals that, from here on, the monitor stack cannot
422 // be trusted. In particular, monitorexit bytecodes may throw
423 // exceptions. We mark this block as changed so that the change
424 // propagates properly.
425 bb._monitor_top = bad_monitors;
426 bb.setChanged(true);
427 _monitor_safe = false;
428 }
429 } else if (!bb.isReachable()) {
430 // First time we look at this BB
431 copyState(bb._state, _state);
432 bb._stack_top = _stack_top;
433 bb._monitor_top = _monitor_top;
434 bb.setChanged(true);
435 } else {
436 throw new RuntimeException("stack height conflict: " +
437 _stack_top + " vs. " + bb._stack_top);
438 }
439 }
440
441 void mergeState (int bci, int[] data) {
442 mergeStateIntoBB(getBasicBlockAt(bci));
443 }
444
445 void setVar (int localNo, CellTypeState cts) {
446 if (Assert.ASSERTS_ENABLED) {
447 Assert.that(cts.isReference() || cts.isValue() || cts.isAddress(),
448 "wrong celltypestate");
449 }
450 if (localNo < 0 || localNo > _max_locals) {
451 throw new RuntimeException("variable write error: r" + localNo);
452 }
453 vars().get(localNo).set(cts);
454 }
455
456 CellTypeState getVar (int localNo) {
457 if (Assert.ASSERTS_ENABLED) {
458 Assert.that(localNo < _max_locals + _nof_refval_conflicts, "variable read error");
459 }
460 if (localNo < 0 || localNo > _max_locals) {
461 throw new RuntimeException("variable read error: r" + localNo);
462 }
463 return vars().get(localNo).copy();
464 }
465
466 CellTypeState pop () {
467 if ( _stack_top <= 0) {
468 throw new RuntimeException("stack underflow");
469 }
470 return stack().get(--_stack_top).copy();
471 }
472
473 void push (CellTypeState cts) {
474 if ( _stack_top >= _max_stack) {
475 if (DEBUG) {
476 System.err.println("Method: " + method().getName().asString() + method().getSignature().asString() +
477 " _stack_top: " + _stack_top + " _max_stack: " + _max_stack);
478 }
479 throw new RuntimeException("stack overflow");
480 }
481 stack().get(_stack_top++).set(cts);
482 if (DEBUG) {
483 System.err.println("After push: _stack_top: " + _stack_top +
484 " _max_stack: " + _max_stack +
485 " just pushed: " + cts.toChar());
486 }
487 }
488
489 CellTypeState monitorPop () {
490 if (Assert.ASSERTS_ENABLED) {
491 Assert.that(_monitor_top != bad_monitors, "monitorPop called on error monitor stack");
492 }
493 if (_monitor_top == 0) {
494 // We have detected a pop of an empty monitor stack.
495 _monitor_safe = false;
496 _monitor_top = bad_monitors;
497
498 if (TraceMonitorMismatch) {
499 reportMonitorMismatch("monitor stack underflow");
500 }
501 return CellTypeState.ref; // just to keep the analysis going.
502 }
503 return monitors().get(--_monitor_top).copy();
504 }
505
506 void monitorPush (CellTypeState cts) {
507 if (Assert.ASSERTS_ENABLED) {
508 Assert.that(_monitor_top != bad_monitors, "monitorPush called on error monitor stack");
509 }
510 if (_monitor_top >= _max_monitors) {
511 // Some monitorenter is being executed more than once.
512 // This means that the monitor stack cannot be simulated.
513 _monitor_safe = false;
514 _monitor_top = bad_monitors;
515
516 if (TraceMonitorMismatch) {
517 reportMonitorMismatch("monitor stack overflow");
518 }
519 return;
520 }
521 monitors().get(_monitor_top++).set(cts);
522 }
523
524 CellTypeStateList vars () { return _state; }
525 CellTypeStateList stack () { return _state.subList(_max_locals, _state.size()); }
526 CellTypeStateList monitors() { return _state.subList(_max_locals+_max_stack, _state.size()); }
527
528 void replaceAllCTSMatches (CellTypeState match,
529 CellTypeState replace) {
530 int i;
531 int len = _max_locals + _stack_top;
532 boolean change = false;
533
534 for (i = len - 1; i >= 0; i--) {
535 if (match.equal(_state.get(i))) {
536 _state.get(i).set(replace);
537 }
538 }
539
540 if (_monitor_top > 0) {
541 int base = _max_locals + _max_stack;
542 len = base + _monitor_top;
543 for (i = len - 1; i >= base; i--) {
544 if (match.equal(_state.get(i))) {
545 _state.get(i).set(replace);
546 }
547 }
548 }
549 }
550
551 void printStates (PrintStream tty, CellTypeStateList vector, int num) {
552 for (int i = 0; i < num; i++) {
553 vector.get(i).print(tty);
554 }
555 }
556
557 void printCurrentState (PrintStream tty,
558 BytecodeStream currentBC,
559 boolean detailed) {
560 if (detailed) {
561 tty.print(" " + currentBC.bci() + " vars = ");
562 printStates(tty, vars(), _max_locals);
563 tty.print(" " + Bytecodes.name(currentBC.code()));
564 switch(currentBC.code()) {
565 case Bytecodes._invokevirtual:
566 case Bytecodes._invokespecial:
567 case Bytecodes._invokestatic:
568 case Bytecodes._invokeinterface:
569 // FIXME: print signature of referenced method (need more
570 // accessors in ConstantPool and ConstantPoolCache)
571 int idx = currentBC.getIndexBig();
572 tty.print(" idx " + idx);
573 /*
574 int idx = currentBC.getIndexBig();
575 ConstantPool cp = method().getConstants();
576 int nameAndTypeIdx = cp.name_and_type_ref_index_at(idx);
577 int signatureIdx = cp.signature_ref_index_at(nameAndTypeIdx);
578 symbolOop signature = cp.symbol_at(signatureIdx);
579 tty.print("%s", signature.as_C_string());
580 */
581 }
582 tty.println();
583 tty.print(" stack = ");
584 printStates(tty, stack(), _stack_top);
585 tty.println();
586 if (_monitor_top != bad_monitors) {
587 tty.print(" monitors = ");
588 printStates(tty, monitors(), _monitor_top);
589 } else {
590 tty.print(" [bad monitor stack]");
591 }
592 tty.println();
593 } else {
594 tty.print(" " + currentBC.bci() + " vars = '" +
595 stateVecToString(vars(), _max_locals) + "' ");
596 tty.print(" stack = '" + stateVecToString(stack(), _stack_top) + "' ");
597 if (_monitor_top != bad_monitors) {
598 tty.print(" monitors = '" + stateVecToString(monitors(), _monitor_top) + "' \t" +
599 Bytecodes.name(currentBC.code()));
600 } else {
601 tty.print(" [bad monitor stack]");
602 }
603 switch(currentBC.code()) {
604 case Bytecodes._invokevirtual:
605 case Bytecodes._invokespecial:
606 case Bytecodes._invokestatic:
607 case Bytecodes._invokeinterface:
608 // FIXME: print signature of referenced method (need more
609 // accessors in ConstantPool and ConstantPoolCache)
610 int idx = currentBC.getIndexBig();
611 tty.print(" idx " + idx);
612 /*
613 int idx = currentBC.getIndexBig();
614 constantPoolOop cp = method().constants();
615 int nameAndTypeIdx = cp.name_and_type_ref_index_at(idx);
616 int signatureIdx = cp.signature_ref_index_at(nameAndTypeIdx);
617 symbolOop signature = cp.symbol_at(signatureIdx);
618 tty.print("%s", signature.as_C_string());
619 */
620 }
621 tty.println();
622 }
623 }
624
625 void reportMonitorMismatch (String msg) {
626 if (Assert.ASSERTS_ENABLED) {
627 System.err.print(" Monitor mismatch in method ");
628 method().printValueOn(System.err);
629 System.err.println(": " + msg);
630 }
631 }
632
633 // Basicblock info
634 BasicBlock[] _basic_blocks; // Array of basicblock info
635 int _gc_points;
636 int _bb_count;
637 BitMap _bb_hdr_bits;
638
639 // Basicblocks methods
640 void initializeBB () {
641 _gc_points = 0;
642 _bb_count = 0;
643 _bb_hdr_bits = new BitMap((int) _method.getCodeSize());
644 }
645
646 void markBBHeadersAndCountGCPoints() {
647 initializeBB();
648
649 boolean fellThrough = false; // False to get first BB marked.
650
651 // First mark all exception handlers as start of a basic-block
652 TypeArray excps = method().getExceptionTable();
653 for(int i = 0; i < excps.getLength(); i += 4) {
654 int handler_pc_idx = i+2;
655 markBB(excps.getIntAt(handler_pc_idx), null);
656 }
657
658 // Then iterate through the code
659 BytecodeStream bcs = new BytecodeStream(_method);
660 int bytecode;
661
662 while( (bytecode = bcs.next()) >= 0) {
663 int bci = bcs.bci();
664
665 if (!fellThrough)
666 markBB(bci, null);
667
668 fellThrough = jumpTargetsDo(bcs,
669 new JumpClosure() {
670 public void process(GenerateOopMap c, int bcpDelta, int[] data) {
671 c.markBB(bcpDelta, data);
672 }
673 },
674 null);
675
676 /* We will also mark successors of jsr's as basic block headers. */
677 switch (bytecode) {
678 case Bytecodes._jsr:
679 if (Assert.ASSERTS_ENABLED) {
680 Assert.that(!fellThrough, "should not happen");
681 }
682 markBB(bci + Bytecodes.lengthFor(bytecode), null);
683 break;
684 case Bytecodes._jsr_w:
685 if (Assert.ASSERTS_ENABLED) {
686 Assert.that(!fellThrough, "should not happen");
687 }
688 markBB(bci + Bytecodes.lengthFor(bytecode), null);
689 break;
690 }
691
692 if (possibleGCPoint(bcs))
693 _gc_points++;
694 }
695 }
696
697 boolean isBBHeader (int bci) {
698 return _bb_hdr_bits.at(bci);
699 }
700
701 int gcPoints () {
702 return _gc_points;
703 }
704
705 int bbCount () {
706 return _bb_count;
707 }
708
709 void setBBMarkBit (int bci) {
710 _bb_hdr_bits.atPut(bci, true);
711 }
712
713 void clear_bbmark_bit (int bci) {
714 _bb_hdr_bits.atPut(bci, false);
715 }
716
717 BasicBlock getBasicBlockAt (int bci) {
718 BasicBlock bb = getBasicBlockContaining(bci);
719 if (Assert.ASSERTS_ENABLED) {
720 Assert.that(bb._bci == bci, "should have found BB");
721 }
722 return bb;
723 }
724
725 BasicBlock getBasicBlockContaining (int bci) {
726 BasicBlock[] bbs = _basic_blocks;
727 int lo = 0, hi = _bb_count - 1;
728
729 while (lo <= hi) {
730 int m = (lo + hi) / 2;
731 int mbci = bbs[m]._bci;
732 int nbci;
733
734 if ( m == _bb_count-1) {
735 if (Assert.ASSERTS_ENABLED) {
736 Assert.that( bci >= mbci && bci < method().getCodeSize(), "sanity check failed");
737 }
738 return bbs[m];
739 } else {
740 nbci = bbs[m+1]._bci;
741 }
742
743 if ( mbci <= bci && bci < nbci) {
744 return bbs[m];
745 } else if (mbci < bci) {
746 lo = m + 1;
747 } else {
748 if (Assert.ASSERTS_ENABLED) {
749 Assert.that(mbci > bci, "sanity check");
750 }
751 hi = m - 1;
752 }
753 }
754
755 throw new RuntimeException("should have found BB");
756 }
757
758 void interpBB (BasicBlock bb) {
759 // We do not want to do anything in case the basic-block has not been initialized. This
760 // will happen in the case where there is dead-code hang around in a method.
761 if (Assert.ASSERTS_ENABLED) {
762 Assert.that(bb.isReachable(), "should be reachable or deadcode exist");
763 }
764 restoreState(bb);
765
766 BytecodeStream itr = new BytecodeStream(_method);
767
768 // Set iterator interval to be the current basicblock
769 int lim_bci = nextBBStartPC(bb);
770 itr.setInterval(bb._bci, lim_bci);
771
772 if (DEBUG) {
773 System.err.println("interpBB: method = " + method().getName().asString() +
774 method().getSignature().asString() +
775 ", BCI interval [" + bb._bci + ", " + lim_bci + ")");
776 {
777 System.err.print("Bytecodes:");
778 for (int i = bb._bci; i < lim_bci; i++) {
779 System.err.print(" 0x" + Long.toHexString(method().getBytecodeOrBPAt(i)));
780 }
781 System.err.println();
782 }
783 }
784
785 if (Assert.ASSERTS_ENABLED) {
786 Assert.that(lim_bci != bb._bci, "must be at least one instruction in a basicblock");
787 }
788 itr.next(); // read first instruction
789
790 // Iterates through all bytecodes except the last in a basic block.
791 // We handle the last one special, since there is controlflow change.
792 while(itr.nextBCI() < lim_bci && !_got_error) {
793 if (_has_exceptions || (_monitor_top != 0)) {
794 // We do not need to interpret the results of exceptional
795 // continuation from this instruction when the method has no
796 // exception handlers and the monitor stack is currently
797 // empty.
798 doExceptionEdge(itr);
799 }
800 interp1(itr);
801 itr.next();
802 }
803
804 // Handle last instruction.
805 if (!_got_error) {
806 if (Assert.ASSERTS_ENABLED) {
807 Assert.that(itr.nextBCI() == lim_bci, "must point to end");
808 }
809 if (_has_exceptions || (_monitor_top != 0)) {
810 doExceptionEdge(itr);
811 }
812 interp1(itr);
813
814 boolean fall_through = jumpTargetsDo(itr, new JumpClosure() {
815 public void process(GenerateOopMap c, int bcpDelta, int[] data) {
816 c.mergeState(bcpDelta, data);
817 }
818 }, null);
819 if (_got_error) return;
820
821 if (itr.code() == Bytecodes._ret) {
822 if (Assert.ASSERTS_ENABLED) {
823 Assert.that(!fall_through, "cannot be set if ret instruction");
824 }
825 // Automatically handles 'wide' ret indicies
826 retJumpTargetsDo(itr, new JumpClosure() {
827 public void process(GenerateOopMap c, int bcpDelta, int[] data) {
828 c.mergeState(bcpDelta, data);
829 }
830 }, itr.getIndex(), null);
831 } else if (fall_through) {
832 // Hit end of BB, but the instr. was a fall-through instruction,
833 // so perform transition as if the BB ended in a "jump".
834 if (Assert.ASSERTS_ENABLED) {
835 Assert.that(lim_bci == _basic_blocks[bbIndex(bb) + 1]._bci, "there must be another bb");
836 }
837 mergeStateIntoBB(_basic_blocks[bbIndex(bb) + 1]);
838 }
839 }
840 }
841
842 void restoreState (BasicBlock bb) {
843 for (int i = 0; i < _state_len; i++) {
844 _state.get(i).set(bb._state.get(i));
845 }
846 _stack_top = bb._stack_top;
847 _monitor_top = bb._monitor_top;
848 }
849
850 int nextBBStartPC (BasicBlock bb) {
851 int bbNum = bbIndex(bb) + 1;
852 if (bbNum == _bb_count)
853 return (int) method().getCodeSize();
854
855 return _basic_blocks[bbNum]._bci;
856 }
857
858 void updateBasicBlocks (int bci, int delta) {
859 BitMap bbBits = new BitMap((int) (_method.getCodeSize() + delta));
860 for(int k = 0; k < _bb_count; k++) {
861 if (_basic_blocks[k]._bci > bci) {
862 _basic_blocks[k]._bci += delta;
863 _basic_blocks[k]._end_bci += delta;
864 }
865 bbBits.atPut(_basic_blocks[k]._bci, true);
866 }
867 _bb_hdr_bits = bbBits;
868 }
869
870 void markBB(int bci, int[] data) {
871 if (Assert.ASSERTS_ENABLED) {
872 Assert.that(bci>= 0 && bci < method().getCodeSize(), "index out of bounds");
873 }
874 if (isBBHeader(bci))
875 return;
876
877 // FIXME: remove
878 // if (TraceNewOopMapGeneration) {
879 // tty.print_cr("Basicblock#%d begins at: %d", c._bb_count, bci);
880 // }
881 setBBMarkBit(bci);
882 _bb_count++;
883 }
884
885 // Dead code detection
886 void markReachableCode() {
887 final int[] change = new int[1];
888 change[0] = 1;
889
890 // Mark entry basic block as alive and all exception handlers
891 _basic_blocks[0].markAsAlive();
892 TypeArray excps = method().getExceptionTable();
893 for(int i = 0; i < excps.getLength(); i += 4) {
894 int handler_pc_idx = i+2;
895 BasicBlock bb = getBasicBlockAt(excps.getIntAt(handler_pc_idx));
896 // If block is not already alive (due to multiple exception handlers to same bb), then
897 // make it alive
898 if (bb.isDead())
899 bb.markAsAlive();
900 }
901
902 BytecodeStream bcs = new BytecodeStream(_method);
903
904 // Iterate through all basic blocks until we reach a fixpoint
905 while (change[0] != 0) {
906 change[0] = 0;
907
908 for (int i = 0; i < _bb_count; i++) {
909 BasicBlock bb = _basic_blocks[i];
910 if (bb.isAlive()) {
911 // Position bytecodestream at last bytecode in basicblock
912 bcs.setStart(bb._end_bci);
913 bcs.next();
914 int bytecode = bcs.code();
915 int bci = bcs.bci();
916 if (Assert.ASSERTS_ENABLED) {
917 Assert.that(bci == bb._end_bci, "wrong bci");
918 }
919
920 boolean fell_through = jumpTargetsDo(bcs, new JumpClosure() {
921 public void process(GenerateOopMap c, int bciDelta, int[] change) {
922 c.reachableBasicblock(bciDelta, change);
923 }
924 }, change);
925
926 // We will also mark successors of jsr's as alive.
927 switch (bytecode) {
928 case Bytecodes._jsr:
929 case Bytecodes._jsr_w:
930 if (Assert.ASSERTS_ENABLED) {
931 Assert.that(!fell_through, "should not happen");
932 }
933 reachableBasicblock(bci + Bytecodes.lengthFor(bytecode), change);
934 break;
935 }
936 if (fell_through) {
937 // Mark successor as alive
938 if (_basic_blocks[i+1].isDead()) {
939 _basic_blocks[i+1].markAsAlive();
940 change[0] = 1;
941 }
942 }
943 }
944 }
945 }
946 }
947
948 void reachableBasicblock (int bci, int[] data) {
949 if (Assert.ASSERTS_ENABLED) {
950 Assert.that(bci>= 0 && bci < method().getCodeSize(), "index out of bounds");
951 }
952 BasicBlock bb = getBasicBlockAt(bci);
953 if (bb.isDead()) {
954 bb.markAsAlive();
955 data[0] = 1; // Mark basicblock as changed
956 }
957 }
958
959 // Interpretation methods (primary)
960 void doInterpretation () {
961 // "i" is just for debugging, so we can detect cases where this loop is
962 // iterated more than once.
963 int i = 0;
964 do {
965 // FIXME: remove
966 // if (TraceNewOopMapGeneration) {
967 // tty.print("\n\nIteration #%d of do_interpretation loop, method:\n", i);
968 // method().print_name(tty);
969 // tty.print("\n\n");
970 // }
971 _conflict = false;
972 _monitor_safe = true;
973 // init_state is now called from init_basic_blocks. The length of a
974 // state vector cannot be determined until we have made a pass through
975 // the bytecodes counting the possible monitor entries.
976 if (!_got_error) initBasicBlocks();
977 if (!_got_error) setupMethodEntryState();
978 if (!_got_error) interpAll();
979 if (!_got_error) rewriteRefvalConflicts();
980 i++;
981 } while (_conflict && !_got_error);
982 }
983
984 void initBasicBlocks () {
985 // Note: Could consider reserving only the needed space for each BB's state
986 // (entry stack may not be of maximal height for every basic block).
987 // But cumbersome since we don't know the stack heights yet. (Nor the
988 // monitor stack heights...)
989
990 _basic_blocks = new BasicBlock[_bb_count];
991 for (int i = 0; i < _bb_count; i++) {
992 _basic_blocks[i] = new BasicBlock();
993 }
994
995 // Make a pass through the bytecodes. Count the number of monitorenters.
996 // This can be used an upper bound on the monitor stack depth in programs
997 // which obey stack discipline with their monitor usage. Initialize the
998 // known information about basic blocks.
999 BytecodeStream j = new BytecodeStream(_method);
1000 int bytecode;
1001
1002 int bbNo = 0;
1003 int monitor_count = 0;
1004 int prev_bci = -1;
1005 while( (bytecode = j.next()) >= 0) {
1006 if (j.code() == Bytecodes._monitorenter) {
1007 monitor_count++;
1008 }
1009
1010 int bci = j.bci();
1011 if (isBBHeader(bci)) {
1012 // Initialize the basicblock structure
1013 BasicBlock bb = _basic_blocks[bbNo];
1014 bb._bci = bci;
1015 bb._max_locals = _max_locals;
1016 bb._max_stack = _max_stack;
1017 bb.setChanged(false);
1018 bb._stack_top = BasicBlock._dead_basic_block; // Initialize all basicblocks are dead.
1019 bb._monitor_top = bad_monitors;
1020
1021 if (bbNo > 0) {
1022 _basic_blocks[bbNo - 1]._end_bci = prev_bci;
1023 }
1024
1025 bbNo++;
1026 }
1027 // Remember prevous bci.
1028 prev_bci = bci;
1029 }
1030 // Set
1031 _basic_blocks[bbNo-1]._end_bci = prev_bci;
1032
1033 _max_monitors = monitor_count;
1034
1035 // Now that we have a bound on the depth of the monitor stack, we can
1036 // initialize the CellTypeState-related information.
1037 initState();
1038
1039 // We allocate space for all state-vectors for all basicblocks in one huge chuck.
1040 // Then in the next part of the code, we set a pointer in each _basic_block that
1041 // points to each piece.
1042 CellTypeStateList basicBlockState = new CellTypeStateList(bbNo * _state_len);
1043
1044 // Make a pass over the basicblocks and assign their state vectors.
1045 for (int blockNum=0; blockNum < bbNo; blockNum++) {
1046 BasicBlock bb = _basic_blocks[blockNum];
1047 bb._state = basicBlockState.subList(blockNum * _state_len, (blockNum + 1) * _state_len);
1048
1049 if (Assert.ASSERTS_ENABLED) {
1050 if (blockNum + 1 < bbNo) {
1051 int bc_len = Bytecodes.javaLengthAt(_method, bb._end_bci);
1052 Assert.that(bb._end_bci + bc_len == _basic_blocks[blockNum + 1]._bci,
1053 "unmatched bci info in basicblock");
1054 }
1055 }
1056 }
1057 if (Assert.ASSERTS_ENABLED) {
1058 BasicBlock bb = _basic_blocks[bbNo-1];
1059 int bc_len = Bytecodes.javaLengthAt(_method, bb._end_bci);
1060 Assert.that(bb._end_bci + bc_len == _method.getCodeSize(), "wrong end bci");
1061 }
1062
1063 // Check that the correct number of basicblocks was found
1064 if (bbNo !=_bb_count) {
1065 if (bbNo < _bb_count) {
1066 throw new RuntimeException("jump into the middle of instruction?");
1067 } else {
1068 throw new RuntimeException("extra basic blocks - should not happen?");
1069 }
1070 }
1071
1072 // Mark all alive blocks
1073 markReachableCode();
1074 }
1075
1076 void setupMethodEntryState () {
1077 // Initialize all locals to 'uninit' and set stack-height to 0
1078 makeContextUninitialized();
1079
1080 // Initialize CellState type of arguments
1081 methodsigToEffect(method().getSignature(), method().isStatic(), vars());
1082
1083 // If some references must be pre-assigned to null, then set that up
1084 initializeVars();
1085
1086 // This is the start state
1087 mergeStateIntoBB(_basic_blocks[0]);
1088
1089 if (Assert.ASSERTS_ENABLED) {
1090 Assert.that(_basic_blocks[0].changed(), "we are not getting off the ground");
1091 }
1092 }
1093
1094 void interpAll () {
1095 boolean change = true;
1096
1097 while (change && !_got_error) {
1098 change = false;
1099 for (int i = 0; i < _bb_count && !_got_error; i++) {
1100 BasicBlock bb = _basic_blocks[i];
1101 if (bb.changed()) {
1102 if (_got_error) return;
1103 change = true;
1104 bb.setChanged(false);
1105 interpBB(bb);
1106 }
1107 }
1108 }
1109 }
1110
1111 //
1112 // Interpretation methods (secondary)
1113 //
1114
1115 /** Sets the current state to be the state after executing the
1116 current instruction, starting in the current state. */
1117 void interp1 (BytecodeStream itr) {
1118 if (DEBUG) {
1119 System.err.println(" - bci " + itr.bci());
1120 }
1121
1122 // if (TraceNewOopMapGeneration) {
1123 // print_current_state(tty, itr, TraceNewOopMapGenerationDetailed);
1124 // }
1125
1126 // Should we report the results? Result is reported *before* the
1127 // instruction at the current bci is executed. However, not for
1128 // calls. For calls we do not want to include the arguments, so we
1129 // postpone the reporting until they have been popped (in method
1130 // ppl).
1131 if (_report_result == true) {
1132 switch(itr.code()) {
1133 case Bytecodes._invokevirtual:
1134 case Bytecodes._invokespecial:
1135 case Bytecodes._invokestatic:
1136 case Bytecodes._invokeinterface:
1137 _itr_send = itr;
1138 _report_result_for_send = true;
1139 break;
1140 default:
1141 fillStackmapForOpcodes(itr, vars(), stack(), _stack_top);
1142 break;
1143 }
1144 }
1145
1146 // abstract interpretation of current opcode
1147 switch(itr.code()) {
1148 case Bytecodes._nop: break;
1149 case Bytecodes._goto: break;
1150 case Bytecodes._goto_w: break;
1151 case Bytecodes._iinc: break;
1152 case Bytecodes._return: doReturnMonitorCheck();
1153 break;
1154
1155 case Bytecodes._aconst_null:
1156 case Bytecodes._new: ppush1(CellTypeState.makeLineRef(itr.bci()));
1157 break;
1158
1159 case Bytecodes._iconst_m1:
1160 case Bytecodes._iconst_0:
1161 case Bytecodes._iconst_1:
1162 case Bytecodes._iconst_2:
1163 case Bytecodes._iconst_3:
1164 case Bytecodes._iconst_4:
1165 case Bytecodes._iconst_5:
1166 case Bytecodes._fconst_0:
1167 case Bytecodes._fconst_1:
1168 case Bytecodes._fconst_2:
1169 case Bytecodes._bipush:
1170 case Bytecodes._sipush: ppush1(valCTS); break;
1171
1172 case Bytecodes._lconst_0:
1173 case Bytecodes._lconst_1:
1174 case Bytecodes._dconst_0:
1175 case Bytecodes._dconst_1: ppush(vvCTS); break;
1176
1177 case Bytecodes._ldc2_w: ppush(vvCTS); break;
1178
1179 case Bytecodes._ldc: doLdc(itr.getIndex(), itr.bci()); break;
1180 case Bytecodes._ldc_w: doLdc(itr.getIndexBig(), itr.bci());break;
1181
1182 case Bytecodes._iload:
1183 case Bytecodes._fload: ppload(vCTS, itr.getIndex()); break;
1184
1185 case Bytecodes._lload:
1186 case Bytecodes._dload: ppload(vvCTS,itr.getIndex()); break;
1187
1188 case Bytecodes._aload: ppload(rCTS, itr.getIndex()); break;
1189
1190 case Bytecodes._iload_0:
1191 case Bytecodes._fload_0: ppload(vCTS, 0); break;
1192 case Bytecodes._iload_1:
1193 case Bytecodes._fload_1: ppload(vCTS, 1); break;
1194 case Bytecodes._iload_2:
1195 case Bytecodes._fload_2: ppload(vCTS, 2); break;
1196 case Bytecodes._iload_3:
1197 case Bytecodes._fload_3: ppload(vCTS, 3); break;
1198
1199 case Bytecodes._lload_0:
1200 case Bytecodes._dload_0: ppload(vvCTS, 0); break;
1201 case Bytecodes._lload_1:
1202 case Bytecodes._dload_1: ppload(vvCTS, 1); break;
1203 case Bytecodes._lload_2:
1204 case Bytecodes._dload_2: ppload(vvCTS, 2); break;
1205 case Bytecodes._lload_3:
1206 case Bytecodes._dload_3: ppload(vvCTS, 3); break;
1207
1208 case Bytecodes._aload_0: ppload(rCTS, 0); break;
1209 case Bytecodes._aload_1: ppload(rCTS, 1); break;
1210 case Bytecodes._aload_2: ppload(rCTS, 2); break;
1211 case Bytecodes._aload_3: ppload(rCTS, 3); break;
1212
1213 case Bytecodes._iaload:
1214 case Bytecodes._faload:
1215 case Bytecodes._baload:
1216 case Bytecodes._caload:
1217 case Bytecodes._saload: pp(vrCTS, vCTS); break;
1218
1219 case Bytecodes._laload: pp(vrCTS, vvCTS); break;
1220 case Bytecodes._daload: pp(vrCTS, vvCTS); break;
1221
1222 case Bytecodes._aaload: ppNewRef(vrCTS, itr.bci()); break;
1223
1224 case Bytecodes._istore:
1225 case Bytecodes._fstore: ppstore(vCTS, itr.getIndex()); break;
1226
1227 case Bytecodes._lstore:
1228 case Bytecodes._dstore: ppstore(vvCTS, itr.getIndex()); break;
1229
1230 case Bytecodes._astore: doAstore(itr.getIndex()); break;
1231
1232 case Bytecodes._istore_0:
1233 case Bytecodes._fstore_0: ppstore(vCTS, 0); break;
1234 case Bytecodes._istore_1:
1235 case Bytecodes._fstore_1: ppstore(vCTS, 1); break;
1236 case Bytecodes._istore_2:
1237 case Bytecodes._fstore_2: ppstore(vCTS, 2); break;
1238 case Bytecodes._istore_3:
1239 case Bytecodes._fstore_3: ppstore(vCTS, 3); break;
1240
1241 case Bytecodes._lstore_0:
1242 case Bytecodes._dstore_0: ppstore(vvCTS, 0); break;
1243 case Bytecodes._lstore_1:
1244 case Bytecodes._dstore_1: ppstore(vvCTS, 1); break;
1245 case Bytecodes._lstore_2:
1246 case Bytecodes._dstore_2: ppstore(vvCTS, 2); break;
1247 case Bytecodes._lstore_3:
1248 case Bytecodes._dstore_3: ppstore(vvCTS, 3); break;
1249
1250 case Bytecodes._astore_0: doAstore(0); break;
1251 case Bytecodes._astore_1: doAstore(1); break;
1252 case Bytecodes._astore_2: doAstore(2); break;
1253 case Bytecodes._astore_3: doAstore(3); break;
1254
1255 case Bytecodes._iastore:
1256 case Bytecodes._fastore:
1257 case Bytecodes._bastore:
1258 case Bytecodes._castore:
1259 case Bytecodes._sastore: ppop(vvrCTS); break;
1260 case Bytecodes._lastore:
1261 case Bytecodes._dastore: ppop(vvvrCTS); break;
1262 case Bytecodes._aastore: ppop(rvrCTS); break;
1263
1264 case Bytecodes._pop: ppopAny(1); break;
1265 case Bytecodes._pop2: ppopAny(2); break;
1266
1267 case Bytecodes._dup: ppdupswap(1, "11"); break;
1268 case Bytecodes._dup_x1: ppdupswap(2, "121"); break;
1269 case Bytecodes._dup_x2: ppdupswap(3, "1321"); break;
1270 case Bytecodes._dup2: ppdupswap(2, "2121"); break;
1271 case Bytecodes._dup2_x1: ppdupswap(3, "21321"); break;
1272 case Bytecodes._dup2_x2: ppdupswap(4, "214321"); break;
1273 case Bytecodes._swap: ppdupswap(2, "12"); break;
1274
1275 case Bytecodes._iadd:
1276 case Bytecodes._fadd:
1277 case Bytecodes._isub:
1278 case Bytecodes._fsub:
1279 case Bytecodes._imul:
1280 case Bytecodes._fmul:
1281 case Bytecodes._idiv:
1282 case Bytecodes._fdiv:
1283 case Bytecodes._irem:
1284 case Bytecodes._frem:
1285 case Bytecodes._ishl:
1286 case Bytecodes._ishr:
1287 case Bytecodes._iushr:
1288 case Bytecodes._iand:
1289 case Bytecodes._ior:
1290 case Bytecodes._ixor:
1291 case Bytecodes._l2f:
1292 case Bytecodes._l2i:
1293 case Bytecodes._d2f:
1294 case Bytecodes._d2i:
1295 case Bytecodes._fcmpl:
1296 case Bytecodes._fcmpg: pp(vvCTS, vCTS); break;
1297
1298 case Bytecodes._ladd:
1299 case Bytecodes._dadd:
1300 case Bytecodes._lsub:
1301 case Bytecodes._dsub:
1302 case Bytecodes._lmul:
1303 case Bytecodes._dmul:
1304 case Bytecodes._ldiv:
1305 case Bytecodes._ddiv:
1306 case Bytecodes._lrem:
1307 case Bytecodes._drem:
1308 case Bytecodes._land:
1309 case Bytecodes._lor:
1310 case Bytecodes._lxor: pp(vvvvCTS, vvCTS); break;
1311
1312 case Bytecodes._ineg:
1313 case Bytecodes._fneg:
1314 case Bytecodes._i2f:
1315 case Bytecodes._f2i:
1316 case Bytecodes._i2c:
1317 case Bytecodes._i2s:
1318 case Bytecodes._i2b: pp(vCTS, vCTS); break;
1319
1320 case Bytecodes._lneg:
1321 case Bytecodes._dneg:
1322 case Bytecodes._l2d:
1323 case Bytecodes._d2l: pp(vvCTS, vvCTS); break;
1324
1325 case Bytecodes._lshl:
1326 case Bytecodes._lshr:
1327 case Bytecodes._lushr: pp(vvvCTS, vvCTS); break;
1328
1329 case Bytecodes._i2l:
1330 case Bytecodes._i2d:
1331 case Bytecodes._f2l:
1332 case Bytecodes._f2d: pp(vCTS, vvCTS); break;
1333
1334 case Bytecodes._lcmp: pp(vvvvCTS, vCTS); break;
1335 case Bytecodes._dcmpl:
1336 case Bytecodes._dcmpg: pp(vvvvCTS, vCTS); break;
1337
1338 case Bytecodes._ifeq:
1339 case Bytecodes._ifne:
1340 case Bytecodes._iflt:
1341 case Bytecodes._ifge:
1342 case Bytecodes._ifgt:
1343 case Bytecodes._ifle:
1344 case Bytecodes._tableswitch: ppop1(valCTS);
1345 break;
1346 case Bytecodes._ireturn:
1347 case Bytecodes._freturn: doReturnMonitorCheck();
1348 ppop1(valCTS);
1349 break;
1350 case Bytecodes._if_icmpeq:
1351 case Bytecodes._if_icmpne:
1352 case Bytecodes._if_icmplt:
1353 case Bytecodes._if_icmpge:
1354 case Bytecodes._if_icmpgt:
1355 case Bytecodes._if_icmple: ppop(vvCTS);
1356 break;
1357
1358 case Bytecodes._lreturn: doReturnMonitorCheck();
1359 ppop(vvCTS);
1360 break;
1361
1362 case Bytecodes._dreturn: doReturnMonitorCheck();
1363 ppop(vvCTS);
1364 break;
1365
1366 case Bytecodes._if_acmpeq:
1367 case Bytecodes._if_acmpne: ppop(rrCTS); break;
1368
1369 case Bytecodes._jsr: doJsr(itr.dest()); break;
1370 case Bytecodes._jsr_w: doJsr(itr.dest_w()); break;
1371
1372 case Bytecodes._getstatic: doField(true, true,
1373 itr.getIndexBig(),
1374 itr.bci()); break;
1375 case Bytecodes._putstatic: doField(false, true, itr.getIndexBig(), itr.bci()); break;
1376 case Bytecodes._getfield: doField(true, false, itr.getIndexBig(), itr.bci()); break;
1377 case Bytecodes._putfield: doField(false, false, itr.getIndexBig(), itr.bci()); break;
1378
1379 case Bytecodes._invokevirtual:
1380 case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexBig(), itr.bci()); break;
1381 case Bytecodes._invokestatic: doMethod(true, false, itr.getIndexBig(), itr.bci()); break;
1382 case Bytecodes._invokeinterface: doMethod(false, true, itr.getIndexBig(), itr.bci()); break;
1383 case Bytecodes._newarray:
1384 case Bytecodes._anewarray: ppNewRef(vCTS, itr.bci()); break;
1385 case Bytecodes._checkcast: doCheckcast(); break;
1386 case Bytecodes._arraylength:
1387 case Bytecodes._instanceof: pp(rCTS, vCTS); break;
1388 case Bytecodes._monitorenter: doMonitorenter(itr.bci()); break;
1389 case Bytecodes._monitorexit: doMonitorexit(itr.bci()); break;
1390
1391 case Bytecodes._athrow: // handled by do_exception_edge() BUT ...
1392 // vlh(apple): doExceptionEdge() does not get
1393 // called if method has no exception handlers
1394 if ((!_has_exceptions) && (_monitor_top > 0)) {
1395 _monitor_safe = false;
1396 }
1397 break;
1398
1399 case Bytecodes._areturn: doReturnMonitorCheck();
1400 ppop1(refCTS);
1401 break;
1402 case Bytecodes._ifnull:
1403 case Bytecodes._ifnonnull: ppop1(refCTS); break;
1404 case Bytecodes._multianewarray: doMultianewarray(itr.codeAt(itr.bci() + 3), itr.bci()); break;
1405
1406 case Bytecodes._wide: throw new RuntimeException("Iterator should skip this bytecode");
1407 case Bytecodes._ret: break;
1408
1409 // Java opcodes
1410 case Bytecodes._fast_aaccess_0: ppNewRef(rCTS, itr.bci()); break; // Pair bytecode for (aload_0, _fast_agetfield)
1411
1412 case Bytecodes._fast_iaccess_0: ppush1(valCTS); break; // Pair bytecode for (aload_0, _fast_igetfield)
1413
1414 case Bytecodes._fast_igetfield: pp(rCTS, vCTS); break;
1415
1416 case Bytecodes._fast_agetfield: ppNewRef(rCTS, itr.bci()); break;
1417
1418 case Bytecodes._fast_aload_0: ppload(rCTS, 0); break;
1419
1420 case Bytecodes._lookupswitch:
1421 case Bytecodes._fast_linearswitch:
1422 case Bytecodes._fast_binaryswitch: ppop1(valCTS); break;
1423
1424 default:
1425 throw new RuntimeException("unexpected opcode: " + itr.code());
1426 }
1427 }
1428
1429 void doExceptionEdge (BytecodeStream itr) {
1430 // Only check exception edge, if bytecode can trap
1431 if (!Bytecodes.canTrap(itr.code())) return;
1432 switch (itr.code()) {
1433 case Bytecodes._aload_0:
1434 case Bytecodes._fast_aload_0:
1435 // These bytecodes can trap for rewriting. We need to assume that
1436 // they do not throw exceptions to make the monitor analysis work.
1437 return;
1438
1439 case Bytecodes._ireturn:
1440 case Bytecodes._lreturn:
1441 case Bytecodes._freturn:
1442 case Bytecodes._dreturn:
1443 case Bytecodes._areturn:
1444 case Bytecodes._return:
1445 // If the monitor stack height is not zero when we leave the method,
1446 // then we are either exiting with a non-empty stack or we have
1447 // found monitor trouble earlier in our analysis. In either case,
1448 // assume an exception could be taken here.
1449 if (_monitor_top == 0) {
1450 return;
1451 }
1452 break;
1453
1454 case Bytecodes._monitorexit:
1455 // If the monitor stack height is bad_monitors, then we have detected a
1456 // monitor matching problem earlier in the analysis. If the
1457 // monitor stack height is 0, we are about to pop a monitor
1458 // off of an empty stack. In either case, the bytecode
1459 // could throw an exception.
1460 if (_monitor_top != bad_monitors && _monitor_top != 0) {
1461 return;
1462 }
1463 break;
1464 }
1465
1466 if (_has_exceptions) {
1467 int bci = itr.bci();
1468 TypeArray exct = method().getExceptionTable();
1469 for(int i = 0; i< exct.getLength(); i+=4) {
1470 int start_pc = exct.getIntAt(i);
1471 int end_pc = exct.getIntAt(i+1);
1472 int handler_pc = exct.getIntAt(i+2);
1473 int catch_type = exct.getIntAt(i+3);
1474
1475 if (start_pc <= bci && bci < end_pc) {
1476 BasicBlock excBB = getBasicBlockAt(handler_pc);
1477 CellTypeStateList excStk = excBB.stack();
1478 CellTypeStateList cOpStck = stack();
1479 CellTypeState cOpStck_0 = cOpStck.get(0).copy();
1480 int cOpStackTop = _stack_top;
1481
1482 // Exception stacks are always the same.
1483 if (Assert.ASSERTS_ENABLED) {
1484 Assert.that(method().getMaxStack() > 0, "sanity check");
1485 }
1486
1487 // We remembered the size and first element of "cOpStck"
1488 // above; now we temporarily set them to the appropriate
1489 // values for an exception handler.
1490 cOpStck.get(0).set(CellTypeState.makeSlotRef(_max_locals));
1491 _stack_top = 1;
1492
1493 mergeStateIntoBB(excBB);
1494
1495 // Now undo the temporary change.
1496 cOpStck.get(0).set(cOpStck_0);
1497 _stack_top = cOpStackTop;
1498
1499 // If this is a "catch all" handler, then we do not need to
1500 // consider any additional handlers.
1501 if (catch_type == 0) {
1502 return;
1503 }
1504 }
1505 }
1506 }
1507
1508 // It is possible that none of the exception handlers would have caught
1509 // the exception. In this case, we will exit the method. We must
1510 // ensure that the monitor stack is empty in this case.
1511 if (_monitor_top == 0) {
1512 return;
1513 }
1514
1515 // We pessimistically assume that this exception can escape the
1516 // method. (It is possible that it will always be caught, but
1517 // we don't care to analyse the types of the catch clauses.)
1518
1519 // We don't set _monitor_top to bad_monitors because there are no successors
1520 // to this exceptional exit.
1521
1522 if (TraceMonitorMismatch && _monitor_safe) {
1523 // We check _monitor_safe so that we only report the first mismatched
1524 // exceptional exit.
1525 reportMonitorMismatch("non-empty monitor stack at exceptional exit");
1526 }
1527 _monitor_safe = false;
1528 }
1529
1530 void checkType (CellTypeState expected, CellTypeState actual) {
1531 if (!expected.equalKind(actual)) {
1532 throw new RuntimeException("wrong type on stack (found: " +
1533 actual.toChar() + " expected: " +
1534 expected.toChar() + ")");
1535 }
1536 }
1537
1538 void ppstore (CellTypeState[] in, int loc_no) {
1539 for (int i = 0; i < in.length && !in[i].equal(CellTypeState.bottom); i++) {
1540 CellTypeState expected = in[i];
1541 CellTypeState actual = pop();
1542 checkType(expected, actual);
1543 if (Assert.ASSERTS_ENABLED) {
1544 Assert.that(loc_no >= 0, "sanity check");
1545 }
1546 setVar(loc_no++, actual);
1547 }
1548 }
1549
1550 void ppload (CellTypeState[] out, int loc_no) {
1551 for (int i = 0; i < out.length && !out[i].equal(CellTypeState.bottom); i++) {
1552 CellTypeState out1 = out[i];
1553 CellTypeState vcts = getVar(loc_no);
1554 if (Assert.ASSERTS_ENABLED) {
1555 Assert.that(out1.canBeReference() || out1.canBeValue(),
1556 "can only load refs. and values.");
1557 }
1558 if (out1.isReference()) {
1559 if (Assert.ASSERTS_ENABLED) {
1560 Assert.that(loc_no>=0, "sanity check");
1561 }
1562 if (!vcts.isReference()) {
1563 // We were asked to push a reference, but the type of the
1564 // variable can be something else
1565 _conflict = true;
1566 if (vcts.canBeUninit()) {
1567 // It is a ref-uninit conflict (at least). If there are other
1568 // problems, we'll get them in the next round
1569 addToRefInitSet(loc_no);
1570 vcts = out1;
1571 } else {
1572 // It wasn't a ref-uninit conflict. So must be a
1573 // ref-val or ref-pc conflict. Split the variable.
1574 recordRefvalConflict(loc_no);
1575 vcts = out1;
1576 }
1577 push(out1); // recover...
1578 } else {
1579 push(vcts); // preserve reference.
1580 }
1581 // Otherwise it is a conflict, but one that verification would
1582 // have caught if illegal. In particular, it can't be a topCTS
1583 // resulting from mergeing two difference pcCTS's since the verifier
1584 // would have rejected any use of such a merge.
1585 } else {
1586 push(out1); // handle val/init conflict
1587 }
1588 loc_no++;
1589 }
1590 }
1591
1592 void ppush1 (CellTypeState in) {
1593 if (Assert.ASSERTS_ENABLED) {
1594 Assert.that(in.isReference() | in.isValue(), "sanity check");
1595 }
1596 if (DEBUG) {
1597 System.err.println(" - pushing " + in.toChar());
1598 }
1599 push(in);
1600 }
1601
1602 void ppush (CellTypeState[] in) {
1603 for (int i = 0; i < in.length && !in[i].equal(CellTypeState.bottom); i++) {
1604 ppush1(in[i]);
1605 }
1606 }
1607
1608 void ppush (CellTypeStateList in) {
1609 for (int i = 0; i < in.size() && !in.get(i).equal(CellTypeState.bottom); i++) {
1610 ppush1(in.get(i));
1611 }
1612 }
1613
1614 void ppop1 (CellTypeState out) {
1615 CellTypeState actual = pop();
1616 if (DEBUG) {
1617 System.err.println(" - popping " + actual.toChar() + ", expecting " + out.toChar());
1618 }
1619 checkType(out, actual);
1620 }
1621
1622 void ppop (CellTypeState[] out) {
1623 for (int i = 0; i < out.length && !out[i].equal(CellTypeState.bottom); i++) {
1624 ppop1(out[i]);
1625 }
1626 }
1627
1628 void ppopAny (int poplen) {
1629 if (_stack_top >= poplen) {
1630 _stack_top -= poplen;
1631 } else {
1632 throw new RuntimeException("stack underflow");
1633 }
1634 }
1635
1636 void pp (CellTypeState[] in, CellTypeState[] out) {
1637 ppop(in);
1638 ppush(out);
1639 }
1640
1641 void ppNewRef (CellTypeState[] in, int bci) {
1642 ppop(in);
1643 ppush1(CellTypeState.makeLineRef(bci));
1644 }
1645
1646 void ppdupswap (int poplen, String out) {
1647 CellTypeState[] actual = new CellTypeState[5];
1648 Assert.that(poplen < 5, "this must be less than length of actual vector");
1649
1650 // pop all arguments
1651 for(int i = 0; i < poplen; i++) actual[i] = pop();
1652
1653 // put them back
1654 for (int i = 0; i < out.length(); i++) {
1655 char push_ch = out.charAt(i);
1656 int idx = push_ch - '1';
1657 if (Assert.ASSERTS_ENABLED) {
1658 Assert.that(idx >= 0 && idx < poplen, "wrong arguments");
1659 }
1660 push(actual[idx]);
1661 }
1662 }
1663
1664 void doLdc (int idx, int bci) {
1665 ConstantPool cp = method().getConstants();
1666 ConstantTag tag = cp.getTagAt(idx);
1667 CellTypeState cts = (tag.isString() || tag.isUnresolvedString() ||
1668 tag.isKlass() || tag.isUnresolvedKlass())
1669 ? CellTypeState.makeLineRef(bci)
1670 : valCTS;
1671 ppush1(cts);
1672 }
1673
1674 void doAstore (int idx) {
1675 CellTypeState r_or_p = pop();
1676 if (!r_or_p.isAddress() && !r_or_p.isReference()) {
1677 // We actually expected ref or pc, but we only report that we expected a ref. It does not
1678 // really matter (at least for now)
1679 throw new RuntimeException("wrong type on stack (found: " +
1680 r_or_p.toChar() + ", expected: {pr})");
1681 }
1682 setVar(idx, r_or_p);
1683 }
1684
1685 void doJsr (int targBCI) {
1686 push(CellTypeState.makeAddr(targBCI));
1687 }
1688
1689 void doField (boolean is_get, boolean is_static, int idx, int bci) {
1690 // Dig up signature for field in constant pool
1691 ConstantPool cp = method().getConstants();
1692 int nameAndTypeIdx = cp.getNameAndTypeRefIndexAt(idx);
1693 int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx);
1694 Symbol signature = cp.getSymbolAt(signatureIdx);
1695
1696 if (DEBUG) {
1697 System.err.println("doField: signature = " + signature.asString() + ", idx = " + idx +
1698 ", nameAndTypeIdx = " + nameAndTypeIdx + ", signatureIdx = " + signatureIdx + ", bci = " + bci);
1699 }
1700
1701 // Parse signature (espcially simple for fields)
1702 // The signature is UFT8 encoded, but the first char is always ASCII for signatures.
1703 char sigch = (char) signature.getByteAt(0);
1704 CellTypeState[] temp = new CellTypeState[4];
1705 CellTypeState[] eff = sigcharToEffect(sigch, bci, temp);
1706
1707 CellTypeState[] in = new CellTypeState[4];
1708 CellTypeState[] out;
1709 int i = 0;
1710
1711 if (is_get) {
1712 out = eff;
1713 } else {
1714 out = epsilonCTS;
1715 i = copyCTS(in, eff);
1716 }
1717 if (!is_static) in[i++] = CellTypeState.ref;
1718 in[i] = CellTypeState.bottom;
1719 if (Assert.ASSERTS_ENABLED) {
1720 Assert.that(i<=3, "sanity check");
1721 }
1722 pp(in, out);
1723 }
1724
1725 void doMethod (boolean is_static, boolean is_interface, int idx, int bci) {
1726 // Dig up signature for field in constant pool
1727 ConstantPool cp = _method.getConstants();
1728 int nameAndTypeIdx = cp.getNameAndTypeRefIndexAt(idx);
1729 int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx);
1730 Symbol signature = cp.getSymbolAt(signatureIdx);
1731
1732 if (DEBUG) {
1733 System.err.println("doMethod: signature = " + signature.asString() + ", idx = " + idx +
1734 ", nameAndTypeIdx = " + nameAndTypeIdx + ", signatureIdx = " + signatureIdx +
1735 ", bci = " + bci);
1736 }
1737
1738 // Parse method signature
1739 CellTypeStateList out = new CellTypeStateList(4);
1740 CellTypeStateList in = new CellTypeStateList(MAXARGSIZE+1); // Includes result
1741 ComputeCallStack cse = new ComputeCallStack(signature);
1742
1743 // Compute return type
1744 int res_length = cse.computeForReturntype(out);
1745
1746 // Temporary hack.
1747 if (out.get(0).equal(CellTypeState.ref) && out.get(1).equal(CellTypeState.bottom)) {
1748 out.get(0).set(CellTypeState.makeLineRef(bci));
1749 }
1750
1751 if (Assert.ASSERTS_ENABLED) {
1752 Assert.that(res_length<=4, "max value should be vv");
1753 }
1754
1755 // Compute arguments
1756 int arg_length = cse.computeForParameters(is_static, in);
1757 if (Assert.ASSERTS_ENABLED) {
1758 Assert.that(arg_length<=MAXARGSIZE, "too many locals");
1759 }
1760
1761 // Pop arguments
1762 for (int i = arg_length - 1; i >= 0; i--) ppop1(in.get(i));// Do args in reverse order.
1763
1764 // Report results
1765 if (_report_result_for_send == true) {
1766 fillStackmapForOpcodes(_itr_send, vars(), stack(), _stack_top);
1767 _report_result_for_send = false;
1768 }
1769
1770 // Push return address
1771 ppush(out);
1772 }
1773
1774 void doMultianewarray (int dims, int bci) {
1775 if (Assert.ASSERTS_ENABLED) {
1776 Assert.that(dims >= 1, "sanity check");
1777 }
1778 for(int i = dims -1; i >=0; i--) {
1779 ppop1(valCTS);
1780 }
1781 ppush1(CellTypeState.makeLineRef(bci));
1782 }
1783
1784 void doMonitorenter (int bci) {
1785 CellTypeState actual = pop();
1786 if (_monitor_top == bad_monitors) {
1787 return;
1788 }
1789
1790 // Bail out when we get repeated locks on an identical monitor. This case
1791 // isn't too hard to handle and can be made to work if supporting nested
1792 // redundant synchronized statements becomes a priority.
1793 //
1794 // See also "Note" in do_monitorexit(), below.
1795 if (actual.isLockReference()) {
1796 _monitor_top = bad_monitors;
1797 _monitor_safe = false;
1798
1799 if (TraceMonitorMismatch) {
1800 reportMonitorMismatch("nested redundant lock -- bailout...");
1801 }
1802 return;
1803 }
1804
1805 CellTypeState lock = CellTypeState.makeLockRef(bci);
1806 checkType(refCTS, actual);
1807 if (!actual.isInfoTop()) {
1808 replaceAllCTSMatches(actual, lock);
1809 monitorPush(lock);
1810 }
1811 }
1812
1813 void doMonitorexit (int bci) {
1814 CellTypeState actual = pop();
1815 if (_monitor_top == bad_monitors) {
1816 return;
1817 }
1818 checkType(refCTS, actual);
1819 CellTypeState expected = monitorPop();
1820 if (!actual.isLockReference() || !expected.equal(actual)) {
1821 // The monitor we are exiting is not verifiably the one
1822 // on the top of our monitor stack. This causes a monitor
1823 // mismatch.
1824 _monitor_top = bad_monitors;
1825 _monitor_safe = false;
1826
1827 // We need to mark this basic block as changed so that
1828 // this monitorexit will be visited again. We need to
1829 // do this to ensure that we have accounted for the
1830 // possibility that this bytecode will throw an
1831 // exception.
1832 BasicBlock bb = getBasicBlockContaining(bci);
1833 bb.setChanged(true);
1834 bb._monitor_top = bad_monitors;
1835
1836 if (TraceMonitorMismatch) {
1837 reportMonitorMismatch("improper monitor pair");
1838 }
1839 } else {
1840 // This code is a fix for the case where we have repeated
1841 // locking of the same object in straightline code. We clear
1842 // out the lock when it is popped from the monitor stack
1843 // and replace it with an unobtrusive reference value that can
1844 // be locked again.
1845 //
1846 // Note: when generateOopMap is fixed to properly handle repeated,
1847 // nested, redundant locks on the same object, then this
1848 // fix will need to be removed at that time.
1849 replaceAllCTSMatches(actual, CellTypeState.makeLineRef(bci));
1850 }
1851
1852 if (_report_for_exit_bci == bci) {
1853 _matching_enter_bci = expected.getMonitorSource();
1854 }
1855 }
1856
1857 void doReturnMonitorCheck () {
1858 if (_monitor_top > 0) {
1859 // The monitor stack must be empty when we leave the method
1860 // for the monitors to be properly matched.
1861 _monitor_safe = false;
1862
1863 // Since there are no successors to the *return bytecode, it
1864 // isn't necessary to set _monitor_top to bad_monitors.
1865
1866 if (TraceMonitorMismatch) {
1867 reportMonitorMismatch("non-empty monitor stack at return");
1868 }
1869 }
1870 }
1871
1872 void doCheckcast () {
1873 CellTypeState actual = pop();
1874 checkType(refCTS, actual);
1875 push(actual);
1876 }
1877
1878 CellTypeState[] sigcharToEffect (char sigch, int bci, CellTypeState[] out) {
1879 // Object and array
1880 if (sigch=='L' || sigch=='[') {
1881 out[0] = CellTypeState.makeLineRef(bci);
1882 out[1] = CellTypeState.bottom;
1883 return out;
1884 }
1885 if (sigch == 'J' || sigch == 'D' ) return vvCTS; // Long and Double
1886 if (sigch == 'V' ) return epsilonCTS; // Void
1887 return vCTS; // Otherwise
1888 }
1889
1890 // Copies (optionally bottom/zero terminated) CTS string from "src" into "dst".
1891 // Does NOT terminate with a bottom. Returns the number of cells copied.
1892 int copyCTS (CellTypeState[] dst, CellTypeState[] src) {
1893 int idx = 0;
1894 for (; idx < src.length && !src[idx].isBottom(); idx++) {
1895 dst[idx] = src[idx];
1896 }
1897 return idx;
1898 }
1899
1900 // Create result set
1901 boolean _report_result;
1902 boolean _report_result_for_send; // Unfortunatly, stackmaps for sends are special, so we need some extra
1903 BytecodeStream _itr_send; // variables to handle them properly.
1904
1905 void reportResult () {
1906 // if (TraceNewOopMapGeneration) tty.print_cr("Report result pass");
1907
1908 // We now want to report the result of the parse
1909 _report_result = true;
1910
1911 // Prolog code
1912 fillStackmapProlog(_gc_points);
1913
1914 // Mark everything changed, then do one interpretation pass.
1915 for (int i = 0; i<_bb_count; i++) {
1916 if (_basic_blocks[i].isReachable()) {
1917 _basic_blocks[i].setChanged(true);
1918 interpBB(_basic_blocks[i]);
1919 }
1920 }
1921
1922 // Note: Since we are skipping dead-code when we are reporting results, then
1923 // the no. of encountered gc-points might be fewer than the previously number
1924 // we have counted. (dead-code is a pain - it should be removed before we get here)
1925 fillStackmapEpilog();
1926
1927 // Report initvars
1928 fillInitVars(_init_vars);
1929
1930 _report_result = false;
1931 }
1932
1933 // Initvars
1934 List/*<Integer>*/ _init_vars;
1935
1936 void initializeVars () {
1937 for (int k = 0; k < _init_vars.size(); k++)
1938 _state.get(((Integer) _init_vars.get(k)).intValue()).set(CellTypeState.makeSlotRef(k));
1939 }
1940
1941 void addToRefInitSet (int localNo) {
1942 // if (TraceNewOopMapGeneration)
1943 // tty.print_cr("Added init vars: %d", localNo);
1944
1945 Integer local = new Integer(localNo);
1946
1947 // Is it already in the set?
1948 if (_init_vars.contains(local))
1949 return;
1950
1951 _init_vars.add(local);
1952 }
1953
1954 // Conflicts rewrite logic
1955 boolean _conflict; // True, if a conflict occured during interpretation
1956 int _nof_refval_conflicts; // No. of conflicts that require rewrites
1957 int[] _new_var_map;
1958
1959 void recordRefvalConflict (int varNo) {
1960 if (Assert.ASSERTS_ENABLED) {
1961 Assert.that(varNo>=0 && varNo< _max_locals, "index out of range");
1962 }
1963
1964 if (TraceOopMapRewrites) {
1965 System.err.println("### Conflict detected (local no: " + varNo + ")");
1966 }
1967
1968 if (_new_var_map == null) {
1969 _new_var_map = new int[_max_locals];
1970 for (int k = 0; k < _max_locals; k++) _new_var_map[k] = k;
1971 }
1972
1973 if ( _new_var_map[varNo] == varNo) {
1974 // Check if max. number of locals has been reached
1975 if (_max_locals + _nof_refval_conflicts >= MAX_LOCAL_VARS) {
1976 throw new RuntimeException("Rewriting exceeded local variable limit");
1977 }
1978 _new_var_map[varNo] = _max_locals + _nof_refval_conflicts;
1979 _nof_refval_conflicts++;
1980 }
1981 }
1982
1983 void rewriteRefvalConflicts () {
1984 if (_nof_refval_conflicts > 0) {
1985 if (VM.getVM().isDebugging()) {
1986 throw new RuntimeException("Should not reach here (method rewriting should have been done by the VM already)");
1987 } else {
1988 throw new RuntimeException("Method rewriting not yet implemented in Java");
1989 }
1990 }
1991 }
1992 // Rewriting-related routines are not needed here
1993 // void rewrite_refval_conflict (int from, int to);
1994 // bool rewrite_refval_conflict_inst (BytecodeStream *i, int from, int to);
1995 // bool rewrite_load_or_store (BytecodeStream *i, Bytecodes.Code bc, Bytecodes.Code bc0, unsigned int varNo);
1996
1997 // bool expand_current_instr (int bci, int ilen, int newIlen, u_char inst_buffer[]);
1998 // bool is_astore (BytecodeStream *itr, int *index);
1999 // bool is_aload (BytecodeStream *itr, int *index);
2000
2001 // List of bci's where a return address is on top of the stack
2002 // GrowableArray<intptr_t> *_ret_adr_tos;
2003
2004 // bool stack_top_holds_ret_addr (int bci);
2005 // void compute_ret_adr_at_TOS ();
2006 // void update_ret_adr_at_TOS (int bci, int delta);
2007
2008 String stateVecToString (CellTypeStateList vec, int len) {
2009 for (int i = 0; i < len; i++) {
2010 _state_vec_buf[i] = vec.get(i).toChar();
2011 }
2012 return new String(_state_vec_buf, 0, len);
2013 }
2014
2015 // Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instuction
2016 // is a control transfer, then calls the jmpFct all possible destinations.
2017 void retJumpTargetsDo (BytecodeStream bcs, JumpClosure closure, int varNo, int[] data) {
2018 CellTypeState ra = vars().get(varNo);
2019 if (!ra.isGoodAddress()) {
2020 throw new RuntimeException("ret returns from two jsr subroutines?");
2021 }
2022 int target = ra.getInfo();
2023
2024 RetTableEntry rtEnt = _rt.findJsrsForTarget(target);
2025 int bci = bcs.bci();
2026 for (int i = 0; i < rtEnt.nofJsrs(); i++) {
2027 int target_bci = rtEnt.jsrs(i);
2028 // Make sure a jrtRet does not set the changed bit for dead basicblock.
2029 BasicBlock jsr_bb = getBasicBlockContaining(target_bci - 1);
2030 if (Assert.ASSERTS_ENABLED) {
2031 BasicBlock target_bb = _basic_blocks[1 + bbIndex(jsr_bb)];
2032 Assert.that(target_bb == getBasicBlockAt(target_bci), "wrong calc. of successor basicblock");
2033 }
2034 boolean alive = jsr_bb.isAlive();
2035 // if (TraceNewOopMapGeneration) {
2036 // tty.print("pc = %d, ret . %d alive: %s\n", bci, target_bci, alive ? "true" : "false");
2037 // }
2038 if (alive) {
2039 closure.process(this, target_bci, data);
2040 }
2041 }
2042 }
2043
2044 /** If the current instruction in "c" has no effect on control flow,
2045 returns "true". Otherwise, calls "closure.process()" one or
2046 more times, with "c", an appropriate "pcDelta", and "data" as
2047 arguments, then returns "false". There is one exception: if the
2048 current instruction is a "ret", returns "false" without calling
2049 "jmpFct". Arrangements for tracking the control flow of a "ret"
2050 must be made externally. */
2051 boolean jumpTargetsDo (BytecodeStream bcs, JumpClosure closure, int[] data) {
2052 int bci = bcs.bci();
2053
2054 switch (bcs.code()) {
2055 case Bytecodes._ifeq:
2056 case Bytecodes._ifne:
2057 case Bytecodes._iflt:
2058 case Bytecodes._ifge:
2059 case Bytecodes._ifgt:
2060 case Bytecodes._ifle:
2061 case Bytecodes._if_icmpeq:
2062 case Bytecodes._if_icmpne:
2063 case Bytecodes._if_icmplt:
2064 case Bytecodes._if_icmpge:
2065 case Bytecodes._if_icmpgt:
2066 case Bytecodes._if_icmple:
2067 case Bytecodes._if_acmpeq:
2068 case Bytecodes._if_acmpne:
2069 case Bytecodes._ifnull:
2070 case Bytecodes._ifnonnull:
2071 closure.process(this, bcs.dest(), data);
2072 closure.process(this, bci + 3, data);
2073 break;
2074
2075 case Bytecodes._goto:
2076 closure.process(this, bcs.dest(), data);
2077 break;
2078 case Bytecodes._goto_w:
2079 closure.process(this, bcs.dest_w(), data);
2080 break;
2081 case Bytecodes._tableswitch:
2082 {
2083 BytecodeTableswitch tableswitch = BytecodeTableswitch.at(bcs);
2084 int len = tableswitch.length();
2085
2086 closure.process(this, bci + tableswitch.defaultOffset(), data); /* Default. jump address */
2087 while (--len >= 0) {
2088 closure.process(this, bci + tableswitch.destOffsetAt(len), data);
2089 }
2090 break;
2091 }
2092
2093 case Bytecodes._fast_linearswitch: // Java opcodes
2094 case Bytecodes._fast_binaryswitch: // get_int_table handles conversions
2095 case Bytecodes._lookupswitch:
2096 {
2097 BytecodeLookupswitch lookupswitch = BytecodeLookupswitch.at(bcs);
2098 int npairs = lookupswitch.numberOfPairs();
2099 closure.process(this, bci + lookupswitch.defaultOffset(), data); /* Default. */
2100 while(--npairs >= 0) {
2101 LookupswitchPair pair = lookupswitch.pairAt(npairs);
2102 closure.process(this, bci + pair.offset(), data);
2103 }
2104 break;
2105 }
2106 case Bytecodes._jsr:
2107 Assert.that(bcs.isWide()==false, "sanity check");
2108 closure.process(this, bcs.dest(), data);
2109 break;
2110 case Bytecodes._jsr_w:
2111 closure.process(this, bcs.dest_w(), data);
2112 break;
2113 case Bytecodes._wide:
2114 throw new RuntimeException("Should not reach here");
2115 case Bytecodes._athrow:
2116 case Bytecodes._ireturn:
2117 case Bytecodes._lreturn:
2118 case Bytecodes._freturn:
2119 case Bytecodes._dreturn:
2120 case Bytecodes._areturn:
2121 case Bytecodes._return:
2122 case Bytecodes._ret:
2123 break;
2124 default:
2125 return true;
2126 }
2127 return false;
2128 }
2129
2130 // Monitor matching
2131 // int fill_out_arrays (int *enter, int *exit, int max);
2132
2133 // friend class RelocCallback;
2134
2135 //----------------------------------------------------------------------
2136 // Public routines for GenerateOopMap
2137 //
2138 public GenerateOopMap(Method method) {
2139 // We have to initialize all variables here, that can be queried direcly
2140 _method = method;
2141 _max_locals=0;
2142 _init_vars = null;
2143 _rt = new RetTable();
2144 }
2145
2146
2147 // Compute the map.
2148 public void computeMap() {
2149 if (DEBUG) {
2150 System.err.println("*** GenerateOopMap: computing for " +
2151 method().getMethodHolder().getName().asString() + "." +
2152 method().getName().asString() +
2153 method().getSignature().asString());
2154 }
2155
2156 // Initialize values
2157 _got_error = false;
2158 _conflict = false;
2159 _max_locals = (int) method().getMaxLocals();
2160 _max_stack = (int) method().getMaxStack();
2161 _has_exceptions = (method().getExceptionTable().getLength() > 0);
2162 _nof_refval_conflicts = 0;
2163 _init_vars = new ArrayList(5); // There are seldom more than 5 init_vars
2164 _report_result = false;
2165 _report_result_for_send = false;
2166 _report_for_exit_bci = -1;
2167 _new_var_map = null;
2168 // _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number;
2169 // _did_rewriting = false;
2170 // _did_relocation = false;
2171
2172 // FIXME: remove
2173 /*
2174 if (TraceNewOopMapGeneration) {
2175 tty.print("Method name: %s\n", method().name().as_C_string());
2176 if (Verbose) {
2177 _method.print_codes();
2178 tty.print_cr("Exception table:");
2179 typeArrayOop excps = method().exception_table();
2180 for(int i = 0; i < excps.length(); i += 4) {
2181 tty.print_cr("[%d - %d] . %d", excps.int_at(i + 0), excps.int_at(i + 1), excps.int_at(i + 2));
2182 }
2183 }
2184 }
2185 */
2186
2187 // if no code - do nothing
2188 // compiler needs info
2189 if (method().getCodeSize() == 0 || _max_locals + method().getMaxStack() == 0) {
2190 fillStackmapProlog(0);
2191 fillStackmapEpilog();
2192 return;
2193 }
2194 // Step 1: Compute all jump targets and their return value
2195 if (!_got_error)
2196 _rt.computeRetTable(_method);
2197
2198 // Step 2: Find all basic blocks and count GC points
2199 if (!_got_error)
2200 markBBHeadersAndCountGCPoints();
2201
2202 // Step 3: Calculate stack maps
2203 if (!_got_error)
2204 doInterpretation();
2205
2206 // Step 4:Return results
2207 if (!_got_error && reportResults())
2208 reportResult();
2209
2210 if (_got_error) {
2211 // We could expand this code to throw somekind of exception (e.g., VerifyException). However,
2212 // an exception thrown in this part of the code is likly to mean that we are executing some
2213 // illegal bytecodes (that the verifier should have caught if turned on), so we will just exit
2214 // with a fatal.
2215 throw new RuntimeException("Illegal bytecode sequence encountered while generating interpreter pointer maps - method should be rejected by verifier.");
2216 }
2217 }
2218
2219 // Do a callback on fill_stackmap_for_opcodes for basicblock containing bci
2220 public void resultForBasicblock(int bci) {
2221 // FIXME: remove
2222 // if (TraceNewOopMapGeneration) tty.print_cr("Report result pass for basicblock");
2223
2224 // We now want to report the result of the parse
2225 _report_result = true;
2226
2227 // Find basicblock and report results
2228 BasicBlock bb = getBasicBlockContaining(bci);
2229 if (Assert.ASSERTS_ENABLED) {
2230 Assert.that(bb.isReachable(), "getting result from unreachable basicblock");
2231 }
2232 bb.setChanged(true);
2233 interpBB(bb);
2234 }
2235
2236 // Query
2237 public int maxLocals() { return _max_locals; }
2238 public Method method() { return _method; }
2239
2240 // bool did_rewriting() { return _did_rewriting; }
2241 // bool did_relocation() { return _did_relocation; }
2242
2243 // static void print_time();
2244
2245 // Monitor query
2246 public boolean monitorSafe() { return _monitor_safe; }
2247 // Takes as input the bci of a monitorexit bytecode.
2248 // Returns the bci of the corresponding monitorenter.
2249 // Can only be called safely after computeMap() is run.
2250 public int getMonitorMatch(int bci) {
2251 if (Assert.ASSERTS_ENABLED) {
2252 Assert.that(_monitor_safe, "Attempt to match monitor in broken code.");
2253 }
2254
2255 // if (TraceNewOopMapGeneration)
2256 // tty.print_cr("Report monitor match for bci : %d", bci);
2257
2258 // We want to report the line number of the monitorenter.
2259 _report_for_exit_bci = bci;
2260 _matching_enter_bci = -1;
2261
2262 // Find basicblock and report results
2263 BasicBlock bb = getBasicBlockContaining(bci);
2264 if (bb.isReachable()) {
2265 bb.setChanged(true);
2266 interpBB(bb);
2267 _report_for_exit_bci = -1;
2268 if (Assert.ASSERTS_ENABLED) {
2269 Assert.that(_matching_enter_bci != -1, "monitor matching invariant");
2270 }
2271 }
2272 return _matching_enter_bci;
2273 }
2274
2275 // Returns a Arena allocated object that contains pairing info.
2276 // MonitorPairs* get_pairing(Arena *arena);
2277
2278 // copies monitor pairing info into area; area_count specifies maximum
2279 // possible number of monitor pairs
2280 // int copy_pairing(int pair_count, MonitorPairs* pairs);
2281
2282 private int bbIndex(BasicBlock bb) {
2283 for (int i = 0; i < _basic_blocks.length; i++) {
2284 if (_basic_blocks[i] == bb) {
2285 return i;
2286 }
2287 }
2288 throw new RuntimeException("Should have found block");
2289 }
2290
2291 //----------------------------------------------------------------------
2292 // Specialization methods. Intended use:
2293 // - possibleGCPoint must return true for every bci for which the
2294 // stackmaps must be returned
2295 // - fillStackmapProlog is called just before the result is
2296 // reported. The arguments tells the estimated number of gc points
2297 // - fillStackmapForOpcodes is called once for each bytecode index
2298 // in order (0...code_length-1)
2299 // - fillStackmapEpilog is called after all results has been
2300 // reported. Note: Since the algorithm does not report stackmaps for
2301 // deadcode, fewer gc_points might have been encounted than assumed
2302 // during the epilog. It is the responsibility of the subclass to
2303 // count the correct number.
2304 // - fillInitVars are called once with the result of the init_vars
2305 // computation
2306 //
2307 // All these methods are used during a call to computeMap. Note:
2308 // None of the return results are valid after computeMap returns,
2309 // since all values are allocated as resource objects.
2310 //
2311 // All virtual method must be implemented in subclasses
2312 public boolean allowRewrites () { return false; }
2313 public boolean reportResults () { return true; }
2314 public boolean reportInitVars () { return true; }
2315 public boolean possibleGCPoint (BytecodeStream bcs) { throw new RuntimeException("ShouldNotReachHere"); }
2316 public void fillStackmapProlog (int nofGCPoints) { throw new RuntimeException("ShouldNotReachHere"); }
2317 public void fillStackmapEpilog () { throw new RuntimeException("ShouldNotReachHere"); }
2318 public void fillStackmapForOpcodes (BytecodeStream bcs,
2319 CellTypeStateList vars,
2320 CellTypeStateList stack,
2321 int stackTop) { throw new RuntimeException("ShouldNotReachHere"); }
2322 public void fillInitVars (List/*<Integer>*/ init_vars) { throw new RuntimeException("ShouldNotReachHere"); }
2323 }