mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8244997: Convert the JavaThread::_threadObj oop to use OopStorage
Move the oop and handle releasing it in the service thread. Remove Universe::oops_do from callers. Co-authored-by: Erik Osterlund <erik.osterlund@oracle.com> Co-authored-by: Tom Rodriguez <tom.rodriguez@oracle.com> Reviewed-by: dholmes, zgu, eosterlund, cjplummer
This commit is contained in:
parent
4d3baa2d37
commit
0c9e0c2e7f
46 changed files with 162 additions and 207 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* 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
|
||||||
|
@ -48,7 +48,7 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) {
|
||||||
void LIR_Address::verify() const {
|
void LIR_Address::verify() const {
|
||||||
assert(base()->is_cpu_register(), "wrong base operand");
|
assert(base()->is_cpu_register(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_double_cpu() || index()->is_single_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_double_cpu() || index()->is_single_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2010, 2020, 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
|
||||||
|
@ -52,12 +52,12 @@ void LIR_Address::verify() const {
|
||||||
// be handled by the back-end or will be rejected if not.
|
// be handled by the back-end or will be rejected if not.
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
#else
|
#else
|
||||||
assert(base()->is_single_cpu(), "wrong base operand");
|
assert(base()->is_single_cpu(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016 SAP SE. 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.
|
||||||
*
|
*
|
||||||
|
@ -52,12 +52,12 @@ void LIR_Address::verify() const {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
assert(base()->is_cpu_register(), "wrong base operand");
|
assert(base()->is_cpu_register(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
#else
|
#else
|
||||||
assert(base()->is_single_cpu(), "wrong base operand");
|
assert(base()->is_single_cpu(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016 SAP SE. 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.
|
||||||
*
|
*
|
||||||
|
@ -51,7 +51,7 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) {
|
||||||
void LIR_Address::verify() const {
|
void LIR_Address::verify() const {
|
||||||
assert(base()->is_cpu_register(), "wrong base operand");
|
assert(base()->is_cpu_register(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* 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
|
||||||
|
@ -62,12 +62,12 @@ void LIR_Address::verify() const {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
assert(base()->is_cpu_register(), "wrong base operand");
|
assert(base()->is_cpu_register(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
#else
|
#else
|
||||||
assert(base()->is_single_cpu(), "wrong base operand");
|
assert(base()->is_single_cpu(), "wrong base operand");
|
||||||
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
||||||
assert(base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
||||||
"wrong type for addresses");
|
"wrong type for addresses");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1315,8 +1315,12 @@ void LIRGenerator::do_isPrimitive(Intrinsic* x) {
|
||||||
// Example: Thread.currentThread()
|
// Example: Thread.currentThread()
|
||||||
void LIRGenerator::do_currentThread(Intrinsic* x) {
|
void LIRGenerator::do_currentThread(Intrinsic* x) {
|
||||||
assert(x->number_of_arguments() == 0, "wrong type");
|
assert(x->number_of_arguments() == 0, "wrong type");
|
||||||
|
LIR_Opr temp = new_register(T_ADDRESS);
|
||||||
LIR_Opr reg = rlock_result(x);
|
LIR_Opr reg = rlock_result(x);
|
||||||
__ move_wide(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg);
|
__ move(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_ADDRESS), temp);
|
||||||
|
// threadObj = ((OopHandle)_threadObj)->resolve();
|
||||||
|
access_load(IN_NATIVE, T_OBJECT,
|
||||||
|
LIR_OprFact::address(new LIR_Address(temp, T_OBJECT)), reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,6 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
|
||||||
|
|
||||||
// Root scanning phases
|
// Root scanning phases
|
||||||
_gc_par_phases[ThreadRoots] = new WorkerDataArray<double>("ThreadRoots", "Thread Roots (ms):", max_gc_threads);
|
_gc_par_phases[ThreadRoots] = new WorkerDataArray<double>("ThreadRoots", "Thread Roots (ms):", max_gc_threads);
|
||||||
_gc_par_phases[UniverseRoots] = new WorkerDataArray<double>("UniverseRoots", "Universe Roots (ms):", max_gc_threads);
|
|
||||||
_gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>("ObjectSynchronizerRoots", "ObjectSynchronizer Roots (ms):", max_gc_threads);
|
_gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>("ObjectSynchronizerRoots", "ObjectSynchronizer Roots (ms):", max_gc_threads);
|
||||||
_gc_par_phases[CLDGRoots] = new WorkerDataArray<double>("CLDGRoots", "CLDG Roots (ms):", max_gc_threads);
|
_gc_par_phases[CLDGRoots] = new WorkerDataArray<double>("CLDGRoots", "CLDG Roots (ms):", max_gc_threads);
|
||||||
AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>("AOTCodeRoots", "AOT Root Scan (ms):", max_gc_threads);)
|
AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>("AOTCodeRoots", "AOT Root Scan (ms):", max_gc_threads);)
|
||||||
|
|
|
@ -48,7 +48,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||||
GCWorkerStart,
|
GCWorkerStart,
|
||||||
ExtRootScan,
|
ExtRootScan,
|
||||||
ThreadRoots,
|
ThreadRoots,
|
||||||
UniverseRoots,
|
|
||||||
ObjectSynchronizerRoots,
|
ObjectSynchronizerRoots,
|
||||||
CLDGRoots,
|
CLDGRoots,
|
||||||
AOT_ONLY(AOTCodeRoots COMMA)
|
AOT_ONLY(AOTCodeRoots COMMA)
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
#include "gc/shared/oopStorageSetParState.inline.hpp"
|
#include "gc/shared/oopStorageSetParState.inline.hpp"
|
||||||
#include "gc/shared/referenceProcessor.hpp"
|
#include "gc/shared/referenceProcessor.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "memory/universe.hpp"
|
|
||||||
#include "runtime/mutex.hpp"
|
#include "runtime/mutex.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
|
@ -181,13 +180,6 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
|
||||||
uint worker_id) {
|
uint worker_id) {
|
||||||
OopClosure* strong_roots = closures->strong_oops();
|
OopClosure* strong_roots = closures->strong_oops();
|
||||||
|
|
||||||
{
|
|
||||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_id);
|
|
||||||
if (_process_strong_tasks.try_claim_task(G1RP_PS_Universe_oops_do)) {
|
|
||||||
Universe::oops_do(strong_roots);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_id);
|
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_id);
|
||||||
if (_process_strong_tasks.try_claim_task(G1RP_PS_ObjectSynchronizer_oops_do)) {
|
if (_process_strong_tasks.try_claim_task(G1RP_PS_ObjectSynchronizer_oops_do)) {
|
||||||
|
|
|
@ -2008,10 +2008,6 @@ static void mark_from_roots_work(ParallelRootType::Value root_type, uint worker_
|
||||||
PCMarkAndPushClosure mark_and_push_closure(cm);
|
PCMarkAndPushClosure mark_and_push_closure(cm);
|
||||||
|
|
||||||
switch (root_type) {
|
switch (root_type) {
|
||||||
case ParallelRootType::universe:
|
|
||||||
Universe::oops_do(&mark_and_push_closure);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParallelRootType::object_synchronizer:
|
case ParallelRootType::object_synchronizer:
|
||||||
ObjectSynchronizer::oops_do(&mark_and_push_closure);
|
ObjectSynchronizer::oops_do(&mark_and_push_closure);
|
||||||
break;
|
break;
|
||||||
|
@ -2225,7 +2221,6 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
|
||||||
PCAdjustPointerClosure oop_closure(cm);
|
PCAdjustPointerClosure oop_closure(cm);
|
||||||
|
|
||||||
// General strong roots.
|
// General strong roots.
|
||||||
Universe::oops_do(&oop_closure);
|
|
||||||
Threads::oops_do(&oop_closure, NULL);
|
Threads::oops_do(&oop_closure, NULL);
|
||||||
ObjectSynchronizer::oops_do(&oop_closure);
|
ObjectSynchronizer::oops_do(&oop_closure);
|
||||||
OopStorageSet::strong_oops_do(&oop_closure);
|
OopStorageSet::strong_oops_do(&oop_closure);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* 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
|
||||||
|
@ -34,7 +34,6 @@ public:
|
||||||
// The order reflects the order these roots are to be processed,
|
// The order reflects the order these roots are to be processed,
|
||||||
// We do not want any holes in the enum as we enumerate these values by incrementing them.
|
// We do not want any holes in the enum as we enumerate these values by incrementing them.
|
||||||
enum Value {
|
enum Value {
|
||||||
universe,
|
|
||||||
object_synchronizer,
|
object_synchronizer,
|
||||||
class_loader_data,
|
class_loader_data,
|
||||||
code_cache,
|
code_cache,
|
||||||
|
|
|
@ -92,10 +92,6 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i
|
||||||
PSPromoteRootsClosure roots_to_old_closure(pm);
|
PSPromoteRootsClosure roots_to_old_closure(pm);
|
||||||
|
|
||||||
switch (root_type) {
|
switch (root_type) {
|
||||||
case ParallelRootType::universe:
|
|
||||||
Universe::oops_do(&roots_closure);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParallelRootType::object_synchronizer:
|
case ParallelRootType::object_synchronizer:
|
||||||
ObjectSynchronizer::oops_do(&roots_closure);
|
ObjectSynchronizer::oops_do(&roots_closure);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 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.
|
* 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
|
||||||
|
@ -141,6 +141,7 @@ Node* BarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) con
|
||||||
bool control_dependent = (decorators & C2_CONTROL_DEPENDENT_LOAD) != 0;
|
bool control_dependent = (decorators & C2_CONTROL_DEPENDENT_LOAD) != 0;
|
||||||
bool unknown_control = (decorators & C2_UNKNOWN_CONTROL_LOAD) != 0;
|
bool unknown_control = (decorators & C2_UNKNOWN_CONTROL_LOAD) != 0;
|
||||||
bool unsafe = (decorators & C2_UNSAFE_ACCESS) != 0;
|
bool unsafe = (decorators & C2_UNSAFE_ACCESS) != 0;
|
||||||
|
bool immutable = (decorators & C2_IMMUTABLE_MEMORY) != 0;
|
||||||
|
|
||||||
bool in_native = (decorators & IN_NATIVE) != 0;
|
bool in_native = (decorators & IN_NATIVE) != 0;
|
||||||
|
|
||||||
|
@ -153,10 +154,14 @@ Node* BarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) con
|
||||||
GraphKit* kit = parse_access.kit();
|
GraphKit* kit = parse_access.kit();
|
||||||
Node* control = control_dependent ? kit->control() : NULL;
|
Node* control = control_dependent ? kit->control() : NULL;
|
||||||
|
|
||||||
if (in_native) {
|
if (immutable) {
|
||||||
load = kit->make_load(control, adr, val_type, access.type(), mo, dep,
|
assert(!requires_atomic_access, "can't ensure atomicity");
|
||||||
requires_atomic_access, unaligned,
|
Compile* C = Compile::current();
|
||||||
|
Node* mem = kit->immutable_memory();
|
||||||
|
load = LoadNode::make(kit->gvn(), control, mem, adr,
|
||||||
|
adr_type, val_type, access.type(), mo, dep, unaligned,
|
||||||
mismatched, unsafe, access.barrier_data());
|
mismatched, unsafe, access.barrier_data());
|
||||||
|
load = kit->gvn().transform(load);
|
||||||
} else {
|
} else {
|
||||||
load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo,
|
load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo,
|
||||||
dep, requires_atomic_access, unaligned, mismatched, unsafe,
|
dep, requires_atomic_access, unaligned, mismatched, unsafe,
|
||||||
|
|
|
@ -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.
|
* 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
|
||||||
|
@ -54,6 +54,8 @@ const DecoratorSet C2_READ_ACCESS = DECORATOR_LAST << 8;
|
||||||
const DecoratorSet C2_TIGHTLY_COUPLED_ALLOC = DECORATOR_LAST << 9;
|
const DecoratorSet C2_TIGHTLY_COUPLED_ALLOC = DECORATOR_LAST << 9;
|
||||||
// Loads and stores from an arraycopy being optimized
|
// Loads and stores from an arraycopy being optimized
|
||||||
const DecoratorSet C2_ARRAY_COPY = DECORATOR_LAST << 10;
|
const DecoratorSet C2_ARRAY_COPY = DECORATOR_LAST << 10;
|
||||||
|
// Loads from immutable memory
|
||||||
|
const DecoratorSet C2_IMMUTABLE_MEMORY = DECORATOR_LAST << 11;
|
||||||
|
|
||||||
class Compile;
|
class Compile;
|
||||||
class ConnectionGraph;
|
class ConnectionGraph;
|
||||||
|
|
|
@ -817,10 +817,6 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope,
|
||||||
bool is_par = scope->n_threads() > 1;
|
bool is_par = scope->n_threads() > 1;
|
||||||
Threads::possibly_parallel_oops_do(is_par, strong_roots, roots_from_code_p);
|
Threads::possibly_parallel_oops_do(is_par, strong_roots, roots_from_code_p);
|
||||||
|
|
||||||
if (_process_strong_tasks->try_claim_task(GCH_PS_Universe_oops_do)) {
|
|
||||||
Universe::oops_do(strong_roots);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_process_strong_tasks->try_claim_task(GCH_PS_ObjectSynchronizer_oops_do)) {
|
if (_process_strong_tasks->try_claim_task(GCH_PS_ObjectSynchronizer_oops_do)) {
|
||||||
ObjectSynchronizer::oops_do(strong_roots);
|
ObjectSynchronizer::oops_do(strong_roots);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,6 @@ protected:
|
||||||
|
|
||||||
// The set of potentially parallel tasks in root scanning.
|
// The set of potentially parallel tasks in root scanning.
|
||||||
enum GCH_strong_roots_tasks {
|
enum GCH_strong_roots_tasks {
|
||||||
GCH_PS_Universe_oops_do,
|
|
||||||
GCH_PS_ObjectSynchronizer_oops_do,
|
GCH_PS_ObjectSynchronizer_oops_do,
|
||||||
GCH_PS_OopStorageSet_oops_do,
|
GCH_PS_OopStorageSet_oops_do,
|
||||||
GCH_PS_ClassLoaderDataGraph_oops_do,
|
GCH_PS_ClassLoaderDataGraph_oops_do,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* 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
|
||||||
|
@ -37,7 +37,7 @@ class OopStorageSet : public AllStatic {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Must be updated when new OopStorages are introduced
|
// Must be updated when new OopStorages are introduced
|
||||||
static const uint strong_count = 2;
|
static const uint strong_count = 3;
|
||||||
static const uint weak_count = 4 JFR_ONLY(+ 1);
|
static const uint weak_count = 4 JFR_ONLY(+ 1);
|
||||||
static const uint all_count = strong_count + weak_count;
|
static const uint all_count = strong_count + weak_count;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ class outputStream;
|
||||||
f(CNT_PREFIX ## TotalWork, DESC_PREFIX "<total>") \
|
f(CNT_PREFIX ## TotalWork, DESC_PREFIX "<total>") \
|
||||||
f(CNT_PREFIX ## ThreadRoots, DESC_PREFIX "Thread Roots") \
|
f(CNT_PREFIX ## ThreadRoots, DESC_PREFIX "Thread Roots") \
|
||||||
f(CNT_PREFIX ## CodeCacheRoots, DESC_PREFIX "Code Cache Roots") \
|
f(CNT_PREFIX ## CodeCacheRoots, DESC_PREFIX "Code Cache Roots") \
|
||||||
f(CNT_PREFIX ## UniverseRoots, DESC_PREFIX "Universe Roots") \
|
|
||||||
f(CNT_PREFIX ## VMStrongRoots, DESC_PREFIX "VM Strong Roots") \
|
f(CNT_PREFIX ## VMStrongRoots, DESC_PREFIX "VM Strong Roots") \
|
||||||
f(CNT_PREFIX ## VMWeakRoots, DESC_PREFIX "VM Weak Roots") \
|
f(CNT_PREFIX ## VMWeakRoots, DESC_PREFIX "VM Weak Roots") \
|
||||||
f(CNT_PREFIX ## ObjectSynchronizerRoots, DESC_PREFIX "Synchronizer Roots") \
|
f(CNT_PREFIX ## ObjectSynchronizerRoots, DESC_PREFIX "Synchronizer Roots") \
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include "gc/shenandoah/shenandoahVMOperations.hpp"
|
#include "gc/shenandoah/shenandoahVMOperations.hpp"
|
||||||
#include "memory/iterator.hpp"
|
#include "memory/iterator.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "memory/universe.hpp"
|
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
|
|
||||||
ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do,
|
ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do,
|
||||||
|
@ -53,12 +52,10 @@ void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShenandoahSerialRoots::ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase) :
|
ShenandoahSerialRoots::ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase) :
|
||||||
_universe_root(&Universe::oops_do, phase, ShenandoahPhaseTimings::UniverseRoots),
|
|
||||||
_object_synchronizer_root(&ObjectSynchronizer::oops_do, phase, ShenandoahPhaseTimings::ObjectSynchronizerRoots) {
|
_object_synchronizer_root(&ObjectSynchronizer::oops_do, phase, ShenandoahPhaseTimings::ObjectSynchronizerRoots) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) {
|
void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) {
|
||||||
_universe_root.oops_do(cl, worker_id);
|
|
||||||
_object_synchronizer_root.oops_do(cl, worker_id);
|
_object_synchronizer_root.oops_do(cl, worker_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ public:
|
||||||
|
|
||||||
class ShenandoahSerialRoots {
|
class ShenandoahSerialRoots {
|
||||||
private:
|
private:
|
||||||
ShenandoahSerialRoot _universe_root;
|
|
||||||
ShenandoahSerialRoot _object_synchronizer_root;
|
ShenandoahSerialRoot _object_synchronizer_root;
|
||||||
public:
|
public:
|
||||||
ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase);
|
ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase);
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include "gc/shared/oopStorage.inline.hpp"
|
#include "gc/shared/oopStorage.inline.hpp"
|
||||||
#include "gc/shared/oopStorageSet.hpp"
|
#include "gc/shared/oopStorageSet.hpp"
|
||||||
#include "gc/shared/weakProcessor.inline.hpp"
|
#include "gc/shared/weakProcessor.inline.hpp"
|
||||||
#include "memory/universe.hpp"
|
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
@ -75,7 +74,6 @@ void ShenandoahRootVerifier::oops_do(OopClosure* oops) {
|
||||||
|
|
||||||
if (verify(SerialRoots)) {
|
if (verify(SerialRoots)) {
|
||||||
shenandoah_assert_safepoint();
|
shenandoah_assert_safepoint();
|
||||||
Universe::oops_do(oops);
|
|
||||||
ObjectSynchronizer::oops_do(oops);
|
ObjectSynchronizer::oops_do(oops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +117,6 @@ void ShenandoahRootVerifier::roots_do(OopClosure* oops) {
|
||||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
||||||
ClassLoaderDataGraph::cld_do(&clds);
|
ClassLoaderDataGraph::cld_do(&clds);
|
||||||
|
|
||||||
Universe::oops_do(oops);
|
|
||||||
JNIHandles::oops_do(oops);
|
JNIHandles::oops_do(oops);
|
||||||
ObjectSynchronizer::oops_do(oops);
|
ObjectSynchronizer::oops_do(oops);
|
||||||
Universe::vm_global()->oops_do(oops);
|
Universe::vm_global()->oops_do(oops);
|
||||||
|
@ -145,7 +142,6 @@ void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) {
|
||||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
||||||
ClassLoaderDataGraph::roots_cld_do(&clds, NULL);
|
ClassLoaderDataGraph::roots_cld_do(&clds, NULL);
|
||||||
|
|
||||||
Universe::oops_do(oops);
|
|
||||||
JNIHandles::oops_do(oops);
|
JNIHandles::oops_do(oops);
|
||||||
ObjectSynchronizer::oops_do(oops);
|
ObjectSynchronizer::oops_do(oops);
|
||||||
Universe::vm_global()->oops_do(oops);
|
Universe::vm_global()->oops_do(oops);
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup");
|
static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots");
|
static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
|
static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsUniverse("Pause Roots Universe");
|
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
|
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
|
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsVMThread("Pause Roots VM Thread");
|
static const ZStatSubPhase ZSubPhasePauseRootsVMThread("Pause Roots VM Thread");
|
||||||
|
@ -185,7 +184,6 @@ void ZJavaThreadsIterator::threads_do(ThreadClosure* cl) {
|
||||||
ZRootsIterator::ZRootsIterator(bool visit_jvmti_weak_export) :
|
ZRootsIterator::ZRootsIterator(bool visit_jvmti_weak_export) :
|
||||||
_visit_jvmti_weak_export(visit_jvmti_weak_export),
|
_visit_jvmti_weak_export(visit_jvmti_weak_export),
|
||||||
_java_threads_iter(),
|
_java_threads_iter(),
|
||||||
_universe(this),
|
|
||||||
_object_synchronizer(this),
|
_object_synchronizer(this),
|
||||||
_jvmti_weak_export(this),
|
_jvmti_weak_export(this),
|
||||||
_vm_thread(this),
|
_vm_thread(this),
|
||||||
|
@ -213,11 +211,6 @@ ZRootsIterator::~ZRootsIterator() {
|
||||||
COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers());
|
COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZRootsIterator::do_universe(ZRootsIteratorClosure* cl) {
|
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsUniverse);
|
|
||||||
Universe::oops_do(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZRootsIterator::do_object_synchronizer(ZRootsIteratorClosure* cl) {
|
void ZRootsIterator::do_object_synchronizer(ZRootsIteratorClosure* cl) {
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer);
|
ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer);
|
||||||
ObjectSynchronizer::oops_do(cl);
|
ObjectSynchronizer::oops_do(cl);
|
||||||
|
@ -248,7 +241,6 @@ void ZRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) {
|
||||||
|
|
||||||
void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
|
void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
|
||||||
ZStatTimer timer(ZSubPhasePauseRoots);
|
ZStatTimer timer(ZSubPhasePauseRoots);
|
||||||
_universe.oops_do(cl);
|
|
||||||
_object_synchronizer.oops_do(cl);
|
_object_synchronizer.oops_do(cl);
|
||||||
_vm_thread.oops_do(cl);
|
_vm_thread.oops_do(cl);
|
||||||
_java_threads.oops_do(cl);
|
_java_threads.oops_do(cl);
|
||||||
|
|
|
@ -110,14 +110,12 @@ private:
|
||||||
const bool _visit_jvmti_weak_export;
|
const bool _visit_jvmti_weak_export;
|
||||||
ZJavaThreadsIterator _java_threads_iter;
|
ZJavaThreadsIterator _java_threads_iter;
|
||||||
|
|
||||||
void do_universe(ZRootsIteratorClosure* cl);
|
|
||||||
void do_object_synchronizer(ZRootsIteratorClosure* cl);
|
void do_object_synchronizer(ZRootsIteratorClosure* cl);
|
||||||
void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
|
void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
|
||||||
void do_vm_thread(ZRootsIteratorClosure* cl);
|
void do_vm_thread(ZRootsIteratorClosure* cl);
|
||||||
void do_java_threads(ZRootsIteratorClosure* cl);
|
void do_java_threads(ZRootsIteratorClosure* cl);
|
||||||
void do_code_cache(ZRootsIteratorClosure* cl);
|
void do_code_cache(ZRootsIteratorClosure* cl);
|
||||||
|
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_universe> _universe;
|
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_vm_thread> _vm_thread;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_vm_thread> _vm_thread;
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "jfr/leakprofiler/chains/edgeQueue.hpp"
|
#include "jfr/leakprofiler/chains/edgeQueue.hpp"
|
||||||
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
|
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
|
||||||
#include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"
|
#include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"
|
||||||
#include "memory/universe.hpp"
|
|
||||||
#include "oops/access.inline.hpp"
|
#include "oops/access.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "runtime/synchronizer.hpp"
|
#include "runtime/synchronizer.hpp"
|
||||||
|
@ -73,7 +72,6 @@ void RootSetClosure<Delegate>::process() {
|
||||||
// We don't follow code blob oops, because they have misaligned oops.
|
// We don't follow code blob oops, because they have misaligned oops.
|
||||||
Threads::oops_do(this, NULL);
|
Threads::oops_do(this, NULL);
|
||||||
ObjectSynchronizer::oops_do(this);
|
ObjectSynchronizer::oops_do(this);
|
||||||
Universe::oops_do(this);
|
|
||||||
OopStorageSet::strong_oops_do(this);
|
OopStorageSet::strong_oops_do(this);
|
||||||
AOTLoader::oops_do(this);
|
AOTLoader::oops_do(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
|
#include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
|
||||||
#include "jfr/utilities/jfrThreadIterator.hpp"
|
#include "jfr/utilities/jfrThreadIterator.hpp"
|
||||||
#include "memory/iterator.hpp"
|
#include "memory/iterator.hpp"
|
||||||
#include "memory/universe.hpp"
|
|
||||||
#include "oops/klass.hpp"
|
#include "oops/klass.hpp"
|
||||||
#include "oops/oop.hpp"
|
#include "oops/oop.hpp"
|
||||||
#include "prims/jvmtiThreadState.hpp"
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
|
@ -97,7 +96,6 @@ class ReferenceToRootClosure : public StackObj {
|
||||||
|
|
||||||
bool do_cldg_roots();
|
bool do_cldg_roots();
|
||||||
bool do_object_synchronizer_roots();
|
bool do_object_synchronizer_roots();
|
||||||
bool do_universe_roots();
|
|
||||||
bool do_oop_storage_roots();
|
bool do_oop_storage_roots();
|
||||||
bool do_string_table_roots();
|
bool do_string_table_roots();
|
||||||
bool do_aot_loader_roots();
|
bool do_aot_loader_roots();
|
||||||
|
@ -138,13 +136,6 @@ bool ReferenceToRootClosure::do_object_synchronizer_roots() {
|
||||||
return rlc.complete();
|
return rlc.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReferenceToRootClosure::do_universe_roots() {
|
|
||||||
assert(!complete(), "invariant");
|
|
||||||
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_universe, OldObjectRoot::_type_undetermined, NULL);
|
|
||||||
Universe::oops_do(&rlc);
|
|
||||||
return rlc.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReferenceToRootClosure::do_oop_storage_roots() {
|
bool ReferenceToRootClosure::do_oop_storage_roots() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) {
|
for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) {
|
||||||
|
@ -185,11 +176,6 @@ bool ReferenceToRootClosure::do_roots() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_universe_roots()) {
|
|
||||||
_complete = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_oop_storage_roots()) {
|
if (do_oop_storage_roots()) {
|
||||||
_complete = true;
|
_complete = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -170,7 +170,7 @@
|
||||||
nonstatic_field(JVMCICompileState, _jvmti_can_post_on_exceptions, jbyte) \
|
nonstatic_field(JVMCICompileState, _jvmti_can_post_on_exceptions, jbyte) \
|
||||||
nonstatic_field(JVMCICompileState, _jvmti_can_pop_frame, jbyte) \
|
nonstatic_field(JVMCICompileState, _jvmti_can_pop_frame, jbyte) \
|
||||||
\
|
\
|
||||||
nonstatic_field(JavaThread, _threadObj, oop) \
|
nonstatic_field(JavaThread, _threadObj, OopHandle) \
|
||||||
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
|
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
|
||||||
nonstatic_field(JavaThread, _vm_result, oop) \
|
nonstatic_field(JavaThread, _vm_result, oop) \
|
||||||
volatile_nonstatic_field(JavaThread, _exception_oop, oop) \
|
volatile_nonstatic_field(JavaThread, _exception_oop, oop) \
|
||||||
|
|
|
@ -223,11 +223,6 @@ void Universe::basic_type_classes_do(KlassClosure *closure) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Universe::oops_do(OopClosure* f) {
|
|
||||||
|
|
||||||
ThreadsSMRSupport::exiting_threads_oops_do(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LatestMethodCache::metaspace_pointers_do(MetaspaceClosure* it) {
|
void LatestMethodCache::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||||
it->push(&_klass);
|
it->push(&_klass);
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,12 +328,6 @@ class Universe: AllStatic {
|
||||||
static bool should_fill_in_stack_trace(Handle throwable);
|
static bool should_fill_in_stack_trace(Handle throwable);
|
||||||
static void check_alignment(uintx size, uintx alignment, const char* name);
|
static void check_alignment(uintx size, uintx alignment, const char* name);
|
||||||
|
|
||||||
// Iteration
|
|
||||||
|
|
||||||
// Apply "f" to the addresses of all the direct heap pointers maintained
|
|
||||||
// as static fields of "Universe".
|
|
||||||
static void oops_do(OopClosure* f);
|
|
||||||
|
|
||||||
// CDS support
|
// CDS support
|
||||||
static void serialize(SerializeClosure* f);
|
static void serialize(SerializeClosure* f);
|
||||||
|
|
||||||
|
|
|
@ -1614,7 +1614,7 @@ Node* GraphKit::access_load(Node* adr, // actual adress to load val at
|
||||||
return top(); // Dead path ?
|
return top(); // Dead path ?
|
||||||
}
|
}
|
||||||
|
|
||||||
C2AccessValuePtr addr(adr, NULL);
|
C2AccessValuePtr addr(adr, adr->bottom_type()->is_ptr());
|
||||||
C2ParseAccess access(this, decorators | C2_READ_ACCESS, bt, NULL, addr);
|
C2ParseAccess access(this, decorators | C2_READ_ACCESS, bt, NULL, addr);
|
||||||
if (access.is_raw()) {
|
if (access.is_raw()) {
|
||||||
return _barrier_set->BarrierSetC2::load_at(access, val_type);
|
return _barrier_set->BarrierSetC2::load_at(access, val_type);
|
||||||
|
|
|
@ -1096,9 +1096,10 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) {
|
||||||
const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull);
|
const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull);
|
||||||
Node* thread = _gvn.transform(new ThreadLocalNode());
|
Node* thread = _gvn.transform(new ThreadLocalNode());
|
||||||
Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset()));
|
Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset()));
|
||||||
Node* threadObj = _gvn.transform(LoadNode::make(_gvn, NULL, immutable_memory(), p, p->bottom_type()->is_ptr(), thread_type, T_OBJECT, MemNode::unordered));
|
|
||||||
tls_output = thread;
|
tls_output = thread;
|
||||||
return threadObj;
|
Node* thread_obj_handle = LoadNode::make(_gvn, NULL, immutable_memory(), p, p->bottom_type()->is_ptr(), TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered);
|
||||||
|
thread_obj_handle = _gvn.transform(thread_obj_handle);
|
||||||
|
return access_load(thread_obj_handle, thread_type, T_OBJECT, IN_NATIVE | C2_IMMUTABLE_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -811,7 +811,9 @@ bool LoadNode::is_immutable_value(Node* adr) {
|
||||||
return (adr->is_AddP() && adr->in(AddPNode::Base)->is_top() &&
|
return (adr->is_AddP() && adr->in(AddPNode::Base)->is_top() &&
|
||||||
adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
|
adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
|
||||||
(adr->in(AddPNode::Offset)->find_intptr_t_con(-1) ==
|
(adr->in(AddPNode::Offset)->find_intptr_t_con(-1) ==
|
||||||
in_bytes(JavaThread::osthread_offset())));
|
in_bytes(JavaThread::osthread_offset()) ||
|
||||||
|
adr->in(AddPNode::Offset)->find_intptr_t_con(-1) ==
|
||||||
|
in_bytes(JavaThread::threadObj_offset())));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -3030,7 +3030,7 @@ inline bool VM_HeapWalkOperation::collect_simple_roots() {
|
||||||
// Many of these won't be visible but others (such as instances of important
|
// Many of these won't be visible but others (such as instances of important
|
||||||
// exceptions) will be visible.
|
// exceptions) will be visible.
|
||||||
blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
|
blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
|
||||||
Universe::oops_do(&blk);
|
Universe::vm_global()->oops_do(&blk);
|
||||||
if (blk.stopped()) {
|
if (blk.stopped()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "gc/shared/oopStorage.hpp"
|
#include "gc/shared/oopStorage.hpp"
|
||||||
#include "gc/shared/oopStorageSet.hpp"
|
#include "gc/shared/oopStorageSet.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
#include "oops/oopHandle.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/interfaceSupport.inline.hpp"
|
#include "runtime/interfaceSupport.inline.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
@ -53,6 +54,29 @@ JvmtiDeferredEvent* ServiceThread::_jvmti_event = NULL;
|
||||||
// to add this field to the per-JavaThread event queue. TODO: fix this sometime later
|
// to add this field to the per-JavaThread event queue. TODO: fix this sometime later
|
||||||
JvmtiDeferredEventQueue ServiceThread::_jvmti_service_queue;
|
JvmtiDeferredEventQueue ServiceThread::_jvmti_service_queue;
|
||||||
|
|
||||||
|
// Defer releasing JavaThread OopHandle to the ServiceThread
|
||||||
|
class OopHandleList : public CHeapObj<mtInternal> {
|
||||||
|
OopHandle _handle;
|
||||||
|
OopHandleList* _next;
|
||||||
|
public:
|
||||||
|
OopHandleList(OopHandle h, OopHandleList* next) : _handle(h), _next(next) {}
|
||||||
|
~OopHandleList() {
|
||||||
|
_handle.release(JavaThread::thread_oop_storage());
|
||||||
|
}
|
||||||
|
OopHandleList* next() const { return _next; }
|
||||||
|
};
|
||||||
|
|
||||||
|
static OopHandleList* _oop_handle_list = NULL;
|
||||||
|
|
||||||
|
static void release_oop_handles() {
|
||||||
|
assert_lock_strong(Service_lock);
|
||||||
|
while (_oop_handle_list != NULL) {
|
||||||
|
OopHandleList* l = _oop_handle_list;
|
||||||
|
_oop_handle_list = l->next();
|
||||||
|
delete l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServiceThread::initialize() {
|
void ServiceThread::initialize() {
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
|
|
||||||
|
@ -139,6 +163,7 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
||||||
(thread_id_table_work = ThreadIdTable::has_work()) |
|
(thread_id_table_work = ThreadIdTable::has_work()) |
|
||||||
(protection_domain_table_work = SystemDictionary::pd_cache_table()->has_work()) |
|
(protection_domain_table_work = SystemDictionary::pd_cache_table()->has_work()) |
|
||||||
(oopstorage_work = OopStorage::has_cleanup_work_and_reset()) |
|
(oopstorage_work = OopStorage::has_cleanup_work_and_reset()) |
|
||||||
|
(_oop_handle_list != NULL) |
|
||||||
(deflate_idle_monitors = ObjectSynchronizer::is_async_deflation_needed())
|
(deflate_idle_monitors = ObjectSynchronizer::is_async_deflation_needed())
|
||||||
) == 0) {
|
) == 0) {
|
||||||
// Wait until notified that there is some work to do.
|
// Wait until notified that there is some work to do.
|
||||||
|
@ -152,6 +177,11 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
||||||
jvmti_event = _jvmti_service_queue.dequeue();
|
jvmti_event = _jvmti_service_queue.dequeue();
|
||||||
_jvmti_event = &jvmti_event;
|
_jvmti_event = &jvmti_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Release thread OopHandles in lock
|
||||||
|
if (_oop_handle_list != NULL) {
|
||||||
|
release_oop_handles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stringtable_work) {
|
if (stringtable_work) {
|
||||||
|
@ -238,3 +268,10 @@ void ServiceThread::nmethods_do(CodeBlobClosure* cf) {
|
||||||
_jvmti_service_queue.nmethods_do(cf);
|
_jvmti_service_queue.nmethods_do(cf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceThread::add_oop_handle_release(OopHandle handle) {
|
||||||
|
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
OopHandleList* new_head = new OopHandleList(handle, _oop_handle_list);
|
||||||
|
_oop_handle_list = new_head;
|
||||||
|
Service_lock->notify_all();
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* 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
|
||||||
|
@ -52,6 +52,7 @@ class ServiceThread : public JavaThread {
|
||||||
|
|
||||||
// Add event to the service thread event queue.
|
// Add event to the service thread event queue.
|
||||||
static void enqueue_deferred_event(JvmtiDeferredEvent* event);
|
static void enqueue_deferred_event(JvmtiDeferredEvent* event);
|
||||||
|
static void add_oop_handle_release(OopHandle handle);
|
||||||
|
|
||||||
// GC support
|
// GC support
|
||||||
void oops_do(OopClosure* f, CodeBlobClosure* cf);
|
void oops_do(OopClosure* f, CodeBlobClosure* cf);
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#include "gc/shared/barrierSet.hpp"
|
#include "gc/shared/barrierSet.hpp"
|
||||||
#include "gc/shared/gcId.hpp"
|
#include "gc/shared/gcId.hpp"
|
||||||
#include "gc/shared/gcLocker.inline.hpp"
|
#include "gc/shared/gcLocker.inline.hpp"
|
||||||
|
#include "gc/shared/oopStorage.hpp"
|
||||||
|
#include "gc/shared/oopStorageSet.hpp"
|
||||||
#include "gc/shared/workgroup.hpp"
|
#include "gc/shared/workgroup.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/linkResolver.hpp"
|
#include "interpreter/linkResolver.hpp"
|
||||||
|
@ -1055,12 +1057,12 @@ static Handle create_initial_thread_group(TRAPS) {
|
||||||
return main_instance;
|
return main_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the initial Thread
|
// Creates the initial Thread, and sets it to running.
|
||||||
static oop create_initial_thread(Handle thread_group, JavaThread* thread,
|
static void create_initial_thread(Handle thread_group, JavaThread* thread,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
InstanceKlass* ik = SystemDictionary::Thread_klass();
|
InstanceKlass* ik = SystemDictionary::Thread_klass();
|
||||||
assert(ik->is_initialized(), "must be");
|
assert(ik->is_initialized(), "must be");
|
||||||
instanceHandle thread_oop = ik->allocate_instance_handle(CHECK_NULL);
|
instanceHandle thread_oop = ik->allocate_instance_handle(CHECK);
|
||||||
|
|
||||||
// Cannot use JavaCalls::construct_new_instance because the java.lang.Thread
|
// Cannot use JavaCalls::construct_new_instance because the java.lang.Thread
|
||||||
// constructor calls Thread.current(), which must be set here for the
|
// constructor calls Thread.current(), which must be set here for the
|
||||||
|
@ -1069,7 +1071,7 @@ static oop create_initial_thread(Handle thread_group, JavaThread* thread,
|
||||||
java_lang_Thread::set_priority(thread_oop(), NormPriority);
|
java_lang_Thread::set_priority(thread_oop(), NormPriority);
|
||||||
thread->set_threadObj(thread_oop());
|
thread->set_threadObj(thread_oop());
|
||||||
|
|
||||||
Handle string = java_lang_String::create_from_str("main", CHECK_NULL);
|
Handle string = java_lang_String::create_from_str("main", CHECK);
|
||||||
|
|
||||||
JavaValue result(T_VOID);
|
JavaValue result(T_VOID);
|
||||||
JavaCalls::call_special(&result, thread_oop,
|
JavaCalls::call_special(&result, thread_oop,
|
||||||
|
@ -1078,8 +1080,12 @@ static oop create_initial_thread(Handle thread_group, JavaThread* thread,
|
||||||
vmSymbols::threadgroup_string_void_signature(),
|
vmSymbols::threadgroup_string_void_signature(),
|
||||||
thread_group,
|
thread_group,
|
||||||
string,
|
string,
|
||||||
CHECK_NULL);
|
CHECK);
|
||||||
return thread_oop();
|
|
||||||
|
// Set thread status to running since main thread has
|
||||||
|
// been started and running.
|
||||||
|
java_lang_Thread::set_thread_status(thread_oop(),
|
||||||
|
java_lang_Thread::RUNNABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char java_runtime_name[128] = "";
|
char java_runtime_name[128] = "";
|
||||||
|
@ -1187,6 +1193,23 @@ static void call_postVMInitHook(TRAPS) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialized by VMThread at vm_global_init
|
||||||
|
static OopStorage* _thread_oop_storage = NULL;
|
||||||
|
|
||||||
|
oop JavaThread::threadObj() const {
|
||||||
|
return _threadObj.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JavaThread::set_threadObj(oop p) {
|
||||||
|
assert(_thread_oop_storage != NULL, "not yet initialized");
|
||||||
|
_threadObj = OopHandle(_thread_oop_storage, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
OopStorage* JavaThread::thread_oop_storage() {
|
||||||
|
assert(_thread_oop_storage != NULL, "not yet initialized");
|
||||||
|
return _thread_oop_storage;
|
||||||
|
}
|
||||||
|
|
||||||
void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name,
|
void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name,
|
||||||
bool daemon, TRAPS) {
|
bool daemon, TRAPS) {
|
||||||
assert(thread_group.not_null(), "thread group should be specified");
|
assert(thread_group.not_null(), "thread group should be specified");
|
||||||
|
@ -1653,7 +1676,6 @@ void JavaThread::initialize() {
|
||||||
// Initialize fields
|
// Initialize fields
|
||||||
|
|
||||||
set_saved_exception_pc(NULL);
|
set_saved_exception_pc(NULL);
|
||||||
set_threadObj(NULL);
|
|
||||||
_anchor.clear();
|
_anchor.clear();
|
||||||
set_entry_point(NULL);
|
set_entry_point(NULL);
|
||||||
set_jni_functions(jni_functions());
|
set_jni_functions(jni_functions());
|
||||||
|
@ -1758,7 +1780,7 @@ void JavaThread::interrupt() {
|
||||||
bool JavaThread::is_interrupted(bool clear_interrupted) {
|
bool JavaThread::is_interrupted(bool clear_interrupted) {
|
||||||
debug_only(check_for_dangling_thread_pointer(this);)
|
debug_only(check_for_dangling_thread_pointer(this);)
|
||||||
|
|
||||||
if (threadObj() == NULL) {
|
if (_threadObj.peek() == NULL) {
|
||||||
// If there is no j.l.Thread then it is impossible to have
|
// If there is no j.l.Thread then it is impossible to have
|
||||||
// been interrupted. We can find NULL during VM initialization
|
// been interrupted. We can find NULL during VM initialization
|
||||||
// or when a JNI thread is still in the process of attaching.
|
// or when a JNI thread is still in the process of attaching.
|
||||||
|
@ -1871,6 +1893,9 @@ JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
|
||||||
|
|
||||||
JavaThread::~JavaThread() {
|
JavaThread::~JavaThread() {
|
||||||
|
|
||||||
|
// Ask ServiceThread to release the threadObj OopHandle
|
||||||
|
ServiceThread::add_oop_handle_release(_threadObj);
|
||||||
|
|
||||||
// JSR166 -- return the parker to the free list
|
// JSR166 -- return the parker to the free list
|
||||||
Parker::Release(_parker);
|
Parker::Release(_parker);
|
||||||
_parker = NULL;
|
_parker = NULL;
|
||||||
|
@ -1971,7 +1996,7 @@ void JavaThread::run() {
|
||||||
|
|
||||||
void JavaThread::thread_main_inner() {
|
void JavaThread::thread_main_inner() {
|
||||||
assert(JavaThread::current() == this, "sanity check");
|
assert(JavaThread::current() == this, "sanity check");
|
||||||
assert(this->threadObj() != NULL, "just checking");
|
assert(_threadObj.peek() != NULL, "just checking");
|
||||||
|
|
||||||
// Execute thread entry point unless this thread has a pending exception
|
// Execute thread entry point unless this thread has a pending exception
|
||||||
// or has been stopped before starting.
|
// or has been stopped before starting.
|
||||||
|
@ -3015,7 +3040,6 @@ void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
|
||||||
|
|
||||||
// Traverse instance variables at the end since the GC may be moving things
|
// Traverse instance variables at the end since the GC may be moving things
|
||||||
// around using this function
|
// around using this function
|
||||||
f->do_oop((oop*) &_threadObj);
|
|
||||||
f->do_oop((oop*) &_vm_result);
|
f->do_oop((oop*) &_vm_result);
|
||||||
f->do_oop((oop*) &_exception_oop);
|
f->do_oop((oop*) &_exception_oop);
|
||||||
f->do_oop((oop*) &_pending_async_exception);
|
f->do_oop((oop*) &_pending_async_exception);
|
||||||
|
@ -3717,13 +3741,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
|
||||||
Handle thread_group = create_initial_thread_group(CHECK);
|
Handle thread_group = create_initial_thread_group(CHECK);
|
||||||
Universe::set_main_thread_group(thread_group());
|
Universe::set_main_thread_group(thread_group());
|
||||||
initialize_class(vmSymbols::java_lang_Thread(), CHECK);
|
initialize_class(vmSymbols::java_lang_Thread(), CHECK);
|
||||||
oop thread_object = create_initial_thread(thread_group, main_thread, CHECK);
|
create_initial_thread(thread_group, main_thread, CHECK);
|
||||||
main_thread->set_threadObj(thread_object);
|
|
||||||
|
|
||||||
// Set thread status to running since main thread has
|
|
||||||
// been started and running.
|
|
||||||
java_lang_Thread::set_thread_status(thread_object,
|
|
||||||
java_lang_Thread::RUNNABLE);
|
|
||||||
|
|
||||||
// The VM creates objects of this class.
|
// The VM creates objects of this class.
|
||||||
initialize_class(vmSymbols::java_lang_Module(), CHECK);
|
initialize_class(vmSymbols::java_lang_Module(), CHECK);
|
||||||
|
@ -3886,6 +3904,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||||
}
|
}
|
||||||
#endif // INCLUDE_JVMCI
|
#endif // INCLUDE_JVMCI
|
||||||
|
|
||||||
|
// Initialize OopStorage for threadObj
|
||||||
|
_thread_oop_storage = OopStorageSet::create_strong("Thread OopStorage");
|
||||||
|
|
||||||
// Attach the main thread to this os thread
|
// Attach the main thread to this os thread
|
||||||
JavaThread* main_thread = new JavaThread();
|
JavaThread* main_thread = new JavaThread();
|
||||||
main_thread->set_thread_state(_thread_in_vm);
|
main_thread->set_thread_state(_thread_in_vm);
|
||||||
|
|
|
@ -92,6 +92,8 @@ class JVMCIPrimitiveArray;
|
||||||
class Metadata;
|
class Metadata;
|
||||||
class ResourceArea;
|
class ResourceArea;
|
||||||
|
|
||||||
|
class OopStorage;
|
||||||
|
|
||||||
DEBUG_ONLY(class ResourceMark;)
|
DEBUG_ONLY(class ResourceMark;)
|
||||||
|
|
||||||
class WorkerThread;
|
class WorkerThread;
|
||||||
|
@ -1017,7 +1019,7 @@ class JavaThread: public Thread {
|
||||||
friend class ThreadsSMRSupport; // to access _threadObj for exiting_threads_oops_do
|
friend class ThreadsSMRSupport; // to access _threadObj for exiting_threads_oops_do
|
||||||
private:
|
private:
|
||||||
bool _on_thread_list; // Is set when this JavaThread is added to the Threads list
|
bool _on_thread_list; // Is set when this JavaThread is added to the Threads list
|
||||||
oop _threadObj; // The Java level thread object
|
OopHandle _threadObj; // The Java level thread object
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
private:
|
private:
|
||||||
|
@ -1277,8 +1279,8 @@ class JavaThread: public Thread {
|
||||||
|
|
||||||
// Thread oop. threadObj() can be NULL for initial JavaThread
|
// Thread oop. threadObj() can be NULL for initial JavaThread
|
||||||
// (or for threads attached via JNI)
|
// (or for threads attached via JNI)
|
||||||
oop threadObj() const { return _threadObj; }
|
oop threadObj() const;
|
||||||
void set_threadObj(oop p) { _threadObj = p; }
|
void set_threadObj(oop p);
|
||||||
|
|
||||||
// Prepare thread and add to priority queue. If a priority is
|
// Prepare thread and add to priority queue. If a priority is
|
||||||
// not specified, use the priority of the thread object. Threads_lock
|
// not specified, use the priority of the thread object. Threads_lock
|
||||||
|
@ -2112,6 +2114,7 @@ public:
|
||||||
void interrupt();
|
void interrupt();
|
||||||
bool is_interrupted(bool clear_interrupted);
|
bool is_interrupted(bool clear_interrupted);
|
||||||
|
|
||||||
|
static OopStorage* thread_oop_storage();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inline implementation of JavaThread::current
|
// Inline implementation of JavaThread::current
|
||||||
|
|
|
@ -41,9 +41,6 @@
|
||||||
#include "utilities/resourceHash.hpp"
|
#include "utilities/resourceHash.hpp"
|
||||||
#include "utilities/vmError.hpp"
|
#include "utilities/vmError.hpp"
|
||||||
|
|
||||||
// List of exiting threads
|
|
||||||
ThreadsSMRSupport::Holder* ThreadsSMRSupport::_exiting_threads = NULL;
|
|
||||||
|
|
||||||
// The '_cnt', '_max' and '_times" fields are enabled via
|
// The '_cnt', '_max' and '_times" fields are enabled via
|
||||||
// -XX:+EnableThreadSMRStatistics:
|
// -XX:+EnableThreadSMRStatistics:
|
||||||
|
|
||||||
|
@ -927,8 +924,6 @@ void ThreadsSMRSupport::release_stable_list_wake_up(bool is_nested) {
|
||||||
|
|
||||||
void ThreadsSMRSupport::remove_thread(JavaThread *thread) {
|
void ThreadsSMRSupport::remove_thread(JavaThread *thread) {
|
||||||
|
|
||||||
ThreadsSMRSupport::add_exiting_thread(thread);
|
|
||||||
|
|
||||||
if (ThreadIdTable::is_initialized()) {
|
if (ThreadIdTable::is_initialized()) {
|
||||||
jlong tid = SharedRuntime::get_java_tid(thread);
|
jlong tid = SharedRuntime::get_java_tid(thread);
|
||||||
ThreadIdTable::remove_thread(tid);
|
ThreadIdTable::remove_thread(tid);
|
||||||
|
@ -998,7 +993,6 @@ void ThreadsSMRSupport::wait_until_not_protected(JavaThread *thread) {
|
||||||
// This is the common case.
|
// This is the common case.
|
||||||
ThreadsSMRSupport::clear_delete_notify();
|
ThreadsSMRSupport::clear_delete_notify();
|
||||||
ThreadsSMRSupport::delete_lock()->unlock();
|
ThreadsSMRSupport::delete_lock()->unlock();
|
||||||
ThreadsSMRSupport::remove_exiting_thread(thread);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!has_logged_once) {
|
if (!has_logged_once) {
|
||||||
|
@ -1188,47 +1182,3 @@ void ThreadsSMRSupport::print_info_elements_on(outputStream* st, ThreadsList* t_
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadsSMRSupport::add_exiting_thread(JavaThread* thread) {
|
|
||||||
assert(thread == JavaThread::current(), "invariant");
|
|
||||||
assert(Threads_lock->owned_by_self(), "invariant");
|
|
||||||
assert(!contains_exiting_thread(thread), "invariant");
|
|
||||||
Holder* h = new Holder(thread, _exiting_threads);
|
|
||||||
_exiting_threads = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadsSMRSupport::remove_exiting_thread(JavaThread* thread) {
|
|
||||||
assert(thread == JavaThread::current(), "invariant");
|
|
||||||
assert(Threads_lock->owned_by_self(), "invariant");
|
|
||||||
// If a thread fails to initialize fully it can be deleted immediately
|
|
||||||
// so we won't remove it from the ThreadsList and so never add it to the
|
|
||||||
// exiting thread list - so we can't assert(contains_exiting_thread(p)) here.
|
|
||||||
|
|
||||||
for (Holder* current = _exiting_threads, **prev_next = &_exiting_threads;
|
|
||||||
current != NULL;
|
|
||||||
prev_next = ¤t->_next, current = current->_next) {
|
|
||||||
if (current->_thread == thread) {
|
|
||||||
*prev_next = current->_next;
|
|
||||||
delete current;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
bool ThreadsSMRSupport::contains_exiting_thread(JavaThread* thread) {
|
|
||||||
for (Holder* current = _exiting_threads; current != NULL; current = current->_next) {
|
|
||||||
if (current->_thread == thread) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ThreadsSMRSupport::exiting_threads_oops_do(OopClosure* f) {
|
|
||||||
assert_locked_or_safepoint(Threads_lock);
|
|
||||||
for (Holder* current = _exiting_threads; current != NULL; current = current->_next) {
|
|
||||||
f->do_oop((oop*) ¤t->_thread->_threadObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -82,33 +82,12 @@ class ThreadClosure;
|
||||||
// but that target JavaThread * will not be deleted until it is no
|
// but that target JavaThread * will not be deleted until it is no
|
||||||
// longer protected by a ThreadsListHandle.
|
// longer protected by a ThreadsListHandle.
|
||||||
//
|
//
|
||||||
// Once a JavaThread has removed itself from the main ThreadsList it is
|
|
||||||
// no longer visited by GC. To ensure that thread's threadObj() oop remains
|
|
||||||
// valid while the thread is still accessible from a ThreadsListHandle we
|
|
||||||
// maintain a special list of exiting threads:
|
|
||||||
// - In remove() we add the exiting thread to the list (under the Threads_lock).
|
|
||||||
// - In wait_until_not_protected() we remove it from the list (again under the
|
|
||||||
// Threads_lock).
|
|
||||||
// - Universe::oops_do walks the list (at a safepoint so VMThread holds
|
|
||||||
// Threads_lock) and visits the _threadObj oop of each JavaThread.
|
|
||||||
|
|
||||||
// SMR Support for the Threads class.
|
// SMR Support for the Threads class.
|
||||||
//
|
//
|
||||||
class ThreadsSMRSupport : AllStatic {
|
class ThreadsSMRSupport : AllStatic {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class SafeThreadsListPtr; // for _nested_thread_list_max, delete_notify(), release_stable_list_wake_up() access
|
friend class SafeThreadsListPtr; // for _nested_thread_list_max, delete_notify(), release_stable_list_wake_up() access
|
||||||
|
|
||||||
// Helper class for the exiting thread list
|
|
||||||
class Holder : public CHeapObj<mtInternal> {
|
|
||||||
public:
|
|
||||||
JavaThread* _thread;
|
|
||||||
Holder* _next;
|
|
||||||
Holder(JavaThread* thread, Holder* next) : _thread(thread), _next(next) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The list of exiting threads
|
|
||||||
static Holder* _exiting_threads;
|
|
||||||
|
|
||||||
// The coordination between ThreadsSMRSupport::release_stable_list() and
|
// The coordination between ThreadsSMRSupport::release_stable_list() and
|
||||||
// ThreadsSMRSupport::smr_delete() uses the delete_lock in order to
|
// ThreadsSMRSupport::smr_delete() uses the delete_lock in order to
|
||||||
// reduce the traffic on the Threads_lock.
|
// reduce the traffic on the Threads_lock.
|
||||||
|
@ -170,12 +149,6 @@ class ThreadsSMRSupport : AllStatic {
|
||||||
static void smr_delete(JavaThread *thread);
|
static void smr_delete(JavaThread *thread);
|
||||||
static void update_tlh_stats(uint millis);
|
static void update_tlh_stats(uint millis);
|
||||||
|
|
||||||
// Exiting thread list maintenance
|
|
||||||
static void add_exiting_thread(JavaThread* thread);
|
|
||||||
static void remove_exiting_thread(JavaThread* thread);
|
|
||||||
DEBUG_ONLY(static bool contains_exiting_thread(JavaThread* thread);)
|
|
||||||
static void exiting_threads_oops_do(OopClosure* f);
|
|
||||||
|
|
||||||
// Logging and printing support:
|
// Logging and printing support:
|
||||||
static void log_statistics();
|
static void log_statistics();
|
||||||
static void print_info_elements_on(outputStream* st, ThreadsList* t_list);
|
static void print_info_elements_on(outputStream* st, ThreadsList* t_list);
|
||||||
|
|
|
@ -740,7 +740,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||||
nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \
|
nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \
|
||||||
nonstatic_field(NamedThread, _name, char*) \
|
nonstatic_field(NamedThread, _name, char*) \
|
||||||
nonstatic_field(NamedThread, _processed_thread, JavaThread*) \
|
nonstatic_field(NamedThread, _processed_thread, JavaThread*) \
|
||||||
nonstatic_field(JavaThread, _threadObj, oop) \
|
nonstatic_field(JavaThread, _threadObj, OopHandle) \
|
||||||
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
|
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
|
||||||
nonstatic_field(JavaThread, _vm_result, oop) \
|
nonstatic_field(JavaThread, _vm_result, oop) \
|
||||||
nonstatic_field(JavaThread, _vm_result_2, Metadata*) \
|
nonstatic_field(JavaThread, _vm_result_2, Metadata*) \
|
||||||
|
|
|
@ -1859,8 +1859,9 @@ void VM_HeapDumper::work(uint worker_id) {
|
||||||
// HPROF_GC_ROOT_JNI_GLOBAL
|
// HPROF_GC_ROOT_JNI_GLOBAL
|
||||||
JNIGlobalsDumper jni_dumper(writer());
|
JNIGlobalsDumper jni_dumper(writer());
|
||||||
JNIHandles::oops_do(&jni_dumper);
|
JNIHandles::oops_do(&jni_dumper);
|
||||||
Universe::oops_do(&jni_dumper); // technically not jni roots, but global roots
|
// technically not jni roots, but global roots
|
||||||
// for things like preallocated throwable backtraces
|
// for things like preallocated throwable backtraces
|
||||||
|
Universe::vm_global()->oops_do(&jni_dumper);
|
||||||
|
|
||||||
// HPROF_GC_ROOT_STICKY_CLASS
|
// HPROF_GC_ROOT_STICKY_CLASS
|
||||||
// These should be classes in the NULL class loader data, and not all classes
|
// These should be classes in the NULL class loader data, and not all classes
|
||||||
|
|
|
@ -43,7 +43,7 @@ import sun.jvm.hotspot.utilities.Observer;
|
||||||
public class JavaThread extends Thread {
|
public class JavaThread extends Thread {
|
||||||
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.JavaThread.DEBUG") != null;
|
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.JavaThread.DEBUG") != null;
|
||||||
|
|
||||||
private static sun.jvm.hotspot.types.OopField threadObjField;
|
private static long threadObjFieldOffset;
|
||||||
private static AddressField anchorField;
|
private static AddressField anchorField;
|
||||||
private static AddressField lastJavaSPField;
|
private static AddressField lastJavaSPField;
|
||||||
private static AddressField lastJavaPCField;
|
private static AddressField lastJavaPCField;
|
||||||
|
@ -85,7 +85,8 @@ public class JavaThread extends Thread {
|
||||||
Type type = db.lookupType("JavaThread");
|
Type type = db.lookupType("JavaThread");
|
||||||
Type anchorType = db.lookupType("JavaFrameAnchor");
|
Type anchorType = db.lookupType("JavaFrameAnchor");
|
||||||
|
|
||||||
threadObjField = type.getOopField("_threadObj");
|
threadObjFieldOffset = type.getField("_threadObj").getOffset();
|
||||||
|
|
||||||
anchorField = type.getAddressField("_anchor");
|
anchorField = type.getAddressField("_anchor");
|
||||||
lastJavaSPField = anchorType.getAddressField("_last_Java_sp");
|
lastJavaSPField = anchorType.getAddressField("_last_Java_sp");
|
||||||
lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
|
lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
|
||||||
|
@ -347,7 +348,9 @@ public class JavaThread extends Thread {
|
||||||
public Oop getThreadObj() {
|
public Oop getThreadObj() {
|
||||||
Oop obj = null;
|
Oop obj = null;
|
||||||
try {
|
try {
|
||||||
obj = VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr));
|
Address addr = getAddress().addOffsetTo(threadObjFieldOffset);
|
||||||
|
VMOopHandle vmOopHandle = VMObjectFactory.newObject(VMOopHandle.class, addr);
|
||||||
|
obj = vmOopHandle.resolve();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,7 +375,19 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess {
|
||||||
public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer");
|
public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer");
|
||||||
public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor");
|
public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor");
|
||||||
public final int javaThreadShouldPostOnExceptionsFlagOffset = getFieldOffset("JavaThread::_should_post_on_exceptions_flag", Integer.class, "int", Integer.MIN_VALUE, JVMCI || JDK >= 12);
|
public final int javaThreadShouldPostOnExceptionsFlagOffset = getFieldOffset("JavaThread::_should_post_on_exceptions_flag", Integer.class, "int", Integer.MIN_VALUE, JVMCI || JDK >= 12);
|
||||||
public final int threadObjectOffset = getFieldOffset("JavaThread::_threadObj", Integer.class, "oop");
|
|
||||||
|
public final boolean threadObjectFieldIsHandle;
|
||||||
|
public final int threadObjectOffset;
|
||||||
|
{
|
||||||
|
if (JDK <= 15) {
|
||||||
|
threadObjectFieldIsHandle = false;
|
||||||
|
threadObjectOffset = getFieldOffset("JavaThread::_threadObj", Integer.class, "oop");
|
||||||
|
} else {
|
||||||
|
threadObjectFieldIsHandle = true;
|
||||||
|
threadObjectOffset = getFieldOffset("JavaThread::_threadObj", Integer.class, "OopHandle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final int osThreadOffset = getFieldOffset("JavaThread::_osthread", Integer.class, "OSThread*");
|
public final int osThreadOffset = getFieldOffset("JavaThread::_osthread", Integer.class, "OSThread*");
|
||||||
public final int threadIsMethodHandleReturnOffset = getFieldOffset("JavaThread::_is_method_handle_return", Integer.class, "int");
|
public final int threadIsMethodHandleReturnOffset = getFieldOffset("JavaThread::_is_method_handle_return", Integer.class, "int");
|
||||||
public final int threadObjectResultOffset = getFieldOffset("JavaThread::_vm_result", Integer.class, "oop");
|
public final int threadObjectResultOffset = getFieldOffset("JavaThread::_vm_result", Integer.class, "oop");
|
||||||
|
|
|
@ -30,6 +30,7 @@ import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK;
|
||||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS;
|
import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS;
|
||||||
import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
|
import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
|
||||||
|
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_HANDLE_LOCATION;
|
||||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION;
|
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION;
|
||||||
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
|
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
|
||||||
|
|
||||||
|
@ -427,12 +428,21 @@ public class HotSpotGraphBuilderPlugins {
|
||||||
AddressNode address = b.add(new OffsetAddressNode(thread, offset));
|
AddressNode address = b.add(new OffsetAddressNode(thread, offset));
|
||||||
// JavaThread::_threadObj is never compressed
|
// JavaThread::_threadObj is never compressed
|
||||||
ObjectStamp stamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), metaAccess.lookupJavaType(Thread.class)));
|
ObjectStamp stamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), metaAccess.lookupJavaType(Thread.class)));
|
||||||
b.addPush(JavaKind.Object, new ReadNode(address, JAVA_THREAD_THREAD_OBJECT_LOCATION, stamp, BarrierType.NONE));
|
ReadNode value = b.add(new ReadNode(address, JAVA_THREAD_THREAD_OBJECT_LOCATION,
|
||||||
|
config.threadObjectFieldIsHandle ? StampFactory.forKind(wordTypes.getWordKind()) : stamp, BarrierType.NONE));
|
||||||
|
if (config.threadObjectFieldIsHandle) {
|
||||||
|
ValueNode handleOffset = ConstantNode.forIntegerKind(wordTypes.getWordKind(), 0, b.getGraph());
|
||||||
|
AddressNode handleAddress = b.add(new OffsetAddressNode(value, handleOffset));
|
||||||
|
value = b.add(new ReadNode(handleAddress, JAVA_THREAD_THREAD_OBJECT_HANDLE_LOCATION, stamp, BarrierType.NONE));
|
||||||
|
}
|
||||||
|
b.push(JavaKind.Object, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.osThreadInterruptedOffset != Integer.MAX_VALUE) {
|
if (config.osThreadInterruptedOffset != Integer.MAX_VALUE) {
|
||||||
|
// This substitution is no longer in use when threadObj is a handle
|
||||||
|
assert !config.threadObjectFieldIsHandle;
|
||||||
r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class);
|
r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,8 @@ public class HotSpotReplacementsUtil {
|
||||||
*/
|
*/
|
||||||
public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.immutable("JavaThread::_threadObj");
|
public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.immutable("JavaThread::_threadObj");
|
||||||
|
|
||||||
|
public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_HANDLE_LOCATION = NamedLocationIdentity.immutable("JavaThread::_threadObj handle");
|
||||||
|
|
||||||
@Fold
|
@Fold
|
||||||
public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) {
|
public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) {
|
||||||
return config.threadObjectOffset;
|
return config.threadObjectOffset;
|
||||||
|
|
|
@ -121,7 +121,6 @@ public class TestGCLogMessages {
|
||||||
new LogMessageWithLevel("LAB Undo Waste", Level.DEBUG),
|
new LogMessageWithLevel("LAB Undo Waste", Level.DEBUG),
|
||||||
// Ext Root Scan
|
// Ext Root Scan
|
||||||
new LogMessageWithLevel("Thread Roots", Level.TRACE),
|
new LogMessageWithLevel("Thread Roots", Level.TRACE),
|
||||||
new LogMessageWithLevel("Universe Roots", Level.TRACE),
|
|
||||||
new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE),
|
new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE),
|
||||||
new LogMessageWithLevel("CLDG Roots", Level.TRACE),
|
new LogMessageWithLevel("CLDG Roots", Level.TRACE),
|
||||||
new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE),
|
new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE),
|
||||||
|
|
|
@ -91,10 +91,10 @@ public class TestG1ParallelPhases {
|
||||||
Set<String> allPhases = of(
|
Set<String> allPhases = of(
|
||||||
"ExtRootScan",
|
"ExtRootScan",
|
||||||
"ThreadRoots",
|
"ThreadRoots",
|
||||||
"UniverseRoots",
|
|
||||||
"ObjectSynchronizerRoots",
|
"ObjectSynchronizerRoots",
|
||||||
"VM Global",
|
"VM Global",
|
||||||
"JNI Global",
|
"JNI Global",
|
||||||
|
"Thread OopStorage",
|
||||||
"CLDGRoots",
|
"CLDGRoots",
|
||||||
"CMRefRoots",
|
"CMRefRoots",
|
||||||
"MergeER",
|
"MergeER",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue