27 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp" |
27 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp" |
28 #include "jfr/recorder/repository/jfrChunkWriter.hpp" |
28 #include "jfr/recorder/repository/jfrChunkWriter.hpp" |
29 #include "oops/klass.inline.hpp" |
29 #include "oops/klass.inline.hpp" |
30 #include "oops/oop.inline.hpp" |
30 #include "oops/oop.inline.hpp" |
31 #include "oops/typeArrayOop.inline.hpp" |
31 #include "oops/typeArrayOop.inline.hpp" |
32 #include "runtime/semaphore.hpp" |
|
33 #include "runtime/thread.inline.hpp" |
32 #include "runtime/thread.inline.hpp" |
34 |
33 |
35 static jbyteArray _metadata_blob = NULL; |
34 static jbyteArray metadata_blob = NULL; |
36 static Semaphore metadata_mutex_semaphore(1); |
35 static u8 metadata_id = 0; |
|
36 static u8 last_metadata_id = 0; |
37 |
37 |
38 void JfrMetadataEvent::lock() { |
38 static void write_metadata_blob(JfrChunkWriter& chunkwriter) { |
39 metadata_mutex_semaphore.wait(); |
39 assert(metadata_blob != NULL, "invariant"); |
|
40 const typeArrayOop arr = (typeArrayOop)JfrJavaSupport::resolve_non_null(metadata_blob); |
|
41 assert(arr != NULL, "invariant"); |
|
42 const int length = arr->length(); |
|
43 const Klass* const k = arr->klass(); |
|
44 assert(k != NULL && k->is_array_klass(), "invariant"); |
|
45 const TypeArrayKlass* const byte_arr_klass = TypeArrayKlass::cast(k); |
|
46 const jbyte* const data_address = arr->byte_at_addr(0); |
|
47 chunkwriter.write_unbuffered(data_address, length); |
40 } |
48 } |
41 |
49 |
42 void JfrMetadataEvent::unlock() { |
50 void JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) { |
43 metadata_mutex_semaphore.signal(); |
51 assert(chunkwriter.is_valid(), "invariant"); |
44 } |
52 if (last_metadata_id == metadata_id && chunkwriter.has_metadata()) { |
45 |
53 return; |
46 static void write_metadata_blob(JfrChunkWriter& chunkwriter, jbyteArray metadata_blob) { |
|
47 if (metadata_blob != NULL) { |
|
48 const typeArrayOop arr = (typeArrayOop)JfrJavaSupport::resolve_non_null(metadata_blob); |
|
49 assert(arr != NULL, "invariant"); |
|
50 const int length = arr->length(); |
|
51 const Klass* const k = arr->klass(); |
|
52 assert(k != NULL && k->is_array_klass(), "invariant"); |
|
53 const TypeArrayKlass* const byte_arr_klass = TypeArrayKlass::cast(k); |
|
54 const jbyte* const data_address = arr->byte_at_addr(0); |
|
55 chunkwriter.write_unbuffered(data_address, length); |
|
56 } |
54 } |
57 } |
|
58 |
|
59 // the semaphore is assumed to be locked (was locked previous safepoint) |
|
60 size_t JfrMetadataEvent::write(JfrChunkWriter& chunkwriter, jlong metadata_offset) { |
|
61 assert(chunkwriter.is_valid(), "invariant"); |
|
62 assert(chunkwriter.current_offset() == metadata_offset, "invariant"); |
|
63 // header |
55 // header |
64 chunkwriter.reserve(sizeof(u4)); |
56 const int64_t metadata_offset = chunkwriter.reserve(sizeof(u4)); |
65 chunkwriter.write<u8>(EVENT_METADATA); // ID 0 |
57 chunkwriter.write<u8>(EVENT_METADATA); // ID 0 |
66 // time data |
58 // time data |
67 chunkwriter.write(JfrTicks::now()); |
59 chunkwriter.write(JfrTicks::now()); |
68 chunkwriter.write((u8)0); // duration |
60 chunkwriter.write((u8)0); // duration |
69 chunkwriter.write((u8)0); // metadata id |
61 chunkwriter.write(metadata_id); // metadata id |
70 write_metadata_blob(chunkwriter, _metadata_blob); // payload |
62 write_metadata_blob(chunkwriter); // payload |
71 unlock(); // open up for java to provide updated metadata |
|
72 // fill in size of metadata descriptor event |
63 // fill in size of metadata descriptor event |
73 const jlong size_written = chunkwriter.current_offset() - metadata_offset; |
64 const int64_t size_written = chunkwriter.current_offset() - metadata_offset; |
74 chunkwriter.write_padded_at_offset((u4)size_written, metadata_offset); |
65 chunkwriter.write_padded_at_offset((u4)size_written, metadata_offset); |
75 return size_written; |
66 chunkwriter.set_last_metadata_offset(metadata_offset); |
|
67 last_metadata_id = metadata_id; |
76 } |
68 } |
77 |
69 |
78 void JfrMetadataEvent::update(jbyteArray metadata) { |
70 void JfrMetadataEvent::update(jbyteArray metadata) { |
79 JavaThread* thread = (JavaThread*)Thread::current(); |
71 JavaThread* thread = (JavaThread*)Thread::current(); |
80 assert(thread->is_Java_thread(), "invariant"); |
72 assert(thread->is_Java_thread(), "invariant"); |
81 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread)); |
73 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread)); |
82 lock(); |
74 if (metadata_blob != NULL) { |
83 if (_metadata_blob != NULL) { |
75 JfrJavaSupport::destroy_global_jni_handle(metadata_blob); |
84 JfrJavaSupport::destroy_global_jni_handle(_metadata_blob); |
|
85 } |
76 } |
86 const oop new_desc_oop = JfrJavaSupport::resolve_non_null(metadata); |
77 const oop new_desc_oop = JfrJavaSupport::resolve_non_null(metadata); |
87 _metadata_blob = new_desc_oop != NULL ? (jbyteArray)JfrJavaSupport::global_jni_handle(new_desc_oop, thread) : NULL; |
78 assert(new_desc_oop != NULL, "invariant"); |
88 unlock(); |
79 metadata_blob = (jbyteArray)JfrJavaSupport::global_jni_handle(new_desc_oop, thread); |
|
80 ++metadata_id; |
89 } |
81 } |