harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r424450 - in /incubator/harmony/enhanced/drlvm/trunk/vm/vmcore: include/ src/class_support/ src/exception/ src/init/ src/jit/ src/thread/ src/util/linux/ src/util/win/ia32/
Date Fri, 21 Jul 2006 20:42:15 GMT
Author: geirm
Date: Fri Jul 21 13:42:14 2006
New Revision: 424450

URL: http://svn.apache.org/viewvc?rev=424450&view=rev
Log:
HARMONY-945

DRLVM didn't handle stack overflow in the expected
way (a SOE exception), but just did a seg fault

I added the JIRA's example as a test case, verified
that it failed, and then post patch verified that
it worked on ubuntu 6

Will test on windows


Modified:
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Fri Jul 21 13:42:14
2006
@@ -123,6 +123,7 @@
     Class* java_lang_Error_Class;
     Class* java_lang_ExceptionInInitializerError_Class;
     Class* java_lang_NullPointerException_Class;
+    Class* java_lang_StackOverflowError_Class;
 
     Class* java_lang_ClassNotFoundException_Class;
     Class* java_lang_NoClassDefFoundError_Class;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h Fri Jul 21 13:42:14
2006
@@ -206,6 +206,9 @@
 // Mutates the regs value, which should be used to "resume" the managed code.
 void exn_athrow_regs(Registers* regs, Class_Handle exn_class);
 
+// exception catch callback to restore stack after Stack Overflow Error
+void exception_catch_callback();
+
 //**** Runtime exception support
 
 // rth_throw takes an exception and throws it
@@ -262,5 +265,10 @@
 ManagedObject* get_current_thread_exception();
 VMEXPORT // temporary solution for interpreter unplug
 void __stdcall set_current_thread_exception(ManagedObject* obj);
+
+void set_guard_stack();
+void init_stack_info();
+VMEXPORT size_t get_available_stack_size();
+VMEXPORT bool check_available_stack_size(size_t required_size);
 
 #endif // _EXCEPTIONS_H_

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h Fri Jul 21
13:42:14 2006
@@ -17,6 +17,6 @@
 #ifndef _VERSION_SVN_TAG_
 #define _VERSION_SVN_TAG_
 
-#define VERSION_SVN_TAG  "unknown"
+#define VERSION_SVN_TAG  "424438"
 
 #endif // _VERSION_SVN_TAG_

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h Fri Jul 21 13:42:14
2006
@@ -101,6 +101,12 @@
     // TODO: Needs to be replaced with jobject!
     volatile ManagedObject*           p_exception_object;
 
+    // flag which indicate that guard page on the stak should be restored
+    bool restore_guard_page;
+
+    // thread stack address
+    void* stack_addr;
+
     // Should JVMTI code be notified about exception in p_exception_object
     bool                              ti_exception_callback_pending;
 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp Fri
Jul 21 13:42:14 2006
@@ -116,6 +116,7 @@
     java_lang_Error_Class = NULL;
     java_lang_ExceptionInInitializerError_Class = NULL;
     java_lang_NullPointerException_Class = NULL;
+    java_lang_StackOverflowError_Class = NULL;
     java_lang_ArrayIndexOutOfBoundsException_Class = NULL;
     java_lang_ArrayStoreException_Class = NULL;
     java_lang_ArithmeticException_Class = NULL;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp Fri Jul
21 13:42:14 2006
@@ -510,6 +510,10 @@
     // gc safe operation.
     assert(!tmn_is_suspend_enabled());
     p_TLS_vmthread->p_exception_object = NULL;
+
+    if (p_TLS_vmthread->restore_guard_page) {
+        set_guard_stack();
+    }
 }   //clear_current_thread_exception
 
 void rethrow_current_thread_exception()
@@ -1079,6 +1083,15 @@
 #endif
 }   //exn_athrow_regs
 
+//////////////////////////////////////////////////////////////////////////
+// Exception Catch support
+
+// exception catch callback to restore stack after Stack Overflow Error
+void exception_catch_callback() {
+    if (p_TLS_vmthread->restore_guard_page) {
+        set_guard_stack();
+    }
+}
 
 //////////////////////////////////////////////////////////////////////////
 // Runtime Exception Support

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp Fri Jul 21 13:42:14
2006
@@ -282,6 +282,8 @@
         preload_class(env, "java/lang/ClassNotFoundException");
     env->java_lang_NullPointerException_Class =
         preload_class(env, env->JavaLangNullPointerException_String);
