Skip to content

Commit 6e1aa90

Browse files
committed
8226690: SIGSEGV in MetadataOnStackClosure::do_metadata
Dont create nmethod if classes have been redefined since compilation start. Reviewed-by: sspitsyn, dlong, eosterlund, gdub
1 parent 848614a commit 6e1aa90

File tree

9 files changed

+43
-7
lines changed

9 files changed

+43
-7
lines changed

src/hotspot/share/ci/ciEnv.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ ciEnv::ciEnv(CompileTask* task)
154154
_the_null_string = NULL;
155155
_the_min_jint_string = NULL;
156156

157+
_jvmti_redefinition_count = 0;
157158
_jvmti_can_hotswap_or_post_breakpoint = false;
158159
_jvmti_can_access_local_variables = false;
159160
_jvmti_can_post_on_exceptions = false;
@@ -209,6 +210,7 @@ ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) {
209210
_the_null_string = NULL;
210211
_the_min_jint_string = NULL;
211212

213+
_jvmti_redefinition_count = 0;
212214
_jvmti_can_hotswap_or_post_breakpoint = false;
213215
_jvmti_can_access_local_variables = false;
214216
_jvmti_can_post_on_exceptions = false;
@@ -231,13 +233,19 @@ void ciEnv::cache_jvmti_state() {
231233
VM_ENTRY_MARK;
232234
// Get Jvmti capabilities under lock to get consistant values.
233235
MutexLocker mu(JvmtiThreadState_lock);
236+
_jvmti_redefinition_count = JvmtiExport::redefinition_count();
234237
_jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
235238
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
236239
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
237240
_jvmti_can_pop_frame = JvmtiExport::can_pop_frame();
238241
}
239242

240243
bool ciEnv::jvmti_state_changed() const {
244+
// Some classes were redefined
245+
if (_jvmti_redefinition_count != JvmtiExport::redefinition_count()) {
246+
return true;
247+
}
248+
241249
if (!_jvmti_can_access_local_variables &&
242250
JvmtiExport::can_access_local_variables()) {
243251
return true;
@@ -254,6 +262,7 @@ bool ciEnv::jvmti_state_changed() const {
254262
JvmtiExport::can_pop_frame()) {
255263
return true;
256264
}
265+
257266
return false;
258267
}
259268

src/hotspot/share/ci/ciEnv.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class ciEnv : StackObj {
6868
int _name_buffer_len;
6969

7070
// Cache Jvmti state
71+
uint64_t _jvmti_redefinition_count;
7172
bool _jvmti_can_hotswap_or_post_breakpoint;
7273
bool _jvmti_can_access_local_variables;
7374
bool _jvmti_can_post_on_exceptions;

src/hotspot/share/code/nmethod.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,17 @@ class VerifyOopsClosure: public OopClosure {
21922192
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
21932193
};
21942194

2195+
class VerifyMetadataClosure: public MetadataClosure {
2196+
public:
2197+
void do_metadata(Metadata* md) {
2198+
if (md->is_method()) {
2199+
Method* method = (Method*)md;
2200+
assert(!method->is_old(), "Should not be installing old methods");
2201+
}
2202+
}
2203+
};
2204+
2205+
21952206
void nmethod::verify() {
21962207

21972208
// Hmm. OSR methods can be deopted but not marked as zombie or not_entrant
@@ -2255,6 +2266,10 @@ void nmethod::verify() {
22552266
Universe::heap()->verify_nmethod(this);
22562267

22572268
verify_scopes();
2269+
2270+
CompiledICLocker nm_verify(this);
2271+
VerifyMetadataClosure vmc;
2272+
metadata_do(&vmc);
22582273
}
22592274

22602275

src/hotspot/share/jvmci/jvmciEnv.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,18 @@ JVMCICompileState::JVMCICompileState(CompileTask* task):
4444
_failure_reason_on_C_heap(false) {
4545
// Get Jvmti capabilities under lock to get consistent values.
4646
MutexLocker mu(JvmtiThreadState_lock);
47+
_jvmti_redefinition_count = JvmtiExport::redefinition_count();
4748
_jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0;
4849
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables() ? 1 : 0;
4950
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0;
5051
_jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0;
5152
}
5253

5354
bool JVMCICompileState::jvmti_state_changed() const {
55+
// Some classes were redefined
56+
if (jvmti_redefinition_count() != JvmtiExport::redefinition_count()) {
57+
return true;
58+
}
5459
if (!jvmti_can_access_local_variables() &&
5560
JvmtiExport::can_access_local_variables()) {
5661
return true;

src/hotspot/share/jvmci/jvmciEnv.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class JVMCICompileState : public ResourceObj {
9494
// Cache JVMTI state. Defined as bytes so that reading them from Java
9595
// via Unsafe is well defined (the C++ type for bool is implementation
9696
// defined and may not be the same as a Java boolean).
97+
uint64_t _jvmti_redefinition_count;
9798
jbyte _jvmti_can_hotswap_or_post_breakpoint;
9899
jbyte _jvmti_can_access_local_variables;
99100
jbyte _jvmti_can_post_on_exceptions;
@@ -113,6 +114,7 @@ class JVMCICompileState : public ResourceObj {
113114
CompileTask* task() { return _task; }
114115

115116
bool jvmti_state_changed() const;
117+
uint64_t jvmti_redefinition_count() const { return _jvmti_redefinition_count; }
116118
bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint != 0; }
117119
bool jvmti_can_access_local_variables() const { return _jvmti_can_access_local_variables != 0; }
118120
bool jvmti_can_post_on_exceptions() const { return _jvmti_can_post_on_exceptions != 0; }

src/hotspot/share/prims/jvmtiExport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ bool JvmtiExport::_can_hotswap_or_post_breakpoint = fals
304304
bool JvmtiExport::_can_modify_any_class = false;
305305
bool JvmtiExport::_can_walk_any_space = false;
306306

307-
bool JvmtiExport::_has_redefined_a_class = false;
307+
uint64_t JvmtiExport::_redefinition_count = 0;
308308
bool JvmtiExport::_all_dependencies_are_recorded = false;
309309

310310
//

src/hotspot/share/prims/jvmtiExport.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,10 @@ class JvmtiExport : public AllStatic {
173173
// one or more classes during the lifetime of the VM. The flag should
174174
// only be set by the friend class and can be queried by other sub
175175
// systems as needed to relax invariant checks.
176-
static bool _has_redefined_a_class;
176+
static uint64_t _redefinition_count;
177177
friend class VM_RedefineClasses;
178-
inline static void set_has_redefined_a_class() {
179-
JVMTI_ONLY(_has_redefined_a_class = true;)
178+
inline static void increment_redefinition_count() {
179+
JVMTI_ONLY(_redefinition_count++;)
180180
}
181181
// Flag to indicate if the compiler has recorded all dependencies. When the
182182
// can_redefine_classes capability is enabled in the OnLoad phase then the compiler
@@ -188,10 +188,13 @@ class JvmtiExport : public AllStatic {
188188

189189
public:
190190
inline static bool has_redefined_a_class() {
191-
JVMTI_ONLY(return _has_redefined_a_class);
191+
JVMTI_ONLY(return _redefinition_count != 0);
192192
NOT_JVMTI(return false);
193193
}
194194

195+
// Only set in safepoint, so no memory ordering needed.
196+
inline static uint64_t redefinition_count() { return _redefinition_count; }
197+
195198
inline static bool all_dependencies_are_recorded() {
196199
return _all_dependencies_are_recorded;
197200
}

src/hotspot/share/prims/jvmtiRedefineClasses.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,9 @@ void VM_RedefineClasses::doit() {
232232
ResolvedMethodTable::adjust_method_entries(&trace_name_printed);
233233
}
234234

235-
// Set flag indicating that some invariants are no longer true.
235+
// Increment flag indicating that some invariants are no longer true.
236236
// See jvmtiExport.hpp for detailed explanation.
237-
JvmtiExport::set_has_redefined_a_class();
237+
JvmtiExport::increment_redefinition_count();
238238

239239
// check_class() is optionally called for product bits, but is
240240
// always called for non-product bits.

src/hotspot/share/runtime/sharedRuntime.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,7 @@ bool SharedRuntime::resolve_sub_helper_internal(methodHandle callee_method, cons
12691269
// will be supported.
12701270
if (!callee_method->is_old() &&
12711271
(callee == NULL || (callee->is_in_use() && callee_method->code() == callee))) {
1272+
NoSafepointVerifier nsv;
12721273
#ifdef ASSERT
12731274
// We must not try to patch to jump to an already unloaded method.
12741275
if (dest_entry_point != 0) {

0 commit comments

Comments
 (0)