8219468: ZGC: Extract iteration functionality into a new ZNMethodTableIteration class
Reviewed-by: pliden
This commit is contained in:
parent
a7707862a9
commit
8fec4b7f85
@ -33,6 +33,7 @@
|
|||||||
#include "gc/z/zNMethodAllocator.hpp"
|
#include "gc/z/zNMethodAllocator.hpp"
|
||||||
#include "gc/z/zNMethodData.hpp"
|
#include "gc/z/zNMethodData.hpp"
|
||||||
#include "gc/z/zNMethodTable.hpp"
|
#include "gc/z/zNMethodTable.hpp"
|
||||||
|
#include "gc/z/zNMethodTableIteration.hpp"
|
||||||
#include "gc/z/zOopClosures.inline.hpp"
|
#include "gc/z/zOopClosures.inline.hpp"
|
||||||
#include "gc/z/zTask.hpp"
|
#include "gc/z/zTask.hpp"
|
||||||
#include "gc/z/zWorkers.hpp"
|
#include "gc/z/zWorkers.hpp"
|
||||||
@ -46,11 +47,9 @@
|
|||||||
|
|
||||||
ZNMethodTableEntry* ZNMethodTable::_table = NULL;
|
ZNMethodTableEntry* ZNMethodTable::_table = NULL;
|
||||||
size_t ZNMethodTable::_size = 0;
|
size_t ZNMethodTable::_size = 0;
|
||||||
ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL;
|
|
||||||
size_t ZNMethodTable::_iter_table_size = 0;
|
|
||||||
size_t ZNMethodTable::_nregistered = 0;
|
size_t ZNMethodTable::_nregistered = 0;
|
||||||
size_t ZNMethodTable::_nunregistered = 0;
|
size_t ZNMethodTable::_nunregistered = 0;
|
||||||
volatile size_t ZNMethodTable::_claimed = 0;
|
ZNMethodTableIteration ZNMethodTable::_iteration;
|
||||||
|
|
||||||
static ZNMethodData* gc_data(const nmethod* nm) {
|
static ZNMethodData* gc_data(const nmethod* nm) {
|
||||||
return nm->gc_data<ZNMethodData>();
|
return nm->gc_data<ZNMethodData>();
|
||||||
@ -60,6 +59,15 @@ static void set_gc_data(nmethod* nm, ZNMethodData* data) {
|
|||||||
return nm->set_gc_data<ZNMethodData>(data);
|
return nm->set_gc_data<ZNMethodData>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
|
||||||
|
void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
|
||||||
|
return ::new (mem) ZNMethodTableEntry[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
|
||||||
|
ZNMethodAllocator::free(table);
|
||||||
|
}
|
||||||
|
|
||||||
void ZNMethodTable::attach_gc_data(nmethod* nm) {
|
void ZNMethodTable::attach_gc_data(nmethod* nm) {
|
||||||
GrowableArray<oop*> immediate_oops;
|
GrowableArray<oop*> immediate_oops;
|
||||||
bool non_immediate_oops = false;
|
bool non_immediate_oops = false;
|
||||||
@ -182,7 +190,7 @@ void ZNMethodTable::rebuild(size_t new_size) {
|
|||||||
_nunregistered, percent_of(_nunregistered, _size), 0.0);
|
_nunregistered, percent_of(_nunregistered, _size), 0.0);
|
||||||
|
|
||||||
// Allocate new table
|
// Allocate new table
|
||||||
ZNMethodTableEntry* const new_table = new ZNMethodTableEntry[new_size];
|
ZNMethodTableEntry* const new_table = ZNMethodTable::create(new_size);
|
||||||
|
|
||||||
// Transfer all registered entries
|
// Transfer all registered entries
|
||||||
for (size_t i = 0; i < _size; i++) {
|
for (size_t i = 0; i < _size; i++) {
|
||||||
@ -192,10 +200,8 @@ void ZNMethodTable::rebuild(size_t new_size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_iter_table != _table) {
|
// Free old table
|
||||||
// Delete old table
|
ZNMethodTable::destroy(_table);
|
||||||
delete [] _table;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install new table
|
// Install new table
|
||||||
_table = new_table;
|
_table = new_table;
|
||||||
@ -323,7 +329,7 @@ void ZNMethodTable::register_nmethod(nmethod* nm) {
|
|||||||
void ZNMethodTable::wait_until_iteration_done() {
|
void ZNMethodTable::wait_until_iteration_done() {
|
||||||
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
|
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
|
||||||
|
|
||||||
while (_iter_table != NULL) {
|
while (_iteration.in_progress()) {
|
||||||
CodeCache_lock->wait(Monitor::_no_safepoint_check_flag);
|
CodeCache_lock->wait(Monitor::_no_safepoint_check_flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,21 +369,14 @@ void ZNMethodTable::nmethods_do_begin() {
|
|||||||
ZNMethodAllocator::activate_deferred_frees();
|
ZNMethodAllocator::activate_deferred_frees();
|
||||||
|
|
||||||
// Prepare iteration
|
// Prepare iteration
|
||||||
_iter_table = _table;
|
_iteration.nmethods_do_begin(_table, _size);
|
||||||
_iter_table_size = _size;
|
|
||||||
_claimed = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZNMethodTable::nmethods_do_end() {
|
void ZNMethodTable::nmethods_do_end() {
|
||||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
// Finish iteration
|
// Finish iteration
|
||||||
if (_iter_table != _table) {
|
_iteration.nmethods_do_end();
|
||||||
delete [] _iter_table;
|
|
||||||
}
|
|
||||||
_iter_table = NULL;
|
|
||||||
|
|
||||||
assert(_claimed >= _iter_table_size, "Failed to claim all table entries");
|
|
||||||
|
|
||||||
// Process deferred frees
|
// Process deferred frees
|
||||||
ZNMethodAllocator::deactivate_and_process_deferred_frees();
|
ZNMethodAllocator::deactivate_and_process_deferred_frees();
|
||||||
@ -436,25 +435,7 @@ void ZNMethodTable::oops_do(OopClosure* cl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ZNMethodTable::nmethods_do(NMethodClosure* cl) {
|
void ZNMethodTable::nmethods_do(NMethodClosure* cl) {
|
||||||
for (;;) {
|
_iteration.nmethods_do(cl);
|
||||||
// Claim table partition. Each partition is currently sized to span
|
|
||||||
// two cache lines. This number is just a guess, but seems to work well.
|
|
||||||
const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
|
|
||||||
const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _iter_table_size);
|
|
||||||
const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size);
|
|
||||||
if (partition_start == partition_end) {
|
|
||||||
// End of table
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process table partition
|
|
||||||
for (size_t i = partition_start; i < partition_end; i++) {
|
|
||||||
const ZNMethodTableEntry entry = _iter_table[i];
|
|
||||||
if (entry.registered()) {
|
|
||||||
cl->do_nmethod(entry.method());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ZNMethodTableUnlinkClosure : public NMethodClosure {
|
class ZNMethodTableUnlinkClosure : public NMethodClosure {
|
||||||
|
@ -28,8 +28,10 @@
|
|||||||
#include "gc/z/zGlobals.hpp"
|
#include "gc/z/zGlobals.hpp"
|
||||||
#include "gc/z/zLock.hpp"
|
#include "gc/z/zLock.hpp"
|
||||||
#include "gc/z/zNMethodTableEntry.hpp"
|
#include "gc/z/zNMethodTableEntry.hpp"
|
||||||
|
#include "gc/z/zNMethodTableIteration.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
|
class nmethod;
|
||||||
class NMethodClosure;
|
class NMethodClosure;
|
||||||
class ZNMethodData;
|
class ZNMethodData;
|
||||||
class ZNMethodDataOops;
|
class ZNMethodDataOops;
|
||||||
@ -37,13 +39,14 @@ class ZWorkers;
|
|||||||
|
|
||||||
class ZNMethodTable : public AllStatic {
|
class ZNMethodTable : public AllStatic {
|
||||||
private:
|
private:
|
||||||
static ZNMethodTableEntry* _table;
|
static ZNMethodTableEntry* _table;
|
||||||
static size_t _size;
|
static size_t _size;
|
||||||
static ZNMethodTableEntry* _iter_table;
|
static size_t _nregistered;
|
||||||
static size_t _iter_table_size;
|
static size_t _nunregistered;
|
||||||
static size_t _nregistered;
|
static ZNMethodTableIteration _iteration;
|
||||||
static size_t _nunregistered;
|
|
||||||
static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
|
static ZNMethodTableEntry* create(size_t size);
|
||||||
|
static void destroy(ZNMethodTableEntry* table);
|
||||||
|
|
||||||
static void attach_gc_data(nmethod* nm);
|
static void attach_gc_data(nmethod* nm);
|
||||||
static void detach_gc_data(nmethod* nm);
|
static void detach_gc_data(nmethod* nm);
|
||||||
|
76
src/hotspot/share/gc/z/zNMethodTableIteration.cpp
Normal file
76
src/hotspot/share/gc/z/zNMethodTableIteration.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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/z/zNMethodTableEntry.hpp"
|
||||||
|
#include "gc/z/zNMethodTableIteration.hpp"
|
||||||
|
#include "memory/iterator.hpp"
|
||||||
|
#include "runtime/atomic.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
|
||||||
|
ZNMethodTableIteration::ZNMethodTableIteration() :
|
||||||
|
_table(NULL),
|
||||||
|
_size(0),
|
||||||
|
_claimed(0) {}
|
||||||
|
|
||||||
|
bool ZNMethodTableIteration::in_progress() const {
|
||||||
|
return _table != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZNMethodTableIteration::nmethods_do_begin(ZNMethodTableEntry* table, size_t size) {
|
||||||
|
assert(!in_progress(), "precondition");
|
||||||
|
|
||||||
|
_table = table;
|
||||||
|
_size = size;
|
||||||
|
_claimed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZNMethodTableIteration::nmethods_do_end() {
|
||||||
|
assert(_claimed >= _size, "Failed to claim all table entries");
|
||||||
|
|
||||||
|
// Finish iteration
|
||||||
|
_table = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZNMethodTableIteration::nmethods_do(NMethodClosure* cl) {
|
||||||
|
for (;;) {
|
||||||
|
// Claim table partition. Each partition is currently sized to span
|
||||||
|
// two cache lines. This number is just a guess, but seems to work well.
|
||||||
|
const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
|
||||||
|
const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
|
||||||
|
const size_t partition_end = MIN2(partition_start + partition_size, _size);
|
||||||
|
if (partition_start == partition_end) {
|
||||||
|
// End of table
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process table partition
|
||||||
|
for (size_t i = partition_start; i < partition_end; i++) {
|
||||||
|
const ZNMethodTableEntry entry = _table[i];
|
||||||
|
if (entry.registered()) {
|
||||||
|
cl->do_nmethod(entry.method());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
src/hotspot/share/gc/z/zNMethodTableIteration.hpp
Normal file
48
src/hotspot/share/gc/z/zNMethodTableIteration.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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_GC_Z_ZNMETHODTABLEITERATION_HPP
|
||||||
|
#define SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP
|
||||||
|
|
||||||
|
#include "gc/z/zGlobals.hpp"
|
||||||
|
|
||||||
|
class NMethodClosure;
|
||||||
|
class ZNMethodTableEntry;
|
||||||
|
|
||||||
|
class ZNMethodTableIteration {
|
||||||
|
private:
|
||||||
|
ZNMethodTableEntry* _table;
|
||||||
|
size_t _size;
|
||||||
|
volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZNMethodTableIteration();
|
||||||
|
|
||||||
|
bool in_progress() const;
|
||||||
|
|
||||||
|
void nmethods_do_begin(ZNMethodTableEntry* table, size_t size);
|
||||||
|
void nmethods_do_end();
|
||||||
|
void nmethods_do(NMethodClosure* cl);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP
|
Loading…
x
Reference in New Issue
Block a user