+    env->java_lang_StackOverflowError_Class =
+        preload_class(env, "java/lang/StackOverflowError");
     env->java_lang_ArrayIndexOutOfBoundsException_Class =
         preload_class(env, env->JavaLangArrayIndexOutOfBoundsException_String);
     env->java_lang_ArrayStoreException_Class =
@@ -295,6 +297,8 @@
     env->java_lang_OutOfMemoryError = oh_allocate_global_handle();
 
     tmn_suspend_disable();
+    // precompile StackOverflowError
+    class_alloc_new_object_and_run_default_constructor(env->java_lang_StackOverflowError_Class);
     env->java_lang_OutOfMemoryError->object = 
         class_alloc_new_object(env->java_lang_OutOfMemoryError_Class);
     tmn_suspend_enable();

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp Fri Jul 21 13:42:14
2006
@@ -742,6 +742,8 @@
         return JIT_SUCCESS;
     } else if (method->get_state()==Method::ST_NotCompiled && exn_raised()) {
         return JIT_FAILURE;
+    } else if(!check_available_stack_size(256*1024)) {
+        return JIT_FAILURE;
     }
 
     JIT_Result res = JIT_FAILURE;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp Fri Jul
21 13:42:14 2006
@@ -364,6 +364,13 @@
 //JNI implementation
 void __cdecl call_the_run_method( void * p_args )
 {
+#ifdef _IA32_
+    init_stack_info();
+#ifdef PLATFORM_POSIX
+    set_guard_stack();
+#endif // PLATFORM_POSIX
+#endif // _IA32_
+
     //when a new thread created, gc is disabled, because VM thread structure 
     //was set 0 initially, then gc_enabled_status kept 0 till now
     VM_thread *p_vm_thread=(VM_thread *)(((void **)p_args)[0]); 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp Fri Jul
21 13:42:14 2006
@@ -26,6 +26,7 @@
 #include "cxxlog.h"
 
 #include "platform.h"
+#include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -102,7 +103,17 @@
     uc->uc_mcontext.gregs[REG_ESP] = regs->esp;
 }
 
-static bool linux_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
+static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
+{
+    Registers regs;
+    linux_sigcontext_to_regs(&regs, uc);
+
+    exn_athrow_regs(&regs, exc_clss);
+
+    linux_regs_to_sigcontext(uc, &regs);
+}
+
+static bool java_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
 {
     ASSERT_NO_INTERPRETER;
     unsigned *eip = (unsigned *) uc->uc_mcontext.gregs[REG_EIP];
@@ -111,12 +122,7 @@
         return false;
     }
 
-    Registers regs;
-    linux_sigcontext_to_regs(&regs, uc);
-
-    exn_athrow_regs(&regs, exc_clss);
-
-    linux_regs_to_sigcontext(uc, &regs);
+    throw_from_sigcontext(uc, exc_clss);
     return true;
 }
 
@@ -185,6 +191,142 @@
     addr2line(buf);
 }
 
