Bring Reference Type Propagation to Instance/StaticInstanceField
For this, we need the field index in FieldInfo, hence the add of the field.
Change-Id: Id219bd826d8496acf3981307a8c42e2eb6ddb712
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index c4f033d..edce948 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -824,13 +824,17 @@
value,
field_type,
resolved_field->GetOffset(),
- resolved_field->IsVolatile()));
+ resolved_field->IsVolatile(),
+ field_index,
+ *dex_file_));
} else {
current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
current_block_->GetLastInstruction(),
field_type,
resolved_field->GetOffset(),
- resolved_field->IsVolatile()));
+ resolved_field->IsVolatile(),
+ field_index,
+ *dex_file_));
UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
}
@@ -932,13 +936,20 @@
temps.Add(cls);
HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
DCHECK_EQ(value->GetType(), field_type);
- current_block_->AddInstruction(
- new (arena_) HStaticFieldSet(cls, value, field_type, resolved_field->GetOffset(),
- resolved_field->IsVolatile()));
+ current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
+ value,
+ field_type,
+ resolved_field->GetOffset(),
+ resolved_field->IsVolatile(),
+ field_index,
+ *dex_file_));
} else {
- current_block_->AddInstruction(
- new (arena_) HStaticFieldGet(cls, field_type, resolved_field->GetOffset(),
- resolved_field->IsVolatile()));
+ current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls,
+ field_type,
+ resolved_field->GetOffset(),
+ resolved_field->IsVolatile(),
+ field_index,
+ *dex_file_));
UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
}
return true;
diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc
index c3ce7e1..d8a09ff 100644
--- a/compiler/optimizing/gvn_test.cc
+++ b/compiler/optimizing/gvn_test.cc
@@ -40,23 +40,40 @@
graph->AddBlock(block);
entry->AddSuccessor(block);
- block->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
- MemberOffset(42), false));
- block->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
- MemberOffset(42), false));
+ block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
+ block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* to_remove = block->GetLastInstruction();
- block->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
- MemberOffset(43), false));
+ block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimNot,
+ MemberOffset(43),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* different_offset = block->GetLastInstruction();
// Kill the value.
- block->AddInstruction(new (&allocator) HInstanceFieldSet(
- parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false));
- block->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
- MemberOffset(42), false));
+ block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
+ parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
+ block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* use_after_kill = block->GetLastInstruction();
block->AddInstruction(new (&allocator) HExit());
@@ -88,9 +105,12 @@
HBasicBlock* block = new (&allocator) HBasicBlock(graph);
graph->AddBlock(block);
entry->AddSuccessor(block);
- block->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
HBasicBlock* then = new (&allocator) HBasicBlock(graph);
@@ -105,17 +125,26 @@
then->AddSuccessor(join);
else_->AddSuccessor(join);
- then->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
then->AddInstruction(new (&allocator) HGoto());
- else_->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
else_->AddInstruction(new (&allocator) HGoto());
- join->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
join->AddInstruction(new (&allocator) HExit());
graph->TryBuildingSsa();
@@ -144,9 +173,12 @@
HBasicBlock* block = new (&allocator) HBasicBlock(graph);
graph->AddBlock(block);
entry->AddSuccessor(block);
- block->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
block->AddInstruction(new (&allocator) HGoto());
HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
@@ -161,26 +193,40 @@
loop_header->AddSuccessor(exit);
loop_body->AddSuccessor(loop_header);
- loop_header->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
// Kill inside the loop body to prevent field gets inside the loop header
// and the body to be GVN'ed.
- loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(
- parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false));
+ loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
+ parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* field_set = loop_body->GetLastInstruction();
- loop_body->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
loop_body->AddInstruction(new (&allocator) HGoto());
- exit->AddInstruction(
- new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
- MemberOffset(42), false));
+ exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
HInstruction* field_get_in_exit = exit->GetLastInstruction();
exit->AddInstruction(new (&allocator) HExit());
@@ -266,8 +312,13 @@
// Check that the loops don't have side effects.
{
// Make one block with a side effect.
- entry->AddInstruction(new (&allocator) HInstanceFieldSet(
- parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false));
+ entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
+ parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()));
SideEffectsAnalysis side_effects(graph);
side_effects.Run();
@@ -280,8 +331,13 @@
// Check that the side effects of the outer loop does not affect the inner loop.
{
outer_loop_body->InsertInstructionBefore(
- new (&allocator) HInstanceFieldSet(
- parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false),
+ new (&allocator) HInstanceFieldSet(parameter,
+ parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()),
outer_loop_body->GetLastInstruction());
SideEffectsAnalysis side_effects(graph);
@@ -297,8 +353,13 @@
{
outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
inner_loop_body->InsertInstructionBefore(
- new (&allocator) HInstanceFieldSet(
- parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false),
+ new (&allocator) HInstanceFieldSet(parameter,
+ parameter,
+ Primitive::kPrimNot,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile()),
inner_loop_body->GetLastInstruction());
SideEffectsAnalysis side_effects(graph);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index a44d745..d9d09aa 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -60,6 +60,8 @@
static constexpr uint32_t kMaxIntShiftValue = 0x1f;
static constexpr uint64_t kMaxLongShiftValue = 0x3f;
+static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
+
static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
enum IfCondition {
@@ -3140,17 +3142,29 @@
class FieldInfo : public ValueObject {
public:
- FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile)
- : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {}
+ FieldInfo(MemberOffset field_offset,
+ Primitive::Type field_type,
+ bool is_volatile,
+ uint32_t index,
+ const DexFile& dex_file)
+ : field_offset_(field_offset),
+ field_type_(field_type),
+ is_volatile_(is_volatile),
+ index_(index),
+ dex_file_(dex_file) {}
MemberOffset GetFieldOffset() const { return field_offset_; }
Primitive::Type GetFieldType() const { return field_type_; }
+ uint32_t GetFieldIndex() const { return index_; }
+ const DexFile& GetDexFile() const { return dex_file_; }
bool IsVolatile() const { return is_volatile_; }
private:
const MemberOffset field_offset_;
const Primitive::Type field_type_;
const bool is_volatile_;
+ uint32_t index_;
+ const DexFile& dex_file_;
};
class HInstanceFieldGet : public HExpression<1> {
@@ -3158,9 +3172,11 @@
HInstanceFieldGet(HInstruction* value,
Primitive::Type field_type,
MemberOffset field_offset,
- bool is_volatile)
+ bool is_volatile,
+ uint32_t field_idx,
+ const DexFile& dex_file)
: HExpression(field_type, SideEffects::DependsOnSomething()),
- field_info_(field_offset, field_type, is_volatile) {
+ field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
SetRawInputAt(0, value);
}
@@ -3198,9 +3214,11 @@
HInstruction* value,
Primitive::Type field_type,
MemberOffset field_offset,
- bool is_volatile)
+ bool is_volatile,
+ uint32_t field_idx,
+ const DexFile& dex_file)
: HTemplateInstruction(SideEffects::ChangesSomething()),
- field_info_(field_offset, field_type, is_volatile),
+ field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
value_can_be_null_(true) {
SetRawInputAt(0, object);
SetRawInputAt(1, value);
@@ -3591,9 +3609,11 @@
HStaticFieldGet(HInstruction* cls,
Primitive::Type field_type,
MemberOffset field_offset,
- bool is_volatile)
+ bool is_volatile,
+ uint32_t field_idx,
+ const DexFile& dex_file)
: HExpression(field_type, SideEffects::DependsOnSomething()),
- field_info_(field_offset, field_type, is_volatile) {
+ field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
SetRawInputAt(0, cls);
}
@@ -3628,9 +3648,11 @@
HInstruction* value,
Primitive::Type field_type,
MemberOffset field_offset,
- bool is_volatile)
+ bool is_volatile,
+ uint32_t field_idx,
+ const DexFile& dex_file)
: HTemplateInstruction(SideEffects::ChangesSomething()),
- field_info_(field_offset, field_type, is_volatile),
+ field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
value_can_be_null_(true) {
SetRawInputAt(0, cls);
SetRawInputAt(1, value);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 91b2e6f..f7d2ed1 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -35,17 +35,22 @@
void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
// TODO: handle other instructions that give type info
- // (Call/Field accesses/array accesses)
+ // (Call/array accesses)
// Initialize exact types first for faster convergence.
for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* instr = it.Current();
+ // TODO: Make ReferenceTypePropagation a visitor or create a new one.
if (instr->IsNewInstance()) {
VisitNewInstance(instr->AsNewInstance());
} else if (instr->IsLoadClass()) {
VisitLoadClass(instr->AsLoadClass());
} else if (instr->IsNewArray()) {
VisitNewArray(instr->AsNewArray());
+ } else if (instr->IsInstanceFieldGet()) {
+ VisitInstanceFieldGet(instr->AsInstanceFieldGet());
+ } else if (instr->IsStaticFieldGet()) {
+ VisitStaticFieldGet(instr->AsStaticFieldGet());
}
}
@@ -161,6 +166,14 @@
}
}
+void ReferenceTypePropagation::SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass) {
+ if (klass != nullptr) {
+ ScopedObjectAccess soa(Thread::Current());
+ MutableHandle<mirror::Class> handle = handles_->NewHandle(klass);
+ instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true));
+ }
+}
+
void ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr,
uint16_t type_idx,
const DexFile& dex_file) {
@@ -169,11 +182,7 @@
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
// Get type from dex cache assuming it was populated by the verifier.
- mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
- if (resolved_class != nullptr) {
- MutableHandle<mirror::Class> handle = handles_->NewHandle(resolved_class);
- instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true));
- }
+ SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx));
}
void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
@@ -184,6 +193,30 @@
UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
}
+void ReferenceTypePropagation::UpdateFieldAccessTypeInfo(HInstruction* instr,
+ const FieldInfo& info) {
+ // The field index is unknown only during tests.
+ if (instr->GetType() != Primitive::kPrimNot || info.GetFieldIndex() == kUnknownFieldIndex) {
+ return;
+ }
+
+ ScopedObjectAccess soa(Thread::Current());
+ ClassLinker* cl = Runtime::Current()->GetClassLinker();
+ mirror::DexCache* dex_cache = cl->FindDexCache(info.GetDexFile());
+ ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), dex_cache);
+ DCHECK(field != nullptr);
+ mirror::Class* klass = field->GetType<false>();
+ SetClassAsTypeInfo(instr, klass);
+}
+
+void ReferenceTypePropagation::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
+ UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
+}
+
+void ReferenceTypePropagation::VisitStaticFieldGet(HStaticFieldGet* instr) {
+ UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
+}
+
void ReferenceTypePropagation::VisitLoadClass(HLoadClass* instr) {
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache =
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index 12c3362..74e425f 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -45,6 +45,8 @@
void VisitNewArray(HNewArray* instr);
void VisitPhi(HPhi* phi);
void VisitBasicBlock(HBasicBlock* block);
+ void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
+ void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass);
void UpdateBoundType(HBoundType* bound_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void UpdatePhi(HPhi* phi) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -52,6 +54,8 @@
void BoundTypeForIfNotNull(HBasicBlock* block);
void BoundTypeForIfInstanceOf(HBasicBlock* block);
void UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, const DexFile& dex_file);
+ void VisitInstanceFieldGet(HInstanceFieldGet* instr);
+ void VisitStaticFieldGet(HStaticFieldGet* instr);
void ProcessWorklist();
void AddToWorklist(HInstruction* instr);
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index b72ffb8..d07a14a 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -474,8 +474,12 @@
graph->AddBlock(block);
entry->AddSuccessor(block);
- HInstruction* test = new (allocator) HInstanceFieldGet(
- parameter, Primitive::kPrimBoolean, MemberOffset(22), false);
+ HInstruction* test = new (allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimBoolean,
+ MemberOffset(22),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile());
block->AddInstruction(test);
block->AddInstruction(new (allocator) HIf(test));
HBasicBlock* then = new (allocator) HBasicBlock(graph);
@@ -494,10 +498,18 @@
*phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt);
join->AddPhi(*phi);
- *input1 = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt,
- MemberOffset(42), false);
- *input2 = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt,
- MemberOffset(42), false);
+ *input1 = new (allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimInt,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile());
+*input2 = new (allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimInt,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile());
then->AddInstruction(*input1);
else_->AddInstruction(*input2);
join->AddInstruction(new (allocator) HExit());
@@ -604,8 +616,12 @@
graph->AddBlock(block);
entry->AddSuccessor(block);
- *field = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt,
- MemberOffset(42), false);
+ *field = new (allocator) HInstanceFieldGet(parameter,
+ Primitive::kPrimInt,
+ MemberOffset(42),
+ false,
+ kUnknownFieldIndex,
+ graph->GetDexFile());
block->AddInstruction(*field);
*ret = new (allocator) HReturn(*field);
block->AddInstruction(*ret);