changeset 4993:897b7d18bebc

added RiCompiledMethod.execute and the required VM infrastructure
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 28 Feb 2012 18:00:35 +0100
parents f86ddbd42a7b
children e37be4557f0b
files graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/cri/GraalRuntime.java graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/CompiledMethodTest.java graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java src/cpu/x86/vm/sharedRuntime_x86_64.cpp src/os/bsd/vm/os_bsd.cpp src/os/linux/vm/os_linux.cpp src/os/solaris/vm/os_solaris.cpp src/os_cpu/windows_x86/vm/os_windows_x86.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalJavaAccess.hpp src/share/vm/runtime/javaCalls.cpp src/share/vm/runtime/javaCalls.hpp src/share/vm/runtime/os.hpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp
diffstat 22 files changed, 206 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiCompiledMethod.java	Tue Feb 28 18:00:35 2012 +0100
@@ -27,6 +27,11 @@
  */
 public interface RiCompiledMethod {
 
+    public abstract class MethodInvalidatedException extends RuntimeException {
+
+        private static final long serialVersionUID = -3540232440794244844L;
+    }
+
     /**
      * Returns the method to which the compiled code belongs.
      * @return the method to which the compiled code belongs.
@@ -37,4 +42,6 @@
      * @return true if the code represented by this object is still valid, false otherwise (may happen due to deopt, etc.)
      */
     boolean isValid();
+
+    Object execute(Object arg1, Object arg2, Object arg3);
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Tue Feb 28 18:00:35 2012 +0100
@@ -156,6 +156,7 @@
         if (plan != null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
         }
+        assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
 
         if (GraalOptions.ProbabilityAnalysis) {
             new DeadCodeEliminationPhase().apply(newGraph);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Tue Feb 28 18:00:35 2012 +0100
@@ -109,5 +109,7 @@
 
     String disassembleJava(HotSpotMethodResolved method);
 
+    Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Feb 28 18:00:35 2012 +0100
@@ -156,5 +156,8 @@
     @Override
     public native String disassembleJava(HotSpotMethodResolved method);
 
+    @Override
+    public native Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
+
     // Checkstyle: resume
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java	Tue Feb 28 18:00:35 2012 +0100
@@ -22,17 +22,25 @@
  */
 package com.oracle.max.graal.hotspot.ri;
 
+import java.lang.reflect.*;
+
+import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.hotspot.*;
+import com.oracle.max.graal.hotspot.Compiler;
 
 /**
  * Implementation of RiCompiledMethod for HotSpot. Stores a reference to the nmethod which contains the compiled code.
  */
-public class HotSpotCompiledMethod implements RiCompiledMethod {
+public class HotSpotCompiledMethod extends CompilerObject implements RiCompiledMethod {
+
+    private static final long serialVersionUID = 156632908220561612L;
 
     private final RiResolvedMethod method;
     private long nmethod;
 
-    public HotSpotCompiledMethod(RiResolvedMethod method) {
+    public HotSpotCompiledMethod(Compiler compiler, RiResolvedMethod method) {
+        super(compiler);
         this.method = method;
     }
 
@@ -50,4 +58,13 @@
     public String toString() {
         return "compiled method " + method + " @" + nmethod;
     }
+
+    @Override
+    public Object execute(Object arg1, Object arg2, Object arg3) {
+        assert method.signature().argumentCount(!Modifier.isStatic(method.accessFlags())) == 3;
+        assert method.signature().argumentKindAt(0, false) == CiKind.Object;
+        assert method.signature().argumentKindAt(1, false) == CiKind.Object;
+        assert !Modifier.isStatic(method.accessFlags()) || method.signature().argumentKindAt(2, false) == CiKind.Object;
+        return compiler.getVMEntries().executeCompiledMethod(this, arg1, arg2, arg3);
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Tue Feb 28 18:00:35 2012 +0100
@@ -35,6 +35,7 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.PhasePlan.*;
 import com.oracle.max.graal.cri.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.hotspot.*;
@@ -448,7 +449,7 @@
         runtimeCall.setStateAfter(initialFrameState.duplicateModified(0, false, CiKind.Void, runtimeCall));
 
         @SuppressWarnings("unused")
-        HotSpotCompiledMethod hotSpotCompiledMethod = new HotSpotCompiledMethod(null); // initialize class...
+        HotSpotCompiledMethod hotSpotCompiledMethod = new HotSpotCompiledMethod(null, null); // initialize class...
         RiResolvedType compiledMethodClass = getType(HotSpotCompiledMethod.class);
         RiResolvedField nmethodField = null;
         for (RiResolvedField field : compiledMethodClass.declaredFields()) {
@@ -483,4 +484,12 @@
         CiTargetMethod result = compiler.getCompiler().compileMethod(method, graph, -1, PhasePlan.DEFAULT);
         return result;
     }
+
+    @Override
+    public CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph) {
+        final PhasePlan plan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
+        plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+        return compiler.getCompiler().compileMethod(method, graph, -1, plan);
+    }
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/cri/GraalRuntime.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/cri/GraalRuntime.java	Tue Feb 28 18:00:35 2012 +0100
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
@@ -36,4 +37,6 @@
     void lower(Node n, CiLoweringTool tool);
 
     StructuredGraph intrinsicGraph(RiResolvedMethod caller, int bci, RiResolvedMethod method, List<? extends Node> parameters);
+
+    CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/CompiledMethodTest.java	Tue Feb 28 18:00:35 2012 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.compiler.tests;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiCompiledMethod.MethodInvalidatedException;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+
+/**
+ * In the following tests, the usages of local variable "a" are replaced with the integer constant 0. Then
+ * canonicalization is applied and it is verified that the resulting graph is equal to the graph of the method that just
+ * has a "return 1" statement in it.
+ */
+public class CompiledMethodTest extends GraphTest {
+
+    public static Object testMethod(Object arg1, Object arg2, Object arg3) {
+        return arg1 + " " + arg2 + " " + arg3;
+    }
+
+    @Test
+    public void test1() {
+        Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+
+        for (Node node : graph.getNodes()) {
+            if (node instanceof ConstantNode) {
+                ConstantNode constant = (ConstantNode) node;
+                if (constant.kind() == CiKind.Object && " ".equals(constant.value.asObject())) {
+                    graph.replaceFloating(constant, ConstantNode.forObject("-", runtime, graph));
+                }
+            }
+        }
+
+        final RiResolvedMethod riMethod = runtime.getRiMethod(method);
+        CiTargetMethod targetMethod = runtime.compile(riMethod, graph);
+        RiCompiledMethod compiledMethod = runtime.addMethod(riMethod, targetMethod);
+        try {
+            Object result = compiledMethod.execute("1", "2", "3");
+            Assert.assertEquals("1-2-3", result);
+        } catch (MethodInvalidatedException t) {
+            Assert.fail("method invalidated");
+        }
+
+    }
+}
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java	Tue Feb 28 17:53:07 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java	Tue Feb 28 18:00:35 2012 +0100
@@ -76,6 +76,10 @@
      * @param methodName the name of the method in {@code this.getClass()} to be parsed
      */
     protected StructuredGraph parse(String methodName) {
+        return parse(getMethod(methodName));
+    }
+
+    protected Method getMethod(String methodName) {
         Method found = null;
         for (Method m : this.getClass().getMethods()) {
             if (m.getName().equals(methodName)) {
@@ -84,7 +88,7 @@
             }
         }
         if (found != null) {
-            return parse(found);
+            return found;
         } else {
             throw new RuntimeException("method not found: " + methodName);
         }
@@ -96,18 +100,7 @@
      * @param methodName the name of the method in {@code this.getClass()} to be parsed
      */
     protected StructuredGraph parseProfiled(String methodName) {
-        Method found = null;
-        for (Method m : this.getClass().getMethods()) {
-            if (m.getName().equals(methodName)) {
-                Assert.assertNull(found);
-                found = m;
-            }
-        }
-        if (found != null) {
-            return parseProfiled(found);
-        } else {
-            throw new RuntimeException("method not found: " + methodName);
-        }
+        return parseProfiled(getMethod(methodName));
     }
 
     /**
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -644,6 +644,16 @@
   // Pre-load the register-jump target early, to schedule it better.
   __ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset())));
 
+#ifdef GRAAL
+  // check if this call should be routed towards a specific entry point
+  __ cmpptr(Address(r15_thread, in_bytes(JavaThread::graal_alternate_call_target_offset())), 0);
+  Label no_alternative_target;
+  __ jcc(Assembler::equal, no_alternative_target);
+  __ movptr(r11, Address(r15_thread, in_bytes(JavaThread::graal_alternate_call_target_offset())));
+  __ movptr(Address(r15_thread, in_bytes(JavaThread::graal_alternate_call_target_offset())), 0);
+  __ bind(no_alternative_target);
+#endif
+
   // Now generate the shuffle code.  Pick up all register args and move the
   // rest through the floating point stack top.
   for (int i = 0; i < total_args_passed; i++) {
--- a/src/os/bsd/vm/os_bsd.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/os/bsd/vm/os_bsd.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -4847,9 +4847,9 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void
-os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
+os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm,
                          JavaCallArguments* args, Thread* thread) {
-  f(value, method, args, thread);
+  f(value, method, nm, args, thread);
 }
 
 void os::print_statistics() {
--- a/src/os/linux/vm/os_linux.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/os/linux/vm/os_linux.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -4486,9 +4486,9 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void
-os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
+os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm,
                          JavaCallArguments* args, Thread* thread) {
-  f(value, method, args, thread);
+  f(value, method, nm, args, thread);
 }
 
 void os::print_statistics() {
--- a/src/os/solaris/vm/os_solaris.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/os/solaris/vm/os_solaris.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -4316,8 +4316,8 @@
 
 // This does not do anything on Solaris. This is basically a hook for being
 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
-void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
-  f(value, method, args, thread);
+void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread) {
+  f(value, method, nm, args, thread);
 }
 
 // This routine may be used by user applications as a "hook" to catch signals.
--- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -76,7 +76,7 @@
 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
 
 // Install a win32 structured exception handler around thread.
-void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
+void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread) {
   __try {
 
 #ifndef AMD64
@@ -116,7 +116,7 @@
 #endif // ASSERT
 #endif // !AMD64
 
-    f(value, method, args, thread);
+    f(value, method, nm, args, thread);
   } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) {
       // Nothing to do.
   }
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Feb 28 18:00:35 2012 +0100
@@ -351,6 +351,7 @@
   template(forObject_name,                            "forObject")                                                      \
   template(callbackInternal_name,                     "callbackInternal")                                               \
   template(callback_signature,                        "(Ljava/lang/Object;)Ljava/lang/Object;")                         \
+  template(MethodInvalidatedException,                "com/oracle/max/cri/ri/RiCompiledMethod$MethodInvalidatedException") \
                                                                                                                         \
                                                                                                   \
   /* common method and field names */                                                             \
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -864,6 +864,7 @@
     instanceKlass::cast(HotSpotCompiledMethod::klass())->initialize(CHECK_NULL);
     Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL);
     assert(obj() != NULL, "must succeed in allocating instance");
+    HotSpotCompiledMethod::set_compiler(obj, VMToCompiler::compilerInstance()());
     HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm);
     HotSpotCompiledMethod::set_method(obj, HotSpotTargetMethod::method(targetMethod));
     nm->set_graal_compiled_method(obj());
@@ -923,6 +924,32 @@
   return JNIHandles::make_local(result());
 }
 
+// public Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
+JNIEXPORT jobject JNICALL Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_executeCompiledMethod(JNIEnv *env, jobject, jobject method, jobject arg1, jobject arg2, jobject arg3) {
+  TRACE_graal_3("CompilerToVM::executeCompiledMethod");
+
+  VM_ENTRY_MARK;
+  ResourceMark rm;
+  HandleMark hm;
+
+  methodHandle actualMethod = getMethodFromHotSpotMethod(HotSpotCompiledMethod::method(method));
+  assert(method != NULL, "just checking");
+  JavaValue result(T_OBJECT);
+  JavaCallArguments args;
+  args.push_oop(JNIHandles::resolve(arg1));
+  args.push_oop(JNIHandles::resolve(arg2));
+  args.push_oop(JNIHandles::resolve(arg3));
+
+  nmethod* nm = (nmethod*) HotSpotCompiledMethod::nmethod(method);
+  if (nm == NULL || !nm->is_alive()) {
+    THROW_0(vmSymbols::MethodInvalidatedException());
+  }
+
+  JavaCalls::call(&result, actualMethod, nm, &args, CHECK_NULL);
+
+  return JNIHandles::make_local((oop) result.get_jobject());
+}
+
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_##f))
@@ -984,6 +1011,7 @@
   {CC"installStub",                       CC"("TARGET_METHOD")"PROXY,                           FN_PTR(installStub)},
   {CC"disassembleNative",                 CC"([BJ)"STRING,                                      FN_PTR(disassembleNative)},
   {CC"disassembleJava",                   CC"("RESOLVED_METHOD")"STRING,                        FN_PTR(disassembleJava)},
+  {CC"executeCompiledMethod",             CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Tue Feb 28 18:00:35 2012 +0100
@@ -85,6 +85,7 @@
     int_field(HotSpotField, accessFlags)                                                \
   end_class                                                                             \
   start_class(HotSpotCompiledMethod)                                                    \
+    oop_field(HotSpotCompiledMethod, compiler, "Lcom/oracle/max/graal/hotspot/Compiler;") \
     long_field(HotSpotCompiledMethod, nmethod)                                          \
     oop_field(HotSpotCompiledMethod, method, "Lcom/oracle/max/cri/ri/RiResolvedMethod;") \
   end_class                                                                             \
--- a/src/share/vm/runtime/javaCalls.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/runtime/javaCalls.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -334,10 +334,19 @@
   assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");
   // Need to wrap each and everytime, since there might be native code down the
   // stack that has installed its own exception handlers
-  os::os_exception_wrapper(call_helper, result, &method, args, THREAD);
+  os::os_exception_wrapper(call_helper, result, &method, NULL, args, THREAD);
 }
 
-void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call(JavaValue* result, methodHandle method, nmethod* nm, JavaCallArguments* args, TRAPS) {
+  // Check if we need to wrap a potential OS exception handler around thread
+  // This is used for e.g. Win32 structured exception handlers
+  assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");
+  // Need to wrap each and everytime, since there might be native code down the
+  // stack that has installed its own exception handlers
+  os::os_exception_wrapper(call_helper, result, &method, nm, args, THREAD);
+}
+
+void JavaCalls::call_helper(JavaValue* result, methodHandle* m, nmethod* nm, JavaCallArguments* args, TRAPS) {
   methodHandle method = *m;
   JavaThread* thread = (JavaThread*)THREAD;
   assert(thread->is_Java_thread(), "must be called by a java thread");
@@ -416,6 +425,19 @@
     os::bang_stack_shadow_pages();
   }
 
+  if (nm != NULL) {
+#ifdef GRAAL
+    if (nm->is_alive()) {
+      ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->entry_point());
+      entry_point = method->adapter()->get_i2c_entry();
+    } else {
+      THROW(vmSymbols::MethodInvalidatedException());
+    }
+#else
+    ShouldNotReachHere();
+#endif
+  }
+
   // do call
   { JavaCallWrapper link(method, receiver, result, CHECK);
     { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner
--- a/src/share/vm/runtime/javaCalls.hpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/runtime/javaCalls.hpp	Tue Feb 28 18:00:35 2012 +0100
@@ -190,7 +190,7 @@
 //
 
 class JavaCalls: AllStatic {
-  static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS);
+  static void call_helper(JavaValue* result, methodHandle* method, nmethod* nm, JavaCallArguments* args, TRAPS);
  public:
   // Optimized Constuctor call
   static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS);
@@ -230,6 +230,7 @@
 
   // Low-level interface
   static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);
+  static void call(JavaValue* result, methodHandle method, nmethod* nm, JavaCallArguments* args, TRAPS);
 };
 
 #endif // SHARE_VM_RUNTIME_JAVACALLS_HPP
--- a/src/share/vm/runtime/os.hpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/runtime/os.hpp	Tue Feb 28 18:00:35 2012 +0100
@@ -79,7 +79,7 @@
 };
 
 // Typedef for structured exception handling support
-typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
+typedef void (*java_call_t)(JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread);
 
 class os: AllStatic {
  public:
@@ -632,7 +632,7 @@
   static void init_random(long initval);   // initialize random sequence
 
   // Structured OS Exception support
-  static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
+  static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread);
 
   // On Windows this will create an actual minidump, on Linux/Solaris it will simply check core dump limits
   static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
--- a/src/share/vm/runtime/thread.cpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/runtime/thread.cpp	Tue Feb 28 18:00:35 2012 +0100
@@ -1304,6 +1304,7 @@
   _doing_unsafe_access = false;
   _stack_guard_state = stack_guard_unused;
   _graal_deopt_info = NULL;
+  _graal_alternate_call_target = NULL;
   _exception_oop = NULL;
   _exception_pc  = 0;
   _exception_handler_pc = 0;
--- a/src/share/vm/runtime/thread.hpp	Tue Feb 28 17:53:07 2012 +0100
+++ b/src/share/vm/runtime/thread.hpp	Tue Feb 28 18:00:35 2012 +0100
@@ -870,6 +870,7 @@
   jint graal_multinewarray_storage[256];
 
   volatile oop _graal_deopt_info;
+  address _graal_alternate_call_target;
 
   StackGuardState        _stack_guard_state;
 
@@ -1236,6 +1237,8 @@
   oop      graal_deopt_info() const              { return _graal_deopt_info; }
   void set_graal_deopt_info(oop o)               { _graal_deopt_info = o; }
 
+  void set_graal_alternate_call_target(address a) { _graal_alternate_call_target = a; }
+
   // Exception handling for compiled methods
   oop      exception_oop() const                 { return _exception_oop; }
   address  exception_pc() const                  { return _exception_pc; }
@@ -1316,6 +1319,7 @@
   static ByteSize saved_exception_pc_offset()    { return byte_offset_of(JavaThread, _saved_exception_pc  ); }
   static ByteSize osthread_offset()              { return byte_offset_of(JavaThread, _osthread            ); }
   static ByteSize graal_deopt_info_offset()      { return byte_offset_of(JavaThread, _graal_deopt_info    ); }
+  static ByteSize graal_alternate_call_target_offset() { return byte_offset_of(JavaThread, _graal_alternate_call_target); }
   static ByteSize exception_oop_offset()         { return byte_offset_of(JavaThread, _exception_oop       ); }
   static ByteSize exception_pc_offset()          { return byte_offset_of(JavaThread, _exception_pc        ); }
   static ByteSize exception_handler_pc_offset()  { return byte_offset_of(JavaThread, _exception_handler_pc); }