Skip to content
Permalink
Browse files

8193210: [JVMCI/Graal] add JFR compiler phase/inlining events

C++ EventCompilerPhase/EventCompilerInlining definitions are extended for JVMCI use.

Reviewed-by: dnsimon, egahlin, kvn, mgronlun, thartmann
  • Loading branch information
jamsheedcm committed Mar 27, 2020
1 parent bfa3ad9 commit 211e5293736e07594deec5a87e3f5224f5343a44
@@ -173,6 +173,7 @@ endif
ifneq ($(call check-jvm-feature, jfr), true)
JVM_CFLAGS_FEATURES += -DINCLUDE_JFR=0
JVM_EXCLUDE_PATTERNS += jfr
JVM_EXCLUDE_FILES += compilerEvent.cpp
endif

################################################################################
@@ -35,8 +35,8 @@
#include "ci/ciUtilities.inline.hpp"
#include "compiler/compilationPolicy.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.hpp"
#include "interpreter/bytecode.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -4331,30 +4331,6 @@ void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) {
}
}

static void post_inlining_event(EventCompilerInlining* event,
int compile_id,
const char* msg,
bool success,
int bci,
ciMethod* caller,
ciMethod* callee) {
assert(caller != NULL, "invariant");
assert(callee != NULL, "invariant");
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
JfrStructCalleeMethod callee_struct;
callee_struct.set_type(callee->holder()->name()->as_utf8());
callee_struct.set_name(callee->name()->as_utf8());
callee_struct.set_descriptor(callee->signature()->as_symbol()->as_utf8());
event->set_compileId(compile_id);
event->set_message(msg);
event->set_succeeded(success);
event->set_bci(bci);
event->set_caller(caller->get_Method());
event->set_callee(callee_struct);
event->commit();
}

void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) {
CompileLog* log = compilation()->log();
if (log != NULL) {
@@ -4367,7 +4343,7 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
}
EventCompilerInlining event;
if (event.should_commit()) {
post_inlining_event(&event, compilation()->env()->task()->compile_id(), msg, success, bci(), method(), callee);
CompilerEvent::InlineEvent::post(event, compilation()->env()->task()->compile_id(), method()->get_Method(), callee, success, msg, bci());
}

CompileTask::print_inlining_ul(callee, scope()->level(), bci(), msg);
@@ -39,11 +39,11 @@
#include "code/codeCache.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
@@ -1160,9 +1160,7 @@ void ciEnv::record_failure(const char* reason) {
void ciEnv::report_failure(const char* reason) {
EventCompilationFailure event;
if (event.should_commit()) {
event.set_compileId(compile_id());
event.set_failureMessage(reason);
event.commit();
CompilerEvent::CompilationFailureEvent::post(event, compile_id(), reason);
}
}

@@ -33,10 +33,10 @@
#include "compiler/compilationPolicy.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerEvent.hpp"
#include "compiler/compilerOracle.hpp"
#include "compiler/directivesParser.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
@@ -592,6 +592,34 @@ CompilerCounters::CompilerCounters() {
_compile_type = CompileBroker::no_compile;
}

#if INCLUDE_JFR
// It appends new compiler phase names to growable array phase_names(a new CompilerPhaseType mapping
// in compiler/compilerEvent.cpp) and registers it with its serializer.
//
// c2 uses explicit CompilerPhaseType idToPhase mapping in opto/phasetype.hpp,
// so if c2 is used, it should be always registered first.
// This function is called during vm initialization.
void register_jfr_phasetype_serializer(CompilerType compiler_type) {
ResourceMark rm;
static bool first_registration = true;
if (compiler_type == compiler_jvmci) {
// register serializer, phases will be added later lazily.
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;
} else if (compiler_type == compiler_c2) {
assert(first_registration, "invariant"); // c2 must be registered first.
GrowableArray<const char*>* c2_phase_names = new GrowableArray<const char*>(PHASE_NUM_TYPES);
for (int i = 0; i < PHASE_NUM_TYPES; i++) {
c2_phase_names->append(CompilerPhaseTypeHelper::to_string((CompilerPhaseType)i));
}
CompilerEvent::PhaseEvent::register_phases(c2_phase_names);
first_registration = false;
}
}
#endif // INCLUDE_JFR

// ------------------------------------------------------------------
// CompileBroker::compilation_init
//
@@ -638,10 +666,21 @@ void CompileBroker::compilation_init_phase1(Thread* THREAD) {
if (true JVMCI_ONLY( && !UseJVMCICompiler)) {
if (_c2_count > 0) {
_compilers[1] = new C2Compiler();
// Register c2 first as c2 CompilerPhaseType idToPhase mapping is explicit.
// idToPhase mapping for c2 is in opto/phasetype.hpp
JFR_ONLY(register_jfr_phasetype_serializer(compiler_c2);)
}
}
#endif // COMPILER2

#if INCLUDE_JVMCI
// Register after c2 registration.
// JVMCI CompilerPhaseType idToPhase mapping is dynamic.
if (EnableJVMCI) {
JFR_ONLY(register_jfr_phasetype_serializer(compiler_jvmci);)
}
#endif // INCLUDE_JVMCI

// Start the compiler thread(s) and the sweeper thread
init_compiler_sweeper_threads();
// totalTime performance counter is always created as it is required
@@ -2018,19 +2057,17 @@ void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, bool
assert(task->compile_id() != CICrashAt, "just as planned");
}

static void post_compilation_event(EventCompilation* event, CompileTask* task) {
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
static void post_compilation_event(EventCompilation& event, CompileTask* task) {
assert(task != NULL, "invariant");
event->set_compileId(task->compile_id());
event->set_compiler(task->compiler()->type());
event->set_method(task->method());
event->set_compileLevel(task->comp_level());
event->set_succeded(task->is_success());
event->set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci);
event->set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
event->set_inlinedBytes(task->num_inlined_bytecodes());
event->commit();
CompilerEvent::CompilationEvent::post(event,
task->compile_id(),
task->compiler()->type(),
task->method(),
task->comp_level(),
task->is_success(),
task->osr_bci() != CompileBroker::standard_entry_bci,
(task->code() == NULL) ? 0 : task->code()->total_size(),
task->num_inlined_bytecodes());
}

int DirectivesStack::_depth = 0;
@@ -2129,7 +2166,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
}
post_compile(thread, task, task->code() != NULL, NULL, compilable, failure_reason);
if (event.should_commit()) {
post_compilation_event(&event, task);
post_compilation_event(event, task);
}

} else
@@ -2189,7 +2226,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {

post_compile(thread, task, !ci_env.failing(), &ci_env, compilable, failure_reason);
if (event.should_commit()) {
post_compilation_event(&event, task);
post_compilation_event(event, task);
}
}
// Remove the JNI handle block after the ciEnv destructor has run in
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "ci/ciMethod.hpp"
#include "compiler/compilerEvent.hpp"
#include "jfr/jfr.hpp"
#include "jfr/metadata/jfrSerializer.hpp"
#include "runtime/semaphore.inline.hpp"
#include "utilities/growableArray.hpp"

