comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2611:bd235cb4375a

FrameState cleanup: split into FrameStateBuilder and fixed-size FrameState, removed MutableFrameState
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 06 May 2011 17:08:00 +0200
parents 01c5c0443158
children 2523de4d378e
comparison
equal deleted inserted replaced
2610:39aa89baa165 2611:bd235cb4375a
79 NoSafepoints; 79 NoSafepoints;
80 80
81 public final int mask = 1 << ordinal(); 81 public final int mask = 1 << ordinal();
82 } 82 }
83 83
84 final IR ir; 84 private final IR ir;
85 final C1XCompilation compilation; 85 private final C1XCompilation compilation;
86 final CiStatistics stats; 86 private final CiStatistics stats;
87 87
88 /** 88 /**
89 * Map used to implement local value numbering for the current block. 89 * Map used to implement local value numbering for the current block.
90 */ 90 */
91 final ValueMap localValueMap; 91 private final ValueMap localValueMap;
92 92
93 /** 93 /**
94 * Map used for local load elimination (i.e. within the current block). 94 * Map used for local load elimination (i.e. within the current block).
95 */ 95 */
96 final MemoryMap memoryMap; 96 private final MemoryMap memoryMap;
97 97
98 final BytecodeStream stream; // the bytecode stream 98 private final BytecodeStream stream; // the bytecode stream
99 // bci-to-block mapping 99 // bci-to-block mapping
100 BlockMap blockMap; 100 private BlockMap blockMap;
101 101
102 // the constant pool 102 // the constant pool
103 final RiConstantPool constantPool; 103 private final RiConstantPool constantPool;
104 104
105 // the worklist of blocks, managed like a sorted list 105 // the worklist of blocks, managed like a sorted list
106 BlockBegin[] workList; 106 private BlockBegin[] workList;
107 107
108 // the current position in the worklist 108 // the current position in the worklist
109 int workListIndex; 109 private int workListIndex;
110 110
111 /** 111 /**
112 * Mask of {@link Flag} values. 112 * Mask of {@link Flag} values.
113 */ 113 */
114 int flags; 114 private int flags;
115 115
116 // Exception handler list 116 // Exception handler list
117 List<ExceptionHandler> exceptionHandlers; 117 private List<ExceptionHandler> exceptionHandlers;
118 118
119 BlockBegin curBlock; // the current block 119 private BlockBegin curBlock; // the current block
120 MutableFrameState curState; // the current execution state 120 private FrameStateBuilder frameState; // the current execution state
121 Instruction lastInstr; // the last instruction added 121 private Instruction lastInstr; // the last instruction added
122 final LogStream log; 122 private final LogStream log;
123 123
124 boolean skipBlock; // skip processing of the rest of this block 124 private boolean skipBlock; // skip processing of the rest of this block
125 private Value rootMethodSynchronizedObject; 125 private Value rootMethodSynchronizedObject;
126 126
127 private final Graph graph; 127 private final Graph graph;
128 128
129 /** 129 /**
141 this.localValueMap = C1XOptions.OptLocalValueNumbering ? new ValueMap() : null; 141 this.localValueMap = C1XOptions.OptLocalValueNumbering ? new ValueMap() : null;
142 log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; 142 log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
143 stream = new BytecodeStream(compilation.method.code()); 143 stream = new BytecodeStream(compilation.method.code());
144 constantPool = compilation.runtime.getConstantPool(compilation.method); 144 constantPool = compilation.runtime.getConstantPool(compilation.method);
145 this.graph = graph; 145 this.graph = graph;
146 this.frameState = new FrameStateBuilder(compilation.method, graph);
146 } 147 }
147 148
148 /** 149 /**
149 * Builds the graph for a the specified {@code IRScope}. 150 * Builds the graph for a the specified {@code IRScope}.
150 * @param scope the top IRScope 151 * @param scope the top IRScope
179 exceptionHandlers.add(h); 180 exceptionHandlers.add(h);
180 } 181 }
181 flags |= Flag.HasHandler.mask; 182 flags |= Flag.HasHandler.mask;
182 } 183 }
183 184
184 MutableFrameState initialState = stateAtEntry(rootMethod); 185 FrameState initialState = frameState.create(-1);
185 startBlock.mergeOrClone(initialState, rootMethod); 186 startBlock.mergeOrClone(initialState, rootMethod);
186 BlockBegin syncHandler = null; 187 BlockBegin syncHandler = null;
187 188
188 // 3. setup internal state for appending instructions 189 // 3. setup internal state for appending instructions
189 curBlock = startBlock; 190 curBlock = startBlock;
190 lastInstr = startBlock; 191 lastInstr = startBlock;
191 lastInstr.appendNext(null, -1); 192 lastInstr.appendNext(null, -1);
192 curState = initialState;
193 193
194 if (isSynchronized(rootMethod.accessFlags())) { 194 if (isSynchronized(rootMethod.accessFlags())) {
195 // 4A.1 add a monitor enter to the start block 195 // 4A.1 add a monitor enter to the start block
196 rootMethodSynchronizedObject = synchronizedObject(initialState, compilation.method); 196 rootMethodSynchronizedObject = synchronizedObject(initialState, compilation.method);
197 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); 197 genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
226 226
227 private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry) { 227 private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry) {
228 assert curBlock == startBlock; 228 assert curBlock == startBlock;
229 Base base = new Base(stdEntry, graph); 229 Base base = new Base(stdEntry, graph);
230 appendWithoutOptimization(base, 0); 230 appendWithoutOptimization(base, 0);
231 FrameState stateAfter = curState.immutableCopy(bci()); 231 FrameState stateAfter = frameState.create(bci());
232 base.setStateAfter(stateAfter); 232 base.setStateAfter(stateAfter);
233 startBlock.setEnd(base); 233 startBlock.setEnd(base);
234 assert stdEntry.stateBefore() == null; 234 assert stdEntry.stateBefore() == null;
235 stdEntry.mergeOrClone(stateAfter, method()); 235 stdEntry.mergeOrClone(stateAfter, method());
236 } 236 }
250 public int nextBCI() { 250 public int nextBCI() {
251 return stream.nextBCI(); 251 return stream.nextBCI();
252 } 252 }
253 253
254 private void ipush(Value x) { 254 private void ipush(Value x) {
255 curState.ipush(x); 255 frameState.ipush(x);
256 } 256 }
257 257
258 private void lpush(Value x) { 258 private void lpush(Value x) {
259 curState.lpush(x); 259 frameState.lpush(x);
260 } 260 }
261 261
262 private void fpush(Value x) { 262 private void fpush(Value x) {
263 curState.fpush(x); 263 frameState.fpush(x);
264 } 264 }
265 265
266 private void dpush(Value x) { 266 private void dpush(Value x) {
267 curState.dpush(x); 267 frameState.dpush(x);
268 } 268 }
269 269
270 private void apush(Value x) { 270 private void apush(Value x) {
271 curState.apush(x); 271 frameState.apush(x);
272 } 272 }
273 273
274 private void wpush(Value x) { 274 private void wpush(Value x) {
275 curState.wpush(x); 275 frameState.wpush(x);
276 } 276 }
277 277
278 private void push(CiKind kind, Value x) { 278 private void push(CiKind kind, Value x) {
279 curState.push(kind, x); 279 frameState.push(kind, x);
280 } 280 }
281 281
282 private void pushReturn(CiKind kind, Value x) { 282 private void pushReturn(CiKind kind, Value x) {
283 if (kind != CiKind.Void) { 283 if (kind != CiKind.Void) {
284 curState.push(kind.stackKind(), x); 284 frameState.push(kind.stackKind(), x);
285 } 285 }
286 } 286 }
287 287
288 private Value ipop() { 288 private Value ipop() {
289 return curState.ipop(); 289 return frameState.ipop();
290 } 290 }
291 291
292 private Value lpop() { 292 private Value lpop() {
293 return curState.lpop(); 293 return frameState.lpop();
294 } 294 }
295 295
296 private Value fpop() { 296 private Value fpop() {
297 return curState.fpop(); 297 return frameState.fpop();
298 } 298 }
299 299
300 private Value dpop() { 300 private Value dpop() {
301 return curState.dpop(); 301 return frameState.dpop();
302 } 302 }
303 303
304 private Value apop() { 304 private Value apop() {
305 return curState.apop(); 305 return frameState.apop();
306 } 306 }
307 307
308 private Value wpop() { 308 private Value wpop() {
309 return curState.wpop(); 309 return frameState.wpop();
310 } 310 }
311 311
312 private Value pop(CiKind kind) { 312 private Value pop(CiKind kind) {
313 return curState.pop(kind); 313 return frameState.pop(kind);
314 } 314 }
315 315
316 private CiKind peekKind() { 316 private CiKind peekKind() {
317 Value top = curState.stackAt(curState.stackSize() - 1); 317 Value top = frameState.stackAt(frameState.stackSize() - 1);
318 if (top == null) { 318 if (top == null) {
319 top = curState.stackAt(curState.stackSize() - 2); 319 top = frameState.stackAt(frameState.stackSize() - 2);
320 assert top != null; 320 assert top != null;
321 assert top.kind.isDoubleWord(); 321 assert top.kind.isDoubleWord();
322 } 322 }
323 return top.kind; 323 return top.kind;
324 } 324 }
325 325
326 private void loadLocal(int index, CiKind kind) { 326 private void loadLocal(int index, CiKind kind) {
327 push(kind, curState.loadLocal(index)); 327 push(kind, frameState.loadLocal(index));
328 } 328 }
329 329
330 private void storeLocal(CiKind kind, int index) { 330 private void storeLocal(CiKind kind, int index) {
331 curState.storeLocal(index, pop(kind)); 331 frameState.storeLocal(index, pop(kind));
332 } 332 }
333 333
334 List<ExceptionHandler> handleException(Instruction x, int bci) { 334 List<ExceptionHandler> handleException(Instruction x, int bci) {
335 if (!hasHandler()) { 335 if (!hasHandler()) {
336 return Util.uncheckedCast(Collections.EMPTY_LIST); 336 return Util.uncheckedCast(Collections.EMPTY_LIST);
378 378
379 assert entry.bci() == handler.handler.handlerBCI(); 379 assert entry.bci() == handler.handler.handlerBCI();
380 assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:" + curState.locksSize() + " entry:" + entryState.locksSize(); 380 assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:" + curState.locksSize() + " entry:" + entryState.locksSize();
381 381
382 // exception handler starts with an empty expression stack 382 // exception handler starts with an empty expression stack
383 curState = curState.immutableCopyWithEmptyStack(); 383 curState = curState.copyWithEmptyStack();
384 384
385 entry.mergeOrClone(curState, method()); 385 entry.mergeOrClone(curState, method());
386 386
387 // add current state for correct handling of phi functions 387 // add current state for correct handling of phi functions
388 int phiOperand = entry.addExceptionState(curState); 388 int phiOperand = entry.addExceptionState(curState);
433 throw new Error("lookupConstant returned an object of incorrect type"); 433 throw new Error("lookupConstant returned an object of incorrect type");
434 } 434 }
435 } 435 }
436 436
437 void genLoadIndexed(CiKind kind) { 437 void genLoadIndexed(CiKind kind) {
438 FrameState stateBefore = curState.immutableCopy(bci()); 438 FrameState stateBefore = frameState.create(bci());
439 Value index = ipop(); 439 Value index = ipop();
440 Value array = apop(); 440 Value array = apop();
441 Value length = null; 441 Value length = null;
442 if (cseArrayLength(array)) { 442 if (cseArrayLength(array)) {
443 length = append(new ArrayLength(array, stateBefore, graph)); 443 length = append(new ArrayLength(array, stateBefore, graph));
445 Value v = append(new LoadIndexed(array, index, length, kind, stateBefore, graph)); 445 Value v = append(new LoadIndexed(array, index, length, kind, stateBefore, graph));
446 push(kind.stackKind(), v); 446 push(kind.stackKind(), v);
447 } 447 }
448 448
449 void genStoreIndexed(CiKind kind) { 449 void genStoreIndexed(CiKind kind) {
450 FrameState stateBefore = curState.immutableCopy(bci()); 450 FrameState stateBefore = frameState.create(bci());
451 Value value = pop(kind.stackKind()); 451 Value value = pop(kind.stackKind());
452 Value index = ipop(); 452 Value index = ipop();
453 Value array = apop(); 453 Value array = apop();
454 Value length = null; 454 Value length = null;
455 if (cseArrayLength(array)) { 455 if (cseArrayLength(array)) {
463 } 463 }
464 464
465 void stackOp(int opcode) { 465 void stackOp(int opcode) {
466 switch (opcode) { 466 switch (opcode) {
467 case POP: { 467 case POP: {
468 curState.xpop(); 468 frameState.xpop();
469 break; 469 break;
470 } 470 }
471 case POP2: { 471 case POP2: {
472 curState.xpop(); 472 frameState.xpop();
473 curState.xpop(); 473 frameState.xpop();
474 break; 474 break;
475 } 475 }
476 case DUP: { 476 case DUP: {
477 Value w = curState.xpop(); 477 Value w = frameState.xpop();
478 curState.xpush(w); 478 frameState.xpush(w);
479 curState.xpush(w); 479 frameState.xpush(w);
480 break; 480 break;
481 } 481 }
482 case DUP_X1: { 482 case DUP_X1: {
483 Value w1 = curState.xpop(); 483 Value w1 = frameState.xpop();
484 Value w2 = curState.xpop(); 484 Value w2 = frameState.xpop();
485 curState.xpush(w1); 485 frameState.xpush(w1);
486 curState.xpush(w2); 486 frameState.xpush(w2);
487 curState.xpush(w1); 487 frameState.xpush(w1);
488 break; 488 break;
489 } 489 }
490 case DUP_X2: { 490 case DUP_X2: {
491 Value w1 = curState.xpop(); 491 Value w1 = frameState.xpop();
492 Value w2 = curState.xpop(); 492 Value w2 = frameState.xpop();
493 Value w3 = curState.xpop(); 493 Value w3 = frameState.xpop();
494 curState.xpush(w1); 494 frameState.xpush(w1);
495 curState.xpush(w3); 495 frameState.xpush(w3);
496 curState.xpush(w2); 496 frameState.xpush(w2);
497 curState.xpush(w1); 497 frameState.xpush(w1);
498 break; 498 break;
499 } 499 }
500 case DUP2: { 500 case DUP2: {
501 Value w1 = curState.xpop(); 501 Value w1 = frameState.xpop();
502 Value w2 = curState.xpop(); 502 Value w2 = frameState.xpop();
503 curState.xpush(w2); 503 frameState.xpush(w2);
504 curState.xpush(w1); 504 frameState.xpush(w1);
505 curState.xpush(w2); 505 frameState.xpush(w2);
506 curState.xpush(w1); 506 frameState.xpush(w1);
507 break; 507 break;
508 } 508 }
509 case DUP2_X1: { 509 case DUP2_X1: {
510 Value w1 = curState.xpop(); 510 Value w1 = frameState.xpop();
511 Value w2 = curState.xpop(); 511 Value w2 = frameState.xpop();
512 Value w3 = curState.xpop(); 512 Value w3 = frameState.xpop();
513 curState.xpush(w2); 513 frameState.xpush(w2);
514 curState.xpush(w1); 514 frameState.xpush(w1);
515 curState.xpush(w3); 515 frameState.xpush(w3);
516 curState.xpush(w2); 516 frameState.xpush(w2);
517 curState.xpush(w1); 517 frameState.xpush(w1);
518 break; 518 break;
519 } 519 }
520 case DUP2_X2: { 520 case DUP2_X2: {
521 Value w1 = curState.xpop(); 521 Value w1 = frameState.xpop();
522 Value w2 = curState.xpop(); 522 Value w2 = frameState.xpop();
523 Value w3 = curState.xpop(); 523 Value w3 = frameState.xpop();
524 Value w4 = curState.xpop(); 524 Value w4 = frameState.xpop();
525 curState.xpush(w2); 525 frameState.xpush(w2);
526 curState.xpush(w1); 526 frameState.xpush(w1);
527 curState.xpush(w4); 527 frameState.xpush(w4);
528 curState.xpush(w3); 528 frameState.xpush(w3);
529 curState.xpush(w2); 529 frameState.xpush(w2);
530 curState.xpush(w1); 530 frameState.xpush(w1);
531 break; 531 break;
532 } 532 }
533 case SWAP: { 533 case SWAP: {
534 Value w1 = curState.xpop(); 534 Value w1 = frameState.xpop();
535 Value w2 = curState.xpop(); 535 Value w2 = frameState.xpop();
536 curState.xpush(w1); 536 frameState.xpush(w1);
537 curState.xpush(w2); 537 frameState.xpush(w2);
538 break; 538 break;
539 } 539 }
540 default: 540 default:
541 throw Util.shouldNotReachHere(); 541 throw Util.shouldNotReachHere();
542 } 542 }
590 } 590 }
591 591
592 void genIncrement() { 592 void genIncrement() {
593 int index = stream().readLocalIndex(); 593 int index = stream().readLocalIndex();
594 int delta = stream().readIncrement(); 594 int delta = stream().readIncrement();
595 Value x = curState.localAt(index); 595 Value x = frameState.localAt(index);
596 Value y = append(Constant.forInt(delta, graph)); 596 Value y = append(Constant.forInt(delta, graph));
597 curState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), null, graph))); 597 frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), null, graph)));
598 } 598 }
599 599
600 void genGoto(int fromBCI, int toBCI) { 600 void genGoto(int fromBCI, int toBCI) {
601 boolean isSafepoint = !noSafepoints() && toBCI <= fromBCI; 601 boolean isSafepoint = !noSafepoints() && toBCI <= fromBCI;
602 append(new Goto(blockAt(toBCI), null, isSafepoint, graph)); 602 append(new Goto(blockAt(toBCI), null, isSafepoint, graph));
610 append(new If(x, cond, y, tsucc, fsucc, isSafepoint ? stateBefore : null, isSafepoint, graph)); 610 append(new If(x, cond, y, tsucc, fsucc, isSafepoint ? stateBefore : null, isSafepoint, graph));
611 } 611 }
612 612
613 void genIfZero(Condition cond) { 613 void genIfZero(Condition cond) {
614 Value y = appendConstant(CiConstant.INT_0); 614 Value y = appendConstant(CiConstant.INT_0);
615 FrameState stateBefore = curState.immutableCopy(bci()); 615 FrameState stateBefore = frameState.create(bci());
616 Value x = ipop(); 616 Value x = ipop();
617 ifNode(x, cond, y, stateBefore); 617 ifNode(x, cond, y, stateBefore);
618 } 618 }
619 619
620 void genIfNull(Condition cond) { 620 void genIfNull(Condition cond) {
621 FrameState stateBefore = curState.immutableCopy(bci()); 621 FrameState stateBefore = frameState.create(bci());
622 Value y = appendConstant(CiConstant.NULL_OBJECT); 622 Value y = appendConstant(CiConstant.NULL_OBJECT);
623 Value x = apop(); 623 Value x = apop();
624 ifNode(x, cond, y, stateBefore); 624 ifNode(x, cond, y, stateBefore);
625 } 625 }
626 626
627 void genIfSame(CiKind kind, Condition cond) { 627 void genIfSame(CiKind kind, Condition cond) {
628 FrameState stateBefore = curState.immutableCopy(bci()); 628 FrameState stateBefore = frameState.create(bci());
629 Value y = pop(kind); 629 Value y = pop(kind);
630 Value x = pop(kind); 630 Value x = pop(kind);
631 ifNode(x, cond, y, stateBefore); 631 ifNode(x, cond, y, stateBefore);
632 } 632 }
633 633
634 void genThrow(int bci) { 634 void genThrow(int bci) {
635 FrameState stateBefore = curState.immutableCopy(bci()); 635 FrameState stateBefore = frameState.create(bci());
636 Throw t = new Throw(apop(), stateBefore, !noSafepoints(), graph); 636 Throw t = new Throw(apop(), stateBefore, !noSafepoints(), graph);
637 appendWithoutOptimization(t, bci); 637 appendWithoutOptimization(t, bci);
638 } 638 }
639 639
640 void genCheckCast() { 640 void genCheckCast() {
663 return; 663 return;
664 } 664 }
665 } 665 }
666 666
667 void genNewInstance(int cpi) { 667 void genNewInstance(int cpi) {
668 FrameState stateBefore = curState.immutableCopy(bci()); 668 FrameState stateBefore = frameState.create(bci());
669 RiType type = constantPool().lookupType(cpi, NEW); 669 RiType type = constantPool().lookupType(cpi, NEW);
670 NewInstance n = new NewInstance(type, cpi, constantPool(), stateBefore, graph); 670 NewInstance n = new NewInstance(type, cpi, constantPool(), stateBefore, graph);
671 if (memoryMap != null) { 671 if (memoryMap != null) {
672 memoryMap.newInstance(n); 672 memoryMap.newInstance(n);
673 } 673 }
674 apush(append(n)); 674 apush(append(n));
675 } 675 }
676 676
677 void genNewTypeArray(int typeCode) { 677 void genNewTypeArray(int typeCode) {
678 FrameState stateBefore = curState.immutableCopy(bci()); 678 FrameState stateBefore = frameState.create(bci());
679 CiKind kind = CiKind.fromArrayTypeCode(typeCode); 679 CiKind kind = CiKind.fromArrayTypeCode(typeCode);
680 RiType elementType = compilation.runtime.asRiType(kind); 680 RiType elementType = compilation.runtime.asRiType(kind);
681 apush(append(new NewTypeArray(ipop(), elementType, stateBefore, graph))); 681 apush(append(new NewTypeArray(ipop(), elementType, stateBefore, graph)));
682 } 682 }
683 683
684 void genNewObjectArray(int cpi) { 684 void genNewObjectArray(int cpi) {
685 RiType type = constantPool().lookupType(cpi, ANEWARRAY); 685 RiType type = constantPool().lookupType(cpi, ANEWARRAY);
686 FrameState stateBefore = curState.immutableCopy(bci()); 686 FrameState stateBefore = frameState.create(bci());
687 NewArray n = new NewObjectArray(type, ipop(), stateBefore, graph); 687 NewArray n = new NewObjectArray(type, ipop(), stateBefore, graph);
688 apush(append(n)); 688 apush(append(n));
689 } 689 }
690 690
691 void genNewMultiArray(int cpi) { 691 void genNewMultiArray(int cpi) {
692 RiType type = constantPool().lookupType(cpi, MULTIANEWARRAY); 692 RiType type = constantPool().lookupType(cpi, MULTIANEWARRAY);
693 FrameState stateBefore = curState.immutableCopy(bci()); 693 FrameState stateBefore = frameState.create(bci());
694 int rank = stream().readUByte(bci() + 3); 694 int rank = stream().readUByte(bci() + 3);
695 Value[] dims = new Value[rank]; 695 Value[] dims = new Value[rank];
696 for (int i = rank - 1; i >= 0; i--) { 696 for (int i = rank - 1; i >= 0; i--) {
697 dims[i] = ipop(); 697 dims[i] = ipop();
698 } 698 }
700 apush(append(n)); 700 apush(append(n));
701 } 701 }
702 702
703 void genGetField(int cpi, RiField field) { 703 void genGetField(int cpi, RiField field) {
704 // Must copy the state here, because the field holder must still be on the stack. 704 // Must copy the state here, because the field holder must still be on the stack.
705 FrameState stateBefore = curState.immutableCopy(bci()); 705 FrameState stateBefore = frameState.create(bci());
706 LoadField load = new LoadField(apop(), field, stateBefore, graph); 706 LoadField load = new LoadField(apop(), field, stateBefore, graph);
707 appendOptimizedLoadField(field.kind(), load); 707 appendOptimizedLoadField(field.kind(), load);
708 } 708 }
709 709
710 void genPutField(int cpi, RiField field) { 710 void genPutField(int cpi, RiField field) {
711 // Must copy the state here, because the field holder must still be on the stack. 711 // Must copy the state here, because the field holder must still be on the stack.
712 FrameState stateBefore = curState.immutableCopy(bci()); 712 FrameState stateBefore = frameState.create(bci());
713 Value value = pop(field.kind().stackKind()); 713 Value value = pop(field.kind().stackKind());
714 appendOptimizedStoreField(new StoreField(apop(), field, value, stateBefore, graph)); 714 appendOptimizedStoreField(new StoreField(apop(), field, value, stateBefore, graph));
715 } 715 }
716 716
717 void genGetStatic(int cpi, RiField field) { 717 void genGetStatic(int cpi, RiField field) {
785 // the result of resolution is not used by the invocation (only the side effect 785 // the result of resolution is not used by the invocation (only the side effect
786 // of initialization is required), it can be commoned with static field accesses. 786 // of initialization is required), it can be commoned with static field accesses.
787 genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi); 787 genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi);
788 } 788 }
789 789
790 Value[] args = curState.popArguments(target.signature().argumentSlots(false)); 790 Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
791 appendInvoke(INVOKESTATIC, target, args, cpi, constantPool); 791 appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
792 } 792 }
793 793
794 void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) { 794 void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
795 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); 795 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
796 796
797 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool); 797 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
798 798
799 } 799 }
800 800
801 void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) { 801 void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
802 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); 802 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
803 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool); 803 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
804 804
805 } 805 }
806 806
807 void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) { 807 void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
808 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); 808 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
809 invokeDirect(target, args, knownHolder, cpi, constantPool); 809 invokeDirect(target, args, knownHolder, cpi, constantPool);
810 810
811 } 811 }
812 812
813 /** 813 /**
965 } 965 }
966 return assumed; 966 return assumed;
967 } 967 }
968 968
969 void callRegisterFinalizer() { 969 void callRegisterFinalizer() {
970 Value receiver = curState.loadLocal(0); 970 Value receiver = frameState.loadLocal(0);
971 RiType declaredType = receiver.declaredType(); 971 RiType declaredType = receiver.declaredType();
972 RiType receiverType = declaredType; 972 RiType receiverType = declaredType;
973 RiType exactType = receiver.exactType(); 973 RiType exactType = receiver.exactType();
974 if (exactType == null && declaredType != null) { 974 if (exactType == null && declaredType != null) {
975 exactType = declaredType.exactType(); 975 exactType = declaredType.exactType();
998 } 998 }
999 } 999 }
1000 1000
1001 if (needsCheck) { 1001 if (needsCheck) {
1002 // append a call to the finalizer registration 1002 // append a call to the finalizer registration
1003 append(new RegisterFinalizer(curState.loadLocal(0), curState.immutableCopy(bci()), graph)); 1003 append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph));
1004 C1XMetrics.InlinedFinalizerChecks++; 1004 C1XMetrics.InlinedFinalizerChecks++;
1005 } 1005 }
1006 } 1006 }
1007 1007
1008 void genReturn(Value x) { 1008 void genReturn(Value x) {
1009 if (method().isConstructor() && method().holder().superType() == null) { 1009 if (method().isConstructor() && method().holder().superType() == null) {
1010 callRegisterFinalizer(); 1010 callRegisterFinalizer();
1011 } 1011 }
1012 1012
1013 curState.truncateStack(0); 1013 frameState.clearStack();
1014 if (Modifier.isSynchronized(method().accessFlags())) { 1014 if (Modifier.isSynchronized(method().accessFlags())) {
1015 FrameState stateBefore = curState.immutableCopy(bci()); 1015 FrameState stateBefore = frameState.create(bci());
1016 // unlock before exiting the method 1016 // unlock before exiting the method
1017 int lockNumber = curState.locksSize() - 1; 1017 int lockNumber = frameState.locksSize() - 1;
1018 MonitorAddress lockAddress = null; 1018 MonitorAddress lockAddress = null;
1019 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 1019 if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
1020 lockAddress = new MonitorAddress(lockNumber, graph); 1020 lockAddress = new MonitorAddress(lockNumber, graph);
1021 append(lockAddress); 1021 append(lockAddress);
1022 } 1022 }
1023 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore, graph)); 1023 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore, graph));
1024 curState.unlock(); 1024 frameState.unlock();
1025 } 1025 }
1026 append(new Return(x, !noSafepoints(), graph)); 1026 append(new Return(x, !noSafepoints(), graph));
1027 } 1027 }
1028 1028
1029 /** 1029 /**
1030 * Gets the number of locks held. 1030 * Gets the number of locks held.
1031 */ 1031 */
1032 private int locksSize() { 1032 private int locksSize() {
1033 return curState.locksSize(); 1033 return frameState.locksSize();
1034 } 1034 }
1035 1035
1036 void genMonitorEnter(Value x, int bci) { 1036 void genMonitorEnter(Value x, int bci) {
1037 int lockNumber = locksSize(); 1037 int lockNumber = locksSize();
1038 MonitorAddress lockAddress = null; 1038 MonitorAddress lockAddress = null;
1040 lockAddress = new MonitorAddress(lockNumber, graph); 1040 lockAddress = new MonitorAddress(lockNumber, graph);
1041 append(lockAddress); 1041 append(lockAddress);
1042 } 1042 }
1043 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, null, graph); 1043 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, null, graph);
1044 appendWithoutOptimization(monitorEnter, bci); 1044 appendWithoutOptimization(monitorEnter, bci);
1045 curState.lock(ir, x, lockNumber + 1); 1045 frameState.lock(ir, x, lockNumber + 1);
1046 monitorEnter.setStateAfter(curState.immutableCopy(bci)); 1046 monitorEnter.setStateAfter(frameState.create(bci));
1047 killMemoryMap(); // prevent any optimizations across synchronization 1047 killMemoryMap(); // prevent any optimizations across synchronization
1048 } 1048 }
1049 1049
1050 void genMonitorExit(Value x, int bci) { 1050 void genMonitorExit(Value x, int bci) {
1051 int lockNumber = curState.locksSize() - 1; 1051 int lockNumber = frameState.locksSize() - 1;
1052 if (lockNumber < 0) { 1052 if (lockNumber < 0) {
1053 throw new CiBailout("monitor stack underflow"); 1053 throw new CiBailout("monitor stack underflow");
1054 } 1054 }
1055 MonitorAddress lockAddress = null; 1055 MonitorAddress lockAddress = null;
1056 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 1056 if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
1057 lockAddress = new MonitorAddress(lockNumber, graph); 1057 lockAddress = new MonitorAddress(lockNumber, graph);
1058 append(lockAddress); 1058 append(lockAddress);
1059 } 1059 }
1060 appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, null, graph), bci); 1060 appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, null, graph), bci);
1061 curState.unlock(); 1061 frameState.unlock();
1062 killMemoryMap(); // prevent any optimizations across synchronization 1062 killMemoryMap(); // prevent any optimizations across synchronization
1063 } 1063 }
1064 1064
1065 void genJsr(int dest) { 1065 void genJsr(int dest) {
1066 throw new CiBailout("jsr/ret not supported"); 1066 throw new CiBailout("jsr/ret not supported");
1084 } 1084 }
1085 int offset = ts.defaultOffset(); 1085 int offset = ts.defaultOffset();
1086 isBackwards |= offset < 0; // if the default successor is backwards 1086 isBackwards |= offset < 0; // if the default successor is backwards
1087 list.add(blockAt(bci + offset)); 1087 list.add(blockAt(bci + offset));
1088 boolean isSafepoint = isBackwards && !noSafepoints(); 1088 boolean isSafepoint = isBackwards && !noSafepoints();
1089 FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null; 1089 FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null;
1090 append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint, graph)); 1090 append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint, graph));
1091 } 1091 }
1092 1092
1093 void genLookupswitch() { 1093 void genLookupswitch() {
1094 int bci = bci(); 1094 int bci = bci();
1106 } 1106 }
1107 int offset = ls.defaultOffset(); 1107 int offset = ls.defaultOffset();
1108 isBackwards |= offset < 0; // if the default successor is backwards 1108 isBackwards |= offset < 0; // if the default successor is backwards
1109 list.add(blockAt(bci + offset)); 1109 list.add(blockAt(bci + offset));
1110 boolean isSafepoint = isBackwards && !noSafepoints(); 1110 boolean isSafepoint = isBackwards && !noSafepoints();
1111 FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null; 1111 FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null;
1112 append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint, graph)); 1112 append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint, graph));
1113 } 1113 }
1114 1114
1115 /** 1115 /**
1116 * Determines whether the length of an array should be extracted out as a separate instruction 1116 * Determines whether the length of an array should be extracted out as a separate instruction
1184 } 1184 }
1185 1185
1186 if (x instanceof StateSplit) { 1186 if (x instanceof StateSplit) {
1187 StateSplit stateSplit = (StateSplit) x; 1187 StateSplit stateSplit = (StateSplit) x;
1188 if (stateSplit.stateBefore() == null) { 1188 if (stateSplit.stateBefore() == null) {
1189 stateSplit.setStateBefore(curState.immutableCopy(bci)); 1189 stateSplit.setStateBefore(frameState.create(bci));
1190 } 1190 }
1191 } 1191 }
1192 1192
1193 if (x.canTrap()) { 1193 if (x.canTrap()) {
1194 // connect the instruction to any exception handlers 1194 // connect the instruction to any exception handlers
1208 1208
1209 private BlockBegin blockAt(int bci) { 1209 private BlockBegin blockAt(int bci) {
1210 BlockBegin result = blockAtOrNull(bci); 1210 BlockBegin result = blockAtOrNull(bci);
1211 assert result != null : "Expected a block to begin at " + bci; 1211 assert result != null : "Expected a block to begin at " + bci;
1212 return result; 1212 return result;
1213 }
1214
1215 MutableFrameState stateAtEntry(RiMethod method) {
1216 MutableFrameState state = new MutableFrameState(-1, method.maxLocals(), method.maxStackSize());
1217 int index = 0;
1218 if (!isStatic(method.accessFlags())) {
1219 // add the receiver and assume it is non null
1220 Local local = new Local(method.holder().kind(), index, graph);
1221 local.setFlag(Value.Flag.NonNull, true);
1222 local.setDeclaredType(method.holder());
1223 state.storeLocal(index, local);
1224 index = 1;
1225 }
1226 RiSignature sig = method.signature();
1227 int max = sig.argumentCount(false);
1228 RiType accessingClass = method.holder();
1229 for (int i = 0; i < max; i++) {
1230 RiType type = sig.argumentTypeAt(i, accessingClass);
1231 CiKind kind = type.kind().stackKind();
1232 Local local = new Local(kind, index, graph);
1233 if (type.isResolved()) {
1234 local.setDeclaredType(type);
1235 }
1236 state.storeLocal(index, local);
1237 index += kind.sizeInSlots();
1238 }
1239 return state;
1240 } 1213 }
1241 1214
1242 private Value synchronizedObject(FrameState curState2, RiMethod target) { 1215 private Value synchronizedObject(FrameState curState2, RiMethod target) {
1243 if (isStatic(target.accessFlags())) { 1216 if (isStatic(target.accessFlags())) {
1244 Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph); 1217 Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph);
1248 } 1221 }
1249 } 1222 }
1250 1223
1251 private void fillSyncHandler(Value lock, BlockBegin syncHandler) { 1224 private void fillSyncHandler(Value lock, BlockBegin syncHandler) {
1252 BlockBegin origBlock = curBlock; 1225 BlockBegin origBlock = curBlock;
1253 MutableFrameState origState = curState; 1226 FrameState origState = frameState.create(-1);
1254 Instruction origLast = lastInstr; 1227 Instruction origLast = lastInstr;
1255 1228
1256 lastInstr = curBlock = syncHandler; 1229 lastInstr = curBlock = syncHandler;
1257 while (lastInstr.next() != null) { 1230 while (lastInstr.next() != null) {
1258 // go forward to the end of the block 1231 // go forward to the end of the block
1259 lastInstr = lastInstr.next(); 1232 lastInstr = lastInstr.next();
1260 } 1233 }
1261 curState = syncHandler.stateBefore().copy(); 1234 frameState.initializeFrom(syncHandler.stateBefore());
1262 1235
1263 int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI; 1236 int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
1264 Value exception = appendWithoutOptimization(new ExceptionObject(curState.immutableCopy(bci), graph), bci); 1237 Value exception = appendWithoutOptimization(new ExceptionObject(frameState.create(bci), graph), bci);
1265 1238
1266 assert lock != null; 1239 assert lock != null;
1267 assert curState.locksSize() > 0 && curState.lockAt(locksSize() - 1) == lock; 1240 assert frameState.locksSize() > 0 && frameState.lockAt(locksSize() - 1) == lock;
1268 if (lock instanceof Instruction) { 1241 if (lock instanceof Instruction) {
1269 Instruction l = (Instruction) lock; 1242 Instruction l = (Instruction) lock;
1270 if (!l.isAppended()) { 1243 if (!l.isAppended()) {
1271 lock = appendWithoutOptimization(l, Instruction.SYNCHRONIZATION_ENTRY_BCI); 1244 lock = appendWithoutOptimization(l, Instruction.SYNCHRONIZATION_ENTRY_BCI);
1272 } 1245 }
1276 1249
1277 apush(exception); 1250 apush(exception);
1278 genThrow(bci); 1251 genThrow(bci);
1279 BlockEnd end = (BlockEnd) lastInstr; 1252 BlockEnd end = (BlockEnd) lastInstr;
1280 curBlock.setEnd(end); 1253 curBlock.setEnd(end);
1281 end.setStateAfter(curState.immutableCopy(bci())); 1254 end.setStateAfter(frameState.create(bci()));
1282 1255
1283 curBlock = origBlock; 1256 curBlock = origBlock;
1284 curState = origState; 1257 frameState.initializeFrom(origState);
1285 lastInstr = origLast; 1258 lastInstr = origLast;
1286 } 1259 }
1287 1260
1288 private void iterateAllBlocks() { 1261 private void iterateAllBlocks() {
1289 BlockBegin b; 1262 BlockBegin b;
1291 if (!b.wasVisited()) { 1264 if (!b.wasVisited()) {
1292 b.setWasVisited(true); 1265 b.setWasVisited(true);
1293 // now parse the block 1266 // now parse the block
1294 killMemoryMap(); 1267 killMemoryMap();
1295 curBlock = b; 1268 curBlock = b;
1296 curState = b.stateBefore().copy(); 1269 frameState.initializeFrom(b.stateBefore());
1297 lastInstr = b; 1270 lastInstr = b;
1298 b.appendNext(null, -1); 1271 b.appendNext(null, -1);
1299 1272
1300 iterateBytecodesForBlock(b.bci(), false); 1273 iterateBytecodesForBlock(b.bci(), false);
1301 } 1274 }
1302 } 1275 }
1303 } 1276 }
1304 1277
1305 private BlockEnd iterateBytecodesForBlock(int bci, boolean inliningIntoCurrentBlock) { 1278 private BlockEnd iterateBytecodesForBlock(int bci, boolean inliningIntoCurrentBlock) {
1306 skipBlock = false; 1279 skipBlock = false;
1307 assert curState != null; 1280 assert frameState != null;
1308 stream.setBCI(bci); 1281 stream.setBCI(bci);
1309 1282
1310 BlockBegin block = curBlock; 1283 BlockBegin block = curBlock;
1311 BlockEnd end = null; 1284 BlockEnd end = null;
1312 boolean pushException = block.isExceptionEntry() && block.next() == null; 1285 boolean pushException = block.isExceptionEntry() && block.next() == null;
1333 // read the opcode 1306 // read the opcode
1334 int opcode = stream.currentBC(); 1307 int opcode = stream.currentBC();
1335 1308
1336 // push an exception object onto the stack if we are parsing an exception handler 1309 // push an exception object onto the stack if we are parsing an exception handler
1337 if (pushException) { 1310 if (pushException) {
1338 FrameState stateBefore = curState.immutableCopy(bci()); 1311 FrameState stateBefore = frameState.create(bci());
1339 apush(append(new ExceptionObject(stateBefore, graph))); 1312 apush(append(new ExceptionObject(stateBefore, graph)));
1340 pushException = false; 1313 pushException = false;
1341 } 1314 }
1342 1315
1343 traceState(); 1316 traceState();
1361 return (BlockEnd) lastInstr; 1334 return (BlockEnd) lastInstr;
1362 } 1335 }
1363 1336
1364 // if the method terminates, we don't need the stack anymore 1337 // if the method terminates, we don't need the stack anymore
1365 if (end instanceof Return || end instanceof Throw) { 1338 if (end instanceof Return || end instanceof Throw) {
1366 curState.clearStack(); 1339 frameState.clearStack();
1367 } 1340 }
1368 1341
1369 // connect to begin and set state 1342 // connect to begin and set state
1370 // NOTE that inlining may have changed the block we are parsing 1343 // NOTE that inlining may have changed the block we are parsing
1371 assert end != null : "end should exist after iterating over bytecodes"; 1344 assert end != null : "end should exist after iterating over bytecodes";
1372 end.setStateAfter(curState.immutableCopy(bci())); 1345 end.setStateAfter(frameState.create(bci()));
1373 curBlock.setEnd(end); 1346 curBlock.setEnd(end);
1374 // propagate the state 1347 // propagate the state
1375 for (BlockBegin succ : end.blockSuccessors()) { 1348 for (BlockBegin succ : end.blockSuccessors()) {
1376 assert succ.blockPredecessors().contains(curBlock); 1349 assert succ.blockPredecessors().contains(curBlock);
1377 succ.mergeOrClone(end.stateAfter(), method()); 1350 succ.mergeOrClone(end.stateAfter(), method());
1380 return end; 1353 return end;
1381 } 1354 }
1382 1355
1383 private void traceState() { 1356 private void traceState() {
1384 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { 1357 if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) {
1385 log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", curState.localsSize(), curState.stackSize(), method())); 1358 log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method()));
1386 for (int i = 0; i < curState.localsSize(); ++i) { 1359 for (int i = 0; i < frameState.localsSize(); ++i) {
1387 Value value = curState.localAt(i); 1360 Value value = frameState.localAt(i);
1388 log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); 1361 log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1389 } 1362 }
1390 for (int i = 0; i < curState.stackSize(); ++i) { 1363 for (int i = 0; i < frameState.stackSize(); ++i) {
1391 Value value = curState.stackAt(i); 1364 Value value = frameState.stackAt(i);
1392 log.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); 1365 log.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1393 } 1366 }
1394 for (int i = 0; i < curState.locksSize(); ++i) { 1367 for (int i = 0; i < frameState.locksSize(); ++i) {
1395 Value value = curState.lockAt(i); 1368 Value value = frameState.lockAt(i);
1396 log.println(String.format("| lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); 1369 log.println(String.format("| lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value));
1397 } 1370 }
1398 } 1371 }
1399 } 1372 }
1400 1373
1501 case SWAP : stackOp(opcode); break; 1474 case SWAP : stackOp(opcode); break;
1502 case IADD : // fall through 1475 case IADD : // fall through
1503 case ISUB : // fall through 1476 case ISUB : // fall through
1504 case IMUL : genArithmeticOp(CiKind.Int, opcode); break; 1477 case IMUL : genArithmeticOp(CiKind.Int, opcode); break;
1505 case IDIV : // fall through 1478 case IDIV : // fall through
1506 case IREM : genArithmeticOp(CiKind.Int, opcode, curState.immutableCopy(bci())); break; 1479 case IREM : genArithmeticOp(CiKind.Int, opcode, frameState.create(bci())); break;
1507 case LADD : // fall through 1480 case LADD : // fall through
1508 case LSUB : // fall through 1481 case LSUB : // fall through
1509 case LMUL : genArithmeticOp(CiKind.Long, opcode); break; 1482 case LMUL : genArithmeticOp(CiKind.Long, opcode); break;
1510 case LDIV : // fall through 1483 case LDIV : // fall through
1511 case LREM : genArithmeticOp(CiKind.Long, opcode, curState.immutableCopy(bci())); break; 1484 case LREM : genArithmeticOp(CiKind.Long, opcode, frameState.create(bci())); break;
1512 case FADD : // fall through 1485 case FADD : // fall through
1513 case FSUB : // fall through 1486 case FSUB : // fall through
1514 case FMUL : // fall through 1487 case FMUL : // fall through
1515 case FDIV : // fall through 1488 case FDIV : // fall through
1516 case FREM : genArithmeticOp(CiKind.Float, opcode); break; 1489 case FREM : genArithmeticOp(CiKind.Float, opcode); break;
1627 log.println(sb.toString()); 1600 log.println(sb.toString());
1628 } 1601 }
1629 } 1602 }
1630 1603
1631 private void genArrayLength() { 1604 private void genArrayLength() {
1632 FrameState stateBefore = curState.immutableCopy(bci()); 1605 FrameState stateBefore = frameState.create(bci());
1633 ipush(append(new ArrayLength(apop(), stateBefore, graph))); 1606 ipush(append(new ArrayLength(apop(), stateBefore, graph)));
1634 } 1607 }
1635 1608
1636 void killMemoryMap() { 1609 void killMemoryMap() {
1637 if (localValueMap != null) { 1610 if (localValueMap != null) {