8035493: JVMTI PopFrame capability must instruct compilers not to prune locals
Reviewed-by: kvn, sla, coleenp, sspitsyn
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -2276,7 +2276,7 @@
if (!has_handler() && (!instruction->needs_exception_state() || instruction->exception_state() != NULL)) {
assert(instruction->exception_state() == NULL
|| instruction->exception_state()->kind() == ValueStack::EmptyExceptionState
- || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->jvmti_can_access_local_variables()),
+ || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->should_retain_local_variables()),
"exception_state should be of exception kind");
return new XHandlers();
}
@@ -2367,7 +2367,7 @@
// This scope and all callees do not handle exceptions, so the local
// variables of this scope are not needed. However, the scope itself is
// required for a correct exception stack trace -> clear out the locals.
- if (_compilation->env()->jvmti_can_access_local_variables()) {
+ if (_compilation->env()->should_retain_local_variables()) {
cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci());
} else {
cur_state = cur_state->copy(ValueStack::EmptyExceptionState, cur_state->bci());
@@ -3251,7 +3251,7 @@
ValueStack* GraphBuilder::copy_state_for_exception_with_bci(int bci) {
ValueStack* s = copy_state_exhandling_with_bci(bci);
if (s == NULL) {
- if (_compilation->env()->jvmti_can_access_local_variables()) {
+ if (_compilation->env()->should_retain_local_variables()) {
s = state()->copy(ValueStack::ExceptionState, bci);
} else {
s = state()->copy(ValueStack::EmptyExceptionState, bci);
--- a/hotspot/src/share/vm/c1/c1_Instruction.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -76,7 +76,7 @@
void Instruction::update_exception_state(ValueStack* state) {
if (state != NULL && (state->kind() == ValueStack::EmptyExceptionState || state->kind() == ValueStack::ExceptionState)) {
- assert(state->kind() == ValueStack::EmptyExceptionState || Compilation::current()->env()->jvmti_can_access_local_variables(), "unexpected state kind");
+ assert(state->kind() == ValueStack::EmptyExceptionState || Compilation::current()->env()->should_retain_local_variables(), "unexpected state kind");
_exception_state = state;
} else {
_exception_state = NULL;
--- a/hotspot/src/share/vm/c1/c1_ValueStack.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/c1/c1_ValueStack.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -52,7 +52,7 @@
, _stack()
, _locks(copy_from->locks_size())
{
- assert(kind != EmptyExceptionState || !Compilation::current()->env()->jvmti_can_access_local_variables(), "need locals");
+ assert(kind != EmptyExceptionState || !Compilation::current()->env()->should_retain_local_variables(), "need locals");
if (kind != EmptyExceptionState) {
// only allocate space if we need to copy the locals-array
_locals = Values(copy_from->locals_size());
--- a/hotspot/src/share/vm/c1/c1_ValueStack.hpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/c1/c1_ValueStack.hpp Sat Feb 22 10:22:05 2014 +0100
@@ -75,7 +75,7 @@
void set_caller_state(ValueStack* s) {
assert(kind() == EmptyExceptionState ||
- (Compilation::current()->env()->jvmti_can_access_local_variables() && kind() == ExceptionState),
+ (Compilation::current()->env()->should_retain_local_variables() && kind() == ExceptionState),
"only EmptyExceptionStates can be modified");
_caller_state = s;
}
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -136,6 +136,11 @@
_ClassCastException_instance = NULL;
_the_null_string = NULL;
_the_min_jint_string = NULL;
+
+ _jvmti_can_hotswap_or_post_breakpoint = false;
+ _jvmti_can_access_local_variables = false;
+ _jvmti_can_post_on_exceptions = false;
+ _jvmti_can_pop_frame = false;
}
ciEnv::ciEnv(Arena* arena) {
@@ -186,6 +191,11 @@
_ClassCastException_instance = NULL;
_the_null_string = NULL;
_the_min_jint_string = NULL;
+
+ _jvmti_can_hotswap_or_post_breakpoint = false;
+ _jvmti_can_access_local_variables = false;
+ _jvmti_can_post_on_exceptions = false;
+ _jvmti_can_pop_frame = false;
}
ciEnv::~ciEnv() {
@@ -205,6 +215,31 @@
_jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
+ _jvmti_can_pop_frame = JvmtiExport::can_pop_frame();
+}
+
+bool ciEnv::should_retain_local_variables() const {
+ return _jvmti_can_access_local_variables || _jvmti_can_pop_frame;
+}
+
+bool ciEnv::jvmti_state_changed() const {
+ if (!_jvmti_can_access_local_variables &&
+ JvmtiExport::can_access_local_variables()) {
+ return true;
+ }
+ if (!_jvmti_can_hotswap_or_post_breakpoint &&
+ JvmtiExport::can_hotswap_or_post_breakpoint()) {
+ return true;
+ }
+ if (!_jvmti_can_post_on_exceptions &&
+ JvmtiExport::can_post_on_exceptions()) {
+ return true;
+ }
+ if (!_jvmti_can_pop_frame &&
+ JvmtiExport::can_pop_frame()) {
+ return true;
+ }
+ return false;
}
// ------------------------------------------------------------------
@@ -940,13 +975,7 @@
No_Safepoint_Verifier nsv;
// Change in Jvmti state may invalidate compilation.
- if (!failing() &&
- ( (!jvmti_can_hotswap_or_post_breakpoint() &&
- JvmtiExport::can_hotswap_or_post_breakpoint()) ||
- (!jvmti_can_access_local_variables() &&
- JvmtiExport::can_access_local_variables()) ||
- (!jvmti_can_post_on_exceptions() &&
- JvmtiExport::can_post_on_exceptions()) )) {
+ if (!failing() && jvmti_state_changed()) {
record_failure("Jvmti state change invalidated dependencies");
}
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp Sat Feb 22 10:22:05 2014 +0100
@@ -69,6 +69,7 @@
bool _jvmti_can_hotswap_or_post_breakpoint;
bool _jvmti_can_access_local_variables;
bool _jvmti_can_post_on_exceptions;
+ bool _jvmti_can_pop_frame;
// Cache DTrace flags
bool _dtrace_extended_probes;
@@ -332,8 +333,9 @@
// Cache Jvmti state
void cache_jvmti_state();
+ bool jvmti_state_changed() const;
+ bool should_retain_local_variables() const;
bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; }
- bool jvmti_can_access_local_variables() const { return _jvmti_can_access_local_variables; }
bool jvmti_can_post_on_exceptions() const { return _jvmti_can_post_on_exceptions; }
// Cache DTrace flags
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -412,7 +412,7 @@
// information.
MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
MethodLivenessResult result = raw_liveness_at_bci(bci);
- if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
+ if (CURRENT_ENV->should_retain_local_variables() || DeoptimizeALot || CompileTheWorld) {
// Keep all locals live for the user's edification and amusement.
result.at_put_range(0, result.size(), true);
}
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -111,7 +111,7 @@
assert(is_initialized(), "Compiler thread must be initialized");
bool subsume_loads = SubsumeLoads;
- bool do_escape_analysis = DoEscapeAnalysis && !env->jvmti_can_access_local_variables();
+ bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
bool eliminate_boxing = EliminateAutoBox;
while (!env->failing()) {
// Attempt to compile while subsuming loads into machine instructions.
--- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Feb 20 16:38:45 2014 -0500
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Sat Feb 22 10:22:05 2014 +0100
@@ -863,7 +863,7 @@
}
}
- if (env()->jvmti_can_access_local_variables()) {
+ if (env()->should_retain_local_variables()) {
// At any safepoint, this method can get breakpointed, which would
// then require an immediate deoptimization.
can_prune_locals = false; // do not prune locals