423
424
425 /**
426 * When a thread (such as the compiler thread or VM thread) cannot post a
427 * JVMTI event itself because the event needs to be posted from a Java
428 * thread, then it can defer the event to the Service thread for posting.
429 * The information needed to post the event is encapsulated into this class
430 * and then enqueued onto the JvmtiDeferredEventQueue, where the Service
431 * thread will pick it up and post it.
432 *
433 * This is currently only used for posting compiled-method-load and unload
434 * events, which we don't want posted from the compiler thread.
435 */
436 class JvmtiDeferredEvent {
437 friend class JvmtiDeferredEventQueue;
438 private:
439 typedef enum {
440 TYPE_NONE,
441 TYPE_COMPILED_METHOD_LOAD,
442 TYPE_COMPILED_METHOD_UNLOAD,
443 TYPE_DYNAMIC_CODE_GENERATED
444 } Type;
445
446 Type _type;
447 union {
448 nmethod* compiled_method_load;
449 struct {
450 nmethod* nm;
451 jmethodID method_id;
452 const void* code_begin;
453 } compiled_method_unload;
454 struct {
455 const char* name;
456 const void* code_begin;
457 const void* code_end;
458 } dynamic_code_generated;
459 } _event_data;
460
461 JvmtiDeferredEvent(Type t) : _type(t) {}
462
463 public:
464
465 JvmtiDeferredEvent() : _type(TYPE_NONE) {}
466
467 // Factory methods
468 static JvmtiDeferredEvent compiled_method_load_event(nmethod* nm)
469 NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
470 static JvmtiDeferredEvent compiled_method_unload_event(nmethod* nm,
471 jmethodID id, const void* code) NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
472 static JvmtiDeferredEvent dynamic_code_generated_event(
473 const char* name, const void* begin, const void* end)
474 NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
475
476 // Actually posts the event.
477 void post() NOT_JVMTI_RETURN;
478 };
479
480 /**
481 * Events enqueued on this queue wake up the Service thread which dequeues
482 * and posts the events. The Service_lock is required to be held
483 * when operating on the queue.
484 */
485 class JvmtiDeferredEventQueue : AllStatic {
486 friend class JvmtiDeferredEvent;
487 private:
488 class QueueNode : public CHeapObj<mtInternal> {
489 private:
490 JvmtiDeferredEvent _event;
491 QueueNode* _next;
492
493 public:
494 QueueNode(const JvmtiDeferredEvent& event)
|
423
424
425 /**
426 * When a thread (such as the compiler thread or VM thread) cannot post a
427 * JVMTI event itself because the event needs to be posted from a Java
428 * thread, then it can defer the event to the Service thread for posting.
429 * The information needed to post the event is encapsulated into this class
430 * and then enqueued onto the JvmtiDeferredEventQueue, where the Service
431 * thread will pick it up and post it.
432 *
433 * This is currently only used for posting compiled-method-load and unload
434 * events, which we don't want posted from the compiler thread.
435 */
436 class JvmtiDeferredEvent {
437 friend class JvmtiDeferredEventQueue;
438 private:
439 typedef enum {
440 TYPE_NONE,
441 TYPE_COMPILED_METHOD_LOAD,
442 TYPE_COMPILED_METHOD_UNLOAD,
443 TYPE_DYNAMIC_CODE_GENERATED,
444 TYPE_CLASS_UNLOADED
445 } Type;
446
447 Type _type;
448 union {
449 nmethod* compiled_method_load;
450 struct {
451 nmethod* nm;
452 jmethodID method_id;
453 const void* code_begin;
454 } compiled_method_unload;
455 struct {
456 const char* name;
457 const void* code_begin;
458 const void* code_end;
459 } dynamic_code_generated;
460 struct {
461 const char* name;
462 } class_unloaded;
463 } _event_data;
464
465 JvmtiDeferredEvent(Type t) : _type(t) {}
466
467 public:
468
469 JvmtiDeferredEvent() : _type(TYPE_NONE) {}
470
471 // Factory methods
472 static JvmtiDeferredEvent compiled_method_load_event(nmethod* nm)
473 NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
474 static JvmtiDeferredEvent compiled_method_unload_event(nmethod* nm,
475 jmethodID id, const void* code) NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
476 static JvmtiDeferredEvent dynamic_code_generated_event(
477 const char* name, const void* begin, const void* end)
478 NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
479 static JvmtiDeferredEvent class_unload_event(
480 const char* name) NOT_JVMTI_RETURN_(JvmtiDeferredEvent());
481
482 // Actually posts the event.
483 void post() NOT_JVMTI_RETURN;
484 };
485
486 /**
487 * Events enqueued on this queue wake up the Service thread which dequeues
488 * and posts the events. The Service_lock is required to be held
489 * when operating on the queue.
490 */
491 class JvmtiDeferredEventQueue : AllStatic {
492 friend class JvmtiDeferredEvent;
493 private:
494 class QueueNode : public CHeapObj<mtInternal> {
495 private:
496 JvmtiDeferredEvent _event;
497 QueueNode* _next;
498
499 public:
500 QueueNode(const JvmtiDeferredEvent& event)
|