Hi again, I have created an updated webrev02 for the feedback I have gotten so far. In addition, I have added a few improvements to the original suggestion.
Updated Webrev02: http://cr.openjdk.java.net/~mgronlun/8028128/webrev02/ Original Webrev01: http://cr.openjdk.java.net/~mgronlun/8028128/webrev01/ Bug: https://bugs.openjdk.java.net/browse/JDK-8028128 Thanks a lot for your help/patience in reviewing this large change - very much appreciated. Cheers Markus Description of deltas/updates to Webrev02 compared to Webrev01: // updates based on feedback utilities/ticks.inline.hpp // removed functions comparing against jlong(s) - #63 inline bool operator==(const Ticks& lhs, jlong compare_value) { - #64 return lhs.value() == compare_value; - #65 } - #89 inline bool operator!=(const Ticks& lhs, jlong compare_value) { - #90 return lhs.value() != compare_value; - #91 } // updated to gt signs for operator<= functions - #52 return !operator<(lhs, rhs); + #52 return !operator >(lhs, rhs); - #98 return !operator<(lhs,rhs); + #98 return !operator>(lhs,rhs); // thanks to Vitaly Davidovich. share/vm/gc_implementation/gcTimer.hpp // removed default parameter for report_gc_phase_* functions - #114 void report_gc_phase_start(const char* name, const Ticks& time = Ticks::now()); + #114 void report_gc_phase_start(const char* name, const Ticks& time); - #115 void report_gc_phase_end(const Ticks& time = Ticks::now()); + #115 void report_gc_phase_end(const Ticks& time); - #145 void register_gc_phase_start(const char* name, const Ticks& time = Ticks::now()); + #145 void register_gc_phase_start(const char* name, const Ticks& time); - #146 void register_gc_phase_end(const Ticks& time = Ticks::now()); + #146 void register_gc_phase_end(const Ticks& time); // thanks to Per Liden. // // // // Additional changes compared to webrev01 (delta) // webrev01 still allows a user to pass in a jlong (knowingly and/or unknowingly) for event.starttime() and event.endtime(). For example: event.set_endtime(os::elapsed_counter()); // direct call using os::elapsed_counter() This can be avoided by increasing encapsulation: src/share/vm/trace/traceEvent.hpp: set_starttime(const TracingTime& time) // remove default parameter and make protected set_endtime(const TracingTime& time) // remove default parameter and make protected Now, the only visible external API for setting the start and/or endtime of an event is by passing a "Ticks" type (a compiler enforced constraint): Using the same example as above, now if attempting to pass a jlong, like a direct call using os::elapsed_counter(), this now yields (at compile time): >..\..\src\share\vm\gc_implementation\shared\gcTraceSend.cpp(63): error C2248: >'TraceEvent<T>::set_endtime' : cannot access protected member declared in >class 'TraceEvent<T>' In order to make these functions protected, i have also had to update the class loader events in SystemDictionary and ClassLoaderDataGraph: share/vm/classfile/SystemDictionary.hpp: // remove include file: - #34 #include "trace/traceTime.hpp" + #80 forward declare class Ticks; // update the signature - #640 static void post_class_load_event(const TracingTime& start_time, instanceKlassHandle k, Handle initiating_loader); + #640 static void post_class_load_event(const Ticks& start_time, instanceKlassHandle k, Handle initiating_loader); share/vm/classfile/SystemDictionary.cpp: // added include files +#58 #include "utilities/macros.hpp" +#59 #include "utilities/ticks.hpp" // removed old include file: - #61 #include "trace/traceMacros.hpp" // updated type - #601 TracingTime class_load_start_time = Tracing::time(); + #601 Ticks class_load_start_time = Ticks::now(); // updated type - #1009 TracingTime class_load_start_time = Tracing::time(); + #1009 Ticks class_load_start_time = Ticks::now(); // updated signature - #2668 void SystemDictionary::post_class_load_event(TracingTime start_time, instanceKlassHandle k, Handle initiating_loader) + #2668 void SystemDictionary::post_class_load_event(const Ticks& start_time, instanceKlassHandle k, Handle initiating_loader) // removed setting the endtime - #2674 event.set_endtime(Tracing::time()); src/share/vm/classfile/classLoaderData.hpp: // update include - #36 #include "trace/traceTime.hpp" + #36 #include "utilities/ticks.hpp" // updated type for _class_unload_time; - #101 static TracingTime _class_unload_time; + #101 static Ticks _class_unload_time; src/share/vm/classfile/classLoaderData.cpp: + #65 #include "utilities/macros.hpp" // updated timestamp - #757 _class_unload_time = Tracing::time(); + #757 _class_unload_time = Ticks::now(); // updated type definition - #835 TracingTime ClassLoaderDataGraph::_class_unload_time; + #835 Ticks ClassLoaderDataGraph::_class_unload_time; src/share/vm/trace/traceEventClasses.xls: // update the !INCLUDE_TRACE stubs - #59 void set_starttime(jlong time) const {} - #60 void set_endtime(jlong time) const {} + #59 void set_starttime(const Ticks& time) {} + #59 void set_endtime(const Ticks& time) {} Thanks Markus > > Greetings, > > Kindly asking for reviews for the following changeset: > > Webrev: http://cr.openjdk.java.net/~mgronlun/8028128/webrev01/ > > Bug: https://bugs.openjdk.java.net/browse/JDK-8028128 > > *Description:* > > Currently, when working with counter based data, the primary data type > representation in the VM are raw jlong's. jlong's are employed to > represent both: > > 1. a single instance in time, for example a "now" timestamp 2. a time > duration, a timespan, for example the duration between "now" - "then" > > Having a raw jlong type represent both of these shifts the > responsibility to the programmer to always ensure the correct validity > of the counter data, without any assistance either at compile time or > at runtime. > > The event based tracing framework relies heavily on counter based data > in order to keep track of time and timing related information and we > have seen counter data errors where the representation sent to the > tracing framework has submitted the wrong time, i.e. a timespan when a > time instant was expected and vice versa. > > We should therefore add an alternative to jlongs for representing > counter based data. We should enlist the help of the type system to > enforce the correct data types at compile time as well as introduce > strong runtime asserts in order to help with the correct usage of time > and to reduce the number of potential bugs. > > I will therefore add two new types in src/share/vm/utilities: > > 1. "Ticks" - represents a single counter based timestamp, a single > instance in time. > 2. "Tickspan" - represents a counter based duration, a timespan, > between two "Ticks" > > Please see the added files: > > -src/share/vm/utilities/ticks.hpp > > -src/share/vm/utilities/ticks.inline.hpp > > -src/share/vm/utilities/ticks.cpp > > I have also updated some of the existing event based tracing "event > sites" to employ usage of these new types as well as updated a few > places in the event based tracing framework implementation to > accommodate these types. > > *Testing completed:* > > nsk.stress.testlist (UTE/Aurora) > > GC nightlies (Aurora) > > gc/gctests/* (UTE/Aurora) > > nsk.gc.testlist (UTE/Aurora) > > SpecJBB2013 (no regression) > > SpecJBB2005 (no regression) > > Kitchensink (locally Windows) runs for +> 9 days (still running.) > > Thanks in advance > Markus >