hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp
changeset 30129 351788433103
parent 30118 dadad0daaab4
child 37466 287c4ebd11b0
--- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp	Tue Mar 31 02:11:09 2015 +0000
+++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp	Tue Mar 31 05:30:36 2015 -0400
@@ -45,6 +45,18 @@
 #include "opto/runtime.hpp"
 #endif
 
+// For SafeFetch we need POSIX tls and setjmp
+#include <setjmp.h>
+#include <pthread.h>
+static pthread_key_t g_jmpbuf_key;
+
+// return the currently active jump buffer for this thread
+//  - if there is any, NULL otherwise. Called from
+//    zero signal handlers.
+extern sigjmp_buf* get_jmp_buf_for_continuation() {
+  return (sigjmp_buf*) pthread_getspecific(g_jmpbuf_key);
+}
+
 // Declaration and definition of StubGenerator (no .hpp file).
 // For a more detailed description of the stub routine structure
 // see the comment in stubRoutines.hpp
@@ -176,17 +188,55 @@
       StubRoutines::_oop_arraycopy;
   }
 
-  // NYI: SafeFetch for Zero isn't actually safe.
   static int SafeFetch32(int *adr, int errValue) {
+
+    // set up a jump buffer; anchor the pointer to the jump buffer in tls; then
+    // do the pointer access. If pointer is invalid, we crash; in signal
+    // handler, we retrieve pointer to jmp buffer from tls, and jump back.
+    //
+    // Note: the jump buffer itself - which can get pretty large depending on
+    // the architecture - lives on the stack and that is fine, because we will
+    // not rewind the stack: either we crash, in which case signal handler
+    // frame is below us, or we don't crash, in which case it does not matter.
+    sigjmp_buf jb;
+    if (sigsetjmp(jb, 1)) {
+      // we crashed. clean up tls and return default value.
+      pthread_setspecific(g_jmpbuf_key, NULL);
+      return errValue;
+    } else {
+      // preparation phase
+      pthread_setspecific(g_jmpbuf_key, &jb);
+    }
+
     int value = errValue;
     value = *adr;
+
+    // all went well. clean tls.
+    pthread_setspecific(g_jmpbuf_key, NULL);
+
     return value;
   }
 
   static intptr_t SafeFetchN(intptr_t *adr, intptr_t errValue) {
+
+    sigjmp_buf jb;
+    if (sigsetjmp(jb, 1)) {
+      // we crashed. clean up tls and return default value.
+      pthread_setspecific(g_jmpbuf_key, NULL);
+      return errValue;
+    } else {
+      // preparation phase
+      pthread_setspecific(g_jmpbuf_key, &jb);
+    }
+
     intptr_t value = errValue;
     value = *adr;
+
+    // all went well. clean tls.
+    pthread_setspecific(g_jmpbuf_key, NULL);
+
     return value;
+
   }
 
   void generate_initial() {
@@ -241,6 +291,7 @@
     generate_arraycopy_stubs();
 
     // Safefetch stubs.
+    pthread_key_create(&g_jmpbuf_key, NULL);
     StubRoutines::_safefetch32_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetch32);
     StubRoutines::_safefetch32_fault_pc = NULL;
     StubRoutines::_safefetch32_continuation_pc = NULL;