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());