changeset 9774:20963f52fdd5

Merge.
author Doug Simon <doug.simon@oracle.com>
date Fri, 17 May 2013 22:45:55 +0200
parents 8a1b0a3d4fc3 (diff) 2461285a2f90 (current diff)
children 5dc05fdcf3c2
files
diffstat 14 files changed, 282 insertions(+), 327 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri May 17 22:45:55 2013 +0200
@@ -426,18 +426,29 @@
                 }
                 long start = System.currentTimeMillis();
                 PhasePlan phasePlan = new PhasePlan();
-                StructuredGraph graphCopy = graph.copy();
+                final StructuredGraph graphCopy = graph.copy();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
                 editPhasePlan(method, graph, phasePlan);
                 CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
-                CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
+                final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL,
                                 new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
-                return addMethod(method, compResult, graphCopy);
+                return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
+
+                    @Override
+                    public InstalledCode call() throws Exception {
+                        InstalledCode code = addMethod(method, compResult, graphCopy);
+                        if (Debug.isDumpEnabled()) {
+                            Debug.dump(new Object[]{compResult, code}, "After code installation");
+                        }
+
+                        return code;
+                    }
+                });
             }
         });
 
@@ -448,18 +459,7 @@
     }
 
     protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) {
-        return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() {
-
-            @Override
-            public InstalledCode call() throws Exception {
-                InstalledCode installedCode = runtime.addMethod(method, compResult, graph);
-                if (Debug.isDumpEnabled()) {
-                    Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
-                }
-
-                return installedCode;
-            }
-        });
+        return runtime.addMethod(method, compResult, graph);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri May 17 22:45:55 2013 +0200
@@ -231,14 +231,16 @@
                 }
             }
         }
-        if (!hsLinkage.isLeaf()) {
-            append(new AMD64HotSpotCRuntimeCallPrologueOp());
-        }
 
-        Variable result = super.emitForeignCall(linkage, info, args);
+        Variable result;
 
         if (!hsLinkage.isLeaf()) {
+            assert info != null;
+            append(new AMD64HotSpotCRuntimeCallPrologueOp());
+            result = super.emitForeignCall(linkage, info, args);
             append(new AMD64HotSpotCRuntimeCallEpilogueOp());
+        } else {
+            result = super.emitForeignCall(linkage, null, args);
         }
 
         if (destroysRegisters) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri May 17 22:45:55 2013 +0200
