diff --git a/vm/interpreter/src/interpreter.cpp b/vm/interpreter/src/interpreter.cpp index 95939d2..c81bb2d 100644 --- a/vm/interpreter/src/interpreter.cpp +++ b/vm/interpreter/src/interpreter.cpp @@ -2595,7 +2595,6 @@ interpreter(StackFrame &frame) { if (!(state & INTERP_STATE_STACK_OVERFLOW)) { state |= INTERP_STATE_STACK_OVERFLOW; interp_throw_exception("java/lang/StackOverflowError"); - state &= ~INTERP_STATE_STACK_OVERFLOW; if (frame.framePopListener) frame_pop_callback(frame.framePopListener, frame.method, true); @@ -3090,6 +3089,12 @@ got_exception: frame.stack.pick().cr = COMPRESS_REF(frame.exc); frame.stack.ref() = FLAG_OBJECT; frame.exc = NULL; + + int &state = get_thread_ptr()->interpreter_state; + + if (state & INTERP_STATE_STACK_OVERFLOW) { + state &= ~INTERP_STATE_STACK_OVERFLOW; + } continue; } diff --git a/vm/port/include/stack_iterator.h b/vm/port/include/stack_iterator.h index 363480a..b13870d 100644 --- a/vm/port/include/stack_iterator.h +++ b/vm/port/include/stack_iterator.h @@ -144,6 +144,15 @@ bool si_is_past_end(StackIterator* si ); void si_goto_previous(StackIterator* si, bool over_popped = true); /** + * Gets the pointer to the top of the stack. + * + * @param[in] si - the pointer to the stack iterator indicating stack + * + * @return The pointer to the top of the stack. + */ +void* si_get_sp(StackIterator* si); + +/** * Gets the instruction pointer for the current frame. * * @param[in] si - the pointer to the stack iterator indicating the current frame diff --git a/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp b/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp index 6934278..b77558a 100644 --- a/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp +++ b/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp @@ -403,6 +403,10 @@ void si_free(StackIterator * si) { STD_FREE(si); } +void* si_get_sp(StackIterator* si) { + return (void*)si->jit_frame_context.rsp; +} + NativeCodePtr si_get_ip(StackIterator * si) { ASSERT_NO_INTERPRETER return (NativeCodePtr)(*si->jit_frame_context.p_rip); diff --git a/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp b/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp index 1a17b37..2c1a446 100644 --- a/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp +++ b/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp @@ -349,6 +349,10 @@ void si_free(StackIterator* si) STD_FREE(si); } +void* si_get_sp(StackIterator* si) { + return (void*)si->c.esp; +} + NativeCodePtr si_get_ip(StackIterator* si) { ASSERT_NO_INTERPRETER diff --git a/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp b/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp index fec7f05..e43934f 100644 --- a/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp +++ b/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp @@ -560,6 +560,10 @@ void si_free(StackIterator* si) STD_FREE(si); } +void* si_get_sp(StackIterator* si) { + return (void*)si->c.sp; +} + NativeCodePtr si_get_ip(StackIterator* si) { return (NativeCodePtr)*si->c.p_eip; diff --git a/vm/vmcore/include/exceptions.h b/vm/vmcore/include/exceptions.h index e7a9be7..190f113 100644 --- a/vm/vmcore/include/exceptions.h +++ b/vm/vmcore/include/exceptions.h @@ -269,17 +269,15 @@ void print_uncaught_exception_message(FILE *f, char* context_message, jthrowable void exn_rethrow(); void exn_rethrow_if_pending(); -#ifndef _EM64T_ void set_guard_stack(); -#endif void init_stack_info(); #ifndef WIN32 void remove_guard_stack(); #endif VMEXPORT size_t get_available_stack_size(); -#ifndef _EM64T_ VMEXPORT bool check_available_stack_size(size_t required_size); -#endif VMEXPORT size_t get_default_stack_size(); +VMEXPORT size_t get_restore_stack_size(); +bool check_stack_size_enough_for_exception_catch(void* sp); #endif // _EXCEPTIONS_H_ diff --git a/vm/vmcore/include/exceptions_jit.h b/vm/vmcore/include/exceptions_jit.h index c749607..8fc6ff2 100644 --- a/vm/vmcore/include/exceptions_jit.h +++ b/vm/vmcore/include/exceptions_jit.h @@ -94,6 +94,7 @@ NativeCodePtr exn_get_rth_throw_illegal_state_exception(); Class_Handle exn_get_class_cast_exception_type(); // Exception catch callback for jvm ti support implementation +extern "C" void asm_exception_catch_callback(); extern "C" void asm_jvmti_exception_catch_callback(); #endif // _EXCEPTIONS_JIT_H_ diff --git a/vm/vmcore/src/class_support/String_Pool.cpp b/vm/vmcore/src/class_support/String_Pool.cpp index aae525e..cfaac3e 100644 --- a/vm/vmcore/src/class_support/String_Pool.cpp +++ b/vm/vmcore/src/class_support/String_Pool.cpp @@ -330,6 +330,11 @@ ManagedObject * String_Pool::intern(String * str) { if (!lang_string) { // if OutOfMemory return NULL; } + + if (exn_raised()) { //if RuntimeException or Error + return NULL; + } + string->object = lang_string; assert(!hythread_is_suspend_enabled()); @@ -339,7 +344,10 @@ ManagedObject * String_Pool::intern(String * str) { assert(env->VM_intern); vm_execute_java_method_array((jmethodID)env->VM_intern, (jvalue*)&string, args); - assert(!exn_raised()); + + if (exn_raised()) { //if RuntimeException or Error + return NULL; + } assert(string); assert(string->object); diff --git a/vm/vmcore/src/exception/exceptions_impl.cpp b/vm/vmcore/src/exception/exceptions_impl.cpp index b436596..1ae89aa 100644 --- a/vm/vmcore/src/exception/exceptions_impl.cpp +++ b/vm/vmcore/src/exception/exceptions_impl.cpp @@ -246,6 +246,10 @@ jthrowable create_exception(Class* exc_class, Method* exc_init, jvalue* args) { exc_object->object = man_obj; args[0].l = exc_object; + if (exn_raised()) { //if RuntimeException or Error + return NULL; + } + vm_execute_java_method_array((jmethodID) exc_init, 0, args); if (suspended_enabled) { diff --git a/vm/vmcore/src/exception/exceptions_jit.cpp b/vm/vmcore/src/exception/exceptions_jit.cpp index e113b71..e58fea3 100644 --- a/vm/vmcore/src/exception/exceptions_jit.cpp +++ b/vm/vmcore/src/exception/exceptions_jit.cpp @@ -166,6 +166,7 @@ static ManagedObject *create_lazy_exception( return result; } //create_object_lazily + ////////////////////////////////////////////////////////////////////////// // Main Exception Propogation Function @@ -206,6 +207,7 @@ static void exn_propagate_exception( Method *interrupted_method; NativeCodePtr interrupted_method_location; JIT *interrupted_method_jit; + bool restore_guard_page = p_TLS_vmthread->restore_guard_page; if (!si_is_native(si)) { @@ -302,6 +304,13 @@ static void exn_propagate_exception( } } #endif // VM_STATS + + if (restore_guard_page) { + if (!check_stack_size_enough_for_exception_catch(si_get_sp(si))) { + break; + } + } + // Setup handler context jit->fix_handler_context(method, si_get_jit_context(si)); si_set_ip(si, handler->get_handler_ip(), false); @@ -472,6 +481,10 @@ void exn_throw_for_JIT(ManagedObject* exn_obj, Class_Handle exn_class, NativeCodePtr callback = (NativeCodePtr) asm_jvmti_exception_catch_callback; si_set_callback(si, &callback); + } else if (p_TLS_vmthread->restore_guard_page) { + NativeCodePtr callback = (NativeCodePtr) + asm_exception_catch_callback; + si_set_callback(si, &callback); } // don't put any call here @@ -530,18 +543,14 @@ void exn_athrow_regs(Registers * regs, Class_Handle exn_class, bool java_code) // exception catch callback to restore stack after Stack Overflow Error void exception_catch_callback() { if (p_TLS_vmthread->restore_guard_page) { -#ifndef _EM64T_ set_guard_stack(); -#endif } } // exception catch support for JVMTI, also restore stack after Stack Overflow Error void jvmti_exception_catch_callback(Registers* regs) { if (p_TLS_vmthread->restore_guard_page) { -#ifndef _EM64T_ set_guard_stack(); -#endif } M2nFrame *m2nf = m2n_push_suspended_frame(regs); diff --git a/vm/vmcore/src/util/linux/signals_em64t.cpp b/vm/vmcore/src/util/linux/signals_em64t.cpp index d9ce667..c7b9eef 100644 --- a/vm/vmcore/src/util/linux/signals_em64t.cpp +++ b/vm/vmcore/src/util/linux/signals_em64t.cpp @@ -104,8 +104,48 @@ void linux_regs_to_ucontext(ucontext_t *uc, Registers* regs) uc->uc_mcontext.gregs[REG_RSP] = regs->rsp; } +// exception catch support for stack restore +extern "C" { + static void __attribute__ ((used, cdecl)) exception_catch_callback_wrapper(){ + exception_catch_callback(); + } +} + +void __attribute__ ((cdecl)) asm_exception_catch_callback() { + asm ( + "pushq %%rax;\n" + "pushq %%rbx;\n" + "pushq %%rcx;\n" + "pushq %%rdx;\n" + "pushq %%rsi;\n" + "pushq %%rdi;\n" + "pushq %%r8;\n" + "pushq %%r9;\n" + "pushq %%r10;\n" + "pushq %%r11;\n" + "call exception_catch_callback_wrapper;\n" + "popq %%r11;\n" + "popq %%r10;\n" + "popq %%r9;\n" + "popq %%r8;\n" + "popq %%rdi;\n" + "popq %%rsi;\n" + "popq %%rdx;\n" + "popq %%rcx;\n" + "popq %%rbx;\n" + "popq %%rax;\n" + : /* no output operands */ + : /* no input operands */ + ); +} + +// exception catch support for JVMTI void asm_jvmti_exception_catch_callback() { + // FIXME: not implemented + fprintf(stderr, "FIXME: asm_jvmti_exception_catch_callback: not implemented\n"); assert(0); + abort(); + } static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss) { @@ -284,7 +324,7 @@ size_t get_available_stack_size() { 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(); + - 2 * get_guard_page_size() - get_guard_stack_size(); return available_stack_size; } @@ -298,6 +338,19 @@ bool check_available_stack_size(size_t required_size) { } } +size_t get_restore_stack_size() { + return 0x8000; +} + +bool check_stack_size_enough_for_exception_catch(void* sp) { + char* stack_adrr = (char*) get_stack_addr(); + size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp); + size_t available_stack_size = + get_stack_size() - used_stack_size + - 2 * get_guard_page_size() - get_guard_stack_size(); + return get_restore_stack_size() < available_stack_size; +} + void remove_guard_stack() { int err; char* stack_addr = (char*) get_stack_addr(); diff --git a/vm/vmcore/src/util/linux/signals_ia32.cpp b/vm/vmcore/src/util/linux/signals_ia32.cpp index 007f9c9..a1351ca 100644 --- a/vm/vmcore/src/util/linux/signals_ia32.cpp +++ b/vm/vmcore/src/util/linux/signals_ia32.cpp @@ -106,6 +106,29 @@ void linux_regs_to_ucontext(ucontext_t *uc, Registers* regs) uc->uc_mcontext.gregs[REG_EFL] = regs->eflags; } +// exception catch support for stack restore +extern "C" { + static void __attribute__ ((used, cdecl)) exception_catch_callback_wrapper(){ + exception_catch_callback(); + } +} + +void __attribute__ ((cdecl)) asm_exception_catch_callback() { + asm ( + "pushl %%eax;\n" + "pushl %%ebx;\n" + "pushl %%ecx;\n" + "pushl %%edx;\n" + "call exception_catch_callback_wrapper;\n" + "popl %%edx;\n" + "popl %%ecx;\n" + "popl %%ebx;\n" + "popl %%eax;\n" + : /* no output operands */ + : /* no input operands */ + ); +} + // exception catch support for JVMTI extern "C" { static void __attribute__ ((used, cdecl)) jvmti_exception_catch_callback_wrapper(Registers regs){ @@ -390,7 +413,7 @@ size_t get_available_stack_size() { 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(); + - 2 * get_guard_page_size() - get_guard_stack_size(); return available_stack_size; } size_t get_default_stack_size() { @@ -407,6 +430,19 @@ bool check_available_stack_size(size_t required_size) { } } +size_t get_restore_stack_size() { + return 0x8000; +} + +bool check_stack_size_enough_for_exception_catch(void* sp) { + char* stack_adrr = (char*) get_stack_addr(); + size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp); + size_t available_stack_size = + get_stack_size() - used_stack_size + - 2 * get_guard_page_size() - get_guard_stack_size(); + return get_restore_stack_size() < available_stack_size; +} + void remove_guard_stack() { int err; char* stack_addr = (char*) get_stack_addr(); diff --git a/vm/vmcore/src/util/linux/signals_ipf.cpp b/vm/vmcore/src/util/linux/signals_ipf.cpp index 642501d..6852094 100644 --- a/vm/vmcore/src/util/linux/signals_ipf.cpp +++ b/vm/vmcore/src/util/linux/signals_ipf.cpp @@ -104,6 +104,13 @@ void linux_regs_to_ucontext(ucontext_t* uc, Registers* regs) } +void asm_exception_catch_callback() { + // FIXME: not implemented + fprintf(stderr, "FIXME: asm_jvmti_exception_catch_callback: not implemented\n"); + assert(0); + abort(); +} + void asm_jvmti_exception_catch_callback() { // FIXME: not implemented fprintf(stderr, "FIXME: asm_jvmti_exception_catch_callback: not implemented\n"); @@ -301,7 +308,7 @@ size_t get_available_stack_size() { 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(); + - 2 * get_guard_page_size() - get_guard_stack_size(); return available_stack_size; } @@ -319,6 +326,20 @@ bool check_available_stack_size(size_t required_size) { } } +size_t get_restore_stack_size() { + return 0x8000; +} + +bool check_stack_size_enough_for_exception_catch(void* sp) { + char* stack_adrr = (char*) get_stack_addr(); + size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp); + size_t available_stack_size = + get_stack_size() - used_stack_size + - 2 * get_guard_page_size() - get_guard_stack_size(); + return get_restore_stack_size() < available_stack_size; +} + + void remove_guard_stack() { int err; char* stack_addr = (char*) get_stack_addr(); diff --git a/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp b/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp index 313ea14..e6812e4 100644 --- a/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp +++ b/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp @@ -179,7 +179,7 @@ size_t get_available_stack_size() { 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(); + - 2 * get_guard_page_size() - get_guard_stack_size(); return available_stack_size; } size_t get_default_stack_size() { @@ -196,6 +196,20 @@ bool check_available_stack_size(size_t required_size) { } } +size_t get_restore_stack_size() { + return 0x8000; +} + +bool check_stack_size_enough_for_exception_catch(void* sp) { + char* stack_adrr = (char*) get_stack_addr(); + size_t used_stack_size = ((size_t)stack_adrr) - ((size_t)sp); + size_t available_stack_size = + get_stack_size() - used_stack_size + - 2 * get_guard_page_size() - get_guard_stack_size(); + return get_restore_stack_size() < available_stack_size; +} + + // exception catch callback to restore stack after Stack Overflow Error void __cdecl exception_catch_callback_wrapper(){ exception_catch_callback(); diff --git a/vm/vmcore/src/util/win/include/exception_filter.h b/vm/vmcore/src/util/win/include/exception_filter.h index bc729f4..31ccc31 100644 --- a/vm/vmcore/src/util/win/include/exception_filter.h +++ b/vm/vmcore/src/util/win/include/exception_filter.h @@ -45,7 +45,7 @@ void __cdecl exception_catch_callback_wrapper(); // exception catch support for JVMTI void __cdecl jvmti_exception_catch_callback_wrapper(); // Assembler wrappers; are used to restore registers -void asm_exception_catch_callback(); +//void asm_exception_catch_callback(); // Declared in exceptions_jit.h //void asm_jvmti_exception_catch_callback(); // Declared in exceptions_jit.h #ifdef __cplusplus