changeset 7484:69318374c8d7

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 16 Jan 2013 14:41:15 +0100
parents 729a79037bd5 (current diff) 5f00bf5a530d (diff)
children 4fc2763e670e
files src/share/vm/graal/graalCompilerToVM.cpp
diffstat 26 files changed, 707 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Wed Jan 16 14:41:15 2013 +0100
@@ -25,9 +25,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 
 /**
@@ -55,7 +52,7 @@
             }
         }};
 
-    public ComputeBlockOrder(int maxBlockId, int loopCount, Block startBlock, boolean reorderLoops) {
+    public ComputeBlockOrder(int maxBlockId, @SuppressWarnings("unused") int loopCount, Block startBlock, @SuppressWarnings("unused") boolean reorderLoops) {
 
         List<Block> newLinearScanOrder = new ArrayList<>();
         List<Block> order = new ArrayList<>();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Wed Jan 16 14:41:15 2013 +0100
@@ -93,6 +93,8 @@
         assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet"));
 //        assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet"));
 
+        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet"));
+        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet"));
         assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet"));
     }
 
@@ -120,6 +122,14 @@
     public static int invokeOverriddenInterfaceMethodSnippet(MultipleImplementorsInterface testInterface) {
         return testInterface.publicOverriddenMethod();
     }
+    @SuppressWarnings("all")
+    public static int invokeOverriddenPublicMethodSnippet(SuperClass superClass) {
+        return superClass.publicOverriddenMethod();
+    }
+    @SuppressWarnings("all")
+    public static int invokeOverriddenProtectedMethodSnippet(SuperClass superClass) {
+        return superClass.protectedOverriddenMethod();
+    }
 
     private StructuredGraph getGraph(final String snippet) {
         return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Wed Jan 16 14:41:15 2013 +0100
@@ -38,6 +38,8 @@
 import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
 import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.DecryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.EncryptBlockStubCall.*;
+import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
+import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*;
 import static com.oracle.graal.lir.amd64.AMD64Call.*;
 
 import com.oracle.graal.api.code.*;
@@ -68,26 +70,26 @@
         addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub,
                 /*           temps */ null,
                 /*             ret */ ret(Kind.Float),
-                /* arg0:         a */ jarg(0, Kind.Float),
-                /* arg1:         b */ jarg(1, Kind.Float));
+                /* arg0:         a */ javaCallingConvention(Kind.Float,
+                /* arg1:         b */                       Kind.Float));
 
         addRuntimeCall(ARITHMETIC_DREM, config.arithmeticDremStub,
                 /*           temps */ null,
                 /*             ret */ ret(Kind.Double),
-                /* arg0:         a */ jarg(0, Kind.Double),
-                /* arg1:         b */ jarg(1, Kind.Double));
+                /* arg0:         a */ javaCallingConvention(Kind.Double,
+                /* arg1:         b */                       Kind.Double));
 
         addRuntimeCall(MONITORENTER, config.monitorEnterStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
-                /* arg0: object */ jarg(0, Kind.Object),
-                /* arg1:   lock */ jarg(1, word));
+                /* arg0: object */ javaCallingConvention(Kind.Object,
+                /* arg1:   lock */                       word));
 
         addRuntimeCall(MONITOREXIT, config.monitorExitStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
-                /* arg0: object */ jarg(0, Kind.Object),
-                /* arg1:   lock */ jarg(1, word));
+                /* arg0: object */ javaCallingConvention(Kind.Object,
+                /* arg1:   lock */                       word));
 
         addRuntimeCall(NEW_ARRAY, 0L,
                 /*        temps */ null,
@@ -126,34 +128,52 @@
         addRuntimeCall(VM_ERROR, config.vmErrorStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
-                /* arg0:  where */ jarg(0, Kind.Object),
-                /* arg1: format */ jarg(1, Kind.Object),
-                /* arg2:  value */ jarg(2, Kind.Long));
+                /* arg0:  where */ javaCallingConvention(Kind.Object,
+                /* arg1: format */                       Kind.Object,
+                /* arg2:  value */                       Kind.Long));
 
         addRuntimeCall(IDENTITY_HASHCODE, config.identityHashCodeStub,
                 /*        temps */ null,
                 /*          ret */ rax.asValue(Kind.Int),
-                /* arg0:    obj */ jarg(0, Kind.Object));
+                /* arg0:    obj */ javaCallingConvention(Kind.Object));
 
         addRuntimeCall(THREAD_IS_INTERRUPTED, config.threadIsInterruptedStub,
                 /*        temps */ null,
                 /*          ret */ rax.asValue(Kind.Int),
-                /* arg0: thread */ jarg(0, Kind.Object),
-      /* arg1: clearInterrupted */ jarg(1, Kind.Boolean));
+                /* arg0: thread */ javaCallingConvention(Kind.Object,
+      /* arg1: clearInterrupted */                       Kind.Boolean));
 
         addRuntimeCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
-                /* arg0:     in */ carg(0, word),
-                /* arg1:    out */ carg(1, word),
-                /* arg2:    key */ carg(2, word));
+                /* arg0:     in */ nativeCallingConvention(word,
+                /* arg1:    out */                         word,
+                /* arg2:    key */                         word));
 
         addRuntimeCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
-                /* arg0:     in */ carg(0, word),
-                /* arg1:    out */ carg(1, word),
-                /* arg2:    key */ carg(2, word));
+                /* arg0:     in */ nativeCallingConvention(word,
+                /* arg1:    out */                         word,
+                /* arg2:    key */                         word));
+
+        addRuntimeCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void),
+                /* arg0:     in */ nativeCallingConvention(word,
+                /* arg1:    out */                         word,
+                /* arg2:    key */                         word,
+                /* arg3:      r */                         word,
+              /* arg4: inLength */                         Kind.Int));
+
+        addRuntimeCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void),
+                /* arg0:     in */ nativeCallingConvention(word,
+                /* arg1:    out */                         word,
+                /* arg2:    key */                         word,
+                /* arg3:      r */                         word,
+              /* arg4: inLength */                         Kind.Int));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Jan 16 14:41:15 2013 +0100
@@ -136,6 +136,7 @@
                         } else {
                             // Compiling an intrinsic graph - must clone the graph
                             graph = graph.copy();
+                            //System.out.println("compiling intrinsic " + method);
                         }
                         return graalRuntime.getCompiler().compileMethod(method, graph, graalRuntime.getCache(), plan, optimisticOpts);
                     }