@@ -29,10 +29,8 @@
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
-import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.DecryptBlockStubCall.*;
-import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.EncryptBlockStubCall.*;
-import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
-import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*;
+import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Fri May 17 22:45:55 2013 +0200
@@ -0,0 +1,187 @@
+/*
+ * 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 static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.security.*;
+
+import javax.crypto.*;
+
+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.*;
+import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Tests the intrinsification of certain crypto methods.
+ */
+public class HotSpotCryptoSubstitutionTest extends GraalCompilerTest {
+
+    @Override
+    protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, StructuredGraph graph) {
+        HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+        HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, graph, true);
+        HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(hsMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult);
+        CodeInstallResult result = graalRuntime().getCompilerToVM().installCode(compiledNmethod, installedCode, null);
+        Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK);
+
+        // HotSpotRuntime hsRuntime = (HotSpotRuntime) runtime;
+        // TTY.println(hsMethod.toString());
+        // TTY.println(hsRuntime.disassemble(installedCode));
+        return installedCode;
+    }
+
+    @Test
+    public void testAESEncryptSubstitution() throws Exception {
+        byte[] seed = {0x4, 0x7, 0x1, 0x1};
+        SecureRandom random = new SecureRandom(seed);
+        KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES");
+        aesKeyGen.init(128, random);
+        SecretKey aesKey = aesKeyGen.generateKey();
+        byte[] input = readClassfile16(getClass());
+
+        ByteArrayOutputStream expected = new ByteArrayOutputStream();
+        expected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
+        expected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+
+        if (compiledAndInstall("com.sun.crypto.provider.AESCrypt", "encryptBlock", "decryptBlock")) {
+            ByteArrayOutputStream actual = new ByteArrayOutputStream();
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+            Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray());
+        }
+
+        if (compiledAndInstall("com.sun.crypto.provider.CipherBlockChaining", "encrypt", "decrypt")) {
+            ByteArrayOutputStream actual = new ByteArrayOutputStream();
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input));
+            actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input));
+            Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray());
+        }
+    }
+
+    /**
+     * Compiles and installs the substitution for some specified methods. Once installed, the next
+     * execution of the methods will use the newly installed code.
+     * 
+     * @param className the name of the class for which substitutions are available
+     * @param methodNames the names of the substituted methods
+     * @return true if at least one substitution was compiled and installed
+     */
+    private boolean compiledAndInstall(String className, String... methodNames) {
+        boolean atLeastOneCompiled = false;
+        for (String methodName : methodNames) {
+            Method method = lookup(className, methodName);
+            if (method != null) {
+                ResolvedJavaMethod installedCodeOwner = runtime.lookupJavaMethod(method);
+                StructuredGraph graph = replacements.getMethodSubstitution(installedCodeOwner);
+                if (graph != null) {
+                    Assert.assertNotNull(getCode(installedCodeOwner, graph, true));
+                    atLeastOneCompiled = true;
+                } else {
+                    Assert.assertFalse(graalRuntime().getConfig().useAESIntrinsics);
+                }
+            }
+        }
+        return atLeastOneCompiled;
+    }
+
+    private static Method lookup(String className, String methodName) {
+        Class c;
+        try {
+            c = Class.forName(className);
+            for (Method m : c.getDeclaredMethods()) {
+                if (m.getName().equals(methodName)) {
+                    return m;
+                }
+            }
+            // If the expected security provider exists, the specific method should also exist
+            throw new NoSuchMethodError(className + "." + methodName);
+        } catch (ClassNotFoundException e) {
+            // It's ok to not find the class - a different security provider
+            // may have been installed
+            return null;
+        }
+    }
+
+    AlgorithmParameters algorithmParameters;
+
+    private byte[] encrypt(byte[] indata, SecretKey key, String algorithm) throws Exception {
+
+        byte[] result = indata;
+
+        Cipher c = Cipher.getInstance(algorithm);
+        c.init(Cipher.ENCRYPT_MODE, key);
+        algorithmParameters = c.getParameters();
+
+        byte[] r1 = c.update(result);
+        byte[] r2 = c.doFinal();
+
+        result = new byte[r1.length + r2.length];
+        System.arraycopy(r1, 0, result, 0, r1.length);
+        System.arraycopy(r2, 0, result, r1.length, r2.length);
+
+        return result;
+    }
+
+    private byte[] decrypt(byte[] indata, SecretKey key, String algorithm) throws Exception {
+
+        byte[] result = indata;
+
+        Cipher c = Cipher.getInstance(algorithm);
+        c.init(Cipher.DECRYPT_MODE, key, algorithmParameters);
+
+        byte[] r1 = c.update(result);
+        byte[] r2 = c.doFinal();
+
+        result = new byte[r1.length + r2.length];
+        System.arraycopy(r1, 0, result, 0, r1.length);
+        System.arraycopy(r2, 0, result, r1.length, r2.length);
+        return result;
+    }
+
+    private static byte[] readClassfile16(Class c) throws IOException {
+        String classFilePath = "/" + c.getName().replace('.', '/') + ".class";
+        InputStream stream = c.getResourceAsStream(classFilePath);
+        int bytesToRead = stream.available();
+        bytesToRead -= bytesToRead % 16;
+        byte[] classFile = new byte[bytesToRead];
+        new DataInputStream(stream).readFully(classFile);
+        return classFile;
+    }
+
+    public byte[] runEncryptDecrypt(SecretKey key, String algorithm, byte[] input) throws Exception {
+        byte[] indata = input.clone();
+        byte[] cipher = encrypt(indata, key, algorithm);
+        byte[] plain = decrypt(cipher, key, algorithm);
+        Assert.assertArrayEquals(indata, plain);
+        return plain;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri May 17 22:45:55 2013 +0200
@@ -31,17 +31,16 @@
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
-import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
-import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
 import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
+import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
 import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
 import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
@@ -95,6 +94,7 @@
 
     public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class);
     public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class);
+    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
 
     public final HotSpotVMConfig config;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Fri May 17 17:43:01 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +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.nodes;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.word.*;
