Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8212879: Make JVMTI TagMap table concurrent #967

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion make/hotspot/lib/JvmFeatures.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ ifneq ($(call check-jvm-feature, jvmti), true)
jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \
jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \
jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \
jvmtiClassFileReconstituter.cpp
jvmtiClassFileReconstituter.cpp jvmtiTagMapTable.cpp
endif

ifneq ($(call check-jvm-feature, jvmci), true)
Expand Down
30 changes: 6 additions & 24 deletions src/hotspot/share/classfile/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,6 @@ void Dictionary::free_entry(DictionaryEntry* entry) {
}

const int _resize_load_trigger = 5; // load factor that will trigger the resize
const double _resize_factor = 2.0; // by how much we will resize using current number of entries
const int _resize_max_size = 40423; // the max dictionary size allowed
const int _primelist[] = {107, 1009, 2017, 4049, 5051, 10103, 20201, _resize_max_size};
const int _prime_array_size = sizeof(_primelist)/sizeof(int);

// Calculate next "good" dictionary size based on requested count
static int calculate_dictionary_size(int requested) {
int newsize = _primelist[0];
int index = 0;
for (newsize = _primelist[index]; index < (_prime_array_size - 1);
newsize = _primelist[++index]) {
if (requested <= newsize) {
break;
}
}
return newsize;
}