@@ -192,4 +193,9 @@
         return id < o.id ? -1 : (id > o.id ? 1 : 0);
     }
 
+    @Override
+    public String toString() {
+        return "Compilation[id=" + id + ", prio=" + priority + " " + MetaUtil.format("%H.%n(%p)", method) +
+                        (entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]";
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java	Wed Jan 16 14:41:15 2013 +0100
@@ -49,12 +49,14 @@
                     return;
                 }
             }
-        } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class) {
+        } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) {
             if (!config.useAESIntrinsics) {
                 return;
             }
             assert config.aescryptEncryptBlockStub != 0L;
             assert config.aescryptDecryptBlockStub != 0L;
+            assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
+            assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
         }
         super.installSubstitution(originalMethod, substituteMethod);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jan 16 14:41:15 2013 +0100
@@ -338,6 +338,8 @@
     public long identityHashCodeStub;
     public long aescryptEncryptBlockStub;
     public long aescryptDecryptBlockStub;
+    public long cipherBlockChainingEncryptAESCryptStub;
+    public long cipherBlockChainingDecryptAESCryptStub;
 
     public int deoptReasonNullCheck;
     public int deoptReasonRangeCheck;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Jan 16 14:41:15 2013 +0100
@@ -23,7 +23,7 @@
 
 package com.oracle.graal.hotspot.bridge;
 
-import static com.oracle.graal.graph.FieldIntrospection.*;
+import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import java.io.*;
 import java.lang.reflect.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Jan 16 14:41:15 2013 +0100
@@ -379,6 +379,7 @@
             Arrays.sort(ptypes);
 
             double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability));
+            assert notRecordedTypeProbability == 0 || entries == config.typeProfileWidth;
             return new JavaTypeProfile(notRecordedTypeProbability, ptypes);
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Jan 16 14:41:15 2013 +0100
@@ -166,14 +166,31 @@
         return globalStubRegConfig.getReturnRegister(kind).asValue(kind);
     }
 
-    protected Value jarg(int index, Kind kind) {
-        RegisterFlag flag = kind == Kind.Float || kind == Kind.Double ? FPU : CPU;
-        return globalStubRegConfig.getCallingConventionRegisters(RuntimeCall, flag)[index].asValue(kind);
+    protected Value[] javaCallingConvention(Kind... arguments) {
+        return callingConvention(arguments, RuntimeCall);
+    }
+
+    protected Value[] nativeCallingConvention(Kind... arguments) {
+        return callingConvention(arguments, NativeCall);
     }
 
-    protected Value carg(int index, Kind kind) {
-        RegisterFlag flag = kind == Kind.Float || kind == Kind.Double ? FPU : CPU;
-        return globalStubRegConfig.getCallingConventionRegisters(NativeCall, flag)[index].asValue(kind);
+    private Value[] callingConvention(Kind[] arguments, CallingConvention.Type type) {
+        Value[] result = new Value[arguments.length];
+
+        TargetDescription target = graalRuntime.getTarget();
+        int currentStackOffset = 0;
+        for (int i = 0; i < arguments.length; i++) {
+            Kind kind = arguments[i];
+            RegisterFlag flag = kind == Kind.Float || kind == Kind.Double ? FPU : CPU;
+            Register[] ccRegs = globalStubRegConfig.getCallingConventionRegisters(type, flag);
+            if (i < ccRegs.length) {
+                result[i] = ccRegs[i].asValue(kind);
+            } else {
+                result[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, false);
+                currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize);
+            }
+        }
+        return result;
     }
 
     protected Value scratch(Kind kind) {
@@ -189,17 +206,17 @@
         addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
-                        /* arg0: exception */ jarg(0, Kind.Object));
+                        /* arg0: exception */ javaCallingConvention(Kind.Object));
 
         addRuntimeCall(OnStackReplacementPhase.OSR_MIGRATION_END, config.osrMigrationEndStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
-                        /* arg0:      long */ jarg(0, Kind.Long));
+                        /* arg0:      long */ javaCallingConvention(Kind.Long));
 
         addRuntimeCall(REGISTER_FINALIZER, config.registerFinalizerStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
-                        /* arg0:    object */ jarg(0, Kind.Object));
+                        /* arg0:    object */ javaCallingConvention(Kind.Object));
 
         addRuntimeCall(CREATE_NULL_POINTER_EXCEPTION, config.createNullPointerExceptionStub,
                         /*           temps */ null,
@@ -208,7 +225,7 @@
         addRuntimeCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, config.createOutOfBoundsExceptionStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Object),
-                        /* arg0:     index */ jarg(0, Kind.Int));
+                        /* arg0:     index */ javaCallingConvention(Kind.Int));
 
         addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub,
                         /*           temps */ null,
@@ -221,38 +238,38 @@
         addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Double),
-                        /* arg0:     index */ jarg(0, Kind.Double));
+                        /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Double),
-                        /* arg0:     index */ jarg(0, Kind.Double));
+                        /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Double),
-                        /* arg0:     index */ jarg(0, Kind.Double));
+                        /* arg0:     index */ javaCallingConvention(Kind.Double));
 
         addRuntimeCall(LOG_PRIMITIVE, config.logPrimitiveStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
-                        /* arg0:  typeChar */ jarg(0, Kind.Int),
-                        /* arg1:     value */ jarg(1, Kind.Long),
-                        /* arg2:   newline */ jarg(2, Kind.Boolean));
+                        /* arg0:  typeChar */ javaCallingConvention(Kind.Int,
+                        /* arg1:     value */                       Kind.Long,
+                        /* arg2:   newline */                       Kind.Boolean));
 
         addRuntimeCall(LOG_PRINTF, config.logPrintfStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
-                        /* arg0:    format */ jarg(0, Kind.Object),
-                        /* arg1:     value */ jarg(1, Kind.Long),
-                        /* arg2:     value */ jarg(2, Kind.Long),
-                        /* arg3:     value */ jarg(3, Kind.Long));
+                        /* arg0:    format */ javaCallingConvention(Kind.Object,
+                        /* arg1:     value */                       Kind.Long,
+                        /* arg2:     value */                       Kind.Long,
+                        /* arg3:     value */                       Kind.Long));
 
         addRuntimeCall(LOG_OBJECT, config.logObjectStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
-                        /* arg0:    object */ jarg(0, Kind.Object),
-                        /* arg1:     flags */ jarg(1, Kind.Int));
+                        /* arg0:    object */ javaCallingConvention(Kind.Object,
+                        /* arg1:     flags */                       Kind.Int));
     }
 
 
@@ -322,8 +339,9 @@
         if (GraalOptions.IntrinsifyClassMethods) {
             installer.installSubstitutions(ClassSubstitutions.class);
         }
-        if (GraalOptions.IntrinsifyAESCryptMethods) {
+        if (GraalOptions.IntrinsifyAESMethods) {
             installer.installSubstitutions(AESCryptSubstitutions.class);
+            installer.installSubstitutions(CipherBlockChainingSubstitutions.class);
         }
         if (GraalOptions.IntrinsifyArrayCopy) {
             installer.installSnippets(ArrayCopySnippets.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Wed Jan 16 14:41:15 2013 +0100
@@ -44,13 +44,16 @@
 @ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt")
 public class AESCryptSubstitutions {
 
-    private static final long kOffset;
+    static final long kOffset;
+    static final Class<?> AESCryptClass;
+
     static {
         try {
             // Need to use launcher class path as com.sun.crypto.provider.AESCrypt
             // is normally not on the boot class path
             ClassLoader cl = Launcher.getLauncher().getClassLoader();
-            kOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.AESCrypt", true, cl).getDeclaredField("K"));
+            AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl);
+            kOffset = UnsafeAccess.unsafe.objectFieldOffset(AESCryptClass.getDeclaredField("K"));
         } catch (Exception ex) {
             throw new GraalInternalError(ex);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Wed Jan 16 14:41:15 2013 +0100
@@ -0,0 +1,152 @@
+/*
+ * 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.snippets;
+
+import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+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.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
+import com.oracle.graal.snippets.Snippet.Fold;
+import com.oracle.graal.word.*;
+
+/**
+ * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods.
+ */
+@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining")
+public class CipherBlockChainingSubstitutions {
+
+    private static final long embeddedCipherOffset;
+    private static final long rOffset;
+    static {
+        try {
+            // Need to use launcher class path as com.sun.crypto.provider.AESCrypt
+            // is normally not on the boot class path
+            ClassLoader cl = Launcher.getLauncher().getClassLoader();
+            embeddedCipherOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl).getDeclaredField("embeddedCipher"));
+            rOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl).getDeclaredField("r"));
+        } catch (Exception ex) {
+            throw new GraalInternalError(ex);
+        }
+    }
+
+    @Fold
+    private static Class getAESCryptClass() {
+        return AESCryptSubstitutions.AESCryptClass;
+    }
+
+    @MethodSubstitution(isStatic = false)
+    static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
+        Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset));
+        if (getAESCryptClass().isInstance(embeddedCipher)) {
+            Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte));
+            Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).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);
+            EncryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength);
+        } else {
+            encrypt(rcvr, in, inOffset, inLength, out, outOffset);
+        }
+    }
+
+    @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));
+        if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
+            Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte));
+            Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).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);
+            DecryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength);
+        } else {
+            decrypt(rcvr, in, inOffset, inLength, out, outOffset);
+        }
+    }
+
+    public static class EncryptAESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+        @Input private final ValueNode in;
+        @Input private final ValueNode out;
+        @Input private final ValueNode key;
+        @Input private final ValueNode r;
+        @Input private final ValueNode inLength;
+
+        public static final Descriptor ENCRYPT = new Descriptor("encrypt", false, 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(StampFactory.forVoid());
+            this.in = in;
+            this.out = out;
+            this.key = key;
+            this.r = r;
+            this.inLength = inLength;
+        }
+
+        @Override
+        public void generate(LIRGenerator gen) {
+            RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(ENCRYPT);
+            gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
+        }
+
+        @NodeIntrinsic
+        public static native void call(Word in, Word out, Word key, Word r, int inLength);
+    }
+
+    public static class DecryptAESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+        @Input private final ValueNode in;
+        @Input private final ValueNode out;
+        @Input private final ValueNode key;
+        @Input private final ValueNode r;
+        @Input private final ValueNode inLength;
+
+        public static final Descriptor DECRYPT = new Descriptor("decrypt", false, void.class, Word.class, Word.class, Word.class, Word.class, int.class);
+
+        public DecryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) {
+            super(StampFactory.forVoid());
+            this.in = in;
+            this.out = out;
+            this.key = key;
+            this.r = r;
+            this.inLength = inLength;
+        }
+
+        @Override
+        public void generate(LIRGenerator gen) {
+            RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(DECRYPT);
+            gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
+        }
+
+        @NodeIntrinsic
+        public static native void call(Word in, Word out, Word key, Word r, int inLength);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Wed Jan 16 14:41:15 2013 +0100
@@ -118,8 +118,10 @@
                 StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class);
                 assert snippetGraph != null : "ArrayCopySnippets should be installed";
                 hits = true;
-                Debug.log("%s > Intinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType());
+                Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType());
                 InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false);
+            } else {
+                Debug.log("%s > not intrinsifying arraycopy", Debug.currentScope());
             }
         }
         if (GraalOptions.OptCanonicalizer && hits) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Wed Jan 16 14:41:15 2013 +0100