+/*
+ * Information about stack
+ */
+inline void* find_stack_addr() {
+    int err;
+    void* stack_addr;
+    pthread_attr_t pthread_attr;
+
+    pthread_t thread = pthread_self();
+    err = pthread_getattr_np(thread, &pthread_attr);
+    err = pthread_attr_getstackaddr(&pthread_attr, &stack_addr);
+    pthread_attr_destroy(&pthread_attr);
+    return stack_addr;
+}
+
+inline size_t find_stack_size() {
+    int err;
+    size_t stack_size;
+    pthread_attr_t pthread_attr;
+
+    pthread_attr_init(&pthread_attr);
+    err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
+    pthread_attr_destroy(&pthread_attr);
+    return stack_size;
+}
+
+inline size_t find_guard_stack_size() {
+    return 64*1024;
+}
+
+inline size_t find_guard_page_size() {
+    int err;
+    size_t guard_size;
+    pthread_attr_t pthread_attr;
+
+    pthread_attr_init(&pthread_attr);
+    err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
+    pthread_attr_destroy(&pthread_attr);
+    return guard_size;
+}
+
+static size_t common_stack_size;
+static size_t common_guard_stack_size;
+static size_t common_guard_page_size;
+
+inline void* get_stack_addr() {
+    return p_TLS_vmthread->stack_addr;
+}
+
+inline size_t get_stack_size() {
+    return common_stack_size;
+}
+
+inline size_t get_guard_stack_size() {
+    return common_guard_stack_size;
+}
+
+inline size_t get_guard_page_size() {
+    return common_guard_page_size;
+}
+
+
+void init_stack_info() {
+    p_TLS_vmthread->stack_addr = find_stack_addr();
+    common_stack_size = find_stack_size();
+    common_guard_stack_size = find_guard_stack_size();
+    common_guard_page_size =find_guard_page_size();
+}
+
+void set_guard_stack() {
+    int err;
+    char* stack_addr = (char*) get_stack_addr();
+    size_t stack_size = get_stack_size();
+    size_t guard_stack_size = get_guard_stack_size();
+    size_t guard_page_size = get_guard_page_size();
+
+    err = mprotect(stack_addr - stack_size + guard_page_size + guard_stack_size,
+        guard_page_size, PROT_NONE);
+
+    stack_t sigalt;
+    sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
+    sigalt.ss_flags = SS_ONSTACK;
+    sigalt.ss_size = guard_stack_size;
+
+    err = sigaltstack (&sigalt, NULL);
+}
+
+size_t get_available_stack_size() {
+    char* stack_adrr = (char*) get_stack_addr();
+    size_t used_stack_size = stack_adrr - ((char*)&stack_adrr);
+    size_t available_stack_size =
+            get_stack_size() - used_stack_size
+            - get_guard_page_size() - get_guard_stack_size();
+    return available_stack_size;
+}
+
+bool check_available_stack_size(size_t required_size) {
+    if (get_available_stack_size() < required_size) {
+        exn_raise_by_name("java/lang/StackOverflowError");
+        return false;
+    } else {
+        return true;
+    }
+}
+
+void remove_guard_stack() {
+    int err;
+    char* stack_addr = (char*) get_stack_addr();
+    size_t stack_size = get_stack_size();
+    size_t guard_stack_size = get_guard_stack_size();
+    size_t guard_page_size = get_guard_page_size();
+
+    err = mprotect(stack_addr - stack_size + guard_page_size + guard_stack_size,
+        guard_page_size, PROT_READ | PROT_WRITE);
+
+    stack_t sigalt;
+    sigalt.ss_sp = stack_addr - stack_size + guard_page_size;
+    sigalt.ss_flags = SS_DISABLE;
+    sigalt.ss_size = guard_stack_size;
+
+    err = sigaltstack (&sigalt, NULL);
+}
+
+bool check_stack_overflow(siginfo_t *info, ucontext_t *uc) {
+    char* stack_addr = (char*) get_stack_addr();
+    size_t stack_size = get_stack_size();
+    size_t guard_stack_size = get_guard_stack_size();
+    size_t guard_page_size = get_guard_page_size();
+
+    char* guard_page_begin = stack_addr - stack_size + guard_page_size + guard_stack_size;
+    char* guard_page_end = guard_page_begin + guard_page_size;
+    char* fault_addr = (char*)(info->si_addr);
+    //char* esp_value = (char*)(uc->uc_mcontext.gregs[REG_ESP]);
+
+    return((guard_page_begin <= fault_addr) && (fault_addr <= guard_page_end));
+}
 
 /*
  * We find the true signal stack frame set-up by kernel,which is located
@@ -193,17 +335,48 @@
  * returned, application can continue its execution in Java exception handler.
  */
 
