Mercurial > hg > truffle
comparison src/share/vm/prims/jvmtiImpl.cpp @ 13038:910026b800b8
8026946: JvmtiEnv::SetBreakpoint and JvmtiEnv::ClearBreakpoint should use MethodHandle
8026948: JvmtiEnv::SetBreakpoint and JvmtiEnv::ClearBreakpoint might not work with anonymous classes
Summary: Walk methods in breakpoints for marking on stack so they aren't deallocated by redefine classes. Use class_holder rather than class_loader to keep GC from reclaiming class owning the method.
Reviewed-by: sspitsyn, ehelin, sla
author | coleenp |
---|---|
date | Fri, 01 Nov 2013 10:32:36 -0400 |
parents | 2fab5b7e6140 |
children | 096c224171c4 78bbf4d43a14 |
comparison
equal
deleted
inserted
replaced
13037:c8fc12209830 | 13038:910026b800b8 |
---|---|
208 GrowableElement *e = _elements->at(i); | 208 GrowableElement *e = _elements->at(i); |
209 e->oops_do(f); | 209 e->oops_do(f); |
210 } | 210 } |
211 } | 211 } |
212 | 212 |
213 void GrowableCache::metadata_do(void f(Metadata*)) { | |
214 int len = _elements->length(); | |
215 for (int i=0; i<len; i++) { | |
216 GrowableElement *e = _elements->at(i); | |
217 e->metadata_do(f); | |
218 } | |
219 } | |
220 | |
213 void GrowableCache::gc_epilogue() { | 221 void GrowableCache::gc_epilogue() { |
214 int len = _elements->length(); | 222 int len = _elements->length(); |
215 for (int i=0; i<len; i++) { | 223 for (int i=0; i<len; i++) { |
216 _cache[i] = _elements->at(i)->getCacheValue(); | 224 _cache[i] = _elements->at(i)->getCacheValue(); |
217 } | 225 } |
222 // | 230 // |
223 | 231 |
224 JvmtiBreakpoint::JvmtiBreakpoint() { | 232 JvmtiBreakpoint::JvmtiBreakpoint() { |
225 _method = NULL; | 233 _method = NULL; |
226 _bci = 0; | 234 _bci = 0; |
227 _class_loader = NULL; | 235 _class_holder = NULL; |
228 } | 236 } |
229 | 237 |
230 JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location) { | 238 JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location) { |
231 _method = m_method; | 239 _method = m_method; |
232 _class_loader = _method->method_holder()->class_loader_data()->class_loader(); | 240 _class_holder = _method->method_holder()->klass_holder(); |
233 #ifdef CHECK_UNHANDLED_OOPS | 241 #ifdef CHECK_UNHANDLED_OOPS |
234 // _class_loader can't be wrapped in a Handle, because JvmtiBreakpoint:s are | 242 // _class_holder can't be wrapped in a Handle, because JvmtiBreakpoints are |
235 // eventually allocated on the heap. | 243 // sometimes allocated on the heap. |
236 // | 244 // |
237 // The code handling JvmtiBreakpoint:s allocated on the stack can't be | 245 // The code handling JvmtiBreakpoints allocated on the stack can't be |
238 // interrupted by a GC until _class_loader is reachable by the GC via the | 246 // interrupted by a GC until _class_holder is reachable by the GC via the |
239 // oops_do method. | 247 // oops_do method. |
240 Thread::current()->allow_unhandled_oop(&_class_loader); | 248 Thread::current()->allow_unhandled_oop(&_class_holder); |
241 #endif // CHECK_UNHANDLED_OOPS | 249 #endif // CHECK_UNHANDLED_OOPS |
242 assert(_method != NULL, "_method != NULL"); | 250 assert(_method != NULL, "_method != NULL"); |
243 _bci = (int) location; | 251 _bci = (int) location; |
244 assert(_bci >= 0, "_bci >= 0"); | 252 assert(_bci >= 0, "_bci >= 0"); |
245 } | 253 } |
246 | 254 |
247 void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) { | 255 void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) { |
248 _method = bp._method; | 256 _method = bp._method; |
249 _bci = bp._bci; | 257 _bci = bp._bci; |
250 _class_loader = bp._class_loader; | 258 _class_holder = bp._class_holder; |
251 } | 259 } |
252 | 260 |
253 bool JvmtiBreakpoint::lessThan(JvmtiBreakpoint& bp) { | 261 bool JvmtiBreakpoint::lessThan(JvmtiBreakpoint& bp) { |
254 Unimplemented(); | 262 Unimplemented(); |
255 return false; | 263 return false; |
363 if (_bp != NULL) { | 371 if (_bp != NULL) { |
364 _bp->oops_do(f); | 372 _bp->oops_do(f); |
365 } | 373 } |
366 } | 374 } |
367 | 375 |
376 void VM_ChangeBreakpoints::metadata_do(void f(Metadata*)) { | |
377 // Walk metadata in breakpoints to keep from being deallocated with RedefineClasses | |
378 if (_bp != NULL) { | |
379 _bp->metadata_do(f); | |
380 } | |
381 } | |
382 | |
368 // | 383 // |
369 // class JvmtiBreakpoints | 384 // class JvmtiBreakpoints |
370 // | 385 // |
371 // a JVMTI internal collection of JvmtiBreakpoint | 386 // a JVMTI internal collection of JvmtiBreakpoint |
372 // | 387 // |
377 | 392 |
378 JvmtiBreakpoints:: ~JvmtiBreakpoints() {} | 393 JvmtiBreakpoints:: ~JvmtiBreakpoints() {} |
379 | 394 |
380 void JvmtiBreakpoints::oops_do(OopClosure* f) { | 395 void JvmtiBreakpoints::oops_do(OopClosure* f) { |
381 _bps.oops_do(f); | 396 _bps.oops_do(f); |
397 } | |
398 | |
399 void JvmtiBreakpoints::metadata_do(void f(Metadata*)) { | |
400 _bps.metadata_do(f); | |
382 } | 401 } |
383 | 402 |
384 void JvmtiBreakpoints::gc_epilogue() { | 403 void JvmtiBreakpoints::gc_epilogue() { |
385 _bps.gc_epilogue(); | 404 _bps.gc_epilogue(); |
386 } | 405 } |
497 if (_jvmti_breakpoints != NULL) { | 516 if (_jvmti_breakpoints != NULL) { |
498 _jvmti_breakpoints->oops_do(f); | 517 _jvmti_breakpoints->oops_do(f); |
499 } | 518 } |
500 } | 519 } |
501 | 520 |
521 void JvmtiCurrentBreakpoints::metadata_do(void f(Metadata*)) { | |
522 if (_jvmti_breakpoints != NULL) { | |
523 _jvmti_breakpoints->metadata_do(f); | |
524 } | |
525 } | |
526 | |
502 void JvmtiCurrentBreakpoints::gc_epilogue() { | 527 void JvmtiCurrentBreakpoints::gc_epilogue() { |
503 if (_jvmti_breakpoints != NULL) { | 528 if (_jvmti_breakpoints != NULL) { |
504 _jvmti_breakpoints->gc_epilogue(); | 529 _jvmti_breakpoints->gc_epilogue(); |
505 } | 530 } |
506 } | 531 } |