3939#include " jfr/writers/jfrTypeWriterHost.hpp"
4040#include " memory/iterator.hpp"
4141#include " memory/resourceArea.hpp"
42+ #include " memory/universe.hpp"
4243#include " oops/instanceKlass.hpp"
4344#include " oops/objArrayKlass.hpp"
4445#include " oops/oop.inline.hpp"
@@ -60,6 +61,7 @@ static JfrArtifactSet* _artifacts = NULL;
6061static JfrArtifactClosure* _subsystem_callback = NULL ;
6162static bool _class_unload = false ;
6263static bool _flushpoint = false ;
64+ static bool _clear_artifacts = false ;
6365
6466// incremented on each rotation
6567static u8 checkpoint_id = 1 ;
@@ -80,6 +82,10 @@ static bool previous_epoch() {
8082 return !current_epoch ();
8183}
8284
85+ static bool is_initial_typeset_for_chunk () {
86+ return _clear_artifacts && !_class_unload;
87+ }
88+
8389static bool is_complete () {
8490 return !_artifacts->has_klass_entries () && current_epoch ();
8591}
@@ -96,6 +102,35 @@ static traceid get_bootstrap_name(bool leakp) {
96102 return create_symbol_id (_artifacts->bootstrap_name (leakp));
97103}
98104
105+ static const char * primitive_name (KlassPtr type_array_klass) {
106+ switch (type_array_klass->name ()->base ()[1 ]) {
107+ case JVM_SIGNATURE_BOOLEAN: return " boolean" ;
108+ case JVM_SIGNATURE_BYTE: return " byte" ;
109+ case JVM_SIGNATURE_CHAR: return " char" ;
110+ case JVM_SIGNATURE_SHORT: return " short" ;
111+ case JVM_SIGNATURE_INT: return " int" ;
112+ case JVM_SIGNATURE_LONG: return " long" ;
113+ case JVM_SIGNATURE_FLOAT: return " float" ;
114+ case JVM_SIGNATURE_DOUBLE: return " double" ;
115+ }
116+ assert (false , " invalid type array klass" );
117+ return NULL ;
118+ }
119+
120+ static Symbol* primitive_symbol (KlassPtr type_array_klass) {
121+ if (type_array_klass == NULL ) {
122+ // void.class
123+ static Symbol* const void_class_name = SymbolTable::probe (" void" , 4 );
124+ assert (void_class_name != NULL , " invariant" );
125+ return void_class_name;
126+ }
127+ const char * const primitive_type_str = primitive_name (type_array_klass);
128+ assert (primitive_type_str != NULL , " invariant" );
129+ Symbol* const primitive_type_sym = SymbolTable::probe (primitive_type_str, (int )strlen (primitive_type_str));
130+ assert (primitive_type_sym != NULL , " invariant" );
131+ return primitive_type_sym;
132+ }
133+
99134template <typename T>
100135static traceid artifact_id (const T* ptr) {
101136 assert (ptr != NULL , " invariant" );
@@ -152,6 +187,11 @@ static s4 get_flags(const T* ptr) {
152187 return ptr->access_flags ().get_flags ();
153188}
154189
190+ // Same as JVM_GetClassModifiers
191+ static u4 get_primitive_flags () {
192+ return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
193+ }
194+
155195static bool is_unsafe_anonymous (const Klass* klass) {
156196 assert (klass != NULL , " invariant" );
157197 return klass->is_instance_klass () && ((const InstanceKlass*)klass)->is_anonymous ();
@@ -260,12 +300,54 @@ static void do_klass(Klass* klass) {
260300 do_implied (klass);
261301}
262302
303+ static traceid primitive_id (KlassPtr array_klass) {
304+ if (array_klass == NULL ) {
305+ // The first klass id is reserved for the void.class.
306+ return MaxJfrEventId + 101 ;
307+ }
308+ // Derive the traceid for a primitive mirror from its associated array klass (+1).
309+ return JfrTraceId::get (array_klass) + 1 ;
310+ }
311+
312+ static void write_primitive (JfrCheckpointWriter* writer, KlassPtr type_array_klass) {
313+ assert (writer != NULL , " invariant" );
314+ assert (_artifacts != NULL , " invariant" );
315+ writer->write (primitive_id (type_array_klass));
316+ writer->write (cld_id (get_cld (Universe::boolArrayKlassObj ()), false ));
317+ writer->write (mark_symbol (primitive_symbol (type_array_klass), false ));
318+ writer->write (package_id (Universe::boolArrayKlassObj (), false ));
319+ writer->write (get_primitive_flags ());
320+ }
321+
322+ static int primitives_count = 9 ;
323+
324+ // A mirror representing a primitive class (e.g. int.class) has no reified Klass*,
325+ // instead it has an associated TypeArrayKlass* (e.g. int[].class).
326+ // We can use the TypeArrayKlass* as a proxy for deriving the id of the primitive class.
327+ // The exception is the void.class, which has neither a Klass* nor a TypeArrayKlass*.
328+ // It will use a reserved constant.
329+ static void do_primitives () {
330+ // Only write the primitive classes once per chunk.
331+ if (is_initial_typeset_for_chunk ()) {
332+ write_primitive (_writer, Universe::boolArrayKlassObj ());
333+ write_primitive (_writer, Universe::byteArrayKlassObj ());
334+ write_primitive (_writer, Universe::charArrayKlassObj ());
335+ write_primitive (_writer, Universe::shortArrayKlassObj ());
336+ write_primitive (_writer, Universe::intArrayKlassObj ());
337+ write_primitive (_writer, Universe::longArrayKlassObj ());
338+ write_primitive (_writer, Universe::singleArrayKlassObj ());
339+ write_primitive (_writer, Universe::doubleArrayKlassObj ());
340+ write_primitive (_writer, NULL ); // void.class
341+ }
342+ }
343+
263344static void do_klasses () {
264345 if (_class_unload) {
265346 ClassLoaderDataGraph::classes_unloading_do (&do_unloaded_klass);
266347 return ;
267348 }
268349 ClassLoaderDataGraph::classes_do (&do_klass);
350+ do_primitives ();
269351}
270352
271353typedef SerializePredicate<KlassPtr> KlassPredicate;
@@ -310,6 +392,11 @@ static bool write_klasses() {
310392 _subsystem_callback = &callback;
311393 do_klasses ();
312394 }
395+ if (is_initial_typeset_for_chunk ()) {
396+ // Because the set of primitives is written outside the callback,
397+ // their count is not automatically incremented.
398+ kw.add (primitives_count);
399+ }
313400 if (is_complete ()) {
314401 return false ;
315402 }
@@ -887,10 +974,8 @@ static void write_symbols() {
887974 _artifacts->tally (sw);
888975}
889976
890- static bool clear_artifacts = false ;
891-
892977void JfrTypeSet::clear () {
893- clear_artifacts = true ;
978+ _clear_artifacts = true ;
894979}
895980
896981typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits;
@@ -904,8 +989,10 @@ static size_t teardown() {
904989 assert (_writer != NULL , " invariant" );
905990 ClearKlassAndMethods clear (_writer);
906991 _artifacts->iterate_klasses (clear);
907- JfrTypeSet::clear () ;
992+ _clear_artifacts = true ;
908993 ++checkpoint_id;
994+ } else {
995+ _clear_artifacts = false ;
909996 }
910997 return total_count;
911998}
@@ -917,9 +1004,8 @@ static void setup(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer
9171004 if (_artifacts == NULL ) {
9181005 _artifacts = new JfrArtifactSet (class_unload);
9191006 } else {
920- _artifacts->initialize (class_unload, clear_artifacts );
1007+ _artifacts->initialize (class_unload, _clear_artifacts );
9211008 }
922- clear_artifacts = false ;
9231009 assert (_artifacts != NULL , " invariant" );
9241010 assert (!_artifacts->has_klass_entries (), " invariant" );
9251011}
0 commit comments