8248132: ZGC: Unify handling of all OopStorage instances in root processing

Reviewed-by: pliden, kbarrett, tschatzl
This commit is contained in:
Stefan Karlsson 2020-06-24 13:15:00 +02:00
parent a1f02d13e5
commit 156f6174ed
6 changed files with 278 additions and 24 deletions

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_HPP
#define SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_HPP
#include "gc/shared/oopStorageParState.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "utilities/valueObjArray.hpp"
template <bool concurrent, bool is_const>
class OopStorageSetStrongParState {
typedef OopStorage::ParState<concurrent, is_const> ParStateType;
typedef ValueObjArray<ParStateType, OopStorageSet::strong_count> ParStateArray;
ParStateArray _par_states;
public:
OopStorageSetStrongParState();
template <typename Closure>
void oops_do(Closure* cl);
};
#endif // SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_HPP

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_INLINE_HPP
#define SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_INLINE_HPP
#include "gc/shared/oopStorageParState.inline.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/oopStorageSetParState.hpp"
template <bool concurrent, bool is_const>
OopStorageSetStrongParState<concurrent, is_const>::OopStorageSetStrongParState() :
_par_states(OopStorageSet::strong_iterator()) {
}
template <bool concurrent, bool is_const>
template <typename Closure>
void OopStorageSetStrongParState<concurrent, is_const>::oops_do(Closure* cl) {
for (int i = 0; i < _par_states.count(); i++) {
_par_states.at(i)->oops_do(cl);
}
}
#endif // SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_INLINE_HPP

View File

@ -30,7 +30,7 @@
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/oopStorageParState.inline.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/oopStorageSetParState.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/z/zBarrierSetNMethod.hpp"
#include "gc/z/zGlobals.hpp"
@ -70,8 +70,7 @@ static const ZStatSubPhase ZSubPhasePauseRootsCodeCache("Pause Roots CodeCache")
static const ZStatSubPhase ZSubPhaseConcurrentRootsSetup("Concurrent Roots Setup");
static const ZStatSubPhase ZSubPhaseConcurrentRoots("Concurrent Roots");
static const ZStatSubPhase ZSubPhaseConcurrentRootsTeardown("Concurrent Roots Teardown");
static const ZStatSubPhase ZSubPhaseConcurrentRootsJNIHandles("Concurrent Roots JNIHandles");
static const ZStatSubPhase ZSubPhaseConcurrentRootsVMHandles("Concurrent Roots VMHandles");
static const ZStatSubPhase ZSubPhaseConcurrentRootsOopStorageSet("Concurrent Roots OopStorageSet");
static const ZStatSubPhase ZSubPhaseConcurrentRootsClassLoaderDataGraph("Concurrent Roots ClassLoaderDataGraph");
static const ZStatSubPhase ZSubPhasePauseWeakRootsSetup("Pause Weak Roots Setup");
@ -286,11 +285,9 @@ void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
}
ZConcurrentRootsIterator::ZConcurrentRootsIterator(int cld_claim) :
_jni_handles_iter(OopStorageSet::jni_global()),
_vm_handles_iter(OopStorageSet::vm_global()),
_oop_storage_set_iter(),
_cld_claim(cld_claim),
_jni_handles(this),
_vm_handles(this),
_oop_storage_set(this),
_class_loader_data_graph(this) {
ZStatTimer timer(ZSubPhaseConcurrentRootsSetup);
ClassLoaderDataGraph::clear_claimed_marks(cld_claim);
@ -300,14 +297,9 @@ ZConcurrentRootsIterator::~ZConcurrentRootsIterator() {
ZStatTimer timer(ZSubPhaseConcurrentRootsTeardown);
}
void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRootsJNIHandles);
_jni_handles_iter.oops_do(cl);
}
void ZConcurrentRootsIterator::do_vm_handles(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRootsVMHandles);
_vm_handles_iter.oops_do(cl);
void ZConcurrentRootsIterator::do_oop_storage_set(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRootsOopStorageSet);
_oop_storage_set_iter.oops_do(cl);
}
void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
@ -318,8 +310,7 @@ void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure*
void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRoots);
_jni_handles.oops_do(cl);
_vm_handles.oops_do(cl),
_oop_storage_set.oops_do(cl);
_class_loader_data_graph.oops_do(cl);
}

View File

