Skip to content

Commit

Permalink
Trivial prototype of JFR context
Browse files Browse the repository at this point in the history
  • Loading branch information
jbachorik committed Oct 18, 2023
1 parent 1e25540 commit 6c1eed1
Show file tree
Hide file tree
Showing 35 changed files with 1,044 additions and 41 deletions.
7 changes: 6 additions & 1 deletion make/src/classes/build/tools/jfr/GenerateJfrFiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ static class TypeElement {
boolean isEvent;
boolean isRelation;
boolean supportStruct = false;
boolean withContext = false;
String commitState;
public boolean primitive;

Expand All @@ -227,6 +228,7 @@ public void persist(DataOutputStream pos) throws IOException {
pos.writeLong(id);
pos.writeBoolean(isEvent);
pos.writeBoolean(isRelation);
pos.writeBoolean(withContext);
}
}

Expand Down Expand Up @@ -524,6 +526,7 @@ public void startElement(String uri, String localName, String qName, Attributes
currentType.commitState = getString(attributes, "commitState");
currentType.isEvent = "Event".equals(qName);
currentType.isRelation = "Relation".equals(qName);
currentType.withContext = getBoolean(attributes, "withContext", false);
break;
case "Field":
currentField = new FieldElement(metadata);
Expand Down Expand Up @@ -655,7 +658,8 @@ private static void printJfrEventControlHpp(Metadata metadata, File outputFile)
out.write(" u1 stacktrace;");
out.write(" u1 enabled;");
out.write(" u1 large;");
out.write(" u1 pad[5]; // Because GCC on linux ia32 at least tries to pack this.");
out.write(" u1 context;");
out.write(" u1 pad[4]; // Because GCC on linux ia32 at least tries to pack this.");
out.write("};");
out.write("");
out.write("union JfrNativeSettings {");
Expand Down Expand Up @@ -860,6 +864,7 @@ private static void printEvent(Printer out, TypeElement event, boolean empty) {
out.write(" static const bool isInstant = " + !event.startTime + ";");
out.write(" static const bool hasCutoff = " + event.cutoff + ";");
out.write(" static const bool hasThrottle = " + event.throttle + ";");
out.write(" static const bool hasContext = " + event.withContext + ";");
out.write(" static const bool isRequestable = " + !event.period.isEmpty() + ";");
out.write(" static const JfrEventId eventId = Jfr" + event.name + "Event;");
out.write("");
Expand Down
15 changes: 15 additions & 0 deletions src/hotspot/share/jfr/jni/jfrJniMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "jfr/instrumentation/jfrEventClassTransformer.hpp"
#include "jfr/instrumentation/jfrJvmtiAgent.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/support/jfrContext.hpp"
#include "jfr/support/jfrJdkJfrEvent.hpp"
#include "jfr/support/jfrKlassUnloading.hpp"
#include "jfr/utilities/jfrJavaLog.hpp"
Expand Down Expand Up @@ -397,3 +398,17 @@ JVM_END
JVM_ENTRY_NO_ENV(void, jfr_emit_data_loss(JNIEnv* env, jclass jvm, jlong bytes))
EventDataLoss::commit(bytes, min_jlong);
JVM_END

NO_TRANSITION(void, jfr_set_used_context_size(JNIEnv* env, jclass jvm, jint size))
JfrContext::set_used_context_size(size);
NO_TRANSITION_END

NO_TRANSITION(jboolean, jfr_is_context_enabled(JNIEnv* env, jclass jvmf))
return JfrOptionSet::is_context_enabled();
NO_TRANSITION_END

NO_TRANSITION(jobject, jfr_get_thread_context_buffer(JNIEnv* env, jclass jvm))
uint64_t* data;
uint8_t size = JfrContext::get_context(&data);
return env->NewDirectByteBuffer((void*)data, (jlong) size * 8);
NO_TRANSITION_END
4 changes: 4 additions & 0 deletions src/hotspot/share/jfr/jni/jfrJniMethod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ jlong JNICALL jfr_host_total_memory(JNIEnv* env, jclass jvm);

void JNICALL jfr_emit_data_loss(JNIEnv* env, jclass jvm, jlong bytes);

void JNICALL jfr_set_used_context_size(JNIEnv* env, jclass jvm, jint size);
jboolean JNICALL jfr_is_context_enabled(JNIEnv* env, jclass jvm);
jobject JNICALL jfr_get_thread_context_buffer(JNIEnv* env, jclass jvm);

#ifdef __cplusplus
}
#endif
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
(char*)"isInstrumented", (char*)"(Ljava/lang/Class;)Z", (void*) jfr_is_class_instrumented,
(char*)"isContainerized", (char*)"()Z", (void*) jfr_is_containerized,
(char*)"hostTotalMemory", (char*)"()J", (void*) jfr_host_total_memory,
(char*)"emitDataLoss", (char*)"(J)V", (void*)jfr_emit_data_loss
(char*)"emitDataLoss", (char*)"(J)V", (void*)jfr_emit_data_loss,
(char*)"setUsedContextSize", (char*)"(I)V", (void*)jfr_set_used_context_size,
(char*)"isContextEnabled", (char*)"()Z", (void*)jfr_is_context_enabled,
(char*)"getThreadContextBuffer0", (char*)"()Ljava/lang/Object;", (void*)jfr_get_thread_context_buffer
};

