Projects
openEuler:24.03:SP1:Everything
openjdk-1.8.0
_service:tar_scm:0026-8072070-Improve-interpret...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0026-8072070-Improve-interpreter-stack-banging.patch of Package openjdk-1.8.0
Date: Thu, 8 Jun 2023 20:43:33 +0800 Subject: 8072070: Improve interpreter stack banging Bug url: https://bugs.openjdk.org/browse/JDK-8072070 --- .../vm/templateInterpreter_aarch64.cpp | 49 +++++++++++--- .../cpu/ppc/vm/templateInterpreter_ppc.cpp | 20 ++++++ .../sparc/vm/templateInterpreter_sparc.cpp | 22 +++++++ .../cpu/x86/vm/templateInterpreter_x86.cpp | 64 +++++++++++++++++++ .../src/share/vm/interpreter/interpreter.cpp | 25 +------- hotspot/src/share/vm/runtime/os.cpp | 7 +- hotspot/src/share/vm/runtime/thread.cpp | 4 +- hotspot/src/share/vm/runtime/thread.hpp | 20 ++++++ 8 files changed, 174 insertions(+), 37 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp index f356fbf81..a5a91e5f3 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp @@ -1087,17 +1087,46 @@ address InterpreterGenerator::generate_Dgemv_dgemv_entry() { } void InterpreterGenerator::bang_stack_shadow_pages(bool native_call) { - // Bang each page in the shadow zone. We can't assume it's been done for - // an interpreter frame with greater than a page of locals, so each page - // needs to be checked. Only true for non-native. - if (UseStackBanging) { - const int start_page = native_call ? StackShadowPages : 1; - const int page_size = os::vm_page_size(); - for (int pages = start_page; pages <= StackShadowPages ; pages++) { - __ sub(rscratch2, sp, pages*page_size); - __ str(zr, Address(rscratch2)); - } + // See more discussion in stackOverflow.hpp. + + const int shadow_zone_size = (int)(JavaThread::stack_shadow_zone_size()); + const int page_size = os::vm_page_size(); + const int n_shadow_pages = shadow_zone_size / page_size; + +#ifdef ASSERT + Label L_good_limit; + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_safe_limit_offset())); + __ cbnz(rscratch1, L_good_limit); + __ stop("shadow zone safe limit is not initialized"); + __ bind(L_good_limit); + + Label L_good_watermark; + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_growth_watermark_offset())); + __ cbnz(rscratch1, L_good_watermark); + __ stop("shadow zone growth watermark is not initialized"); + __ bind(L_good_watermark); +#endif + + Label L_done; + + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_growth_watermark_offset())); + __ cmp(sp, rscratch1); + __ br(Assembler::HI, L_done); + + for (int p = 1; p <= n_shadow_pages; p++) { + __ sub(rscratch2, sp, p*page_size); + __ str(zr, Address(rscratch2)); } + + // Record the new watermark, but only if the update is above the safe limit. + // Otherwise, the next time around the check above would pass the safe limit. + __ ldr(rscratch1, Address(rthread, JavaThread::shadow_zone_safe_limit_offset())); + __ cmp(sp, rscratch1); + __ br(Assembler::LS, L_done); + __ mov(rscratch1, sp); + __ str(rscratch1, Address(rthread, JavaThread::shadow_zone_growth_watermark_offset())); + + __ bind(L_done); } diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp index 42dd8f2a9..0fb934166 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp @@ -2030,5 +2030,25 @@ void TemplateInterpreterGenerator::stop_interpreter_at() { __ bind(L); } +void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { + // Quick & dirty stack overflow checking: bang the stack & handle trap. + // Note that we do the banging after the frame is setup, since the exception + // handling code expects to find a valid interpreter frame on the stack. + // Doing the banging earlier fails if the caller frame is not an interpreter + // frame. + // (Also, the exception throwing code expects to unlock any synchronized + // method receiever, so do the banging after locking the receiver.) + + // Bang each page in the shadow zone. We can't assume it's been done for + // an interpreter frame with greater than a page of locals, so each page + // needs to be checked. Only true for non-native. + if (UseStackBanging) { + const int start_page = native_call ? StackShadowPages : 1; + const int page_size = os::vm_page_size(); + for (int pages = start_page; pages <= StackShadowPages ; pages++) { + __ bang_stack_with_offset(pages*page_size); + } + } +} #endif // !PRODUCT #endif // !CC_INTERP diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index 83d40496c..540f9b287 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -2113,5 +2113,27 @@ void TemplateInterpreterGenerator::stop_interpreter_at() { __ cmp(G3_scratch, G4_scratch); __ breakpoint_trap(Assembler::equal, Assembler::icc); } + +void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { + // Quick & dirty stack overflow checking: bang the stack & handle trap. + // Note that we do the banging after the frame is setup, since the exception + // handling code expects to find a valid interpreter frame on the stack. + // Doing the banging earlier fails if the caller frame is not an interpreter + // frame. + // (Also, the exception throwing code expects to unlock any synchronized + // method receiever, so do the banging after locking the receiver.) + + // Bang each page in the shadow zone. We can't assume it's been done for + // an interpreter frame with greater than a page of locals, so each page + // needs to be checked. Only true for non-native. + if (UseStackBanging) { + const int start_page = native_call ? StackShadowPages : 1; + const int page_size = os::vm_page_size(); + for (int pages = start_page; pages <= StackShadowPages ; pages++) { + __ bang_stack_with_offset(pages*page_size); + } + } +} + #endif // not PRODUCT #endif // !CC_INTERP diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp index e470aa62d..fda2908c3 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp @@ -29,6 +29,8 @@ #ifndef CC_INTERP +# define __ _masm-> + // asm based interpreter deoptimization helpers int AbstractInterpreter::size_activation(int max_stack, int temps, @@ -121,4 +123,66 @@ void AbstractInterpreter::layout_activation(Method* method, method->constants()->cache(); } +void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { + // See more discussion in stackOverflow.hpp. + + // Note that we do the banging after the frame is setup, since the exception + // handling code expects to find a valid interpreter frame on the stack. + // Doing the banging earlier fails if the caller frame is not an interpreter + // frame. + // (Also, the exception throwing code expects to unlock any synchronized + // method receiver, so do the banging after locking the receiver.) + + const int shadow_zone_size = (int)(JavaThread::stack_shadow_zone_size()); + const int page_size = os::vm_page_size(); + const int n_shadow_pages = shadow_zone_size / page_size; + + const Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread); + #ifndef _LP64 + __ push(thread); + __ get_thread(thread); +#endif + +#ifdef ASSERT + Label L_good_limit; + __ cmpptr(Address(thread, JavaThread::shadow_zone_safe_limit_offset()), (int32_t)NULL_WORD); + __ jcc(Assembler::notEqual, L_good_limit); + __ stop("shadow zone safe limit is not initialized"); + __ bind(L_good_limit); + + Label L_good_watermark; + __ cmpptr(Address(thread, JavaThread::shadow_zone_growth_watermark_offset()), (int32_t)NULL_WORD); + __ jcc(Assembler::notEqual, L_good_watermark); + __ stop("shadow zone growth watermark is not initialized"); + __ bind(L_good_watermark); +#endif + + Label L_done; + + __ cmpptr(rsp, Address(thread, JavaThread::shadow_zone_growth_watermark_offset())); + __ jcc(Assembler::above, L_done); + + for (int p = 1; p <= n_shadow_pages; p++) { + __ bang_stack_with_offset(p*page_size); + } + + // Record a new watermark, unless the update is above the safe limit. + // Otherwise, the next time around a check above would pass the safe limit. + __ cmpptr(rsp, Address(thread, JavaThread::shadow_zone_safe_limit_offset())); + __ jccb(Assembler::belowEqual, L_done); +#ifdef _LP64 + __ movptr(rscratch1, rsp); + __ andptr(rscratch1, ~(page_size - 1)); + __ movptr(Address(thread, JavaThread::shadow_zone_growth_watermark_offset()), rscratch1); +#else + __ movptr(Address(thread, JavaThread::shadow_zone_growth_watermark_offset()), rsp); +#endif + + __ bind(L_done); + +#ifndef _LP64 + __ pop(thread); +#endif +} + #endif // CC_INTERP diff --git a/hotspot/src/share/vm/interpreter/interpreter.cpp b/hotspot/src/share/vm/interpreter/interpreter.cpp index bfcb1bea2..d5d94f34c 100644 --- a/hotspot/src/share/vm/interpreter/interpreter.cpp +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp @@ -44,7 +44,9 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/timer.hpp" - +#include "runtime/vframeArray.hpp" +#include "utilities/debug.hpp" +#include "utilities/macros.hpp" # define __ _masm-> @@ -474,27 +476,6 @@ bool AbstractInterpreter::bytecode_should_reexecute(Bytecodes::Code code) { } } -void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { - // Quick & dirty stack overflow checking: bang the stack & handle trap. - // Note that we do the banging after the frame is setup, since the exception - // handling code expects to find a valid interpreter frame on the stack. - // Doing the banging earlier fails if the caller frame is not an interpreter - // frame. - // (Also, the exception throwing code expects to unlock any synchronized - // method receiever, so do the banging after locking the receiver.) - - // Bang each page in the shadow zone. We can't assume it's been done for - // an interpreter frame with greater than a page of locals, so each page - // needs to be checked. Only true for non-native. - if (UseStackBanging) { - const int start_page = native_call ? StackShadowPages : 1; - const int page_size = os::vm_page_size(); - for (int pages = start_page; pages <= StackShadowPages ; pages++) { - __ bang_stack_with_offset(pages*page_size); - } - } -} - void AbstractInterpreterGenerator::initialize_method_handle_entries() { // method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate: for (int i = Interpreter::method_handle_invoke_FIRST; i <= Interpreter::method_handle_invoke_LAST; i++) { diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index b4f83a3cb..84841b76e 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1371,11 +1371,10 @@ bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) { // respectively. const int framesize_in_bytes = Interpreter::size_top_interpreter_activation(method()) * wordSize; - int reserved_area = ((StackShadowPages + StackRedPages + StackYellowPages) - * vm_page_size()) + framesize_in_bytes; + // The very lower end of the stack - address stack_limit = thread->stack_base() - thread->stack_size(); - return (sp > (stack_limit + reserved_area)); + address stack_limit = ((JavaThread*)thread)->shadow_zone_safe_limit(); + return (sp > (stack_limit + framesize_in_bytes)); } size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) { diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index d111aff96..2be226463 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -326,7 +326,7 @@ void Thread::record_stack_base_and_size() { set_stack_base(os::current_stack_base()); set_stack_size(os::current_stack_size()); if (is_Java_thread()) { - ((JavaThread*) this)->set_stack_overflow_limit(); + ((JavaThread*) this)->set_shadow_zone_limits(); } // CR 7190089: on Solaris, primordial thread's stack is adjusted // in initialize_thread(). Without the adjustment, stack size is @@ -1488,6 +1488,8 @@ void JavaThread::initialize() { _suspend_equivalent = false; _in_deopt_handler = 0; _doing_unsafe_access = false; + _shadow_zone_safe_limit = NULL; + _shadow_zone_growth_watermark = NULL; _stack_guard_state = stack_guard_unused; (void)const_cast<oop&>(_exception_oop = oop(NULL)); _exception_pc = 0; diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 0e126964d..f1f0cdc58 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -561,6 +561,7 @@ protected: void set_stack_base(address base) { _stack_base = base; } size_t stack_size() const { return _stack_size; } void set_stack_size(size_t size) { _stack_size = size; } + address stack_end() const { return stack_base() - stack_size(); } void record_stack_base_and_size(); bool on_local_stack(address adr) const { @@ -925,6 +926,9 @@ class JavaThread: public Thread { // We load it from here to simplify the stack overflow check in assembly. address _stack_overflow_limit; + address _shadow_zone_safe_limit; + address _shadow_zone_growth_watermark; + // Compiler exception handling (NOTE: The _exception_oop is *NOT* the same as _pending_exception. It is // used to temp. parsing values into and out of the runtime system during exception handling for compiled // code) @@ -1313,6 +1317,14 @@ class JavaThread: public Thread { bool in_stack_red_zone(address a) { return (a <= stack_red_zone_base()) && (a >= (address)((intptr_t)stack_base() - stack_size())); } + static size_t stack_shadow_zone_size() + { return StackShadowPages * os::vm_page_size(); } + + address shadow_zone_safe_limit() const { + assert(_shadow_zone_safe_limit != NULL, "Don't call this before the field is initialized."); + return _shadow_zone_safe_limit; + } + void create_stack_guard_pages(); void remove_stack_guard_pages(); @@ -1344,6 +1356,12 @@ class JavaThread: public Thread { StackRedPages) * os::vm_page_size()); } + void set_shadow_zone_limits() { + _shadow_zone_safe_limit = + Thread::stack_end() + JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size() + JavaThread::stack_shadow_zone_size(); + _shadow_zone_growth_watermark = JavaThread::stack_base(); + } + // Misc. accessors/mutators void set_do_not_unlock(void) { _do_not_unlock_if_synchronized = true; } void clr_do_not_unlock(void) { _do_not_unlock_if_synchronized = false; } @@ -1381,6 +1399,8 @@ class JavaThread: public Thread { static ByteSize stack_overflow_limit_offset() { return byte_offset_of(JavaThread, _stack_overflow_limit); } static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); } static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } + static ByteSize shadow_zone_safe_limit_offset() { return byte_offset_of(JavaThread, _shadow_zone_safe_limit);} + static ByteSize shadow_zone_growth_watermark_offset() { return byte_offset_of(JavaThread, _shadow_zone_growth_watermark);} static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } static ByteSize do_not_unlock_if_synchronized_offset() { return byte_offset_of(JavaThread, _do_not_unlock_if_synchronized); } -- 2.22.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2