# HG changeset patch # User Thomas Wuerthinger # Date 1397822967 -7200 # Node ID 27afd57655bab7071bf38af367510f868d3d5a94 # Parent 7aa0ef5348e526588c008a3e9c53a116d1604bc1# Parent 25a18b4a5b90ec0d7037fb69650748676ad9880a Merge. diff -r 25a18b4a5b90 -r 27afd57655ba graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Fri Apr 18 13:45:41 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Fri Apr 18 14:09:27 2014 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; /** * The {@code ArrayLength} instruction gets the length of an array. @@ -57,18 +58,25 @@ /** * Gets the length of an array if possible. * - * @param graph TODO - * @param array an array - * * @return a node representing the length of {@code array} or null if it is not available */ - public static ValueNode readArrayLength(StructuredGraph graph, ValueNode array, ConstantReflectionProvider constantReflection) { - if (array instanceof ArrayLengthProvider) { - ValueNode length = ((ArrayLengthProvider) array).length(); + public static ValueNode readArrayLength(StructuredGraph graph, ValueNode originalArray, ConstantReflectionProvider constantReflection) { + ArrayLengthProvider foundArrayLengthProvider = null; + ValueNode result = originalArray; + while (result instanceof ValueProxy) { + if (result instanceof ArrayLengthProvider) { + foundArrayLengthProvider = (ArrayLengthProvider) result; + } + result = ((ValueProxy) result).getOriginalNode(); + } + + if (foundArrayLengthProvider != null) { + ValueNode length = foundArrayLengthProvider.length(); if (length != null) { return length; } } + ValueNode array = GraphUtil.unproxify(originalArray); if (constantReflection != null && array.isConstant() && !array.isNullConstant()) { Constant constantValue = array.asConstant(); if (constantValue != null && constantValue.isNonNull()) { diff -r 25a18b4a5b90 -r 27afd57655ba 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 Fri Apr 18 13:45:41 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Fri Apr 18 14:09:27 2014 +0200 @@ -51,6 +51,8 @@ protected final CompilationPolicy compilationPolicy; private OptimizedCallTarget splitSource; private final AtomicInteger callSitesKnown = new AtomicInteger(0); + @CompilationFinal private Class[] profiledArgumentTypes; + @CompilationFinal private Assumption profiledArgumentTypesAssumption; @CompilationFinal private Class profiledReturnType; @CompilationFinal private Assumption profiledReturnTypeAssumption; @@ -83,9 +85,21 @@ } 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; + } + } + Object result = callBoundary(args); Class klass = profiledReturnType; - if (klass != null && profiledReturnTypeAssumption.isValid()) { + if (klass != null && CompilerDirectives.inCompiledCode() && profiledReturnTypeAssumption.isValid()) { result = CompilerDirectives.unsafeCast(result, klass, true, true); } return result; @@ -247,7 +261,13 @@ } } - public final Object callRoot(Object[] args) { + 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); + } + VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args); Object result = callProxy(frame); @@ -269,6 +289,10 @@ return result; } + private static Object castArrayFixedLength(Object[] args, @SuppressWarnings("unused") int length) { + return args; + } + public static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) { return new FrameWithoutBoxing(descriptor, args); } diff -r 25a18b4a5b90 -r 27afd57655ba graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Fri Apr 18 13:45:41 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Fri Apr 18 14:09:27 2014 +0200 @@ -55,6 +55,11 @@ } @MethodSubstitution + public static boolean inCompiledCode() { + return true; + } + + @MethodSubstitution public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) { } diff -r 25a18b4a5b90 -r 27afd57655ba graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Fri Apr 18 13:45:41 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Fri Apr 18 14:09:27 2014 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.truffle.substitutions; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.truffle.api.frame.*; @@ -34,4 +36,9 @@ private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) { return NewFrameNode.allocate(FrameWithoutBoxing.class, descriptor, args); } + + @MethodSubstitution + private static Object castArrayFixedLength(Object[] args, int length) { + return PiArrayNode.piArrayCast(args, length, StampFactory.forNodeIntrinsic()); + } } diff -r 25a18b4a5b90 -r 27afd57655ba graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Fri Apr 18 13:45:41 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Fri Apr 18 14:09:27 2014 +0200 @@ -84,6 +84,15 @@ } /** + * Returns a boolean value indicating whether the method is executed in the compiled code. + * + * @return {@code false} when executed in the interpreter, {@code true} in compiled code. + */ + public static boolean inCompiledCode() { + return false; + } + + /** * Directive for the compiler that the given runnable should only be executed in the interpreter * and ignored in the compiled code. *