8252898: remove bulk registration of JFR CompilerPhaseType names
Reviewed-by: kvn, jcm
This commit is contained in:
parent
779d2c34ae
commit
b05290aaea
@ -601,19 +601,16 @@ void register_jfr_phasetype_serializer(CompilerType compiler_type) {
|
|||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
static bool first_registration = true;
|
static bool first_registration = true;
|
||||||
if (compiler_type == compiler_jvmci) {
|
if (compiler_type == compiler_jvmci) {
|
||||||
// register serializer, phases will be added later lazily.
|
CompilerEvent::PhaseEvent::get_phase_id("NOT_A_PHASE_NAME", false, false, false);
|
||||||
GrowableArray<const char*>* jvmci_phase_names = new GrowableArray<const char*>(1);
|
|
||||||
jvmci_phase_names->append("NOT_A_PHASE_NAME");
|
|
||||||
CompilerEvent::PhaseEvent::register_phases(jvmci_phase_names);
|
|
||||||
first_registration = false;
|
first_registration = false;
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
} else if (compiler_type == compiler_c2) {
|
} else if (compiler_type == compiler_c2) {
|
||||||
assert(first_registration, "invariant"); // c2 must be registered first.
|
assert(first_registration, "invariant"); // c2 must be registered first.
|
||||||
GrowableArray<const char*>* c2_phase_names = new GrowableArray<const char*>(PHASE_NUM_TYPES);
|
GrowableArray<const char*>* c2_phase_names = new GrowableArray<const char*>(PHASE_NUM_TYPES);
|
||||||
for (int i = 0; i < PHASE_NUM_TYPES; i++) {
|
for (int i = 0; i < PHASE_NUM_TYPES; i++) {
|
||||||
c2_phase_names->append(CompilerPhaseTypeHelper::to_string((CompilerPhaseType)i));
|
const char* phase_name = CompilerPhaseTypeHelper::to_string((CompilerPhaseType) i);
|
||||||
|
CompilerEvent::PhaseEvent::get_phase_id(phase_name, false, false, false);
|
||||||
}
|
}
|
||||||
CompilerEvent::PhaseEvent::register_phases(c2_phase_names);
|
|
||||||
first_registration = false;
|
first_registration = false;
|
||||||
#endif // COMPILER2
|
#endif // COMPILER2
|
||||||
}
|
}
|
||||||
|
@ -34,67 +34,84 @@
|
|||||||
class PhaseTypeGuard : public StackObj {
|
class PhaseTypeGuard : public StackObj {
|
||||||
private:
|
private:
|
||||||
static Semaphore _mutex_semaphore;
|
static Semaphore _mutex_semaphore;
|
||||||
|
bool _enabled;
|
||||||
public:
|
public:
|
||||||
PhaseTypeGuard() {
|
PhaseTypeGuard(bool enabled=true) {
|
||||||
_mutex_semaphore.wait();
|
if (enabled) {
|
||||||
|
_mutex_semaphore.wait();
|
||||||
|
_enabled = true;
|
||||||
|
} else {
|
||||||
|
_enabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
~PhaseTypeGuard() {
|
~PhaseTypeGuard() {
|
||||||
_mutex_semaphore.signal();
|
if (_enabled) {
|
||||||
|
_mutex_semaphore.signal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Semaphore PhaseTypeGuard::_mutex_semaphore(1);
|
Semaphore PhaseTypeGuard::_mutex_semaphore(1);
|
||||||
|
|
||||||
static void write_phases(JfrCheckpointWriter& writer, u4 base_idx, GrowableArray<const char*>* phases) {
|
// Table for mapping compiler phases names to int identifiers.
|
||||||
assert(phases != NULL, "invariant");
|
|
||||||
assert(phases->is_nonempty(), "invariant");
|
|
||||||
const u4 nof_entries = phases->length();
|
|
||||||
writer.write_count(nof_entries);
|
|
||||||
for (u4 i = 0; i < nof_entries; i++) {
|
|
||||||
writer.write_key(base_idx + i);
|
|
||||||
writer.write(phases->at(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GrowableArray<const char*>* phase_names = NULL;
|
static GrowableArray<const char*>* phase_names = NULL;
|
||||||
|
|
||||||
class CompilerPhaseTypeConstant : public JfrSerializer {
|
class CompilerPhaseTypeConstant : public JfrSerializer {
|
||||||
public:
|
public:
|
||||||
void serialize(JfrCheckpointWriter& writer) {
|
void serialize(JfrCheckpointWriter& writer) {
|
||||||
PhaseTypeGuard guard;
|
PhaseTypeGuard guard;
|
||||||
write_phases(writer, 0, phase_names);
|
assert(phase_names != NULL, "invariant");
|
||||||
|
assert(phase_names->is_nonempty(), "invariant");
|
||||||
|
const u4 nof_entries = phase_names->length();
|
||||||
|
writer.write_count(nof_entries);
|
||||||
|
for (u4 i = 0; i < nof_entries; i++) {
|
||||||
|
writer.write_key(i);
|
||||||
|
writer.write(phase_names->at(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function provides support for adding dynamic entries to JFR type CompilerPhaseType.
|
static int lookup_phase(const char* phase_name) {
|
||||||
// The mapping for CompilerPhaseType is maintained as growable array phase_names.
|
for (int i = 0; i < phase_names->length(); i++) {
|
||||||
// The serializer CompilerPhaseTypeConstant must be registered with JFR at vm init.
|
const char* name = phase_names->at(i);
|
||||||
// Registration of new phase names creates mapping, serialize it for current chunk and registers its serializer with JFR if it is not already done.
|
if (strcmp(name, phase_name) == 0) {
|
||||||
int CompilerEvent::PhaseEvent::register_phases(GrowableArray<const char*>* new_phases) {
|
return i;
|
||||||
int idx = -1;
|
}
|
||||||
if (new_phases == NULL || new_phases->is_empty()) {
|
|
||||||
return idx;
|
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompilerEvent::PhaseEvent::get_phase_id(const char* phase_name, bool may_exist, bool use_strdup, bool sync) {
|
||||||
|
int index;
|
||||||
bool register_jfr_serializer = false;
|
bool register_jfr_serializer = false;
|
||||||
{
|
{
|
||||||
PhaseTypeGuard guard;
|
PhaseTypeGuard guard(sync);
|
||||||
if (phase_names == NULL) {
|
if (phase_names == NULL) {
|
||||||
phase_names = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<const char*>(100, mtCompiler);
|
phase_names = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<const char*>(100, mtCompiler);
|
||||||
register_jfr_serializer = true;
|
register_jfr_serializer = true;
|
||||||
|
} else if (may_exist) {
|
||||||
|
index = lookup_phase(phase_name);
|
||||||
|
if (index != -1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert((index = lookup_phase(phase_name)) == -1, "phase name \"%s\" already registered: %d", phase_name, index);
|
||||||
}
|
}
|
||||||
idx = phase_names->length();
|
|
||||||
phase_names->appendAll(new_phases);
|
index = phase_names->length();
|
||||||
guarantee(phase_names->length() < 256, "exceeds maximum supported phases");
|
phase_names->append(use_strdup ? strdup(phase_name) : phase_name);
|
||||||
}
|
}
|
||||||
if (register_jfr_serializer) {
|
if (register_jfr_serializer) {
|
||||||
JfrSerializer::register_serializer(TYPE_COMPILERPHASETYPE, false, new CompilerPhaseTypeConstant());
|
JfrSerializer::register_serializer(TYPE_COMPILERPHASETYPE, false, new CompilerPhaseTypeConstant());
|
||||||
} else if (Jfr::is_recording()) {
|
} else if (Jfr::is_recording()) {
|
||||||
// serialize new_phases.
|
// serialize new phase.
|
||||||
JfrCheckpointWriter writer;
|
JfrCheckpointWriter writer;
|
||||||
writer.write_type(TYPE_COMPILERPHASETYPE);
|
writer.write_type(TYPE_COMPILERPHASETYPE);
|
||||||
write_phases(writer, idx, new_phases);
|
writer.write_count(1);
|
||||||
|
writer.write_key(index);
|
||||||
|
writer.write(phase_name);
|
||||||
}
|
}
|
||||||
return idx;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerEvent::CompilationEvent::post(EventCompilation& event, int compile_id, CompilerType compiler_type, Method* method, int compile_level, bool success, bool is_osr, int code_size, int inlined_bytecodes) {
|
void CompilerEvent::CompilationEvent::post(EventCompilation& event, int compile_id, CompilerType compiler_type, Method* method, int compile_level, bool success, bool is_osr, int code_size, int inlined_bytecodes) {
|
||||||
|
@ -64,15 +64,13 @@ class CompilerEvent : AllStatic {
|
|||||||
class PhaseEvent : AllStatic {
|
class PhaseEvent : AllStatic {
|
||||||
friend class CompilerPhaseTypeConstant;
|
friend class CompilerPhaseTypeConstant;
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Register compiler phases for JFR type CompilerPhaseType serialization purposes.
|
// Gets a unique identifier for `phase_name`, computing and registering it first if necessary.
|
||||||
* This method is called during compiler creation or during compilation.
|
// If `may_exist` is true, then current registrations are searched first. If false, then
|
||||||
* Registration will serialize the passed in phase constants, supporting bulk and/or incremental registrations.
|
// there must not be an existing registration for `phase_name`.
|
||||||
* This method returns start index of new list that just got appended to phase_names.
|
// If `use_strdup` is true, then `phase_name` is strdup'ed before registration.
|
||||||
* Param new_phases may contain duplicates.
|
// If `sync` is true, then access to the registration table is synchronized.
|
||||||
* Return value could be used for mapping purpose at caller site, or caller can assume explicit order of registration.
|
static int get_phase_id(const char* phase_name, bool may_exist, bool use_strdup, bool sync) NOT_JFR_RETURN_(-1);
|
||||||
*/
|
|
||||||
static int register_phases(GrowableArray<const char*>* new_phases) NOT_JFR_RETURN_(-1);
|
|
||||||
|
|
||||||
static void post(EventCompilerPhase& event, const Ticks& start_time, int phase, int compile_id, int level) NOT_JFR_RETURN();
|
static void post(EventCompilerPhase& event, const Ticks& start_time, int phase, int compile_id, int level) NOT_JFR_RETURN();
|
||||||
static void post(EventCompilerPhase& event, jlong start_time, int phase, int compile_id, int level) {
|
static void post(EventCompilerPhase& event, jlong start_time, int phase, int compile_id, int level) {
|
||||||
|
@ -2639,19 +2639,11 @@ C2V_VMENTRY_0(jlong, ticksNow, (JNIEnv* env, jobject))
|
|||||||
return CompilerEvent::ticksNow();
|
return CompilerEvent::ticksNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
C2V_VMENTRY_0(jint, registerCompilerPhases, (JNIEnv* env, jobject, jobjectArray jphases))
|
C2V_VMENTRY_0(jint, registerCompilerPhase, (JNIEnv* env, jobject, jstring jphase_name))
|
||||||
#if INCLUDE_JFR
|
#if INCLUDE_JFR
|
||||||
if (jphases == NULL) {
|
JVMCIObject phase_name = JVMCIENV->wrap(jphase_name);
|
||||||
return -1;
|
const char *name = JVMCIENV->as_utf8_string(phase_name);
|
||||||
}
|
return CompilerEvent::PhaseEvent::get_phase_id(name, true, true, true);
|
||||||
JVMCIObjectArray phases = JVMCIENV->wrap(jphases);
|
|
||||||
int len = JVMCIENV->get_length(phases);
|
|
||||||
GrowableArray<const char*>* jvmci_phase_names = new GrowableArray<const char*>(len);
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
JVMCIObject phase = JVMCIENV->get_object_at(phases, i);
|
|
||||||
jvmci_phase_names->append(strdup(JVMCIENV->as_utf8_string(phase)));
|
|
||||||
}
|
|
||||||
return CompilerEvent::PhaseEvent::register_phases(jvmci_phase_names);
|
|
||||||
#else
|
#else
|
||||||
return -1;
|
return -1;
|
||||||
#endif // !INCLUDE_JFR
|
#endif // !INCLUDE_JFR
|
||||||
@ -2823,7 +2815,7 @@ JNINativeMethod CompilerToVM::methods[] = {
|
|||||||
{CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)},
|
{CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)},
|
||||||
{CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)},
|
{CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)},
|
||||||
{CC "ticksNow", CC "()J", FN_PTR(ticksNow)},
|
{CC "ticksNow", CC "()J", FN_PTR(ticksNow)},
|
||||||
{CC "registerCompilerPhases", CC "([" STRING ")I", FN_PTR(registerCompilerPhases)},
|
{CC "registerCompilerPhase", CC "(" STRING ")I", FN_PTR(registerCompilerPhase)},
|
||||||
{CC "notifyCompilerPhaseEvent", CC "(JIII)V", FN_PTR(notifyCompilerPhaseEvent)},
|
{CC "notifyCompilerPhaseEvent", CC "(JIII)V", FN_PTR(notifyCompilerPhaseEvent)},
|
||||||
{CC "notifyCompilerInliningEvent", CC "(I" HS_RESOLVED_METHOD HS_RESOLVED_METHOD "ZLjava/lang/String;I)V", FN_PTR(notifyCompilerInliningEvent)},
|
{CC "notifyCompilerInliningEvent", CC "(I" HS_RESOLVED_METHOD HS_RESOLVED_METHOD "ZLjava/lang/String;I)V", FN_PTR(notifyCompilerInliningEvent)},
|
||||||
};
|
};
|
||||||
|
@ -999,9 +999,9 @@ final class CompilerToVM {
|
|||||||
/**
|
/**
|
||||||
* Adds phases in HotSpot JFR.
|
* Adds phases in HotSpot JFR.
|
||||||
*
|
*
|
||||||
* @see JFR.CompilerPhaseEvent#registerPhases and JFR.CompilerPhaseEvent#write
|
* @see JFR.CompilerPhaseEvent#write
|
||||||
*/
|
*/
|
||||||
native int registerCompilerPhases(String[] phases);
|
native int registerCompilerPhase(String phaseName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see JFR.CompilerPhaseEvent#write
|
* @see JFR.CompilerPhaseEvent#write
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package jdk.vm.ci.hotspot;
|
package jdk.vm.ci.hotspot;
|
||||||
|
|
||||||
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
|
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
|
||||||
@ -33,8 +32,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper methods for interacting with the Java Flight Recorder (JFR) to register events and notify it when events occur.
|
* Helper methods for interacting with the Java Flight Recorder (JFR) to register events and notify
|
||||||
* The JFR events are defined in {see @code src/share/jfr/metadata/metadata.xml}.
|
* it when events occur. The JFR events are defined in {see @code
|
||||||
|
* src/share/jfr/metadata/metadata.xml}.
|
||||||
*/
|
*/
|
||||||
public final class JFR {
|
public final class JFR {
|
||||||
|
|
||||||
@ -60,22 +60,7 @@ public final class JFR {
|
|||||||
private static final ConcurrentHashMap<String, Integer> phaseToId = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<String, Integer> phaseToId = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static int getPhaseToId(String phaseName) {
|
private static int getPhaseToId(String phaseName) {
|
||||||
String[] phaseNames = { phaseName };
|
return phaseToId.computeIfAbsent(phaseName, k -> compilerToVM().registerCompilerPhase(phaseName));
|
||||||
return phaseToId.computeIfAbsent(phaseName, k -> compilerToVM().registerCompilerPhases(phaseNames));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers new compiler phases with JFR. This should be called during compiler initialization.
|
|
||||||
*
|
|
||||||
* @param phaseNames compiler phase names
|
|
||||||
*/
|
|
||||||
public static synchronized void registerPhases(String[] phaseNames) {
|
|
||||||
ArrayList<String> toProcess = new ArrayList<>(Arrays.asList(phaseNames));
|
|
||||||
toProcess.removeAll(phaseToId.keySet());
|
|
||||||
int pid = compilerToVM().registerCompilerPhases(toProcess.toArray(new String[toProcess.size()]));
|
|
||||||
for (String phase : toProcess) {
|
|
||||||
phaseToId.put(phase, pid++);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,8 +77,8 @@ public final class JFR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper methods for managing JFR CompilerInlining events.
|
* Helper methods for managing JFR CompilerInlining events. The events are defined in {see @code
|
||||||
* The events are defined in {see @code src/share/jfr/metadata/metadata.xml}.
|
* src/share/jfr/metadata/metadata.xml}.
|
||||||
*/
|
*/
|
||||||
public static final class CompilerInliningEvent {
|
public static final class CompilerInliningEvent {
|
||||||
|
|
||||||
@ -112,4 +97,3 @@ public final class JFR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user