@ -25,6 +25,7 @@
#define SHARE_GC_Z_ZROOTSITERATOR_HPP
#include "gc/shared/oopStorageParState.hpp"
#include "gc/shared/oopStorageSetParState.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "memory/allocation.hpp"
#include "memory/iterator.hpp"
@ -35,6 +36,7 @@
class ZRootsIteratorClosure;
typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;
typedef OopStorageSetStrongParState<true /* concurrent */, false /* is_const */> ZOopStorageSetIterator;
template <typename T, void (T::*F)(ZRootsIteratorClosure*)>
class ZSerialOopsDo {
@ -134,16 +136,13 @@ public:
class ZConcurrentRootsIterator {
private:
ZOopStorageIterator _jni_handles_iter;
ZOopStorageIterator _vm_handles_iter;
const int _cld_claim;
ZOopStorageSetIterator _oop_storage_set_iter;
const int _cld_claim;
void do_jni_handles(ZRootsIteratorClosure* cl);
void do_vm_handles(ZRootsIteratorClosure* cl);
void do_oop_storage_set(ZRootsIteratorClosure* cl);
void do_class_loader_data_graph(ZRootsIteratorClosure* cl);
ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_jni_handles> _jni_handles;
ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_vm_handles> _vm_handles;
ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_oop_storage_set> _oop_storage_set;
ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_class_loader_data_graph> _class_loader_data_graph;
public:

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_UTILITIES_VALUEOBJARRAY_HPP
#define SHARE_UTILITIES_VALUEOBJARRAY_HPP
#include "utilities/debug.hpp"
// Stamps out Count instances of Type using a recursive template.
template <typename Type, int Count>
class ValueObjBlock {
typedef ValueObjBlock<Type, Count - 1> Next;
Type _instance;
Next _next;
public:
template <typename Generator>
ValueObjBlock(Generator g, Type** save_to) :
_instance(*g),
_next(++g, save_to + 1) {
*save_to = &_instance;
}
};
// Specialization for the recursion base case.
template <typename Type>
class ValueObjBlock<Type, 0> {
public:
template <typename Generator>
ValueObjBlock(Generator, Type**) {}
};
// Maps an array of size Count over stamped-out instances of Type.
template <typename Type, int Count>
struct ValueObjArray {
Type* _ptrs[Count];
ValueObjBlock<Type, Count> _block;
template <typename Generator>
ValueObjArray(Generator g) : _ptrs(), _block(g, _ptrs) {}
Type* at(int index) const {
assert(0 <= index && index < Count, "index out-of-bounds: %d", index);
return _ptrs[index];
}
static int count() {
return Count;
}
};
#endif // SHARE_UTILITIES_VALUEOBJARRAY_HPP

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "utilities/valueObjArray.hpp"
#include "unittest.hpp"
class ValueObjArrayTest : public ::testing::Test {
protected:
class IntGenerator {
int _current;
public:
IntGenerator() : _current(0) {}
int operator*() const {
return _current;
}
IntGenerator operator++() {
++_current;
return *this;
}
};
struct Struct {
int _value;
const char* _string;
};
class StructGenerator {
int _current;
static const char* str(int i) {
const char* array[] = {
"0",
"1",
"2",
"3"};
return array[i];
}
public:
StructGenerator() : _current(0) {}
Struct operator*() const {
assert(_current < 4, "precondition");
Struct s = { _current, str(_current)};
return s;
}
StructGenerator operator++() {
++_current;
return *this;
}
};
};
TEST_F(ValueObjArrayTest, primitive) {
ValueObjArrayTest::IntGenerator g;
ValueObjArray<int, 4> array(g);
ASSERT_EQ(array.count(), 4);
ASSERT_EQ(*array.at(0), 0);
ASSERT_EQ(*array.at(1), 1);
ASSERT_EQ(*array.at(2), 2);
ASSERT_EQ(*array.at(3), 3);
}
TEST_F(ValueObjArrayTest, struct) {
ValueObjArrayTest::StructGenerator g;
ValueObjArray<Struct, 4> array(g);
ASSERT_EQ(array.count(), 4);
ASSERT_EQ(array.at(0)->_value, 0);
ASSERT_EQ(array.at(1)->_value, 1);
ASSERT_EQ(array.at(2)->_value, 2);
ASSERT_EQ(array.at(3)->_value, 3);
ASSERT_EQ(array.at(0)->_string[0], '0');
ASSERT_EQ(array.at(1)->_string[0], '1');
ASSERT_EQ(array.at(2)->_string[0], '2');
ASSERT_EQ(array.at(3)->_string[0], '3');
}