/* Sun-$Revision: 23.5 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface // The event log is used for debugging; it is a circular buffer containing // the last N events. An event is represented by an identifying string // and up to NPARAM parameters. -Urs const fint NPARAM = 3; // number of params per event // helper macros # define LOG_EVENT(name) eventLog->log(name) # define LOG_EVENT1(name,p1) eventLog->log(name, (void*)(p1)) # define LOG_EVENT2(name,p1,p2) eventLog->log(name, (void*)(p1),(void*)(p2)) # define LOG_EVENT3(name,p1,p2,p3) \ eventLog->log(name, (void*)(p1), (void*)(p2), (void*)(p3)) enum EventStatus { starting, ending, atomic }; struct Event /* no superclass - never allocated individually */ { char* name; // in lprintf format EventStatus status; // for nested events void* args[NPARAM]; }; struct EventLog { Event* buf; // event buffer Event* bufEnd; Event* next; // where the next entry will go int32 nesting; // current nesting depth EventLog(); void init(); Event* nextEvent(Event* e, Event* start, Event* endArg) { if (e + 1 == endArg) return start; else return e + 1; } Event* prevEvent(Event* e, Event* start, Event* endArg) { if (e == start) return endArg - 1; else return e - 1; } void inc() { next = nextEvent(next, buf, bufEnd); } void log(Event* e) { *next = *e; inc(); } void log(char* name) { next->name = name; next->status = atomic; inc(); } void log(char* name, void* p1) { next->name = name; next->status = atomic; next->args[0] = p1; inc(); } void log(char* name, void* p1, void* p2) { next->name = name; next->status = atomic; next->args[0] = p1; next->args[1] = p2; inc(); } void log(char* name, void* p1, void* p2, void* p3) { next->name = name; next->status = atomic; next->args[0] = p1; next->args[1] = p2; next->args[2] = p3; inc(); } void resize(); // resize buffer # ifdef DEBUG void print() { printPartial(bufEnd - buf); } # endif void printPartial(int32 n); }; extern EventLog* eventLog; struct EventMarker : StackObj { // for events which have a duration Event event; Event* here; EventMarker(char* n) { init(n, 0, 0, 0); } EventMarker(char* n, void* p1) { init(n, p1, 0, 0); } EventMarker(char* n, void* p1, void* p2) { init(n, p1, p2, 0); } EventMarker(char* n, void* p1, void* p2, void* p3) { init(n, p1, p2, p3);} void init(char* n, void* p1, void* p2, void* p3) { here = eventLog->next; eventLog->log(n, p1, p2, p3); here->status = starting; event = *here; eventLog->nesting++; } ~EventMarker() { eventLog->nesting--; // optimization to make log less verbose; this isn't totally failproof // but that's ok if (here == eventLog->next - 1) { *here = event; here->status = atomic; // nothing happened inbetween } else { event.status = ending; eventLog->log(&event); } } }; oop printEvent_prim(oop rcvr, oop arg);