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
This commit is contained in:
parent
bfa3ad9108
commit
211e529373
make/hotspot/lib
src
hotspot/share
c1
ci
compiler
jfr/recorder
jvmci
opto
utilities
jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot
test/jdk/jdk/jfr
@ -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
|
||||
|
149
src/hotspot/share/compiler/compilerEvent.cpp
Normal file
149
src/hotspot/share/compiler/compilerEvent.cpp
Normal file
@ -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);
|
||||
}
|
86
src/hotspot/share/compiler/compilerEvent.hpp
Normal file
86
src/hotspot/share/compiler/compilerEvent.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SHARE_COMPILER_COMPILEREVENT_HPP
|
||||
#define SHARE_COMPILER_COMPILEREVENT_HPP
|
||||
|
||||
#include "jni.h"
|
||||
#include "compiler/compilerDefinitions.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/utilities/jfrTime.hpp"
|
||||
#endif
|
||||
|
||||
class ciMethod;
|
||||
template <typename>
|
||||
class GrowableArray;
|
||||
class Method;
|
||||
|
||||
class CompilerEvent : AllStatic {
|
||||
public:
|
||||
static jlong ticksNow() {
|
||||
// Using Ticks for consistent usage outside JFR folder.
|
||||
JFR_ONLY(return JfrTime::is_ft_enabled() ? Ticks::now().ft_value() : Ticks::now().value();) NOT_JFR_RETURN_(0L);
|
||||
}
|
||||
|
||||
class CompilationEvent : AllStatic {
|
||||
public:
|
||||
static void post(EventCompilation& event, int compile_id, CompilerType type, Method* method, int compile_level, bool success, bool is_osr, int code_size, int inlined_bytecodes) NOT_JFR_RETURN();
|
||||
};
|
||||
|
||||
class CompilationFailureEvent : AllStatic {
|
||||
public:
|
||||
static void post(EventCompilationFailure& event, int compile_id, const char* reason) NOT_JFR_RETURN();
|
||||
};
|
||||
|
||||
class PhaseEvent : AllStatic {
|
||||
friend class CompilerPhaseTypeConstant;
|
||||
public:
|
||||
/**
|
||||
* Register compiler phases for JFR type CompilerPhaseType serialization purposes.
|
||||
* This method is called during compiler creation or during compilation.
|
||||
* Registration will serialize the passed in phase constants, supporting bulk and/or incremental registrations.
|
||||
* This method returns start index of new list that just got appended to phase_names.
|
||||
* Param new_phases may contain duplicates.
|
||||
* Return value could be used for mapping purpose at caller site, or caller can assume explicit order of registration.
|
||||
*/
|
||||
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, jlong start_time, int phase, int compile_id, int level) {
|
||||
JFR_ONLY(post(event, Ticks(start_time), phase, compile_id, level);)
|
||||
}
|
||||
};
|
||||
|
||||
class InlineEvent : AllStatic {
|
||||
static void post(EventCompilerInlining& event, int compile_id, Method* caller, const JfrStructCalleeMethod& callee, bool success, const char* msg, int bci) NOT_JFR_RETURN();
|
||||
public:
|
||||
static void post(EventCompilerInlining& event, int compile_id, Method* caller, Method* callee, bool success, const char* msg, int bci) NOT_JFR_RETURN();
|
||||
static void post(EventCompilerInlining& event, int compile_id, Method* caller, ciMethod* callee, bool success, const char* msg, int bci) NOT_JFR_RETURN();
|
||||
};
|
||||
};
|
||||
#endif // SHARE_COMPILER_COMPILEREVENT_HPP
|
@ -54,6 +54,22 @@ typedef JfrCheckpointManager::Buffer* BufferPtr;
|
||||
|
||||
static JfrCheckpointManager* _instance = NULL;
|
||||
|
||||
static volatile bool constant_pending = false;
|
||||
|
||||
static bool is_constant_pending() {
|
||||
if (Atomic::load_acquire(&constant_pending)) {
|
||||
Atomic::release_store(&constant_pending, false); // reset
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void set_constant_pending() {
|
||||
if (!Atomic::load_acquire(&constant_pending)) {
|
||||
Atomic::release_store(&constant_pending, true);
|
||||
}
|
||||
}
|
||||
|
||||
JfrCheckpointManager& JfrCheckpointManager::instance() {
|
||||
return *_instance;
|
||||
}
|
||||
@ -215,6 +231,7 @@ BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t request
|
||||
if (0 == requested) {
|
||||
// indicates a lease is being returned
|
||||
release(old, thread);
|
||||
set_constant_pending();
|
||||
return NULL;
|
||||
}
|
||||
// migration of in-flight information
|
||||
@ -361,16 +378,6 @@ size_t JfrCheckpointManager::write_epoch_transition_mspace() {
|
||||
return write_mspace<ExclusiveOp, CompositeOperation>(_epoch_transition_mspace, _chunkwriter);
|
||||
}
|
||||
|
||||
typedef MutexedWriteOp<WriteOperation> FlushOperation;
|
||||
|
||||
size_t JfrCheckpointManager::flush() {
|
||||
WriteOperation wo(_chunkwriter);
|
||||
FlushOperation fo(wo);
|
||||
assert(_free_list_mspace->is_full_empty(), "invariant");
|
||||
process_free_list(fo, _free_list_mspace);
|
||||
return wo.processed();
|
||||
}
|
||||
|
||||
typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
|
||||
size_t JfrCheckpointManager::clear() {
|
||||
clear_type_set();
|
||||
@ -394,10 +401,6 @@ static JfrBuffer* get_epoch_transition_buffer(JfrCheckpointMspace* mspace, Threa
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool JfrCheckpointManager::is_static_type_set_required() {
|
||||
return JfrTypeManager::has_new_static_type();
|
||||
}
|
||||
|
||||
size_t JfrCheckpointManager::write_static_type_set() {
|
||||
Thread* const t = Thread::current();
|
||||
ResourceMark rm(t);
|
||||
@ -472,27 +475,26 @@ void JfrCheckpointManager::write_type_set_for_unloaded_classes() {
|
||||
}
|
||||
}
|
||||
|
||||
bool JfrCheckpointManager::is_type_set_required() {
|
||||
return JfrTraceIdEpoch::has_changed_tag_state();
|
||||
}
|
||||
typedef MutexedWriteOp<WriteOperation> FlushOperation;
|
||||
|
||||
size_t JfrCheckpointManager::flush_type_set() {
|
||||
size_t elements = 0;
|
||||
{
|
||||
if (JfrTraceIdEpoch::has_changed_tag_state()) {
|
||||
JfrCheckpointWriter writer(Thread::current());
|
||||
// can safepoint here
|
||||
MutexLocker cld_lock(ClassLoaderDataGraph_lock);
|
||||
MutexLocker module_lock(Module_lock);
|
||||
elements = JfrTypeSet::serialize(&writer, NULL, false, true);
|
||||
}
|
||||
flush();
|
||||
if (is_constant_pending()) {
|
||||
WriteOperation wo(_chunkwriter);
|
||||
FlushOperation fo(wo);
|
||||
assert(_free_list_mspace->is_full_empty(), "invariant");
|
||||
process_free_list(fo, _free_list_mspace);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
void JfrCheckpointManager::flush_static_type_set() {
|
||||
flush();
|
||||
}
|
||||
|
||||
void JfrCheckpointManager::create_thread_blob(Thread* t) {
|
||||
JfrTypeManager::create_thread_blob(t);
|
||||
}
|
||||
|
@ -80,11 +80,9 @@ class JfrCheckpointManager : public JfrCHeapObj {
|
||||
size_t write();
|
||||
size_t flush();
|
||||
|
||||
bool is_static_type_set_required();
|
||||
size_t write_static_type_set();
|
||||
size_t write_threads();
|
||||
size_t write_static_type_set_and_threads();
|
||||
bool is_type_set_required();
|
||||
void clear_type_set();
|
||||
void write_type_set();
|
||||
static void write_type_set_for_unloaded_classes();
|
||||
@ -106,7 +104,6 @@ class JfrCheckpointManager : public JfrCHeapObj {
|
||||
|
||||
public:
|
||||
size_t flush_type_set();
|
||||
void flush_static_type_set();
|
||||
static void create_thread_blob(Thread* t);
|
||||
static void write_thread_checkpoint(Thread* t);
|
||||
void register_service_thread(const Thread* t);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -241,17 +241,6 @@ void NarrowOopModeConstant::serialize(JfrCheckpointWriter& writer) {
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerPhaseTypeConstant::serialize(JfrCheckpointWriter& writer) {
|
||||
#ifdef COMPILER2
|
||||
static const u4 nof_entries = PHASE_NUM_TYPES;
|
||||
writer.write_count(nof_entries);
|
||||
for (u4 i = 0; i < nof_entries; ++i) {
|
||||
writer.write_key(i);
|
||||
writer.write(CompilerPhaseTypeHelper::to_string((CompilerPhaseType)i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CodeBlobTypeConstant::serialize(JfrCheckpointWriter& writer) {
|
||||
static const u4 nof_entries = CodeBlobType::NumTypes;
|
||||
writer.write_count(nof_entries);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -77,11 +77,6 @@ class NarrowOopModeConstant : public JfrSerializer {
|
||||
void serialize(JfrCheckpointWriter& writer);
|
||||
};
|
||||
|
||||
class CompilerPhaseTypeConstant : public JfrSerializer {
|
||||
public:
|
||||
void serialize(JfrCheckpointWriter& writer);
|
||||
};
|
||||
|
||||
class CodeBlobTypeConstant : public JfrSerializer {
|
||||
public:
|
||||
void serialize(JfrCheckpointWriter& writer);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -186,8 +186,6 @@ static void assert_not_registered_twice(JfrTypeId id, List& list) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool new_registration = false;
|
||||
|
||||
static bool register_static_type(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) {
|
||||
assert(serializer != NULL, "invariant");
|
||||
JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer);
|
||||
@ -200,7 +198,6 @@ static bool register_static_type(JfrTypeId id, bool permit_cache, JfrSerializer*
|
||||
if (JfrRecorder::is_recording()) {
|
||||
JfrCheckpointWriter writer(STATICS);
|
||||
registration->invoke(writer);
|
||||
new_registration = true;
|
||||
}
|
||||
types.prepend(registration);
|
||||
return true;
|
||||
@ -218,7 +215,6 @@ bool JfrTypeManager::initialize() {
|
||||
register_static_type(TYPE_METASPACEOBJECTTYPE, true, new MetaspaceObjectTypeConstant());
|
||||
register_static_type(TYPE_REFERENCETYPE, true, new ReferenceTypeConstant());
|
||||
register_static_type(TYPE_NARROWOOPMODE, true, new NarrowOopModeConstant());
|
||||
register_static_type(TYPE_COMPILERPHASETYPE, true, new CompilerPhaseTypeConstant());
|
||||
register_static_type(TYPE_CODEBLOBTYPE, true, new CodeBlobTypeConstant());
|
||||
register_static_type(TYPE_VMOPERATIONTYPE, true, new VMOperationTypeConstant());
|
||||
register_static_type(TYPE_THREADSTATE, true, new ThreadStateConstant());
|
||||
@ -233,14 +229,6 @@ bool JfrSerializer::register_serializer(JfrTypeId id, bool permit_cache, JfrSeri
|
||||
return register_static_type(id, permit_cache, serializer);
|
||||
}
|
||||
|
||||
bool JfrTypeManager::has_new_static_type() {
|
||||
if (new_registration) {
|
||||
SerializerRegistrationGuard guard;
|
||||
new_registration = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void JfrTypeManager::write_static_types(JfrCheckpointWriter& writer) {
|
||||
SerializerRegistrationGuard guard;
|
||||
@ -248,5 +236,4 @@ void JfrTypeManager::write_static_types(JfrCheckpointWriter& writer) {
|
||||
while (iter.has_next()) {
|
||||
iter.next()->invoke(writer);
|
||||
}
|
||||
new_registration = false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -37,7 +37,6 @@ class JfrTypeManager : public AllStatic {
|
||||
static void write_threads(JfrCheckpointWriter& writer);
|
||||
static void create_thread_blob(Thread* t);
|
||||
static void write_thread_checkpoint(Thread* t);
|
||||
static bool has_new_static_type();
|
||||
static void write_static_types(JfrCheckpointWriter& writer);
|
||||
};
|
||||
|
||||
|
@ -623,13 +623,7 @@ size_t JfrRecorderService::flush() {
|
||||
if (_stack_trace_repository.is_modified()) {
|
||||
total_elements += flush_stacktrace(_stack_trace_repository, _chunkwriter);
|
||||
}
|
||||
if (_checkpoint_manager.is_type_set_required()) {
|
||||
total_elements += flush_typeset(_checkpoint_manager, _chunkwriter);
|
||||
} else if (_checkpoint_manager.is_static_type_set_required()) {
|
||||
// don't tally this, it is only in order to flush the waiting constants
|
||||
_checkpoint_manager.flush_static_type_set();
|
||||
}
|
||||
return total_elements;
|
||||
return flush_typeset(_checkpoint_manager, _chunkwriter) + total_elements;
|
||||
}
|
||||
|
||||
typedef Content<JfrRecorderService, &JfrRecorderService::flush> FlushFunctor;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "code/scopeDesc.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compilerEvent.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "interpreter/linkResolver.hpp"
|
||||
#include "interpreter/bytecodeStream.hpp"
|
||||
@ -2628,6 +2629,45 @@ C2V_VMENTRY(void, callSystemExit, (JNIEnv* env, jobject, jint status))
|
||||
CHECK);
|
||||
}
|
||||
|
||||
C2V_VMENTRY_0(jlong, ticksNow, (JNIEnv* env, jobject))
|
||||
return CompilerEvent::ticksNow();
|
||||
}
|
||||
|
||||
C2V_VMENTRY_0(jint, registerCompilerPhases, (JNIEnv* env, jobject, jobjectArray jphases))
|
||||
#if INCLUDE_JFR
|
||||
if (jphases == NULL) {
|
||||
return -1;
|
||||
}
|
||||
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
|
||||
return -1;
|
||||
#endif // !INCLUDE_JFR
|
||||
}
|
||||
|
||||
C2V_VMENTRY(void, notifyCompilerPhaseEvent, (JNIEnv* env, jobject, jlong startTime, jint phase, jint compileId, jint level))
|
||||
EventCompilerPhase event;
|
||||
if (event.should_commit()) {
|
||||
CompilerEvent::PhaseEvent::post(event, startTime, phase, compileId, level);
|
||||
}
|
||||
}
|
||||
|
||||
C2V_VMENTRY(void, notifyCompilerInliningEvent, (JNIEnv* env, jobject, jint compileId, jobject caller, jobject callee, jboolean succeeded, jstring jmessage, jint bci))
|
||||
EventCompilerInlining event;
|
||||
if (event.should_commit()) {
|
||||
Method* caller_method = JVMCIENV->asMethod(caller);
|
||||
Method* callee_method = JVMCIENV->asMethod(callee);
|
||||
JVMCIObject message = JVMCIENV->wrap(jmessage);
|
||||
CompilerEvent::InlineEvent::post(event, compileId, caller_method, callee_method, succeeded, JVMCIENV->as_utf8_string(message), bci);
|
||||
}
|
||||
}
|
||||
|
||||
#define CC (char*) /*cast a literal from (const char*)*/
|
||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
|
||||
|
||||
@ -2775,6 +2815,10 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||
{CC "releaseFailedSpeculations", CC "(J)V", FN_PTR(releaseFailedSpeculations)},
|
||||
{CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)},
|
||||
{CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)},
|
||||
{CC "ticksNow", CC "()J", FN_PTR(ticksNow)},
|
||||
{CC "registerCompilerPhases", CC "([" STRING ")I", FN_PTR(registerCompilerPhases)},
|
||||
{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)},
|
||||
};
|
||||
|
||||
int CompilerToVM::methods_count() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -27,9 +27,9 @@
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compilerEvent.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "interpreter/linkResolver.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "opto/callGenerator.hpp"
|
||||
#include "opto/parse.hpp"
|
||||
@ -531,25 +531,6 @@ const char* InlineTree::check_can_parse(ciMethod* callee) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void post_inlining_event(int compile_id,const char* msg, bool success, int bci, ciMethod* caller, ciMethod* callee) {
|
||||
assert(caller != NULL, "invariant");
|
||||
assert(callee != NULL, "invariant");
|
||||
EventCompilerInlining event;
|
||||
if (event.should_commit()) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------print_inlining---------------------------------
|
||||
void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci,
|
||||
ciMethod* caller_method, bool success) const {
|
||||
@ -566,14 +547,17 @@ void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci,
|
||||
caller_bci, inline_msg);
|
||||
if (C->print_inlining()) {
|
||||
C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg);
|
||||
guarantee(callee_method != NULL, "would crash in post_inlining_event");
|
||||
guarantee(callee_method != NULL, "would crash in CompilerEvent::InlineEvent::post");
|
||||
if (Verbose) {
|
||||
const InlineTree *top = this;
|
||||
while (top->caller_tree() != NULL) { top = top->caller_tree(); }
|
||||
//tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count());
|
||||
}
|
||||
}
|
||||
post_inlining_event(C->compile_id(), inline_msg, success, caller_bci, caller_method, callee_method);
|
||||
EventCompilerInlining event;
|
||||
if (event.should_commit()) {
|
||||
CompilerEvent::InlineEvent::post(event, C->compile_id(), caller_method->get_Method(), callee_method, success, inline_msg, caller_bci);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------ok_to_inline-----------------------------------
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -30,9 +30,9 @@
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compilerEvent.hpp"
|
||||
#include "libadt/dict.hpp"
|
||||
#include "libadt/vectset.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/methodData.hpp"
|
||||
#include "opto/idealGraphPrinter.hpp"
|
||||
@ -631,11 +631,7 @@ class Compile : public Phase {
|
||||
void print_method(CompilerPhaseType cpt, int level = 1, int idx = 0) {
|
||||
EventCompilerPhase event;
|
||||
if (event.should_commit()) {
|
||||
event.set_starttime(C->_latest_stage_start_counter);
|
||||
event.set_phase((u1) cpt);
|
||||
event.set_compileId(C->_compile_id);
|
||||
event.set_phaseLevel(level);
|
||||
event.commit();
|
||||
CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, cpt, C->_compile_id, level);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -655,12 +651,9 @@ class Compile : public Phase {
|
||||
void end_method(int level = 1) {
|
||||
EventCompilerPhase event;
|
||||
if (event.should_commit()) {
|
||||
event.set_starttime(C->_latest_stage_start_counter);
|
||||
event.set_phase((u1) PHASE_END);
|
||||
event.set_compileId(C->_compile_id);
|
||||
event.set_phaseLevel(level);
|
||||
event.commit();
|
||||
CompilerEvent::PhaseEvent::post(event, C->_latest_stage_start_counter, PHASE_END, C->_compile_id, level);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (_printer && _printer->should_print(level)) {
|
||||
_printer->end_method();
|
||||
|
@ -261,9 +261,11 @@
|
||||
|
||||
#if INCLUDE_JFR
|
||||
#define JFR_ONLY(code) code
|
||||
#define NOT_JFR_RETURN() /* next token must be ; */
|
||||
#define NOT_JFR_RETURN_(code) /* next token must be ; */
|
||||
#else
|
||||
#define JFR_ONLY(code)
|
||||
#define NOT_JFR_RETURN() {}
|
||||
#define NOT_JFR_RETURN_(code) { return code; }
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -237,6 +237,7 @@ class TimeInstant : public Rep<TimeSource> {
|
||||
// GC unit tests
|
||||
friend class TimePartitionPhasesIteratorTest;
|
||||
friend class GCTimerTest;
|
||||
friend class CompilerEvent;
|
||||
};
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -985,4 +985,27 @@ final class CompilerToVM {
|
||||
* @see HotSpotJVMCIRuntime#exitHotSpot(int)
|
||||
*/
|
||||
native void callSystemExit(int status);
|
||||
|
||||
/**
|
||||
* @see JFR.Ticks#now
|
||||
*/
|
||||
native long ticksNow();
|
||||
|
||||
/**
|
||||
* Adds phases in HotSpot JFR.
|
||||
*
|
||||
* @see JFR.CompilerPhaseEvent#registerPhases and JFR.CompilerPhaseEvent#write
|
||||
*/
|
||||
native int registerCompilerPhases(String[] phases);
|
||||
|
||||
/**
|
||||
* @see JFR.CompilerPhaseEvent#write
|
||||
*/
|
||||
native void notifyCompilerPhaseEvent(long startTime, int phase, int compileId, int level);
|
||||
|
||||
/**
|
||||
* @see JFR.CompilerInliningEvent#write
|
||||
*/
|
||||
native void notifyCompilerInliningEvent(int compileId, HotSpotResolvedJavaMethodImpl caller, HotSpotResolvedJavaMethodImpl callee, boolean succeeded, String message, int bci);
|
||||
|
||||
}
|
||||
|
115
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/JFR.java
Normal file
115
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/JFR.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
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.
|
||||
* The JFR events are defined in {see @code src/share/jfr/metadata/metadata.xml}.
|
||||
*/
|
||||
public final class JFR {
|
||||
|
||||
/**
|
||||
* Provides access to current JFR time stamp.
|
||||
*/
|
||||
public static final class Ticks {
|
||||
|
||||
/**
|
||||
* @return current JFR time stamp
|
||||
*/
|
||||
public static long now() {
|
||||
return compilerToVM().ticksNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper methods for managing JFR CompilerPhase events.
|
||||
* The events are defined in {see @code src/share/jfr/metadata/metadata.xml}.
|
||||
*/
|
||||
public static final class CompilerPhaseEvent {
|
||||
|
||||
private static final ConcurrentHashMap<String, Integer> phaseToId = new ConcurrentHashMap<>();
|
||||
|
||||
private static int getPhaseToId(String phaseName) {
|
||||
String[] phaseNames = { 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++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits a CompilerPhase event.
|
||||
*
|
||||
* @param startTime time captured at the start of compiler phase
|
||||
* @param phaseName compiler phase name
|
||||
* @param compileId current compilation unit id
|
||||
* @param phaseLevel compiler phase nesting level
|
||||
*/
|
||||
public static void write(long startTime, String phaseName, int compileId, int phaseLevel) {
|
||||
compilerToVM().notifyCompilerPhaseEvent(startTime, getPhaseToId(phaseName), compileId, phaseLevel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper methods for managing JFR CompilerInlining events.
|
||||
* The events are defined in {see @code src/share/jfr/metadata/metadata.xml}.
|
||||
*/
|
||||
public static final class CompilerInliningEvent {
|
||||
|
||||
/**
|
||||
* Commits a CompilerInlining event.
|
||||
*
|
||||
* @param compileId current compilation unit id
|
||||
* @param caller caller method
|
||||
* @param callee callee method
|
||||
* @param succeeded inlining succeeded or not
|
||||
* @param message extra information on inlining
|
||||
* @param bci invocation byte code index
|
||||
*/
|
||||
public static void write(int compileId, ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, String message, int bci) {
|
||||
compilerToVM().notifyCompilerInliningEvent(compileId, (HotSpotResolvedJavaMethodImpl) caller, (HotSpotResolvedJavaMethodImpl) callee, succeeded, message, bci);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
package jdk.jfr.event.compiler;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -34,13 +35,15 @@ import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.jfr.EventNames;
|
||||
import jdk.test.lib.jfr.Events;
|
||||
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
// THIS TEST IS LINE NUMBER SENSITIVE
|
||||
|
||||
// Careful if moving this class or method somewhere since verifyDeoptimizationEventFields asserts the linenumber
|
||||
class Dummy {
|
||||
static void dummyMethod(boolean b) {
|
||||
public static void dummyMethod(boolean b) {
|
||||
if (b) {
|
||||
return;
|
||||
System.out.println("Deoptimized");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,29 +56,52 @@ class Dummy {
|
||||
* @requires vm.compMode != "Xint"
|
||||
* @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == 4 | vm.opt.TieredStopAtLevel == null)
|
||||
* @library /test/lib
|
||||
* @run main/othervm -XX:-BackgroundCompilation jdk.jfr.event.compiler.TestDeoptimization
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run main/othervm -XX:-BackgroundCompilation -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI jdk.jfr.event.compiler.TestDeoptimization
|
||||
*/
|
||||
public class TestDeoptimization {
|
||||
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
private final static String TYPE_NAME = Dummy.class.getName().replace(".", "/");
|
||||
private final static String METHOD_NAME = "dummyMethod";
|
||||
private static final String METHOD_DESCRIPTOR = "(Z)V";
|
||||
private static final String COMPILER = "c2";
|
||||
private static final String[] COMPILER = { "c2", "jvmci" };
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
new TestDeoptimization().doTest();
|
||||
}
|
||||
|
||||
public void doTest() throws Throwable {
|
||||
Method dummyMethodDesc = Dummy.class.getDeclaredMethod("dummyMethod", boolean.class);
|
||||
|
||||
System.out.println("Deoptimization Test");
|
||||
|
||||
Recording recording = new Recording();
|
||||
recording.enable(EventNames.Deoptimization);
|
||||
recording.enable(EventNames.Compilation);
|
||||
recording.start();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
// compile dummyMethod
|
||||
|
||||
// load
|
||||
Dummy.dummyMethod(false);
|
||||
|
||||
// compiling at level 3, for profiling support
|
||||
if (!WHITE_BOX.enqueueMethodForCompilation(dummyMethodDesc, 3)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// profile dummyMethod
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
Dummy.dummyMethod(false);
|
||||
}
|
||||
|
||||
// compiling at level 4
|
||||
if (!WHITE_BOX.enqueueMethodForCompilation(dummyMethodDesc, 4)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// provoke deoptimization by executing the uncommon trap in dummyMethod
|
||||
Dummy.dummyMethod(true);
|
||||
System.out.println("Time to load, compile and deoptimize dummyMethod: " + (System.currentTimeMillis() - start));
|
||||
@ -114,11 +140,13 @@ public class TestDeoptimization {
|
||||
private void verifyDeoptimizationEventFields(RecordedEvent event) {
|
||||
Events.assertEventThread(event);
|
||||
Events.assertField(event, "compileId").atLeast(0);
|
||||
Events.assertField(event, "compiler").equal(COMPILER);
|
||||
Events.assertField(event, "lineNumber").equal(42);
|
||||
Events.assertField(event, "bci").equal(1);
|
||||
Events.assertField(event, "instruction").equal("ifeq");
|
||||
Events.assertField(event, "compiler").containsAny(COMPILER);
|
||||
Events.assertField(event, "lineNumber").equal(45);
|
||||
Events.assertField(event, "bci").atMost(1);
|
||||
// Both graal and c2 traps at ifeq. c2 deopt reinterpret from unstable ifeq, while Graal deopt reinterpret from next instruction after last state change.
|
||||
Events.assertField(event, "instruction").containsAny("ifeq", "iload_0");
|
||||
Events.assertField(event, "action").notEmpty().equal("reinterpret");
|
||||
Events.assertField(event, "reason").notEmpty().equal("unstable_if");
|
||||
Events.assertField(event, "reason").notEmpty().containsAny("unstable_if", "null_assert_or_unreached0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -28,7 +28,7 @@
|
||||
* @bug 8157032
|
||||
* @key jfr
|
||||
* @summary verify that jfr can not be used when JVM is executed only with java.base
|
||||
* @requires vm.hasJFR
|
||||
* @requires vm.hasJFR & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @run driver jdk.jfr.jvm.TestJfrJavaBase
|
||||
|
Loading…
x
Reference in New Issue
Block a user