代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/openjdk-1.8.0 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。