const size_t method_array_length = sizeof(method) / sizeof(JNINativeMethod);
Expand Down
12 changes: 6 additions & 6 deletions src/hotspot/share/jfr/metadata/metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,28 +89,28 @@
<Field type="Thread" name="thread" label="Java Thread" />
</Event>

<Event name="ThreadPark" category="Java Application" label="Java Thread Park" thread="true" stackTrace="true">
<Event name="ThreadPark" category="Java Application" label="Java Thread Park" thread="true" stackTrace="true" withContext="true">
<Field type="Class" name="parkedClass" label="Class Parked On" />
<Field type="long" contentType="nanos" name="timeout" label="Park Timeout" />
<Field type="long" contentType="epochmillis" name="until" label="Park Until" />
<Field type="ulong" contentType="address" name="address" label="Address of Object Parked" relation="JavaMonitorAddress" />
</Event>

<Event name="JavaMonitorEnter" category="Java Application" label="Java Monitor Blocked" thread="true" stackTrace="true">
<Event name="JavaMonitorEnter" category="Java Application" label="Java Monitor Blocked" thread="true" stackTrace="true" withContext="true">
<Field type="Class" name="monitorClass" label="Monitor Class" />
<Field type="Thread" name="previousOwner" label="Previous Monitor Owner" />
<Field type="ulong" contentType="address" name="address" label="Monitor Address" relation="JavaMonitorAddress" />
</Event>

<Event name="JavaMonitorWait" category="Java Application" label="Java Monitor Wait" description="Waiting on a Java monitor" thread="true" stackTrace="true">
<Event name="JavaMonitorWait" category="Java Application" label="Java Monitor Wait" description="Waiting on a Java monitor" thread="true" stackTrace="true" withContext="true">
<Field type="Class" name="monitorClass" label="Monitor Class" description="Class of object waited on" />
<Field type="Thread" name="notifier" label="Notifier Thread" description="Notifying Thread" />
<Field type="long" contentType="millis" name="timeout" label="Timeout" description="Maximum wait time" />
<Field type="boolean" name="timedOut" label="Timed Out" description="Wait has been timed out" />
<Field type="ulong" contentType="address" name="address" label="Monitor Address" description="Address of object waited on" relation="JavaMonitorAddress" />
</Event>

