# HG changeset patch # User Gilles Duboscq # Date 1307694454 -7200 # Node ID 7300d86deac27e94002117ed0ba06b112ab1fac5 # Parent 5f1778eb38543ca7b7ae3e2bb97058b1f2ab739b# Parent 1e13559b112db496b8a3013b8b38988d9687c6ce Merge diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jun 10 10:27:34 2011 +0200 @@ -104,8 +104,9 @@ // Code generator settings public static boolean GenLIR = true; public static boolean GenCode = true; + public static boolean UseBranchPrediction = ____; - public static boolean UseConstDirectCall = false; + public static boolean UseConstDirectCall = ____; public static boolean GenSpecialDivChecks = ____; public static boolean GenAssertionCode = ____; diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jun 10 10:27:34 2011 +0200 @@ -164,7 +164,12 @@ assert lastOp instanceof LIRBranch : "branch must be of type LIRBranch"; LIRBranch lastBranch = (LIRBranch) lastOp; - assert lastBranch.block() != null : "last branch must always have a block as target"; + if (lastBranch.block() == null) { + // this might target a deoptimization stub... + // TODO check if the target is really a deopt stub... +// assert lastBranch.block() != null : "last branch must always have a block as target, current block #" + block.blockID(); + continue; + } assert lastBranch.label() == lastBranch.block().label() : "must be equal"; if (lastBranch.info == null) { diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jun 10 10:27:34 2011 +0200 @@ -140,6 +140,7 @@ stream.println(" "); stream.println(" "); + flush(); } private List printNodes(Collection nodes, boolean shortNames, NodeMap nodeToBlock) { diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Fri Jun 10 10:27:34 2011 +0200 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.*; import com.sun.cri.bytecode.*; @@ -133,6 +134,14 @@ public Block next; } + public static class DeoptBlock extends Block { + } + + public static class BranchOverride { + public DeoptBlock block; + public boolean taken; + } + private static final Block[] NO_SUCCESSORS = new Block[0]; /** @@ -148,6 +157,8 @@ private final RiMethod method; + public final HashMap branchOverride; + private Block[] blockMap; private BitSet canTrap; @@ -164,6 +175,7 @@ } this.blocks = new ArrayList(); this.storesInLoops = new BitSet(method.maxLocals()); + branchOverride = new HashMap(); } /** @@ -258,8 +270,11 @@ case IFNULL: // fall through case IFNONNULL: { current = null; - Block b1 = makeBlock(bci + 3); - Block b2 = makeBlock(bci + Bytes.beS2(code, bci + 1)); + + int probability = GraalOptions.UseBranchPrediction ? method.branchProbability(bci) : -1; + + Block b1 = probability == 100 ? makeBranchOverrideBlock(bci, bci + 3, false) : makeBlock(bci + 3); + Block b2 = probability == 0 ? makeBranchOverrideBlock(bci, bci + Bytes.beS2(code, bci + 1), true) : makeBlock(bci + Bytes.beS2(code, bci + 1)); setSuccessors(bci, b1, b2); assert lengthOf(code, bci) == 3; @@ -376,6 +391,17 @@ } } + private Block makeBranchOverrideBlock(int branchBci, int startBci, boolean taken) { + DeoptBlock newBlock = new DeoptBlock(); + newBlock.startBci = startBci; + BranchOverride override = new BranchOverride(); + override.block = newBlock; + override.taken = taken; + assert branchOverride.get(branchBci) == null; + branchOverride.put(branchBci, override); + return newBlock; + } + private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) { int max = tswitch.numberOfCases(); Block[] successors = new Block[max + 1]; diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Fri Jun 10 10:27:34 2011 +0200 @@ -84,6 +84,7 @@ public final RiMethod target; public final RiType returnType; public final int bci; // XXX needed because we can not compute the bci from the sateBefore bci of this Invoke was optimized from INVOKEINTERFACE to INVOKESPECIAL + public final RiTypeProfile profile; /** * Constructs a new Invoke instruction. @@ -95,12 +96,13 @@ * @param target the target method being called * @param stateBefore the state before executing the invocation */ - public Invoke(int bci, int opcode, CiKind result, Value[] args, RiMethod target, RiType returnType, Graph graph) { + public Invoke(int bci, int opcode, CiKind result, Value[] args, RiMethod target, RiType returnType, RiTypeProfile profile, Graph graph) { super(result, args.length, SUCCESSOR_COUNT, graph); this.opcode = opcode; this.target = target; this.returnType = returnType; this.bci = bci; + this.profile = profile; this.argumentCount = args.length; for (int i = 0; i < args.length; i++) { @@ -147,6 +149,10 @@ return target; } + public RiTypeProfile profile() { + return profile; + } + /** * Checks whether this invocation has a receiver object. * @return {@code true} if this invocation has a receiver object; {@code false} otherwise, if this is a @@ -196,7 +202,7 @@ @Override public Node copy(Graph into) { - Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, into); + Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, profile, into); return x; } } diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Jun 10 10:27:34 2011 +0200 @@ -77,6 +77,7 @@ // bci-to-block mapping private Block[] blockFromBci; private ArrayList blockList; + private HashMap branchOverride; private int nextBlockNumber; @@ -144,6 +145,7 @@ // 2. compute the block map, setup exception handlers and get the entrypoint(s) BlockMap blockMap = compilation.getBlockMap(method); + this.branchOverride = blockMap.branchOverride; blockList = new ArrayList(blockMap.blocks); blockFromBci = new Block[method.code().length]; @@ -151,7 +153,7 @@ int blockID = nextBlockNumber(); assert blockID == i; Block block = blockList.get(i); - if (block.startBci >= 0) { + if (block.startBci >= 0 && !(block instanceof BlockMap.DeoptBlock)) { blockFromBci[block.startBci] = block; } } @@ -653,9 +655,20 @@ assert !x.isDeleted() && !y.isDeleted(); If ifNode = new If(new Compare(x, cond, y, graph), graph); append(ifNode); - Instruction tsucc = createTargetAt(stream().readBranchDest(), frameState); + BlockMap.BranchOverride override = branchOverride.get(bci()); + Instruction tsucc; + if (override == null || override.taken == false) { + tsucc = createTargetAt(stream().readBranchDest(), frameState); + } else { + tsucc = createTarget(override.block, frameState); + } ifNode.setBlockSuccessor(0, tsucc); - Instruction fsucc = createTargetAt(stream().nextBCI(), frameState); + Instruction fsucc; + if (override == null || override.taken == true) { + fsucc = createTargetAt(stream().nextBCI(), frameState); + } else { + fsucc = createTarget(override.block, frameState); + } ifNode.setBlockSuccessor(1, fsucc); } @@ -906,7 +919,7 @@ private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { CiKind resultType = returnKind(target); - Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph); + Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), method.typeProfile(bci()), graph); Value result = appendWithBCI(invoke); invoke.setExceptionEdge(handleException(null, bci())); frameState.pushReturn(resultType, result); @@ -1093,7 +1106,8 @@ private Instruction createTarget(Block block, FrameStateAccess stateAfter) { assert block != null && stateAfter != null; - assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors"; + assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : + "non-loop block must be iterated after all its predecessors. startBci=" + block.startBci + ", " + block.getClass().getSimpleName() + ", " + block.firstInstruction.next(); if (block.isExceptionEntry) { assert stateAfter.stackSize() == 1; @@ -1153,6 +1167,8 @@ createUnwindBlock(block); } else if (block instanceof ExceptionBlock) { createExceptionDispatch((ExceptionBlock) block); + } else if (block instanceof DeoptBlock) { + createDeoptBlock((DeoptBlock) block); } else { iterateBytecodesForBlock(block); } @@ -1182,6 +1198,13 @@ } } + private void createDeoptBlock(DeoptBlock block) { +// Merge x = new Merge(graph); +// x.setStateBefore(((StateSplit) block.firstInstruction).stateBefore()); +// append(x); + append(new Deoptimize(graph)); + } + private void createUnwindBlock(Block block) { if (Modifier.isSynchronized(method.accessFlags())) { genMonitorExit(methodSynchronizedObject); diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jun 10 10:27:34 2011 +0200 @@ -135,6 +135,12 @@ private boolean checkInliningConditions(Invoke invoke) { String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false); + if (invoke.profile() != null && invoke.profile().count < compilation.method.invocationCount() / 2) { + if (trace) { + System.out.println("not inlining " + name + " because the invocation counter is too low"); + } + return false; + } if (invoke.predecessors().size() == 0) { if (trace) { System.out.println("not inlining " + name + " because the invoke is dead code"); diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolved.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolved.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolved.java Fri Jun 10 10:27:34 2011 +0200 @@ -39,6 +39,7 @@ private int accessFlags = -1; private int maxLocals = -1; private int maxStackSize = -1; + private int invocationCount = -1; private RiExceptionHandler[] exceptionHandlers; private RiSignature signature; private Boolean hasBalancedMonitors; @@ -89,12 +90,12 @@ @Override public boolean isClassInitializer() { - return "".equals(name); + return "".equals(name) && Modifier.isStatic(accessFlags()); } @Override public boolean isConstructor() { - return "".equals(name); + return "".equals(name) && !Modifier.isStatic(accessFlags()); } @Override @@ -189,4 +190,19 @@ public boolean minimalDebugInfo() { return false; } + + public int invocationCount() { + if (invocationCount == -1) { + invocationCount = compiler.getVMEntries().RiMethod_invocationCount(vmId); + } + return invocationCount; + } + + public RiTypeProfile typeProfile(int bci) { + return compiler.getVMEntries().RiMethod_typeProfile(vmId, bci); + } + + public int branchProbability(int bci) { + return compiler.getVMEntries().RiMethod_branchProbability(vmId, bci); + } } diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Fri Jun 10 10:27:34 2011 +0200 @@ -155,4 +155,16 @@ public int intrinsic() { return 0; } + + public int invocationCount() { + return -1; + } + + public RiTypeProfile typeProfile(int bci) { + return null; + } + + public int branchProbability(int bci) { + return -1; + } } diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java Fri Jun 10 10:27:34 2011 +0200 @@ -95,5 +95,11 @@ RiType getRiType(CiConstant constant); + int RiMethod_invocationCount(long vmId); + + RiTypeProfile RiMethod_typeProfile(long vmId, int bci); + + int RiMethod_branchProbability(long vmId, int bci); + // Checkstyle: resume } diff -r 5f1778eb3854 -r 7300d86deac2 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java Fri Jun 10 10:27:23 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java Fri Jun 10 10:27:34 2011 +0200 @@ -138,5 +138,14 @@ return getType(o.getClass()); } + @Override + public native int RiMethod_invocationCount(long vmId); + + @Override + public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); + + @Override + public native int RiMethod_branchProbability(long vmId, int bci); + // Checkstyle: resume } diff -r 5f1778eb3854 -r 7300d86deac2 src/cpu/x86/vm/c1_globals_x86.hpp --- a/src/cpu/x86/vm/c1_globals_x86.hpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/cpu/x86/vm/c1_globals_x86.hpp Fri Jun 10 10:27:34 2011 +0200 @@ -40,7 +40,7 @@ define_pd_global(bool, ProfileTraps, false); define_pd_global(bool, UseOnStackReplacement, true ); define_pd_global(bool, TieredCompilation, false); -define_pd_global(intx, CompileThreshold, 1500 ); +define_pd_global(intx, CompileThreshold, 10000 ); // changed for GRAAL define_pd_global(intx, BackEdgeThreshold, 100000); define_pd_global(intx, OnStackReplacePercentage, 933 ); @@ -48,7 +48,7 @@ define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(intx, InitialCodeCacheSize, 160*K); define_pd_global(intx, ReservedCodeCacheSize, 32*M ); -define_pd_global(bool, ProfileInterpreter, false); +define_pd_global(bool, ProfileInterpreter, true ); // changed for GRAAL define_pd_global(intx, CodeCacheExpansionSize, 32*K ); define_pd_global(uintx,CodeCacheMinBlockLength, 1); define_pd_global(uintx,PermSize, 12*M ); @@ -57,7 +57,7 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); #endif // !TIERED -define_pd_global(bool, UseTypeProfile, false); +define_pd_global(bool, UseTypeProfile, true ); // changed for GRAAL define_pd_global(bool, RoundFPResults, true ); define_pd_global(bool, LIRFillDelaySlots, false); diff -r 5f1778eb3854 -r 7300d86deac2 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Jun 10 10:27:34 2011 +0200 @@ -2669,8 +2669,10 @@ // fetch_unroll_info needs to call last_java_frame() __ set_last_Java_frame(noreg, noreg, NULL); - __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute); - __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames + // __ movl(c_rarg1, (int32_t)Deoptimization::Unpack_reexecute); + // __ movl(r14, c_rarg1); // save into r14 for later call to unpack_frames + __ movl(c_rarg1, (int32_t)-1); + __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute); __ mov(c_rarg0, r15_thread); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/c1/c1_Runtime1.cpp Fri Jun 10 10:27:34 2011 +0200 @@ -216,7 +216,6 @@ // All other stubs should have oopmaps default: - tty->print_cr("No oopmap found for %d", id); assert(oop_maps != NULL, "must have an oopmap"); } #endif diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Jun 10 10:27:34 2011 +0200 @@ -182,14 +182,14 @@ template(Integer_klass, java_lang_Integer, Pre) \ template(Long_klass, java_lang_Long, Pre) \ \ - template(graalOptions_klass, com_sun_graal_graalOptions, Opt) \ - template(HotSpotTypeResolved_klass, com_sun_hotspot_graal_HotSpotTypeResolved, Opt) \ - template(HotSpotType_klass, com_sun_hotspot_graal_HotSpotType, Opt) \ - template(HotSpotField_klass, com_sun_hotspot_graal_HotSpotField, Opt) \ - template(HotSpotMethodResolved_klass, com_sun_hotspot_graal_HotSpotMethodResolved, Opt) \ - template(HotSpotTargetMethod_klass, com_sun_hotspot_graal_HotSpotTargetMethod, Opt) \ - template(HotSpotExceptionHandler_klass,com_sun_hotspot_graal_HotSpotExceptionHandler, Opt) \ - template(HotSpotProxy_klass, com_sun_hotspot_graal_HotSpotProxy, Opt) \ + template(graalOptions_klass, com_sun_graal_graalOptions, Opt) \ + template(HotSpotTypeResolved_klass, com_sun_hotspot_graal_HotSpotTypeResolved, Opt) \ + template(HotSpotType_klass, com_sun_hotspot_graal_HotSpotType, Opt) \ + template(HotSpotField_klass, com_sun_hotspot_graal_HotSpotField, Opt) \ + template(HotSpotMethodResolved_klass, com_sun_hotspot_graal_HotSpotMethodResolved, Opt) \ + template(HotSpotTargetMethod_klass, com_sun_hotspot_graal_HotSpotTargetMethod, Opt) \ + template(HotSpotExceptionHandler_klass,com_sun_hotspot_graal_HotSpotExceptionHandler, Opt) \ + template(HotSpotProxy_klass, com_sun_hotspot_graal_HotSpotProxy, Opt) \ template(CiAssumptions_klass, com_sun_cri_ci_CiAssumptions, Opt) \ template(CiAssumptions_ConcreteSubtype_klass, com_sun_cri_ci_CiAssumptions_ConcreteSubtype, Opt) \ template(CiAssumptions_ConcreteMethod_klass, com_sun_cri_ci_CiAssumptions_ConcreteMethod, Opt) \ @@ -213,6 +213,7 @@ template(CiRuntimeCall_klass, com_sun_cri_ci_CiRuntimeCall, Opt) \ template(RiMethod_klass, com_sun_cri_ri_RiMethod, Opt) \ template(RiExceptionHandler_klass, com_sun_cri_ri_RiExceptionHandler, Opt) \ + template(RiTypeProfile_klass, com_sun_cri_ri_RiTypeProfile, Opt) \ /*end*/ diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Jun 10 10:27:34 2011 +0200 @@ -273,6 +273,7 @@ template(com_sun_cri_ri_RiMethod, "com/sun/cri/ri/RiMethod") \ template(com_sun_cri_ri_RiField, "com/sun/cri/ri/RiField") \ template(com_sun_cri_ri_RiType, "com/sun/cri/ri/RiType") \ + template(com_sun_cri_ri_RiTypeProfile, "com/sun/cri/ri/RiTypeProfile") \ template(com_sun_cri_ri_RiConstantPool, "com/sun/cri/ri/RiConstantPool") \ template(com_sun_cri_ri_RiExceptionHandler, "com/sun/cri/ri/RiExceptionHandler") \ template(com_sun_cri_ci_CiAssumptions, "com/sun/cri/ci/CiAssumptions") \ diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/graal/graalJavaAccess.cpp --- a/src/share/vm/graal/graalJavaAccess.cpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/graal/graalJavaAccess.cpp Fri Jun 10 10:27:34 2011 +0200 @@ -61,12 +61,13 @@ #define INT_FIELD(klass, name) FIELD(klass, name, "I", false) #define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false) #define LONG_FIELD(klass, name) FIELD(klass, name, "J", false) +#define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false) #define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false) #define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true) void graal_compute_offsets() { - COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, OOP_FIELD, STATIC_OOP_FIELD) + COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) } #define EMPTY0 @@ -75,7 +76,7 @@ #define FIELD2(klass, name) int klass::_##name##_offset = 0; #define FIELD3(klass, name, sig) FIELD2(klass, name) -COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3) +COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3) diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Jun 10 10:27:34 2011 +0200 @@ -44,7 +44,7 @@ * */ -#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, oop_field, static_oop_field) \ +#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field) \ start_class(HotSpotTypeResolved) \ oop_field(HotSpotTypeResolved, compiler, "Lcom/oracle/max/graal/runtime/Compiler;") \ oop_field(HotSpotTypeResolved, javaMirror, "Ljava/lang/Class;") \ @@ -200,11 +200,14 @@ start_class(CiStackSlot) \ int_field(CiStackSlot, index) \ end_class \ + start_class(RiTypeProfile) \ + int_field(RiTypeProfile, count) \ + int_field(RiTypeProfile, morphism) \ + oop_field(RiTypeProfile, probabilities, "[F") \ + oop_field(RiTypeProfile, types, "[Lcom/sun/cri/ri/RiType;") \ + end_class \ /* end*/ - - - #define START_CLASS(name) \ class name : AllStatic { \ private: \ @@ -229,6 +232,7 @@ #define INT_FIELD(klass, name) FIELD(name, jint, int_field) #define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field) #define LONG_FIELD(klass, name) FIELD(name, jlong, long_field) +#define FLOAT_FIELD(klass, name) FIELD(name, jfloat, float_field) #define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field) #define STATIC_OOP_FIELD(klassName, name, signature) \ static int _##name##_offset; \ @@ -250,7 +254,7 @@ oopDesc::encode_store_heap_oop((oop*)addr, x); \ } \ } -COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, OOP_FIELD, STATIC_OOP_FIELD) +COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) #undef START_CLASS #undef END_CLASS #undef FIELD @@ -258,6 +262,7 @@ #undef INT_FIELD #undef BOOLEAN_FIELD #undef LONG_FIELD +#undef FLOAT_FIELD #undef OOP_FIELD #undef STATIC_OOP_FIELD diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/graal/graalVMEntries.cpp Fri Jun 10 10:27:34 2011 +0200 @@ -30,6 +30,7 @@ #include "graal/graalVmIds.hpp" #include "c1/c1_Runtime1.hpp" #include "memory/oopFactory.hpp" +#include "ci/ciMethodData.hpp" // public byte[] RiMethod_code(long vmId); JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jlong vmId) { @@ -158,6 +159,84 @@ return JNIHandles::make_local(THREAD, method_resolved); } +// public native int RiMethod_invocationCount(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1invocationCount(JNIEnv *, jobject, jlong vmId) { + TRACE_graal_3("VMEntries::RiMethod_invocationCount"); + return VmIds::get(vmId)->invocation_count(); +} + +// public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1typeProfile(JNIEnv *, jobject, jlong vmId, jint bci) { + TRACE_graal_3("VMEntries::RiMethod_typeProfile"); + ciMethod* cimethod; + { + VM_ENTRY_MARK; + cimethod = (ciMethod*)CURRENT_ENV->get_object(VmIds::get(vmId)); + } + + ciCallProfile profile = cimethod->call_profile_at_bci(bci); + + Handle obj; + { + VM_ENTRY_MARK; + instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL); + obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL); + assert(obj() != NULL, "must succeed in allocating instance"); + + RiTypeProfile::set_count(obj, cimethod->scale_count(profile.count(), 1)); + RiTypeProfile::set_morphism(obj, profile.morphism()); + + RiTypeProfile::set_probabilities(obj, NULL); + RiTypeProfile::set_types(obj, NULL); + } + + return JNIHandles::make_local(obj()); +} + +// public native RiTypeProfile RiMethod_branchProfile(long vmId, int bci); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1branchProbability(JNIEnv *, jobject, jlong vmId, jint bci) { + TRACE_graal_3("VMEntries::RiMethod_typeProfile"); + ciMethodData* method_data; + ciMethod* cimethod; + { + VM_ENTRY_MARK; + cimethod = (ciMethod*)CURRENT_ENV->get_object(VmIds::get(vmId)); + } + method_data = cimethod->method_data(); + + jfloat probability = -1; + + if (!method_data->is_mature()) return -1; + + ciProfileData* data = method_data->bci_to_data(bci); + if (!data->is_JumpData()) return -1; + + // get taken and not taken values + int taken = data->as_JumpData()->taken(); + int not_taken = 0; + if (data->is_BranchData()) { + not_taken = data->as_BranchData()->not_taken(); + } + + // scale the counts to be commensurate with invocation counts: + taken = cimethod->scale_count(taken); + not_taken = cimethod->scale_count(not_taken); + + // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. + // We also check that individual counters are positive first, otherwise the sum can become positive. + if (taken < 0 || not_taken < 0 || taken + not_taken < 40) return -1; + + // Pin probability to sane limits + if (taken == 0) + return 0; + else if (not_taken == 0) + return 100; + else { // Compute probability of true path + int probability = (int)(taken * 100.0 / (taken + not_taken)); + return MIN2(99, MAX2(1, probability)); + } +} + // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { TRACE_graal_3("VMEntries::RiSignature_lookupType"); @@ -354,6 +433,7 @@ default: constant.print(); fatal("Unhandled constant"); + break; } if (constant_object != NULL) { HotSpotField::set_constant(field_handle, constant_object); @@ -614,6 +694,7 @@ #endif // SERIALGC default: ShouldNotReachHere(); + break; } jintArray arrayOffsets = env->NewIntArray(basicTypeCount); @@ -661,6 +742,7 @@ #define TYPE "Lcom/sun/cri/ri/RiType;" #define RESOLVED_TYPE "Lcom/oracle/max/graal/runtime/HotSpotTypeResolved;" #define METHOD "Lcom/sun/cri/ri/RiMethod;" +#define TYPE_PROFILE "Lcom/sun/cri/ri/RiTypeProfile;" #define SIGNATURE "Lcom/sun/cri/ri/RiSignature;" #define FIELD "Lcom/sun/cri/ri/RiField;" #define CONSTANT_POOL "Lcom/sun/cri/ri/RiConstantPool;" @@ -684,6 +766,9 @@ {CC"RiMethod_exceptionHandlers", CC"("PROXY")"EXCEPTION_HANDLERS, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers)}, {CC"RiMethod_hasBalancedMonitors", CC"("PROXY")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors)}, {CC"RiMethod_uniqueConcreteMethod", CC"("PROXY")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod)}, + {CC"RiMethod_invocationCount", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1invocationCount)}, + {CC"RiMethod_typeProfile", CC"("PROXY"I)"TYPE_PROFILE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1typeProfile)}, + {CC"RiMethod_branchProbability", CC"("PROXY"I)I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1branchProbability)}, {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType)}, {CC"RiConstantPool_lookupConstant", CC"("PROXY"I)"OBJECT, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant)}, {CC"RiConstantPool_lookupMethod", CC"("PROXY"IB)"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod)}, diff -r 5f1778eb3854 -r 7300d86deac2 src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Fri Jun 10 10:27:23 2011 +0200 +++ b/src/share/vm/runtime/java.cpp Fri Jun 10 10:27:34 2011 +0200 @@ -419,9 +419,9 @@ #define BEFORE_EXIT_DONE 2 static jint volatile _before_exit_status = BEFORE_EXIT_NOT_RUN; - if (UseGraal) { - GraalCompiler::instance()->exit(); - } +// if (UseGraal) { +// GraalCompiler::instance()->exit(); +// } // Note: don't use a Mutex to guard the entire before_exit(), as // JVMTI post_thread_end_event and post_vm_death_event will run native code.