+void stack_overflow_handler(int signum, siginfo_t* UNREF info, void* context)
+{
+    ucontext_t *uc = (ucontext_t *)context;
+    Global_Env *env = VM_Global_State::loader_env;
+
+    if (java_throw_from_sigcontext(
+                uc, env->java_lang_StackOverflowError_Class)) {
+        return;
+    } else {
+        if (is_unwindable()) {
+            if (tmn_is_suspend_enabled()) {
+                tmn_suspend_disable();
+            }
+            throw_from_sigcontext(
+                uc, env->java_lang_StackOverflowError_Class);
+        } else {
+            remove_guard_stack();
+            exn_raise_by_name("java/lang/StackOverflowError");
+            p_TLS_vmthread->restore_guard_page = true;
+        }
+    }
+}
+
 void null_java_reference_handler(int signum, siginfo_t* UNREF info, void* context)
 {
     ucontext_t *uc = (ucontext_t *)context;
     Global_Env *env = VM_Global_State::loader_env;
 
+    if (check_stack_overflow(info, uc)) {
+        stack_overflow_handler(signum, info, context);
+        return;
+    }
+
     if (env->shutting_down != 0) {
         fprintf(stderr, "null_java_reference_handler(): called in shutdown stage\n");
     } else if (!interpreter_enabled()) {
-        if (linux_throw_from_sigcontext(
+        if (java_throw_from_sigcontext(
                     uc, env->java_lang_NullPointerException_Class)) {
             return;
+        } else {
+            fprintf(stderr, "SIGSEGV in VM code.\n");
+            return;
         }
     }
 
@@ -220,7 +393,7 @@
     if (env->shutting_down != 0) {
         fprintf(stderr, "null_java_divide_by_zero_handler(): called in shutdown stage\n");
     } else if (!interpreter_enabled()) {
-        if (linux_throw_from_sigcontext(
+        if (java_throw_from_sigcontext(
                     uc, env->java_lang_ArithmeticException_Class)) {
             return;
         }
@@ -305,7 +478,7 @@
         ebp = (uint32 *)ebp[0];
     }
 
-    if (sc_nest < 0) {
+     if (sc_nest < 0) {
         printf("cannot locate sigcontext.\n");
         printf("Please add or remove any irrelevant statement(e.g. add a null printf) in
VM source code, then rebuild it. If problem remains, please submit a bug report. Thank you
very much\n");
         exit(1);
@@ -376,7 +549,7 @@
     sigaction(SIGUSR2, &sa, NULL);
 
     sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_SIGINFO;
+    sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
     sa.sa_sigaction = &null_java_reference_handler;
     sigaction(SIGSEGV, &sa, NULL);
 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp?rev=424450&r1=424449&r2=424450&view=diff
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp
(original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp
Fri Jul 21 13:42:14 2006
@@ -21,6 +21,7 @@
 
 #include "cxxlog.h"
 #include "method_lookup.h"
+#include "m2n.h"
 #include "open/thread.h"
 #include "Environment.h"
 #include "exceptions.h"
@@ -148,6 +149,141 @@
     fflush(stderr);
 }
 
+/*
+ * Information about stack
+ */
+inline void* find_stack_addr() {
+    void* stack_addr;
+    size_t reg_size;
+    MEMORY_BASIC_INFORMATION memory_information;
+
+    VirtualQuery(&memory_information, &memory_information, sizeof(memory_information));
+    reg_size = memory_information.RegionSize;
+    stack_addr =((char*) memory_information.BaseAddress) + reg_size;
+
+    return stack_addr;
+}
+
+inline size_t find_stack_size() {
+   void* stack_addr;
+    size_t stack_size;
+    size_t reg_size;
+    MEMORY_BASIC_INFORMATION memory_information;
+
+    VirtualQuery(&memory_information, &memory_information, sizeof(memory_information));
+    reg_size = memory_information.RegionSize;
+    stack_addr = ((char*) memory_information.BaseAddress) + reg_size;
+    stack_size = ((char*) stack_addr) - ((char*) memory_information.AllocationBase);
+
+    return stack_size;
+}
+
+inline size_t find_guard_page_size() {
+    size_t  guard_size;
+    SYSTEM_INFO system_info;
+
+    GetSystemInfo(&system_info);
+    guard_size = system_info.dwPageSize;
+
+    return guard_size;
+}
+
+inline size_t find_guard_stack_size() {
+    // guaerded stack size on windows can be equals one page size only :(
+    return find_guard_page_size();
+}
+
+static size_t common_stack_size;
+static size_t common_guard_stack_size;
+static size_t common_guard_page_size;
+
+inline void* get_stack_addr() {
+    return p_TLS_vmthread->stack_addr;
+}
+
+inline size_t get_stack_size() {
+    return common_stack_size;
+}
+
+inline size_t get_guard_stack_size() {
+    return common_guard_stack_size;
+}
+
+inline size_t get_guard_page_size() {
+    return common_guard_page_size;
+}
+
+
+void init_stack_info() {
+    p_TLS_vmthread->stack_addr = find_stack_addr();
+    common_stack_size = find_stack_size();
+    common_guard_stack_size = find_guard_stack_size();
+    common_guard_page_size =find_guard_page_size();
+}
+
+void set_guard_stack() {
+    void* stack_addr = get_stack_addr();
+    size_t stack_size = get_stack_size();
+    size_t page_size = get_guard_page_size();
+
+    if (!VirtualFree((char*)stack_addr - stack_size + page_size,
+        page_size, MEM_DECOMMIT)) {
+        // should be successful always
+        assert(0);
+    }
+
+    DWORD oldProtect;
+
+    if (!VirtualProtect((char*)stack_addr - stack_size + page_size + page_size,
+        page_size, PAGE_GUARD | PAGE_READWRITE, &oldProtect)) {
+        // should be successful always
+        assert(0);
+    }
+
+    p_TLS_vmthread->restore_guard_page = false;
+}
+
+size_t get_available_stack_size() {
+    char* stack_adrr = (char*) get_stack_addr();
+    size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)(&stack_adrr));
+    size_t available_stack_size =
+            get_stack_size() - used_stack_size
+            - get_guard_page_size() - get_guard_stack_size();
+    return available_stack_size;
+}
+
+bool check_available_stack_size(size_t required_size) {
+    if (get_available_stack_size() < required_size) {
+        exn_raise_by_name("java/lang/StackOverflowError");
+        return false;
+    } else {
+        return true;
+    }
+}
+
+// exception catch callback to restore stack after Stack Overflow Error
+static void __cdecl exception_catch_callback_wrapper(){
+    exception_catch_callback();
+}
+
+static void __declspec(naked) __stdcall naked_exception_catch_callback() {
+    __asm {
+        push ebp
+        mov ebp, esp
+        push eax
+        push ebx
+        push ecx
+        push edx
+        call exception_catch_callback_wrapper
+        pop edx
+        pop ecx
+        pop ebx
+        pop eax
+        leave
+        ret
+    }
+}
+
 LONG NTAPI vectored_exception_handler(LPEXCEPTION_POINTERS nt_exception)
 {
     DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
@@ -167,9 +303,22 @@
         // method else crash handler or default handler is executed, this means that
         // it was thrown by VM C/C++ code.
         if ((code == STATUS_ACCESS_VIOLATION
-                || code == STATUS_INTEGER_DIVIDE_BY_ZERO)
-                && vm_identify_eip((void *)context->Eip) == VM_TYPE_JAVA)
+                || code == STATUS_INTEGER_DIVIDE_BY_ZERO
+                || code == STATUS_STACK_OVERFLOW)
+                && vm_identify_eip((void *)context->Eip) == VM_TYPE_JAVA) {
             run_default_handler = false;
+        } else if (code == STATUS_STACK_OVERFLOW) {
+            if (is_unwindable()) {
+                if (tmn_is_suspend_enabled()) {
+                    tmn_suspend_disable();
+                }
+                run_default_handler = false;
+            } else {
+                exn_raise_by_name("java/lang/StackOverflowError");
+                p_TLS_vmthread->restore_guard_page = true;
+                return EXCEPTION_CONTINUE_EXECUTION;
+            }
+        }
 
     } else {
         if (VM_Global_State::loader_env->shutting_down > 1) {
@@ -233,6 +382,17 @@
 
     switch(nt_exception->ExceptionRecord->ExceptionCode) 
     {
+    case STATUS_STACK_OVERFLOW:
+        // stack overflow exception -- see ...\vc\include\winnt.h
+        {
+            TRACE2("signals", "StackOverflowError detected at "
+                << (void *) context->Eip << " on the stack at "
+                << (void *) context->Esp);
+            // Lazy exception object creation
+            exc_clss = env->java_lang_StackOverflowError_Class;
+            p_TLS_vmthread->restore_guard_page = true;
+        }
+        break;
     case STATUS_ACCESS_VIOLATION:
         // null pointer exception -- see ...\vc\include\winnt.h
         {
@@ -256,9 +416,25 @@
     }
 
     Registers regs;
+
     nt_to_vm_context(context, &regs);
 
+    uint32 exception_esp = regs.esp;
+    DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
+
     exn_athrow_regs(&regs, exc_clss);
+
+    if (exception_esp < regs.esp) {
+        if (p_TLS_vmthread->restore_guard_page) {
+            regs.esp = regs.esp - 4;
+            *((uint32*) regs.esp) = regs.eip;
+            regs.eip = ((uint32)naked_exception_catch_callback);
+        }
+    } else {
+        // should be unreachable code
+        //jvmti_exception_catch_callback(&regs);
+        assert(0);
+    }
 
     vm_to_nt_context(&regs, context);
 



Mime
View raw message