Avoid race on Thread::tlsPtr_::top_handle_scope.
Require mutator lock for that field and update tests to hold
the mutator lock when needed. This prevents GC thread that
executes a thread roots flip on behalf of suspended threads
from racing against construction or destruction of handle
scopes by those threads and possibly seeing invalid values.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 189439174
Change-Id: I268a0ef6e5aa838347956febca0d3b6e02fe3ae5
diff --git a/compiler/optimizing/instruction_simplifier_test.cc b/compiler/optimizing/instruction_simplifier_test.cc
index ac0bdb9..2063eed 100644
--- a/compiler/optimizing/instruction_simplifier_test.cc
+++ b/compiler/optimizing/instruction_simplifier_test.cc
@@ -127,7 +127,8 @@
// target_phi = PHI[param2, param3, obj2]
// return PredFieldGet[val_phi, target_phi] => PredFieldGet[val_phi, target_phi]
TEST_F(InstructionSimplifierTest, SimplifyPredicatedFieldGetNoMerge) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -219,7 +220,8 @@
// target_phi = PHI[param2, param3, obj2]
// return PredFieldGet[val_phi, target_phi] => PredFieldGet[3, target_phi]
TEST_F(InstructionSimplifierTest, SimplifyPredicatedFieldGetMerge) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -308,7 +310,8 @@
// target_phi = PHI[obj1, obj2]
// return PredFieldGet[val_phi, target_phi] => FieldGet[target_phi]
TEST_F(InstructionSimplifierTest, SimplifyPredicatedFieldGetNoNull) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -394,7 +397,8 @@
// EXIT
// return obj.field
TEST_P(InstanceOfInstructionSimplifierTestGroup, ExactClassInstanceOfOther) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
InitGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
@@ -483,7 +487,8 @@
// EXIT
// return obj
TEST_P(InstanceOfInstructionSimplifierTestGroup, ExactClassCheckCastOther) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
InitGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", {{"entry", "exit"}}));
diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc
index 67abc0f..cebc3f3 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -1265,7 +1265,8 @@
// // EXIT
// obj.field;
TEST_F(LoadStoreAnalysisTest, PartialEscape5) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList(
"entry",
diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc
index 1424652..812a32a 100644
--- a/compiler/optimizing/load_store_elimination_test.cc
+++ b/compiler/optimizing/load_store_elimination_test.cc
@@ -1233,7 +1233,8 @@
// return t;
// }
TEST_F(LoadStoreEliminationTest, ArrayLoopOverlap) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blocks(graph_,
GetAllocator(),
@@ -1361,7 +1362,8 @@
// return t;
// }
TEST_F(LoadStoreEliminationTest, ArrayLoopOverlap2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blocks(graph_,
GetAllocator(),
@@ -1500,7 +1502,8 @@
}
TEST_F(LoadStoreEliminationTest, ArrayNonLoopPhi) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blocks(graph_,
GetAllocator(),
@@ -1594,7 +1597,8 @@
}
TEST_F(LoadStoreEliminationTest, ArrayMergeDefault) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blocks(graph_,
GetAllocator(),
@@ -1685,7 +1689,8 @@
// array location with index `idx + constant`. This could have led to
// replacing the load with, for example, the default value 0.
TEST_F(LoadStoreEliminationTest, ArrayLoopAliasing1) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blocks(graph_,
GetAllocator(),
@@ -1778,7 +1783,8 @@
// loop unrolling. This gtest does not need to jump through those hoops
// as we do not unnecessarily run those optimization passes.
TEST_F(LoadStoreEliminationTest, ArrayLoopAliasing2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blocks(graph_,
GetAllocator(),
@@ -2043,7 +2049,8 @@
// EXIT
// return PHI(foo_l, foo_r)
TEST_F(LoadStoreEliminationTest, PartialLoadElimination) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit_REAL",
@@ -2119,7 +2126,8 @@
// return obj.field
// This test runs with partial LSE disabled.
TEST_F(LoadStoreEliminationTest, PartialLoadPreserved) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit_REAL",
@@ -2190,7 +2198,8 @@
// return obj.field
// NB This test is for non-partial LSE flow. Normally the obj.field writes will be removed
TEST_F(LoadStoreEliminationTest, PartialLoadPreserved2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit_REAL",
@@ -2278,7 +2287,8 @@
// ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoadElimination2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -2386,7 +2396,8 @@
// // first = phi[out.foo, 13]
// return first + new_inst.foo;
TEST_F(LoadStoreEliminationTest, PartialPhiPropagation) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -2545,7 +2556,8 @@
// return select(param3, obj1.foo, obj2.foo);
// EXIT
TEST_P(OrderDependentTestGroup, PredicatedUse) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -2712,7 +2724,8 @@
// return obj1.foo + obj2.foo;
// EXIT
TEST_P(OrderDependentTestGroup, PredicatedEnvUse) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -2860,7 +2873,8 @@
// predicated-ELIMINATE
// return obj1.field + obj2.field
TEST_P(OrderDependentTestGroup, FieldSetOrderEnv) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -3031,7 +3045,8 @@
// // EXIT
// return;
TEST_P(OrderDependentTestGroup, MaterializationMovedUse) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -3141,7 +3156,8 @@
// } else {}
// EXIT
TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -3226,7 +3242,8 @@
// noescape();
// return a + b + c
TEST_F(LoadStoreEliminationTest, MutiPartialLoadStore) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -3385,7 +3402,8 @@
// EXIT
// return a + b + c + obj.foo
TEST_F(LoadStoreEliminationTest, MutiPartialLoadStore2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
// Need to have an actual entry block since we check env-layout and the way we
// add constants would screw this up otherwise.
@@ -3552,7 +3570,8 @@
// }
// EXIT
TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -3663,7 +3682,8 @@
// return obj.a;
// EXIT
TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -3781,7 +3801,8 @@
// return obj.a;
// EXIT
TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
// Break the critical edge between entry and set_two with the
// set_two_critical_break node. Graph simplification would do this for us if
@@ -3913,7 +3934,8 @@
// return obj.a;
// EXIT
TEST_F(LoadStoreEliminationTest, MovePredicatedAlloc5) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
// Break the critical edge between entry and set_two with the
// set_two_critical_break node. Graph simplification would do this for us if
@@ -4044,7 +4066,8 @@
// }
// EXIT
TEST_F(LoadStoreEliminationTest, PartialLoadElimination3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList(
"entry",
@@ -4121,7 +4144,8 @@
// }
// EXIT
TEST_F(LoadStoreEliminationTest, PartialLoadElimination4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4223,7 +4247,8 @@
// ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoadElimination5) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4306,7 +4331,8 @@
// ELIMINATE
// return obj.fid
TEST_F(LoadStoreEliminationTest, PartialLoadElimination6) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4398,7 +4424,8 @@
// return obj.field;
// EXIT
TEST_F(LoadStoreEliminationTest, PartialLoadPreserved3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4506,7 +4533,8 @@
// return obj.field;
// EXIT
TEST_F(LoadStoreEliminationTest, PartialLoadPreserved4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4611,7 +4639,8 @@
// ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoadPreserved5) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4789,7 +4818,8 @@
// PREDICATED GET
// return obj.field
TEST_P(PartialComparisonTestGroup, PartialComparisonBeforeCohort) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -4917,7 +4947,8 @@
// PREDICATED GET
// return obj.field
TEST_P(PartialComparisonTestGroup, PartialComparisonInCohortBeforeEscape) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5046,7 +5077,8 @@
// PREDICATED GET
// return obj.field
TEST_P(PartialComparisonTestGroup, PartialComparisonAfterCohort) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5176,7 +5208,8 @@
// return obj.field
TEST_P(PartialComparisonTestGroup, PartialComparisonInCohortAfterEscape) {
PartialComparisonKind kind = GetParam();
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5335,7 +5368,8 @@
// predicated-ELIMINATE
// obj.field = 3;
TEST_F(LoadStoreEliminationTest, PredicatedStore1) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
InitGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5423,7 +5457,8 @@
// predicated-ELIMINATE
// obj.field = 4;
TEST_F(LoadStoreEliminationTest, PredicatedStore2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5534,7 +5569,8 @@
// predicated-ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PredicatedLoad1) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5635,7 +5671,8 @@
// predicated-ELIMINATE
// return obj1.field + obj2.field
TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad1) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5787,7 +5824,8 @@
// predicated-ELIMINATE
// return obj1.field + obj2.field
TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -5951,7 +5989,8 @@
// // allow us to entirely remove the allocation in this test.
// return obj.foo;
TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6081,7 +6120,8 @@
// predicated-ELIMINATE
// return obj.field + abc
TEST_F(LoadStoreEliminationTest, PredicatedLoad4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6221,7 +6261,8 @@
// // won't be changed. The escape happens with .BAR set so this is in escaping cohort.
// return read_bottom.foo;
TEST_F(LoadStoreEliminationTest, MultiPredicatedLoad4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6325,7 +6366,8 @@
// predicated-ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PredicatedLoad2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6462,7 +6504,8 @@
// predicated-ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PredicatedLoad3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6589,7 +6632,8 @@
// predicated-ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PredicatedLoadDefaultValue) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6685,7 +6729,8 @@
// // predicated-ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoopPhis1) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -6871,7 +6916,8 @@
// // predicated-ELIMINATE
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoopPhis2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7041,7 +7087,8 @@
// EXIT
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoopPhis3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7188,7 +7235,8 @@
// EXIT
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoopPhis4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7332,7 +7380,8 @@
// EXIT
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoopPhis5) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7490,7 +7539,8 @@
// }
// return obj.field
TEST_F(LoadStoreEliminationTest, PartialLoopPhis6) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(/*handles=*/&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7649,7 +7699,8 @@
// }
// return obj.field;
TEST_F(LoadStoreEliminationTest, SimplifyTest) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7740,7 +7791,8 @@
// }
// return obj.field;
TEST_F(LoadStoreEliminationTest, SimplifyTest2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7843,7 +7895,8 @@
// }
// return obj.field;
TEST_F(LoadStoreEliminationTest, SimplifyTest3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -7949,7 +8002,8 @@
// }
// return obj.field;
TEST_F(LoadStoreEliminationTest, SimplifyTest4) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -8061,7 +8115,8 @@
// }
// return obj.foo;
TEST_F(LoadStoreEliminationTest, PartialIrreducibleLoop) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("start",
"exit",
@@ -8229,7 +8284,8 @@
// b = obj.foo;
// return a + b;
TEST_P(UsesOrderDependentTestGroup, RecordPredicatedReplacements1) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -8393,7 +8449,8 @@
// b = obj.foo;
// return a + b;
TEST_P(UsesOrderDependentTestGroup, RecordPredicatedReplacements2) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
@@ -8566,7 +8623,8 @@
// b = obj.foo;
// return a + b + x;
TEST_P(UsesOrderDependentTestGroupForThreeItems, RecordPredicatedReplacements3) {
- VariableSizedHandleScope vshs(Thread::Current());
+ ScopedObjectAccess soa(Thread::Current());
+ VariableSizedHandleScope vshs(soa.Self());
CreateGraph(&vshs);
AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
"exit",
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index cb0333f..3aa9e52 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -44,26 +44,22 @@
}
template<size_t kNumReferences>
-inline FixedSizeHandleScope<kNumReferences>::FixedSizeHandleScope(BaseHandleScope* link)
- : HandleScope(link, kNumReferences) {
- static_assert(kNumReferences >= 1, "FixedSizeHandleScope must contain at least 1 reference");
- DCHECK_EQ(&storage_[0], GetReferences()); // TODO: Figure out how to use a compile assert.
- for (size_t i = 0; i < kNumReferences; ++i) {
- SetReferenceToNull(i);
- }
-}
-
-template<size_t kNumReferences>
inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self,
ObjPtr<mirror::Object> fill_value)
: FixedSizeHandleScope<kNumReferences>(self->GetTopHandleScope(), fill_value),
self_(self) {
DCHECK_EQ(self, Thread::Current());
+ if (kDebugLocking) {
+ Locks::mutator_lock_->AssertSharedHeld(self_);
+ }
self_->PushHandleScope(this);
}
template<size_t kNumReferences>
inline StackHandleScope<kNumReferences>::~StackHandleScope() {
+ if (kDebugLocking) {
+ Locks::mutator_lock_->AssertSharedHeld(self_);
+ }
BaseHandleScope* top_handle_scope = self_->PopHandleScope();
DCHECK_EQ(top_handle_scope, this);
}
@@ -161,12 +157,6 @@
GetReferences()[i].Assign(object);
}
-template<size_t kNumReferences>
-inline void FixedSizeHandleScope<kNumReferences>::SetReferenceToNull(size_t i) {
- DCHECK_LT(i, kNumReferences);
- GetReferences()[i].Assign(nullptr);
-}
-
// Number of references contained within this handle scope.
inline uint32_t BaseHandleScope::NumberOfReferences() const {
return LIKELY(!IsVariableSized())
@@ -227,10 +217,17 @@
self_(self),
current_scope_(&first_scope_),
first_scope_(/*link=*/ nullptr) {
+ DCHECK_EQ(self, Thread::Current());
+ if (kDebugLocking) {
+ Locks::mutator_lock_->AssertSharedHeld(self_);
+ }
self_->PushHandleScope(this);
}
inline VariableSizedHandleScope::~VariableSizedHandleScope() {
+ if (kDebugLocking) {
+ Locks::mutator_lock_->AssertSharedHeld(self_);
+ }
BaseHandleScope* top_handle_scope = self_->PopHandleScope();
DCHECK_EQ(top_handle_scope, this);
// Don't delete first_scope_ since it is not heap allocated.
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index ed77e19..58322d1 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -195,15 +195,10 @@
}
private:
- explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link);
explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link,
- ObjPtr<mirror::Object> fill_value)
+ ObjPtr<mirror::Object> fill_value = nullptr)
REQUIRES_SHARED(Locks::mutator_lock_);
-
- ALWAYS_INLINE ~FixedSizeHandleScope() {}
-
- // Helper to set references to null without any mutator-locks.
- ALWAYS_INLINE void SetReferenceToNull(size_t i);
+ ALWAYS_INLINE ~FixedSizeHandleScope() REQUIRES_SHARED(Locks::mutator_lock_) {}
template<class T>
ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -226,8 +221,10 @@
class PACKED(4) StackHandleScope final : public FixedSizeHandleScope<kNumReferences> {
public:
explicit ALWAYS_INLINE StackHandleScope(Thread* self,
- ObjPtr<mirror::Object> fill_value = nullptr);
- ALWAYS_INLINE ~StackHandleScope();
+ ObjPtr<mirror::Object> fill_value = nullptr)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ ALWAYS_INLINE ~StackHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);
Thread* Self() const {
return self_;
@@ -246,8 +243,8 @@
// list.
class VariableSizedHandleScope : public BaseHandleScope {
public:
- explicit VariableSizedHandleScope(Thread* const self);
- ~VariableSizedHandleScope();
+ explicit VariableSizedHandleScope(Thread* const self) REQUIRES_SHARED(Locks::mutator_lock_);
+ ~VariableSizedHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);
template<class T>
MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/thread.h b/runtime/thread.h
index bf8b00a..676bfd8 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -908,16 +908,16 @@
void HandleScopeVisitRoots(RootVisitor* visitor, uint32_t thread_id)
REQUIRES_SHARED(Locks::mutator_lock_);
- BaseHandleScope* GetTopHandleScope() {
+ BaseHandleScope* GetTopHandleScope() REQUIRES_SHARED(Locks::mutator_lock_) {
return tlsPtr_.top_handle_scope;
}
- void PushHandleScope(BaseHandleScope* handle_scope) {
+ void PushHandleScope(BaseHandleScope* handle_scope) REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK_EQ(handle_scope->GetLink(), tlsPtr_.top_handle_scope);
tlsPtr_.top_handle_scope = handle_scope;
}
- BaseHandleScope* PopHandleScope() {
+ BaseHandleScope* PopHandleScope() REQUIRES_SHARED(Locks::mutator_lock_) {
BaseHandleScope* handle_scope = tlsPtr_.top_handle_scope;
DCHECK(handle_scope != nullptr);
tlsPtr_.top_handle_scope = tlsPtr_.top_handle_scope->GetLink();