comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2628:569228710be8

More FrameState work
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Tue, 10 May 2011 16:49:50 +0200
parents 91d3952f7eb7
children 721a45190d6d
comparison
equal deleted inserted replaced
2623:b129b7da1397 2628:569228710be8
342 342
343 if (con instanceof RiType) { 343 if (con instanceof RiType) {
344 // this is a load of class constant which might be unresolved 344 // this is a load of class constant which might be unresolved
345 RiType riType = (RiType) con; 345 RiType riType = (RiType) con;
346 if (!riType.isResolved() || C1XOptions.TestPatching) { 346 if (!riType.isResolved() || C1XOptions.TestPatching) {
347 frameState.push(CiKind.Object, append(new ResolveClass(riType, RiType.Representation.JavaClass, null, graph))); 347 frameState.push(CiKind.Object, append(new ResolveClass(riType, RiType.Representation.JavaClass, graph)));
348 } else { 348 } else {
349 frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph))); 349 frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
350 } 350 }
351 } else if (con instanceof CiConstant) { 351 } else if (con instanceof CiConstant) {
352 CiConstant constant = (CiConstant) con; 352 CiConstant constant = (CiConstant) con;
355 throw new Error("lookupConstant returned an object of incorrect type"); 355 throw new Error("lookupConstant returned an object of incorrect type");
356 } 356 }
357 } 357 }
358 358
359 void genLoadIndexed(CiKind kind) { 359 void genLoadIndexed(CiKind kind) {
360 FrameState stateBefore = frameState.create(bci());
361 Value index = frameState.ipop(); 360 Value index = frameState.ipop();
362 Value array = frameState.apop(); 361 Value array = frameState.apop();
363 Value length = null; 362 Value length = null;
364 if (cseArrayLength(array)) { 363 if (cseArrayLength(array)) {
365 length = append(new ArrayLength(array, stateBefore, graph)); 364 length = append(new ArrayLength(array, graph));
366 } 365 }
367 Value v = append(new LoadIndexed(array, index, length, kind, stateBefore, graph)); 366 Value v = append(new LoadIndexed(array, index, length, kind, graph));
368 frameState.push(kind.stackKind(), v); 367 frameState.push(kind.stackKind(), v);
369 } 368 }
370 369
371 void genStoreIndexed(CiKind kind) { 370 void genStoreIndexed(CiKind kind) {
372 FrameState stateBefore = frameState.create(bci());
373 Value value = frameState.pop(kind.stackKind()); 371 Value value = frameState.pop(kind.stackKind());
374 Value index = frameState.ipop(); 372 Value index = frameState.ipop();
375 Value array = frameState.apop(); 373 Value array = frameState.apop();
376 Value length = null; 374 Value length = null;
377 if (cseArrayLength(array)) { 375 if (cseArrayLength(array)) {
378 length = append(new ArrayLength(array, stateBefore, graph)); 376 length = append(new ArrayLength(array, graph));
379 } 377 }
380 StoreIndexed result = new StoreIndexed(array, index, length, kind, value, stateBefore, graph); 378 StoreIndexed result = new StoreIndexed(array, index, length, kind, value, graph);
381 append(result); 379 append(result);
382 if (memoryMap != null) { 380 if (memoryMap != null) {
383 memoryMap.storeValue(value); 381 memoryMap.storeValue(value);
384 } 382 }
385 } 383 }
617 frameState.apush(append(n)); 615 frameState.apush(append(n));
618 } 616 }
619 617
620 void genGetField(int cpi, RiField field) { 618 void genGetField(int cpi, RiField field) {
621 // Must copy the state here, because the field holder must still be on the stack. 619 // Must copy the state here, because the field holder must still be on the stack.
622 FrameState stateBefore = frameState.create(bci()); 620 LoadField load = new LoadField(frameState.apop(), field, graph);
623 LoadField load = new LoadField(frameState.apop(), field, stateBefore, graph);
624 appendOptimizedLoadField(field.kind(), load); 621 appendOptimizedLoadField(field.kind(), load);
625 } 622 }
626 623
627 void genPutField(int cpi, RiField field) { 624 void genPutField(int cpi, RiField field) {
628 // Must copy the state here, because the field holder must still be on the stack. 625 // Must copy the state here, because the field holder must still be on the stack.
629 FrameState stateBefore = frameState.create(bci());
630 Value value = frameState.pop(field.kind().stackKind()); 626 Value value = frameState.pop(field.kind().stackKind());
631 appendOptimizedStoreField(new StoreField(frameState.apop(), field, value, stateBefore, graph)); 627 appendOptimizedStoreField(new StoreField(frameState.apop(), field, value, graph));
632 } 628 }
633 629
634 void genGetStatic(int cpi, RiField field) { 630 void genGetStatic(int cpi, RiField field) {
635 RiType holder = field.holder(); 631 RiType holder = field.holder();
636 boolean isInitialized = !C1XOptions.TestPatching && field.isResolved(); 632 boolean isInitialized = !C1XOptions.TestPatching && field.isResolved();
640 } 636 }
641 if (constantValue != null) { 637 if (constantValue != null) {
642 frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue)); 638 frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
643 } else { 639 } else {
644 Value container = genResolveClass(RiType.Representation.StaticFields, holder, field.isResolved(), cpi); 640 Value container = genResolveClass(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
645 LoadField load = new LoadField(container, field, null, graph); 641 LoadField load = new LoadField(container, field, graph);
646 appendOptimizedLoadField(field.kind(), load); 642 appendOptimizedLoadField(field.kind(), load);
647 } 643 }
648 } 644 }
649 645
650 void genPutStatic(int cpi, RiField field) { 646 void genPutStatic(int cpi, RiField field) {
651 RiType holder = field.holder(); 647 RiType holder = field.holder();
652 Value container = genResolveClass(RiType.Representation.StaticFields, holder, field.isResolved(), cpi); 648 Value container = genResolveClass(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
653 Value value = frameState.pop(field.kind().stackKind()); 649 Value value = frameState.pop(field.kind().stackKind());
654 StoreField store = new StoreField(container, field, value, null, graph); 650 StoreField store = new StoreField(container, field, value, graph);
655 appendOptimizedStoreField(store); 651 appendOptimizedStoreField(store);
656 } 652 }
657 653
658 private Value genResolveClass(RiType.Representation representation, RiType holder, boolean initialized, int cpi) { 654 private Value genResolveClass(RiType.Representation representation, RiType holder, boolean initialized, int cpi) {
659 Value holderInstr; 655 Value holderInstr;
660 if (initialized) { 656 if (initialized) {
661 holderInstr = appendConstant(holder.getEncoding(representation)); 657 holderInstr = appendConstant(holder.getEncoding(representation));
662 } else { 658 } else {
663 holderInstr = append(new ResolveClass(holder, representation, null, graph)); 659 holderInstr = append(new ResolveClass(holder, representation, graph));
664 } 660 }
665 return holderInstr; 661 return holderInstr;
666 } 662 }
667 663
668 private void appendOptimizedStoreField(StoreField store) { 664 private void appendOptimizedStoreField(StoreField store) {
701 // Re-use the same resolution code as for accessing a static field. Even though 697 // Re-use the same resolution code as for accessing a static field. Even though
702 // the result of resolution is not used by the invocation (only the side effect 698 // the result of resolution is not used by the invocation (only the side effect
703 // of initialization is required), it can be commoned with static field accesses. 699 // of initialization is required), it can be commoned with static field accesses.
704 genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi); 700 genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi);
705 } 701 }
706
707 FrameState stateBefore = frameState.create(bci());
708 Value[] args = frameState.popArguments(target.signature().argumentSlots(false)); 702 Value[] args = frameState.popArguments(target.signature().argumentSlots(false));
709 appendInvoke(INVOKESTATIC, target, args, cpi, constantPool, stateBefore); 703 appendInvoke(INVOKESTATIC, target, args, cpi, constantPool);
710 } 704 }
711 705
712 void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) { 706 void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) {
713 FrameState stateBefore = frameState.create(bci());
714 Value[] args = frameState.popArguments(target.signature().argumentSlots(true)); 707 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
715 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool, stateBefore); 708 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool);
716 709
717 } 710 }
718 711
719 void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) { 712 void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) {
720 FrameState stateBefore = frameState.create(bci());
721 Value[] args = frameState.popArguments(target.signature().argumentSlots(true)); 713 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
722 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool, stateBefore); 714 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool);
723 715
724 } 716 }
725 717
726 void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) { 718 void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) {
727 FrameState stateBefore = frameState.create(bci());
728 Value[] args = frameState.popArguments(target.signature().argumentSlots(true)); 719 Value[] args = frameState.popArguments(target.signature().argumentSlots(true));
729 invokeDirect(target, args, knownHolder, cpi, constantPool, stateBefore); 720 invokeDirect(target, args, knownHolder, cpi, constantPool);
730 721
731 } 722 }
732 723
733 /** 724 /**
734 * Temporary work-around to support the @ACCESSOR Maxine annotation. 725 * Temporary work-around to support the @ACCESSOR Maxine annotation.
760 target = newTarget; 751 target = newTarget;
761 } 752 }
762 return target; 753 return target;
763 } 754 }
764 755
765 private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool, FrameState stateBefore) { 756 private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
766 Value receiver = args[0]; 757 Value receiver = args[0];
767 // attempt to devirtualize the call 758 // attempt to devirtualize the call
768 if (target.isResolved()) { 759 if (target.isResolved()) {
769 RiType klass = target.holder(); 760 RiType klass = target.holder();
770 761
771 // 0. check for trivial cases 762 // 0. check for trivial cases
772 if (target.canBeStaticallyBound() && !isAbstract(target.accessFlags())) { 763 if (target.canBeStaticallyBound() && !isAbstract(target.accessFlags())) {
773 // check for trivial cases (e.g. final methods, nonvirtual methods) 764 // check for trivial cases (e.g. final methods, nonvirtual methods)
774 invokeDirect(target, args, target.holder(), cpi, constantPool, stateBefore); 765 invokeDirect(target, args, target.holder(), cpi, constantPool);
775 return; 766 return;
776 } 767 }
777 // 1. check if the exact type of the receiver can be determined 768 // 1. check if the exact type of the receiver can be determined
778 RiType exact = getExactType(klass, receiver); 769 RiType exact = getExactType(klass, receiver);
779 if (exact != null && exact.isResolved()) { 770 if (exact != null && exact.isResolved()) {
780 // either the holder class is exact, or the receiver object has an exact type 771 // either the holder class is exact, or the receiver object has an exact type
781 invokeDirect(exact.resolveMethodImpl(target), args, exact, cpi, constantPool, stateBefore); 772 invokeDirect(exact.resolveMethodImpl(target), args, exact, cpi, constantPool);
782 return; 773 return;
783 } 774 }
784 // 2. check if an assumed leaf method can be found 775 // 2. check if an assumed leaf method can be found
785 RiMethod leaf = getAssumedLeafMethod(target, receiver); 776 RiMethod leaf = getAssumedLeafMethod(target, receiver);
786 if (leaf != null && leaf.isResolved() && !isAbstract(leaf.accessFlags()) && leaf.holder().isResolved()) { 777 if (leaf != null && leaf.isResolved() && !isAbstract(leaf.accessFlags()) && leaf.holder().isResolved()) {
787 if (C1XOptions.PrintAssumptions) { 778 if (C1XOptions.PrintAssumptions) {
788 TTY.println("Optimistic invoke direct because of leaf method to " + leaf); 779 TTY.println("Optimistic invoke direct because of leaf method to " + leaf);
789 } 780 }
790 invokeDirect(leaf, args, null, cpi, constantPool, stateBefore); 781 invokeDirect(leaf, args, null, cpi, constantPool);
791 return; 782 return;
792 } else if (C1XOptions.PrintAssumptions) { 783 } else if (C1XOptions.PrintAssumptions) {
793 TTY.println("Could not make leaf method assumption for target=" + target + " leaf=" + leaf + " receiver.declaredType=" + receiver.declaredType()); 784 TTY.println("Could not make leaf method assumption for target=" + target + " leaf=" + leaf + " receiver.declaredType=" + receiver.declaredType());
794 } 785 }
795 // 3. check if the either of the holder or declared type of receiver can be assumed to be a leaf 786 // 3. check if the either of the holder or declared type of receiver can be assumed to be a leaf
798 RiMethod targetMethod = exact.resolveMethodImpl(target); 789 RiMethod targetMethod = exact.resolveMethodImpl(target);
799 if (C1XOptions.PrintAssumptions) { 790 if (C1XOptions.PrintAssumptions) {
800 TTY.println("Optimistic invoke direct because of leaf type to " + targetMethod); 791 TTY.println("Optimistic invoke direct because of leaf type to " + targetMethod);
801 } 792 }
802 // either the holder class is exact, or the receiver object has an exact type 793 // either the holder class is exact, or the receiver object has an exact type
803 invokeDirect(targetMethod, args, exact, cpi, constantPool, stateBefore); 794 invokeDirect(targetMethod, args, exact, cpi, constantPool);
804 return; 795 return;
805 } else if (C1XOptions.PrintAssumptions) { 796 } else if (C1XOptions.PrintAssumptions) {
806 TTY.println("Could not make leaf type assumption for type " + klass); 797 TTY.println("Could not make leaf type assumption for type " + klass);
807 } 798 }
808 } 799 }
809 // devirtualization failed, produce an actual invokevirtual 800 // devirtualization failed, produce an actual invokevirtual
810 appendInvoke(opcode, target, args, cpi, constantPool, stateBefore); 801 appendInvoke(opcode, target, args, cpi, constantPool);
811 } 802 }
812 803
813 private CiKind returnKind(RiMethod target) { 804 private CiKind returnKind(RiMethod target) {
814 return target.signature().returnKind(); 805 return target.signature().returnKind();
815 } 806 }
816 807
817 private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool, FrameState stateBefore) { 808 private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) {
818 appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool, stateBefore); 809 appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool);
819 } 810 }
820 811
821 private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool, FrameState stateBefore) { 812 private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) {
822 CiKind resultType = returnKind(target); 813 CiKind resultType = returnKind(target);
823 Value result = append(new Invoke(opcode, resultType.stackKind(), args, target, target.signature().returnType(compilation.method.holder()), stateBefore, graph)); 814 Value result = append(new Invoke(opcode, resultType.stackKind(), args, target, target.signature().returnType(compilation.method.holder()), graph));
824 frameState.pushReturn(resultType, result); 815 frameState.pushReturn(resultType, result);
825 } 816 }
826 817
827 private RiType getExactType(RiType staticType, Value receiver) { 818 private RiType getExactType(RiType staticType, Value receiver) {
828 RiType exact = staticType.exactType(); 819 RiType exact = staticType.exactType();
918 } 909 }
919 } 910 }
920 911
921 if (needsCheck) { 912 if (needsCheck) {
922 // append a call to the finalizer registration 913 // append a call to the finalizer registration
923 append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph)); 914 append(new RegisterFinalizer(frameState.loadLocal(0), graph));
924 C1XMetrics.InlinedFinalizerChecks++; 915 C1XMetrics.InlinedFinalizerChecks++;
925 } 916 }
926 } 917 }
927 918
928 void genReturn(Value x) { 919 void genReturn(Value x) {
930 callRegisterFinalizer(); 921 callRegisterFinalizer();
931 } 922 }
932 923
933 frameState.clearStack(); 924 frameState.clearStack();
934 if (Modifier.isSynchronized(method().accessFlags())) { 925 if (Modifier.isSynchronized(method().accessFlags())) {
935 FrameState stateBefore = frameState.create(bci());
936 // unlock before exiting the method 926 // unlock before exiting the method
937 int lockNumber = frameState.locksSize() - 1; 927 int lockNumber = frameState.locksSize() - 1;
938 MonitorAddress lockAddress = null; 928 MonitorAddress lockAddress = null;
939 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 929 if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
940 lockAddress = new MonitorAddress(lockNumber, graph); 930 lockAddress = new MonitorAddress(lockNumber, graph);
941 append(lockAddress); 931 append(lockAddress);
942 } 932 }
943 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore, graph)); 933 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph));
944 frameState.unlock(); 934 frameState.unlock();
945 } 935 }
946 append(new Return(x, !noSafepoints(), graph)); 936 append(new Return(x, !noSafepoints(), graph));
947 } 937 }
948 938
959 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 949 if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
960 lockAddress = new MonitorAddress(lockNumber, graph); 950 lockAddress = new MonitorAddress(lockNumber, graph);
961 append(lockAddress); 951 append(lockAddress);
962 } 952 }
963 frameState.push(CiKind.Object, x); 953 frameState.push(CiKind.Object, x);
964 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, frameState.create(bci()), graph); 954 MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph);
965 frameState.apop(); 955 frameState.apop();
966 appendWithoutOptimization(monitorEnter, bci); 956 appendWithoutOptimization(monitorEnter, bci);
967 frameState.lock(ir, x, lockNumber + 1); 957 frameState.lock(ir, x, lockNumber + 1);
968 monitorEnter.setStateAfter(frameState.create(bci)); 958 monitorEnter.setStateAfter(frameState.create(bci));
969 killMemoryMap(); // prevent any optimizations across synchronization 959 killMemoryMap(); // prevent any optimizations across synchronization
977 MonitorAddress lockAddress = null; 967 MonitorAddress lockAddress = null;
978 if (compilation.runtime.sizeOfBasicObjectLock() != 0) { 968 if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
979 lockAddress = new MonitorAddress(lockNumber, graph); 969 lockAddress = new MonitorAddress(lockNumber, graph);
980 append(lockAddress); 970 append(lockAddress);
981 } 971 }
982 appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, null, graph), bci); 972 appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, graph), bci);
983 frameState.unlock(); 973 frameState.unlock();
984 killMemoryMap(); // prevent any optimizations across synchronization 974 killMemoryMap(); // prevent any optimizations across synchronization
985 } 975 }
986 976
987 void genJsr(int dest) { 977 void genJsr(int dest) {
1089 } 1079 }
1090 1080
1091 assert x.next() == null : "instruction should not have been appended yet"; 1081 assert x.next() == null : "instruction should not have been appended yet";
1092 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; 1082 assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
1093 1083
1094 if (lastInstr instanceof StateSplit) {
1095 StateSplit stateSplit = (StateSplit) lastInstr;
1096 if (stateSplit.stateAfter() == null) {
1097 stateSplit.setStateAfter(frameState.create(bci));
1098 }
1099 }
1100
1101 if (lastInstr instanceof Base) { 1084 if (lastInstr instanceof Base) {
1102 assert false : "may only happen when inlining intrinsics"; 1085 assert false : "may only happen when inlining intrinsics";
1103 } else { 1086 } else {
1104 lastInstr = lastInstr.appendNext(x, bci); 1087 lastInstr = lastInstr.appendNext(x, bci);
1105 } 1088 }
1242 prevBCI = bci; 1225 prevBCI = bci;
1243 1226
1244 if (lastInstr instanceof BlockEnd) { 1227 if (lastInstr instanceof BlockEnd) {
1245 end = (BlockEnd) lastInstr; 1228 end = (BlockEnd) lastInstr;
1246 break; 1229 break;
1230 }
1231 if (lastInstr instanceof StateSplit) {
1232 StateSplit stateSplit = (StateSplit) lastInstr;
1233 if (stateSplit.stateAfter() == null && stateSplit.needsStateAfter()) {
1234 stateSplit.setStateAfter(frameState.create(bci));
1235 }
1247 } 1236 }
1248 stream.next(); 1237 stream.next();
1249 bci = stream.currentBCI(); 1238 bci = stream.currentBCI();
1250 blockStart = false; 1239 blockStart = false;
1251 } 1240 }
1517 log.println(sb.toString()); 1506 log.println(sb.toString());
1518 } 1507 }
1519 } 1508 }
1520 1509
1521 private void genArrayLength() { 1510 private void genArrayLength() {
1522 FrameState stateBefore = frameState.create(bci()); 1511 frameState.ipush(append(new ArrayLength(frameState.apop(), graph)));
1523 frameState.ipush(append(new ArrayLength(frameState.apop(), stateBefore, graph)));
1524 } 1512 }
1525 1513
1526 void killMemoryMap() { 1514 void killMemoryMap() {
1527 if (localValueMap != null) { 1515 if (localValueMap != null) {
1528 localValueMap.killAll(); 1516 localValueMap.killAll();