<Event name="JavaMonitorInflate" category="Java Application" label="Java Monitor Inflated" thread="true" stackTrace="true">
<Event name="JavaMonitorInflate" category="Java Application" label="Java Monitor Inflated" thread="true" stackTrace="true" withContext="true">
<Field type="Class" name="monitorClass" label="Monitor Class" />
<Field type="ulong" contentType="address" name="address" label="Monitor Address" relation="JavaMonitorAddress" />
<Field type="InflateCause" name="cause" label="Monitor Inflation Cause" description="Cause of inflation" />
Expand Down Expand Up @@ -727,7 +727,7 @@
<Field type="ulong" contentType="bytes" name="allocationSize" label="Allocation Size" />
</Event>

<Event name="ObjectAllocationSample" category="Java Application" label="Object Allocation Sample" thread="true" stackTrace="true" startTime="false" throttle="true">
<Event name="ObjectAllocationSample" category="Java Application" label="Object Allocation Sample" thread="true" stackTrace="true" startTime="false" throttle="true" withContext="true">
<Field type="Class" name="objectClass" label="Object Class" description="Class of allocated object" />
<Field type="long" contentType="bytes" name="weight" label="Sample Weight"
description="The relative weight of the sample. Aggregating the weights for a large number of samples, for a particular class, thread or stack trace, gives a statistically accurate representation of the allocation pressure" />
Expand Down Expand Up @@ -915,7 +915,7 @@
</Event>

