# HG changeset patch # User Andreas Woess # Date 1405013787 -7200 # Node ID 352de9bd8fd52516d2aeb78632d42172081fcee6 # Parent cec5a97ba1e4dab7dae843076772fd1a986d92cf# Parent efbf9195dfcb6f730f612b0912d32a432a5bf709 Merge diff -r cec5a97ba1e4 -r 352de9bd8fd5 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Jul 10 19:34:49 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Jul 10 19:36:27 2014 +0200 @@ -113,22 +113,16 @@ @Override public Object call(Object... args) { + if (profiledArgumentTypesAssumption != null && profiledArgumentTypesAssumption.isValid()) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + profiledArgumentTypesAssumption.invalidate(); + profiledArgumentTypes = null; + } return callBoundary(args); } public Object callDirect(Object... args) { - if (profiledArgumentTypesAssumption == null) { - CompilerDirectives.transferToInterpreter(); - profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types"); - profiledArgumentTypes = new Class[args.length]; - } else if (profiledArgumentTypes != null) { - if (profiledArgumentTypes.length != args.length) { - CompilerDirectives.transferToInterpreter(); - profiledArgumentTypesAssumption.invalidate(); - profiledArgumentTypes = null; - } - } - + profileArguments(args); Object result = callBoundary(args); Class klass = profiledReturnType; if (klass != null && CompilerDirectives.inCompiledCode() && profiledReturnTypeAssumption.isValid()) { @@ -137,6 +131,66 @@ return result; } + @ExplodeLoop + private void profileArguments(Object[] args) { + if (profiledArgumentTypesAssumption == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + initializeProfiledArgumentTypes(args); + } else if (profiledArgumentTypes != null) { + if (profiledArgumentTypes.length != args.length) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + profiledArgumentTypesAssumption.invalidate(); + profiledArgumentTypes = null; + } else if (TruffleArgumentTypeSpeculation.getValue() && profiledArgumentTypesAssumption.isValid()) { + for (int i = 0; i < profiledArgumentTypes.length; i++) { + if (profiledArgumentTypes[i] != null && !profiledArgumentTypes[i].isInstance(args[i])) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + updateProfiledArgumentTypes(args); + break; + } + } + } + } + } + + private void initializeProfiledArgumentTypes(Object[] args) { + CompilerAsserts.neverPartOfCompilation(); + profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types"); + profiledArgumentTypes = new Class[args.length]; + if (TruffleArgumentTypeSpeculation.getValue()) { + for (int i = 0; i < args.length; i++) { + profiledArgumentTypes[i] = classOf(args[i]); + } + } + } + + private void updateProfiledArgumentTypes(Object[] args) { + CompilerAsserts.neverPartOfCompilation(); + profiledArgumentTypesAssumption.invalidate(); + for (int j = 0; j < profiledArgumentTypes.length; j++) { + profiledArgumentTypes[j] = joinTypes(profiledArgumentTypes[j], classOf(args[j])); + } + profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types"); + } + + private static Class classOf(Object arg) { + return arg != null ? arg.getClass() : null; + } + + private static Class joinTypes(Class class1, Class class2) { + if (class1 == class2) { + return class1; + } else if (class1 == null || class2 == null) { + return null; + } else if (class1.isAssignableFrom(class2)) { + return class1; + } else if (class2.isAssignableFrom(class1)) { + return class2; + } else { + return Object.class; + } + } + @TruffleCallBoundary private Object callBoundary(Object[] args) { if (CompilerDirectives.inInterpreter()) { @@ -313,10 +367,12 @@ } public final Object callRoot(Object[] originalArguments) { - Object[] args = originalArguments; if (this.profiledArgumentTypesAssumption != null && CompilerDirectives.inCompiledCode() && profiledArgumentTypesAssumption.isValid()) { args = CompilerDirectives.unsafeCast(castArrayFixedLength(args, profiledArgumentTypes.length), Object[].class, true, true); + if (TruffleArgumentTypeSpeculation.getValue() && this.profiledArgumentTypes != null) { + args = castArguments(args); + } } VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args); @@ -325,13 +381,13 @@ // Profile call return type if (profiledReturnTypeAssumption == null) { if (TruffleReturnTypeSpeculation.getValue()) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); profiledReturnType = (result == null ? null : result.getClass()); profiledReturnTypeAssumption = Truffle.getRuntime().createAssumption("Profiled Return Type"); } } else if (profiledReturnType != null) { if (result == null || profiledReturnType != result.getClass()) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); profiledReturnType = null; profiledReturnTypeAssumption.invalidate(); } @@ -340,6 +396,15 @@ return result; } + @ExplodeLoop + private Object[] castArguments(Object[] originalArguments) { + Object[] castArguments = new Object[profiledArgumentTypes.length]; + for (int i = 0; i < profiledArgumentTypes.length; i++) { + castArguments[i] = profiledArgumentTypes[i] != null ? CompilerDirectives.unsafeCast(originalArguments[i], profiledArgumentTypes[i], true, true) : originalArguments[i]; + } + return castArguments; + } + private static Object castArrayFixedLength(Object[] args, @SuppressWarnings("unused") int length) { return args; } diff -r cec5a97ba1e4 -r 352de9bd8fd5 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Thu Jul 10 19:34:49 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Thu Jul 10 19:36:27 2014 +0200 @@ -91,6 +91,8 @@ public static final OptionValue TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false); @Option(help = "") public static final OptionValue TruffleReturnTypeSpeculation = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TruffleArgumentTypeSpeculation = new StableOptionValue<>(true); // tracing @Option(help = "")