src/share/vm/utilities/events.cpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

duke@435 1 /*
duke@435 2 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 #include "incls/_precompiled.incl"
duke@435 26 #include "incls/_events.cpp.incl"
duke@435 27
duke@435 28
duke@435 29 #ifndef PRODUCT
duke@435 30
duke@435 31 ////////////////////////////////////////////////////////////////////////////
duke@435 32 // Event
duke@435 33
duke@435 34 typedef u4 EventID;
duke@435 35
duke@435 36 class Event VALUE_OBJ_CLASS_SPEC {
duke@435 37 private:
duke@435 38 jlong _time_tick;
duke@435 39 intx _thread_id;
duke@435 40 const char* _format;
duke@435 41 int _indent;
duke@435 42 intptr_t _arg_1;
duke@435 43 intptr_t _arg_2;
duke@435 44 intptr_t _arg_3;
duke@435 45
duke@435 46 // only EventBuffer::add_event() can assign event id
duke@435 47 friend class EventBuffer;
duke@435 48 EventID _id;
duke@435 49
duke@435 50 public:
duke@435 51
duke@435 52 void clear() { _format = NULL; }
duke@435 53
duke@435 54 EventID id() const { return _id; }
duke@435 55
duke@435 56 void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
duke@435 57 _format = format;
duke@435 58 _arg_1 = arg_1;
duke@435 59 _arg_2 = arg_2;
duke@435 60 _arg_3 = arg_3;
duke@435 61
duke@435 62 _indent = indent;
duke@435 63
duke@435 64 _thread_id = os::current_thread_id();
duke@435 65 _time_tick = os::elapsed_counter();
duke@435 66 }
duke@435 67
duke@435 68 void print_on(outputStream *st) {
duke@435 69 if (_format == NULL) return;
duke@435 70 st->print(" %d", _thread_id);
duke@435 71 st->print(" %3.2g ", (double)_time_tick / os::elapsed_frequency());
duke@435 72 st->fill_to(20);
duke@435 73 for (int index = 0; index < _indent; index++) {
duke@435 74 st->print("| ");
duke@435 75 }
duke@435 76 st->print_cr(_format, _arg_1, _arg_2, _arg_3);
duke@435 77 }
duke@435 78 };
duke@435 79
duke@435 80 ////////////////////////////////////////////////////////////////////////////
duke@435 81 // EventBuffer
duke@435 82 //
duke@435 83 // Simple lock-free event queue. Every event has a unique 32-bit id.
duke@435 84 // It's fine if two threads add events at the same time, because they
duke@435 85 // will get different event id, and then write to different buffer location.
duke@435 86 // However, it is assumed that add_event() is quick enough (or buffer size
duke@435 87 // is big enough), so when one thread is adding event, there can't be more
duke@435 88 // than "size" events created by other threads; otherwise we'll end up having
duke@435 89 // two threads writing to the same location.
duke@435 90
duke@435 91 class EventBuffer : AllStatic {
duke@435 92 private:
duke@435 93 static Event* buffer;
duke@435 94 static int size;
duke@435 95 static jint indent;
duke@435 96 static volatile EventID _current_event_id;
duke@435 97
duke@435 98 static EventID get_next_event_id() {
duke@435 99 return (EventID)Atomic::add(1, (jint*)&_current_event_id);
duke@435 100 }
duke@435 101
duke@435 102 public:
duke@435 103 static void inc_indent() { Atomic::inc(&indent); }
duke@435 104 static void dec_indent() { Atomic::dec(&indent); }
duke@435 105
duke@435 106 static bool get_event(EventID id, Event* event) {
duke@435 107 int index = (int)(id % size);
duke@435 108 if (buffer[index].id() == id) {
duke@435 109 memcpy(event, &buffer[index], sizeof(Event));
duke@435 110 // check id again; if buffer[index] is being updated by another thread,
duke@435 111 // event->id() will contain different value.
duke@435 112 return (event->id() == id);
duke@435 113 } else {
duke@435 114 // id does not match - id is invalid, or event is overwritten
duke@435 115 return false;
duke@435 116 }
duke@435 117 }
duke@435 118
duke@435 119 // add a new event to the queue; if EventBuffer is full, this call will
duke@435 120 // overwrite the oldest event in the queue
duke@435 121 static EventID add_event(const char* format,
duke@435 122 intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
duke@435 123 // assign a unique id
duke@435 124 EventID id = get_next_event_id();
duke@435 125
duke@435 126 // event will be copied to buffer[index]
duke@435 127 int index = (int)(id % size);
duke@435 128
duke@435 129 // first, invalidate id, buffer[index] can't have event with id = index + 2
duke@435 130 buffer[index]._id = index + 2;
duke@435 131
duke@435 132 // make sure everyone has seen that buffer[index] is invalid
duke@435 133 OrderAccess::fence();
duke@435 134
duke@435 135 // ... before updating its value
duke@435 136 buffer[index].fill(indent, format, arg_1, arg_2, arg_3);
duke@435 137
duke@435 138 // finally, set up real event id, now buffer[index] contains valid event
duke@435 139 OrderAccess::release_store(&(buffer[index]._id), id);
duke@435 140
duke@435 141 return id;
duke@435 142 }
duke@435 143
duke@435 144 static void print_last(outputStream *st, int number) {
duke@435 145 st->print_cr("[Last %d events in the event buffer]", number);
duke@435 146 st->print_cr("-<thd>-<elapsed sec>-<description>---------------------");
duke@435 147
duke@435 148 int count = 0;
duke@435 149 EventID id = _current_event_id;
duke@435 150 while (count < number) {
duke@435 151 Event event;
duke@435 152 if (get_event(id, &event)) {
duke@435 153 event.print_on(st);
duke@435 154 }
duke@435 155 id--;
duke@435 156 count++;
duke@435 157 }
duke@435 158 }
duke@435 159
duke@435 160 static void print_all(outputStream* st) {
duke@435 161 print_last(st, size);
duke@435 162 }
duke@435 163
duke@435 164 static void init() {
duke@435 165 // Allocate the event buffer
duke@435 166 size = EventLogLength;
duke@435 167 buffer = NEW_C_HEAP_ARRAY(Event, size);
duke@435 168
duke@435 169 _current_event_id = 0;
duke@435 170
duke@435 171 // Clear the event buffer
duke@435 172 for (int index = 0; index < size; index++) {
duke@435 173 buffer[index]._id = index + 1; // index + 1 is invalid id
duke@435 174 buffer[index].clear();
duke@435 175 }
duke@435 176 }
duke@435 177 };
duke@435 178
duke@435 179 Event* EventBuffer::buffer;
duke@435 180 int EventBuffer::size;
duke@435 181 volatile EventID EventBuffer::_current_event_id;
duke@435 182 int EventBuffer::indent;
duke@435 183
duke@435 184 ////////////////////////////////////////////////////////////////////////////
duke@435 185 // Events
duke@435 186
duke@435 187 // Events::log() is safe for signal handlers
duke@435 188 void Events::log(const char* format, ...) {
duke@435 189 if (LogEvents) {
duke@435 190 va_list ap;
duke@435 191 va_start(ap, format);
duke@435 192 intptr_t arg_1 = va_arg(ap, intptr_t);
duke@435 193 intptr_t arg_2 = va_arg(ap, intptr_t);
duke@435 194 intptr_t arg_3 = va_arg(ap, intptr_t);
duke@435 195 va_end(ap);
duke@435 196
duke@435 197 EventBuffer::add_event(format, arg_1, arg_2, arg_3);
duke@435 198 }
duke@435 199 }
duke@435 200
duke@435 201 void Events::print_all(outputStream *st) {
duke@435 202 EventBuffer::print_all(st);
duke@435 203 }
duke@435 204
duke@435 205 void Events::print_last(outputStream *st, int number) {
duke@435 206 EventBuffer::print_last(st, number);
duke@435 207 }
duke@435 208
duke@435 209 ///////////////////////////////////////////////////////////////////////////
duke@435 210 // EventMark
duke@435 211
duke@435 212 EventMark::EventMark(const char* format, ...) {
duke@435 213 if (LogEvents) {
duke@435 214 va_list ap;
duke@435 215 va_start(ap, format);
duke@435 216 intptr_t arg_1 = va_arg(ap, intptr_t);
duke@435 217 intptr_t arg_2 = va_arg(ap, intptr_t);
duke@435 218 intptr_t arg_3 = va_arg(ap, intptr_t);
duke@435 219 va_end(ap);
duke@435 220
duke@435 221 EventBuffer::add_event(format, arg_1, arg_2, arg_3);
duke@435 222 EventBuffer::inc_indent();
duke@435 223 }
duke@435 224 }
duke@435 225
duke@435 226 EventMark::~EventMark() {
duke@435 227 if (LogEvents) {
duke@435 228 EventBuffer::dec_indent();
duke@435 229 EventBuffer::add_event("done", 0, 0, 0);
duke@435 230 }
duke@435 231 }
duke@435 232
duke@435 233 ///////////////////////////////////////////////////////////////////////////
duke@435 234
duke@435 235 void eventlog_init() {
duke@435 236 EventBuffer::init();
duke@435 237 }
duke@435 238
duke@435 239 int print_all_events(outputStream *st) {
duke@435 240 EventBuffer::print_all(st);
duke@435 241 return 1;
duke@435 242 }
duke@435 243
duke@435 244 #else
duke@435 245
duke@435 246 void eventlog_init() {}
duke@435 247 int print_all_events(outputStream *st) { return 0; }
duke@435 248
duke@435 249 #endif // PRODUCT

mercurial