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

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

mercurial