提交 5382b8e0 编写于 作者: 卓昂 提交者: 云矅

[JFR] Full patch for hotspot

Reviewers: 效山, 芳玺, 传胜, 三红, yumin.qi

Reviewed By: 三红, 芳玺, 效山, 卓仁

Differential Revision: https://aone.alibaba-inc.com/code/D815657
上级 fef241bb
# #
# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -50,8 +50,10 @@ VPATH += $(Src_Dirs_V:%=%:) ...@@ -50,8 +50,10 @@ VPATH += $(Src_Dirs_V:%=%:)
TraceGeneratedNames = \ TraceGeneratedNames = \
traceEventClasses.hpp \ traceEventClasses.hpp \
traceEventIds.hpp \ traceEventIds.hpp \
traceTypes.hpp traceTypes.hpp \
traceEventControl.hpp \
tracePeriodic.hpp
ifeq ($(HAS_ALT_SRC), true) ifeq ($(HAS_ALT_SRC), true)
TraceGeneratedNames += \ TraceGeneratedNames += \
...@@ -69,6 +71,8 @@ TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) ...@@ -69,6 +71,8 @@ TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%)
XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen
XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \
$(TraceSrcDir)/tracerelationdecls.xml \
$(TraceSrcDir)/traceevents.xml \
$(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod
ifeq ($(HAS_ALT_SRC), true) ifeq ($(HAS_ALT_SRC), true)
XML_DEPS += $(TraceAltSrcDir)/traceevents.xml XML_DEPS += $(TraceAltSrcDir)/traceevents.xml
...@@ -96,6 +100,12 @@ ifeq ($(HAS_ALT_SRC), false) ...@@ -96,6 +100,12 @@ ifeq ($(HAS_ALT_SRC), false)
$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS)
$(GENERATE_CODE) $(GENERATE_CODE)
$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventControl.xsl $(XML_DEPS)
$(GENERATE_CODE)
$(TraceOutDir)/tracePeriodic.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracePeriodic.xsl $(XML_DEPS)
$(GENERATE_CODE)
else else
$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS)
......
/*
* Copyright (c) 2013, 2019, 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 "rdtsc_x86.hpp"
#include "runtime/thread.inline.hpp"
#include "vm_version_ext_x86.hpp"
// The following header contains the implementations of rdtsc()
#ifdef TARGET_OS_ARCH_linux_x86
#include "os_linux_x86.inline.hpp"
#endif
static jlong baseline_counter = 0;
static bool rdtsc_elapsed_counter_enabled = false;
static jlong tsc_frequency = 0;
static jlong set_baseline_counter() {
assert(0 == baseline_counter, "invariant");
baseline_counter = os::rdtsc();
return baseline_counter;
}
// Base loop to estimate ticks frequency for tsc counter from user mode.
// Volatiles and sleep() are used to prevent compiler from applying optimizations.
static void do_time_measurements(volatile jlong& time_base,
volatile jlong& time_fast,
volatile jlong& time_base_elapsed,
volatile jlong& time_fast_elapsed) {
static const unsigned int FT_SLEEP_MILLISECS = 1;
const unsigned int loopcount = 3;
volatile jlong start = 0;
volatile jlong fstart = 0;
volatile jlong end = 0;
volatile jlong fend = 0;
// Figure out the difference between rdtsc and os provided timer.
// base algorithm adopted from JRockit.
for (unsigned int times = 0; times < loopcount; times++) {
start = os::elapsed_counter();
OrderAccess::fence();
fstart = os::rdtsc();
// use sleep to prevent compiler from optimizing
os::sleep(Thread::current(), FT_SLEEP_MILLISECS, true);
end = os::elapsed_counter();
OrderAccess::fence();
fend = os::rdtsc();
time_base += end - start;
time_fast += fend - fstart;
// basis for calculating the os tick start
// to fast time tick start offset
time_base_elapsed += end;
time_fast_elapsed += (fend - baseline_counter);
}
time_base /= loopcount;
time_fast /= loopcount;
time_base_elapsed /= loopcount;
time_fast_elapsed /= loopcount;
}
static jlong initialize_frequency() {
assert(0 == tsc_frequency, "invariant");
assert(0 == baseline_counter, "invariant");
jlong initial_counter = set_baseline_counter();
if (initial_counter == 0) {
return 0;
}
// os time frequency
static double os_freq = (double)os::elapsed_frequency();
assert(os_freq > 0, "os_elapsed frequency corruption!");
double tsc_freq = .0;
double os_to_tsc_conv_factor = 1.0;
// if platform supports invariant tsc,
// apply higher resolution and granularity for conversion calculations
if (VM_Version_Ext::supports_tscinv_ext()) {
// for invariant tsc platforms, take the maximum qualified cpu frequency
tsc_freq = (double)VM_Version_Ext::maximum_qualified_cpu_frequency();
os_to_tsc_conv_factor = tsc_freq / os_freq;
} else {
// for non-trusted platforms, use measurements to estimate
// a conversion factor and the tsc frequency
volatile jlong time_base = 0;
volatile jlong time_fast = 0;
volatile jlong time_base_elapsed = 0;
volatile jlong time_fast_elapsed = 0;
// do measurements to get base data
// on os timer and fast ticks tsc time relation.
do_time_measurements(time_base, time_fast, time_base_elapsed, time_fast_elapsed);
// if invalid measurements, cannot proceed
if (time_fast == 0 || time_base == 0) {
return 0;
}
os_to_tsc_conv_factor = (double)time_fast / (double)time_base;
if (os_to_tsc_conv_factor > 1) {
// estimate on tsc counter frequency
tsc_freq = os_to_tsc_conv_factor * os_freq;
}
}
if ((tsc_freq < 0) || (tsc_freq > 0 && tsc_freq <= os_freq) || (os_to_tsc_conv_factor <= 1)) {
// safer to run with normal os time
tsc_freq = .0;
}
// frequency of the tsc_counter
return (jlong)tsc_freq;
}
static bool initialize_elapsed_counter() {
tsc_frequency = initialize_frequency();
return tsc_frequency != 0 && baseline_counter != 0;
}
static bool ergonomics() {
const bool invtsc_support = Rdtsc::is_supported();
if (FLAG_IS_DEFAULT(UseFastUnorderedTimeStamps) && invtsc_support) {
FLAG_SET_ERGO(bool, UseFastUnorderedTimeStamps, true);
}
bool ft_enabled = UseFastUnorderedTimeStamps && invtsc_support;
if (!ft_enabled) {
if (UseFastUnorderedTimeStamps && VM_Version::supports_tsc()) {
warning("\nThe hardware does not support invariant tsc (INVTSC) register and/or cannot guarantee tsc synchronization between sockets at startup.\n"\
"Values returned via rdtsc() are not guaranteed to be accurate, esp. when comparing values from cross sockets reads. Enabling UseFastUnorderedTimeStamps on non-invariant tsc hardware should be considered experimental.\n");
ft_enabled = true;
}
}
if (!ft_enabled) {
// Warn if unable to support command-line flag
if (UseFastUnorderedTimeStamps && !VM_Version::supports_tsc()) {
warning("Ignoring UseFastUnorderedTimeStamps, hardware does not support normal tsc");
}
}
return ft_enabled;
}
bool Rdtsc::is_supported() {
return VM_Version_Ext::supports_tscinv_ext();
}
bool Rdtsc::is_elapsed_counter_enabled() {
return rdtsc_elapsed_counter_enabled;
}
jlong Rdtsc::frequency() {
return tsc_frequency;
}
jlong Rdtsc::elapsed_counter() {
return os::rdtsc() - baseline_counter;
}
jlong Rdtsc::raw() {
return os::rdtsc();
}
bool Rdtsc::initialize() {
static bool initialized = false;
if (!initialized) {
assert(!rdtsc_elapsed_counter_enabled, "invariant");
VM_Version_Ext::initialize();
assert(0 == tsc_frequency, "invariant");
assert(0 == baseline_counter, "invariant");
bool result = initialize_elapsed_counter(); // init hw
if (result) {
result = ergonomics(); // check logical state
}
rdtsc_elapsed_counter_enabled = result;
initialized = true;
}
return rdtsc_elapsed_counter_enabled;
}
/*
* Copyright (c) 2012, 2019, 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 CPU_X86_VM_RDTSC_X86_HPP
#define CPU_X86_VM_RDTSC_X86_HPP
#include "memory/allocation.hpp"
#include "utilities/macros.hpp"
// Interface to the x86 rdtsc() time counter, if available.
// Not guaranteed to be synchronized across hardware threads and
// therefore software threads, and can be updated asynchronously
// by software. elapsed_counter() can jump backwards
// as well as jump forward when threads query different cores/sockets.
// Very much not recommended for general use.
// INVTSC is a minimal requirement for auto-enablement.
class Rdtsc : AllStatic {
public:
static jlong elapsed_counter(); // provides quick time stamps
static jlong frequency(); // tsc register
static bool is_supported(); // InvariantTSC
static jlong raw(); // direct rdtsc() access
static bool is_elapsed_counter_enabled(); // turn off with -XX:-UseFastUnorderedTimeStamps
static jlong elapsed_counter_baseline();
static bool initialize();
};
#endif // CPU_X86_VM_RDTSC_X86_HPP
此差异已折叠。
/*
* Copyright (c) 2013, 2019, 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 CPU_X86_VM_VM_VERSION_EXT_X86_HPP
#define CPU_X86_VM_VM_VERSION_EXT_X86_HPP
#include "utilities/macros.hpp"
#include "vm_version_x86.hpp"
class VM_Version_Ext : public VM_Version {
private:
static const size_t VENDOR_LENGTH;
static const size_t CPU_EBS_MAX_LENGTH;
static const size_t CPU_TYPE_DESC_BUF_SIZE;
static const size_t CPU_DETAILED_DESC_BUF_SIZE;
static const char* const _family_id_intel[];
static const char* const _family_id_amd[];
static const char* const _brand_id[];
static const char* const _model_id_pentium_pro[];
static const char* const _feature_edx_id[];
static const char* const _feature_extended_edx_id[];
static const char* const _feature_ecx_id[];
static const char* const _feature_extended_ecx_id[];
static int _no_of_threads;
static int _no_of_cores;
static int _no_of_packages;
static char* _cpu_brand_string;
static jlong _max_qualified_cpu_frequency;
static const char* cpu_family_description(void);
static const char* cpu_model_description(void);
static const char* cpu_brand(void);
static const char* cpu_brand_string(void);
static int cpu_type_description(char* const buf, size_t buf_len);
static int cpu_detailed_description(char* const buf, size_t buf_len);
static int cpu_extended_brand_string(char* const buf, size_t buf_len);
static bool cpu_is_em64t(void);
static bool is_netburst(void);
static size_t cpu_write_support_string(char* const buf, size_t buf_len);
static void resolve_cpu_information_details(void);
static jlong max_qualified_cpu_freq_from_brand_string(void);
public:
// Offsets for cpuid asm stub brand string
static ByteSize proc_name_0_offset() { return byte_offset_of(CpuidInfo, proc_name_0); }
static ByteSize proc_name_1_offset() { return byte_offset_of(CpuidInfo, proc_name_1); }
static ByteSize proc_name_2_offset() { return byte_offset_of(CpuidInfo, proc_name_2); }
static ByteSize proc_name_3_offset() { return byte_offset_of(CpuidInfo, proc_name_3); }
static ByteSize proc_name_4_offset() { return byte_offset_of(CpuidInfo, proc_name_4); }
static ByteSize proc_name_5_offset() { return byte_offset_of(CpuidInfo, proc_name_5); }
static ByteSize proc_name_6_offset() { return byte_offset_of(CpuidInfo, proc_name_6); }
static ByteSize proc_name_7_offset() { return byte_offset_of(CpuidInfo, proc_name_7); }
static ByteSize proc_name_8_offset() { return byte_offset_of(CpuidInfo, proc_name_8); }
static ByteSize proc_name_9_offset() { return byte_offset_of(CpuidInfo, proc_name_9); }
static ByteSize proc_name_10_offset() { return byte_offset_of(CpuidInfo, proc_name_10); }
static ByteSize proc_name_11_offset() { return byte_offset_of(CpuidInfo, proc_name_11); }
static int number_of_threads(void);
static int number_of_cores(void);
static int number_of_sockets(void);
static jlong maximum_qualified_cpu_frequency(void);
static bool supports_tscinv_ext(void);
static const char* cpu_name(void);
static const char* cpu_description(void);
static void initialize();
};
#endif // CPU_X86_VM_VM_VERSION_EXT_X86_HPP
...@@ -2141,9 +2141,44 @@ void os::print_dll_info(outputStream *st) { ...@@ -2141,9 +2141,44 @@ void os::print_dll_info(outputStream *st) {
jio_snprintf(fname, sizeof(fname), "/proc/%d/maps", pid); jio_snprintf(fname, sizeof(fname), "/proc/%d/maps", pid);
if (!_print_ascii_file(fname, st)) { if (!_print_ascii_file(fname, st)) {
st->print("Can not get library information for pid = %d\n", pid); st->print("Can not get library information for pid = %d\n", pid);
} }
}
int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
FILE *procmapsFile = NULL;
// Open the procfs maps file for the current process
if ((procmapsFile = fopen("/proc/self/maps", "r")) != NULL) {
// Allocate PATH_MAX for file name plus a reasonable size for other fields.
char line[PATH_MAX + 100];
// Read line by line from 'file'
while (fgets(line, sizeof(line), procmapsFile) != NULL) {
u8 base, top, offset, inode;
char permissions[5];
char device[6];
char name[PATH_MAX + 1];
// Parse fields from line
sscanf(line, UINT64_FORMAT_X "-" UINT64_FORMAT_X " %4s " UINT64_FORMAT_X " %5s " INT64_FORMAT " %s",
&base, &top, permissions, &offset, device, &inode, name);
// Filter by device id '00:00' so that we only get file system mapped files.
if (strcmp(device, "00:00") != 0) {
// Call callback with the fields of interest
if(callback(name, (address)base, (address)top, param)) {
// Oops abort, callback aborted
fclose(procmapsFile);
return 1;
}
}
}
fclose(procmapsFile);
}
return 0;
} }
void os::print_os_info_brief(outputStream* st) { void os::print_os_info_brief(outputStream* st) {
...@@ -4030,6 +4065,10 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) { ...@@ -4030,6 +4065,10 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) {
return ::read(fd, buf, nBytes); return ::read(fd, buf, nBytes);
} }
size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
return ::pread(fd, buf, nBytes, offset);
}
// TODO-FIXME: reconcile Solaris' os::sleep with the linux variation. // TODO-FIXME: reconcile Solaris' os::sleep with the linux variation.
// Solaris uses poll(), linux uses park(). // Solaris uses poll(), linux uses park().
// Poll() is likely a better choice, assuming that Thread.interrupt() // Poll() is likely a better choice, assuming that Thread.interrupt()
......
此差异已折叠。
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -858,6 +858,68 @@ void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) { ...@@ -858,6 +858,68 @@ void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) {
} }
} }
Thread* os::ThreadCrashProtection::_protected_thread = NULL;
os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL;
volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0;
os::ThreadCrashProtection::ThreadCrashProtection() {
}
/*
* See the caveats for this class in os_posix.hpp
* Protects the callback call so that SIGSEGV / SIGBUS jumps back into this
* method and returns false. If none of the signals are raised, returns true.
* The callback is supposed to provide the method that should be protected.
*/
bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
sigset_t saved_sig_mask;
Thread::muxAcquire(&_crash_mux, "CrashProtection");
_protected_thread = ThreadLocalStorage::thread();
assert(_protected_thread != NULL, "Cannot crash protect a NULL thread");
// we cannot rely on sigsetjmp/siglongjmp to save/restore the signal mask
// since on at least some systems (OS X) siglongjmp will restore the mask
// for the process, not the thread
pthread_sigmask(0, NULL, &saved_sig_mask);
if (sigsetjmp(_jmpbuf, 0) == 0) {
// make sure we can see in the signal handler that we have crash protection
// installed
_crash_protection = this;
cb.call();
// and clear the crash protection
_crash_protection = NULL;
_protected_thread = NULL;
Thread::muxRelease(&_crash_mux);
return true;
}
// this happens when we siglongjmp() back
pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
_crash_protection = NULL;
_protected_thread = NULL;
Thread::muxRelease(&_crash_mux);
return false;
}
void os::ThreadCrashProtection::restore() {
assert(_crash_protection != NULL, "must have crash protection");
siglongjmp(_jmpbuf, 1);
}
void os::ThreadCrashProtection::check_crash_protection(int sig,
Thread* thread) {
if (thread != NULL &&
thread == _protected_thread &&
_crash_protection != NULL) {
if (sig == SIGSEGV || sig == SIGBUS) {
_crash_protection->restore();
}
}
}
os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
} }
......
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -61,6 +61,33 @@ public: ...@@ -61,6 +61,33 @@ public:
}; };
/*
* Crash protection utility used by JFR. Wrap the callback
* with a sigsetjmp and in case of a SIGSEGV/SIGBUS we siglongjmp
* back.
* To be able to use this - don't take locks, don't rely on destructors,
* don't make OS library calls, don't allocate memory, don't print,
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
class ThreadCrashProtection : public StackObj {
public:
static bool is_crash_protected(Thread* thr) {
return _crash_protection != NULL && _protected_thread == thr;
}
ThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
static void check_crash_protection(int signal, Thread* thread);
private:
static Thread* _protected_thread;
static ThreadCrashProtection* _crash_protection;
static volatile intptr_t _crash_mux;
void restore();
sigjmp_buf _jmpbuf;
};
/* /*
* Crash protection for the watcher thread. Wrap the callback * Crash protection for the watcher thread. Wrap the callback
* with a sigsetjmp and in case of a SIGSEGV/SIGBUS we siglongjmp * with a sigsetjmp and in case of a SIGSEGV/SIGBUS we siglongjmp
......
/*
* Copyright (c) 2019, 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/precompiled.hpp"
#ifndef __APPLE__
#include "runtime/os.hpp"
// POSIX unamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#include <semaphore.h>
#define check_with_errno(check_type, cond, msg) \
do { \
int err = errno; \
check_type(cond, msg); \
} while (false)
#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg)
#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
PosixSemaphore::PosixSemaphore(uint value) {
int ret = sem_init(&_semaphore, 0, value);
guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
}
PosixSemaphore::~PosixSemaphore() {
sem_destroy(&_semaphore);
}
void PosixSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
int ret = sem_post(&_semaphore);
assert_with_errno(ret == 0, "sem_post failed");
}
}
void PosixSemaphore::wait() {
int ret;
do {
ret = sem_wait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0, "sem_wait failed");
}
bool PosixSemaphore::trywait() {
int ret;
do {
ret = sem_trywait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed");
return ret == 0;
}
bool PosixSemaphore::timedwait(struct timespec ts) {
while (true) {
int result = sem_timedwait(&_semaphore, &ts);
if (result == 0) {
return true;
} else if (errno == EINTR) {
continue;
} else if (errno == ETIMEDOUT) {
return false;
} else {
assert_with_errno(false, "timedwait failed");
return false;
}
}
}
#endif // __APPLE__
/*
* Copyright (c) 2015, 2019, 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 OS_POSIX_VM_SEMAPHORE_POSIX_HPP
#define OS_POSIX_VM_SEMAPHORE_POSIX_HPP
#include "memory/allocation.hpp"
#include <semaphore.h>
class PosixSemaphore : public CHeapObj<mtInternal> {
sem_t _semaphore;
// Prevent copying and assignment.
PosixSemaphore(const PosixSemaphore&);
PosixSemaphore& operator=(const PosixSemaphore&);
public:
PosixSemaphore(uint value = 0);
~PosixSemaphore();
void signal(uint count = 1);
void wait();
bool trywait();
bool timedwait(struct timespec ts);
};
typedef PosixSemaphore SemaphoreImpl;
#endif // OS_POSIX_VM_SEMAPHORE_POSIX_HPP
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -102,6 +102,10 @@ inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* ...@@ -102,6 +102,10 @@ inline jint Atomic::cmpxchg (jint exchange_value, volatile jint*
#ifdef AMD64 #ifdef AMD64
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline void Atomic::store (julong store_value, julong* dest) {
assert(EnableJFR, "sanity check");
*dest = store_value;
}
inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
intptr_t addend = add_value; intptr_t addend = add_value;
......
/* /*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -73,8 +73,21 @@ inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } ...@@ -73,8 +73,21 @@ inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); } inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); }
inline bool OrderAccess::load_acquire(const volatile bool* p) {
assert(EnableJFR, "sanity check");
return *p;
}
inline julong OrderAccess::load_acquire(const volatile julong* p) {
assert(EnableJFR, "sanity check");
return Atomic::load((volatile jlong*)p);
}
inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; }
inline uintptr_t OrderAccess::load_ptr_acquire(const volatile uintptr_t* p) {
assert(EnableJFR, "sanity check");
return *p;
}
inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; }
inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; }
......
/* /*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -224,6 +224,8 @@ JVM_handle_linux_signal(int sig, ...@@ -224,6 +224,8 @@ JVM_handle_linux_signal(int sig,
// (no destructors can be run) // (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t); os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
os::ThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t); SignalHandlerMark shm(t);
// Note: it's not uncommon that JNI code uses signal/sigset to install // Note: it's not uncommon that JNI code uses signal/sigset to install
......
/* /*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -3461,10 +3461,11 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { ...@@ -3461,10 +3461,11 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
break; break;
#ifdef TRACE_HAVE_INTRINSICS #ifdef TRACE_HAVE_INTRINSICS
case vmIntrinsics::_classID: case vmIntrinsics::_getClassId:
case vmIntrinsics::_threadID: cantrap = false;
preserves_state = true; break;
cantrap = true;
case vmIntrinsics::_getEventWriter:
break; break;
case vmIntrinsics::_counterTime: case vmIntrinsics::_counterTime:
...@@ -4411,6 +4412,18 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes ...@@ -4411,6 +4412,18 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
log->inline_fail("reason unknown"); log->inline_fail("reason unknown");
} }
} }
#if INCLUDE_TRACE
EventCompilerInlining event;
if (event.should_commit()) {
event.set_compileId(compilation()->env()->task()->compile_id());
event.set_message(msg);
event.set_succeeded(success);
event.set_bci(bci());
event.set_caller(method()->get_Method());
event.set_callee(callee->to_trace_struct());
event.commit();
}
#endif // INCLUDE_TRACE
if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) { if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
return; return;
......
/* /*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
#include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegion.hpp"
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
#ifdef TRACE_HAVE_INTRINSICS
#include "trace/traceMacros.hpp"
#endif
#ifdef ASSERT #ifdef ASSERT
#define __ gen()->lir(__FILE__, __LINE__)-> #define __ gen()->lir(__FILE__, __LINE__)->
...@@ -3069,39 +3072,47 @@ void LIRGenerator::do_RuntimeCall(address routine, int expected_arguments, Intri ...@@ -3069,39 +3072,47 @@ void LIRGenerator::do_RuntimeCall(address routine, int expected_arguments, Intri
} }
#ifdef TRACE_HAVE_INTRINSICS #ifdef TRACE_HAVE_INTRINSICS
void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) { void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) {
LIR_Opr thread = getThreadPointer(); CodeEmitInfo* info = state_for(x);
LIR_Opr osthread = new_pointer_register(); CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check
__ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread);
size_t thread_id_size = OSThread::thread_id_size(); assert(info != NULL, "must have info");
if (thread_id_size == (size_t) BytesPerLong) { LIRItem arg(x->argument_at(0), this);
LIR_Opr id = new_register(T_LONG);
__ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id); arg.load_item();
__ convert(Bytecodes::_l2i, id, rlock_result(x)); LIR_Opr klass = new_register(T_METADATA);
} else if (thread_id_size == (size_t) BytesPerInt) { __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), klass, info);
__ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x)); LIR_Opr id = new_register(T_LONG);
} else { ByteSize offset = TRACE_KLASS_TRACE_ID_OFFSET;
ShouldNotReachHere(); LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG);
}
__ move(trace_id_addr, id);
__ logical_or(id, LIR_OprFact::longConst(0x01l), id);
__ store(id, trace_id_addr);
#ifdef TRACE_ID_META_BITS
__ logical_and(id, LIR_OprFact::longConst(~TRACE_ID_META_BITS), id);
#endif
#ifdef TRACE_ID_CLASS_SHIFT
__ unsigned_shift_right(id, TRACE_ID_CLASS_SHIFT, id);
#endif
__ move(id, rlock_result(x));
} }
void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { void LIRGenerator::do_getEventWriter(Intrinsic* x) {
CodeEmitInfo* info = state_for(x); LabelObj* L_end = new LabelObj();
CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check
BasicType klass_pointer_type = NOT_LP64(T_INT) LP64_ONLY(T_LONG); LIR_Address* jobj_addr = new LIR_Address(getThreadPointer(),
assert(info != NULL, "must have info"); in_bytes(TRACE_THREAD_DATA_WRITER_OFFSET),
LIRItem arg(x->argument_at(1), this); T_OBJECT);
arg.load_item(); LIR_Opr result = rlock_result(x);
LIR_Opr klass = new_pointer_register(); __ move_wide(jobj_addr, result);
__ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), klass_pointer_type), klass, info); __ cmp(lir_cond_equal, result, LIR_OprFact::oopConst(NULL));
LIR_Opr id = new_register(T_LONG); __ branch(lir_cond_equal, T_OBJECT, L_end->label());
ByteSize offset = TRACE_ID_OFFSET; __ move_wide(new LIR_Address(result, T_OBJECT), result);
LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG);
__ move(trace_id_addr, id); __ branch_destination(L_end->label());
__ logical_or(id, LIR_OprFact::longConst(0x01l), id);
__ store(id, trace_id_addr);
__ logical_and(id, LIR_OprFact::longConst(~0x3l), id);
__ move(id, rlock_result(x));
} }
#endif #endif
...@@ -3116,8 +3127,16 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { ...@@ -3116,8 +3127,16 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
} }
#ifdef TRACE_HAVE_INTRINSICS #ifdef TRACE_HAVE_INTRINSICS
case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break; case vmIntrinsics::_getClassId:
case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break; if (EnableJFR) {
do_ClassIDIntrinsic(x);
}
break;
case vmIntrinsics::_getEventWriter:
if (EnableJFR) {
do_getEventWriter(x);
}
break;
case vmIntrinsics::_counterTime: case vmIntrinsics::_counterTime:
do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), 0, x); do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), 0, x);
break; break;
......
/* /*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -437,8 +437,8 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { ...@@ -437,8 +437,8 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x); void do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x);
#ifdef TRACE_HAVE_INTRINSICS #ifdef TRACE_HAVE_INTRINSICS
void do_ThreadIDIntrinsic(Intrinsic* x);
void do_ClassIDIntrinsic(Intrinsic* x); void do_ClassIDIntrinsic(Intrinsic* x);
void do_getEventWriter(Intrinsic* x);
#endif #endif
ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k,
Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k,
......
/* /*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1467,3 +1467,13 @@ void ciMethod::print_impl(outputStream* st) { ...@@ -1467,3 +1467,13 @@ void ciMethod::print_impl(outputStream* st) {
st->print(" loaded=false"); st->print(" loaded=false");
} }
} }
#if INCLUDE_TRACE
TraceStructCalleeMethod ciMethod::to_trace_struct() const {
TraceStructCalleeMethod result;
result.set_type(holder()->name()->as_utf8());
result.set_name(name()->as_utf8());
result.set_descriptor(signature()->as_symbol()->as_utf8());
return result;
}
#endif
/* /*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "compiler/methodLiveness.hpp" #include "compiler/methodLiveness.hpp"
#include "prims/methodHandles.hpp" #include "prims/methodHandles.hpp"
#include "utilities/bitMap.hpp" #include "utilities/bitMap.hpp"
#include "trace/tracing.hpp"
class ciMethodBlocks; class ciMethodBlocks;
class MethodLiveness; class MethodLiveness;
...@@ -93,12 +94,6 @@ class ciMethod : public ciMetadata { ...@@ -93,12 +94,6 @@ class ciMethod : public ciMetadata {
ciMethod(methodHandle h_m, ciInstanceKlass* holder); ciMethod(methodHandle h_m, ciInstanceKlass* holder);
ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor);
Method* get_Method() const {
Method* m = (Method*)_metadata;
assert(m != NULL, "illegal use of unloaded method");
return m;
}
oop loader() const { return _holder->loader(); } oop loader() const { return _holder->loader(); }
const char* type_string() { return "ciMethod"; } const char* type_string() { return "ciMethod"; }
...@@ -156,6 +151,11 @@ class ciMethod : public ciMetadata { ...@@ -156,6 +151,11 @@ class ciMethod : public ciMetadata {
} }
} }
Method* get_Method() const {
Method* m = (Method*)_metadata;
assert(m != NULL, "illegal use of unloaded method");
return m;
}
// Method code and related information. // Method code and related information.
address code() { if (_code == NULL) load_code(); return _code; } address code() { if (_code == NULL) load_code(); return _code; }
...@@ -347,6 +347,10 @@ class ciMethod : public ciMetadata { ...@@ -347,6 +347,10 @@ class ciMethod : public ciMetadata {
// Print the name of this method in various incarnations. // Print the name of this method in various incarnations.
void print_name(outputStream* st = tty); void print_name(outputStream* st = tty);
void print_short_name(outputStream* st = tty); void print_short_name(outputStream* st = tty);
#if INCLUDE_TRACE
TraceStructCalleeMethod to_trace_struct() const;
#endif
}; };
#endif // SHARE_VM_CI_CIMETHOD_HPP #endif // SHARE_VM_CI_CIMETHOD_HPP
/* /*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "runtime/timer.hpp" #include "runtime/timer.hpp"
#include "services/classLoadingService.hpp" #include "services/classLoadingService.hpp"
#include "services/threadService.hpp" #include "services/threadService.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/array.hpp" #include "utilities/array.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp" #include "utilities/ostream.hpp"
...@@ -3885,6 +3886,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3885,6 +3886,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// This class and superclass // This class and superclass
u2 this_class_index = cfs->get_u2_fast(); u2 this_class_index = cfs->get_u2_fast();
_this_class_index = this_class_index; //used by jfr
check_property( check_property(
valid_cp_range(this_class_index, cp_size) && valid_cp_range(this_class_index, cp_size) &&
cp->tag_at(this_class_index).is_unresolved_klass(), cp->tag_at(this_class_index).is_unresolved_klass(),
...@@ -4212,6 +4214,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -4212,6 +4214,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
ClassLoadingService::notify_class_loaded(InstanceKlass::cast(this_klass()), ClassLoadingService::notify_class_loaded(InstanceKlass::cast(this_klass()),
false /* not shared class */); false /* not shared class */);
TRACE_INIT_ID(InstanceKlass::cast(this_klass()));
if (TraceClassLoading) { if (TraceClassLoading) {
ResourceMark rm; ResourceMark rm;
...@@ -5273,3 +5276,19 @@ char* ClassFileParser::skip_over_field_signature(char* signature, ...@@ -5273,3 +5276,19 @@ char* ClassFileParser::skip_over_field_signature(char* signature,
} }
return NULL; return NULL;
} }
const ClassFileStream* ClassFileParser::clone_stream() const {
assert(_stream != NULL, "invariant");
return _stream->clone();
}
void ClassFileParser::set_klass_to_deallocate(InstanceKlass* klass) {
#ifdef ASSERT
if (klass != NULL) {
assert(NULL == _klass, "leaking?");
}
#endif
_klass = klass;
}
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,6 +47,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -47,6 +47,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool _relax_verify; bool _relax_verify;
u2 _major_version; u2 _major_version;
u2 _minor_version; u2 _minor_version;
u2 _this_class_index;
Symbol* _class_name; Symbol* _class_name;
ClassLoaderData* _loader_data; ClassLoaderData* _loader_data;
KlassHandle _host_klass; KlassHandle _host_klass;
...@@ -90,6 +91,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -90,6 +91,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void create_combined_annotations(TRAPS); void create_combined_annotations(TRAPS);
void init_parsed_class_attributes(ClassLoaderData* loader_data) { void init_parsed_class_attributes(ClassLoaderData* loader_data) {
_this_class_index = 0;
_loader_data = loader_data; _loader_data = loader_data;
_synthetic_flag = false; _synthetic_flag = false;
_sourcefile_index = 0; _sourcefile_index = 0;
...@@ -486,6 +488,10 @@ PRAGMA_DIAG_POP ...@@ -486,6 +488,10 @@ PRAGMA_DIAG_POP
bool verify, bool verify,
TRAPS); TRAPS);
u2 this_class_index() const { return _this_class_index; }
const ClassFileStream* clone_stream() const;
void set_klass_to_deallocate(InstanceKlass* klass);
// Verifier checks // Verifier checks
static void check_super_class_access(instanceKlassHandle this_klass, TRAPS); static void check_super_class_access(instanceKlassHandle this_klass, TRAPS);
static void check_super_interface_access(instanceKlassHandle this_klass, TRAPS); static void check_super_interface_access(instanceKlassHandle this_klass, TRAPS);
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,6 +38,33 @@ ClassFileStream::ClassFileStream(u1* buffer, int length, const char* source) { ...@@ -38,6 +38,33 @@ ClassFileStream::ClassFileStream(u1* buffer, int length, const char* source) {
_need_verify = false; _need_verify = false;
} }
const u1* ClassFileStream::clone_buffer() const {
u1* const new_buffer_start = NEW_RESOURCE_ARRAY(u1, length());
memcpy(new_buffer_start, _buffer_start, length());
return new_buffer_start;
}
const char* const ClassFileStream::clone_source() const {
const char* const src = source();
char* source_copy = NULL;
if (src != NULL) {
size_t source_len = strlen(src);
source_copy = NEW_RESOURCE_ARRAY(char, source_len + 1);
strncpy(source_copy, src, source_len + 1);
}
return source_copy;
}
// Caller responsible for ResourceMark
// clone stream with a rewound position
const ClassFileStream* ClassFileStream::clone() const {
const u1* const new_buffer_start = clone_buffer();
return new ClassFileStream(const_cast<u1*>(new_buffer_start),
length(),
clone_source()/*,
need_verify()*/);
}
u1 ClassFileStream::get_u1(TRAPS) { u1 ClassFileStream::get_u1(TRAPS) {
if (_need_verify) { if (_need_verify) {
guarantee_more(1, CHECK_0); guarantee_more(1, CHECK_0);
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -57,15 +57,24 @@ class ClassFileStream: public ResourceObj { ...@@ -57,15 +57,24 @@ class ClassFileStream: public ResourceObj {
bool _need_verify; // True if verification is on for the class file bool _need_verify; // True if verification is on for the class file
void truncated_file_error(TRAPS); void truncated_file_error(TRAPS);
protected:
const u1* clone_buffer() const;
const char* const clone_source() const;
public: public:
// Constructor // Constructor
ClassFileStream(u1* buffer, int length, const char* source); ClassFileStream(u1* buffer, int length, const char* source);
virtual const ClassFileStream* clone() const;
// Buffer access // Buffer access
u1* buffer() const { return _buffer_start; } u1* buffer() const { return _buffer_start; }
int length() const { return _buffer_end - _buffer_start; } int length() const { return _buffer_end - _buffer_start; }
u1* current() const { return _current; } u1* current() const { return _current; }
void set_current(u1* pos) { _current = pos; } void set_current(u1* pos) { _current = pos; }
// for relative positioning
juint current_offset() const {
return (juint)(_current - _buffer_start);
}
const char* source() const { return _source; } const char* source() const { return _source; }
void set_verify(bool flag) { _need_verify = flag; } void set_verify(bool flag) { _need_verify = flag; }
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1127,6 +1127,8 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { ...@@ -1127,6 +1127,8 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
parsed_name, parsed_name,
context.should_verify(classpath_index), context.should_verify(classpath_index),
THREAD); THREAD);
TRACE_KLASS_CREATION(result, parser, THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
ResourceMark rm; ResourceMark rm;
if (DumpSharedSpaces) { if (DumpSharedSpaces) {
......
...@@ -82,6 +82,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen ...@@ -82,6 +82,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
_next(NULL), _dependencies(dependencies), _next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
// empty // empty
TRACE_INIT_ID(this);
} }
void ClassLoaderData::init_dependencies(TRAPS) { void ClassLoaderData::init_dependencies(TRAPS) {
...@@ -646,6 +647,20 @@ void ClassLoaderDataGraph::cld_do(CLDClosure* cl) { ...@@ -646,6 +647,20 @@ void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
} }
} }
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
// this method is only used by jfr now, if you need to use this method in another case,
// this check should be removed.
assert(EnableJFR && FlightRecorder, "just check");
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cl->do_cld(cld);
}
}
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) { void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
CLDClosure* closure = cld->keep_alive() ? strong : weak; CLDClosure* closure = cld->keep_alive() ? strong : weak;
...@@ -980,9 +995,7 @@ void ClassLoaderDataGraph::class_unload_event(Klass* const k) { ...@@ -980,9 +995,7 @@ void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
EventClassUnload event(UNTIMED); EventClassUnload event(UNTIMED);
event.set_endtime(_class_unload_time); event.set_endtime(_class_unload_time);
event.set_unloadedClass(k); event.set_unloadedClass(k);
oop defining_class_loader = k->class_loader(); event.set_definingClassLoader(k->class_loader_data());
event.set_definingClassLoader(defining_class_loader != NULL ?
defining_class_loader->klass() : (Klass*)NULL);
event.commit(); event.commit();
} }
......
/* /*
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#if INCLUDE_TRACE #if INCLUDE_TRACE
#include "utilities/ticks.hpp" #include "utilities/ticks.hpp"
#endif #endif
#include "jfr/utilities/jfrLog.hpp"
// //
// A class loader represents a linkset. Conceptually, a linkset identifies // A class loader represents a linkset. Conceptually, a linkset identifies
...@@ -82,6 +83,7 @@ class ClassLoaderDataGraph : public AllStatic { ...@@ -82,6 +83,7 @@ class ClassLoaderDataGraph : public AllStatic {
static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
// cld do // cld do
static void cld_do(CLDClosure* cl); static void cld_do(CLDClosure* cl);
static void cld_unloading_do(CLDClosure* cl);
static void roots_cld_do(CLDClosure* strong, CLDClosure* weak); static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
static void keep_alive_cld_do(CLDClosure* cl); static void keep_alive_cld_do(CLDClosure* cl);
static void always_strong_cld_do(CLDClosure* cl); static void always_strong_cld_do(CLDClosure* cl);
...@@ -128,6 +130,8 @@ class ClassLoaderDataGraph : public AllStatic { ...@@ -128,6 +130,8 @@ class ClassLoaderDataGraph : public AllStatic {
class ClassLoaderData : public CHeapObj<mtClass> { class ClassLoaderData : public CHeapObj<mtClass> {
friend class VMStructs; friend class VMStructs;
friend class CLDClaimContext;
friend class CLDClaimStateClosure;
private: private:
class Dependencies VALUE_OBJ_CLASS_SPEC { class Dependencies VALUE_OBJ_CLASS_SPEC {
objArrayOop _list_head; objArrayOop _list_head;
...@@ -213,6 +217,8 @@ class ClassLoaderData : public CHeapObj<mtClass> { ...@@ -213,6 +217,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
static Metaspace* _ro_metaspace; static Metaspace* _ro_metaspace;
static Metaspace* _rw_metaspace; static Metaspace* _rw_metaspace;
TRACE_DEFINE_TRACE_ID_FIELD;
void set_next(ClassLoaderData* next) { _next = next; } void set_next(ClassLoaderData* next) { _next = next; }
ClassLoaderData* next() const { return _next; } ClassLoaderData* next() const { return _next; }
...@@ -325,6 +331,8 @@ class ClassLoaderData : public CHeapObj<mtClass> { ...@@ -325,6 +331,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
Metaspace* ro_metaspace(); Metaspace* ro_metaspace();
Metaspace* rw_metaspace(); Metaspace* rw_metaspace();
void initialize_shared_metaspaces(); void initialize_shared_metaspaces();
TRACE_DEFINE_TRACE_ID_METHODS;
}; };
// An iterator that distributes Klasses to parallel worker threads. // An iterator that distributes Klasses to parallel worker threads.
......
/* /*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1047,7 +1047,7 @@ void java_lang_Thread::set_thread_status(oop java_thread, ...@@ -1047,7 +1047,7 @@ void java_lang_Thread::set_thread_status(oop java_thread,
// Read thread status value from threadStatus field in java.lang.Thread java class. // Read thread status value from threadStatus field in java.lang.Thread java class.
java_lang_Thread::ThreadStatus java_lang_Thread::get_thread_status(oop java_thread) { java_lang_Thread::ThreadStatus java_lang_Thread::get_thread_status(oop java_thread) {
assert(Thread::current()->is_Watcher_thread() || Thread::current()->is_VM_thread() || assert((EnableJFR && Threads_lock->owned_by_self()) || Thread::current()->is_Watcher_thread() || Thread::current()->is_VM_thread() ||
JavaThread::current()->thread_state() == _thread_in_vm, JavaThread::current()->thread_state() == _thread_in_vm,
"Java Thread is not running in vm"); "Java Thread is not running in vm");
// The threadStatus is only present starting in 1.5 // The threadStatus is only present starting in 1.5
......
/* /*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1003,15 +1003,16 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, ...@@ -1003,15 +1003,16 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name,
// //
// Note: "name" is updated. // Note: "name" is updated.
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, ClassFileParser parser(st);
loader_data, instanceKlassHandle k = parser.parseClassFile(class_name,
protection_domain, loader_data,
host_klass, protection_domain,
cp_patches, host_klass,
parsed_name, cp_patches,
true, parsed_name,
THREAD); true,
THREAD);
TRACE_KLASS_CREATION(k, parser, THREAD);
if (host_klass.not_null() && k.not_null()) { if (host_klass.not_null() && k.not_null()) {
assert(EnableInvokeDynamic, ""); assert(EnableInvokeDynamic, "");
...@@ -1085,12 +1086,14 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, ...@@ -1085,12 +1086,14 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
// //
// Note: "name" is updated. // Note: "name" is updated.
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, ClassFileParser parser(st);
loader_data, instanceKlassHandle k = parser.parseClassFile(class_name,
protection_domain, loader_data,
parsed_name, protection_domain,
verify, parsed_name,
THREAD); verify,
THREAD);
TRACE_KLASS_CREATION(k, parser, THREAD);
const char* pkg = "java/"; const char* pkg = "java/";
size_t pkglen = strlen(pkg); size_t pkglen = strlen(pkg);
...@@ -1385,6 +1388,19 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha ...@@ -1385,6 +1388,19 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
} }
} }
static void class_define_event(InstanceKlass* k,
const ClassLoaderData* def_cld) {
#if INCLUDE_TRACE
EventClassDefine event;
if (event.should_commit()) {
ResourceMark m;
event.set_definedClass(k);
event.set_definingClassLoader(def_cld);
event.commit();
}
#endif // INCLUDE_TRACE
}
void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) {
ClassLoaderData* loader_data = k->class_loader_data(); ClassLoaderData* loader_data = k->class_loader_data();
...@@ -1455,6 +1471,7 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { ...@@ -1455,6 +1471,7 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) {
} }
class_define_event(k(), loader_data);
} }
// Support parallel classloading // Support parallel classloading
...@@ -2692,16 +2709,11 @@ void SystemDictionary::post_class_load_event(const Ticks& start_time, ...@@ -2692,16 +2709,11 @@ void SystemDictionary::post_class_load_event(const Ticks& start_time,
instanceKlassHandle k, instanceKlassHandle k,
Handle initiating_loader) { Handle initiating_loader) {
#if INCLUDE_TRACE #if INCLUDE_TRACE
EventClassLoad event(UNTIMED); EventClassLoad event;
if (event.should_commit()) { if (event.should_commit()) {
event.set_starttime(start_time);
event.set_loadedClass(k()); event.set_loadedClass(k());
oop defining_class_loader = k->class_loader(); event.set_definingClassLoader(k->class_loader_data());
event.set_definingClassLoader(defining_class_loader != NULL ? event.set_initiatingClassLoader(ClassLoaderData::class_loader_data_or_null(initiating_loader()));
defining_class_loader->klass() : (Klass*)NULL);
oop class_loader = initiating_loader.is_null() ? (oop)NULL : initiating_loader();
event.set_initiatingClassLoader(class_loader != NULL ?
class_loader->klass() : (Klass*)NULL);
event.commit(); event.commit();
} }
#endif // INCLUDE_TRACE #endif // INCLUDE_TRACE
......
/* /*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -77,7 +77,6 @@ class LoaderConstraintTable; ...@@ -77,7 +77,6 @@ class LoaderConstraintTable;
template <MEMFLAGS F> class HashtableBucket; template <MEMFLAGS F> class HashtableBucket;
class ResolutionErrorTable; class ResolutionErrorTable;
class SymbolPropertyTable; class SymbolPropertyTable;
class Ticks;
// Certain classes are preloaded, such as java.lang.Object and java.lang.String. // Certain classes are preloaded, such as java.lang.Object and java.lang.String.
// They are all "well-known", in the sense that no class loader is allowed // They are all "well-known", in the sense that no class loader is allowed
......
/* /*
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
#include "c1/c1_Runtime1.hpp" #include "c1/c1_Runtime1.hpp"
#endif #endif
unsigned int align_code_offset(int offset) { unsigned int CodeBlob::align_code_offset(int offset) {
// align the size to CodeEntryAlignment // align the size to CodeEntryAlignment
return return
((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1)) ((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1))
......
/* /*
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,6 +30,15 @@ ...@@ -30,6 +30,15 @@
#include "runtime/frame.hpp" #include "runtime/frame.hpp"
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
// CodeBlob Types, used for jfr
// Used in the CodeCache to assign CodeBlobs to different CodeHeaps
struct CodeBlobType {
enum {
All = 0, // All types (No code cache segmentation)
NumTypes = 1 // Number of CodeBlobTypes
};
};
// CodeBlob - superclass for all entries in the CodeCache. // CodeBlob - superclass for all entries in the CodeCache.
// //
// Suptypes are: // Suptypes are:
...@@ -71,6 +80,7 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { ...@@ -71,6 +80,7 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
public: public:
// Returns the space needed for CodeBlob // Returns the space needed for CodeBlob
static unsigned int allocation_size(CodeBuffer* cb, int header_size); static unsigned int allocation_size(CodeBuffer* cb, int header_size);
static unsigned int align_code_offset(int offset);
// Creation // Creation
// a) simple CodeBlob // a) simple CodeBlob
...@@ -205,6 +215,7 @@ class BufferBlob: public CodeBlob { ...@@ -205,6 +215,7 @@ class BufferBlob: public CodeBlob {
friend class AdapterBlob; friend class AdapterBlob;
friend class VtableBlob; friend class VtableBlob;
friend class MethodHandlesAdapterBlob; friend class MethodHandlesAdapterBlob;
friend class WhiteBox;
private: private:
// Creation support // Creation support
......
/* /*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -188,6 +188,14 @@ CodeBlob* CodeCache::allocate(int size, bool is_critical) { ...@@ -188,6 +188,14 @@ CodeBlob* CodeCache::allocate(int size, bool is_critical) {
if (cb != NULL) break; if (cb != NULL) break;
if (!_heap->expand_by(CodeCacheExpansionSize)) { if (!_heap->expand_by(CodeCacheExpansionSize)) {
// Expansion failed // Expansion failed
if (EnableJFR) {
if (CodeCache_lock->owned_by_self()) {
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
report_codemem_full();
} else {
report_codemem_full();
}
}
return NULL; return NULL;
} }
if (PrintCodeCacheExtension) { if (PrintCodeCacheExtension) {
...@@ -779,6 +787,7 @@ void CodeCache::report_codemem_full() { ...@@ -779,6 +787,7 @@ void CodeCache::report_codemem_full() {
_codemem_full_count++; _codemem_full_count++;
EventCodeCacheFull event; EventCodeCacheFull event;
if (event.should_commit()) { if (event.should_commit()) {
event.set_codeBlobType((u1)CodeBlobType::All);
event.set_startAddress((u8)low_bound()); event.set_startAddress((u8)low_bound());
event.set_commitedTopAddress((u8)high()); event.set_commitedTopAddress((u8)high());
event.set_reservedTopAddress((u8)high_bound()); event.set_reservedTopAddress((u8)high_bound());
......
...@@ -2035,7 +2035,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { ...@@ -2035,7 +2035,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
assert(task->compile_id() != CICrashAt, "just as planned"); assert(task->compile_id() != CICrashAt, "just as planned");
if (event.should_commit()) { if (event.should_commit()) {
event.set_method(target->get_Method()); event.set_method(target->get_Method());
event.set_compileID(compile_id); event.set_compileId(compile_id);
event.set_compileLevel(task->comp_level()); event.set_compileLevel(task->comp_level());
event.set_succeded(task->is_success()); event.set_succeded(task->is_success());
event.set_isOsr(is_osr); event.set_isOsr(is_osr);
......
/* /*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -75,7 +75,6 @@ class G1NewTracer; ...@@ -75,7 +75,6 @@ class G1NewTracer;
class G1OldTracer; class G1OldTracer;
class EvacuationFailedInfo; class EvacuationFailedInfo;
class nmethod; class nmethod;
class Ticks;
typedef OverflowTaskQueue<StarTask, mtGC> RefToScanQueue; typedef OverflowTaskQueue<StarTask, mtGC> RefToScanQueue;
typedef GenericTaskQueueSet<RefToScanQueue, mtGC> RefToScanQueueSet; typedef GenericTaskQueueSet<RefToScanQueue, mtGC> RefToScanQueueSet;
...@@ -1082,6 +1081,7 @@ public: ...@@ -1082,6 +1081,7 @@ public:
ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; }
G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; }
G1NewTracer* gc_tracer_stw() const { return _gc_tracer_stw; }
virtual size_t capacity() const; virtual size_t capacity() const;
virtual size_t used() const; virtual size_t used() const;
......
/* /*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -282,6 +282,9 @@ G1CollectorPolicy::G1CollectorPolicy() : ...@@ -282,6 +282,9 @@ G1CollectorPolicy::G1CollectorPolicy() :
double max_gc_time = (double) MaxGCPauseMillis / 1000.0; double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
double time_slice = (double) GCPauseIntervalMillis / 1000.0; double time_slice = (double) GCPauseIntervalMillis / 1000.0;
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time); _mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
if (EnableJFR) {
_ihop_control = create_ihop_control();
}
uintx confidence_perc = G1ConfidencePercent; uintx confidence_perc = G1ConfidencePercent;
// Put an artificial ceiling on this so that it's not set to a silly value. // Put an artificial ceiling on this so that it's not set to a silly value.
...@@ -320,6 +323,13 @@ G1CollectorPolicy::G1CollectorPolicy() : ...@@ -320,6 +323,13 @@ G1CollectorPolicy::G1CollectorPolicy() :
_collectionSetChooser = new CollectionSetChooser(); _collectionSetChooser = new CollectionSetChooser();
} }
G1CollectorPolicy::~G1CollectorPolicy() {
if (EnableJFR) {
assert(_ihop_control != NULL, "sanity check");
delete _ihop_control;
}
}
void G1CollectorPolicy::initialize_alignments() { void G1CollectorPolicy::initialize_alignments() {
_space_alignment = HeapRegion::GrainBytes; _space_alignment = HeapRegion::GrainBytes;
size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable); size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
...@@ -507,6 +517,10 @@ void G1CollectorPolicy::record_new_heap_size(uint new_number_of_regions) { ...@@ -507,6 +517,10 @@ void G1CollectorPolicy::record_new_heap_size(uint new_number_of_regions) {
_reserve_regions = (uint) ceil(reserve_regions_d); _reserve_regions = (uint) ceil(reserve_regions_d);
_young_gen_sizer->heap_size_changed(new_number_of_regions); _young_gen_sizer->heap_size_changed(new_number_of_regions);
if (EnableJFR) {
_ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes);
}
} }
uint G1CollectorPolicy::calculate_young_list_desired_min_length( uint G1CollectorPolicy::calculate_young_list_desired_min_length(
...@@ -1189,6 +1203,15 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, Evacua ...@@ -1189,6 +1203,15 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, Evacua
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS), update_rs_time_goal_ms); phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS), update_rs_time_goal_ms);
_collectionSetChooser->verify(); _collectionSetChooser->verify();
if (EnableJFR) {
_ihop_control->send_trace_event(_g1->gc_tracer_stw());
}
}
G1IHOPControl* G1CollectorPolicy::create_ihop_control() {
assert(EnableJFR, "sanity check");
return new G1StaticIHOPControl(InitiatingHeapOccupancyPercent);
} }
#define EXT_SIZE_FORMAT "%.1f%s" #define EXT_SIZE_FORMAT "%.1f%s"
......
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "gc_implementation/g1/collectionSetChooser.hpp" #include "gc_implementation/g1/collectionSetChooser.hpp"
#include "gc_implementation/g1/g1Allocator.hpp" #include "gc_implementation/g1/g1Allocator.hpp"
#include "gc_implementation/g1/g1MMUTracker.hpp" #include "gc_implementation/g1/g1MMUTracker.hpp"
#include "gc_implementation/g1/g1IHOPControl.hpp"
#include "memory/collectorPolicy.hpp" #include "memory/collectorPolicy.hpp"
// A G1CollectorPolicy makes policy decisions that determine the // A G1CollectorPolicy makes policy decisions that determine the
...@@ -161,6 +162,8 @@ public: ...@@ -161,6 +162,8 @@ public:
class G1CollectorPolicy: public CollectorPolicy { class G1CollectorPolicy: public CollectorPolicy {
private: private:
static G1IHOPControl* create_ihop_control();
// either equal to the number of parallel threads, if ParallelGCThreads // either equal to the number of parallel threads, if ParallelGCThreads
// has been set, or 1 otherwise // has been set, or 1 otherwise
int _parallel_gc_threads; int _parallel_gc_threads;
...@@ -173,6 +176,7 @@ private: ...@@ -173,6 +176,7 @@ private:
}; };
G1MMUTracker* _mmu_tracker; G1MMUTracker* _mmu_tracker;
G1IHOPControl* _ihop_control;
void initialize_alignments(); void initialize_alignments();
void initialize_flags(); void initialize_flags();
...@@ -636,6 +640,7 @@ private: ...@@ -636,6 +640,7 @@ private:
public: public:
G1CollectorPolicy(); G1CollectorPolicy();
virtual ~G1CollectorPolicy();
virtual G1CollectorPolicy* as_g1_policy() { return this; } virtual G1CollectorPolicy* as_g1_policy() { return this; }
......
/*
* Copyright (c) 2016, 2019, 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_VM_GC_G1_G1HEAPREGIONTRACETYPE_HPP
#define SHARE_VM_GC_G1_G1HEAPREGIONTRACETYPE_HPP
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
class G1HeapRegionTraceType : AllStatic {
public:
enum Type {
Free,
Eden,
Survivor,
StartsHumongous,
ContinuesHumongous,
Old,
Pinned,
OpenArchive,
ClosedArchive,
G1HeapRegionTypeEndSentinel
};
static const char* to_string(G1HeapRegionTraceType::Type type) {
switch (type) {
case Free: return "Free";
case Eden: return "Eden";
case Survivor: return "Survivor";
case StartsHumongous: return "Starts Humongous";
case ContinuesHumongous: return "Continues Humongous";
case Old: return "Old";
case Pinned: return "Pinned";
case OpenArchive: return "OpenArchive";
case ClosedArchive: return "ClosedArchive";
default: ShouldNotReachHere(); return NULL;
}
}
};
#endif // SHARE_VM_GC_G1_G1HEAPREGIONTRACETYPE_HPP
/*
* Copyright (c) 2015, 2019, 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 "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1IHOPControl.hpp"
#include "gc_implementation/shared/gcTrace.hpp"
#include "jfr/utilities/jfrLog.hpp"
G1IHOPControl::G1IHOPControl(double initial_ihop_percent) :
_initial_ihop_percent(initial_ihop_percent),
_target_occupancy(0),
_last_allocated_bytes(0),
_last_allocation_time_s(0.0)
{
assert(_initial_ihop_percent >= 0.0 && _initial_ihop_percent <= 100.0, "Initial IHOP value must be between 0 and 100.");
}
void G1IHOPControl::update_target_occupancy(size_t new_target_occupancy) {
log_debug(gc, ihop)("Target occupancy update: old: " SIZE_FORMAT "B, new: " SIZE_FORMAT "B",
_target_occupancy, new_target_occupancy);
_target_occupancy = new_target_occupancy;
}
void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size) {
assert(allocation_time_s >= 0.0, "Allocation time must be positive.");
_last_allocation_time_s = allocation_time_s;
_last_allocated_bytes = allocated_bytes;
}
// should be defined in globalDefinitions.hpp
template<typename T>
inline double percent_of(T numerator, T denominator) {
return denominator != 0 ? (double)numerator / denominator * 100.0 : 0.0;
}
void G1IHOPControl::print() {
assert(_target_occupancy > 0, "Target occupancy still not updated yet.");
size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold();
log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B, "
"recent allocation size: " SIZE_FORMAT "B, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms",
cur_conc_mark_start_threshold,
percent_of(cur_conc_mark_start_threshold, _target_occupancy),
_target_occupancy,
G1CollectedHeap::heap()->used(),
_last_allocated_bytes,
_last_allocation_time_s * 1000.0,
_last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0,
last_marking_length_s() * 1000.0);
}
void G1IHOPControl::send_trace_event(G1NewTracer* tracer) {
assert(_target_occupancy > 0, "Target occupancy still not updated yet.");
tracer->report_basic_ihop_statistics(get_conc_mark_start_threshold(),
_target_occupancy,
G1CollectedHeap::heap()->used(),
_last_allocated_bytes,
_last_allocation_time_s,
last_marking_length_s());
}
G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent) :
G1IHOPControl(ihop_percent),
_last_marking_length_s(0.0) {
}
/*
* Copyright (c) 2015, 2019, 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_VM_GC_G1_G1IHOPCONTROL_HPP
#define SHARE_VM_GC_G1_G1IHOPCONTROL_HPP
#include "memory/allocation.hpp"
#include "utilities/numberSeq.hpp"
class G1NewTracer;
// Base class for algorithms that calculate the heap occupancy at which
// concurrent marking should start. This heap usage threshold should be relative
// to old gen size.
class G1IHOPControl : public CHeapObj<mtGC> {
protected:
// The initial IHOP value relative to the target occupancy.
double _initial_ihop_percent;
// The target maximum occupancy of the heap. The target occupancy is the number
// of bytes when marking should be finished and reclaim started.
size_t _target_occupancy;
// Most recent complete mutator allocation period in seconds.
double _last_allocation_time_s;
// Amount of bytes allocated during _last_allocation_time_s.
size_t _last_allocated_bytes;
// Initialize an instance with the initial IHOP value in percent. The target
// occupancy will be updated at the first heap expansion.
G1IHOPControl(double initial_ihop_percent);
// Most recent time from the end of the initial mark to the start of the first
// mixed gc.
virtual double last_marking_length_s() const = 0;
public:
virtual ~G1IHOPControl() { }
// Get the current non-young occupancy at which concurrent marking should start.
virtual size_t get_conc_mark_start_threshold() = 0;
// Adjust target occupancy.
virtual void update_target_occupancy(size_t new_target_occupancy);
// Update information about time during which allocations in the Java heap occurred,
// how large these allocations were in bytes, and an additional buffer.
// The allocations should contain any amount of space made unusable for further
// allocation, e.g. any waste caused by TLAB allocation, space at the end of
// humongous objects that can not be used for allocation, etc.
// Together with the target occupancy, this additional buffer should contain the
// difference between old gen size and total heap size at the start of reclamation,
// and space required for that reclamation.
virtual void update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size);
// Update the time spent in the mutator beginning from the end of initial mark to
// the first mixed gc.
virtual void update_marking_length(double marking_length_s) = 0;
virtual void print();
virtual void send_trace_event(G1NewTracer* tracer);
};
// The returned concurrent mark starting occupancy threshold is a fixed value
// relative to the maximum heap size.
class G1StaticIHOPControl : public G1IHOPControl {
// Most recent mutator time between the end of initial mark to the start of the
// first mixed gc.
double _last_marking_length_s;
protected:
double last_marking_length_s() const { return _last_marking_length_s; }
public:
G1StaticIHOPControl(double ihop_percent);
size_t get_conc_mark_start_threshold() {
guarantee(_target_occupancy > 0, "Target occupancy must have been initialized.");
return (size_t) (_initial_ihop_percent * _target_occupancy / 100.0);
}
virtual void update_marking_length(double marking_length_s) {
assert(marking_length_s > 0.0, "Marking length must be larger than zero.");
_last_marking_length_s = marking_length_s;
}
};
#endif // SHARE_VM_GC_G1_G1IHOPCONTROL_HPP
/* /*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -105,6 +105,11 @@ void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) { ...@@ -105,6 +105,11 @@ void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
++_no_entries; ++_no_entries;
} }
_array[_head_index] = G1MMUTrackerQueueElem(start, end); _array[_head_index] = G1MMUTrackerQueueElem(start, end);
if (EnableJFR) {
double slice_time = calculate_gc_time(end);
G1MMUTracer::report_mmu(_time_slice, slice_time, _max_gc_time, gc_thread);
}
} }
// basically the _internal call does not remove expired entries // basically the _internal call does not remove expired entries
......
/* /*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -198,6 +198,21 @@ InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop co ...@@ -198,6 +198,21 @@ InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop co
return dest(state); return dest(state);
} }
void G1ParScanThreadState::report_promotion_event(InCSetState const dest_state,
oop const old, size_t word_sz, uint age,
HeapWord * const obj_ptr, AllocationContext_t context) const {
assert(EnableJFR, "sanity check");
ParGCAllocBuffer* alloc_buf = _g1_par_allocator->alloc_buffer(dest_state, context);
if (alloc_buf->contains(obj_ptr)) {
_g1h->_gc_tracer_stw->report_promotion_in_new_plab_event(old->klass(), word_sz, age,
dest_state.value() == InCSetState::Old,
alloc_buf->word_sz());
} else {
_g1h->_gc_tracer_stw->report_promotion_outside_plab_event(old->klass(), word_sz, age,
dest_state.value() == InCSetState::Old);
}
}
oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
oop const old, oop const old,
markOop const old_mark) { markOop const old_mark) {
...@@ -225,6 +240,10 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, ...@@ -225,6 +240,10 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
return _g1h->handle_evacuation_failure_par(this, old); return _g1h->handle_evacuation_failure_par(this, old);
} }
} }
if (EnableJFR && _g1h->_gc_tracer_stw->should_report_promotion_events()) {
// The events are checked individually as part of the actual commit
report_promotion_event(dest_state, old, word_sz, age, obj_ptr, context);
}
} }
assert(obj_ptr != NULL, "when we get here, allocation should have succeeded"); assert(obj_ptr != NULL, "when we get here, allocation should have succeeded");
......
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -213,6 +213,10 @@ class G1ParScanThreadState : public StackObj { ...@@ -213,6 +213,10 @@ class G1ParScanThreadState : public StackObj {
AllocationContext_t const context); AllocationContext_t const context);
inline InCSetState next_state(InCSetState const state, markOop const m, uint& age); inline InCSetState next_state(InCSetState const state, markOop const m, uint& age);
inline InCSetState next_state(InCSetState const state, markOop const m, uint& age, AllocationContext_t context);
void report_promotion_event(InCSetState const dest_state,
oop const old, size_t word_sz, uint age,
HeapWord * const obj_ptr, AllocationContext_t context) const;
public: public:
oop copy_to_survivor_space(InCSetState const state, oop const obj, markOop const old_mark); oop copy_to_survivor_space(InCSetState const state, oop const obj, markOop const old_mark);
......
/* /*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "gc_implementation/g1/heapRegionBounds.inline.hpp" #include "gc_implementation/g1/heapRegionBounds.inline.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "gc_implementation/g1/heapRegionManager.inline.hpp" #include "gc_implementation/g1/heapRegionManager.inline.hpp"
#include "gc_implementation/g1/heapRegionTracer.hpp"
#include "gc_implementation/shared/liveRange.hpp" #include "gc_implementation/shared/liveRange.hpp"
#include "memory/genOopClosures.inline.hpp" #include "memory/genOopClosures.inline.hpp"
#include "memory/iterator.hpp" #include "memory/iterator.hpp"
...@@ -217,7 +218,9 @@ void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) { ...@@ -217,7 +218,9 @@ void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
"Should be normal before the humongous object allocation"); "Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty"); assert(top() == bottom(), "should be empty");
assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); assert(bottom() <= new_top && new_top <= new_end, "pre-condition");
if (EnableJFR) {
report_region_type_change(G1HeapRegionTraceType::StartsHumongous);
}
_type.set_starts_humongous(); _type.set_starts_humongous();
_humongous_start_region = this; _humongous_start_region = this;
...@@ -231,7 +234,9 @@ void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) { ...@@ -231,7 +234,9 @@ void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) {
"Should be normal before the humongous object allocation"); "Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty"); assert(top() == bottom(), "should be empty");
assert(first_hr->startsHumongous(), "pre-condition"); assert(first_hr->startsHumongous(), "pre-condition");
if (EnableJFR) {
report_region_type_change(G1HeapRegionTraceType::ContinuesHumongous);
}
_type.set_continues_humongous(); _type.set_continues_humongous();
_humongous_start_region = first_hr; _humongous_start_region = first_hr;
} }
...@@ -303,6 +308,16 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) { ...@@ -303,6 +308,16 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
record_timestamp(); record_timestamp();
} }
void HeapRegion::report_region_type_change(G1HeapRegionTraceType::Type to) {
assert(EnableJFR, "sanity check");
HeapRegionTracer::send_region_type_change(_hrm_index,
get_trace_type(),
to,
(uintptr_t)bottom(),
used());
}
CompactibleSpace* HeapRegion::next_compaction_space() const { CompactibleSpace* HeapRegion::next_compaction_space() const {
return G1CollectedHeap::heap()->next_compaction_region(this); return G1CollectedHeap::heap()->next_compaction_region(this);
} }
......
/* /*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "gc_implementation/g1/g1_specialized_oop_closures.hpp" #include "gc_implementation/g1/g1_specialized_oop_closures.hpp"
#include "gc_implementation/g1/heapRegionType.hpp" #include "gc_implementation/g1/heapRegionType.hpp"
#include "gc_implementation/g1/survRateGroup.hpp" #include "gc_implementation/g1/survRateGroup.hpp"
#include "gc_implementation/g1/g1HeapRegionTraceType.hpp"
#include "gc_implementation/shared/ageTable.hpp" #include "gc_implementation/shared/ageTable.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_implementation/shared/spaceDecorator.hpp"
#include "memory/space.inline.hpp" #include "memory/space.inline.hpp"
...@@ -211,6 +212,8 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -211,6 +212,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
G1BlockOffsetArrayContigSpace* offsets() { return &_offsets; } G1BlockOffsetArrayContigSpace* offsets() { return &_offsets; }
void report_region_type_change(G1HeapRegionTraceType::Type to);
protected: protected:
// The index of this region in the heap region sequence. // The index of this region in the heap region sequence.
uint _hrm_index; uint _hrm_index;
...@@ -405,6 +408,7 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -405,6 +408,7 @@ class HeapRegion: public G1OffsetTableContigSpace {
const char* get_type_str() const { return _type.get_str(); } const char* get_type_str() const { return _type.get_str(); }
const char* get_short_type_str() const { return _type.get_short_str(); } const char* get_short_type_str() const { return _type.get_short_str(); }
G1HeapRegionTraceType::Type get_trace_type() { return _type.get_trace_type(); }
bool is_free() const { return _type.is_free(); } bool is_free() const { return _type.is_free(); }
...@@ -667,13 +671,40 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -667,13 +671,40 @@ class HeapRegion: public G1OffsetTableContigSpace {
} }
} }
void set_free() { _type.set_free(); } void set_free() {
if (EnableJFR) {
report_region_type_change(G1HeapRegionTraceType::Free);
}
_type.set_free();
}
void set_eden() { _type.set_eden(); } void set_eden() {
void set_eden_pre_gc() { _type.set_eden_pre_gc(); } if (EnableJFR) {
void set_survivor() { _type.set_survivor(); } report_region_type_change(G1HeapRegionTraceType::Eden);
}
_type.set_eden();
}
void set_old() { _type.set_old(); } void set_old() {
if (EnableJFR) {
report_region_type_change(G1HeapRegionTraceType::Old);
}
_type.set_old();
}
void set_eden_pre_gc() {
if (EnableJFR) {
report_region_type_change(G1HeapRegionTraceType::Eden);
}
_type.set_eden_pre_gc();
}
void set_survivor() {
if (EnableJFR) {
report_region_type_change(G1HeapRegionTraceType::Survivor);
}
_type.set_survivor();
}
// Determine if an object has been allocated since the last // Determine if an object has been allocated since the last
// mark performed by the collector. This returns true iff the object // mark performed by the collector. This returns true iff the object
......
/*
* Copyright (c) 2013, 2019, 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 "gc_implementation/g1/heapRegionTracer.hpp"
#include "trace/tracing.hpp"
void HeapRegionTracer::send_region_type_change(uint index,
G1HeapRegionTraceType::Type from,
G1HeapRegionTraceType::Type to,
uintptr_t start,
size_t used) {
EventG1HeapRegionTypeChange e;
if (e.should_commit()) {
e.set_index(index);
e.set_from(from);
e.set_to(to);
e.set_start(start);
e.set_used(used);
e.commit();
}
}
/*
* Copyright (c) 2019, 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_VM_GC_G1_HEAPREGIONTRACER_HPP
#define SHARE_VM_GC_G1_HEAPREGIONTRACER_HPP
#include "gc_implementation/g1/g1HeapRegionTraceType.hpp"
#include "memory/allocation.hpp"
class HeapRegionTracer : AllStatic {
public:
static void send_region_type_change(uint index,
G1HeapRegionTraceType::Type from,
G1HeapRegionTraceType::Type to,
uintptr_t start,
size_t used);
};
#endif // SHARE_VM_GC_G1_HEAPREGIONTRACER_HPP
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc_implementation/g1/g1HeapRegionTraceType.hpp"
#include "gc_implementation/g1/heapRegionType.hpp" #include "gc_implementation/g1/heapRegionType.hpp"
bool HeapRegionType::is_valid(Tag tag) { bool HeapRegionType::is_valid(Tag tag) {
...@@ -67,3 +68,18 @@ const char* HeapRegionType::get_short_str() const { ...@@ -67,3 +68,18 @@ const char* HeapRegionType::get_short_str() const {
// keep some compilers happy // keep some compilers happy
return NULL; return NULL;
} }
G1HeapRegionTraceType::Type HeapRegionType::get_trace_type() {
hrt_assert_is_valid(_tag);
switch (_tag) {
case FreeTag: return G1HeapRegionTraceType::Free;
case EdenTag: return G1HeapRegionTraceType::Eden;
case SurvTag: return G1HeapRegionTraceType::Survivor;
case HumStartsTag: return G1HeapRegionTraceType::StartsHumongous;
case HumContTag: return G1HeapRegionTraceType::ContinuesHumongous;
case OldTag: return G1HeapRegionTraceType::Old;
default:
ShouldNotReachHere();
return G1HeapRegionTraceType::Free; // keep some compilers happy
}
}
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONTYPE_HPP
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "gc_implementation/g1/g1HeapRegionTraceType.hpp"
#define hrt_assert_is_valid(tag) \ #define hrt_assert_is_valid(tag) \
assert(is_valid((tag)), err_msg("invalid HR type: %u", (uint) (tag))) assert(is_valid((tag)), err_msg("invalid HR type: %u", (uint) (tag)))
...@@ -127,6 +128,7 @@ public: ...@@ -127,6 +128,7 @@ public:
const char* get_str() const; const char* get_str() const;
const char* get_short_str() const; const char* get_short_str() const;
G1HeapRegionTraceType::Type get_trace_type();
HeapRegionType() : _tag(FreeTag) { hrt_assert_is_valid(_tag); } HeapRegionType() : _tag(FreeTag) { hrt_assert_is_valid(_tag); }
}; };
......
/* /*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -148,6 +148,10 @@ class PSPromotionManager VALUE_OBJ_CLASS_SPEC { ...@@ -148,6 +148,10 @@ class PSPromotionManager VALUE_OBJ_CLASS_SPEC {
claimed_stack_depth()->push(p); claimed_stack_depth()->push(p);
} }
inline void promotion_trace_event(oop new_obj, oop old_obj, size_t obj_size,
uint age, bool tenured,
const PSPromotionLAB* lab);
protected: protected:
static OopStarTaskQueueSet* stack_array_depth() { return _stack_array_depth; } static OopStarTaskQueueSet* stack_array_depth() { return _stack_array_depth; }
public: public:
......
/* /*
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -64,6 +64,34 @@ inline void PSPromotionManager::claim_or_forward_depth(T* p) { ...@@ -64,6 +64,34 @@ inline void PSPromotionManager::claim_or_forward_depth(T* p) {
claim_or_forward_internal_depth(p); claim_or_forward_internal_depth(p);
} }
inline void PSPromotionManager::promotion_trace_event(oop new_obj, oop old_obj,
size_t obj_size,
uint age, bool tenured,
const PSPromotionLAB* lab) {
assert(EnableJFR, "sanity check");
// Skip if memory allocation failed
if (new_obj != NULL) {
const ParallelScavengeTracer* gc_tracer = PSScavenge::gc_tracer();
if (lab != NULL) {
// Promotion of object through newly allocated PLAB
if (gc_tracer->should_report_promotion_in_new_plab_event()) {
size_t obj_bytes = obj_size * HeapWordSize;
size_t lab_size = lab->capacity();
gc_tracer->report_promotion_in_new_plab_event(old_obj->klass(), obj_bytes,
age, tenured, lab_size);
}
} else {
// Promotion of object directly to heap
if (gc_tracer->should_report_promotion_outside_plab_event()) {
size_t obj_bytes = obj_size * HeapWordSize;
gc_tracer->report_promotion_outside_plab_event(old_obj->klass(), obj_bytes,
age, tenured);
}
}
}
}
// //
// This method is pretty bulky. It would be nice to split it up // This method is pretty bulky. It would be nice to split it up
// into smaller submethods, but we need to be careful not to hurt // into smaller submethods, but we need to be careful not to hurt
...@@ -98,6 +126,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { ...@@ -98,6 +126,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) {
if (new_obj_size > (YoungPLABSize / 2)) { if (new_obj_size > (YoungPLABSize / 2)) {
// Allocate this object directly // Allocate this object directly
new_obj = (oop)young_space()->cas_allocate(new_obj_size); new_obj = (oop)young_space()->cas_allocate(new_obj_size);
if (EnableJFR) {
promotion_trace_event(new_obj, o, new_obj_size, age, false, NULL);
}
} else { } else {
// Flush and fill // Flush and fill
_young_lab.flush(); _young_lab.flush();
...@@ -107,6 +138,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { ...@@ -107,6 +138,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) {
_young_lab.initialize(MemRegion(lab_base, YoungPLABSize)); _young_lab.initialize(MemRegion(lab_base, YoungPLABSize));
// Try the young lab allocation again. // Try the young lab allocation again.
new_obj = (oop) _young_lab.allocate(new_obj_size); new_obj = (oop) _young_lab.allocate(new_obj_size);
if (EnableJFR) {
promotion_trace_event(new_obj, o, new_obj_size, age, false, &_young_lab);
}
} else { } else {
_young_gen_is_full = true; _young_gen_is_full = true;
} }
...@@ -127,11 +161,20 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { ...@@ -127,11 +161,20 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) {
new_obj_is_tenured = true; new_obj_is_tenured = true;
if (new_obj == NULL) { if (new_obj == NULL) {
uint age = 0;
if (EnableJFR) {
// Find the objects age, MT safe.
age = (test_mark->has_displaced_mark_helper() /* o->has_displaced_mark() */) ?
test_mark->displaced_mark_helper()->age() : test_mark->age();
}
if (!_old_gen_is_full) { if (!_old_gen_is_full) {
// Do we allocate directly, or flush and refill? // Do we allocate directly, or flush and refill?
if (new_obj_size > (OldPLABSize / 2)) { if (new_obj_size > (OldPLABSize / 2)) {
// Allocate this object directly // Allocate this object directly
new_obj = (oop)old_gen()->cas_allocate(new_obj_size); new_obj = (oop)old_gen()->cas_allocate(new_obj_size);
if (EnableJFR) {
promotion_trace_event(new_obj, o, new_obj_size, age, true, NULL);
}
} else { } else {
// Flush and fill // Flush and fill
_old_lab.flush(); _old_lab.flush();
...@@ -148,6 +191,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { ...@@ -148,6 +191,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) {
_old_lab.initialize(MemRegion(lab_base, OldPLABSize)); _old_lab.initialize(MemRegion(lab_base, OldPLABSize));
// Try the old lab allocation again. // Try the old lab allocation again.
new_obj = (oop) _old_lab.allocate(new_obj_size); new_obj = (oop) _old_lab.allocate(new_obj_size);
if (EnableJFR) {
promotion_trace_event(new_obj, o, new_obj_size, age, true, &_old_lab);
}
} }
} }
} }
......
/* /*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -93,6 +93,8 @@ class PSScavenge: AllStatic { ...@@ -93,6 +93,8 @@ class PSScavenge: AllStatic {
// Private accessors // Private accessors
static CardTableExtension* const card_table() { assert(_card_table != NULL, "Sanity"); return _card_table; } static CardTableExtension* const card_table() { assert(_card_table != NULL, "Sanity"); return _card_table; }
static const ParallelScavengeTracer* gc_tracer() { return &_gc_tracer; }
public: public:
// Accessors // Accessors
static uint tenuring_threshold() { return _tenuring_threshold; } static uint tenuring_threshold() { return _tenuring_threshold; }
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc_implementation/shared/ageTable.hpp" #include "gc_implementation/shared/ageTable.hpp"
#include "gc_implementation/shared/gcPolicyCounters.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp"
#include "gc_implementation/shared/ageTableTracer.hpp"
#include "memory/collectorPolicy.hpp" #include "memory/collectorPolicy.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "memory/sharedHeap.hpp" #include "memory/sharedHeap.hpp"
...@@ -92,7 +93,7 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { ...@@ -92,7 +93,7 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
} }
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold; uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
if (PrintTenuringDistribution || UsePerfData) { if (PrintTenuringDistribution || UsePerfData || (EnableJFR && AgeTableTracer::is_tenuring_distribution_event_enabled())) {
if (PrintTenuringDistribution) { if (PrintTenuringDistribution) {
gclog_or_tty->cr(); gclog_or_tty->cr();
...@@ -110,6 +111,11 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { ...@@ -110,6 +111,11 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
age, sizes[age]*oopSize, total*oopSize); age, sizes[age]*oopSize, total*oopSize);
} }
} }
if (EnableJFR) {
AgeTableTracer::send_tenuring_distribution_event(age, sizes[age] * oopSize);
}
if (UsePerfData) { if (UsePerfData) {
_perf_sizes[age]->set_value(sizes[age]*oopSize); _perf_sizes[age]->set_value(sizes[age]*oopSize);
} }
......
/*
* Copyright (c) 2019, 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 "gc_implementation/shared/ageTableTracer.hpp"
#include "gc_implementation/shared/gcId.hpp"
#include "trace/tracing.hpp"
void AgeTableTracer::send_tenuring_distribution_event(uint age, size_t size) {
EventTenuringDistribution e;
if (e.should_commit()) {
// FIXME gc id ...
e.set_gcId(GCId::peek().id() - 1);
e.set_age(age);
e.set_size(size);
e.commit();
}
}
bool AgeTableTracer::is_tenuring_distribution_event_enabled() {
return EventTenuringDistribution::is_enabled();
}
/*
* Copyright (c) 2019, 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_VM_GC_SHARED_AGETABLETRACER_HPP
#define SHARE_VM_GC_SHARED_AGETABLETRACER_HPP
#include "memory/allocation.hpp"
class AgeTableTracer : AllStatic {
public:
static void send_tenuring_distribution_event(uint age, size_t size);
static bool is_tenuring_distribution_event_enabled();
};
#endif // SHARE_VM_GC_SHARED_AGETABLETRACER_HPP
/*
* Copyright (c) 2012, 2019, 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 "gc_interface/collectedHeap.hpp"
#include "gc_implementation/shared/gcConfiguration.hpp"
#include "memory/universe.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
GCName GCConfiguration::young_collector() const {
if (UseG1GC) {
return G1New;
}
if (UseParallelGC) {
return ParallelScavenge;
}
if (UseConcMarkSweepGC) {
return ParNew;
}
return DefNew;
}
GCName GCConfiguration::old_collector() const {
if (UseG1GC) {
return G1Old;
}
if (UseConcMarkSweepGC) {
return ConcurrentMarkSweep;
}
if (UseParallelOldGC) {
return ParallelOld;
}
return SerialOld;
}
uint GCConfiguration::num_parallel_gc_threads() const {
return ParallelGCThreads;
}
uint GCConfiguration::num_concurrent_gc_threads() const {
return ConcGCThreads;
}
bool GCConfiguration::uses_dynamic_gc_threads() const {
return UseDynamicNumberOfGCThreads;
}
bool GCConfiguration::is_explicit_gc_concurrent() const {
return ExplicitGCInvokesConcurrent;
}
bool GCConfiguration::is_explicit_gc_disabled() const {
return DisableExplicitGC;
}
bool GCConfiguration::has_pause_target_default_value() const {
return FLAG_IS_DEFAULT(MaxGCPauseMillis);
}
uintx GCConfiguration::pause_target() const {
return MaxGCPauseMillis;
}
uintx GCConfiguration::gc_time_ratio() const {
return GCTimeRatio;
}
bool GCTLABConfiguration::uses_tlabs() const {
return UseTLAB;
}
size_t GCTLABConfiguration::min_tlab_size() const {
return MinTLABSize;
}
uint GCTLABConfiguration::tlab_refill_waste_limit() const {
return TLABRefillWasteFraction;
}
intx GCSurvivorConfiguration::max_tenuring_threshold() const {
return MaxTenuringThreshold;
}
intx GCSurvivorConfiguration::initial_tenuring_threshold() const {
return InitialTenuringThreshold;
}
size_t GCHeapConfiguration::max_size() const {
return MaxHeapSize;
}
size_t GCHeapConfiguration::min_size() const {
return Arguments::min_heap_size();
}
size_t GCHeapConfiguration::initial_size() const {
return InitialHeapSize;
}
bool GCHeapConfiguration::uses_compressed_oops() const {
return UseCompressedOops;
}
Universe::NARROW_OOP_MODE GCHeapConfiguration::narrow_oop_mode() const {
return Universe::narrow_oop_mode();
}
uint GCHeapConfiguration::object_alignment_in_bytes() const {
return ObjectAlignmentInBytes;
}
int GCHeapConfiguration::heap_address_size_in_bits() const {
return BitsPerHeapOop;
}
bool GCYoungGenerationConfiguration::has_max_size_default_value() const {
return FLAG_IS_DEFAULT(MaxNewSize);
}
uintx GCYoungGenerationConfiguration::max_size() const {
return MaxNewSize;
}
uintx GCYoungGenerationConfiguration::min_size() const {
return NewSize;
}
intx GCYoungGenerationConfiguration::new_ratio() const {
return NewRatio;
}
/*
* Copyright (c) 2012, 2019, 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_VM_GC_SHARED_GCCONFIGURATION_HPP
#define SHARE_VM_GC_SHARED_GCCONFIGURATION_HPP
#include "gc_interface/gcName.hpp"
#include "memory/universe.hpp"
#include "utilities/globalDefinitions.hpp"
class GCConfiguration {
public:
GCName young_collector() const;
GCName old_collector() const;
uint num_parallel_gc_threads() const;
uint num_concurrent_gc_threads() const;
bool uses_dynamic_gc_threads() const;
bool is_explicit_gc_concurrent() const;
bool is_explicit_gc_disabled() const;
uintx gc_time_ratio() const;
bool has_pause_target_default_value() const;
uintx pause_target() const;
};
class GCTLABConfiguration {
public:
bool uses_tlabs() const;
size_t min_tlab_size() const;
uint tlab_refill_waste_limit() const;
};
class GCSurvivorConfiguration {
public:
intx initial_tenuring_threshold() const;
intx max_tenuring_threshold() const;
};
class GCHeapConfiguration {
public:
size_t max_size() const;
size_t min_size() const;
size_t initial_size() const;
bool uses_compressed_oops() const;
Universe::NARROW_OOP_MODE narrow_oop_mode() const;
uint object_alignment_in_bytes() const;
int heap_address_size_in_bits() const;
};
class GCYoungGenerationConfiguration {
public:
bool has_max_size_default_value() const;
uintx max_size() const;
uintx min_size() const;
intx new_ratio() const;
};
#endif // SHARE_VM_GC_SHARED_GCCONFIGURATION_HPP
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -78,11 +78,13 @@ class MetaspaceSizes : public StackObj { ...@@ -78,11 +78,13 @@ class MetaspaceSizes : public StackObj {
class GCHeapSummary; class GCHeapSummary;
class PSHeapSummary; class PSHeapSummary;
class G1HeapSummary;
class GCHeapSummaryVisitor { class GCHeapSummaryVisitor {
public: public:
virtual void visit(const GCHeapSummary* heap_summary) const = 0; virtual void visit(const GCHeapSummary* heap_summary) const = 0;
virtual void visit(const PSHeapSummary* heap_summary) const {} virtual void visit(const PSHeapSummary* heap_summary) const {}
virtual void visit(const G1HeapSummary* heap_summary) const {}
}; };
class GCHeapSummary : public StackObj { class GCHeapSummary : public StackObj {
...@@ -125,6 +127,24 @@ class PSHeapSummary : public GCHeapSummary { ...@@ -125,6 +127,24 @@ class PSHeapSummary : public GCHeapSummary {
} }
}; };
class G1HeapSummary : public GCHeapSummary {
size_t _edenUsed;
size_t _edenCapacity;
size_t _survivorUsed;
uint _numberOfRegions;
public:
G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed, uint numberOfRegions) :
GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed), _numberOfRegions(numberOfRegions) { }
const size_t edenUsed() const { return _edenUsed; }
const size_t edenCapacity() const { return _edenCapacity; }
const size_t survivorUsed() const { return _survivorUsed; }
const uint numberOfRegions() const { return _numberOfRegions; }
virtual void accept(GCHeapSummaryVisitor* visitor) const {
visitor->visit(this);
}
};
class MetaspaceSummary : public StackObj { class MetaspaceSummary : public StackObj {
size_t _capacity_until_GC; size_t _capacity_until_GC;
MetaspaceSizes _meta_space; MetaspaceSizes _meta_space;
......
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -172,6 +172,30 @@ void YoungGCTracer::report_tenuring_threshold(const uint tenuring_threshold) { ...@@ -172,6 +172,30 @@ void YoungGCTracer::report_tenuring_threshold(const uint tenuring_threshold) {
_tenuring_threshold = tenuring_threshold; _tenuring_threshold = tenuring_threshold;
} }
bool YoungGCTracer::should_report_promotion_events() const {
return should_report_promotion_in_new_plab_event() ||
should_report_promotion_outside_plab_event();
}
bool YoungGCTracer::should_report_promotion_in_new_plab_event() const {
return should_send_promotion_in_new_plab_event();
}
bool YoungGCTracer::should_report_promotion_outside_plab_event() const {
return should_send_promotion_outside_plab_event();
}
void YoungGCTracer::report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
uint age, bool tenured,
size_t plab_size) const {
send_promotion_in_new_plab_event(klass, obj_size, age, tenured, plab_size);
}
void YoungGCTracer::report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
uint age, bool tenured) const {
send_promotion_outside_plab_event(klass, obj_size, age, tenured);
}
void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) { void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id(); assert_set_gc_id();
...@@ -199,6 +223,13 @@ void OldGCTracer::report_concurrent_mode_failure() { ...@@ -199,6 +223,13 @@ void OldGCTracer::report_concurrent_mode_failure() {
} }
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
void G1MMUTracer::report_mmu(double time_slice_sec, double gc_time_sec, double max_time_sec, bool gc_thread) {
send_g1_mmu_event(time_slice_sec * MILLIUNITS,
gc_time_sec * MILLIUNITS,
max_time_sec * MILLIUNITS,
gc_thread);
}
void G1NewTracer::report_yc_type(G1YCType type) { void G1NewTracer::report_yc_type(G1YCType type) {
assert_set_gc_id(); assert_set_gc_id();
...@@ -224,4 +255,19 @@ void G1NewTracer::report_evacuation_failed(EvacuationFailedInfo& ef_info) { ...@@ -224,4 +255,19 @@ void G1NewTracer::report_evacuation_failed(EvacuationFailedInfo& ef_info) {
send_evacuation_failed_event(ef_info); send_evacuation_failed_event(ef_info);
ef_info.reset(); ef_info.reset();
} }
void G1NewTracer::report_basic_ihop_statistics(size_t threshold,
size_t target_ccupancy,
size_t current_occupancy,
size_t last_allocation_size,
double last_allocation_duration,
double last_marking_length) {
send_basic_ihop_statistics(threshold,
target_ccupancy,
current_occupancy,
last_allocation_size,
last_allocation_duration,
last_marking_length);
}
#endif #endif
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -157,9 +157,39 @@ class YoungGCTracer : public GCTracer { ...@@ -157,9 +157,39 @@ class YoungGCTracer : public GCTracer {
void report_promotion_failed(const PromotionFailedInfo& pf_info); void report_promotion_failed(const PromotionFailedInfo& pf_info);
void report_tenuring_threshold(const uint tenuring_threshold); void report_tenuring_threshold(const uint tenuring_threshold);
/*
* Methods for reporting Promotion in new or outside PLAB Events.
*
* The object age is always required as it is not certain that the mark word
* of the oop can be trusted at this stage.
*
* obj_size is the size of the promoted object in bytes.
*
* tenured should be true if the object has been promoted to the old
* space during this GC, if the object is copied to survivor space
* from young space or survivor space (aging) tenured should be false.
*
* plab_size is the size of the newly allocated PLAB in bytes.
*/
bool should_report_promotion_events() const;
bool should_report_promotion_in_new_plab_event() const;
bool should_report_promotion_outside_plab_event() const;
void report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
uint age, bool tenured,
size_t plab_size) const;
void report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
uint age, bool tenured) const;
private: private:
void send_young_gc_event() const; void send_young_gc_event() const;
void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const; void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const;
bool should_send_promotion_in_new_plab_event() const;
bool should_send_promotion_outside_plab_event() const;
void send_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
uint age, bool tenured,
size_t plab_size) const;
void send_promotion_outside_plab_event(Klass* klass, size_t obj_size,
uint age, bool tenured) const;
}; };
class OldGCTracer : public GCTracer { class OldGCTracer : public GCTracer {
...@@ -210,6 +240,13 @@ class ParNewTracer : public YoungGCTracer { ...@@ -210,6 +240,13 @@ class ParNewTracer : public YoungGCTracer {
}; };
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
class G1MMUTracer : public AllStatic {
static void send_g1_mmu_event(double time_slice_ms, double gc_time_ms, double max_time_ms, bool gc_thread);
public:
static void report_mmu(double time_slice_sec, double gc_time_sec, double max_time_sec, bool gc_thread);
};
class G1NewTracer : public YoungGCTracer { class G1NewTracer : public YoungGCTracer {
G1YoungGCInfo _g1_young_gc_info; G1YoungGCInfo _g1_young_gc_info;
...@@ -221,10 +258,25 @@ class G1NewTracer : public YoungGCTracer { ...@@ -221,10 +258,25 @@ class G1NewTracer : public YoungGCTracer {
void report_evacuation_info(EvacuationInfo* info); void report_evacuation_info(EvacuationInfo* info);
void report_evacuation_failed(EvacuationFailedInfo& ef_info); void report_evacuation_failed(EvacuationFailedInfo& ef_info);
void report_basic_ihop_statistics(size_t threshold,
size_t target_occupancy,
size_t current_occupancy,
size_t last_allocation_size,
double last_allocation_duration,
double last_marking_length);
private: private:
void send_g1_young_gc_event(); void send_g1_young_gc_event();
void send_evacuation_info_event(EvacuationInfo* info); void send_evacuation_info_event(EvacuationInfo* info);
void send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const; void send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const;
void send_basic_ihop_statistics(size_t threshold,
size_t target_occupancy,
size_t current_occupancy,
size_t last_allocation_size,
double last_allocation_duration,
double last_marking_length);
}; };
#endif #endif
......
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -72,7 +72,8 @@ GCTraceTime::~GCTraceTime() { ...@@ -72,7 +72,8 @@ GCTraceTime::~GCTraceTime() {
if (_doit) { if (_doit) {
const Tickspan duration = stop_counter - _start_counter; const Tickspan duration = stop_counter - _start_counter;
double duration_in_seconds = TicksToTimeHelper::seconds(duration); double duration_in_seconds = TimeHelper::counter_to_seconds(duration.value());
if (_print_cr) { if (_print_cr) {
gclog_or_tty->print_cr(", %3.7f secs]", duration_in_seconds); gclog_or_tty->print_cr(", %3.7f secs]", duration_in_seconds);
} else { } else {
......
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,28 +32,44 @@ ...@@ -32,28 +32,44 @@
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#include "utilities/ticks.hpp" #include "utilities/ticks.hpp"
#if INCLUDE_SERVICES #if INCLUDE_SERVICES
void ObjectCountEventSender::send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp) {
#if INCLUDE_TRACE
assert(Tracing::is_event_enabled(EventObjectCountAfterGC::eventId),
"Only call this method if the event is enabled");
EventObjectCountAfterGC event(UNTIMED);
event.set_gcId(gc_id.id());
event.set_class(entry->klass());
event.set_count(entry->count());
event.set_totalSize(entry->words() * BytesPerWord);
event.set_endtime(timestamp);
event.commit();
#endif // INCLUDE_TRACE
}
bool ObjectCountEventSender::should_send_event() { bool ObjectCountEventSender::should_send_event() {
#if INCLUDE_TRACE #if INCLUDE_TRACE
return Tracing::is_event_enabled(EventObjectCountAfterGC::eventId); return _should_send_requestable_event ||
Tracing::is_event_enabled(EventObjectCountAfterGC::eventId);
#else #else
return false; return false;
#endif // INCLUDE_TRACE #endif // INCLUDE_TRACE
} }
bool ObjectCountEventSender::_should_send_requestable_event = false;
void ObjectCountEventSender::enable_requestable_event() {
_should_send_requestable_event = true;
}
void ObjectCountEventSender::disable_requestable_event() {
_should_send_requestable_event = false;
}
template <typename T>
void ObjectCountEventSender::send_event_if_enabled(Klass* klass, jlong count, julong size, GCId gc_id, const Ticks& timestamp) {
T event(UNTIMED);
if (event.should_commit()) {
event.set_gcId(gc_id.id());
event.set_objectClass(klass);
event.set_count(count);
event.set_totalSize(size);
event.set_endtime(timestamp);
event.commit();
}
}
void ObjectCountEventSender::send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp) {
Klass* klass = entry->klass();
jlong count = entry->count();
julong total_size = entry->words() * BytesPerWord;
send_event_if_enabled<EventObjectCount>(klass, count, total_size, gc_id, timestamp);
send_event_if_enabled<EventObjectCountAfterGC>(klass, count, total_size, gc_id, timestamp);
}
#endif // INCLUDE_SERVICES #endif // INCLUDE_SERVICES
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,10 +32,25 @@ ...@@ -32,10 +32,25 @@
#if INCLUDE_SERVICES #if INCLUDE_SERVICES
class KlassInfoEntry; class KlassInfoEntry;
class Ticks;
class ObjectCountEventSender : public AllStatic { class ObjectCountEventSender : public AllStatic {
static bool _should_send_requestable_event;
template <typename T>
static void send_event_if_enabled(Klass* klass, jlong count, julong size, GCId gc_id, const Ticks& timestamp);
public:
static void enable_requestable_event();
static void disable_requestable_event();
public: public:
// The following two functions have the exact same signature as
// hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp
//
// This file will replace the open file if a closed build is performed.
// These function signatures can therefore not be changed if the open
// signatures aren't changed as well.
static void send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp); static void send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp);
static bool should_send_event(); static bool should_send_event();
}; };
......
/* /*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,19 +29,21 @@ ...@@ -29,19 +29,21 @@
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
void AllocTracer::send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size) { void AllocTracer::send_allocation_outside_tlab_event(KlassHandle klass, HeapWord* obj, size_t alloc_size, Thread* thread) {
EventAllocObjectOutsideTLAB event; TRACE_ALLOCATION(obj, alloc_size, thread);
EventObjectAllocationOutsideTLAB event;
if (event.should_commit()) { if (event.should_commit()) {
event.set_class(klass()); event.set_objectClass(klass());
event.set_allocationSize(alloc_size); event.set_allocationSize(alloc_size);
event.commit(); event.commit();
} }
} }
void AllocTracer::send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size) { void AllocTracer::send_allocation_in_new_tlab_event(KlassHandle klass, HeapWord* obj, size_t tlab_size, size_t alloc_size, Thread* thread) {
EventAllocObjectInNewTLAB event; TRACE_ALLOCATION(obj, alloc_size, thread);
EventObjectAllocationInNewTLAB event;
if (event.should_commit()) { if (event.should_commit()) {
event.set_class(klass()); event.set_objectClass(klass());
event.set_allocationSize(alloc_size); event.set_allocationSize(alloc_size);
event.set_tlabSize(tlab_size); event.set_tlabSize(tlab_size);
event.commit(); event.commit();
......
/* /*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
class AllocTracer : AllStatic { class AllocTracer : AllStatic {
public: public:
static void send_allocation_outside_tlab_event(KlassHandle klass, size_t alloc_size); static void send_allocation_outside_tlab_event(KlassHandle klass, HeapWord* obj, size_t alloc_size, Thread* thread);
static void send_allocation_in_new_tlab_event(KlassHandle klass, size_t tlab_size, size_t alloc_size); static void send_allocation_in_new_tlab_event(KlassHandle klass, HeapWord* obj, size_t tlab_size, size_t alloc_size, Thread* thread);
static void send_allocation_requiring_gc_event(size_t size, const GCId& gcId); static void send_allocation_requiring_gc_event(size_t size, const GCId& gcId);
}; };
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册