-
-/**
- * Node implementing a call to {@code GraalRuntime::monitorenter}.
- */
-public class MonitorEnterStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    @Input private ValueNode object;
-    @Input private ValueNode lock;
-    public static final ForeignCallDescriptor MONITORENTER = new ForeignCallDescriptor("monitorenter", void.class, Object.class, Word.class);
-
-    public MonitorEnterStubCall(ValueNode object, ValueNode lock) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.lock = lock;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(MONITORENTER);
-        gen.emitForeignCall(linkage, this, gen.operand(object), gen.operand(lock));
-    }
-
-    @NodeIntrinsic
-    public static native void call(Object object, Word lock);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Fri May 17 17:43:01 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +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.nodes;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Node implementing a call to {@code GraalRuntime::thread_is_interrupted}.
- */
-public class ThreadIsInterruptedStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    @Input private ValueNode thread;
-    @Input private ValueNode clearIsInterrupted;
-    public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class);
-
-    public ThreadIsInterruptedStubCall(ValueNode thread, ValueNode clearIsInterrupted) {
-        super(StampFactory.forInteger(Kind.Int, 0, 1));
-        this.thread = thread;
-        this.clearIsInterrupted = clearIsInterrupted;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED);
-        Variable result = gen.emitForeignCall(linkage, this, gen.operand(thread), gen.operand(clearIsInterrupted));
-        gen.setResult(this, result);
-    }
-
-    @NodeIntrinsic
-    public static boolean call(Thread thread, boolean clearIsInterrupted) {
-        try {
-            Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class);
-            isInterrupted.setAccessible(true);
-            return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted);
-        } catch (Exception e) {
-            throw new GraalInternalError(e);
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Fri May 17 17:43:01 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +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.nodes;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Call to {@link VerifyOopStub}.
- */
-public class VerifyOopStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    @Input private ValueNode object;
-    public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class);
-
-    public VerifyOopStubCall(ValueNode object) {
-        super(StampFactory.objectNonNull());
-        this.object = object;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(VerifyOopStubCall.VERIFY_OOP);
-        gen.emitForeignCall(linkage, this, gen.operand(object));
-    }
-
-    @NodeIntrinsic
-    public static native Object call(Object object);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Fri May 17 22:45:55 2013 +0200
@@ -25,15 +25,13 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import sun.misc.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -72,56 +70,18 @@
         Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
         Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
         if (encrypt) {
-            EncryptBlockStubCall.call(inAddr, outAddr, kAddr);
+            encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr);
         } else {
-            DecryptBlockStubCall.call(inAddr, outAddr, kAddr);
+            decryptBlockStub(DECRYPT_BLOCK, inAddr, outAddr, kAddr);
         }
     }
 
-    abstract static class CryptBlockStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-        @Input private ValueNode in;
-        @Input private ValueNode out;
-        @Input private ValueNode key;
-
-        private final ForeignCallDescriptor descriptor;
-
-        public CryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key, ForeignCallDescriptor descriptor) {
-            super(StampFactory.forVoid());
-            this.in = in;
-            this.out = out;
-            this.key = key;
-            this.descriptor = descriptor;
-        }
-
-        @Override
-        public void generate(LIRGenerator gen) {
-            ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
-            gen.emitForeignCall(linkage, null, gen.operand(in), gen.operand(out), gen.operand(key));
-        }
-    }
+    public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class);
+    public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class);
 
-    public static class EncryptBlockStubCall extends CryptBlockStubCall {
-
-        public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class);
-
-        public EncryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) {
-            super(in, out, key, ENCRYPT_BLOCK);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key);
-    }
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void encryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key);
 
-    public static class DecryptBlockStubCall extends CryptBlockStubCall {
-
-        public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class);
-
-        public DecryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) {
-            super(in, out, key, DECRYPT_BLOCK);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key);
-    }
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void decryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Fri May 17 22:45:55 2013 +0200
@@ -25,15 +25,13 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import sun.misc.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
 
@@ -72,19 +70,6 @@
         }
     }
 
-    private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
-        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
-        Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
-        Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
-        if (encrypt) {
-            EncryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength);
-        } else {
-            DecryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength);
-        }
-
-    }
-
     @MethodSubstitution(isStatic = false)
     static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
         Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION);
@@ -95,54 +80,24 @@
         }
     }
 
