summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2021-01-22 06:58:44 -0800
committer Alex Light <allight@google.com> 2021-01-22 07:15:21 -0800
commitc6da1be58086e873c9695f8c4c1a3a8ca718696e (patch)
tree1d445a789a52b537a349aab00ca5fed761cad273 /compiler
parentb171bc4b117e0d8d399f7a71a95ca5ec6cff19ca (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.cc4
-rw-r--r--compiler/optimizing/load_store_elimination_test.cc80
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, &current_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];