From b798a3002bf64e89ccfdb2911ba4b7a4491721b5 Mon Sep 17 00:00:00 2001 From: Pavel Afremov Date: Mon, 16 Jul 2007 16:30:18 +0400 Subject: [PATCH] Fix SOE support on Windows x86-64. Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit On Windows x86-64.DRL VM can't process SOE, because one page on the stack is not enough to create exception. But on Windows x86-64 there is function SetThreadStackGuarantee, which allow increase size of guard stack. Unfortunately this function doesn’t work on Windows x86-32 now. Current patch enable use of this function on x86-64 platform. Also it fix asm_helpers for exception callback functions, compile_me function checks, and si_set_callback. --- .../exclude.drlvm_smoke.windows.x86_64.jet | 4 -- .../exclude.drlvm_smoke.windows.x86_64.jit | 5 -- .../exclude.drlvm_smoke.windows.x86_64.opt | 5 -- .../exclude.drlvm_smoke.windows.x86_64.srv | 5 -- vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp | 4 ++ vm/vmcore/src/jit/compile.cpp | 2 +- vm/vmcore/src/util/em64t/base/ini_em64t.cpp | 5 ++- .../src/util/win/em64t/exception_handlers.asm | 56 ++++++++++++++++++-- .../win/ia32_em64t/nt_exception_filter_common.cpp | 47 ++++++++++++---- 9 files changed, 96 insertions(+), 37 deletions(-) diff --git a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jet b/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jet index 684eebe..b4af579 100644 --- a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jet +++ b/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jet @@ -1,10 +1,6 @@ Check.java PerfCheck.java -# HARMONY-2972 -StackTest.java -stress/Stack.java - # HARMONY-2977 io/Integers.java diff --git a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jit b/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jit index ef177fc..f9a9c1e 100644 --- a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.jit +++ b/build/make/excludes/exclude.drlvm_smoke.windows.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 - # HARMONY-2977 io/Integers.java diff --git a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.opt b/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.opt index d5f9a48..19629f7 100644 --- a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.opt +++ b/build/make/excludes/exclude.drlvm_smoke.windows.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 - # HARMONY-3917 gc/PhantomReferenceTest.java gc/WeakReferenceTest.java diff --git a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.srv b/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.srv index 9a12e48..184ad9b 100644 --- a/build/make/excludes/exclude.drlvm_smoke.windows.x86_64.srv +++ b/build/make/excludes/exclude.drlvm_smoke.windows.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 - # Server mode failures specific to Windows x86_64 stress/Mix.java 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 ea85581..f1ab066 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,11 @@ void si_copy_to_registers(StackIterator * si, Registers * regs) { } void si_set_callback(StackIterator* si, NativeCodePtr* callback) { +#ifdef WIN32 + const static uint64 red_zone_size = 0x00; +#else const static uint64 red_zone_size = 0x80; +#endif 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/src/jit/compile.cpp b/vm/vmcore/src/jit/compile.cpp index b9e6279..0aac41a 100644 --- a/vm/vmcore/src/jit/compile.cpp +++ b/vm/vmcore/src/jit/compile.cpp @@ -747,7 +747,7 @@ static JIT_Result compile_do_compilation(Method* method) } else if (method->get_state()==Method::ST_NotCompiled && exn_raised()) { method->unlock(); return JIT_FAILURE; - } else if(!check_available_stack_size(0x4000)) { + } else if(!check_available_stack_size(0x8000)) { method->unlock(); return JIT_FAILURE; } diff --git a/vm/vmcore/src/util/em64t/base/ini_em64t.cpp b/vm/vmcore/src/util/em64t/base/ini_em64t.cpp index 09ab4dd..5e456a0 100644 --- a/vm/vmcore/src/util/em64t/base/ini_em64t.cpp +++ b/vm/vmcore/src/util/em64t/base/ini_em64t.cpp @@ -111,13 +111,16 @@ static invoke_managed_func_int_t gen_invoke_managed_func() { stub = push(stub, rbp_opnd); stub = mov(stub, rbp_opnd, rsp_opnd); + // align stack pointer if required (rsp % 16 == 0) + stub = alu(stub, and_opc, rsp_opnd, Imm_Opnd(0xfffffff0)); + // 1) move stacked arguments in reverse (right-to-left) order stub = mov(stub, rcx_opnd, M_Base_Opnd(rbp_reg, STACK_NARGS_OFFSET)); stub = alu(stub, or_opc, rcx_opnd, rcx_opnd); stub = branch8(stub, Condition_Z, Imm_Opnd(size_8, 0)); labels.add_patch_to_label(MOVE_STACK_ARGS_END, stub - 1, LPT_Rel8); - // align stack if required (rsp % 16 == 0) + // align stack arguments if required (rsp % 16 == 0) stub = test(stub, rcx_opnd, Imm_Opnd(size_32, 1)); stub = branch8(stub, Condition_Z, Imm_Opnd(size_8, 0)); labels.add_patch_to_label(COMPUTE_ADDRESS, stub - 1, LPT_Rel8); diff --git a/vm/vmcore/src/util/win/em64t/exception_handlers.asm b/vm/vmcore/src/util/win/em64t/exception_handlers.asm index 6a22223..292267f 100644 --- a/vm/vmcore/src/util/win/em64t/exception_handlers.asm +++ b/vm/vmcore/src/util/win/em64t/exception_handlers.asm @@ -25,7 +25,7 @@ vectored_exception_handler PROC cld sub rsp, 32 ; allocate stack for 4 registers call vectored_exception_handler_internal - add esp, 32 + add rsp, 32 popfq ret @@ -44,9 +44,25 @@ asm_c_exception_handler PROC pushfq cld + push rax + push rbx + push rcx + push rdx + push r8 + push r9 + push r10 + push r11 sub rsp, 32 ; allocate stack for 4 registers call c_exception_handler - add esp, 32 + add rsp, 32 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdx + pop rcx + pop rbx + pop rax popfq ret @@ -64,9 +80,25 @@ asm_exception_catch_callback PROC pushfq cld + push rax + push rbx + push rcx + push rdx + push r8 + push r9 + push r10 + push r11 sub rsp, 32 ; allocate stack for 4 registers call exception_catch_callback_wrapper - add esp, 32 + add rsp, 32 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdx + pop rcx + pop rbx + pop rax popfq ret @@ -84,9 +116,25 @@ asm_jvmti_exception_catch_callback PROC pushfq cld + push rax + push rbx + push rcx + push rdx + push r8 + push r9 + push r10 + push r11 sub rsp, 32 ; allocate stack for 4 registers call jvmti_exception_catch_callback_wrapper - add esp, 32 + add rsp, 32 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdx + pop rcx + pop rbx + pop rax popfq ret 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 e6c930f..d0f23e6 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 @@ -121,8 +121,13 @@ inline size_t find_guard_page_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(); +# ifdef _EM64T_ + //this code in future should be used on both platforms x86-32 and x86-64 + return 64*1024; +# else + // guaerded stack size on windows 32 can be equals one page size only :( + return find_guard_page_size(); +# endif } static size_t common_guard_stack_size; @@ -150,13 +155,26 @@ void init_stack_info() { p_TLS_vmthread->stack_size = hythread_get_thread_stacksize(hythread_self()); common_guard_stack_size = find_guard_stack_size(); common_guard_page_size = find_guard_page_size(); + + + //this code in future should be used on both platforms x86-32 and x86-64 +# ifdef _EM64T_ + ULONG guard_stack_size_param = common_guard_stack_size; + + if (!SetThreadStackGuarantee(&guard_stack_size_param)) { + // should be successful always + assert(0); + } +# endif } 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))); + size_t guard_stack_size = get_guard_stack_size(); + + assert(((size_t)(&stack_addr)) > ((size_t)((char*)stack_addr - stack_size + 2 * page_size + guard_stack_size))); if (!VirtualFree((char*)stack_addr - stack_size + page_size, page_size, MEM_DECOMMIT)) { @@ -164,14 +182,13 @@ void set_guard_stack() { assert(0); } - DWORD oldProtect; - - if (!VirtualProtect((char*)stack_addr - stack_size + page_size + page_size, - page_size, PAGE_GUARD | PAGE_READWRITE, &oldProtect)) { + //if (!VirtualProtect((char*)stack_addr - stack_size + page_size + page_size, + // page_size, PAGE_GUARD | PAGE_READWRITE, &oldProtect)) { + if (!VirtualAlloc( (char*)stack_addr - stack_size + page_size + guard_stack_size, + page_size, MEM_COMMIT, PAGE_GUARD | PAGE_READWRITE)) { // should be successful always assert(0); } - p_TLS_vmthread->restore_guard_page = false; } @@ -179,12 +196,13 @@ 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(); + size_t guard_stack_size = get_guard_stack_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, + if (!VirtualProtect((char*)stack_addr - stack_size + page_size + guard_stack_size, page_size, PAGE_READWRITE, &oldProtect)) { // should be successful always assert(0); @@ -194,9 +212,14 @@ void remove_guard_stack() { size_t get_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 + int available_stack_size; + + if (!p_TLS_vmthread->restore_guard_page) { + available_stack_size = get_stack_size() - used_stack_size - 2 * get_guard_page_size() - get_guard_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; @@ -223,7 +246,7 @@ bool check_available_stack_size(size_t required_size) { } size_t get_restore_stack_size() { - return 0x0100; + return 0x0200; } bool check_stack_size_enough_for_exception_catch(void* sp) { -- 1.5.0.3