Mercurial > hg > graal-compiler
comparison graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2515:4fdef1464592
Removed extended bytecodes and related HIR instructions.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 15:36:29 +0200 |
parents | 16b9a8b5ad39 |
children | a384fac3fd34 |
comparison
equal
deleted
inserted
replaced
2514:34b5eea9b001 | 2515:4fdef1464592 |
---|---|
30 | 30 |
31 import com.sun.c1x.*; | 31 import com.sun.c1x.*; |
32 import com.sun.c1x.debug.*; | 32 import com.sun.c1x.debug.*; |
33 import com.sun.c1x.graph.ScopeData.ReturnBlock; | 33 import com.sun.c1x.graph.ScopeData.ReturnBlock; |
34 import com.sun.c1x.ir.*; | 34 import com.sun.c1x.ir.*; |
35 import com.sun.c1x.ir.Value.Flag; | |
36 import com.sun.c1x.opt.*; | 35 import com.sun.c1x.opt.*; |
37 import com.sun.c1x.util.*; | 36 import com.sun.c1x.util.*; |
38 import com.sun.c1x.value.*; | 37 import com.sun.c1x.value.*; |
39 import com.sun.cri.bytecode.*; | 38 import com.sun.cri.bytecode.*; |
40 import com.sun.cri.bytecode.Bytecodes.JniOp; | |
41 import com.sun.cri.ci.*; | 39 import com.sun.cri.ci.*; |
42 import com.sun.cri.ri.*; | 40 import com.sun.cri.ri.*; |
43 import com.sun.cri.ri.RiType.Representation; | 41 import com.sun.cri.ri.RiType.Representation; |
44 | 42 |
45 /** | 43 /** |
189 // 6B.1 do the normal parsing | 187 // 6B.1 do the normal parsing |
190 scopeData.addToWorkList(stdEntry); | 188 scopeData.addToWorkList(stdEntry); |
191 iterateAllBlocks(); | 189 iterateAllBlocks(); |
192 } | 190 } |
193 } else { | 191 } else { |
194 RiType accessor = openAccessorScope(rootMethod); | |
195 | |
196 // 6B.1 do the normal parsing | 192 // 6B.1 do the normal parsing |
197 scopeData.addToWorkList(stdEntry); | 193 scopeData.addToWorkList(stdEntry); |
198 iterateAllBlocks(); | 194 iterateAllBlocks(); |
199 | |
200 closeAccessorScope(accessor); | |
201 } | 195 } |
202 | 196 |
203 if (syncHandler != null && syncHandler.stateBefore() != null) { | 197 if (syncHandler != null && syncHandler.stateBefore() != null) { |
204 // generate unlocking code if the exception handler is reachable | 198 // generate unlocking code if the exception handler is reachable |
205 fillSyncHandler(rootMethodSynchronizedObject, syncHandler, false); | 199 fillSyncHandler(rootMethodSynchronizedObject, syncHandler, false); |
210 assert osrBlock.wasVisited(); | 204 assert osrBlock.wasVisited(); |
211 if (!osrBlock.stateBefore().stackEmpty()) { | 205 if (!osrBlock.stateBefore().stackEmpty()) { |
212 throw new CiBailout("cannot OSR with non-empty stack"); | 206 throw new CiBailout("cannot OSR with non-empty stack"); |
213 } | 207 } |
214 } | 208 } |
215 } | |
216 | |
217 private void closeAccessorScope(RiType accessor) { | |
218 if (accessor != null) { | |
219 boundAccessor.set(null); | |
220 } | |
221 } | |
222 | |
223 private RiType openAccessorScope(RiMethod rootMethod) { | |
224 RiType accessor = rootMethod.accessor(); | |
225 if (accessor != null) { | |
226 assert boundAccessor.get() == null; | |
227 boundAccessor.set(accessor); | |
228 | |
229 // What looks like an object receiver in the bytecode may not be a word value | |
230 compilation.setNotTypesafe(); | |
231 } | |
232 return accessor; | |
233 } | 209 } |
234 | 210 |
235 private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry, BlockBegin osrEntry) { | 211 private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry, BlockBegin osrEntry) { |
236 assert curBlock == startBlock; | 212 assert curBlock == startBlock; |
237 Base base = new Base(stdEntry, osrEntry); | 213 Base base = new Base(stdEntry, osrEntry); |
680 if (!resultKind.isVoid()) { | 656 if (!resultKind.isVoid()) { |
681 ipush(value); | 657 ipush(value); |
682 } | 658 } |
683 } | 659 } |
684 | 660 |
685 void genUnsignedCompareOp(CiKind kind, int opcode, int op) { | |
686 Value y = pop(kind); | |
687 Value x = pop(kind); | |
688 ipush(append(new UnsignedCompareOp(opcode, op, x, y))); | |
689 } | |
690 | |
691 void genConvert(int opcode, CiKind from, CiKind to) { | 661 void genConvert(int opcode, CiKind from, CiKind to) { |
692 CiKind tt = to.stackKind(); | 662 CiKind tt = to.stackKind(); |
693 push(tt, append(new Convert(opcode, pop(from.stackKind()), tt))); | 663 push(tt, append(new Convert(opcode, pop(from.stackKind()), tt))); |
694 } | 664 } |
695 | 665 |
737 | 707 |
738 void genThrow(int bci) { | 708 void genThrow(int bci) { |
739 FrameState stateBefore = curState.immutableCopy(bci()); | 709 FrameState stateBefore = curState.immutableCopy(bci()); |
740 Throw t = new Throw(apop(), stateBefore, !scopeData.noSafepoints()); | 710 Throw t = new Throw(apop(), stateBefore, !scopeData.noSafepoints()); |
741 appendWithoutOptimization(t, bci); | 711 appendWithoutOptimization(t, bci); |
742 } | |
743 | |
744 void genUnsafeCast(RiMethod method) { | |
745 compilation.setNotTypesafe(); | |
746 RiSignature signature = method.signature(); | |
747 int argCount = signature.argumentCount(false); | |
748 RiType accessingClass = scope().method.holder(); | |
749 RiType fromType; | |
750 RiType toType = signature.returnType(accessingClass); | |
751 if (argCount == 1) { | |
752 fromType = signature.argumentTypeAt(0, accessingClass); | |
753 } else { | |
754 assert argCount == 0 : "method with @UNSAFE_CAST must have exactly 1 argument"; | |
755 fromType = method.holder(); | |
756 } | |
757 CiKind from = fromType.kind(); | |
758 CiKind to = toType.kind(); | |
759 boolean redundant = compilation.archKindsEqual(to, from); | |
760 curState.push(to, append(new UnsafeCast(toType, curState.pop(from), redundant))); | |
761 } | 712 } |
762 | 713 |
763 void genCheckCast() { | 714 void genCheckCast() { |
764 int cpi = stream().readCPI(); | 715 int cpi = stream().readCPI(); |
765 RiType type = constantPool().lookupType(cpi, CHECKCAST); | 716 RiType type = constantPool().lookupType(cpi, CHECKCAST); |
904 memoryMap.setResult(load, optimized); | 855 memoryMap.setResult(load, optimized); |
905 } | 856 } |
906 push(kind.stackKind(), optimized); | 857 push(kind.stackKind(), optimized); |
907 } | 858 } |
908 | 859 |
909 /** | |
910 * Temporary work-around to support the @ACCESSOR Maxine annotation. | |
911 */ | |
912 private RiMethod handleInvokeAccessorOrBuiltin(RiMethod target) { | |
913 target = bindAccessorMethod(target); | |
914 if (target.intrinsic() != 0) { | |
915 int intrinsic = target.intrinsic(); | |
916 int opcode = intrinsic & 0xff; | |
917 switch (opcode) { | |
918 case PREAD : genLoadPointer(intrinsic); break; | |
919 case PGET : genLoadPointer(intrinsic); break; | |
920 case PWRITE : genStorePointer(intrinsic); break; | |
921 case PSET : genStorePointer(intrinsic); break; | |
922 case PCMPSWP : genCompareAndSwap(intrinsic); break; | |
923 default: | |
924 throw new CiBailout("unknown bytecode " + opcode + " (" + nameOf(opcode) + ")"); | |
925 } | |
926 return null; | |
927 } | |
928 return target; | |
929 } | |
930 | |
931 void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) { | 860 void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) { |
932 target = handleInvokeAccessorOrBuiltin(target); | |
933 if (target == null) { | |
934 return; | |
935 } | |
936 RiType holder = target.holder(); | 861 RiType holder = target.holder(); |
937 boolean isInitialized = !C1XOptions.TestPatching && target.isResolved() && holder.isInitialized(); | 862 boolean isInitialized = !C1XOptions.TestPatching && target.isResolved() && holder.isInitialized(); |
938 if (!isInitialized && C1XOptions.ResolveClassBeforeStaticInvoke) { | 863 if (!isInitialized && C1XOptions.ResolveClassBeforeStaticInvoke) { |
939 // Re-use the same resolution code as for accessing a static field. Even though | 864 // Re-use the same resolution code as for accessing a static field. Even though |
940 // the result of resolution is not used by the invocation (only the side effect | 865 // the result of resolution is not used by the invocation (only the side effect |
949 } | 874 } |
950 } | 875 } |
951 } | 876 } |
952 | 877 |
953 void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) { | 878 void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) { |
954 target = handleInvokeAccessorOrBuiltin(target); | |
955 if (target == null) { | |
956 return; | |
957 } | |
958 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); | 879 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); |
959 if (!tryRemoveCall(target, args, false)) { | 880 if (!tryRemoveCall(target, args, false)) { |
960 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool); | 881 genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool); |
961 } | 882 } |
962 } | 883 } |
963 | 884 |
964 void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) { | 885 void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) { |
965 target = handleInvokeAccessorOrBuiltin(target); | |
966 if (target == null) { | |
967 return; | |
968 } | |
969 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); | 886 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); |
970 if (!tryRemoveCall(target, args, false)) { | 887 if (!tryRemoveCall(target, args, false)) { |
971 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool); | 888 genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool); |
972 } | 889 } |
973 } | 890 } |
974 | 891 |
975 void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) { | 892 void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) { |
976 target = handleInvokeAccessorOrBuiltin(target); | |
977 if (target == null) { | |
978 return; | |
979 } | |
980 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); | 893 Value[] args = curState.popArguments(target.signature().argumentSlots(true)); |
981 if (!tryRemoveCall(target, args, false)) { | 894 if (!tryRemoveCall(target, args, false)) { |
982 invokeDirect(target, args, knownHolder, cpi, constantPool); | 895 invokeDirect(target, args, knownHolder, cpi, constantPool); |
983 } | 896 } |
984 } | 897 } |
1011 RiMethod newTarget = accessor.resolveMethodImpl(target); | 924 RiMethod newTarget = accessor.resolveMethodImpl(target); |
1012 assert target != newTarget : "Could not bind " + target + " to a method in " + accessor; | 925 assert target != newTarget : "Could not bind " + target + " to a method in " + accessor; |
1013 target = newTarget; | 926 target = newTarget; |
1014 } | 927 } |
1015 return target; | 928 return target; |
1016 } | |
1017 | |
1018 /** | |
1019 * Temporary work-around to support the @ACCESSOR Maxine annotation. | |
1020 */ | |
1021 private boolean inlineWithBoundAccessor(RiMethod target, Value[] args, boolean forcedInline) { | |
1022 RiType accessor = target.accessor(); | |
1023 if (accessor != null) { | |
1024 assert boundAccessor.get() == null; | |
1025 boundAccessor.set(accessor); | |
1026 try { | |
1027 // What looks like an object receiver in the bytecode may not be a word value | |
1028 compilation.setNotTypesafe(); | |
1029 inline(target, args, forcedInline); | |
1030 } finally { | |
1031 boundAccessor.set(null); | |
1032 } | |
1033 return true; | |
1034 } | |
1035 return false; | |
1036 } | 929 } |
1037 | 930 |
1038 private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { | 931 private void genInvokeIndirect(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { |
1039 Value receiver = args[0]; | 932 Value receiver = args[0]; |
1040 // attempt to devirtualize the call | 933 // attempt to devirtualize the call |
1783 if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) { | 1676 if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) { |
1784 log.println("| [inlining " + target + "]"); | 1677 log.println("| [inlining " + target + "]"); |
1785 log.println("|"); | 1678 log.println("|"); |
1786 } | 1679 } |
1787 } | 1680 } |
1788 if (!inlineWithBoundAccessor(target, args, forcedInline)) { | 1681 |
1789 inline(target, args, forcedInline); | 1682 inline(target, args, forcedInline); |
1790 } | |
1791 | 1683 |
1792 if (C1XOptions.TraceBytecodeParserLevel > 0) { | 1684 if (C1XOptions.TraceBytecodeParserLevel > 0) { |
1793 if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) { | 1685 if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) { |
1794 log.println("|"); | 1686 log.println("|"); |
1795 log.println("| [return to " + curState.scope().method + "]"); | 1687 log.println("| [return to " + curState.scope().method + "]"); |
2441 case MULTIANEWARRAY : genNewMultiArray(s.readCPI()); break; | 2333 case MULTIANEWARRAY : genNewMultiArray(s.readCPI()); break; |
2442 case IFNULL : genIfNull(Condition.EQ); break; | 2334 case IFNULL : genIfNull(Condition.EQ); break; |
2443 case IFNONNULL : genIfNull(Condition.NE); break; | 2335 case IFNONNULL : genIfNull(Condition.NE); break; |
2444 case GOTO_W : genGoto(s.currentBCI(), s.readFarBranchDest()); break; | 2336 case GOTO_W : genGoto(s.currentBCI(), s.readFarBranchDest()); break; |
2445 case JSR_W : genJsr(s.readFarBranchDest()); break; | 2337 case JSR_W : genJsr(s.readFarBranchDest()); break; |
2446 default: | |
2447 processExtendedBytecode(bci, s, opcode); | |
2448 } | |
2449 // Checkstyle: resume | |
2450 } | |
2451 | |
2452 private void processExtendedBytecode(int bci, BytecodeStream s, int opcode) { | |
2453 // Checkstyle: stop | |
2454 switch (opcode) { | |
2455 case UNSAFE_CAST : genUnsafeCast(constantPool().lookupMethod(s.readCPI(), (byte)Bytecodes.UNSAFE_CAST)); break; | |
2456 case WLOAD : loadLocal(s.readLocalIndex(), CiKind.Word); break; | |
2457 case WLOAD_0 : loadLocal(0, CiKind.Word); break; | |
2458 case WLOAD_1 : loadLocal(1, CiKind.Word); break; | |
2459 case WLOAD_2 : loadLocal(2, CiKind.Word); break; | |
2460 case WLOAD_3 : loadLocal(3, CiKind.Word); break; | |
2461 | |
2462 case WSTORE : storeLocal(CiKind.Word, s.readLocalIndex()); break; | |
2463 case WSTORE_0 : // fall through | |
2464 case WSTORE_1 : // fall through | |
2465 case WSTORE_2 : // fall through | |
2466 case WSTORE_3 : storeLocal(CiKind.Word, opcode - WSTORE_0); break; | |
2467 | |
2468 case WCONST_0 : wpush(appendConstant(CiConstant.ZERO)); break; | |
2469 case WDIV : // fall through | |
2470 case WREM : genArithmeticOp(CiKind.Word, opcode, curState.immutableCopy(bci())); break; | |
2471 case WDIVI : genArithmeticOp(CiKind.Word, opcode, CiKind.Word, CiKind.Int, curState.immutableCopy(bci())); break; | |
2472 case WREMI : genArithmeticOp(CiKind.Int, opcode, CiKind.Word, CiKind.Int, curState.immutableCopy(bci())); break; | |
2473 | |
2474 case READREG : genLoadRegister(s.readCPI()); break; | |
2475 case WRITEREG : genStoreRegister(s.readCPI()); break; | |
2476 case INCREG : genIncRegister(s.readCPI()); break; | |
2477 | |
2478 case PREAD : genLoadPointer(PREAD | (s.readCPI() << 8)); break; | |
2479 case PGET : genLoadPointer(PGET | (s.readCPI() << 8)); break; | |
2480 case PWRITE : genStorePointer(PWRITE | (s.readCPI() << 8)); break; | |
2481 case PSET : genStorePointer(PSET | (s.readCPI() << 8)); break; | |
2482 case PCMPSWP : genCompareAndSwap(PCMPSWP | (s.readCPI() << 8)); break; | |
2483 case MEMBAR : genMemoryBarrier(s.readCPI()); break; | |
2484 | |
2485 case WRETURN : genReturn(wpop()); break; | |
2486 case INFOPOINT : genInfopoint(INFOPOINT | (s.readUByte(bci() + 1) << 16), s.readUByte(bci() + 2) != 0); break; | |
2487 case JNICALL : genNativeCall(s.readCPI()); break; | |
2488 case JNIOP : genJniOp(s.readCPI()); break; | |
2489 case ALLOCA : genStackAllocate(); break; | |
2490 | |
2491 case MOV_I2F : genConvert(opcode, CiKind.Int, CiKind.Float ); break; | |
2492 case MOV_F2I : genConvert(opcode, CiKind.Float, CiKind.Int ); break; | |
2493 case MOV_L2D : genConvert(opcode, CiKind.Long, CiKind.Double ); break; | |
2494 case MOV_D2L : genConvert(opcode, CiKind.Double, CiKind.Long ); break; | |
2495 | |
2496 case UCMP : genUnsignedCompareOp(CiKind.Int, opcode, s.readCPI()); break; | |
2497 case UWCMP : genUnsignedCompareOp(CiKind.Word, opcode, s.readCPI()); break; | |
2498 | |
2499 case STACKHANDLE : genStackHandle(s.readCPI() == 0); break; | |
2500 case BREAKPOINT_TRAP: genBreakpointTrap(); break; | |
2501 case PAUSE : genPause(); break; | |
2502 case LSB : // fall through | |
2503 case MSB : genSignificantBit(opcode);break; | |
2504 | |
2505 case TEMPLATE_CALL : genTemplateCall(constantPool().lookupMethod(s.readCPI(), (byte)Bytecodes.TEMPLATE_CALL)); break; | |
2506 case ICMP : genCompareOp(CiKind.Int, opcode, CiKind.Void); break; | |
2507 case WCMP : genCompareOp(CiKind.Word, opcode, CiKind.Void); break; | |
2508 | |
2509 case BREAKPOINT: | 2338 case BREAKPOINT: |
2510 throw new CiBailout("concurrent setting of breakpoint"); | 2339 throw new CiBailout("concurrent setting of breakpoint"); |
2511 default: | 2340 default: |
2512 throw new CiBailout("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]"); | 2341 throw new CiBailout("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]"); |
2513 } | 2342 } |
2526 sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode)); | 2355 sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode)); |
2527 for (int i = bci + 1; i < s.nextBCI(); ++i) { | 2356 for (int i = bci + 1; i < s.nextBCI(); ++i) { |
2528 sb.append(' ').append(s.readUByte(i)); | 2357 sb.append(' ').append(s.readUByte(i)); |
2529 } | 2358 } |
2530 log.println(sb.toString()); | 2359 log.println(sb.toString()); |
2531 } | |
2532 } | |
2533 | |
2534 private void genPause() { | |
2535 append(new Pause()); | |
2536 } | |
2537 | |
2538 private void genBreakpointTrap() { | |
2539 append(new BreakpointTrap()); | |
2540 } | |
2541 | |
2542 private void genStackHandle(boolean isCategory1) { | |
2543 Value value = curState.xpop(); | |
2544 wpush(append(new StackHandle(value))); | |
2545 } | |
2546 | |
2547 private void genStackAllocate() { | |
2548 Value size = pop(CiKind.Int); | |
2549 wpush(append(new StackAllocate(size))); | |
2550 } | |
2551 | |
2552 private void genSignificantBit(int opcode) { | |
2553 Value value = pop(CiKind.Word); | |
2554 push(CiKind.Int, append(new SignificantBitOp(value, opcode))); | |
2555 } | |
2556 | |
2557 private void appendSnippetCall(RiSnippetCall snippetCall) { | |
2558 Value[] args = new Value[snippetCall.arguments.length]; | |
2559 RiMethod snippet = snippetCall.snippet; | |
2560 RiSignature signature = snippet.signature(); | |
2561 assert signature.argumentCount(!isStatic(snippet.accessFlags())) == args.length; | |
2562 for (int i = args.length - 1; i >= 0; --i) { | |
2563 CiKind argKind = signature.argumentKindAt(i); | |
2564 if (snippetCall.arguments[i] == null) { | |
2565 args[i] = pop(argKind); | |
2566 } else { | |
2567 args[i] = append(new Constant(snippetCall.arguments[i])); | |
2568 } | |
2569 } | |
2570 | |
2571 if (!tryRemoveCall(snippet, args, true)) { | |
2572 if (!tryInline(snippet, args)) { | |
2573 appendInvoke(snippetCall.opcode, snippet, args, true, (char) 0, constantPool()); | |
2574 } | |
2575 } | |
2576 } | |
2577 | |
2578 private void genJniOp(int operand) { | |
2579 RiSnippets snippets = compilation.runtime.getSnippets(); | |
2580 switch (operand) { | |
2581 case JniOp.LINK: { | |
2582 RiMethod nativeMethod = scope().method; | |
2583 RiSnippetCall linkSnippet = snippets.link(nativeMethod); | |
2584 if (linkSnippet.result != null) { | |
2585 wpush(appendConstant(linkSnippet.result)); | |
2586 } else { | |
2587 appendSnippetCall(linkSnippet); | |
2588 } | |
2589 break; | |
2590 } | |
2591 case JniOp.J2N: { | |
2592 RiMethod nativeMethod = scope().method; | |
2593 appendSnippetCall(snippets.enterNative(nativeMethod)); | |
2594 break; | |
2595 } | |
2596 case JniOp.N2J: { | |
2597 RiMethod nativeMethod = scope().method; | |
2598 appendSnippetCall(snippets.enterVM(nativeMethod)); | |
2599 break; | |
2600 } | |
2601 } | |
2602 } | |
2603 | |
2604 private void genNativeCall(int cpi) { | |
2605 Value nativeFunctionAddress = wpop(); | |
2606 RiSignature sig = constantPool().lookupSignature(cpi); | |
2607 Value[] args = curState.popArguments(sig.argumentSlots(false)); | |
2608 | |
2609 RiMethod nativeMethod = scope().method; | |
2610 CiKind returnKind = sig.returnKind(); | |
2611 pushReturn(returnKind, append(new NativeCall(nativeMethod, sig, nativeFunctionAddress, args, null))); | |
2612 | |
2613 // Sign extend or zero the upper bits of a return value smaller than an int to | |
2614 // preserve the invariant that all such values are represented by an int | |
2615 // in the VM. We cannot rely on the native C compiler doing this for us. | |
2616 switch (sig.returnKind()) { | |
2617 case Boolean: | |
2618 case Byte: { | |
2619 genConvert(I2B, CiKind.Int, CiKind.Byte); | |
2620 break; | |
2621 } | |
2622 case Short: { | |
2623 genConvert(I2S, CiKind.Int, CiKind.Short); | |
2624 break; | |
2625 } | |
2626 case Char: { | |
2627 genConvert(I2C, CiKind.Int, CiKind.Char); | |
2628 break; | |
2629 } | |
2630 } | |
2631 } | |
2632 | |
2633 void genTemplateCall(RiMethod method) { | |
2634 RiSignature sig = method.signature(); | |
2635 Value[] args = curState.popArguments(sig.argumentSlots(false)); | |
2636 assert args.length <= 2; | |
2637 CiKind returnKind = sig.returnKind(); | |
2638 Value address = null; | |
2639 Value receiver = null; | |
2640 if (args.length == 1) { | |
2641 address = args[0]; | |
2642 assert address.kind.isWord(); | |
2643 } else if (args.length == 2) { | |
2644 address = args[0]; | |
2645 assert address.kind.isWord(); | |
2646 receiver = args[1]; | |
2647 assert receiver.kind.isObject(); | |
2648 } | |
2649 pushReturn(returnKind, append(new TemplateCall(returnKind, address, receiver))); | |
2650 } | |
2651 | |
2652 private void genInfopoint(int opcode, boolean inclFrame) { | |
2653 // TODO: create slimmer frame state if inclFrame is false | |
2654 FrameState state = curState.immutableCopy(bci()); | |
2655 assert opcode != SAFEPOINT || !scopeData.noSafepoints() : "cannot place explicit safepoint in uninterruptible code scope"; | |
2656 Value result = append(new Infopoint(opcode, state)); | |
2657 if (!result.kind.isVoid()) { | |
2658 push(result.kind, result); | |
2659 } | |
2660 } | |
2661 | |
2662 private void genLoadRegister(int registerId) { | |
2663 CiRegister register = compilation.registerConfig.getRegisterForRole(registerId); | |
2664 if (register == null) { | |
2665 throw new CiBailout("Unsupported READREG operand " + registerId); | |
2666 } | |
2667 LoadRegister load = new LoadRegister(CiKind.Word, register); | |
2668 RiRegisterAttributes regAttr = compilation.registerConfig.getAttributesMap()[register.number]; | |
2669 if (regAttr.isNonZero) { | |
2670 load.setFlag(Flag.NonNull); | |
2671 } | |
2672 wpush(append(load)); | |
2673 } | |
2674 | |
2675 private void genStoreRegister(int registerId) { | |
2676 CiRegister register = compilation.registerConfig.getRegisterForRole(registerId); | |
2677 if (register == null) { | |
2678 throw new CiBailout("Unsupported WRITEREG operand " + registerId); | |
2679 } | |
2680 Value value = pop(CiKind.Word); | |
2681 append(new StoreRegister(CiKind.Word, register, value)); | |
2682 } | |
2683 | |
2684 private void genIncRegister(int registerId) { | |
2685 CiRegister register = compilation.registerConfig.getRegisterForRole(registerId); | |
2686 if (register == null) { | |
2687 throw new CiBailout("Unsupported INCREG operand " + registerId); | |
2688 } | |
2689 Value value = pop(CiKind.Int); | |
2690 append(new IncrementRegister(register, value)); | |
2691 } | |
2692 | |
2693 /** | |
2694 * Gets the data kind corresponding to a given pointer operation opcode. | |
2695 * The data kind may be more specific than a {@linkplain CiKind#stackKind()}. | |
2696 * | |
2697 * @return the kind of value at the address accessed by the pointer operation denoted by {@code opcode} | |
2698 */ | |
2699 private static CiKind dataKindForPointerOp(int opcode) { | |
2700 switch (opcode) { | |
2701 case PGET_BYTE : | |
2702 case PSET_BYTE : | |
2703 case PREAD_BYTE : | |
2704 case PREAD_BYTE_I : | |
2705 case PWRITE_BYTE : | |
2706 case PWRITE_BYTE_I : return CiKind.Byte; | |
2707 case PGET_CHAR : | |
2708 case PREAD_CHAR : | |
2709 case PREAD_CHAR_I : return CiKind.Char; | |
2710 case PGET_SHORT : | |
2711 case PSET_SHORT : | |
2712 case PREAD_SHORT : | |
2713 case PREAD_SHORT_I : | |
2714 case PWRITE_SHORT : | |
2715 case PWRITE_SHORT_I : return CiKind.Short; | |
2716 case PGET_INT : | |
2717 case PSET_INT : | |
2718 case PREAD_INT : | |
2719 case PREAD_INT_I : | |
2720 case PWRITE_INT : | |
2721 case PWRITE_INT_I : return CiKind.Int; | |
2722 case PGET_FLOAT : | |
2723 case PSET_FLOAT : | |
2724 case PREAD_FLOAT : | |
2725 case PREAD_FLOAT_I : | |
2726 case PWRITE_FLOAT : | |
2727 case PWRITE_FLOAT_I : return CiKind.Float; | |
2728 case PGET_LONG : | |
2729 case PSET_LONG : | |
2730 case PREAD_LONG : | |
2731 case PREAD_LONG_I : | |
2732 case PWRITE_LONG : | |
2733 case PWRITE_LONG_I : return CiKind.Long; | |
2734 case PGET_DOUBLE : | |
2735 case PSET_DOUBLE : | |
2736 case PREAD_DOUBLE : | |
2737 case PREAD_DOUBLE_I : | |
2738 case PWRITE_DOUBLE : | |
2739 case PWRITE_DOUBLE_I : return CiKind.Double; | |
2740 case PGET_WORD : | |
2741 case PSET_WORD : | |
2742 case PREAD_WORD : | |
2743 case PREAD_WORD_I : | |
2744 case PWRITE_WORD : | |
2745 case PWRITE_WORD_I : return CiKind.Word; | |
2746 case PGET_REFERENCE : | |
2747 case PSET_REFERENCE : | |
2748 case PREAD_REFERENCE : | |
2749 case PREAD_REFERENCE_I : | |
2750 case PWRITE_REFERENCE : | |
2751 case PWRITE_REFERENCE_I : return CiKind.Object; | |
2752 default: | |
2753 throw new CiBailout("Unsupported pointer operation opcode " + opcode + "(" + nameOf(opcode) + ")"); | |
2754 } | |
2755 } | |
2756 | |
2757 /** | |
2758 * Pops the value producing the scaled-index or the byte offset for a pointer operation. | |
2759 * If compiling for a 64-bit platform and the value is an {@link CiKind#Int} parameter, | |
2760 * then a conversion is inserted to sign extend the int to a word. | |
2761 * | |
2762 * This is required as the value is used as a 64-bit value and so the high 32 bits | |
2763 * need to be correct. | |
2764 * | |
2765 * @param isInt specifies if the value is an {@code int} | |
2766 */ | |
2767 private Value popOffsetOrIndexForPointerOp(boolean isInt) { | |
2768 if (isInt) { | |
2769 Value offsetOrIndex = ipop(); | |
2770 if (compilation.target.arch.is64bit() && offsetOrIndex instanceof Local) { | |
2771 return append(new Convert(I2L, offsetOrIndex, CiKind.Word)); | |
2772 } | |
2773 return offsetOrIndex; | |
2774 } | |
2775 return wpop(); | |
2776 } | |
2777 | |
2778 private void genLoadPointer(int opcode) { | |
2779 FrameState stateBefore = curState.immutableCopy(bci()); | |
2780 CiKind dataKind = dataKindForPointerOp(opcode); | |
2781 Value offsetOrIndex; | |
2782 Value displacement; | |
2783 if ((opcode & 0xff) == PREAD) { | |
2784 offsetOrIndex = popOffsetOrIndexForPointerOp(opcode >= PREAD_BYTE_I && opcode <= PREAD_REFERENCE_I); | |
2785 displacement = null; | |
2786 } else { | |
2787 offsetOrIndex = popOffsetOrIndexForPointerOp(true); | |
2788 displacement = ipop(); | |
2789 } | |
2790 Value pointer = wpop(); | |
2791 push(dataKind.stackKind(), append(new LoadPointer(dataKind, opcode, pointer, displacement, offsetOrIndex, stateBefore, false))); | |
2792 } | |
2793 | |
2794 private void genStorePointer(int opcode) { | |
2795 FrameState stateBefore = curState.immutableCopy(bci()); | |
2796 CiKind dataKind = dataKindForPointerOp(opcode); | |
2797 Value value = pop(dataKind.stackKind()); | |
2798 Value offsetOrIndex; | |
2799 Value displacement; | |
2800 if ((opcode & 0xff) == PWRITE) { | |
2801 offsetOrIndex = popOffsetOrIndexForPointerOp(opcode >= PWRITE_BYTE_I && opcode <= PWRITE_REFERENCE_I); | |
2802 displacement = null; | |
2803 } else { | |
2804 offsetOrIndex = popOffsetOrIndexForPointerOp(true); | |
2805 displacement = ipop(); | |
2806 } | |
2807 Value pointer = wpop(); | |
2808 append(new StorePointer(opcode, dataKind, pointer, displacement, offsetOrIndex, value, stateBefore, false)); | |
2809 } | |
2810 | |
2811 private static CiKind kindForCompareAndSwap(int opcode) { | |
2812 switch (opcode) { | |
2813 case PCMPSWP_INT : | |
2814 case PCMPSWP_INT_I : return CiKind.Int; | |
2815 case PCMPSWP_WORD : | |
2816 case PCMPSWP_WORD_I : return CiKind.Word; | |
2817 case PCMPSWP_REFERENCE : | |
2818 case PCMPSWP_REFERENCE_I: return CiKind.Object; | |
2819 default: | |
2820 throw new CiBailout("Unsupported compare-and-swap opcode " + opcode + "(" + nameOf(opcode) + ")"); | |
2821 } | |
2822 } | |
2823 | |
2824 private void genCompareAndSwap(int opcode) { | |
2825 FrameState stateBefore = curState.immutableCopy(bci()); | |
2826 CiKind kind = kindForCompareAndSwap(opcode); | |
2827 Value newValue = pop(kind); | |
2828 Value expectedValue = pop(kind); | |
2829 Value offset; | |
2830 offset = popOffsetOrIndexForPointerOp(opcode >= PCMPSWP_INT_I && opcode <= PCMPSWP_REFERENCE_I); | |
2831 Value pointer = wpop(); | |
2832 push(kind, append(new CompareAndSwap(opcode, pointer, offset, expectedValue, newValue, stateBefore, false))); | |
2833 } | |
2834 | |
2835 | |
2836 private void genMemoryBarrier(int barriers) { | |
2837 int explicitMemoryBarriers = barriers & ~compilation.target.arch.implicitMemoryBarriers; | |
2838 if (explicitMemoryBarriers != 0) { | |
2839 append(new MemoryBarrier(explicitMemoryBarriers)); | |
2840 } | 2360 } |
2841 } | 2361 } |
2842 | 2362 |
2843 private void genArrayLength() { | 2363 private void genArrayLength() { |
2844 FrameState stateBefore = curState.immutableCopy(bci()); | 2364 FrameState stateBefore = curState.immutableCopy(bci()); |