@@ -43,6 +43,7 @@
     public void setProbability(double probability) {
         assert probability >= 0 : String.format("Invalid argument %f, because the probability of a node must not be negative.", probability);
         this.probability = probability;
+        assert !Double.isNaN(probability);
     }
 
     protected void copyInto(FixedNode newNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Jan 16 14:41:15 2013 +0100
@@ -57,6 +57,10 @@
 
     void setProbability(double value);
 
+    double inliningRelevance();
+
+    void setInliningRelevance(double value);
+
     boolean useForInlining();
 
     void setUseForInlining(boolean value);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Jan 16 14:41:15 2013 +0100
@@ -42,6 +42,7 @@
     private boolean polymorphic;
     private boolean useForInlining;
     private final long leafGraphId;
+    private double inliningRelevance;
 
     /**
      * Constructs a new Invoke instruction.
@@ -56,6 +57,7 @@
         this.leafGraphId = leafGraphId;
         this.polymorphic = false;
         this.useForInlining = true;
+        this.inliningRelevance = Double.NaN;
     }
 
     @Override
@@ -88,6 +90,16 @@
     }
 
     @Override
+    public double inliningRelevance() {
+        return inliningRelevance;
+    }
+
+    @Override
+    public void setInliningRelevance(double value) {
+        inliningRelevance = value;
+    }
+
+    @Override
     public long leafGraphId() {
         return leafGraphId;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Jan 16 14:41:15 2013 +0100
@@ -41,6 +41,7 @@
     private boolean polymorphic;
     private boolean useForInlining;
     private final long leafGraphId;
+    private double inliningRelevance;
 
     public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci, long leafGraphId) {
         super(callTarget.returnStamp());
@@ -50,6 +51,7 @@
         this.leafGraphId = leafGraphId;
         this.polymorphic = false;
         this.useForInlining = true;
+        this.inliningRelevance = Double.NaN;
     }
 
     public DispatchBeginNode exceptionEdge() {
@@ -99,6 +101,16 @@
     }
 
     @Override
+    public double inliningRelevance() {
+        return inliningRelevance;
+    }
+
+    @Override
+    public void setInliningRelevance(double value) {
+        inliningRelevance = value;
+    }
+
+    @Override
     public long leafGraphId() {
         return leafGraphId;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Wed Jan 16 14:41:15 2013 +0100
@@ -65,6 +65,8 @@
                 }
             }
         }
+
+        new ComputeInliningRelevanceIterator(graph).apply();
     }
 
     private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) {
@@ -369,4 +371,74 @@
             return probability;
         }
     }
+
+    private static class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator {
+        private final HashMap<FixedNode, Double> lowestPathProbabilities;
+        private double currentProbability;
+
+        public ComputeInliningRelevanceIterator(StructuredGraph graph) {
+            super(graph);
+            this.lowestPathProbabilities = computeLowestPathProbabilities(graph);
+        }
+
+        @Override
+        protected void initializeScope() {
+            currentProbability = lowestPathProbabilities.get(currentScope);
+        }
+
+        @Override
+        protected void invoke(Invoke invoke) {
+            assert !Double.isNaN(invoke.probability());
+            invoke.setInliningRelevance(invoke.probability() / currentProbability);
+        }
+
+        private HashMap<FixedNode, Double> computeLowestPathProbabilities(StructuredGraph graph) {
+            HashMap<FixedNode, Double> result = new HashMap<>();
+            Deque<FixedNode> scopes = getScopes(graph);
+
+            while (!scopes.isEmpty()) {
+                FixedNode scopeBegin = scopes.pop();
+                double probability = computeLowestPathProbability(scopeBegin);
+                result.put(scopeBegin, probability);
+            }
+
+            return result;
+        }
+
+        private static double computeLowestPathProbability(FixedNode scopeStart) {
+            double minPathProbability = scopeStart.probability();
+            Node current = scopeStart;
+
+            while (current != null) {
+                if (current instanceof ControlSplitNode) {
+                    ControlSplitNode controlSplit = (ControlSplitNode) current;
+                    current = getMaxProbabilitySux(controlSplit);
+                    if (((FixedNode) current).probability() < minPathProbability) {
+                        minPathProbability = ((FixedNode) current).probability();
+                    }
+                } else {
+                    assert current.successors().count() <= 1;
+                    current = current.successors().first();
+                }
+            }
+
+            return minPathProbability;
+        }
+
+        private static Node getMaxProbabilitySux(ControlSplitNode controlSplit) {
+            Node maxSux = null;
+            double maxProbability = 0.0;
+
+            // TODO: process recursively if we have multiple successors with same probability
+            for (Node sux: controlSplit.successors()) {
+                double probability = controlSplit.probability((BeginNode) sux);
+                if (probability > maxProbability) {
+                    maxProbability = probability;
+                    maxSux = sux;
+                }
+            }
+
+            return maxSux;
+        }
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Wed Jan 16 14:41:15 2013 +0100
@@ -81,6 +81,7 @@
 
         while (inliningPolicy.continueInlining(graph)) {
             final InlineInfo candidate = inliningPolicy.next();
+
             if (candidate != null) {
                 boolean isWorthInlining = inliningPolicy.isWorthInlining(candidate);
 
@@ -149,7 +150,8 @@
     }
 
     private abstract static class AbstractInliningDecision implements InliningDecision {
-        public static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
+        protected static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
+            assert !Double.isNaN(info.weight()) && !Double.isNaN(maxSize);
             boolean success = info.weight() <= maxSize;
             if (GraalOptions.Debug) {
                 String formatterString = success ? "(size %f <= %f)" : "(too large %f > %f)";
@@ -158,13 +160,21 @@
             return success;
         }
 
-        public static boolean checkCompiledCodeSize(InlineInfo info) {
+        protected static boolean checkCompiledCodeSize(InlineInfo info) {
             if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
                 InliningUtil.logNotInlinedMethod(info, "(CompiledCodeSize %d > %d)", info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
                 return false;
             }
             return true;
         }
+
+        protected static double getRelevance(Invoke invoke) {
+            if (GraalOptions.UseRelevanceBasedInlining) {
+                return invoke.inliningRelevance();
+            } else {
+                return invoke.probability();
+            }
+        }
     }
 
     private static class C1StaticSizeBasedInliningDecision extends AbstractInliningDecision {
@@ -183,7 +193,7 @@
                 return false;
             }
 
-            double inlineWeight = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability());
+            double inlineWeight = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
             double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize * inlineWeight;
             maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize);
 
@@ -199,7 +209,8 @@
                 return false;
             }
 
-            double inlineBoost = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()) + Math.log10(Math.max(1, info.invoke().probability() - GraalOptions.ProbabilityCapForInlining + 1));
+            double relevance = getRelevance(info.invoke());
+            double inlineBoost = Math.min(GraalOptions.RatioCapForInlining, relevance) + Math.log10(Math.max(1, relevance - GraalOptions.RatioCapForInlining + 1));
             double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize;
             maxSize = maxSize + maxSize * inlineBoost;
             maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize));
@@ -226,7 +237,7 @@
                 maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue;
             }
 
-            double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability());
+            double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
             maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
             maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
 
@@ -240,7 +251,7 @@
             assert GraalOptions.ProbabilityAnalysis;
 
             double maxSize = GraalOptions.MaximumGreedyInlineSize;
-            double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability());
+            double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke()));
             maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio;
             maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
 
@@ -251,6 +262,10 @@
     private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
         @Override
         public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
+            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
+                return 0;
+            }
+
             double codeSize = method.getCodeSize();
             if (preferredInvoke) {
                 codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis;
@@ -262,6 +277,10 @@
     private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy {
         @Override
         public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
+            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
+                return 0;
+            }
+
             double complexity = method.getCompilationComplexity();
             if (preferredInvoke) {
                 complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis;
@@ -273,6 +292,10 @@
     private static class CompiledCodeSizeWeightComputationPolicy implements WeightComputationPolicy {
         @Override
         public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
+            if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) {
+                return 0;
+            }
+
             int compiledCodeSize = method.getCompiledCodeSize();
             return compiledCodeSize > 0 ? compiledCodeSize : method.getCodeSize() * 10;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Wed Jan 16 14:41:15 2013 +0100
@@ -84,7 +84,7 @@
 
     private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) {
         if (shouldLogInliningDecision()) {
-            String methodString = invoke.callTarget() == null ? "callTarget=null" : invoke.callTarget().targetName();
+            String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName());
             logInliningDecision(methodString, false, msg, new Object[0]);
         }
         return false;
@@ -200,11 +200,11 @@
             return computeInliningLevel(invoke);
         }
 
-        protected static StructuredGraph getGraph(final Invoke invoke, final ResolvedJavaMethod concrete, final InliningCallback callback) {
+        protected static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) {
             return Debug.scope("GetInliningGraph", concrete, new Callable<StructuredGraph>() {
                 @Override
                 public StructuredGraph call() throws Exception {
-                    StructuredGraph result = getIntrinsicGraph(invoke, concrete);
+                    StructuredGraph result = getIntrinsicGraph(concrete);
                     if (result == null) {
                         assert !Modifier.isNative(concrete.getModifiers());
                         result = callback.buildGraph(concrete);
@@ -229,14 +229,14 @@
 
         @Override
         public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) {
-            StructuredGraph graph = getGraph(invoke, concrete, callback);
+            StructuredGraph graph = getGraph(concrete, callback);
             assumptions.recordMethodContents(concrete);
             InliningUtil.inline(invoke, graph, true);
         }
 
         @Override
         public int compiledCodeSize() {
-            return concrete.getCompiledCodeSize();
+            return InliningUtil.compiledCodeSize(concrete);
         }
 
         @Override
@@ -261,7 +261,7 @@
 
         @Override
         public int compiledCodeSize() {
-            return concrete.getCompiledCodeSize();
+            return InliningUtil.compiledCodeSize(concrete);
         }
 
         @Override
@@ -283,7 +283,7 @@
             graph.addBeforeFixed(invoke.node(), guard);
             graph.addBeforeFixed(invoke.node(), anchor);
 
-            StructuredGraph calleeGraph = getGraph(invoke, concrete, callback);
+            StructuredGraph calleeGraph = getGraph(concrete, callback);
             assumptions.recordMethodContents(concrete);
             InliningUtil.inline(invoke, calleeGraph, false);
         }
@@ -320,7 +320,7 @@
         public int compiledCodeSize() {
             int result = 0;
             for (ResolvedJavaMethod m: concretes) {
-                result += m.getCompiledCodeSize();
+                result += InliningUtil.compiledCodeSize(m);
             }
             return result;
         }
@@ -410,7 +410,7 @@
             StructuredGraph[] calleeGraphs = new StructuredGraph[numberOfMethods];
             for (int i = 0; i < numberOfMethods; i++) {
                 ResolvedJavaMethod concrete = concretes.get(i);
-                calleeGraphs[i] = getGraph(invoke, concrete, callback);
+                calleeGraphs[i] = getGraph(concrete, callback);
                 assumptions.recordMethodContents(concrete);
             }
 
@@ -512,7 +512,7 @@
             calleeEntryNode.setNext(invoke.node());
 
             ResolvedJavaMethod concrete = concretes.get(0);
-            StructuredGraph calleeGraph = getGraph(invoke, concrete, callback);
+            StructuredGraph calleeGraph = getGraph(concrete, callback);
             assumptions.recordMethodContents(concrete);
             InliningUtil.inline(invoke, calleeGraph, false);
         }
@@ -563,6 +563,7 @@
             result.node().replaceFirstInput(result.callTarget(), callTarget);
             result.setUseForInlining(useForInlining);
             result.setProbability(probability);
+            result.setInliningRelevance(invoke.inliningRelevance() * probability);
 
             Kind kind = invoke.node().kind();
             if (kind != Kind.Void) {
@@ -757,6 +758,7 @@
                 return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining polymorphic calls is disabled (%d types)", ptypes.size());
             }
             if (!optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) {
+                // due to filtering impossible types, notRecordedTypeProbability can be > 0 although the number of types is lower than what can be recorded in a type profile
                 return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.size(), notRecordedTypeProbability * 100);
             }
 
@@ -799,7 +801,7 @@
             ProfiledType ptype = types[i];
             ResolvedJavaType type = ptype.getType();
             assert !type.isInterface() && (type.isArray() || !Modifier.isAbstract(type.getModifiers())) : type;
-            if (holder.isAssignableFrom(type)) {
+            if (!GraalOptions.OptFilterProfiledTypes || holder.isAssignableFrom(type)) {
                 result.add(ptype);
             }
         }
@@ -816,14 +818,14 @@
     }
 
     private static boolean checkInvokeConditions(Invoke invoke) {
-        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
+        if (invoke.predecessor() == null || !invoke.node().isAlive()) {
+            return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code");
+        } else if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node");
         } else if (invoke.methodCallTarget().targetMethod() == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, "target method is null");
         } else if (invoke.stateAfter() == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has no after state");
-        } else if (invoke.predecessor() == null || !invoke.node().isAlive()) {
-            return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code");
         } else if (!invoke.useForInlining()) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is marked to be not used for inlining");
         } else if (invoke.methodCallTarget().receiver() != null && invoke.methodCallTarget().receiver().isConstant() && invoke.methodCallTarget().receiver().asConstant().isNull()) {
@@ -836,7 +838,7 @@
     private static boolean checkTargetConditions(Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) {
         if (method == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "the method is not resolved");
-        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(invoke, method))) {
+        } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(method))) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "it is a non-intrinsic native method");
         } else if (Modifier.isAbstract(method.getModifiers())) {
             return logNotInlinedMethodAndReturnFalse(invoke, method, "it is an abstract method");
@@ -974,6 +976,14 @@
                     }
                     fixed.setProbability(newProbability);
                 }
+                if (node instanceof Invoke) {
+                    Invoke newInvoke = (Invoke) node;
+                    double newRelevance = newInvoke.inliningRelevance() * invoke.inliningRelevance();
+                    if (GraalOptions.LimitInlinedProbability) {
+                        newRelevance = Math.min(newRelevance, invoke.inliningRelevance());
+                    }
+                    newInvoke.setInliningRelevance(newRelevance);
+                }
             }
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
@@ -1032,13 +1042,20 @@
         }
     }
 
-    public static boolean canIntrinsify(Invoke invoke, ResolvedJavaMethod target) {
-        StructuredGraph intrinsicGraph = getIntrinsicGraph(invoke, target);
+    public static boolean canIntrinsify(ResolvedJavaMethod target) {
+        StructuredGraph intrinsicGraph = getIntrinsicGraph(target);
         return intrinsicGraph != null;
     }
 
-    public static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target) {
-        assert invoke.node().isAlive();
+    public static StructuredGraph getIntrinsicGraph(ResolvedJavaMethod target) {
         return (StructuredGraph) target.getCompilerStorage().get(Graph.class);
     }
+
+    private static int compiledCodeSize(ResolvedJavaMethod target) {
+        if (GraalOptions.AlwaysInlineIntrinsics && canIntrinsify(target)) {
+            return 0;
+        } else {
+            return target.getCompiledCodeSize();
+        }
+    }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Wed Jan 16 14:41:15 2013 +0100
@@ -39,6 +39,7 @@
 
     // inlining settings
     public static boolean Inline                             = true;
+    public static boolean AlwaysInlineIntrinsics             = ____;
     public static boolean Intrinsify                         = true;
            static boolean InlineMonomorphicCalls             = true;
            static boolean InlinePolymorphicCalls             = true;
@@ -52,6 +53,7 @@
     public static int     MaximumRecursiveInlining           = 1;
     public static int     SmallCompiledCodeSize              = 2200;
     public static boolean LimitInlinedProbability            = ____;
+    public static boolean UseRelevanceBasedInlining          = ____;
     // WeightBasedInliningPolicy (0)
     public static float   InliningSizePenaltyExp             = 20;
     public static float   MaximumInlineWeight                = 1.25f;
@@ -65,7 +67,7 @@
     // Common options for inlining policies 1 to 4
     public static float   NestedInliningSizeRatio            = 1f;
     public static float   BoostInliningForEscapeAnalysis     = 2f;
-    public static float   ProbabilityCapForInlining          = 1f;
+    public static float   RatioCapForInlining                = 1f;
 
     // escape analysis settings
     public static boolean PartialEscapeAnalysis              = true;
@@ -199,6 +201,7 @@
     public static boolean OptFloatingReads                   = true;
     public static boolean OptTailDuplication                 = true;
     public static boolean OptEliminatePartiallyRedundantGuards = true;
+    public static boolean OptFilterProfiledTypes             = true;
 
     // Intrinsification settings
     public static boolean IntrinsifyArrayCopy                = true;
@@ -208,7 +211,7 @@
     public static boolean IntrinsifyThreadMethods            = true;
     public static boolean IntrinsifyUnsafeMethods            = true;
     public static boolean IntrinsifyMathMethods              = true;
-    public static boolean IntrinsifyAESCryptMethods          = true;
+    public static boolean IntrinsifyAESMethods               = true;
 
     /**
      * Counts the various paths taken through snippets.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Wed Jan 16 14:41:15 2013 +0100
@@ -0,0 +1,175 @@
+/*
+ * 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.phases.graph;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+
+public abstract class ScopedPostOrderNodeIterator {
+    private final NodeBitMap processedNodes;
+    private final Deque<FixedNode> nodeQueue;
+    private final NodeBitMap queuedNodes;
+    private final Deque<FixedNode> scopes;
+
+    protected FixedNode currentScope;
+
+    public ScopedPostOrderNodeIterator(StructuredGraph graph) {
+        this.processedNodes = graph.createNodeBitMap();
+        this.queuedNodes = graph.createNodeBitMap();
+        this.nodeQueue = new ArrayDeque<>();
+        this.scopes = getScopes(graph);
+    }
+
+    public void apply() {
+        while (!scopes.isEmpty()) {
+            processedNodes.clearAll();
+            queuedNodes.clearAll();
+            this.currentScope = scopes.pop();
+            initializeScope();
+            processScope();
+        }
+    }
+
+    public void processScope() {
+        FixedNode current = currentScope;
+        do {
+            assert current.isAlive();
+            processedNodes.mark(current);
+
+            if (current instanceof Invoke) {
+                invoke((Invoke) current);
+                queueSuccessors(current);
+                current = nextQueuedNode();
+            } else if (current instanceof LoopBeginNode) {
+                queueLoopBeginSuccessors((LoopBeginNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof LoopExitNode) {
+                queueLoopExitSuccessors((LoopExitNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof LoopEndNode) {
+                current = nextQueuedNode();
+            } else if (current instanceof MergeNode) {
+                current = ((MergeNode) current).next();
+                assert current != null;
+            } else if (current instanceof FixedWithNextNode) {
+                queueSuccessors(current);
+                current = nextQueuedNode();
+            } else if (current instanceof EndNode) {
+                queueMerge((EndNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof DeoptimizeNode) {
+                current = nextQueuedNode();
+            } else if (current instanceof ReturnNode) {
+                current = nextQueuedNode();
+            } else if (current instanceof UnwindNode) {
+                current = nextQueuedNode();
+            } else if (current instanceof ControlSplitNode) {
+                queueSuccessors(current);
+                current = nextQueuedNode();
+            } else {
+                assert false : current;
+            }
+        } while(current != null);
+    }
+
+    protected void queueLoopBeginSuccessors(LoopBeginNode node) {
+        if (currentScope == node) {
+            queue(node.next());
+        } else if (currentScope instanceof LoopBeginNode) {
+            // so we are currently processing loop A and found another loop B
+            // -> queue all loop exits of B except those that also exit loop A
+            for (LoopExitNode loopExit: node.loopExits()) {
+                if (!((LoopBeginNode) currentScope).loopExits().contains(loopExit)) {
+                    queue(loopExit);
+                }
+            }
+        } else {
+            queue(node.loopExits());
+        }
+    }
+
+    protected void queueLoopExitSuccessors(LoopExitNode node) {
+        if (!(currentScope instanceof LoopBeginNode) || !((LoopBeginNode) currentScope).loopExits().contains(node)) {
+            queueSuccessors(node);
+        }
+    }
+
+    protected Deque<FixedNode> getScopes(StructuredGraph graph) {
+        Deque<FixedNode> result = new ArrayDeque<>();
+        result.push(graph.start());
+        for (LoopBeginNode loopBegin: graph.getNodes(LoopBeginNode.class)) {
+            result.push(loopBegin);
+        }
+        return result;
+    }
+
+    private void queueSuccessors(FixedNode x) {
+        queue(x.successors());
+    }
+
+    private void queue(NodeIterable<? extends Node> iter) {
+        for (Node node : iter) {
+            queue(node);
+        }
+    }
+
+    private void queue(Node node) {
+        if (node != null && !queuedNodes.isMarked(node)) {
+            queuedNodes.mark(node);
+            nodeQueue.addFirst((FixedNode) node);
+        }
+    }
+
+    private FixedNode nextQueuedNode() {
+        if (nodeQueue.isEmpty()) {
+            return null;
+        }
+
+        FixedNode result = nodeQueue.removeFirst();
+        assert queuedNodes.isMarked(result);
+        return result;
+    }
+
+    private void queueMerge(EndNode end) {
+        MergeNode merge = end.merge();
+        if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
+            queuedNodes.mark(merge);
+            nodeQueue.add(merge);
+        }
+    }
+
+    private boolean visitedAllEnds(MergeNode merge) {
+        for (int i = 0; i < merge.forwardEndCount(); i++) {
+            if (!processedNodes.isMarked(merge.forwardEndAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected abstract void initializeScope();
+    protected abstract void invoke(Invoke invoke);
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java	Wed Jan 16 14:41:15 2013 +0100
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.meta.*;
 
 /**
- * Denotes a class that substitutes methods of another specified class with snippets.
+ * Denotes a class that substitutes methods of another specified class.
  * The substitute methods are exactly those annotated by {@link MethodSubstitution}.
  */
 @Retention(RetentionPolicy.RUNTIME)
@@ -35,7 +35,7 @@
 public @interface ClassSubstitution {
 
     /**
-     * Specifies the substituted class.
+     * Specifies the original class.
      * <p>
      * If the default value is specified for this element, then a non-default
      * value must be given for the {@link #className()} element.
@@ -43,9 +43,9 @@
     Class<?> value() default ClassSubstitution.class;
 
     /**
-     * Specifies the substituted class.
+     * Specifies the original class.
      * <p>
-     * This method is provided for cases where the substituted class
+     * This method is provided for cases where the original class
      * is not accessible (according to Java language access control rules).
      * <p>
      * If the default value is specified for this element, then a non-default
@@ -54,29 +54,30 @@
     String className() default "";
 
     /**
-     * Denotes a substitute method.
+     * Denotes a substitute method. A substitute method can call the original/substituted
+     * method by making a recursive call to itself.
      */
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.METHOD)
     public @interface MethodSubstitution {
         /**
-         * Gets the name of the substituted method.
+         * Gets the name of the original method.
          * <p>
          * If the default value is specified for this element, then the
-         * name of the substituted method is same as the substitute method.
+         * name of the original method is same as the substitute method.
          */
         String value() default "";
 
         /**
-         * Determines if the substituted method is static.
+         * Determines if the original method is static.
          */
         boolean isStatic() default true;
 
         /**
-         * Gets the {@linkplain Signature#getMethodDescriptor() signature} of the substituted method.
+         * Gets the {@linkplain Signature#getMethodDescriptor() signature} of the original method.
          * <p>
          * If the default value is specified for this element, then the
-         * signature of the substituted method is the same as the substitute method.
+         * signature of the original method is the same as the substitute method.
          */
         String signature() default "";
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Wed Jan 16 14:41:04 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Wed Jan 16 14:41:15 2013 +0100
@@ -56,6 +56,7 @@
     private final TargetDescription target;
     private final Assumptions assumptions;
     private final BoxingMethodPool pool;
+    private final Thread owner;
 
     /**
      * A graph cache used by this installer to avoid using the compiler
@@ -71,6 +72,7 @@
         this.assumptions = assumptions;
         this.pool = new BoxingMethodPool(runtime);
         this.graphCache = new HashMap<>();
+        this.owner = Thread.currentThread();
     }
 
     /**
@@ -101,6 +103,7 @@
      * {@linkplain ResolvedJavaMethod#getCompilerStorage() compiler storage} of each original method.
      */
     public void installSubstitutions(Class<?> substitutions) {
+        assert owner == Thread.currentThread() : "substitution installation must be single threaded";
         ClassSubstitution classSubstitution = substitutions.getAnnotation(ClassSubstitution.class);
         for (Method substituteMethod : substitutions.getDeclaredMethods()) {
             MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class);
@@ -122,6 +125,11 @@
         }
     }
 
+    // These fields are used to detect calls from the substitute method to the original method.
+    ResolvedJavaMethod substitute;
+    ResolvedJavaMethod original;
+    boolean substituteCallsOriginal;
+
     /**
      * Installs a method substitution.
      *
@@ -129,12 +137,18 @@
      * @param substituteMethod the substitute method
      */
     protected void installSubstitution(Method originalMethod, Method substituteMethod) {
-        ResolvedJavaMethod substitute = runtime.lookupJavaMethod(substituteMethod);
-        ResolvedJavaMethod original = runtime.lookupJavaMethod(originalMethod);
-        //System.out.println("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
-        StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute), true);
-        Object oldValue = original.getCompilerStorage().put(Graph.class, graph);
-        assert oldValue == null;
+        substitute = runtime.lookupJavaMethod(substituteMethod);
+        original = runtime.lookupJavaMethod(originalMethod);
+        try {
+            //System.out.println("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
+            StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute), true);
+            Object oldValue = original.getCompilerStorage().put(Graph.class, graph);
+            assert oldValue == null;
+        } finally {
+            substitute = null;
+            original = null;
+            substituteCallsOriginal = false;
+        }
     }
 
     private SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) {
@@ -161,7 +175,7 @@
 
                 new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph);
 
