# HG changeset patch # User Doug Simon # Date 1426175124 -3600 # Node ID 7ee4427666857a0623fab66f13fc39f098cacede # Parent 4bc9b6838303154ca510296a526649ffbfdd2b6d# Parent 4bc952439f2a7a0f62992a15f0bc97121f134ac2 Merge. diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu Mar 12 16:45:24 2015 +0100 @@ -134,9 +134,6 @@ @Option(help = "", type = OptionType.Debug) public static final OptionValue PrintFilter = new OptionValue<>(null); - @Option(help = "", type = OptionType.Debug) - public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); - // Debug settings: @Option(help = "", type = OptionType.Debug) public static final OptionValue BootstrapReplacements = new OptionValue<>(false); @@ -324,13 +321,6 @@ @Option(help = "Mark well-known stable fields as such.", type = OptionType.Debug) public static final OptionValue ImplicitStableValues = new OptionValue<>(true); - - @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug) - public static final OptionValue MaximumLoopExplosionCount = new OptionValue<>(10000); - - @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug) - public static final OptionValue FailedLoopExplosionIsFatal = new OptionValue<>(false); - /** * Counts the various paths taken through snippets. */ diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Mar 12 16:45:24 2015 +0100 @@ -1444,6 +1444,7 @@ @HotSpotVMValue(expression = "SharedRuntime::dsin", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticSinAddress; @HotSpotVMValue(expression = "SharedRuntime::dcos", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticCosAddress; @HotSpotVMValue(expression = "SharedRuntime::dtan", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticTanAddress; + @HotSpotVMValue(expression = "SharedRuntime::dpow", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticPowAddress; @HotSpotVMValue(expression = "(jint) GraalCounterSize") @Stable public int graalCountersSize; diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Mar 12 16:45:24 2015 +0100 @@ -150,6 +150,7 @@ registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_POW, c.arithmeticPowAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, ANY_LOCATION); registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java Thu Mar 12 16:45:24 2015 +0100 @@ -27,10 +27,10 @@ import static java.lang.String.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderContext.Replacement; import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; @@ -69,8 +69,10 @@ public void notifyOfNoninlinedInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { if (b.parsingReplacement()) { - boolean compilingSnippet = b.getRootMethod().getAnnotation(MethodSubstitution.class) == null; - assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", b.getRootMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)")); + boolean compilingSnippet = b.getRootMethod().getAnnotation(Snippet.class) != null; + Replacement replacement = b.getReplacement(); + assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", replacement.getReplacementMethod().format("%H.%n(%p)"), + method.format("%h.%n(%p)")); } } } diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Thu Mar 12 16:45:24 2015 +0100 @@ -27,6 +27,7 @@ import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; + import java.util.*; import com.oracle.graal.api.code.*; @@ -37,6 +38,7 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.GraphBuilderContext.Replacement; import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; import com.oracle.graal.java.GraphBuilderPlugin.LoadIndexedPlugin; @@ -51,18 +53,27 @@ @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); - @Option(help = "Inlines trivial methods during parsing of the bytecodes.", type = OptionType.Expert) + @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false); - @Option(help = "Traces inlining eagerly performed during bytecode parsing", type = OptionType.Debug) + @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); - @Option(help = "Traces use of bytecode parser plugins", type = OptionType.Debug) + @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug) public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); - @Option(help = "Maximum depth when inlining during parsing.", type = OptionType.Debug) + @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); + @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) + public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); + + @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug) + public static final OptionValue MaximumLoopExplosionCount = new OptionValue<>(10000); + + @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug) + public static final OptionValue FailedLoopExplosionIsFatal = new OptionValue<>(false); + // @formatter:on } @@ -71,7 +82,7 @@ * happen when a call to a {@link MethodSubstitution} is encountered or the root of compilation * is a {@link MethodSubstitution} or a snippet. */ - static class ReplacementContext { + static class ReplacementContext implements Replacement { /** * The method being replaced. */ @@ -87,6 +98,18 @@ this.replacement = substitute; } + public ResolvedJavaMethod getOriginalMethod() { + return method; + } + + public ResolvedJavaMethod getReplacementMethod() { + return replacement; + } + + public boolean isIntrinsic() { + return false; + } + /** * Determines if a call within the compilation scope of a replacement represents a call to * the original method. @@ -102,7 +125,7 @@ /** * Context for a replacement being inlined as a compiler intrinsic. Deoptimization within a - * compiler intrinic must replay the intrinsified call. This context object retains the + * compiler intrinsic must replay the intrinsified call. This context object retains the * information required to build a frame state denoting the JVM state just before the * intrinsified call. */ @@ -127,6 +150,11 @@ this.invokeBci = invokeBci; } + @Override + public boolean isIntrinsic() { + return true; + } + /** * Gets the frame state that will restart the interpreter just before the intrinsified * invocation. diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Thu Mar 12 16:45:24 2015 +0100 @@ -34,6 +34,30 @@ */ public interface GraphBuilderContext { + /** + * Information about a snippet or method substitution currently being processed by the graph + * builder. + */ + public interface Replacement { + + /** + * Gets the method being replaced. + */ + ResolvedJavaMethod getOriginalMethod(); + + /** + * Gets the replacement method. + */ + ResolvedJavaMethod getReplacementMethod(); + + /** + * Determines if this replacement is being inlined as a compiler intrinsic. A compiler + * intrinsic is atomic with respect to deoptimization. Deoptimization within a compiler + * intrinsic will restart the interpreter at the intrinsified call. + */ + boolean isIntrinsic(); + } + T append(T fixed); T append(T fixed); @@ -87,7 +111,15 @@ /** * Determines if the current parsing context is a snippet or method substitution. */ - boolean parsingReplacement(); + default boolean parsingReplacement() { + return getReplacement() == null; + } + + /** + * Gets the replacement of the current parsing context or {@code null} if not + * {@link #parsingReplacement() parsing a replacement}. + */ + Replacement getReplacement(); /** * @see GuardingPiNode#nullCheckedValue(ValueNode) diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Mar 12 16:45:24 2015 +0100 @@ -461,7 +461,7 @@ for (int i = loopBegins.size() - 1; i >= 0; --i) { LoopBeginNode loopBegin = loopBegins.get(i); insertLoopExits(loopBegin, innerLoopsMap); - if (GraalOptions.DumpDuringGraphBuilding.getValue()) { + if (DumpDuringGraphBuilding.getValue()) { Debug.dump(currentGraph, "After building loop exits for %s.", loopBegin); } } @@ -527,7 +527,7 @@ for (LoopBeginNode inner : innerLoopBegins) { addLoopExits(loopBegin, inner, innerLoopsMap, visited); - if (GraalOptions.DumpDuringGraphBuilding.getValue()) { + if (DumpDuringGraphBuilding.getValue()) { Debug.dump(currentGraph, "After adding loop exits for %s.", inner); } } @@ -1210,9 +1210,10 @@ } ReplacementContext context = this.replacementContext; if (context != null && context.isCallToOriginal(targetMethod)) { + assert context.asIntrinsic() == null : "intrinsic cannot call the method it is intrinsifying"; // Self recursive replacement means the original // method should be called. - if (targetMethod.hasBytecodes()) { + if (context.method.hasBytecodes()) { parseAndInlineCallee(context.method, args, null); } else { return false; @@ -1225,9 +1226,13 @@ context = new ReplacementContext(targetMethod, inlinedMethod); } } - parseAndInlineCallee(inlinedMethod, args, context); - if (plugin != null) { - plugin.postInline(inlinedMethod); + if (inlinedMethod.hasBytecodes()) { + parseAndInlineCallee(inlinedMethod, args, context); + if (plugin != null) { + plugin.postInline(inlinedMethod); + } + } else { + return false; } } return true; @@ -2350,6 +2355,10 @@ return parent == null ? 0 : 1 + parent.getDepth(); } + public Replacement getReplacement() { + return replacementContext; + } + public ResolvedJavaMethod getRootMethod() { return rootMethod; } diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Thu Mar 12 16:45:24 2015 +0100 @@ -77,7 +77,7 @@ /** * The method to be inlined. If this is not equal to the {@code method} argument passed * to {@link InlineInvokePlugin#getClass()}, the graph builder context interprets it as - * a {@linkplain GraphBuilderContext#parsingReplacement() replacement}. + * a {@linkplain GraphBuilderContext.Replacement replacement}. */ public final ResolvedJavaMethod methodToInline; diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Thu Mar 12 16:45:24 2015 +0100 @@ -438,10 +438,11 @@ } else { // only handle the outermost frame states if (frameState.outerFrameState() == null) { + assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI : frameState; assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState; - assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()); - assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && frameState.bci != BytecodeFrame.BEFORE_BCI && frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && - frameState.bci != BytecodeFrame.UNWIND_BCI : frameState.bci; + assert frameState.bci != BytecodeFrame.UNKNOWN_BCI : frameState; + assert frameState.bci != BytecodeFrame.UNWIND_BCI : frameState; + assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()) : frameState; if (outerFrameState == null) { outerFrameState = stateAtReturn.duplicateModifiedDuringCall(invoke.bci(), invokeReturnKind); } diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Thu Mar 12 16:45:24 2015 +0100 @@ -51,16 +51,6 @@ static class TestMethodsSubstitutions { @MethodSubstitution(isStatic = true) - static double next(double v) { - return TestMethods.next(v); - } - - @MethodSubstitution(isStatic = true) - static double next2(double v) { - return next2(v); - } - - @MethodSubstitution(isStatic = true) static double nextAfter(double x, double d) { double xx = (x == -0.0 ? 0.0 : x); return Math.nextAfter(xx, d); diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Thu Mar 12 16:45:24 2015 +0100 @@ -57,42 +57,68 @@ test("mathAll", value); } - @SuppressWarnings("all") + @Test + public void testMathPow() { + double a = 34567.891D; + double b = 4.6D; + test("mathPow", a, b); + + // Test the values directly handled by the substitution + + // If the second argument is positive or negative zero, then the result is 1.0. + test("mathPow", a, 0.0D); + test("mathPow", a, -0.0D); + // If the second argument is 1.0, then the result is the same as the first argument. + test("mathPow", a, 1.0D); + // If the second argument is NaN, then the result is NaN. + test("mathPow", a, Double.NaN); + // If the first argument is NaN and the second argument is nonzero, then the result is NaN. + test("mathPow", Double.NaN, b); + test("mathPow", Double.NaN, 0.0D); + // x**-1 = 1/x + test("mathPow", a, -1.0D); + // x**2 = x*x + test("mathPow", a, 2.0D); + // x**0.5 = sqrt(x) + test("mathPow", a, 0.5D); + } + + public static double mathPow(double a, double b) { + return mathPow0(a, b); + } + + public static double mathPow0(double a, double b) { + return Math.pow(a, b); + } + public static double mathAbs(double value) { return Math.abs(value); } - @SuppressWarnings("all") public static double mathSqrt(double value) { return Math.sqrt(value); } - @SuppressWarnings("all") public static double mathLog(double value) { return Math.log(value); } - @SuppressWarnings("all") public static double mathLog10(double value) { return Math.log10(value); } - @SuppressWarnings("all") public static double mathSin(double value) { return Math.sin(value); } - @SuppressWarnings("all") public static double mathCos(double value) { return Math.cos(value); } - @SuppressWarnings("all") public static double mathTan(double value) { return Math.tan(value); } - @SuppressWarnings("all") public static double mathAll(double value) { return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value); } @@ -130,22 +156,18 @@ testSubstitution("integerBitCount", BitCountNode.class, Integer.class, "bitCount", true, args); } - @SuppressWarnings("all") public static int integerReverseBytes(int value) { return Integer.reverseBytes(value); } - @SuppressWarnings("all") public static int integerNumberOfLeadingZeros(int value) { return Integer.numberOfLeadingZeros(value); } - @SuppressWarnings("all") public static int integerNumberOfTrailingZeros(int value) { return Integer.numberOfTrailingZeros(value); } - @SuppressWarnings("all") public static int integerBitCount(int value) { return Integer.bitCount(value); } @@ -160,22 +182,18 @@ testSubstitution("longBitCount", BitCountNode.class, Long.class, "bitCount", true, args); } - @SuppressWarnings("all") public static long longReverseBytes(long value) { return Long.reverseBytes(value); } - @SuppressWarnings("all") public static int longNumberOfLeadingZeros(long value) { return Long.numberOfLeadingZeros(value); } - @SuppressWarnings("all") public static int longNumberOfTrailingZeros(long value) { return Long.numberOfTrailingZeros(value); } - @SuppressWarnings("all") public static int longBitCount(long value) { return Long.bitCount(value); } @@ -186,12 +204,10 @@ testGraph("intBitsToFloat"); } - @SuppressWarnings("all") public static int floatToIntBits(float value) { return Float.floatToIntBits(value); } - @SuppressWarnings("all") public static float intBitsToFloat(int value) { return Float.intBitsToFloat(value); } @@ -202,22 +218,18 @@ testGraph("longBitsToDouble"); } - @SuppressWarnings("all") public static long doubleToLongBits(double value) { return Double.doubleToLongBits(value); } - @SuppressWarnings("all") public static double longBitsToDouble(long value) { return Double.longBitsToDouble(value); } - @SuppressWarnings("all") public static boolean isInstance(Class clazz, Object object) { return clazz.isInstance(object); } - @SuppressWarnings("all") public static boolean isAssignableFrom(Class clazz, Class other) { return clazz.isAssignableFrom(other); } diff -r 4bc952439f2a -r 7ee442766685 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Thu Mar 12 15:59:01 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Thu Mar 12 16:45:24 2015 +0100 @@ -46,12 +46,12 @@ @MethodSubstitution(guard = MathGuard.class) public static double pow(double x, double y) { // If the second argument is positive or negative zero, then the result is 1.0. - if (y == 0) { + if (y == 0.0D) { return 1; } // If the second argument is 1.0, then the result is the same as the first argument. - if (y == 1) { + if (y == 1.0D) { return x; } @@ -61,26 +61,25 @@ } // If the first argument is NaN and the second argument is nonzero, then the result is NaN. - if (Double.isNaN(x) && y != 0) { + if (Double.isNaN(x) && y != 0.0D) { return Double.NaN; } // x**-1 = 1/x - if (y == -1) { + if (y == -1.0D) { return 1 / x; } // x**2 = x*x - if (y == 2) { + if (y == 2.0D) { return x * x; } // x**0.5 = sqrt(x) - if (y == 0.5 && x >= 0) { + if (y == 0.5D && x >= 0.0D) { return Math.sqrt(x); } - - return pow(x, y); + return callDouble2(ARITHMETIC_POW, x, y); } // NOTE on snippets below: @@ -94,7 +93,7 @@ if (Math.abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.SIN); } else { - return callDouble(ARITHMETIC_SIN, x); + return callDouble1(ARITHMETIC_SIN, x); } } @@ -103,7 +102,7 @@ if (Math.abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.COS); } else { - return callDouble(ARITHMETIC_COS, x); + return callDouble1(ARITHMETIC_COS, x); } } @@ -112,7 +111,7 @@ if (Math.abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.TAN); } else { - return callDouble(ARITHMETIC_TAN, x); + return callDouble1(ARITHMETIC_TAN, x); } } @@ -127,7 +126,11 @@ public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class); public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class); public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class); + public static final ForeignCallDescriptor ARITHMETIC_POW = new ForeignCallDescriptor("arithmeticPow", double.class, double.class, double.class); @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) - public static native double callDouble(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); + private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); + + @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b); }