From 8a2cc2fa20eea6ecf73d440151e5e06cca34cc79 Mon Sep 17 00:00:00 2001 From: Pavel Afremov Date: Tue, 10 Jul 2007 16:21:59 +0400 Subject: [PATCH] Size of the stack required for guard page setting was tuned. Also several bugs was fixed to enable SOE support in stress environment and on Linux x86-64 platform. --- .../excludes/exclude.drlvm_smoke.linux.x86_64.jet | 5 - .../excludes/exclude.drlvm_smoke.linux.x86_64.jit | 5 - .../excludes/exclude.drlvm_smoke.linux.x86_64.opt | 5 - .../excludes/exclude.drlvm_smoke.linux.x86_64.srv | 5 - .../src/codegenerator/ia32/Ia32StackInfo.cpp | 99 ++++++++++--------- vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp | 3 +- vm/vmcore/include/exceptions.h | 1 + vm/vmcore/src/exception/exceptions_jit.cpp | 7 +- vm/vmcore/src/jit/compile.cpp | 4 +- vm/vmcore/src/util/linux/signals_em64t.cpp | 87 +++++++++++++++-- vm/vmcore/src/util/linux/signals_ia32.cpp | 32 +++++-- vm/vmcore/src/util/linux/signals_ipf.cpp | 32 +++++-- .../win/ia32_em64t/nt_exception_filter_common.cpp | 38 +++++++- 13 files changed, 221 insertions(+), 102 deletions(-) diff --git a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jet b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jet index 96ea6e1..43b09ec 100644 --- a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jet +++ b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jet @@ -6,11 +6,6 @@ gc/LOS.java gc/MultiThreads.java perf/MultiThreadsSimple.java -# HARMONY-2972 -StackTest.java -exception/FinalizeStackTest.java -stress/Stack.java - # fails on Ubuntu6 x86_64 gc/Mark.java diff --git a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jit b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jit index 96ea6e1..43b09ec 100644 --- a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jit +++ b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.jit @@ -6,11 +6,6 @@ gc/LOS.java gc/MultiThreads.java perf/MultiThreadsSimple.java -# HARMONY-2972 -StackTest.java -exception/FinalizeStackTest.java -stress/Stack.java - # fails on Ubuntu6 x86_64 gc/Mark.java diff --git a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.opt b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.opt index 316f19f..439b0a5 100644 --- a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.opt +++ b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.opt @@ -6,11 +6,6 @@ gc/LOS.java gc/MultiThreads.java perf/MultiThreadsSimple.java -# HARMONY-2972 -StackTest.java -exception/FinalizeStackTest.java -stress/Stack.java - # fails on Ubuntu6 x86_64 gc/Mark.java diff --git a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.srv b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.srv index 316f19f..439b0a5 100644 --- a/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.srv +++ b/build/make/excludes/exclude.drlvm_smoke.linux.x86_64.srv @@ -6,11 +6,6 @@ gc/LOS.java gc/MultiThreads.java perf/MultiThreadsSimple.java -# HARMONY-2972 -StackTest.java -exception/FinalizeStackTest.java -stress/Stack.java - # fails on Ubuntu6 x86_64 gc/Mark.java diff --git a/vm/jitrino/src/codegenerator/ia32/Ia32StackInfo.cpp b/vm/jitrino/src/codegenerator/ia32/Ia32StackInfo.cpp index e24b3e7..b4bba4f 100644 --- a/vm/jitrino/src/codegenerator/ia32/Ia32StackInfo.cpp +++ b/vm/jitrino/src/codegenerator/ia32/Ia32StackInfo.cpp @@ -213,43 +213,46 @@ void StackInfo::unwind(MethodDesc* pMethodDesc, JitFrameContext* context, bool i <<::std::endl; } - assert(!(context->rsp & 15)); context->rsp += stackDepth; + assert((context->rsp & 0xf) == 0x8); POINTER_SIZE_INT offset = context->rsp; context->p_rip = (POINTER_SIZE_INT *) (offset); - offset += icalleeOffset; - if(getRegMask(RegName_R15) & icalleeMask) { - context->p_r15 = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_R14) & icalleeMask) { - context->p_r14 = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_R13) & icalleeMask) { - context->p_r13 = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_R12) & icalleeMask) { - context->p_r12 = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_RDI) & icalleeMask) { - context->p_rdi = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_RSI) & icalleeMask) { - context->p_rsi = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_RBP) & icalleeMask) { - context->p_rbp = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_RBX) & icalleeMask) { - context->p_rbx = (POINTER_SIZE_INT *) offset; + offset += icalleeOffset; + + if(stackDepth != 0) { + if(getRegMask(RegName_R15) & icalleeMask) { + context->p_r15 = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_R14) & icalleeMask) { + context->p_r14 = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_R13) & icalleeMask) { + context->p_r13 = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_R12) & icalleeMask) { + context->p_r12 = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_RDI) & icalleeMask) { + context->p_rdi = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_RSI) & icalleeMask) { + context->p_rsi = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_RBP) & icalleeMask) { + context->p_rbp = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_RBX) & icalleeMask) { + context->p_rbx = (POINTER_SIZE_INT *) offset; + } } context->rsp += offset_step; //IP register size #else @@ -265,21 +268,23 @@ void StackInfo::unwind(MethodDesc* pMethodDesc, JitFrameContext* context, bool i uint32 offset = context->esp; context->p_eip = (POINTER_SIZE_INT *) offset; - offset += icalleeOffset; - if(getRegMask(RegName_EDI) & icalleeMask) { - context->p_edi = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_ESI) & icalleeMask) { - context->p_esi = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_EBP) & icalleeMask) { - context->p_ebp = (POINTER_SIZE_INT *) offset; - offset += offset_step; - } - if(getRegMask(RegName_EBX) & icalleeMask) { - context->p_ebx = (POINTER_SIZE_INT *) offset; + offset += icalleeOffset; + if(stackDepth != 0) { + if(getRegMask(RegName_EDI) & icalleeMask) { + context->p_edi = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_ESI) & icalleeMask) { + context->p_esi = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_EBP) & icalleeMask) { + context->p_ebp = (POINTER_SIZE_INT *) offset; + offset += offset_step; + } + if(getRegMask(RegName_EBX) & icalleeMask) { + context->p_ebx = (POINTER_SIZE_INT *) offset; + } } context->esp += offset_step; //IP register size #endif 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 b77558a..ea85581 100644 --- a/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp +++ b/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp @@ -496,7 +496,8 @@ void si_copy_to_registers(StackIterator * si, Registers * regs) { } void si_set_callback(StackIterator* si, NativeCodePtr* callback) { - si->jit_frame_context.rsp = si->jit_frame_context.rsp - 4; + const static uint64 red_zone_size = 0x80; + si->jit_frame_context.rsp = si->jit_frame_context.rsp - red_zone_size - sizeof(void*); *((uint64*) si->jit_frame_context.rsp) = *(si->jit_frame_context.p_rip); si->jit_frame_context.p_rip = ((uint64*)callback); } diff --git a/vm/vmcore/include/exceptions.h b/vm/vmcore/include/exceptions.h index 190f113..4aebcd7 100644 --- a/vm/vmcore/include/exceptions.h +++ b/vm/vmcore/include/exceptions.h @@ -270,6 +270,7 @@ void exn_rethrow(); void exn_rethrow_if_pending(); void set_guard_stack(); +void remove_guard_stack(); void init_stack_info(); #ifndef WIN32 void remove_guard_stack(); diff --git a/vm/vmcore/src/exception/exceptions_jit.cpp b/vm/vmcore/src/exception/exceptions_jit.cpp index e58fea3..dda5a1d 100644 --- a/vm/vmcore/src/exception/exceptions_jit.cpp +++ b/vm/vmcore/src/exception/exceptions_jit.cpp @@ -158,7 +158,12 @@ static ManagedObject *create_lazy_exception( tmn_suspend_enable(); jthrowable exc_object = create_exception( (Class*) exn_class, (Method*) exn_constr, vm_exn_constr_args); - result = exc_object->object; + + if (exc_object) { + result = exc_object->object; + } else { + result = NULL; + } tmn_suspend_disable(); } set_unwindable(unwindable); diff --git a/vm/vmcore/src/jit/compile.cpp b/vm/vmcore/src/jit/compile.cpp index b6775e3..b9e6279 100644 --- a/vm/vmcore/src/jit/compile.cpp +++ b/vm/vmcore/src/jit/compile.cpp @@ -747,11 +747,9 @@ static JIT_Result compile_do_compilation(Method* method) } else if (method->get_state()==Method::ST_NotCompiled && exn_raised()) { method->unlock(); return JIT_FAILURE; -#ifndef _EM64T_ - } else if(!check_available_stack_size(get_default_stack_size()/100)) { + } else if(!check_available_stack_size(0x4000)) { method->unlock(); return JIT_FAILURE; -#endif } if (method->is_native()) { diff --git a/vm/vmcore/src/util/linux/signals_em64t.cpp b/vm/vmcore/src/util/linux/signals_em64t.cpp index 06f34e5..e77aafd 100644 --- a/vm/vmcore/src/util/linux/signals_em64t.cpp +++ b/vm/vmcore/src/util/linux/signals_em64t.cpp @@ -137,6 +137,21 @@ void asm_exception_catch_callback() { : /* no output operands */ : /* no input operands */ ); +#ifdef _DEBUG + asm ( + "movq %%rbp, %%rsp\n" + "popq %%rbp\n" + "retq $0x80;\n" + : /* no output operands */ + : /* no input operands */ + ); +#else // _DEBUG + asm ( + "retq $0x80;\n" + : /* no output operands */ + : /* no input operands */ + ); +#endif // ! _DEBUG} } // exception catch support for JVMTI @@ -291,11 +306,42 @@ inline size_t get_guard_page_size() { void set_guard_stack(); void init_stack_info() { - p_TLS_vmthread->stack_addr = find_stack_addr(); - p_TLS_vmthread->stack_size = hythread_get_thread_stacksize(hythread_self()); + char* stack_addr = (char *)find_stack_addr(); + unsigned int stack_size = hythread_get_thread_stacksize(hythread_self()); + p_TLS_vmthread->stack_addr = stack_addr; + p_TLS_vmthread->stack_size = stack_size; common_guard_stack_size = find_guard_stack_size(); common_guard_page_size =find_guard_page_size(); + // stack should be mapped so it's result of future mapping + char* res; + + // begin of the stack can be protected by OS, but this part already mapped + // found address of current stack page + char* current_page_addr = + (char*)(((size_t)&res) & (~(common_guard_page_size-1))); + + // leave place for mmap work + char* mapping_page_addr = current_page_addr - common_guard_page_size; + + // makes sure that stack allocated till mapping_page_addr + //stack_holder(mapping_page_addr); + + // found size of the stack area which should be maped + size_t stack_mapping_size = (size_t)mapping_page_addr + - (size_t)stack_addr + stack_size; + + // maps unmapped part of the stack + res = (char*) mmap(stack_addr - stack_size, + stack_mapping_size, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, + -1, + 0); + // stack should be mapped, checks result + assert(res == (stack_addr - stack_size)); + + // set guard page set_guard_stack(); } @@ -306,6 +352,9 @@ void set_guard_stack() { size_t guard_stack_size = get_guard_stack_size(); size_t guard_page_size = get_guard_page_size(); + assert(((size_t)(&stack_addr)) > ((size_t)((char*)stack_addr - stack_size + + guard_stack_size + 2 * guard_page_size))); + err = mprotect(stack_addr - stack_size + guard_page_size + guard_stack_size, guard_page_size, PROT_NONE); @@ -320,16 +369,31 @@ void set_guard_stack() { } 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 + char* stack_addr = (char*) get_stack_addr(); + size_t used_stack_size = stack_addr - ((char*)&stack_addr); + int available_stack_size; + + if (((char*)&stack_addr) > (stack_addr - get_stack_size() + get_guard_page_size() + get_guard_stack_size())) { + available_stack_size = get_stack_size() - used_stack_size - 2 * get_guard_page_size() - get_guard_stack_size(); - return available_stack_size; + } else { + available_stack_size = get_stack_size() - used_stack_size - get_guard_page_size(); + } + + if (available_stack_size > 0) { + return (size_t) available_stack_size; + } else { + return 0; + } } bool check_available_stack_size(size_t required_size) { - if (get_available_stack_size() < required_size) { + size_t available_stack_size = get_available_stack_size(); + + if (available_stack_size < required_size) { + if (available_stack_size < get_guard_stack_size()) { + remove_guard_stack(); + } Global_Env *env = VM_Global_State::loader_env; exn_raise_by_class(env->java_lang_StackOverflowError_Class); return false; @@ -339,7 +403,7 @@ bool check_available_stack_size(size_t required_size) { } size_t get_restore_stack_size() { - return 0x8000; + return 0x0800; } bool check_stack_size_enough_for_exception_catch(void* sp) { @@ -379,6 +443,10 @@ bool check_stack_overflow(siginfo_t *info, ucontext_t *uc) { char* guard_page_begin = stack_addr - stack_size + guard_page_size + guard_stack_size; char* guard_page_end = guard_page_begin + guard_page_size; + + // FIXME: Workaround for main thread + guard_page_end += guard_page_size; + char* fault_addr = (char*)(info->si_addr); //char* esp_value = (char*)(uc->uc_mcontext.gregs[REG_ESP]); @@ -410,7 +478,6 @@ void stack_overflow_handler(int signum, siginfo_t* UNREF info, void* context) } else { remove_guard_stack(); exn_raise_by_class(env->java_lang_StackOverflowError_Class); - p_TLS_vmthread->restore_guard_page = true; } } } diff --git a/vm/vmcore/src/util/linux/signals_ia32.cpp b/vm/vmcore/src/util/linux/signals_ia32.cpp index a1351ca..7de3d87 100644 --- a/vm/vmcore/src/util/linux/signals_ia32.cpp +++ b/vm/vmcore/src/util/linux/signals_ia32.cpp @@ -391,6 +391,9 @@ void set_guard_stack() { size_t guard_stack_size = get_guard_stack_size(); size_t guard_page_size = get_guard_page_size(); + assert(((size_t)(&stack_addr)) > ((size_t)((char*)stack_addr - stack_size + + guard_stack_size + 2 * guard_page_size))); + err = mprotect(stack_addr - stack_size + guard_page_size + guard_stack_size, guard_page_size, PROT_NONE ); @@ -409,19 +412,34 @@ void set_guard_stack() { } 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 + char* stack_addr = (char*) get_stack_addr(); + size_t used_stack_size = stack_addr - ((char*)&stack_addr); + int available_stack_size; + + if (((char*)&stack_addr) > (stack_addr - get_stack_size() + get_guard_page_size() + get_guard_stack_size())) { + available_stack_size = get_stack_size() - used_stack_size - 2 * get_guard_page_size() - get_guard_stack_size(); - return available_stack_size; + } else { + available_stack_size = get_stack_size() - used_stack_size - get_guard_page_size(); + } + + if (available_stack_size > 0) { + return (size_t) available_stack_size; + } else { + return 0; + } } size_t get_default_stack_size() { size_t default_stack_size = get_stack_size(); return default_stack_size; } bool check_available_stack_size(size_t required_size) { - if (get_available_stack_size() < required_size) { + size_t available_stack_size = get_available_stack_size(); + + if (available_stack_size < required_size) { + if (available_stack_size < get_guard_stack_size()) { + remove_guard_stack(); + } Global_Env *env = VM_Global_State::loader_env; exn_raise_by_class(env->java_lang_StackOverflowError_Class); return false; @@ -431,7 +449,7 @@ bool check_available_stack_size(size_t required_size) { } size_t get_restore_stack_size() { - return 0x8000; + return 0x0200; } bool check_stack_size_enough_for_exception_catch(void* sp) { diff --git a/vm/vmcore/src/util/linux/signals_ipf.cpp b/vm/vmcore/src/util/linux/signals_ipf.cpp index 6852094..b86c5b5 100644 --- a/vm/vmcore/src/util/linux/signals_ipf.cpp +++ b/vm/vmcore/src/util/linux/signals_ipf.cpp @@ -273,6 +273,9 @@ void set_guard_stack() { size_t guard_stack_size = get_guard_stack_size(); size_t guard_page_size = get_guard_page_size(); + assert(((size_t)(&stack_addr)) > ((size_t)((char*)stack_addr - stack_size + + guard_stack_size + 2 * guard_page_size))); + // map the guard page and protect it void UNUSED *res = mmap(stack_addr - stack_size + guard_page_size + guard_stack_size, guard_page_size, PROT_READ | PROT_WRITE, @@ -304,12 +307,22 @@ void set_guard_stack() { } 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 + char* stack_addr = (char*) get_stack_addr(); + size_t used_stack_size = stack_addr - ((char*)&stack_addr); + int available_stack_size; + + if (((char*)&stack_addr) > (stack_addr - get_stack_size() + get_guard_page_size() + get_guard_stack_size())) { + available_stack_size = get_stack_size() - used_stack_size - 2 * get_guard_page_size() - get_guard_stack_size(); - return available_stack_size; + } else { + available_stack_size = get_stack_size() - used_stack_size - get_guard_page_size(); + } + + if (available_stack_size > 0) { + return (size_t) available_stack_size; + } else { + return 0; + } } size_t get_default_stack_size() { @@ -318,7 +331,12 @@ size_t get_default_stack_size() { } bool check_available_stack_size(size_t required_size) { - if (get_available_stack_size() < required_size) { + size_t available_stack_size = get_available_stack_size(); + + if (available_stack_size < required_size) { + if (available_stack_size < get_guard_stack_size()) { + remove_guard_stack(); + } exn_raise_by_name("java/lang/StackOverflowError"); return false; } else { @@ -327,7 +345,7 @@ bool check_available_stack_size(size_t required_size) { } size_t get_restore_stack_size() { - return 0x8000; + return 0x0200; } bool check_stack_size_enough_for_exception_catch(void* sp) { 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 e6812e4..e6c930f 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 @@ -156,6 +156,7 @@ 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(); + assert(((size_t)(&stack_addr)) > ((size_t)((char*)stack_addr - stack_size + 3 * page_size))); if (!VirtualFree((char*)stack_addr - stack_size + page_size, page_size, MEM_DECOMMIT)) { @@ -174,20 +175,45 @@ void set_guard_stack() { p_TLS_vmthread->restore_guard_page = false; } +void remove_guard_stack() { + void* stack_addr = get_stack_addr(); + size_t stack_size = get_stack_size(); + size_t page_size = get_guard_page_size(); + DWORD oldProtect; + + assert(((size_t)(&stack_addr)) > ((size_t)((char*)stack_addr - stack_size + 3 * page_size))); + p_TLS_vmthread->restore_guard_page = true; + + if (!VirtualProtect((char*)stack_addr - stack_size + page_size + page_size, + page_size, PAGE_READWRITE, &oldProtect)) { + // should be successful always + assert(0); + } +} + 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 = + char* stack_addr = (char*) get_stack_addr(); + size_t used_stack_size = ((size_t)stack_addr) - ((size_t)(&stack_addr)); + int available_stack_size = get_stack_size() - used_stack_size - 2 * get_guard_page_size() - get_guard_stack_size(); - return available_stack_size; + + if (available_stack_size > 0) { + return (size_t) available_stack_size; + } else { + return 0; + } } size_t get_default_stack_size() { size_t default_stack_size = get_stack_size(); return default_stack_size; } bool check_available_stack_size(size_t required_size) { - if (get_available_stack_size() < required_size) { + size_t available_stack_size = get_available_stack_size(); + if (available_stack_size < required_size) { + if (available_stack_size < get_guard_stack_size()) { + remove_guard_stack(); + } Global_Env *env = VM_Global_State::loader_env; exn_raise_by_class(env->java_lang_StackOverflowError_Class); return false; @@ -197,7 +223,7 @@ bool check_available_stack_size(size_t required_size) { } size_t get_restore_stack_size() { - return 0x8000; + return 0x0100; } bool check_stack_size_enough_for_exception_catch(void* sp) { -- 1.5.0.3