-                if (isSubstitution) {
+                if (isSubstitution && !substituteCallsOriginal) {
                     // TODO (ds) remove the constraint of only processing substitutions
                     // once issues with the arraycopy snippets have been resolved
                     new SnippetFrameStateCleanupPhase().apply(graph);
@@ -203,14 +217,29 @@
         for (Invoke invoke : graph.getInvokes()) {
             MethodCallTargetNode callTarget = invoke.methodCallTarget();
             ResolvedJavaMethod callee = callTarget.targetMethod();
-            if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) {
-                StructuredGraph targetGraph = parseGraph(callee, policy);
-                InliningUtil.inline(invoke, targetGraph, true);
+            if (callee == substitute) {
+                final StructuredGraph originalGraph = new StructuredGraph(original);
+                new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph);
+                InliningUtil.inline(invoke, originalGraph, true);
+
+                // TODO the inlined frame states still show the call from the substitute to the original.
+                // If this poses a problem, a phase should added to fix up these frame states.
+
                 Debug.dump(graph, "after inlining %s", callee);
                 if (GraalOptions.OptCanonicalizer) {
-                    new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
                     new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
                 }
+                substituteCallsOriginal = true;
+            } else {
+                if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) {
+                    StructuredGraph targetGraph = parseGraph(callee, policy);
+                    InliningUtil.inline(invoke, targetGraph, true);
+                    Debug.dump(graph, "after inlining %s", callee);
+                    if (GraalOptions.OptCanonicalizer) {
+                        new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
+                        new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+                    }
+                }
             }
         }
 
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp	Wed Jan 16 14:41:04 2013 +0100
+++ b/src/cpu/x86/vm/graalRuntime_x86.cpp	Wed Jan 16 14:41:15 2013 +0100
@@ -188,25 +188,46 @@
 
 int GraalStubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3, Register arg4) {
 #ifdef _LP64
-  // if there is any conflict use the stack
-  if (arg1 == c_rarg2 || arg1 == c_rarg3 || arg1 == c_rarg4 ||
-      arg2 == c_rarg1 || arg2 == c_rarg3 || arg2 == c_rarg4 ||
-      arg3 == c_rarg1 || arg3 == c_rarg2 || arg3 == c_rarg4 ||
-      arg4 == c_rarg1 || arg4 == c_rarg2 || arg4 == c_rarg3) {
-    push(arg4);
-    push(arg3);
-    push(arg2);
-    push(arg1);
-    pop(c_rarg1);
-    pop(c_rarg2);
-    pop(c_rarg3);
-    pop(c_rarg4);
-  } else {
-    mov(c_rarg1, arg1);
-    mov(c_rarg2, arg2);
-    mov(c_rarg3, arg3);
-    mov(c_rarg4, arg4);
-  }
+  #ifdef _WIN64
+    // on windows we only have the registers c_rarg0 to c_rarg3 for transferring parameters -> remaining parameters are on the stack
+    if (arg1 == c_rarg2 || arg1 == c_rarg3 || 
+        arg2 == c_rarg1 || arg2 == c_rarg3 || 
+        arg3 == c_rarg1 || arg3 == c_rarg2 || 
+        arg4 == c_rarg1 || arg4 == c_rarg2) {
+      push(arg4);
+      push(arg3);
+      push(arg2);
+      push(arg1);
+      pop(c_rarg1);
+      pop(c_rarg2);
+      pop(c_rarg3);
+    } else {
+      mov(c_rarg1, arg1);
+      mov(c_rarg2, arg2);
+      mov(c_rarg3, arg3);
+      push(arg4);
+    }
+  #else
+    // if there is any conflict use the stack
+    if (arg1 == c_rarg2 || arg1 == c_rarg3 || arg1 == c_rarg4 ||
+        arg2 == c_rarg1 || arg2 == c_rarg3 || arg2 == c_rarg4 ||
+        arg3 == c_rarg1 || arg3 == c_rarg2 || arg3 == c_rarg4 ||
+        arg4 == c_rarg1 || arg4 == c_rarg2 || arg4 == c_rarg3) {
+      push(arg4);
+      push(arg3);
+      push(arg2);
+      push(arg1);
+      pop(c_rarg1);
+      pop(c_rarg2);
+      pop(c_rarg3);
+      pop(c_rarg4);
+    } else {
+      mov(c_rarg1, arg1);
+      mov(c_rarg2, arg2);
+      mov(c_rarg3, arg3);
+      mov(c_rarg4, arg4);
+    }
+  #endif
 #else
   push(arg4);
   push(arg3);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jan 16 14:41:04 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jan 16 14:41:15 2013 +0100
@@ -736,6 +736,8 @@
   set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id)));
   set_long("aescryptEncryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_encryptBlock()));
   set_long("aescryptDecryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_decryptBlock()));
+  set_long("cipherBlockChainingEncryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_encryptAESCrypt()));
+  set_long("cipherBlockChainingDecryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_decryptAESCrypt()));
 
   set_int("deoptReasonNone", Deoptimization::Reason_none);
   set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);
--- a/src/share/vm/graal/graalRuntime.cpp	Wed Jan 16 14:41:04 2013 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Wed Jan 16 14:41:15 2013 +0100
@@ -588,11 +588,9 @@
 JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted))
   // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
   Handle receiverHandle(thread, receiver);
-  JRT_BLOCK
-    MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock);
-    JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
-    return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
-  JRT_BLOCK_END
+  MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock);
+  JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
+  return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
 JRT_END
 
 // JVM_InitializeGraalRuntime