-    abstract static class AESCryptStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-        @Input private ValueNode in;
-        @Input private ValueNode out;
-        @Input private ValueNode key;
-        @Input private ValueNode r;
-        @Input private ValueNode inLength;
-
-        private final ForeignCallDescriptor descriptor;
-
-        public AESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength, ForeignCallDescriptor descriptor) {
-            super(StampFactory.forVoid());
-            this.in = in;
-            this.out = out;
-            this.key = key;
-            this.r = r;
-            this.inLength = inLength;
-            this.descriptor = descriptor;
-        }
-
-        @Override
-        public void generate(LIRGenerator gen) {
-            ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
-            gen.emitForeignCall(linkage, null, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
+    private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) {
+        Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte));
+        Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset);
+        Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset);
+        if (encrypt) {
+            encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
+        } else {
+            decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
         }
     }
 
-    public static class EncryptAESCryptStubCall extends AESCryptStubCall {
-
-        public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
-
-        public EncryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) {
-            super(in, out, key, r, inLength, ENCRYPT);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key, Word r, int inLength);
-    }
+    public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
+    public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
 
-    public static class DecryptAESCryptStubCall extends AESCryptStubCall {
-
-        public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class);
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void encryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key, Word r, int inLength);
 
-        public DecryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) {
-            super(in, out, key, r, inLength, DECRYPT);
-        }
-
-        @NodeIntrinsic
-        public static native void call(Word in, Word out, Word key, Word r, int inLength);
-    }
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void decryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key, Word r, int inLength);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Fri May 17 22:45:55 2013 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity;
 import com.oracle.graal.replacements.Snippet.Fold;
@@ -450,11 +449,14 @@
 
     public static Object verifyOop(Object object) {
         if (verifyOops()) {
-            VerifyOopStubCall.call(object);
+            verifyOopStub(VERIFY_OOP, object);
         }
         return object;
     }
 
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
+
     /**
      * Gets the value of the stack pointer register as a Word.
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri May 17 22:45:55 2013 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -159,7 +160,7 @@
                         // owns the bias and we need to revoke that bias. The revocation will occur
                         // in the interpreter runtime.
                         traceObject(trace, "+lock{stub:revoke}", object);
-                        MonitorEnterStubCall.call(object, lock);
+                        monitorenterStub(MONITORENTER, object, lock);
                         return;
                     } else {
                         // At this point we know the epoch has expired, meaning that the
@@ -179,7 +180,7 @@
                         // succeeded in biasing it toward itself and we need to revoke that
                         // bias. The revocation will occur in the runtime in the slow case.
                         traceObject(trace, "+lock{stub:epoch-expired}", object);
-                        MonitorEnterStubCall.call(object, lock);
+                        monitorenterStub(MONITORENTER, object, lock);
                         return;
                     }
                 } else {
@@ -236,7 +237,7 @@
             if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) {
                 // Most likely not a recursive lock, go into a slow runtime call
                 traceObject(trace, "+lock{stub:failed-cas}", object);
-                MonitorEnterStubCall.call(object, lock);
+                monitorenterStub(MONITORENTER, object, lock);
                 return;
             } else {
                 // Recursively locked => write 0 to the lock slot
@@ -262,7 +263,7 @@
         // cannot float about the null check above
         final Word lock = beginLockScope(lockDepth);
         traceObject(trace, "+lock{stub}", object);
-        MonitorEnterStubCall.call(object, lock);
+        monitorenterStub(MONITORENTER, object, lock);
     }
 
     @Snippet
@@ -517,4 +518,10 @@
             }
         }
     }
+
+    public static final ForeignCallDescriptor MONITORENTER = new ForeignCallDescriptor("monitorenter", void.class, Object.class, Word.class);
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native void monitorenterStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock);
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Fri May 17 22:45:55 2013 +0200
@@ -24,8 +24,15 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -51,6 +58,22 @@
             }
         }
 
-        return ThreadIsInterruptedStubCall.call(thisObject, clearInterrupted);
+        return threadIsInterruptedStub(THREAD_IS_INTERRUPTED, thisObject, clearInterrupted);
+    }
+
+    public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class);
+
+    /**
+     * @param descriptor
+     */
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static boolean threadIsInterruptedStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Thread thread, boolean clearIsInterrupted) {
+        try {
+            Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class);
+            isInterrupted.setAccessible(true);
+            return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted);
+        } catch (Exception e) {
+            throw new GraalInternalError(e);
+        }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Fri May 17 17:43:01 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java	Fri May 17 22:45:55 2013 +0200
@@ -27,12 +27,11 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.*;
 
 /**
- * Stub called from {@link VerifyOopStubCall}.
+ * Stub called via {@link HotSpotRuntime#VERIFY_OOP}.
  */
 public class VerifyOopStub extends SnippetStub {