// Synchronizes access to phases_names.
class PhaseTypeGuard : public StackObj {
private:
static Semaphore _mutex_semaphore;
public:
PhaseTypeGuard() {
_mutex_semaphore.wait();
}
~PhaseTypeGuard() {
_mutex_semaphore.signal();
}
};

Semaphore PhaseTypeGuard::_mutex_semaphore(1);

static void write_phases(JfrCheckpointWriter& writer, u4 base_idx, GrowableArray<const char*>* phases) {
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;

class CompilerPhaseTypeConstant : public JfrSerializer {
public:
void serialize(JfrCheckpointWriter& writer) {
PhaseTypeGuard guard;
write_phases(writer, 0, phase_names);
}
};

// This function provides support for adding dynamic entries to JFR type CompilerPhaseType.
// The mapping for CompilerPhaseType is maintained as growable array phase_names.
// The serializer CompilerPhaseTypeConstant must be registered with JFR at vm init.
// Registration of new phase names creates mapping, serialize it for current chunk and registers its serializer with JFR if it is not already done.
int CompilerEvent::PhaseEvent::register_phases(GrowableArray<const char*>* new_phases) {
int idx = -1;
if (new_phases == NULL || new_phases->is_empty()) {
return idx;
}
bool register_jfr_serializer = false;
{
PhaseTypeGuard guard;
if (phase_names == NULL) {
phase_names = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<const char*>(100, true);
register_jfr_serializer = true;
}
idx = phase_names->length();
phase_names->appendAll(new_phases);
guarantee(phase_names->length() < 256, "exceeds maximum supported phases");
}
if (register_jfr_serializer) {
JfrSerializer::register_serializer(TYPE_COMPILERPHASETYPE, false, new CompilerPhaseTypeConstant());
} else if (Jfr::is_recording()) {
// serialize new_phases.
JfrCheckpointWriter writer;
writer.write_type(TYPE_COMPILERPHASETYPE);
write_phases(writer, idx, new_phases);
}
return idx;
}

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) {
event.set_compileId(compile_id);
event.set_compiler(compiler_type);
event.set_method(method);
event.set_compileLevel((short)compile_level);
event.set_succeded(success);
event.set_isOsr(is_osr);
event.set_codeSize(code_size);
event.set_inlinedBytes(inlined_bytecodes);
event.commit();
}

void CompilerEvent::CompilationFailureEvent::post(EventCompilationFailure& event, int compile_id, const char* reason) {
event.set_compileId(compile_id);
event.set_failureMessage(reason);
event.commit();
}

void CompilerEvent::PhaseEvent::post(EventCompilerPhase& event, const Ticks& start_time, int phase, int compile_id, int level) {
event.set_starttime(start_time);
event.set_phase((u1) phase);
event.set_compileId(compile_id);
event.set_phaseLevel((short)level);
event.commit();
}

void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, const JfrStructCalleeMethod& callee, bool success, const char* msg, int bci) {
event.set_compileId(compile_id);
event.set_caller(caller);
event.set_callee(callee);
event.set_succeeded(success);
event.set_message(msg);
event.set_bci(bci);
event.commit();
}

void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, Method* callee, bool success, const char* msg, int bci) {
JfrStructCalleeMethod callee_struct;
callee_struct.set_type(callee->klass_name()->as_utf8());
callee_struct.set_name(callee->name()->as_utf8());
callee_struct.set_descriptor(callee->signature()->as_utf8());
post(event, compile_id, caller, callee_struct, success, msg, bci);
}

void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, ciMethod* callee, bool success, const char* msg, int bci) {
JfrStructCalleeMethod callee_struct;
callee_struct.set_type(callee->holder()->name()->as_utf8());
callee_struct.set_name(callee->name()->as_utf8());
callee_struct.set_descriptor(callee->signature()->as_symbol()->as_utf8());
post(event, compile_id, caller, callee_struct, success, msg, bci);
}

0 comments on commit 211e529

Please sign in to comment.