# HG changeset patch # User Lukas Stadler # Date 1365756889 -7200 # Node ID 220c9bef97a460eba031cfee85765a21fa87f2fe # Parent 35a52b195f28fb14f55533963e5a0ea2b9d5a9ff# Parent 9a3e25e270a0c71b555b32f93ba38987eaa5eb60 Merge diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Fri Apr 12 10:54:49 2013 +0200 @@ -45,6 +45,40 @@ private static final long serialVersionUID = -1936652569665112915L; } + public static final class NoFinalizableSubclass extends Assumption { + + private static final long serialVersionUID = 6451169735564055081L; + + private ResolvedJavaType receiverType; + + public NoFinalizableSubclass(ResolvedJavaType receiverType) { + this.receiverType = receiverType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + receiverType.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof NoFinalizableSubclass) { + NoFinalizableSubclass other = (NoFinalizableSubclass) obj; + return other.receiverType == receiverType; + } + return false; + } + + @Override + public String toString() { + return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]"; + } + + } + /** * An assumption about a unique subtype of a given type. */ @@ -273,12 +307,10 @@ * Records an assumption that the specified type has no finalizable subclasses. * * @param receiverType the type that is assumed to have no finalizable subclasses - * @return {@code true} if the assumption was recorded and can be assumed; {@code false} - * otherwise */ - public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { + public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { assert useOptimisticAssumptions; - return false; + record(new NoFinalizableSubclass(receiverType)); } /** diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Fri Apr 12 10:54:49 2013 +0200 @@ -31,14 +31,6 @@ public interface InstalledCode { /** - * Exception thrown by the runtime in case an invalidated machine code is called. - */ - public abstract class MethodInvalidatedException extends RuntimeException { - - private static final long serialVersionUID = -3540232440794244844L; - } - - /** * Returns the method (if any) to which the installed code belongs. */ ResolvedJavaMethod getMethod(); @@ -61,6 +53,12 @@ boolean isValid(); /** + * Invalidates this installed code such that any subsequent invocation will throw an + * {@link InvalidInstalledCodeException}. + */ + void invalidate(); + + /** * Executes the installed code with three object arguments. * * @param arg1 the first argument @@ -68,7 +66,7 @@ * @param arg3 the third argument * @return the value returned by the executed code */ - Object execute(Object arg1, Object arg2, Object arg3); + Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException; /** * Executes the installed code with a variable number of arguments. @@ -76,5 +74,5 @@ * @param args the array of object arguments * @return the value returned by the executed code */ - Object executeVarargs(Object... args); + Object executeVarargs(Object... args) throws InvalidInstalledCodeException; } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.code; + +/** + * Exception thrown by the runtime in case an invalidated machine code is called. + */ +public final class InvalidInstalledCodeException extends Exception { + + private static final long serialVersionUID = -3540232440794244844L; +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Fri Apr 12 10:54:49 2013 +0200 @@ -98,7 +98,9 @@ * Looks up the appendix at the specified index. * * @param cpi the constant pool index - * @return the appendix if resolved or {@code null}. + * @param opcode the opcode of the instruction for which the lookup is being performed or + * {@code -1} + * @return the appendix if it exists and is resolved or {@code null} */ - Object lookupAppendix(int cpi); + Object lookupAppendix(int cpi, int opcode); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -67,7 +67,11 @@ protected Object runTest(String methodName, CodeGenTest test, Object... args) { Method method = getMethod(methodName); InstalledCode code = assembleMethod(method, test); - return code.executeVarargs(args); + try { + return code.executeVarargs(args); + } catch (InvalidInstalledCodeException e) { + throw new RuntimeException(e); + } } protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.Test; + +public class ArrayTest extends PTXTestBase { + + @Test + public void testArray() { + compile("testArray1I"); + compile("testArray1J"); + compile("testArray1B"); + compile("testArray1S"); + compile("testArray1C"); + compile("testArray1F"); + compile("testArray1D"); + compile("testArray1L"); + compile("testStoreArray1I"); + compile("testStoreArray1J"); + compile("testStoreArray1B"); + compile("testStoreArray1S"); + compile("testStoreArray1F"); + compile("testStoreArray1D"); + } + + public static int testArray1I(int[] array, int i) { + return array[i]; + } + + public static long testArray1J(long[] array, int i) { + return array[i]; + } + + public static byte testArray1B(byte[] array, int i) { + return array[i]; + } + + public static short testArray1S(short[] array, int i) { + return array[i]; + } + + public static char testArray1C(char[] array, int i) { + return array[i]; + } + + public static float testArray1F(float[] array, int i) { + return array[i]; + } + + public static double testArray1D(double[] array, int i) { + return array[i]; + } + + public static Object testArray1L(Object[] array, int i) { + return array[i]; + } + + public static void testStoreArray1I(int[] array, int i, int val) { + array[i] = val; + } + + public static void testStoreArray1B(byte[] array, int i, byte val) { + array[i] = val; + } + + public static void testStoreArray1S(short[] array, int i, short val) { + array[i] = val; + } + + public static void testStoreArray1J(long[] array, int i, long val) { + array[i] = val; + } + + public static void testStoreArray1F(float[] array, int i, float val) { + array[i] = val; + } + + public static void testStoreArray1D(double[] array, int i, double val) { + array[i] = val; + } + + public static void main(String[] args) { + ArrayTest test = new ArrayTest(); + for (Method m : ArrayTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -33,28 +33,19 @@ @Test public void testAdd() { - compile("testAddSnippet"); - } - - public static int testAddSnippet(int a) { - return a + 1; + compile("testAddConst1I"); } - @Test - public void testArray() { - compile("testArraySnippet"); - } - - public static int testArraySnippet(int[] array) { - return array[0]; + public static int testAddConst1I(int a) { + return a + 1; } public static void main(String[] args) { BasicPTXTest test = new BasicPTXTest(); Method[] methods = BasicPTXTest.class.getMethods(); for (Method m : methods) { - if (m.getAnnotation(Test.class) != null) { - String name = m.getName() + "Snippet"; + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { // CheckStyle: stop system..print check System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); // CheckStyle: resume system..print check diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Apr 12 10:54:49 2013 +0200 @@ -155,7 +155,7 @@ baseRegister = asAllocatable(base); } - if (index != Value.ILLEGAL) { + if (index != Value.ILLEGAL && scale != 0) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { @@ -169,6 +169,9 @@ if (baseRegister == AllocatableValue.UNUSED) { baseRegister = asAllocatable(indexRegister); } else { + Variable newBase = newVariable(Kind.Int); + emitMove(newBase, baseRegister); + baseRegister = newBase; baseRegister = emitAdd(baseRegister, indexRegister); } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -27,13 +27,10 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.test.*; @@ -75,7 +72,7 @@ try { Object result = compiledMethod.execute("1", "2", "3"); Assert.assertEquals("1-2-3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } @@ -89,7 +86,7 @@ try { Object result = compiledMethod.executeVarargs("1", "2", "3"); Assert.assertEquals("1 2 3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } @@ -104,98 +101,8 @@ f1 = "0"; Object result = compiledMethod.executeVarargs(this, "1", "2", "3"); Assert.assertEquals("0 1 2 3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } - - @LongTest - public void test2() throws NoSuchMethodException, SecurityException { - Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); - ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph); - new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - for (Node node : graph.getNodes()) { - if (node instanceof ConstantNode) { - ConstantNode constant = (ConstantNode) node; - if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph)); - } - } - } - - InstalledCode compiledMethod = getCode(javaMethod, graph); - final CompilableObject compilableObject = new CompilableObjectImpl(0); - - Object result; - result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3"); - Assert.assertEquals("1-3", result); - } - - public abstract class CompilableObject { - - private CompiledObject compiledObject; - private final int compileThreshold; - private int counter; - - public CompilableObject(int compileThreshold) { - this.compileThreshold = compileThreshold; - } - - public final Object execute(ObjectCompiler compiler, String args) { - if (counter++ < compileThreshold || compiler == null) { - return executeHelper(compiler, args); - } else { - compiledObject = compiler.compile(this); - return compiledObject.execute(compiler, args); - } - } - - protected abstract Object executeHelper(ObjectCompiler context, String args); - } - - private final class CompilableObjectImpl extends CompilableObject { - - private CompilableObjectImpl(int compileThreshold) { - super(compileThreshold); - } - - @Override - protected Object executeHelper(ObjectCompiler compiler, String args) { - return "1 " + args; - } - } - - public interface CompiledObject { - - Object execute(ObjectCompiler context, String args); - } - - public interface ObjectCompiler { - - CompiledObject compile(CompilableObject node); - } - - private final class ObjectCompilerImpl implements ObjectCompiler { - - private final InstalledCode compiledMethod; - - private ObjectCompilerImpl(InstalledCode compiledMethod) { - this.compiledMethod = compiledMethod; - } - - @Override - public CompiledObject compile(final CompilableObject node) { - return new CompiledObject() { - - @Override - public Object execute(ObjectCompiler compiler, String args) { - return compiledMethod.execute(node, compiler, args); - } - }; - } - } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -27,7 +27,6 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; @@ -59,7 +58,7 @@ try { Object result = compiledMethod.executeVarargs(testString); Assert.assertEquals(testString, result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } @@ -67,7 +66,7 @@ Object result = compiledMethod.executeVarargs(new Object[]{null}); Assert.assertEquals(null, result); Assert.assertFalse(compiledMethod.isValid()); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Apr 12 10:54:49 2013 +0200 @@ -335,7 +335,7 @@ TTY.println("LIRGen for " + instr); } FrameState stateAfter = null; - if (instr instanceof StateSplit) { + if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) { stateAfter = ((StateSplit) instr).stateAfter(); } if (instr instanceof ValueNode) { diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; + +public class HotSpotInstalledCodeTest extends GraalCompilerTest { + + private static final int ITERATION_COUNT = 100000; + + @Test + public void testInstallCodeInvalidation() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph); + Assert.assertTrue(installedCode.isValid()); + Object result; + try { + result = installedCode.execute("a", "b", "c"); + assertEquals(43, result); + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + Assert.assertTrue(installedCode.isValid()); + installedCode.invalidate(); + Assert.assertFalse(installedCode.isValid()); + try { + result = installedCode.execute(null, null, null); + Assert.fail("Code was not invalidated"); + } catch (InvalidInstalledCodeException e) { + } + Assert.assertFalse(installedCode.isValid()); + } + + @Test + public void testInstalledCodeCalledFromCompiledCode() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph); + Assert.assertTrue(installedCode.isValid()); + try { + for (int i = 0; i < ITERATION_COUNT; ++i) { + installedCode.execute("a", "b", "c"); + } + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + } + + @SuppressWarnings("unused") + public static Object foo(Object a1, Object a2, Object a3) { + return 42; + } + + @SuppressWarnings("unused") + public static Object otherFoo(Object a1, Object a2, Object a3) { + return 43; + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Fri Apr 12 10:54:49 2013 +0200 @@ -24,6 +24,7 @@ import java.lang.reflect.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; @@ -36,7 +37,7 @@ // TODO this is not a test, move it somewhere else // CheckStyle: stop system..print check - public void test1() throws NoSuchMethodException, SecurityException { + public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException { final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class); final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod); @@ -63,7 +64,7 @@ // CheckStyle: resume system..print check - public static Long bench(long nmethod, long metaspacemethod) { + public static Long bench(long nmethod, long metaspacemethod) throws InvalidInstalledCodeException { long start = System.currentTimeMillis(); for (int i = 0; i < ITERATIONS; i++) { @@ -78,7 +79,7 @@ return 42; } - public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) { + public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Apr 12 10:54:49 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; /** @@ -62,4 +63,24 @@ } return super.registerMethodSubstitution(originalMethod, substituteMethod); } + + @Override + public Class getMacroSubstitution(ResolvedJavaMethod method) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + int intrinsicId = hsMethod.intrinsicId(); + if (intrinsicId != 0) { + if (intrinsicId == config.vmIntrinsicInvokeBasic) { + return MethodHandleInvokeBasicNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { + return MethodHandleLinkToInterfaceNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { + return MethodHandleLinkToSpecialNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { + return MethodHandleLinkToStaticNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { + return MethodHandleLinkToVirtualNode.class; + } + } + return super.getMacroSubstitution(method); + } } diff -r 35a52b195f28 -r 220c9bef97a4 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 Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Apr 12 10:54:49 2013 +0200 @@ -187,6 +187,11 @@ public int methodAccessFlagsOffset; /** + * Offset of _intrinsic_id in a metaspace Method object. + */ + public int methodIntrinsicIdOffset; + + /** * Offset of _max_locals in a metaspace Method object. */ public int methodMaxLocalsOffset; @@ -378,6 +383,12 @@ public int deoptActionMakeNotEntrant; public int deoptActionMakeNotCompilable; + public int vmIntrinsicInvokeBasic; + public int vmIntrinsicLinkToVirtual; + public int vmIntrinsicLinkToStatic; + public int vmIntrinsicLinkToSpecial; + public int vmIntrinsicLinkToInterface; + public void check() { assert codeEntryAlignment > 0; assert stackShadowPages > 0; diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 12 10:54:49 2013 +0200 @@ -138,6 +138,8 @@ void lookupReferencedTypeInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + // Must be kept in sync with enum in graalEnv.hpp public enum CodeInstallResult { OK, DEPENDENCIES_FAILED, CACHE_FULL @@ -199,9 +201,9 @@ StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); - Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3); + Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException; - Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args); + Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException; int getVtableEntryOffset(long metaspaceMethod); @@ -222,5 +224,7 @@ */ void reprofile(long metaspaceMethod); - Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi); + void invalidateInstalledCode(long nativeMethod); + + boolean isInstalledCodeValid(long nativeMethod); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 12 10:54:49 2013 +0200 @@ -133,10 +133,7 @@ public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); @Override - public native Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3); - - @Override - public native Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args); + public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod); @Override public native int getVtableEntryOffset(long metaspaceMethod); @@ -160,5 +157,18 @@ public native void reprofile(long metaspaceMethod); @Override - public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi); + public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + + @Override + public native void invalidateInstalledCode(long nativeMethod); + + @Override + public native boolean isInstalledCodeValid(long nativeMethod); + + @Override + public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException { + return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod); + } + + private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Apr 12 10:54:49 2013 +0200 @@ -153,7 +153,8 @@ @Override public void run() { - for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) { + ServiceLoader serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class); + for (ReplacementsProvider provider : serviceLoader) { provider.registerReplacements(replacements); } runtime.registerReplacements(replacements); diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Apr 12 10:54:49 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.bytecode.*; import com.oracle.graal.hotspot.*; /** @@ -51,10 +52,9 @@ } @Override - public Object lookupAppendix(int cpi) { - assert cpi != 0; - Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi); - return constant; + public Object lookupAppendix(int cpi, int opcode) { + assert Bytecodes.isInvoke(opcode); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode); } @Override diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 12 10:54:49 2013 +0200 @@ -39,10 +39,11 @@ private final HotSpotResolvedJavaMethod method; private final boolean isDefault; - long nmethod; + private final long nmethod; // This field is set by the runtime upon code installation. long start; public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) { + this.nmethod = 0; this.method = method; this.isDefault = isDefault; } @@ -62,7 +63,12 @@ @Override public boolean isValid() { - return nmethod != 0; + return HotSpotGraalRuntime.getInstance().getCompilerToVM().isInstalledCodeValid(nmethod); + } + + @Override + public void invalidate() { + HotSpotGraalRuntime.getInstance().getCompilerToVM().invalidateInstalledCode(nmethod); } @Override @@ -71,12 +77,12 @@ } @Override - public Object execute(Object arg1, Object arg2, Object arg3) { + public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3; assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(method.metaspaceMethod, nmethod, arg1, arg2, arg3); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod); } private boolean checkArgs(Object... args) { @@ -94,9 +100,9 @@ } @Override - public Object executeVarargs(Object... args) { + public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args); - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod); } @Override @@ -109,7 +115,8 @@ return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod); } - public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(metaspaceMethod, nmethod, arg1, arg2, arg3); + @SuppressWarnings("unused") + public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod); } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 12 10:54:49 2013 +0200 @@ -362,4 +362,9 @@ } return speculationLog; } + + public int intrinsicId() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff; + } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 12 10:54:49 2013 +0200 @@ -327,17 +327,6 @@ replacements.registerSubstitutions(AESCryptSubstitutions.class); replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class); } - if (GraalOptions.IntrinsifyArrayCopy) { - replacements.registerSnippets(ArrayCopySnippets.class); - } - if (GraalOptions.IntrinsifyObjectClone) { - replacements.registerSnippets(ObjectCloneSnippets.class); - } - - replacements.registerSnippets(BoxingSnippets.class); - for (Class clazz : BoxingSubstitutions.getClasses()) { - replacements.registerSubstitutions(clazz); - } checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget()); @@ -710,7 +699,7 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof UnwindNode) { + } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) { // Nothing to do, using direct LIR lowering for these nodes. } else if (n instanceof BoxNode) { boxingSnippets.lower((BoxNode) n); @@ -905,7 +894,7 @@ public String disassemble(InstalledCode code) { if (code.isValid()) { - long nmethod = ((HotSpotInstalledCode) code).nmethod; + long nmethod = ((HotSpotInstalledCode) code).getnmethod(); return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); } return null; diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -75,7 +74,7 @@ private static final Kind VECTOR_KIND = Kind.Long; private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); - public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) { + private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) { checkNonNull(src); checkNonNull(dest); checkLimits(src, srcPos, dest, destPos, length); diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.replacements; - -import static com.oracle.graal.replacements.SnippetTemplate.*; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; -import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; -import com.oracle.graal.word.*; - -public class BoxingSnippets implements Snippets { - - /** - * This snippet inlining policy differs from the default one in that it does normal inlining of - * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). - */ - public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { - - @Override - public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { - return false; - } - if (method.getAnnotation(Fold.class) != null) { - return false; - } - if (method.getAnnotation(NodeIntrinsic.class) != null) { - return false; - } - if (method.getAnnotation(Word.Operation.class) != null) { - return false; - } - return true; - } - - @Override - public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { - return false; - } - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Boolean valueOf(@Parameter("value") boolean value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Byte valueOf(@Parameter("value") byte value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Character valueOf(@Parameter("value") char value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Double valueOf(@Parameter("value") double value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Float valueOf(@Parameter("value") float value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Integer valueOf(@Parameter("value") int value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Long valueOf(@Parameter("value") long value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Short valueOf(@Parameter("value") short value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static boolean booleanValue(@Parameter("value") Boolean value) { - valueOfCounter.inc(); - return value.booleanValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static byte byteValue(@Parameter("value") Byte value) { - valueOfCounter.inc(); - return value.byteValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static char charValue(@Parameter("value") Character value) { - valueOfCounter.inc(); - return value.charValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static double doubleValue(@Parameter("value") Double value) { - valueOfCounter.inc(); - return value.doubleValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static float floatValue(@Parameter("value") Float value) { - valueOfCounter.inc(); - return value.floatValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static int intValue(@Parameter("value") Integer value) { - valueOfCounter.inc(); - return value.intValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static long longValue(@Parameter("value") Long value) { - valueOfCounter.inc(); - return value.longValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static short shortValue(@Parameter("value") Short value) { - valueOfCounter.inc(); - return value.shortValue(); - } - - public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { - ValueNode value = box.getValue(); - if (value.isConstant()) { - Constant sourceConstant = value.asConstant(); - switch (box.getBoxingKind()) { - case Boolean: - return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); - case Byte: - return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); - case Char: - return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); - case Short: - return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); - case Int: - return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); - case Long: - return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); - case Float: - return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); - case Double: - return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); - default: - assert false : "Unexpected source kind for boxing"; - break; - } - } - return null; - } - - public static class Templates extends AbstractTemplates { - - private final ResolvedJavaMethod[] valueOfMethods = new ResolvedJavaMethod[Kind.values().length]; - private final ResolvedJavaMethod[] unboxMethods = new ResolvedJavaMethod[Kind.values().length]; - - public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, BoxingSnippets.class); - for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { - valueOfMethods[kind.ordinal()] = snippet("valueOf", kind.toJavaClass()); - unboxMethods[kind.ordinal()] = snippet(kind.getJavaName() + "Value", kind.toBoxedJavaClass()); - } - } - - private ResolvedJavaMethod getValueOf(Kind kind) { - assert valueOfMethods[kind.ordinal()] != null; - return valueOfMethods[kind.ordinal()]; - } - - private ResolvedJavaMethod getUnbox(Kind kind) { - assert unboxMethods[kind.ordinal()] != null; - return unboxMethods[kind.ordinal()]; - } - - public void lower(BoxNode box) { - FloatingNode canonical = canonicalizeBoxing(box, runtime); - if (canonical != null) { - ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); - } else { - Key key = new Key(getValueOf(box.getBoxingKind())); - Arguments arguments = new Arguments().add("value", box.getValue()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, arguments); - template.instantiate(runtime, box, DEFAULT_REPLACER, arguments); - } - } - - public void lower(UnboxNode unbox) { - Key key = new Key(getUnbox(unbox.getBoxingKind())); - Arguments arguments = new Arguments().add("value", unbox.getValue()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, arguments); - template.instantiate(runtime, unbox, DEFAULT_REPLACER, arguments); - } - } - - private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; - private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); - -} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java Fri Apr 12 10:53:37 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.replacements; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.extended.*; - -public class BoxingSubstitutions { - - @ClassSubstitution(Boolean.class) - private static class BooleanSubstitutions { - - @MethodSubstitution(forced = true) - public static Boolean valueOf(boolean value) { - return BoxNode.box(value, Boolean.class, Kind.Boolean); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static boolean booleanValue(Boolean value) { - return UnboxNode.unbox(value, Kind.Boolean); - } - } - - @ClassSubstitution(Byte.class) - private static class ByteSubstitutions { - - @MethodSubstitution(forced = true) - public static Byte valueOf(byte value) { - return BoxNode.box(value, Byte.class, Kind.Byte); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static byte byteValue(Byte value) { - return UnboxNode.unbox(value, Kind.Byte); - } - } - - @ClassSubstitution(Character.class) - private static class CharacterSubstitutions { - - @MethodSubstitution(forced = true) - public static Character valueOf(char value) { - return BoxNode.box(value, Character.class, Kind.Char); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static char charValue(Character value) { - return UnboxNode.unbox(value, Kind.Char); - } - } - - @ClassSubstitution(Double.class) - private static class DoubleSubstitutions { - - @MethodSubstitution(forced = true) - public static Double valueOf(double value) { - return BoxNode.box(value, Double.class, Kind.Double); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static double doubleValue(Double value) { - return UnboxNode.unbox(value, Kind.Double); - } - } - - @ClassSubstitution(Float.class) - private static class FloatSubstitutions { - - @MethodSubstitution(forced = true) - public static Float valueOf(float value) { - return BoxNode.box(value, Float.class, Kind.Float); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static float floatValue(Float value) { - return UnboxNode.unbox(value, Kind.Float); - } - } - - @ClassSubstitution(Integer.class) - private static class IntegerSubstitutions { - - @MethodSubstitution(forced = true) - public static Integer valueOf(int value) { - return BoxNode.box(value, Integer.class, Kind.Int); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static int intValue(Integer value) { - return UnboxNode.unbox(value, Kind.Int); - } - } - - @ClassSubstitution(Long.class) - private static class LongSubstitutions { - - @MethodSubstitution(forced = true) - public static Long valueOf(long value) { - return BoxNode.box(value, Long.class, Kind.Long); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static long longValue(Long value) { - return UnboxNode.unbox(value, Kind.Long); - } - } - - @ClassSubstitution(Short.class) - private static class ShortSubstitutions { - - @MethodSubstitution(forced = true) - public static Short valueOf(short value) { - return BoxNode.box(value, Short.class, Kind.Short); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static short shortValue(Short value) { - return UnboxNode.unbox(value, Kind.Short); - } - } - - public static Class[] getClasses() { - return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, - LongSubstitutions.class, ShortSubstitutions.class}; - } -} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Fri Apr 12 10:54:49 2013 +0200 @@ -40,25 +40,25 @@ replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class); } } -} + + @ClassSubstitution(ConstantCallSite.class) + private static class ConstantCallSiteSubstitutions { -@ClassSubstitution(ConstantCallSite.class) -class ConstantCallSiteSubstitutions { + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(ConstantCallSite callSite); + } - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(ConstantCallSite callSite); -} + @ClassSubstitution(MutableCallSite.class) + private static class MutableCallSiteSubstitutions { -@ClassSubstitution(MutableCallSite.class) -class MutableCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(MutableCallSite callSite); -} + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(MutableCallSite callSite); + } -@ClassSubstitution(VolatileCallSite.class) -class VolatileCallSiteSubstitutions { + @ClassSubstitution(VolatileCallSite.class) + private static class VolatileCallSiteSubstitutions { - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(VolatileCallSite callSite); + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(VolatileCallSite callSite); + } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -28,11 +28,9 @@ import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; @@ -42,7 +40,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -58,16 +60,11 @@ @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word hub, Word objectHub); - // @formatter:off - /** * Type test used when the type being tested against is a final type. */ @Snippet - public static Object checkcastExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -76,30 +73,25 @@ if (objectHub.notEqual(exactHub)) { probability(DEOPT_PATH_PROBABILITY); exactMiss.inc(); - //bkpt(object, exactHub, objectHub); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } exactHit.inc(); } - /* make sure that the unsafeCast is done *after* the check above, - * cf. ReadAfterCheckCast */ + /* + * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } /** * Type test used when the type being tested against is a restricted primary type. - * - * This test ignores use of hints altogether as the display-based type check only - * involves one extra load where the second load should hit the same cache line as the - * first. + * + * This test ignores use of hints altogether as the display-based type check only involves one + * extra load where the second load should hit the same cache line as the first. */ @Snippet - public static Object checkcastPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -120,11 +112,7 @@ * Type test used when the type being tested against is a restricted secondary type. */ @Snippet - public static Object checkcastSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @VarargsParameter("hints") Word[] hints, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -149,14 +137,11 @@ } /** - * Type test used when the type being tested against is not known at compile time (e.g. the type test - * in an object array store check). + * Type test used when the type being tested against is not known at compile time (e.g. the type + * test in an object array store check). */ @Snippet - public static Object checkcastDynamic( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -170,21 +155,15 @@ return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod exact; - private final ResolvedJavaMethod primary; - private final ResolvedJavaMethod secondary; - private final ResolvedJavaMethod dynamic; + private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact"); + private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary"); + private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary"); + private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, CheckCastSnippets.class); - exact = snippet("checkcastExact", Object.class, Word.class, boolean.class); - primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class); - secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class); - dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class); + super(runtime, replacements, target); } /** @@ -193,31 +172,34 @@ public void lower(CheckCastNode checkcast, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); ValueNode object = checkcast.object(); - final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; - assert type != null; + Arguments args; if (hintInfo.exact) { ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; assert hints.length == 1; - key = new Key(exact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]); + args = new Arguments(exact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object); + args = new Arguments(primary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; - key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); + args = new Arguments(secondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints); } + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } /** @@ -225,16 +207,16 @@ */ public void lower(CheckCastDynamicNode checkcast) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); - ValueNode hub = checkcast.type(); ValueNode object = checkcast.object(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(dynamic).add("checkNull", checkNull); - Arguments arguments = arguments("hub", hub).add("object", object); + Arguments args = new Arguments(dynamic); + args.add("hub", checkcast.type()); + args.add("object", object); + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -24,21 +24,22 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,18 +53,11 @@ */ public class InstanceOfSnippets implements Snippets { - // @formatter:off - /** * A test against a final type. */ @Snippet - public static Object instanceofExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -83,13 +77,7 @@ * A test against a primary type. */ @Snippet - public static Object instanceofPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -109,14 +97,8 @@ * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @VarargsParameter("hints") Word[] hints, - @VarargsParameter("hintIsPositive") boolean[] hintIsPositive, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -144,12 +126,7 @@ * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic( - @Parameter("mirror") Class mirror, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -164,65 +141,63 @@ return trueValue; } - // @formatter:on - - public static class Templates extends InstanceOfSnippetsTemplates { + public static class Templates extends InstanceOfSnippetsTemplates { - private final ResolvedJavaMethod instanceofExact; - private final ResolvedJavaMethod instanceofPrimary; - private final ResolvedJavaMethod instanceofSecondary; - private final ResolvedJavaMethod instanceofDynamic; + private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact"); + private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); + private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary"); + private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, InstanceOfSnippets.class); - instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class); - instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class); - instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean[].class, boolean.class); - instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class); + super(runtime, replacements, target); } @Override - protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { + protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { if (replacer.instanceOf instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; + + Arguments args; if (hintInfo.exact) { ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs; assert hints.length == 1; - key = new Key(instanceofExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofExact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofPrimary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, runtime, false, hub.graph()); - ConstantNode[] hintHubs = hints.hubs; - boolean[] hintIsPositive = hints.isPositive; - Varargs hintsParam = vargargs(new Word[hintHubs.length], StampFactory.forKind(wordKind())); - Varargs hintIsPositiveParam = vargargs(new boolean[hintIsPositive.length], StampFactory.forKind(Kind.Boolean)); - key = new Key(instanceofSecondary).add("hints", hintsParam).add("hintIsPositive", hintIsPositiveParam).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hintHubs).add("hintIsPositive", hintIsPositive).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofSecondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs); + args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } - return new KeyAndArguments(key, arguments); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; + } else { assert replacer.instanceOf instanceof InstanceOfDynamicNode; InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); - ValueNode mirror = instanceOf.mirror(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(instanceofDynamic).add("checkNull", checkNull); - Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); - return new KeyAndArguments(key, arguments); + + Arguments args = new Arguments(instanceofDynamic); + args.add("mirror", instanceOf.mirror()); + args.add("object", object); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; } } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -27,16 +27,13 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -53,23 +50,17 @@ return unsafeCast(exception, StampFactory.forNodeIntrinsic()); } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod loadException; + private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, LoadExceptionObjectSnippets.class); - loadException = snippet("loadException"); + super(runtime, replacements, target); } public void lower(LoadExceptionObjectNode loadExceptionObject) { - StructuredGraph graph = (StructuredGraph) loadExceptionObject.graph(); - Arguments arguments = new Arguments(); - - Key key = new Key(loadException); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering exception object in %s: node=%s, template=%s, arguments=%s", graph, loadExceptionObject, template, arguments); - template.instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(loadException); + template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args); } } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}. + */ +public class MethodHandleInvokeBasicNode extends MacroNode { + + public MethodHandleInvokeBasicNode(Invoke invoke) { + super(invoke); + } + + @Override + protected StructuredGraph getSnippetGraph(LoweringTool tool) { + return super.getSnippetGraph(tool); + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}. + */ +public class MethodHandleLinkToInterfaceNode extends MacroNode { + + public MethodHandleLinkToInterfaceNode(Invoke invoke) { + super(invoke); + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}. + */ +public class MethodHandleLinkToSpecialNode extends MacroNode { + + public MethodHandleLinkToSpecialNode(Invoke invoke) { + super(invoke); + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}. + */ +public class MethodHandleLinkToStaticNode extends MacroNode { + + public MethodHandleLinkToStaticNode(Invoke invoke) { + super(invoke); + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}. + */ +public class MethodHandleLinkToVirtualNode extends MacroNode { + + public MethodHandleLinkToVirtualNode(Invoke invoke) { + super(invoke); + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -46,7 +46,10 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -73,7 +76,7 @@ public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced"); @Snippet - public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); if (checkNull && object == null) { @@ -262,7 +265,7 @@ * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); incCounter(); if (checkNull && object == null) { @@ -276,7 +279,7 @@ } @Snippet - public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexit(Object object, @ConstantParameter boolean trace) { trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op @@ -328,7 +331,7 @@ * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter boolean trace) { verifyOop(object); traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); @@ -398,54 +401,45 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod monitorenter; - private final ResolvedJavaMethod monitorexit; - private final ResolvedJavaMethod monitorenterStub; - private final ResolvedJavaMethod monitorexitStub; - private final ResolvedJavaMethod monitorenterEliminated; - private final ResolvedJavaMethod monitorexitEliminated; - private final ResolvedJavaMethod initCounter; - private final ResolvedJavaMethod checkCounter; + private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); + private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit"); + private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub"); + private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub"); + private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated"); + private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated"); + private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter"); + private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); + private final boolean useFastLocking; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) { - super(runtime, replacements, target, MonitorSnippets.class); - monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class); - monitorexit = snippet("monitorexit", Object.class, boolean.class); - monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class); - monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class); - monitorenterEliminated = snippet("monitorenterEliminated"); - monitorexitEliminated = snippet("monitorexitEliminated"); - initCounter = snippet("initCounter"); - checkCounter = snippet("checkCounter", String.class); + super(runtime, replacements, target); this.useFastLocking = useFastLocking; } public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorenterNode.graph(); - checkBalancedMonitors(graph); - FrameState stateAfter = monitorenterNode.stateAfter(); - boolean eliminated = monitorenterNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub; - boolean checkNull = !monitorenterNode.object().stamp().nonNull(); - Key key = new Key(method); - if (method != monitorenterEliminated) { - key.add("checkNull", checkNull); - } - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorenterNode.eliminated()) { + args = new Arguments(monitorenterEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorenter); + } else { + args = new Arguments(monitorenterStub); + } + args.add("object", monitorenterNode.object()); + args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull()); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorenterNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments); + Map nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof BeginLockScopeNode) { BeginLockScopeNode begin = (BeginLockScopeNode) n; @@ -460,18 +454,22 @@ public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorexitNode.graph(); FrameState stateAfter = monitorexitNode.stateAfter(); - boolean eliminated = monitorexitNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub; - Key key = new Key(method); - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorexitNode.eliminated()) { + args = new Arguments(monitorexitEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorexit); + } else { + args = new Arguments(monitorexitStub); + } + args.add("object", monitorexitNode.object()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorexitNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments); + + Map nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof EndLockScopeNode) { EndLockScopeNode end = (EndLockScopeNode) n; @@ -521,27 +519,27 @@ NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. - JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass()); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType)); + JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass()); + MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType)); InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0)); invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); - StructuredGraph inlineeGraph = replacements.getSnippet(initCounter); + StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); List rets = graph.getNodes().filter(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { - returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass()); + returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d"); ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph); - callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType)); + callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0)); List stack = Collections.emptyList(); FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); - inlineeGraph = replacements.getSnippet(checkCounter); + inlineeGraph = replacements.getSnippet(checkCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -26,9 +26,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; @@ -43,7 +41,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,15 +54,16 @@ */ public class NewObjectSnippets implements Snippets { - // @formatter:off - @Snippet - public static Word allocate(@Parameter("size") int size) { + public static Word allocate(int size) { Word thread = thread(); Word top = readTlabTop(thread); Word end = readTlabEnd(thread); Word newTop = top.add(size); - // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) + /* + * this check might lead to problems if the TLAB is within 16GB of the address space end + * (checked in c++ code) + */ if (newTop.belowOrEqual(end)) { probability(FAST_PATH_PROBABILITY); writeTlabTop(thread, newTop); @@ -70,13 +73,7 @@ } @Snippet - public static Object initializeObject( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("size") int size, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) { Object result; if (memory.equal(0)) { @@ -91,22 +88,17 @@ } result = memory.toObject(); } - /* make sure that the unsafeCast is anchored after initialization, - * see ReadAfterCheckCast and CheckCastSnippets */ + /* + * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast + * and CheckCastSnippets + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); } @Snippet - public static Object initializeArray( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("length") int length, - @Parameter("allocationSize") int allocationSize, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents, + @ConstantParameter boolean locked) { if (locked) { return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents); } else { @@ -135,13 +127,8 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocateArrayAndInitialize( - @Parameter("length") int length, - @ConstantParameter("alignment") int alignment, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("log2ElementSize") int log2ElementSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("type") ResolvedJavaType type) { + public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { probability(DEOPT_PATH_PROBABILITY); // This handles both negative array sizes and very large array sizes @@ -153,9 +140,10 @@ } /** - * Computes the size of the memory chunk allocated for an array. This size accounts for the array - * header size, boy size and any padding after the last element to satisfy object alignment requirements. - * + * Computes the size of the memory chunk allocated for an array. This size accounts for the + * array header size, boy size and any padding after the last element to satisfy object + * alignment requirements. + * * @param length the number of elements in the array * @param alignment the object alignment requirement * @param headerSize the size of the array header @@ -171,10 +159,7 @@ * Calls the runtime stub for implementing MULTIANEWARRAY. */ @Snippet - public static Object newmultiarray( - @Parameter("hub") Word hub, - @ConstantParameter("rank") int rank, - @VarargsParameter("dimensions") int[] dimensions) { + public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { @@ -184,9 +169,8 @@ } /** - * Maximum size of an object whose body is initialized by a sequence of - * zero-stores to its fields. Larger objects have their bodies initialized - * in a loop. + * Maximum size of an object whose body is initialized by a sequence of zero-stores to its + * fields. Larger objects have their bodies initialized in a loop. */ private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); @@ -217,7 +201,10 @@ */ public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); - // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null + /* + * store hub last as the concurrent garbage collectors assume length is valid if hub field + * is not null + */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { @@ -226,27 +213,19 @@ } } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod allocate; - private final ResolvedJavaMethod initializeObject; - private final ResolvedJavaMethod initializeArray; - private final ResolvedJavaMethod allocateArrayAndInitialize; - private final ResolvedJavaMethod newmultiarray; - private final TargetDescription target; + private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate"); + private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject"); + private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray"); + private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize"); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray"); + private final boolean useTLAB; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) { - super(runtime, replacements, target, NewObjectSnippets.class); - this.target = target; + super(runtime, replacements, target); this.useTLAB = useTLAB; - allocate = snippet("allocate", int.class); - initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class); - initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); - allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class); - newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class); } /** @@ -289,9 +268,10 @@ int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); if (!useTLAB) { ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph); - // value for 'size' doesn't matter as it isn't used since a stub call will be made - // anyway - // for both allocation and initialization - it just needs to be non-null + /* + * value for 'size' doesn't matter as it isn't used since a stub call will be made + * anyway for both allocation and initialization - it just needs to be non-null + */ ConstantNode size = ConstantNode.forInt(-1, graph); InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); @@ -304,12 +284,17 @@ InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else { - Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents", - newArrayNode.fillContents()).add("type", arrayType); - Arguments arguments = new Arguments().add("length", lengthNode); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); - template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocateArrayAndInitialize); + args.add("length", lengthNode); + args.addConst("alignment", alignment); + args.addConst("headerSize", headerSize); + args.addConst("log2ElementSize", log2ElementSize); + args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("type", arrayType); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); } } @@ -317,11 +302,11 @@ public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); ValueNode size = tlabAllocateNode.size(); - Key key = new Key(allocate); - Arguments arguments = arguments("size", size); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); - template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocate).add("size", size); + + SnippetTemplate template = template(args); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args); + template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -331,12 +316,18 @@ assert !type.isArray(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); int size = instanceSize(type); - Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeObject); + args.add("memory", memory); + args.add("hub", hub); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("size", size).addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -348,13 +339,21 @@ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length", - initializeNode.length()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeArray); + args.add("memory", memory); + args.add("hub", hub); + args.add("length", initializeNode.length()); + args.add("allocationSize", initializeNode.allocationSize()); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("headerSize", headerSize); + args.addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -367,10 +366,12 @@ } HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank); - Arguments arguments = arguments("dimensions", dims).add("hub", hub); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(newmultiarray); + args.add("hub", hub); + args.addConst("rank", rank); + args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims); + template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args); } private static int instanceSize(HotSpotResolvedObjectType type) { diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,18 +31,17 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; public class WriteBarrierSnippets implements Snippets { @Snippet - public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) { + public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) { Object object = FixedValueAnchorNode.getObject(obj); Pointer oop; if (usePrecise) { @@ -62,7 +61,7 @@ } @Snippet - public static void serialArrayRangeWriteBarrier(@Parameter("object") Object object, @Parameter("startIndex") int startIndex, @Parameter("length") int length) { + public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) { Object dest = FixedValueAnchorNode.getObject(object); int cardShift = cardTableShift(); long cardStart = cardTableStart(); @@ -77,37 +76,29 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod serialArrayWriteBarrier; - private final ResolvedJavaMethod serialArrayRangeWriteBarrier; + private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier"); + private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, WriteBarrierSnippets.class); - serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class, boolean.class); - serialArrayRangeWriteBarrier = snippet("serialArrayRangeWriteBarrier", Object.class, int.class, int.class); + super(runtime, replacements, target); } public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayWriteBarrier; - Key key = new Key(method); - key.add("usePrecise", arrayWriteBarrier.usePrecise()); - Arguments arguments = new Arguments(); - arguments.add("object", arrayWriteBarrier.getObject()); - arguments.add("location", arrayWriteBarrier.getLocation()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(serialArrayWriteBarrier); + args.add("obj", arrayWriteBarrier.getObject()); + args.add("location", arrayWriteBarrier.getLocation()); + args.addConst("usePrecise", arrayWriteBarrier.usePrecise()); + template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args); } public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayRangeWriteBarrier; - Key key = new Key(method); - Arguments arguments = new Arguments(); - arguments.add("object", arrayRangeWriteBarrier.getObject()); - arguments.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); - arguments.add("length", arrayRangeWriteBarrier.getLength()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(serialArrayRangeWriteBarrier); + args.add("object", arrayRangeWriteBarrier.getObject()); + args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("length", arrayRangeWriteBarrier.getLength()); + template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Apr 12 10:54:49 2013 +0200 @@ -27,15 +27,15 @@ import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -47,14 +47,19 @@ public class NewArrayStub extends Stub { public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newArray"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.add("length", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub")); + return args; } /** @@ -67,7 +72,7 @@ * @param log specifies if logging is enabled */ @Snippet - private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Apr 12 10:54:49 2013 +0200 @@ -36,8 +36,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -49,14 +49,18 @@ public class NewInstanceStub extends Stub { public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newInstance"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub")); + return args; } /** @@ -67,7 +71,7 @@ * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) { diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 12 10:54:49 2013 +0200 @@ -22,9 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,7 +39,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Base class for implementing some low level code providing the out-of-line slow path for a @@ -56,7 +54,7 @@ /** * The method implementing the stub. */ - protected final HotSpotResolvedJavaMethod stubMethod; + protected final SnippetInfo stubInfo; /** * The linkage information for the stub. @@ -69,15 +67,14 @@ protected InstalledCode stubCode; /** - * Creates a new stub container. The new stub still needs to be {@linkplain #getAddress(Backend) - * installed}. + * Creates a new stub container. The new stub still needs to be + * {@linkplain #getAddress(Backend) installed}. * * @param linkage linkage details for a call to the stub */ - @SuppressWarnings("unchecked") - public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, null); - stubMethod = findStubMethod(runtime, getClass()); + public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) { + super(runtime, replacements, target); + this.stubInfo = snippet(getClass(), methodName); this.linkage = linkage; } @@ -85,7 +82,7 @@ /** * Adds the {@linkplain ConstantParameter constant} arguments of this stub. */ - protected abstract void populateKey(Key key); + protected abstract Arguments makeArguments(SnippetInfo stub); protected HotSpotRuntime runtime() { return (HotSpotRuntime) runtime; @@ -95,7 +92,7 @@ * Gets the method implementing this stub. */ public ResolvedJavaMethod getMethod() { - return stubMethod; + return stubInfo.getMethod(); } public HotSpotRuntimeCallTarget getLinkage() { @@ -109,25 +106,22 @@ */ public synchronized long getAddress(Backend backend) { if (stubCode == null) { - StructuredGraph graph = replacements.getSnippet(stubMethod); - - Key key = new Key(stubMethod); - populateKey(key); - SnippetTemplate template = cache.get(key); - graph = template.copySpecializedGraph(); + Arguments args = makeArguments(stubInfo); + SnippetTemplate template = template(args); + StructuredGraph graph = template.copySpecializedGraph(); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, - OptimisticOptimizations.ALL, new SpeculationLog()); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); - stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable() { + stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable() { @Override public InstalledCode call() { - InstalledCode installedCode = runtime().addMethod(stubMethod, compResult); - assert installedCode != null : "error installing stub " + stubMethod; + InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); + assert installedCode != null : "error installing stub " + getMethod(); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } @@ -135,24 +129,8 @@ } }); - assert stubCode != null : "error installing stub " + stubMethod; + assert stubCode != null : "error installing stub " + getMethod(); } return stubCode.getStart(); } - - /** - * Finds the static method annotated with {@link Snippet} in a given class of which there must - * be exactly one. - */ - private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class stubClass) { - HotSpotResolvedJavaMethod m = null; - for (Method candidate : stubClass.getDeclaredMethods()) { - if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) { - assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate); - } - } - assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - return m; - } } diff -r 35a52b195f28 -r 220c9bef97a4 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 Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Apr 12 10:54:49 2013 +0200 @@ -1071,7 +1071,7 @@ private void genInvokeDynamic(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { - Object appendix = constantPool.lookupAppendix(stream.readCPI4()); + Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC); if (appendix != null) { frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); } @@ -1084,8 +1084,20 @@ private void genInvokeVirtual(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); - genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) + // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see + // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic + boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); + Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver)); + if (hasReceiver) { + genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + } else { + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } } else { handleUnresolvedInvoke(target, InvokeKind.Virtual); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Fri Apr 12 10:54:49 2013 +0200 @@ -133,9 +133,27 @@ public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { PTXAddress addr = address.toAddress(); switch (address.getKind()) { + case Byte: + masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Short: + masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Char: + masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; case Int: masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; + case Long: + masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Float: + masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Double: + masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; case Object: masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; @@ -162,11 +180,23 @@ assert isRegister(input); PTXAddress addr = address.toAddress(); switch (address.getKind()) { + case Byte: + masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Short: + masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; case Int: masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); break; - case Byte: - masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + case Long: + masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Float: + masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Double: + masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input)); break; case Object: masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") -public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable, DeoptimizingNode { +public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode { @Input private FrameState deoptState; @@ -51,6 +51,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.emitDeoptimize(action, this); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -147,6 +147,9 @@ @Override public FrameState stateDuring() { FrameState stateAfter = stateAfter(); + if (stateAfter == null) { + return null; + } FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), kind()); stateDuring.setDuringCall(true); return stateDuring; diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -51,5 +51,5 @@ } @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, ValueNode anchor); + public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor); } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -84,7 +84,7 @@ } @NodeIntrinsic - public static native void writeMemory(Object object, Object value, Object location); + public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers); @Override public Object[] getLocationIdentities() { diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Apr 12 10:54:49 2013 +0200 @@ -65,7 +65,8 @@ } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) { // if either the declared type of receiver or the holder // can be assumed to have no finalizers - if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) { + if (tool.assumptions().useOptimisticAssumptions()) { + tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type()); needsCheck = false; } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Fri Apr 12 10:54:49 2013 +0200 @@ -63,11 +63,6 @@ Assumptions getAssumptions(); /** - * Registers all the snippet methods defined by a given class. - */ - void registerSnippets(Class snippets); - - /** * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution * macro} substitutions defined by a given class. */ diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.replacements.amd64; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; +import java.util.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match @@ -54,7 +56,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { + public static int f2i(float input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -80,7 +82,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { + public static long f2l(float input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -106,7 +108,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { + public static int d2i(double input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -132,7 +134,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { + public static long d2l(double input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -146,34 +148,26 @@ return result; } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod f2i; - private final ResolvedJavaMethod f2l; - private final ResolvedJavaMethod d2i; - private final ResolvedJavaMethod d2l; + private final EnumMap snippets; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, AMD64ConvertSnippets.class); - f2i = snippet("f2i", float.class, int.class); - f2l = snippet("f2l", float.class, long.class); - d2i = snippet("d2i", double.class, int.class); - d2l = snippet("d2l", double.class, long.class); + super(runtime, replacements, target); + + snippets = new EnumMap<>(Op.class); + snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i")); + snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l")); + snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i")); + snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l")); } public void lower(ConvertNode convert, LoweringTool tool) { - if (convert.opcode == Op.F2I) { - lower0(convert, tool, f2i); - } else if (convert.opcode == Op.F2L) { - lower0(convert, tool, f2l); - } else if (convert.opcode == Op.D2I) { - lower0(convert, tool, d2i); - } else if (convert.opcode == Op.D2L) { - lower0(convert, tool, d2l); + SnippetInfo key = snippets.get(convert.opcode); + if (key == null) { + return; } - } - private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) { StructuredGraph graph = (StructuredGraph) convert.graph(); // Insert a unique placeholder node in place of the Convert node so that the @@ -183,11 +177,13 @@ LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); convert.replaceAtUsages(replacee); - Key key = new Key(snippet); - Arguments arguments = arguments("input", convert.value()).add("result", convert); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments); - template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments); + Arguments args = new Arguments(key); + args.add("input", convert.value()); + args.add("result", convert); + + SnippetTemplate template = template(args); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args); + template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args); } } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.replacements.Snippet.Fold; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; + +public class BoxingSnippets implements Snippets { + + /** + * This snippet inlining policy differs from the default one in that it does normal inlining of + * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). + */ + public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { + + @Override + public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { + if (Modifier.isNative(method.getModifiers())) { + return false; + } + if (method.getAnnotation(Fold.class) != null) { + return false; + } + if (method.getAnnotation(NodeIntrinsic.class) != null) { + return false; + } + if (method.getAnnotation(Word.Operation.class) != null) { + return false; + } + return true; + } + + @Override + public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { + return false; + } + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Boolean booleanValueOf(boolean value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Byte byteValueOf(byte value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Character charValueOf(char value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Double doubleValueOf(double value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Float floatValueOf(float value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Integer intValueOf(int value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Long longValueOf(long value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Short shortValueOf(short value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static boolean booleanValue(Boolean value) { + valueOfCounter.inc(); + return value.booleanValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static byte byteValue(Byte value) { + valueOfCounter.inc(); + return value.byteValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static char charValue(Character value) { + valueOfCounter.inc(); + return value.charValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static double doubleValue(Double value) { + valueOfCounter.inc(); + return value.doubleValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static float floatValue(Float value) { + valueOfCounter.inc(); + return value.floatValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static int intValue(Integer value) { + valueOfCounter.inc(); + return value.intValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static long longValue(Long value) { + valueOfCounter.inc(); + return value.longValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static short shortValue(Short value) { + valueOfCounter.inc(); + return value.shortValue(); + } + + public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { + ValueNode value = box.getValue(); + if (value.isConstant()) { + Constant sourceConstant = value.asConstant(); + switch (box.getBoxingKind()) { + case Boolean: + return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); + case Byte: + return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); + case Char: + return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); + case Short: + return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); + case Int: + return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); + case Long: + return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); + case Float: + return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); + case Double: + return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); + default: + assert false : "Unexpected source kind for boxing"; + break; + } + } + return null; + } + + public static class Templates extends AbstractTemplates { + + private final EnumMap boxSnippets = new EnumMap<>(Kind.class); + private final EnumMap unboxSnippets = new EnumMap<>(Kind.class); + + public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); + for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { + boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf")); + unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value")); + } + } + + public void lower(BoxNode box) { + FloatingNode canonical = canonicalizeBoxing(box, runtime); + if (canonical != null) { + ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); + } else { + Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind())); + args.add("value", box.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); + template.instantiate(runtime, box, DEFAULT_REPLACER, args); + } + } + + public void lower(UnboxNode unbox) { + Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind())); + args.add("value", unbox.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); + template.instantiate(runtime, unbox, DEFAULT_REPLACER, args); + } + } + + private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; + private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); + +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Fri Apr 12 10:54:49 2013 +0200 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.extended.*; + +public class BoxingSubstitutions { + + @ClassSubstitution(Boolean.class) + private static class BooleanSubstitutions { + + @MethodSubstitution(forced = true) + public static Boolean valueOf(boolean value) { + return BoxNode.box(value, Boolean.class, Kind.Boolean); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static boolean booleanValue(Boolean value) { + return UnboxNode.unbox(value, Kind.Boolean); + } + } + + @ClassSubstitution(Byte.class) + private static class ByteSubstitutions { + + @MethodSubstitution(forced = true) + public static Byte valueOf(byte value) { + return BoxNode.box(value, Byte.class, Kind.Byte); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static byte byteValue(Byte value) { + return UnboxNode.unbox(value, Kind.Byte); + } + } + + @ClassSubstitution(Character.class) + private static class CharacterSubstitutions { + + @MethodSubstitution(forced = true) + public static Character valueOf(char value) { + return BoxNode.box(value, Character.class, Kind.Char); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static char charValue(Character value) { + return UnboxNode.unbox(value, Kind.Char); + } + } + + @ClassSubstitution(Double.class) + private static class DoubleSubstitutions { + + @MethodSubstitution(forced = true) + public static Double valueOf(double value) { + return BoxNode.box(value, Double.class, Kind.Double); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static double doubleValue(Double value) { + return UnboxNode.unbox(value, Kind.Double); + } + } + + @ClassSubstitution(Float.class) + private static class FloatSubstitutions { + + @MethodSubstitution(forced = true) + public static Float valueOf(float value) { + return BoxNode.box(value, Float.class, Kind.Float); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static float floatValue(Float value) { + return UnboxNode.unbox(value, Kind.Float); + } + } + + @ClassSubstitution(Integer.class) + private static class IntegerSubstitutions { + + @MethodSubstitution(forced = true) + public static Integer valueOf(int value) { + return BoxNode.box(value, Integer.class, Kind.Int); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static int intValue(Integer value) { + return UnboxNode.unbox(value, Kind.Int); + } + } + + @ClassSubstitution(Long.class) + private static class LongSubstitutions { + + @MethodSubstitution(forced = true) + public static Long valueOf(long value) { + return BoxNode.box(value, Long.class, Kind.Long); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static long longValue(Long value) { + return UnboxNode.unbox(value, Kind.Long); + } + } + + @ClassSubstitution(Short.class) + private static class ShortSubstitutions { + + @MethodSubstitution(forced = true) + public static Short valueOf(short value) { + return BoxNode.box(value, Short.class, Kind.Short); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static short shortValue(Short value) { + return UnboxNode.unbox(value, Kind.Short); + } + } + + public static Class[] getClasses() { + return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, + LongSubstitutions.class, ShortSubstitutions.class}; + } +} diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Fri Apr 12 10:54:49 2013 +0200 @@ -33,6 +33,10 @@ public class GraalMethodSubstitutions implements ReplacementsProvider { public void registerReplacements(Replacements replacements) { + for (Class clazz : BoxingSubstitutions.getClasses()) { + replacements.registerSubstitutions(clazz); + } + if (GraalOptions.Intrinsify) { replacements.registerSubstitutions(MathSubstitutionsX86.class); replacements.registerSubstitutions(DoubleSubstitutions.class); diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Fri Apr 12 10:54:49 2013 +0200 @@ -34,7 +34,9 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer; /** * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity @@ -49,31 +51,16 @@ * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested * by the {@link IfNode}. */ -public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { +public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { - public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - super(runtime, replacements, target, snippetsClass); + public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); } /** - * The key and arguments used to retrieve and instantiate an instanceof snippet template. + * Gets the arguments used to retrieve and instantiate an instanceof snippet template. */ - public static class KeyAndArguments { - - public final Key key; - public final Arguments arguments; - - public KeyAndArguments(Key key, Arguments arguments) { - this.key = key; - this.arguments = arguments; - } - - } - - /** - * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template. - */ - protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); + protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); public void lower(FloatingNode instanceOf, LoweringTool tool) { assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode; @@ -90,9 +77,8 @@ // No need to re-instantiate the snippet - just re-use its result replacer.replaceUsingInstantiation(); } else { - KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); - SnippetTemplate template = cache.get(keyAndArguments.key); - template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments); + Arguments args = makeArguments(replacer, tool); + template(args).instantiate(runtime, instanceOf, replacer, tool, args); } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 12 10:54:49 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,6 @@ // These data structures are all fully initialized during single-threaded // compiler startup and so do not need to be concurrent. private final Map registeredMethodSubstitutions; - private final Set registeredSnippets; private final Map> registerMacroSubstitutions; private final Set forcedSubstitutions; @@ -70,36 +69,20 @@ this.assumptions = assumptions; this.graphs = new ConcurrentHashMap<>(); this.registeredMethodSubstitutions = new HashMap<>(); - this.registeredSnippets = new HashSet<>(); this.registerMacroSubstitutions = new HashMap<>(); this.forcedSubstitutions = new HashSet<>(); } - public void registerSnippets(Class snippets) { - assert Snippets.class.isAssignableFrom(snippets); - for (Method method : snippets.getDeclaredMethods()) { - if (method.getAnnotation(Snippet.class) != null) { - int modifiers = method.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); - } - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - registeredSnippets.add(snippet); - } - } - } + public StructuredGraph getSnippet(ResolvedJavaMethod method) { + assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; - public StructuredGraph getSnippet(ResolvedJavaMethod method) { - if (!registeredSnippets.contains(method)) { - return null; - } StructuredGraph graph = graphs.get(method); if (graph == null) { graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method))); graph = graphs.get(method); } return graph; - } public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) { @@ -488,7 +471,6 @@ @Override public Collection getAllReplacements() { HashSet result = new HashSet<>(); - result.addAll(registeredSnippets); result.addAll(registeredMethodSubstitutions.keySet()); result.addAll(registerMacroSubstitutions.keySet()); return result; diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Fri Apr 12 10:54:49 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -122,20 +121,6 @@ } /** - * Denotes a snippet parameter that will be bound during snippet template - * {@linkplain SnippetTemplate#instantiate instantiation}. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.PARAMETER) - public @interface Parameter { - - /** - * The name of this parameter. - */ - String value(); - } - - /** * Denotes a snippet parameter representing 0 or more arguments that will be bound during * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet * template creation, its value must be an array whose length specifies the number of arguments @@ -149,11 +134,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface VarargsParameter { - - /** - * The name of this parameter. - */ - String value(); } /** @@ -163,61 +143,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface ConstantParameter { - - /** - * The name of this constant. - */ - String value(); - } - - /** - * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. - */ - public static class Varargs { - - private final Object args; - private final Class argType; - private final int length; - private final Stamp argStamp; - - public static Varargs vargargs(Object array, Stamp argStamp) { - return new Varargs(array, argStamp); - } - - public Varargs(Object array, Stamp argStamp) { - assert array != null; - this.argType = array.getClass().getComponentType(); - this.argStamp = argStamp; - assert this.argType != null; - this.length = java.lang.reflect.Array.getLength(array); - this.args = array; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Varargs) { - Varargs other = (Varargs) obj; - return other.argType == argType && other.length == length; - } - return false; - } - - public Object getArray() { - return args; - } - - public Stamp getArgStamp() { - return argStamp; - } - - @Override - public int hashCode() { - return argType.hashCode() ^ length; - } - - @Override - public String toString() { - return argType.getName() + "[" + length + "]"; - } } } diff -r 35a52b195f28 -r 220c9bef97a4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 12 10:53:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 12 10:54:49 2013 +0200 @@ -22,11 +22,8 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.reflect.*; import java.util.*; -import java.util.Map.Entry; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,8 +39,6 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.Varargs; import com.oracle.graal.replacements.Snippet.VarargsParameter; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -53,173 +48,274 @@ * A snippet template is a graph created by parsing a snippet method and then specialized by binding * constants to the snippet's {@link ConstantParameter} parameters. * - * Snippet templates can be managed in a {@link Cache}. + * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}. */ public class SnippetTemplate { /** - * A snippet template key encapsulates the method from which a snippet was built and the - * arguments used to specialize the snippet. - * - * @see Cache + * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the + * method that needs to be computed only once. The {@link SnippetInfo} should be created once + * per snippet an then cached. */ - public static class Key implements Iterable> { + public static class SnippetInfo { + + protected final ResolvedJavaMethod method; + protected final ConstantParameter[] constantParameters; + protected final VarargsParameter[] varargsParameters; + + /** + * The parameter names, taken from the local variables table. Only used for assertion + * checking, so use only within an assert statement. + */ + protected final String[] names; + + protected SnippetInfo(ResolvedJavaMethod method) { + this.method = method; - public final ResolvedJavaMethod method; - private final HashMap map = new HashMap<>(); - private int hash; + assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); + int count = method.getSignature().getParameterCount(false); + constantParameters = new ConstantParameter[count]; + varargsParameters = new VarargsParameter[count]; + for (int i = 0; i < count; i++) { + constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); + varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); + + assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" + + VarargsParameter.class.getSimpleName(); + } - public Key(ResolvedJavaMethod method) { - this.method = method; - this.hash = method.hashCode(); + names = new String[count]; + // Retrieve the names only when assertions are turned on. + assert initNames(); + } + + private boolean initNames() { + int slotIdx = 0; + for (int i = 0; i < names.length; i++) { + names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName(); + + Kind kind = method.getSignature().getParameterKind(i); + slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1; + } + return true; } - public Key add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - hash = hash ^ name.hashCode(); - if (value != null) { - hash *= (value.hashCode() + 1); - } + public ResolvedJavaMethod getMethod() { + return method; + } + + public int getParameterCount() { + return constantParameters.length; + } + + public boolean isConstantParameter(int paramIdx) { + return constantParameters[paramIdx] != null; + } + + public boolean isVarargsParameter(int paramIdx) { + return varargsParameters[paramIdx] != null; + } + } + + /** + * Values that are bound to the snippet method parameters. The methods {@link #add}, + * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the + * signature of the snippet method. The parameter name is passed to the add methods for + * assertion checking, i.e., to enforce that the order matches. Which method needs to be called + * depends on the annotation of the snippet method parameter: + *
    + *
  • Use {@link #add} for a parameter without an annotation. The value is bound when the + * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}. + *
  • Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value + * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}. + *
  • Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A + * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every + * distinct array length. The actual values are bound when the {@link SnippetTemplate} is + * {@link SnippetTemplate#instantiate instantiated} + *
+ */ + public static class Arguments { + + protected final SnippetInfo info; + protected final CacheKey cacheKey; + protected final Object[] values; + + protected int nextParamIdx; + + public Arguments(SnippetInfo info) { + this.info = info; + this.cacheKey = new CacheKey(info); + this.values = new Object[info.getParameterCount()]; + } + + public Arguments add(String name, Object value) { + assert check(name, false, false); + values[nextParamIdx] = value; + nextParamIdx++; return this; } - public int length() { - return map.size(); + public Arguments addConst(String name, Object value) { + assert check(name, true, false); + values[nextParamIdx] = value; + cacheKey.setParam(nextParamIdx, value); + nextParamIdx++; + return this; } - public Object get(String name) { - return map.get(name); + public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) { + assert check(name, false, true); + Varargs varargs = new Varargs(componentType, argStamp, value); + values[nextParamIdx] = varargs; + // A separate template is necessary for every distinct array length + cacheKey.setParam(nextParamIdx, varargs.length); + nextParamIdx++; + return this; + } + + private boolean check(String name, boolean constParam, boolean varargsParam) { + assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + " " + this; + assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + " " + this; + assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name + + " " + this; + assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name + + " " + this; + return true; } @Override - public Iterator> iterator() { - return map.entrySet().iterator(); + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" ["); + String sep = ""; + for (int i = 0; i < info.getParameterCount(); i++) { + result.append(sep); + if (info.isConstantParameter(i)) { + result.append("const "); + } else if (info.isVarargsParameter(i)) { + result.append("varargs "); + } + result.append(info.names[i]).append(" = ").append(values[i]); + sep = ", "; + } + result.append(">"); + return result.toString(); + } + } + + /** + * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. + */ + static class Varargs { + + protected final Class componentType; + protected final Stamp stamp; + protected final Object value; + protected final int length; + + protected Varargs(Class componentType, Stamp stamp, Object value) { + this.componentType = componentType; + this.stamp = stamp; + this.value = value; + if (value instanceof List) { + this.length = ((List) value).size(); + } else { + this.length = Array.getLength(value); + } + } + } + + static class CacheKey { + + private final ResolvedJavaMethod method; + private final Object[] values; + private int hash; + + protected CacheKey(SnippetInfo info) { + this.method = info.method; + this.values = new Object[info.getParameterCount()]; + this.hash = info.method.hashCode(); + } + + protected void setParam(int paramIdx, Object value) { + values[paramIdx] = value; + hash = (hash * 31) ^ (value == null ? 0 : value.hashCode()); } @Override public boolean equals(Object obj) { - if (obj instanceof Key) { - Key other = (Key) obj; - return other.method == method && other.map.equals(map); + if (!(obj instanceof CacheKey)) { + return false; + } + CacheKey other = (CacheKey) obj; + if (method != other.method) { + return false; } - return false; + for (int i = 0; i < values.length; i++) { + if (values[i] != null && !values[i].equals(other.values[i])) { + return false; + } + } + return true; } @Override public int hashCode() { return hash; } - - @Override - public String toString() { - return MetaUtil.format("%h.%n", method) + map.toString(); - } - - public Set names() { - return map.keySet(); - } } /** - * Arguments used to instantiate a template. + * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s. */ - public static class Arguments implements Iterable> { - - private final HashMap map = new HashMap<>(); - - public static Arguments arguments(String name, Object value) { - return new Arguments().add(name, value); - } - - public Arguments add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - return this; - } - - public int length() { - return map.size(); - } + public abstract static class AbstractTemplates { - @Override - public Iterator> iterator() { - return map.entrySet().iterator(); - } - - @Override - public String toString() { - return map.toString(); - } - } + protected final MetaAccessProvider runtime; + protected final Replacements replacements; + protected final TargetDescription target; + private final ConcurrentHashMap templates; - /** - * A collection of snippet templates accessed by a {@link Key} instance. - */ - public static class Cache { - - private final ConcurrentHashMap templates = new ConcurrentHashMap<>(); - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Replacements replacements; - - public Cache(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { this.runtime = runtime; this.replacements = replacements; this.target = target; + this.templates = new ConcurrentHashMap<>(); + } + + protected SnippetInfo snippet(Class declaringClass, String methodName) { + Method found = null; + for (Method method : declaringClass.getDeclaredMethods()) { + if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) { + assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + found = method; + } + } + assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + + return new SnippetInfo(runtime.lookupJavaMethod(found)); } /** * Gets a template for a given key, creating it first if necessary. */ - public SnippetTemplate get(final SnippetTemplate.Key key) { - SnippetTemplate template = templates.get(key); + protected SnippetTemplate template(final Arguments args) { + SnippetTemplate template = templates.get(args.cacheKey); if (template == null) { - template = Debug.scope("SnippetSpecialization", key.method, new Callable() { + template = Debug.scope("SnippetSpecialization", args.info.method, new Callable() { @Override public SnippetTemplate call() throws Exception { - return new SnippetTemplate(runtime, replacements, target, key); + return new SnippetTemplate(runtime, replacements, target, args); } }); - templates.put(key, template); + templates.put(args.cacheKey, template); } return template; } } - public abstract static class AbstractTemplates { - - protected final Cache cache; - protected final MetaAccessProvider runtime; - protected final Replacements replacements; - protected Class snippetsClass; - - public AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - this.runtime = runtime; - this.replacements = replacements; - if (snippetsClass == null) { - assert this instanceof Snippets; - this.snippetsClass = getClass(); - } else { - this.snippetsClass = snippetsClass; - } - this.cache = new Cache(runtime, replacements, target); - replacements.registerSnippets(this.snippetsClass); - } - - protected ResolvedJavaMethod snippet(String name, Class... parameterTypes) { - try { - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes)); - assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName(); - return snippet; - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - } - private static final Object UNUSED_PARAMETER = "DEAD PARAMETER"; + private static final Object CONSTANT_PARAMETER = "CONSTANT"; /** * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. @@ -236,31 +332,25 @@ /** * Creates a snippet template. */ - public SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, SnippetTemplate.Key key) { - ResolvedJavaMethod method = key.method; - assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method; + protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) { + StructuredGraph snippetGraph = replacements.getSnippet(args.info.method); + + ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); // Copy snippet graph, replacing constant parameters with given arguments - StructuredGraph snippetGraph = replacements.getSnippet(method); - if (snippetGraph == null) { - throw new GraalInternalError("Snippet has not been registered: %s", format("%H.%n(%p)", method)); - } StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap nodeReplacements = new IdentityHashMap<>(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); - int parameterCount = signature.getParameterCount(false); - assert checkTemplate(runtime, key, parameterCount, method, signature); + assert checkTemplate(runtime, args, method, signature); - Parameter[] parameterAnnotations = new Parameter[parameterCount]; - VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount]; + int parameterCount = args.info.getParameterCount(); ConstantNode[] placeholders = new ConstantNode[parameterCount]; + for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - if (c != null) { - String name = c.value(); - Object arg = key.get(name); + if (args.info.isConstantParameter(i)) { + Object arg = args.values[i]; Kind kind = signature.getParameterKind(i); Constant constantArg; if (arg instanceof Constant) { @@ -269,19 +359,12 @@ constantArg = Constant.forBoxed(kind, arg); } nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy)); - } else { - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - if (vp != null) { - String name = vp.value(); - Varargs varargs = (Varargs) key.get(name); - Object array = varargs.getArray(); - ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); - nodeReplacements.put(snippetGraph.getLocal(i), placeholder); - placeholders[i] = placeholder; - varargsParameterAnnotations[i] = vp; - } else { - parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - } + } else if (args.info.isVarargsParameter(i)) { + Varargs varargs = (Varargs) args.values[i]; + Object array = Array.newInstance(varargs.componentType, varargs.length); + ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); + nodeReplacements.put(snippetGraph.getLocal(i), placeholder); + placeholders[i] = placeholder; } } snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements); @@ -297,23 +380,23 @@ assert NodeIntrinsificationVerificationPhase.verify(snippetCopy); // Gather the template parameters - parameters = new HashMap<>(); + parameters = new Object[parameterCount]; for (int i = 0; i < parameterCount; i++) { - VarargsParameter vp = varargsParameterAnnotations[i]; - if (vp != null) { + if (args.info.isConstantParameter(i)) { + parameters[i] = CONSTANT_PARAMETER; + } else if (args.info.isVarargsParameter(i)) { assert snippetCopy.getLocal(i) == null; - Varargs varargs = (Varargs) key.get(vp.value()); - Object array = varargs.getArray(); - int length = Array.getLength(array); + Varargs varargs = (Varargs) args.values[i]; + int length = varargs.length; LocalNode[] locals = new LocalNode[length]; - Stamp stamp = varargs.getArgStamp(); + Stamp stamp = varargs.stamp; for (int j = 0; j < length; j++) { assert (parameterCount & 0xFFFF) == parameterCount; int idx = i << 16 | j; LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp)); locals[j] = local; } - parameters.put(vp.value(), locals); + parameters[i] = locals; ConstantNode placeholder = placeholders[i]; assert placeholder != null; @@ -327,15 +410,12 @@ } } } else { - Parameter p = parameterAnnotations[i]; - if (p != null) { - LocalNode local = snippetCopy.getLocal(i); - if (local == null) { - // Parameter value was eliminated - parameters.put(p.value(), UNUSED_PARAMETER); - } else { - parameters.put(p.value(), local); - } + LocalNode local = snippetCopy.getLocal(i); + if (local == null) { + // Parameter value was eliminated + parameters[i] = UNUSED_PARAMETER; + } else { + parameters[i] = local; } } } @@ -434,11 +514,11 @@ return true; } - private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { - Object arg = varargs.getArray(); + private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); assert type.isArray() : "varargs parameter must be an array type"; - assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg; + assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " + + varargs.componentType; return true; } @@ -453,7 +533,7 @@ * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the * value is identical to the key. */ - private final Map parameters; + private final Object[] parameters; /** * The return node (if any) of the snippet. @@ -481,33 +561,33 @@ * * @return the map that will be used to bind arguments to parameters when inlining this template */ - private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) { + private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) { IdentityHashMap replacements = new IdentityHashMap<>(); - assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")"; - for (Map.Entry e : args) { - String name = e.getKey(); - Object parameter = parameters.get(name); - assert parameter != null : this + " has no parameter named " + name; - Object argument = e.getValue(); + assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")"; + for (int i = 0; i < parameters.length; i++) { + Object parameter = parameters[i]; + assert parameter != null : this + " has no parameter named " + args.info.names[i]; + Object argument = args.values[i]; if (parameter instanceof LocalNode) { if (argument instanceof ValueNode) { replacements.put((LocalNode) parameter, (ValueNode) argument); } else { Kind kind = ((LocalNode) parameter).kind(); - assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name; + assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i]; Constant constant = forBoxed(argument, kind); replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph)); } } else if (parameter instanceof LocalNode[]) { LocalNode[] locals = (LocalNode[]) parameter; + Varargs varargs = (Varargs) argument; int length = locals.length; List list = null; Object array = null; - if (argument instanceof List) { - list = (List) argument; + if (varargs.value instanceof List) { + list = (List) varargs.value; assert list.size() == length : length + " != " + list.size(); } else { - array = argument; + array = varargs.value; assert array != null && array.getClass().isArray(); assert Array.getLength(array) == length : length + " != " + Array.getLength(array); } @@ -525,7 +605,7 @@ } } } else { - assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter; + assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter; } } return replacements; @@ -592,7 +672,7 @@ * @param args the arguments to be bound to the flattened positional parameters of the snippet * @return the map of duplicated nodes (original -> duplicate) */ - public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) { + public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -668,7 +748,7 @@ * @param replacer object that replaces the usages of {@code replacee} * @param args the arguments to be bound to the flattened positional parameters of the snippet */ - public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) { + public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -727,12 +807,14 @@ public String toString() { StringBuilder buf = new StringBuilder(snippet.toString()).append('('); String sep = ""; - for (Map.Entry e : parameters.entrySet()) { - String name = e.getKey(); - Object value = e.getValue(); + for (int i = 0; i < parameters.length; i++) { + String name = "[" + i + "]"; + Object value = parameters[i]; buf.append(sep); sep = ", "; - if (value == UNUSED_PARAMETER) { + if (value == null) { + buf.append(" ").append(name); + } else if (value == UNUSED_PARAMETER) { buf.append(" ").append(name); } else if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; @@ -746,42 +828,18 @@ return buf.append(')').toString(); } - private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) { - Set expected = new HashSet<>(); - for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - if (c != null) { - assert vp == null && p == null; - String name = c.value(); - expected.add(name); + private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) { + for (int i = 0; i < args.info.getParameterCount(); i++) { + if (args.info.isConstantParameter(i)) { Kind kind = signature.getParameterKind(i); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind); - } else if (vp != null) { - assert p == null; - String name = vp.value(); - expected.add(name); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert key.get(name) instanceof Varargs; - Varargs varargs = (Varargs) key.get(name); - assert checkVarargs(method, signature, i, name, varargs); - } else { - assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" + - VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName(); + assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind); + + } else if (args.info.isVarargsParameter(i)) { + assert args.values[i] instanceof Varargs; + Varargs varargs = (Varargs) args.values[i]; + assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs); } } - if (!key.names().containsAll(expected)) { - expected.removeAll(key.names()); - assert false : expected + " missing from key " + key; - } - if (!expected.containsAll(key.names())) { - Set namesCopy = new HashSet<>(key.names()); - namesCopy.removeAll(expected); - assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " + - MetaUtil.format("%H.%n(%p)", method); - } return true; } } diff -r 35a52b195f28 -r 220c9bef97a4 mx/commands.py --- a/mx/commands.py Fri Apr 12 10:53:37 2013 +0200 +++ b/mx/commands.py Fri Apr 12 10:54:49 2013 +0200 @@ -777,7 +777,9 @@ name = 'JUnitWrapper' javaSource = join(mxdir, name + '.java') javaClass = join(mxdir, name + '.class') - (_, testfile) = tempfile.mkstemp(".testclasses", "graal") + testfile = os.environ.get('MX_TESTFILE', None) + if testfile is None: + (_, testfile) = tempfile.mkstemp(".testclasses", "graal") def harness(projectscp, vmArgs): if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): @@ -791,7 +793,8 @@ try: _run_tests(args, harness, annotations, testfile) finally: - os.remove(testfile) + if os.environ.get('MX_TESTFILE') is None: + os.remove(testfile) def unittest(args): """run the JUnit tests (all testcases) diff -r 35a52b195f28 -r 220c9bef97a4 mxtool/mx.py --- a/mxtool/mx.py Fri Apr 12 10:53:37 2013 +0200 +++ b/mxtool/mx.py Fri Apr 12 10:54:49 2013 +0200 @@ -3018,9 +3018,10 @@ if exists(tmpbase): shutil.rmtree(tmpbase) -def findclass(args): +def findclass(args, logToConsole=True): """find all classes matching a given substring""" + matches = [] for entry, filename in classpath_walk(includeBootClasspath=True): if filename.endswith('.class'): if isinstance(entry, zipfile.ZipFile): @@ -3030,20 +3031,19 @@ classname = classname[:-len('.class')] for a in args: if a in classname: - log(classname) + matches.append(classname) + if logToConsole: + log(classname) + return matches def javap(args): - """launch javap with a -classpath option denoting all available classes - - Run the JDK javap class file disassembler with the following prepended options: - - -private -verbose -classpath """ + """disassemble classes matching given pattern with javap""" javap = java().javap if not exists(javap): abort('The javap executable does not exists: ' + javap) else: - run([javap, '-private', '-verbose', '-classpath', classpath()] + args) + run([javap, '-private', '-verbose', '-classpath', classpath()] + findclass(args, logToConsole=False)) def show_projects(args): """show all loaded projects""" @@ -3081,7 +3081,7 @@ 'ideinit': [ideinit, ''], 'archive': [archive, '[options]'], 'projectgraph': [projectgraph, ''], - 'javap': [javap, ''], + 'javap': [javap, ''], 'javadoc': [javadoc, '[options]'], 'site': [site, '[options]'], 'netbeansinit': [netbeansinit, ''], diff -r 35a52b195f28 -r 220c9bef97a4 src/cpu/sparc/vm/interpreter_sparc.cpp --- a/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -381,6 +381,7 @@ case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; + case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; diff -r 35a52b195f28 -r 220c9bef97a4 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -1917,6 +1917,7 @@ BasicType* in_sig_bt, VMRegPair* in_regs, BasicType ret_type) { + assert (method->intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "not yet ported"); if (method->is_method_handle_intrinsic()) { vmIntrinsics::ID iid = method->intrinsic_id(); intptr_t start = (intptr_t)__ pc(); diff -r 35a52b195f28 -r 220c9bef97a4 src/cpu/x86/vm/interpreterGenerator_x86.hpp --- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -36,6 +36,7 @@ address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); + address generate_execute_compiled_method_entry(); address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind); address generate_empty_entry(void); diff -r 35a52b195f28 -r 220c9bef97a4 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -1670,6 +1670,11 @@ verify_oop_args(masm, method, sig_bt, regs); vmIntrinsics::ID iid = method->intrinsic_id(); + if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + return; + } + // Now write the args into the outgoing interpreter space bool has_receiver = false; Register receiver_reg = noreg; diff -r 35a52b195f28 -r 220c9bef97a4 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -873,6 +873,31 @@ return generate_accessor_entry(); } +// Interpreter stub for calling a compiled method with 3 object arguments +address InterpreterGenerator::generate_execute_compiled_method_entry() { + address entry_point = __ pc(); + + // Pick up the return address + __ movptr(rax, Address(rsp, 0)); + + // Must preserve original SP for loading incoming arguments because + // we need to align the outgoing SP for compiled code. + __ movptr(r11, rsp); + + // Ensure compiled code always sees stack at proper alignment + __ andptr(rsp, -16); + + // push the return address and misalign the stack that youngest frame always sees + // as far as the placement of the call instruction + __ push(rax); + + __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5)); + __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4)); + __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3)); + __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize)); + __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + return entry_point; +} // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the @@ -1561,6 +1586,7 @@ switch (kind) { case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; + case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break; case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -199,6 +199,7 @@ /* graal.api.code */ \ do_klass(Assumptions_klass, com_oracle_graal_api_code_Assumptions, Opt) \ do_klass(Assumptions_ConcreteMethod_klass, com_oracle_graal_api_code_Assumptions_ConcreteMethod, Opt) \ + do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, Opt) \ do_klass(Assumptions_ConcreteSubtype_klass, com_oracle_graal_api_code_Assumptions_ConcreteSubtype, Opt) \ do_klass(Assumptions_MethodContents_klass, com_oracle_graal_api_code_Assumptions_MethodContents, Opt) \ do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue, Opt) \ diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -299,6 +299,7 @@ template(com_oracle_graal_hotspot_HotSpotCompilationResult, "com/oracle/graal/hotspot/HotSpotCompilationResult") \ template(com_oracle_graal_hotspot_HotSpotRuntimeCallTarget, "com/oracle/graal/hotspot/HotSpotRuntimeCallTarget") \ template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ + template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl, "com/oracle/graal/hotspot/bridge/CompilerToVMImpl") \ template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo, "com/oracle/graal/hotspot/meta/HotSpotCodeInfo") \ template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode, "com/oracle/graal/hotspot/meta/HotSpotInstalledCode") \ template(com_oracle_graal_hotspot_meta_HotSpotJavaType, "com/oracle/graal/hotspot/meta/HotSpotJavaType") \ @@ -322,6 +323,7 @@ template(com_oracle_graal_api_code_Assumptions, "com/oracle/graal/api/code/Assumptions") \ template(com_oracle_graal_api_code_Assumptions_MethodContents, "com/oracle/graal/api/code/Assumptions$MethodContents") \ template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype, "com/oracle/graal/api/code/Assumptions$ConcreteSubtype") \ + template(com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/code/Assumptions$NoFinalizableSubclass") \ template(com_oracle_graal_api_code_Assumptions_ConcreteMethod, "com/oracle/graal/api/code/Assumptions$ConcreteMethod") \ template(com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/code/Assumptions$CallSiteTargetValue") \ template(com_oracle_graal_api_code_CompilationResult, "com/oracle/graal/api/code/CompilationResult") \ @@ -339,6 +341,7 @@ template(com_oracle_graal_api_code_RegisterValue, "com/oracle/graal/api/code/RegisterValue") \ template(com_oracle_graal_api_code_StackSlot, "com/oracle/graal/api/code/StackSlot") \ template(com_oracle_graal_api_code_VirtualObject, "com/oracle/graal/api/code/VirtualObject") \ + template(com_oracle_graal_api_code_InvalidInstalledCodeException, "com/oracle/graal/api/code/InvalidInstalledCodeException") \ template(startCompiler_name, "startCompiler") \ template(bootstrap_name, "bootstrap") \ template(shutdownCompiler_name, "shutdownCompiler") \ @@ -379,7 +382,6 @@ template(forObject_name, "forObject") \ template(callbackInternal_name, "callbackInternal") \ template(callback_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \ - template(MethodInvalidatedException, "com/oracle/graal/api/code/InstalledCode$MethodInvalidatedException") \ /* graal.api.interpreter */ \ template(com_oracle_graal_api_interpreter_Interpreter, "com/oracle/graal/api/interpreter/Interpreter") \ template(interpreter_execute_name, "execute") \ @@ -1128,6 +1130,9 @@ do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \ do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ \ + do_intrinsic(_CompilerToVMImpl_executeCompiledMethod, com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\ + do_name( CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;") \ + do_name( executeCompiledMethod_name, "executeCompiledMethodIntrinsic") \ /*end*/ diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/code/dependencies.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -144,6 +144,11 @@ assert_common_1(evol_method, DepValue(_oop_recorder, m)); } +void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) { + check_ctxk(ctxk); + assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk)); +} + void Dependencies::assert_leaf_type(Klass* ctxk) { if (ctxk->oop_is_array()) { // As a special case, support this assertion on an array type, diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/code/dependencies.hpp --- a/src/share/vm/code/dependencies.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/code/dependencies.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -360,6 +360,7 @@ public: void assert_evol_method(Method* m); + void assert_has_no_finalizable_subclasses(Klass* ctxk); void assert_leaf_type(Klass* ctxk); void assert_unique_concrete_method(Klass* ctxk, Method* uniqm); void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck); diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/code/nmethod.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -1308,7 +1308,6 @@ #ifdef GRAAL if (_graal_installed_code != NULL) { - HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0); _graal_installed_code = NULL; } #endif @@ -1394,18 +1393,17 @@ return false; } -#ifdef GRAAL - if (_graal_installed_code != NULL) { - HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0); - _graal_installed_code = NULL; - } -#endif - // The caller can be calling the method statically or through an inline // cache call. if (!is_osr_method() && !is_not_entrant()) { - NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), - SharedRuntime::get_handle_wrong_method_stub()); + if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) { + // This was manually installed machine code. Patch entry with stub that throws an exception. + NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), + SharedRuntime::get_deoptimized_installed_code_stub()); + } else { + NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), + SharedRuntime::get_handle_wrong_method_stub()); + } } if (is_in_use()) { diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -1225,7 +1225,7 @@ assert(method->method_holder()->oop_is_instance(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods"); - assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized"); + assert(!method->method_holder()->is_not_initialized() || method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "method holder must be initialized"); if (!TieredCompilation) { comp_level = CompLevel_highest_tier; diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -294,6 +294,8 @@ if (!assumption.is_null()) { if (assumption->klass() == Assumptions_MethodContents::klass()) { assumption_MethodContents(assumption); + } else if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) { + assumption_NoFinalizableSubclass(assumption); } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) { assumption_ConcreteSubtype(assumption); } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) { @@ -447,6 +449,12 @@ _dependencies->assert_evol_method(method()); } +void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) { + Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption()); + Klass* receiverType = asKlass(HotSpotResolvedObjectType::metaspaceKlass(receiverType_handle)); + _dependencies->assert_has_no_finalizable_subclasses(receiverType); +} + void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) { Handle context_handle = Assumptions_ConcreteSubtype::context(assumption()); Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption()); diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -93,6 +93,7 @@ void initialize_buffer(CodeBuffer& buffer); void assumption_MethodContents(Handle assumption); + void assumption_NoFinalizableSubclass(Handle assumption); void assumption_ConcreteSubtype(Handle assumption); void assumption_ConcreteMethod(Handle assumption); void assumption_CallSiteTargetValue(Handle assumption); diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -98,6 +98,21 @@ return ((index & 0xFF) << 24) | ((index & 0xFF00) << 8) | ((index & 0xFF0000) >> 8) | ((index & 0xFF000000) >> 24); } + static int to_cp_index(int raw_index, Bytecodes::Code bc) { + int cp_index; + if (bc == Bytecodes::_invokedynamic) { + cp_index = to_index_u4(raw_index); + assert(ConstantPool::is_invokedynamic_index(raw_index), "not an invokedynamic constant pool index"); + } else { + assert(bc == Bytecodes::_getfield || bc == Bytecodes::_putfield || + bc == Bytecodes::_getstatic || bc == Bytecodes::_putstatic || + bc == Bytecodes::_invokeinterface || bc == Bytecodes::_invokevirtual || + bc == Bytecodes::_invokespecial || bc == Bytecodes::_invokestatic, err_msg("unexpected invoke opcode: %d %s", bc, Bytecodes::name(bc))); + cp_index = to_cp_index_u2(raw_index); + } + return cp_index; + } + static void initialize_buffer_blob(); }; diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -416,10 +416,11 @@ return JNIHandles::make_local(THREAD, result); C2V_END -C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index)) - assert(GraalCompiler::to_index_u4(index) < 0, "not an invokedynamic constant pool index"); +C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode)) + Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); + index = GraalCompiler::to_cp_index(index, bc); constantPoolHandle cpool(InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants()); - oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, GraalCompiler::to_index_u4(index)); + oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, index); return JNIHandles::make_local(THREAD, appendix_oop); C2V_END @@ -429,7 +430,7 @@ instanceKlassHandle pool_holder(cp->pool_holder()); Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); - index = (bc == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index); + index = GraalCompiler::to_cp_index(index, bc); methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); if (!method.is_null()) { @@ -459,11 +460,11 @@ C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - int opcode = (op & 0xFF); - if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray - && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w) + Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF); + if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray + && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w) { - index = cp->remap_instruction_operand_from_cache((opcode == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index)); + index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index(index, bc)); } constantTag tag = cp->tag_at(index); if (tag.is_field_or_method()) { @@ -656,6 +657,7 @@ set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset())); set_int("extraStackEntries", Method::extra_stack_entries()); set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); + set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes()); set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); @@ -779,6 +781,13 @@ set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret); set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant); set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable); + + set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic); + set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual); + set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic); + set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial); + set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface); + set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index())); set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf())); set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes); @@ -898,23 +907,17 @@ return JNIHandles::make_local(element); C2V_END -C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args)) +C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod)) ResourceMark rm; HandleMark hm; - assert(metaspace_method != 0, "just checking"); - methodHandle mh = asMethod(metaspace_method); + nmethod* nm = (nmethod*) (address) nativeMethod; + methodHandle mh = nm->method(); Symbol* signature = mh->signature(); JavaCallArguments jca(mh->size_of_parameters()); JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); JavaValue result(jap.get_ret_type()); - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - THROW_0(vmSymbols::MethodInvalidatedException()); - } - jca.set_alternative_target(nm); JavaCalls::call(&result, mh, &jca, CHECK_NULL); @@ -928,29 +931,6 @@ } C2V_END -C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3)) - ResourceMark rm; - HandleMark hm; - - methodHandle method = asMethod(metaspace_method); - assert(!method.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(JNIHandles::resolve(arg1)); - args.push_oop(JNIHandles::resolve(arg2)); - args.push_oop(JNIHandles::resolve(arg3)); - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - THROW_0(vmSymbols::MethodInvalidatedException()); - } - - args.set_alternative_target(nm); - JavaCalls::call(&result, method, &args, CHECK_NULL); - - return JNIHandles::make_local((oop) result.get_jobject()); -C2V_END - C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method)) Method* method = asMethod(metaspace_method); @@ -1021,10 +1001,10 @@ u2 typeCPIdx = table[i].descriptor_cp_index; u2 slot = table[i].slot; - char* name = method->constants()->string_at_noresolve(nameCPIdx); + char* name = method->constants()->symbol_at(nameCPIdx)->as_C_string(); Handle nameHandle = java_lang_String::create_from_str(name, CHECK_NULL); - char* typeInfo = method->constants()->string_at_noresolve(typeCPIdx); + char* typeInfo = method->constants()->symbol_at(typeCPIdx)->as_C_string(); Handle typeHandle = java_lang_String::create_from_str(typeInfo, CHECK_NULL); Handle holderHandle = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); @@ -1069,6 +1049,20 @@ C2V_END +C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod)) + nmethod* m = (nmethod*)nativeMethod; + if (!m->is_not_entrant()) { + m->mark_for_deoptimization(); + VM_Deoptimize op; + VMThread::execute(&op); + } +C2V_END + + +C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod)) + nmethod* m = (nmethod*)nativeMethod; + return m->is_alive() && !m->is_not_entrant(); +C2V_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -1120,7 +1114,7 @@ {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, - {CC"lookupAppendixInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupAppendixInPool)}, + {CC"lookupAppendixInPool", CC"("HS_RESOLVED_TYPE"IB)"OBJECT, FN_PTR(lookupAppendixInPool)}, {CC"lookupMethodInPool", CC"("HS_RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, {CC"lookupTypeInPool", CC"("HS_RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, @@ -1138,14 +1132,15 @@ {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I", FN_PTR(installCode0)}, {CC"getCode", CC"(J)[B", FN_PTR(getCode)}, {CC"disassembleNMethod", CC"(J)"STRING, FN_PTR(disassembleNMethod)}, - {CC"executeCompiledMethod", CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, - {CC"executeCompiledMethodVarargs", CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"executeCompiledMethodVarargs", CC"(["OBJECT NMETHOD")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, {CC"getLocalVariableTable", CC"("HS_RESOLVED_METHOD")["LOCAL, FN_PTR(getLocalVariableTable)}, {CC"getFileName", CC"("HS_RESOLVED_JAVA_TYPE")"STRING, FN_PTR(getFileName)}, {CC"clearQueuedForCompilation", CC"("HS_RESOLVED_METHOD")V", FN_PTR(clearQueuedForCompilation)}, {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)}, + {CC"invalidateInstalledCode", CC"(J)V", FN_PTR(invalidateInstalledCode)}, + {CC"isInstalledCodeValid", CC"(J)Z", FN_PTR(isInstalledCodeValid)}, }; int CompilerToVM_methods_count() { diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/graal/graalEnv.cpp --- a/src/share/vm/graal/graalEnv.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/graal/graalEnv.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -340,6 +340,27 @@ Symbol* name_sym = cpool->name_ref_at(index); Symbol* sig_sym = cpool->signature_ref_at(index); + if (cpool->has_preresolution() + || (holder() == SystemDictionary::MethodHandle_klass() && + MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) { + // Short-circuit lookups for JSR 292-related call sites. + // That is, do not rely only on name-based lookups, because they may fail + // if the names are not resolvable in the boot class loader (7056328). + switch (bc) { + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + case Bytecodes::_invokespecial: + case Bytecodes::_invokestatic: + { + Method* m = ConstantPool::method_at_if_loaded(cpool, index); + if (m != NULL) { + return m; + } + } + break; + } + } + if (holder_is_accessible) { // Our declared holder is loaded. instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder); methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc); diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -110,6 +110,9 @@ start_class(Assumptions_MethodContents) \ oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ end_class \ + start_class(Assumptions_NoFinalizableSubclass) \ + oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ + end_class \ start_class(Assumptions_ConcreteSubtype) \ oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/interpreter/abstractInterpreter.hpp --- a/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -85,6 +85,7 @@ zerolocals_synchronized, // method needs locals initialization & is synchronized native, // native method native_synchronized, // native method & is synchronized + execute_compiled_method, // direct call to compiled method address empty, // empty method (code: _return) accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return) abstract, // abstract method (throws an AbstractMethodException) diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/interpreter/interpreter.cpp --- a/src/share/vm/interpreter/interpreter.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/interpreter/interpreter.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -188,6 +188,9 @@ // Method handle primitive? if (m->is_method_handle_intrinsic()) { vmIntrinsics::ID id = m->intrinsic_id(); + if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + return AbstractInterpreter::execute_compiled_method; + } assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic"); MethodKind kind = (MethodKind)( method_handle_invoke_FIRST + ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) ); @@ -287,6 +290,7 @@ case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break; case native : tty->print("native" ); break; case native_synchronized : tty->print("native_synchronized" ); break; + case execute_compiled_method: tty->print("execute_compiled_method"); break; case empty : tty->print("empty" ); break; case accessor : tty->print("accessor" ); break; case abstract : tty->print("abstract" ); break; diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/interpreter/templateInterpreter.cpp --- a/src/share/vm/interpreter/templateInterpreter.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -360,6 +360,7 @@ method_entry(zerolocals) method_entry(zerolocals_synchronized) method_entry(empty) + method_entry(execute_compiled_method) method_entry(accessor) method_entry(abstract) method_entry(java_lang_math_sin ) diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/oops/method.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -722,7 +722,7 @@ if (number_of_breakpoints() > 0) return true; if (is_method_handle_intrinsic()) - return !is_synthetic(); // the generated adapters must be compiled + return !is_synthetic() && intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod; // the generated adapters must be compiled if (comp_level == CompLevel_any) return is_not_c1_compilable() || is_not_c2_compilable(); if (is_c1_compile(comp_level)) @@ -850,7 +850,10 @@ (void) make_adapters(h_method, CHECK); // ONLY USE the h_method now as make_adapter may have blocked - + if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier, + methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK); + } } address Method::make_adapters(methodHandle mh, TRAPS) { @@ -1014,8 +1017,8 @@ // Test if this method is an internal MH primitive method. bool Method::is_method_handle_intrinsic() const { vmIntrinsics::ID iid = intrinsic_id(); - return (MethodHandles::is_signature_polymorphic(iid) && - MethodHandles::is_signature_polymorphic_intrinsic(iid)); + return ((MethodHandles::is_signature_polymorphic(iid) && + MethodHandles::is_signature_polymorphic_intrinsic(iid))) || iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod; } bool Method::has_member_arg() const { diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/runtime/javaCalls.cpp --- a/src/share/vm/runtime/javaCalls.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/runtime/javaCalls.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -412,7 +412,7 @@ ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point()); entry_point = method->adapter()->get_i2c_entry(); } else { - THROW(vmSymbols::MethodInvalidatedException()); + THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException()); } } #endif diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Fri Apr 12 10:54:49 2013 +0200 @@ -83,6 +83,7 @@ #endif // Shared stub locations +RuntimeStub* SharedRuntime::_deoptimized_installed_code_blob; RuntimeStub* SharedRuntime::_wrong_method_blob; RuntimeStub* SharedRuntime::_ic_miss_blob; RuntimeStub* SharedRuntime::_resolve_opt_virtual_call_blob; @@ -101,6 +102,7 @@ //----------------------------generate_stubs----------------------------------- void SharedRuntime::generate_stubs() { + _deoptimized_installed_code_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_deoptimized_installed_code), "deoptimized_installed_code"); _wrong_method_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method), "wrong_method_stub"); _ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub"); _resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), "resolve_opt_virtual_call"); @@ -1350,6 +1352,12 @@ return callee_method->verified_code_entry(); JRT_END +// Installed code has been deoptimized +JRT_BLOCK_ENTRY(address, SharedRuntime::handle_deoptimized_installed_code(JavaThread* thread)) + JavaThread* THREAD = thread; + ThreadInVMfromJava tiv(THREAD); + THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); +JRT_END // Handle call site that has been made non-entrant JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread)) diff -r 35a52b195f28 -r 220c9bef97a4 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Fri Apr 12 10:53:37 2013 +0200 +++ b/src/share/vm/runtime/sharedRuntime.hpp Fri Apr 12 10:54:49 2013 +0200 @@ -55,6 +55,7 @@ // Shared stub locations + static RuntimeStub* _deoptimized_installed_code_blob; static RuntimeStub* _wrong_method_blob; static RuntimeStub* _ic_miss_blob; static RuntimeStub* _resolve_opt_virtual_call_blob; @@ -209,6 +210,11 @@ return _wrong_method_blob->entry_point(); } + static address get_deoptimized_installed_code_stub() { + assert(_deoptimized_installed_code_blob!= NULL, "oops"); + return _deoptimized_installed_code_blob->entry_point(); + } + #ifdef COMPILER2 static void generate_uncommon_trap_blob(void); static UncommonTrapBlob* uncommon_trap_blob() { return _uncommon_trap_blob; } @@ -486,6 +492,9 @@ static address handle_wrong_method(JavaThread* thread); static address handle_wrong_method_ic_miss(JavaThread* thread); + // handle deoptimized installed code + static address handle_deoptimized_installed_code(JavaThread* thread); + #ifndef PRODUCT // Collect and print inline cache miss statistics