bool Dictionary::does_any_dictionary_needs_resizing() {
return Dictionary::_some_dictionary_needs_resizing;
Expand All @@ -128,15 +111,14 @@ void Dictionary::check_if_needs_resize() {
}

bool Dictionary::resize_if_needed() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
int desired_size = 0;
if (_needs_resizing == true) {
desired_size = calculate_dictionary_size((int)(_resize_factor*number_of_entries()));
if (desired_size >= _resize_max_size) {
desired_size = _resize_max_size;
// We have reached the limit, turn resizing off
_resizable = false;
}
if ((desired_size != 0) && (desired_size != table_size())) {
desired_size = calculate_resize(false);
assert(desired_size != 0, "bug in calculate_resize");
if (desired_size == table_size()) {
_resizable = false; // hit max
} else {
if (!resize(desired_size)) {
// Something went wrong, turn resizing off
_resizable = false;
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/shared/oopStorageSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class OopStorageSet : public AllStatic {
public:
// Must be updated when new OopStorages are introduced
static const uint strong_count = 4 JVMTI_ONLY(+ 1);
static const uint weak_count = 5 JFR_ONLY(+ 1);
static const uint weak_count = 5 JVMTI_ONLY(+ 1) JFR_ONLY(+ 1);
static const uint all_count = strong_count + weak_count;

private:
Expand Down
35 changes: 23 additions & 12 deletions src/hotspot/share/gc/shared/weakProcessor.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -37,16 +37,30 @@
#include "runtime/globals.hpp"
#include "utilities/macros.hpp"

void WeakProcessor::do_serial_parts(BoolObjectClosure* is_alive,
OopClosure* keep_alive) {
WeakProcessorPhases::Iterator it = WeakProcessorPhases::serial_iterator();
for ( ; !it.is_end(); ++it) {
WeakProcessorPhases::processor(*it)(is_alive, keep_alive);
}
#if INCLUDE_JVMTI
#include "prims/jvmtiTagMap.hpp"
#endif // INCLUDE_JVMTI

void notify_jvmti_tagmaps() {
#if INCLUDE_JVMTI
// Notify JVMTI tagmaps that a STW weak reference processing might be
// clearing entries, so the tagmaps need cleaning. Doing this here allows
// the tagmap's oopstorage notification handler to not care whether it's
// invoked by STW or concurrent reference processing.
JvmtiTagMap::set_needs_cleaning();

// Notify JVMTI tagmaps that a STW collection may have moved objects, so
// the tagmaps need rehashing. This isn't the right place for this, but
// is convenient because all the STW collectors use WeakProcessor. One
// problem is that the end of a G1 concurrent collection also comes here,
// possibly triggering unnecessary rehashes.
JvmtiTagMap::set_needs_rehashing();
#endif // INCLUDE_JVMTI
}

void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
do_serial_parts(is_alive, keep_alive);

notify_jvmti_tagmaps();

OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
for ( ; !it.is_end(); ++it) {
Expand All @@ -61,8 +75,6 @@ void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_a
}

void WeakProcessor::oops_do(OopClosure* closure) {
AlwaysTrueClosure always_true;
do_serial_parts(&always_true, closure);

OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
for ( ; !it.is_end(); ++it) {
Expand Down Expand Up @@ -106,12 +118,12 @@ void WeakProcessor::Task::initialize() {
if (_phase_times) {
_phase_times->set_active_workers(_nworkers);
}
notify_jvmti_tagmaps();
}

WeakProcessor::Task::Task(uint nworkers) :
_phase_times(NULL),
_nworkers(nworkers),
_serial_phases_done(WeakProcessorPhases::serial_phase_count),
_storage_states()
{
initialize();
Expand All @@ -120,7 +132,6 @@ WeakProcessor::Task::Task(uint nworkers) :
WeakProcessor::Task::Task(WeakProcessorPhaseTimes* phase_times, uint nworkers) :
_phase_times(phase_times),
_nworkers(nworkers),
_serial_phases_done(WeakProcessorPhases::serial_phase_count),
_storage_states()
{
initialize();
Expand Down
5 changes: 1 addition & 4 deletions src/hotspot/share/gc/shared/weakProcessor.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -72,16 +72,13 @@ class WeakProcessor : AllStatic {

private:
class GangTask;

static void do_serial_parts(BoolObjectClosure* is_alive, OopClosure* keep_alive);
};

class WeakProcessor::Task {
typedef OopStorage::ParState<false, false> StorageState;

WeakProcessorPhaseTimes* _phase_times;
uint _nworkers;
SubTasksDone _serial_phases_done;
OopStorageSetWeakParState<false, false> _storage_states;

void initialize();
Expand Down
18 changes: 1 addition & 17 deletions src/hotspot/share/gc/shared/weakProcessor.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,33 +96,17 @@ void WeakProcessor::Task::work(uint worker_id,

typedef WeakProcessorPhases::Iterator Iterator;

for (Iterator it = WeakProcessorPhases::serial_iterator(); !it.is_end(); ++it) {
WeakProcessorPhase phase = *it;
CountingIsAliveClosure<IsAlive> cl(is_alive);
uint serial_index = WeakProcessorPhases::serial_index(phase);
if (_serial_phases_done.try_claim_task(serial_index)) {
WeakProcessorPhaseTimeTracker pt(_phase_times, phase);
WeakProcessorPhases::processor(phase)(&cl, keep_alive);
if (_phase_times != NULL) {
_phase_times->record_phase_items(phase, cl.num_dead(), cl.num_total());
}
}
}

for (Iterator it = WeakProcessorPhases::oopstorage_iterator(); !it.is_end(); ++it) {
WeakProcessorPhase phase = *it;
CountingSkippedIsAliveClosure<IsAlive, KeepAlive> cl(is_alive, keep_alive);
WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id);
uint oopstorage_index = WeakProcessorPhases::oopstorage_index(phase);
StorageState* cur_state = _storage_states.par_state(oopstorage_index);
StorageState* cur_state = _storage_states.par_state(phase);
cur_state->oops_do(&cl);
cur_state->increment_num_dead(cl.num_skipped() + cl.num_dead());
if (_phase_times != NULL) {
_phase_times->record_worker_items(worker_id, phase, cl.num_dead(), cl.num_total());
}
}

_serial_phases_done.all_tasks_completed(_nworkers);
}

class WeakProcessor::GangTask : public AbstractGangTask {
Expand Down
107 changes: 3 additions & 104 deletions src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -33,48 +33,12 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/ticks.hpp"

static uint serial_phase_index(WeakProcessorPhase phase) {
return WeakProcessorPhases::serial_index(phase);
}

static bool is_serial_phase(WeakProcessorPhase phase) {
return WeakProcessorPhases::is_serial(phase);
}

static void assert_serial_phase(WeakProcessorPhase phase) {
assert(is_serial_phase(phase),
"Not a serial phase %u", static_cast<uint>(phase));
}

static void assert_oopstorage_phase(WeakProcessorPhase phase) {
assert(WeakProcessorPhases::is_oopstorage(phase),
"Not an oopstorage phase %u", static_cast<uint>(phase));
}

const double uninitialized_time = -1.0;

#ifdef ASSERT
static bool is_initialized_time(double t) { return t >= 0.0; }
static bool is_initialized_items(size_t i) { return i != 0; }
#endif // ASSERT

static void reset_times(double* times, size_t ntimes) {
for (size_t i = 0; i < ntimes; ++i) {
times[i] = uninitialized_time;
}
}

static void reset_items(size_t* items, size_t nitems) {
for (size_t i = 0; i < nitems; ++i) {
items[i] = 0;
}
}

void WeakProcessorPhaseTimes::reset_phase_data() {
reset_times(_phase_times_sec, ARRAY_SIZE(_phase_times_sec));
reset_items(_phase_dead_items, ARRAY_SIZE(_phase_dead_items));
reset_items(_phase_total_items, ARRAY_SIZE(_phase_total_items));
}

WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) :
_max_threads(max_threads),
Expand All @@ -84,8 +48,6 @@ WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) :
{
assert(_max_threads > 0, "max_threads must not be zero");

reset_phase_data();

WorkerDataArray<double>** wpt = _worker_data;
OopStorageSet::Iterator it = OopStorageSet::weak_iterator();
for ( ; !it.is_end(); ++it) {
Expand Down Expand Up @@ -122,7 +84,6 @@ void WeakProcessorPhaseTimes::set_active_workers(uint n) {
void WeakProcessorPhaseTimes::reset() {
_active_workers = 0;
_total_time_sec = uninitialized_time;
reset_phase_data();
for (size_t i = 0; i < ARRAY_SIZE(_worker_data); ++i) {
_worker_data[i]->reset();
}
Expand All @@ -138,34 +99,8 @@ void WeakProcessorPhaseTimes::record_total_time_sec(double time_sec) {
_total_time_sec = time_sec;
}

double WeakProcessorPhaseTimes::phase_time_sec(WeakProcessorPhase phase) const {
assert_serial_phase(phase);
assert(is_initialized_time(_phase_times_sec[serial_phase_index(phase)]),
"phase time not set %u", serial_phase_index(phase));
return _phase_times_sec[serial_phase_index(phase)];
}

void WeakProcessorPhaseTimes::record_phase_time_sec(WeakProcessorPhase phase, double time_sec) {
assert_serial_phase(phase);
assert(!is_initialized_time(_phase_times_sec[serial_phase_index(phase)]),
"Already set time for phase %u", serial_phase_index(phase));
_phase_times_sec[serial_phase_index(phase)] = time_sec;
}

void WeakProcessorPhaseTimes::record_phase_items(WeakProcessorPhase phase, size_t num_dead, size_t num_total) {
assert_serial_phase(phase);
uint p = serial_phase_index(phase);
assert(!is_initialized_items(_phase_dead_items[p]),
"Already set dead items for phase %u", p);
assert(!is_initialized_items(_phase_total_items[p]),
"Already set total items for phase %u", p);
_phase_dead_items[p] = num_dead;
_phase_total_items[p] = num_total;
}

WorkerDataArray<double>* WeakProcessorPhaseTimes::worker_data(WeakProcessorPhase phase) const {
assert_oopstorage_phase(phase);
return _worker_data[WeakProcessorPhases::oopstorage_index(phase)];
return _worker_data[phase];
}

double WeakProcessorPhaseTimes::worker_time_sec(uint worker_id, WeakProcessorPhase phase) const {
Expand Down Expand Up @@ -213,29 +148,15 @@ WeakProcessorPhaseTimeTracker::WeakProcessorPhaseTimeTracker(WeakProcessorPhaseT
_worker_id(worker_id),
_start_time(Ticks::now())
{
assert_oopstorage_phase(_phase);
assert(_times == NULL || worker_id < _times->active_workers(),
"Invalid worker_id %u", worker_id);
}

WeakProcessorPhaseTimeTracker::WeakProcessorPhaseTimeTracker(WeakProcessorPhaseTimes* times,
WeakProcessorPhase phase) :
_times(times),
_phase(phase),
_worker_id(0),
_start_time(Ticks::now())
{
assert_serial_phase(phase);
}

WeakProcessorPhaseTimeTracker::~WeakProcessorPhaseTimeTracker() {
if (_times != NULL) {
double time_sec = elapsed_time_sec(_start_time, Ticks::now());
if (is_serial_phase(_phase)) {
_times->record_phase_time_sec(_phase, time_sec);
} else {
_times->record_worker_time_sec(_worker_id, _phase, time_sec);
}
_times->record_worker_time_sec(_worker_id, _phase, time_sec);
}
}

Expand All @@ -251,25 +172,6 @@ static const char* indent_str(size_t i) {

#define TIME_FORMAT "%.1lfms"

void WeakProcessorPhaseTimes::log_st_phase(WeakProcessorPhase phase,
uint indent) const {
assert_serial_phase(phase);
log_debug(gc, phases)("%s%s: " TIME_FORMAT,
indent_str(indent),
WeakProcessorPhases::description(phase),
phase_time_sec(phase) * MILLIUNITS);

log_debug(gc, phases)("%s%s: " SIZE_FORMAT,
indent_str(indent + 1),
"Dead",
_phase_dead_items[serial_phase_index(phase)]);

log_debug(gc, phases)("%s%s: " SIZE_FORMAT,
indent_str(indent + 1),
"Total",
_phase_total_items[serial_phase_index(phase)]);
}

void WeakProcessorPhaseTimes::log_mt_phase_summary(WeakProcessorPhase phase,
uint indent) const {
LogTarget(Debug, gc, phases) lt;
Expand Down Expand Up @@ -302,9 +204,6 @@ void WeakProcessorPhaseTimes::log_mt_phase_details(WorkerDataArray<T>* data,
void WeakProcessorPhaseTimes::log_print_phases(uint indent) const {
if (log_is_enabled(Debug, gc, phases)) {
typedef WeakProcessorPhases::Iterator Iterator;
for (Iterator it = WeakProcessorPhases::serial_iterator(); !it.is_end(); ++it) {
log_st_phase(*it, indent);
}
for (Iterator it = WeakProcessorPhases::oopstorage_iterator(); !it.is_end(); ++it) {
log_mt_phase_summary(*it, indent);
}
Expand Down
Loading