diff options
author | 2021-01-22 06:58:44 -0800 | |
---|---|---|
committer | 2021-01-22 07:15:21 -0800 | |
commit | c6da1be58086e873c9695f8c4c1a3a8ca718696e (patch) | |
tree | 1d445a789a52b537a349aab00ca5fed761cad273 /compiler | |
parent | b171bc4b117e0d8d399f7a71a95ca5ec6cff19ca (diff) |
Enable LSE of shadow$_monitor_ field
The shadow$_monitor_ field is an object header field. Unlike
shadow_klass this field has regular default initialization and we
should record this in LSE. This won't have any actual effect generally
since the only (java) use of the field is in Object.identityHashCode
and the object always escapes if the value is 0. Still this simplifies
partial LSE since we will not need to special case this field.
Test: ./test.py --host
Bug: 67037140
Change-Id: I68a8e4a4d84d42cd206e0dce37cefb19fd099b20
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 4 | ||||
-rw-r--r-- | compiler/optimizing/load_store_elimination_test.cc | 80 |
2 files changed, 83 insertions, 1 deletions
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index 8eeb6af65c..2e0f2b12d5 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -967,8 +967,10 @@ class LSEVisitor final : private HGraphDelegateVisitor { heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo()->GetReference(); size_t offset = heap_location_collector_.GetHeapLocation(i)->GetOffset(); if (ref == new_instance) { - if (offset >= mirror::kObjectHeaderSize) { + if (offset >= mirror::kObjectHeaderSize || + MemberOffset(offset) == mirror::Object::MonitorOffset()) { // Instance fields except the header fields are set to default heap values. + // The shadow$_monitor_ field is set to the default value however. heap_values[i].value = Value::Default(); heap_values[i].stored_by = Value::PureUnknown(); } else if (MemberOffset(offset) == mirror::Object::ClassOffset()) { diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc index fe55974635..9904192501 100644 --- a/compiler/optimizing/load_store_elimination_test.cc +++ b/compiler/optimizing/load_store_elimination_test.cc @@ -991,6 +991,86 @@ TEST_F(LoadStoreEliminationTest, DefaultShadowClass) { EXPECT_EQ(cls, return_val->InputAt(0)); } +// Object o = new Obj(); +// // Needed because otherwise we short-circuit LSA since GVN would get almost +// // everything other than this. Also since this isn't expected to be a very +// // common pattern (only a single java function, Object.identityHashCode, +// // ever reads this field) it's not worth changing the LSA logic. +// o.foo = 3; +// return o.shadow$_monitor_; +TEST_F(LoadStoreEliminationTest, DefaultShadowMonitor) { + CreateGraph(); + AdjacencyListGraph blocks( + graph_, GetAllocator(), "entry", "exit", {{"entry", "main"}, {"main", "exit"}}); +#define GET_BLOCK(name) HBasicBlock* name = blocks.Get(#name) + GET_BLOCK(entry); + GET_BLOCK(main); + GET_BLOCK(exit); +#undef GET_BLOCK + + HInstruction* suspend_check = new (GetAllocator()) HSuspendCheck(); + entry->AddInstruction(suspend_check); + entry->AddInstruction(new (GetAllocator()) HGoto()); + ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction)); + ManuallyBuildEnvFor(suspend_check, ¤t_locals); + + HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(), + dex::TypeIndex(10), + graph_->GetDexFile(), + ScopedNullHandle<mirror::Class>(), + false, + 0, + false); + HInstruction* new_inst = + new (GetAllocator()) HNewInstance(cls, + 0, + dex::TypeIndex(10), + graph_->GetDexFile(), + false, + QuickEntrypointEnum::kQuickAllocObjectInitialized); + HInstruction* const_fence = new (GetAllocator()) HConstructorFence(new_inst, 0, GetAllocator()); + HInstruction* set_field = new (GetAllocator()) HInstanceFieldSet(new_inst, + graph_->GetIntConstant(33), + nullptr, + DataType::Type::kReference, + MemberOffset(32), + false, + 0, + 0, + graph_->GetDexFile(), + 0); + HInstruction* get_field = new (GetAllocator()) HInstanceFieldGet(new_inst, + nullptr, + DataType::Type::kInt32, + mirror::Object::MonitorOffset(), + false, + 0, + 0, + graph_->GetDexFile(), + 0); + HInstruction* return_val = new (GetAllocator()) HReturn(get_field); + main->AddInstruction(cls); + main->AddInstruction(new_inst); + main->AddInstruction(const_fence); + main->AddInstruction(set_field); + main->AddInstruction(get_field); + main->AddInstruction(return_val); + cls->CopyEnvironmentFrom(suspend_check->GetEnvironment()); + new_inst->CopyEnvironmentFrom(suspend_check->GetEnvironment()); + + exit->AddInstruction(new (GetAllocator()) HExit()); + + graph_->ClearDominanceInformation(); + PerformLSE(); + + EXPECT_TRUE(IsRemoved(new_inst)); + EXPECT_TRUE(IsRemoved(const_fence)); + EXPECT_TRUE(IsRemoved(get_field)); + EXPECT_TRUE(IsRemoved(set_field)); + EXPECT_FALSE(IsRemoved(cls)); + EXPECT_EQ(graph_->GetIntConstant(0), return_val->InputAt(0)); +} + // void DO_CAL() { // int i = 1; // int[] w = new int[80]; |