<Event name="ExecutionSample" category="Java Virtual Machine, Profiling" label="Method Profiling Sample" description="Snapshot of a threads state"
period="everyChunk">
period="everyChunk" withContext="true">
<Field type="Thread" name="sampledThread" label="Thread" />
<Field type="StackTrace" name="stackTrace" label="Stack Trace" />
<Field type="ThreadState" name="state" label="Thread State" />
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jfr/metadata/metadata.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<xs:attribute name="period" type="periodType" use="optional" />
<xs:attribute name="cutoff" type="xs:boolean" use="optional" />
<xs:attribute name="throttle" type="xs:boolean" use="optional" />
<xs:attribute name="withContext" type="xs:boolean" use="optional" />
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" name="Type">
Expand Down
8 changes: 8 additions & 0 deletions src/hotspot/share/jfr/recorder/service/jfrEvent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "jfr/recorder/jfrEventSetting.inline.hpp"
#include "jfr/recorder/service/jfrEventThrottler.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
#include "jfr/support/jfrContext.hpp"
#include "jfr/utilities/jfrTime.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "jfr/writers/jfrNativeEventWriter.hpp"
Expand Down Expand Up @@ -243,6 +244,13 @@ class JfrEvent {
if (T::hasStackTrace) {
writer.write(sid);
}
if (T::hasContext) {
uint64_t* data;
uint8_t ctx_len = JfrContext::get_context(&data);
for (uint8_t i = 0; i < ctx_len; i++) {
writer.write(data[i]);
}
}
// Payload.
static_cast<T*>(this)->writeData(writer);
return writer.end_event_write(large_size) > 0;
Expand Down
7 changes: 7 additions & 0 deletions src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class JfrOptionSet : public AllStatic {
static u4 _stack_depth;
static jboolean _retransform;
static jboolean _sample_protection;
static jboolean _context;

static bool initialize(JavaThread* thread);
static bool configure(TRAPS);
Expand Down Expand Up @@ -74,6 +75,12 @@ class JfrOptionSet : public AllStatic {
static bool allow_event_retransforms();
static bool sample_protection();
DEBUG_ONLY(static void set_sample_protection(jboolean protection);)
static void enable_context() {
_context = true;
}
static bool is_context_enabled() {
return true; // _context;
}

static bool parse_flight_recorder_option(const JavaVMOption** option, char* delimiter);
static bool parse_start_flight_recording_option(const JavaVMOption** option, char* delimiter);
Expand Down
67 changes: 67 additions & 0 deletions src/hotspot/share/jfr/support/jfrContext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "precompiled.hpp"
#include "jfrContext.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/thread.hpp"

#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

uint8_t JfrContext::_size = 0;

JfrThreadLocal* getThreadLocal() {
Thread* thrd = Thread::current_or_null_safe();
return thrd != nullptr ? thrd->jfr_thread_local() : nullptr;
}

void JfrContext::set_used_context_size(uint8_t size) {
assert(size <= 8, "max context size is 8");
_size = size;
}

uint64_t JfrContext::get_and_set_context(uint8_t idx, uint64_t value) {
JfrThreadLocal* jfrTLocal = getThreadLocal();
if (jfrTLocal != nullptr) {
uint64_t old_value = 0;
jfrTLocal->get_context(&old_value, 1, idx);
jfrTLocal->set_context(&value, 1, idx);
return old_value;
}
return 0;
}

uint8_t JfrContext::get_all_context(uint64_t* data, uint8_t length) {
JfrThreadLocal* jfrTLocal = getThreadLocal();
if (jfrTLocal != nullptr) {
return jfrTLocal->get_context(data, MIN(_size, length), 0);
}

return 0;
}

uint8_t JfrContext::get_context(uint64_t** data) {
void* buffer = get_thread_context_buffer();
if (buffer) {
*data = (uint64_t*) buffer;
return _size;
}
return 0;
}

uint8_t JfrContext::set_all_context(uint64_t* data, uint8_t length) {
JfrThreadLocal* jfrTLocal = getThreadLocal();
if (jfrTLocal != nullptr) {
jfrTLocal->set_context(data, MIN(_size, length), 0);
return length;
}

return 0;
}

void* JfrContext::get_thread_context_buffer() {
JfrThreadLocal* jfrTLocal = getThreadLocal();
if (jfrTLocal != nullptr) {
return (void*)jfrTLocal->get_context_buffer();
}
return nullptr;
}
20 changes: 20 additions & 0 deletions src/hotspot/share/jfr/support/jfrContext.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef SHARE_JFR_SUPPORT_CONTEXT_HPP
#define SHARE_JFR_SUPPORT_CONTEXT_HPP

#include "memory/allStatic.hpp"
#include "utilities/globalDefinitions.hpp"

class JfrContext : AllStatic {
private:
static uint8_t _size;
public:
static void set_used_context_size(uint8_t size);
static inline uint8_t get_used_context_size() { return _size; }
static uint64_t get_and_set_context(uint8_t idx, uint64_t value);
static uint8_t get_all_context(uint64_t* data, uint8_t length);
static uint8_t set_all_context(uint64_t* data, uint8_t length);
static uint8_t get_context(uint64_t** data);
static void* get_thread_context_buffer();
};

#endif // SHARE_JFR_SUPPORT_CONTEXT_HPP
24 changes: 24 additions & 0 deletions src/hotspot/share/jfr/support/jfrThreadLocal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class JfrThreadLocal {
bool _vthread;
bool _notified;
bool _dead;
uint64_t _context[8] {0};
uint8_t _context_size = 0;

JfrBuffer* install_native_buffer() const;
JfrBuffer* install_java_buffer() const;
Expand Down Expand Up @@ -267,6 +269,28 @@ class JfrThreadLocal {
return _dead;
}

// context operations
void set_context(uint64_t* context, uint8_t len, uint8_t offset) {
assert(len > 0, "setting empty context");
assert(len + offset < 8, "context capacity");
memcpy(_context + offset, context, len * sizeof(uint64_t));
uint8_t new_size = len + offset;
_context_size = new_size > _context_size ? new_size : _context_size;
}

uint8_t get_context(uint64_t* context, uint8_t len, uint8_t offset) {
int limit = (len + offset < 8) ? len : (len - offset);
len = limit < 0 ? 0 : limit;
assert(len >= 0, "getting empty context");
assert(len + offset <= 8, "context capacity");
memcpy(context, _context + offset, len * sizeof(uint64_t));
return len;
}

uint64_t* get_context_buffer() {
return _context;
}

bool is_excluded() const;
bool is_included() const;
static bool is_excluded(const Thread* thread);
Expand Down
Loading

0 comments on commit 6c1eed1

Please sign in to comment.