aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/utilities/events.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/vm/utilities/events.cpp')
-rw-r--r--src/share/vm/utilities/events.cpp231
1 files changed, 34 insertions, 197 deletions
diff --git a/src/share/vm/utilities/events.cpp b/src/share/vm/utilities/events.cpp
index 62341195d..9c1ecb546 100644
--- a/src/share/vm/utilities/events.cpp
+++ b/src/share/vm/utilities/events.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
#include "memory/allocation.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/osThread.hpp"
+#include "runtime/threadCritical.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "runtime/timer.hpp"
#include "utilities/events.hpp"
@@ -43,184 +44,40 @@
#endif
-#ifndef PRODUCT
+EventLog* Events::_logs = NULL;
+StringEventLog* Events::_messages = NULL;
+StringEventLog* Events::_exceptions = NULL;
+StringEventLog* Events::_deopt_messages = NULL;
-////////////////////////////////////////////////////////////////////////////
-// Event
-
-typedef u4 EventID;
-
-class Event VALUE_OBJ_CLASS_SPEC {
- private:
- jlong _time_tick;
- intx _thread_id;
- const char* _format;
- int _indent;
- intptr_t _arg_1;
- intptr_t _arg_2;
- intptr_t _arg_3;
-
- // only EventBuffer::add_event() can assign event id
- friend class EventBuffer;
- EventID _id;
-
- public:
-
- void clear() { _format = NULL; }
-
- EventID id() const { return _id; }
-
- void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
- _format = format;
- _arg_1 = arg_1;
- _arg_2 = arg_2;
- _arg_3 = arg_3;
-
- _indent = indent;
-
- _thread_id = os::current_thread_id();
- _time_tick = os::elapsed_counter();
- }
-
- void print_on(outputStream *st) {
- if (_format == NULL) return;
- st->print(" %d", _thread_id);
- st->print(" %3.2g ", (double)_time_tick / os::elapsed_frequency());
- st->fill_to(20);
- for (int index = 0; index < _indent; index++) {
- st->print("| ");
- }
- st->print_cr(_format, _arg_1, _arg_2, _arg_3);
- }
-};
-
-////////////////////////////////////////////////////////////////////////////
-// EventBuffer
-//
-// Simple lock-free event queue. Every event has a unique 32-bit id.
-// It's fine if two threads add events at the same time, because they
-// will get different event id, and then write to different buffer location.
-// However, it is assumed that add_event() is quick enough (or buffer size
-// is big enough), so when one thread is adding event, there can't be more
-// than "size" events created by other threads; otherwise we'll end up having
-// two threads writing to the same location.
-
-class EventBuffer : AllStatic {
- private:
- static Event* buffer;
- static int size;
- static jint indent;
- static volatile EventID _current_event_id;
-
- static EventID get_next_event_id() {
- return (EventID)Atomic::add(1, (jint*)&_current_event_id);
- }
-
- public:
- static void inc_indent() { Atomic::inc(&indent); }
- static void dec_indent() { Atomic::dec(&indent); }
-
- static bool get_event(EventID id, Event* event) {
- int index = (int)(id % size);
- if (buffer[index].id() == id) {
- memcpy(event, &buffer[index], sizeof(Event));
- // check id again; if buffer[index] is being updated by another thread,
- // event->id() will contain different value.
- return (event->id() == id);
- } else {
- // id does not match - id is invalid, or event is overwritten
- return false;
- }
- }
-
- // add a new event to the queue; if EventBuffer is full, this call will
- // overwrite the oldest event in the queue
- static EventID add_event(const char* format,
- intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
- // assign a unique id
- EventID id = get_next_event_id();
-
- // event will be copied to buffer[index]
- int index = (int)(id % size);
-
- // first, invalidate id, buffer[index] can't have event with id = index + 2
- buffer[index]._id = index + 2;
-
- // make sure everyone has seen that buffer[index] is invalid
- OrderAccess::fence();
-
- // ... before updating its value
- buffer[index].fill(indent, format, arg_1, arg_2, arg_3);
-
- // finally, set up real event id, now buffer[index] contains valid event
- OrderAccess::release_store(&(buffer[index]._id), id);
-
- return id;
- }
-
- static void print_last(outputStream *st, int number) {
- st->print_cr("[Last %d events in the event buffer]", number);
- st->print_cr("-<thd>-<elapsed sec>-<description>---------------------");
-
- int count = 0;
- EventID id = _current_event_id;
- while (count < number) {
- Event event;
- if (get_event(id, &event)) {
- event.print_on(st);
- }
- id--;
- count++;
- }
- }
-
- static void print_all(outputStream* st) {
- print_last(st, size);
- }
-
- static void init() {
- // Allocate the event buffer
- size = EventLogLength;
- buffer = NEW_C_HEAP_ARRAY(Event, size);
-
- _current_event_id = 0;
+EventLog::EventLog() {
+ // This normally done during bootstrap when we're only single
+ // threaded but use a ThreadCritical to ensure inclusion in case
+ // some are created slightly late.
+ ThreadCritical tc;
+ _next = Events::_logs;
+ Events::_logs = this;
+}
- // Clear the event buffer
- for (int index = 0; index < size; index++) {
- buffer[index]._id = index + 1; // index + 1 is invalid id
- buffer[index].clear();
- }
+// For each registered event logger, print out the current contents of
+// the buffer. This is normally called when the JVM is crashing.
+void Events::print_all(outputStream* out) {
+ EventLog* log = _logs;
+ while (log != NULL) {
+ log->print_log_on(out);
+ log = log->next();
}
-};
-
-Event* EventBuffer::buffer;
-int EventBuffer::size;
-volatile EventID EventBuffer::_current_event_id;
-int EventBuffer::indent;
-
-////////////////////////////////////////////////////////////////////////////
-// Events
+}
-// Events::log() is safe for signal handlers
-void Events::log(const char* format, ...) {
+void Events::init() {
if (LogEvents) {
- va_list ap;
- va_start(ap, format);
- intptr_t arg_1 = va_arg(ap, intptr_t);
- intptr_t arg_2 = va_arg(ap, intptr_t);
- intptr_t arg_3 = va_arg(ap, intptr_t);
- va_end(ap);
-
- EventBuffer::add_event(format, arg_1, arg_2, arg_3);
+ _messages = new StringEventLog("Events");
+ _exceptions = new StringEventLog("Internal exceptions");
+ _deopt_messages = new StringEventLog("Deoptimization events");
}
}
-void Events::print_all(outputStream *st) {
- EventBuffer::print_all(st);
-}
-
-void Events::print_last(outputStream *st, int number) {
- EventBuffer::print_last(st, number);
+void eventlog_init() {
+ Events::init();
}
///////////////////////////////////////////////////////////////////////////
@@ -230,37 +87,17 @@ EventMark::EventMark(const char* format, ...) {
if (LogEvents) {
va_list ap;
va_start(ap, format);
- intptr_t arg_1 = va_arg(ap, intptr_t);
- intptr_t arg_2 = va_arg(ap, intptr_t);
- intptr_t arg_3 = va_arg(ap, intptr_t);
+ // Save a copy of begin message and log it.
+ _buffer.printv(format, ap);
+ Events::log(NULL, _buffer);
va_end(ap);
-
- EventBuffer::add_event(format, arg_1, arg_2, arg_3);
- EventBuffer::inc_indent();
}
}
EventMark::~EventMark() {
if (LogEvents) {
- EventBuffer::dec_indent();
- EventBuffer::add_event("done", 0, 0, 0);
+ // Append " done" to the begin message and log it
+ _buffer.append(" done");
+ Events::log(NULL, _buffer);
}
}
-
-///////////////////////////////////////////////////////////////////////////
-
-void eventlog_init() {
- EventBuffer::init();
-}
-
-int print_all_events(outputStream *st) {
- EventBuffer::print_all(st);
- return 1;
-}
-
-#else
-
-void eventlog_init() {}
-int print_all_events(outputStream *st) { return 0; }
-
-#endif // PRODUCT