# HG changeset patch # User Lukas Stadler # Date 1307633588 -7200 # Node ID f9c6d9bc4fbcbb220583ff3fc13f799f2f146610 # Parent 0e3ec0a4eda4fa22df25309173a884b60bea1222 RiMethod provides branch prediction information diff -r 0e3ec0a4eda4 -r f9c6d9bc4fbc 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 Thu Jun 09 15:25:27 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Thu Jun 09 17:33:08 2011 +0200 @@ -133,6 +133,9 @@ public Block next; } + public static class DeoptBlock extends Block { + } + private static final Block[] NO_SUCCESSORS = new Block[0]; /** @@ -257,9 +260,15 @@ case IF_ACMPNE: // fall through case IFNULL: // fall through case IFNONNULL: { + int probability = method.branchProbability(bci); +// if (probability == 0 || probability == 100) { +// System.out.println("prob: " + probability); +// } current = null; Block b1 = makeBlock(bci + 3); Block b2 = makeBlock(bci + Bytes.beS2(code, bci + 1)); +// Block b1 = probability == 100 ? makeDeoptBlock(bci + 3) : makeBlock(bci + 3); +// Block b2 = probability == 0 ? makeDeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1)); setSuccessors(bci, b1, b2); assert lengthOf(code, bci) == 3; @@ -376,6 +385,14 @@ } } + private Block makeDeoptBlock(int startBci) { + System.out.println("Deopt block created"); + DeoptBlock newBlock = new DeoptBlock(); + newBlock.startBci = startBci; + blockMap[startBci] = newBlock; + return newBlock; + } + private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) { int max = tswitch.numberOfCases(); Block[] successors = new Block[max + 1]; diff -r 0e3ec0a4eda4 -r f9c6d9bc4fbc 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 Thu Jun 09 15:25:27 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Thu Jun 09 17:33:08 2011 +0200 @@ -31,6 +31,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.graph.*; +import com.oracle.max.graal.compiler.graph.BlockMap.DeoptBlock; import com.oracle.max.graal.compiler.graph.BlockMap.*; import com.oracle.max.graal.compiler.graph.BlockMap.Block; import com.oracle.max.graal.compiler.ir.*; @@ -1153,6 +1154,8 @@ createUnwindBlock(block); } else if (block instanceof ExceptionBlock) { createExceptionDispatch((ExceptionBlock) block); + } else if (block instanceof DeoptBlock) { + createDeoptBlock((DeoptBlock) block); } else { iterateBytecodesForBlock(block); } @@ -1182,6 +1185,10 @@ } } + private void createDeoptBlock(DeoptBlock block) { + append(new Deoptimize(graph)); + } + private void createUnwindBlock(Block block) { if (Modifier.isSynchronized(method.accessFlags())) { genMonitorExit(methodSynchronizedObject); diff -r 0e3ec0a4eda4 -r f9c6d9bc4fbc 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 Thu Jun 09 15:25:27 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolved.java Thu Jun 09 17:33:08 2011 +0200 @@ -201,4 +201,8 @@ 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 0e3ec0a4eda4 -r f9c6d9bc4fbc 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 Thu Jun 09 15:25:27 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodUnresolved.java Thu Jun 09 17:33:08 2011 +0200 @@ -163,4 +163,8 @@ public RiTypeProfile typeProfile(int bci) { return null; } + + public int branchProbability(int bci) { + return -1; + } } diff -r 0e3ec0a4eda4 -r f9c6d9bc4fbc 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 Thu Jun 09 15:25:27 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntries.java Thu Jun 09 17:33:08 2011 +0200 @@ -99,5 +99,7 @@ RiTypeProfile RiMethod_typeProfile(long vmId, int bci); + int RiMethod_branchProbability(long vmId, int bci); + // Checkstyle: resume } diff -r 0e3ec0a4eda4 -r f9c6d9bc4fbc 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 Thu Jun 09 15:25:27 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMEntriesNative.java Thu Jun 09 17:33:08 2011 +0200 @@ -144,5 +144,8 @@ @Override public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); + @Override + public native int RiMethod_branchProbability(long vmId, int bci); + // Checkstyle: resume } diff -r 0e3ec0a4eda4 -r f9c6d9bc4fbc src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Thu Jun 09 15:25:27 2011 +0200 +++ b/src/share/vm/c1/c1_Runtime1.cpp Thu Jun 09 17:33:08 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 0e3ec0a4eda4 -r f9c6d9bc4fbc src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Thu Jun 09 15:25:27 2011 +0200 +++ b/src/share/vm/graal/graalVMEntries.cpp Thu Jun 09 17:33:08 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,13 +159,13 @@ return JNIHandles::make_local(THREAD, method_resolved); } -// public native int RiMethod_invocationCount(); +// 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(int bci); +// 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; @@ -192,6 +193,50 @@ 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"); @@ -723,6 +768,7 @@ {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)},