Revert "Improve ArraySet codegen."
This reverts commit 0ece86491008837a9814f7a2e0d7961c74ef4195.
Reason for revert: Breaks heap poisoning tests.
Bug: 32489401
Change-Id: Ied4150829eea848d0f967866d87c6aa7dafd39a1
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 9d3bdef..6469c69 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -6168,11 +6168,13 @@
bool needs_write_barrier =
CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
- bool needs_type_check = instruction->NeedsTypeCheck();
+ bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck();
LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
instruction,
- needs_type_check ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
+ may_need_runtime_call_for_type_check ?
+ LocationSummary::kCallOnSlowPath :
+ LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
@@ -6193,7 +6195,7 @@
vixl32::Register array = InputRegisterAt(instruction, 0);
Location index = locations->InAt(1);
DataType::Type value_type = instruction->GetComponentType();
- bool needs_type_check = instruction->NeedsTypeCheck();
+ bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck();
bool needs_write_barrier =
CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
uint32_t data_offset =
@@ -6245,7 +6247,8 @@
if (instruction->InputAt(2)->IsNullConstant()) {
// Just setting null.
if (index.IsConstant()) {
- size_t offset = (Int32ConstantFrom(index) << TIMES_4) + data_offset;
+ size_t offset =
+ (Int32ConstantFrom(index) << TIMES_4) + data_offset;
GetAssembler()->StoreToOffset(kStoreWord, value, array, offset);
} else {
DCHECK(index.IsRegister()) << index;
@@ -6258,7 +6261,7 @@
// store instruction.
codegen_->MaybeRecordImplicitNullCheck(instruction);
DCHECK(!needs_write_barrier);
- DCHECK(!needs_type_check);
+ DCHECK(!may_need_runtime_call_for_type_check);
break;
}
@@ -6267,21 +6270,36 @@
vixl32::Register temp1 = RegisterFrom(temp1_loc);
Location temp2_loc = locations->GetTemp(1);
vixl32::Register temp2 = RegisterFrom(temp2_loc);
+ uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
+ uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
+ uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
+ vixl32::Label done;
+ vixl32::Label* final_label = codegen_->GetFinalLabel(instruction, &done);
+ SlowPathCodeARMVIXL* slow_path = nullptr;
- bool can_value_be_null = instruction->GetValueCanBeNull();
- vixl32::Label do_store;
- if (can_value_be_null) {
- __ CompareAndBranchIfZero(value, &do_store, /* is_far_target= */ false);
- }
-
- if (needs_type_check) {
- SlowPathCodeARMVIXL* slow_path =
- new (codegen_->GetScopedAllocator()) ArraySetSlowPathARMVIXL(instruction);
+ if (may_need_runtime_call_for_type_check) {
+ slow_path = new (codegen_->GetScopedAllocator()) ArraySetSlowPathARMVIXL(instruction);
codegen_->AddSlowPath(slow_path);
-
- const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
- const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
- const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
+ if (instruction->GetValueCanBeNull()) {
+ vixl32::Label non_zero;
+ __ CompareAndBranchIfNonZero(value, &non_zero);
+ if (index.IsConstant()) {
+ size_t offset =
+ (Int32ConstantFrom(index) << TIMES_4) + data_offset;
+ GetAssembler()->StoreToOffset(kStoreWord, value, array, offset);
+ } else {
+ DCHECK(index.IsRegister()) << index;
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ vixl32::Register temp = temps.Acquire();
+ __ Add(temp, array, data_offset);
+ codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index));
+ }
+ // TODO(VIXL): Use a scope to ensure we record the pc info immediately after the preceding
+ // store instruction.
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
+ __ B(final_label);
+ __ Bind(&non_zero);
+ }
// Note that when read barriers are enabled, the type checks
// are performed without read barriers. This is fine, even in
@@ -6311,7 +6329,8 @@
__ Cmp(temp1, temp2);
if (instruction->StaticTypeOfArrayIsObjectArray()) {
- __ B(eq, slow_path->GetExitLabel(), /* is_far_target= */ false);
+ vixl32::Label do_put;
+ __ B(eq, &do_put, /* is_far_target= */ false);
// If heap poisoning is enabled, the `temp1` reference has
// not been unpoisoned yet; unpoison it now.
GetAssembler()->MaybeUnpoisonHeapReference(temp1);
@@ -6321,14 +6340,12 @@
// If heap poisoning is enabled, no need to unpoison
// `temp1`, as we are comparing against null below.
__ CompareAndBranchIfNonZero(temp1, slow_path->GetEntryLabel());
+ __ Bind(&do_put);
} else {
__ B(ne, slow_path->GetEntryLabel());
}
- __ Bind(slow_path->GetExitLabel());
}
- codegen_->MarkGCCard(temp1, temp2, array, value, /* can_be_null= */ false);
-
vixl32::Register source = value;
if (kPoisonHeapReferences) {
// Note that in the case where `value` is a null reference,
@@ -6340,13 +6357,9 @@
source = temp1;
}
- if (can_value_be_null) {
- DCHECK(do_store.IsReferenced());
- __ Bind(&do_store);
- }
-
if (index.IsConstant()) {
- size_t offset = (Int32ConstantFrom(index) << TIMES_4) + data_offset;
+ size_t offset =
+ (Int32ConstantFrom(index) << TIMES_4) + data_offset;
GetAssembler()->StoreToOffset(kStoreWord, source, array, offset);
} else {
DCHECK(index.IsRegister()) << index;
@@ -6360,12 +6373,22 @@
RegisterFrom(index));
}
- if (can_value_be_null || !needs_type_check) {
+ if (!may_need_runtime_call_for_type_check) {
// TODO(VIXL): Ensure we record the pc position immediately after the preceding store
// instruction.
codegen_->MaybeRecordImplicitNullCheck(instruction);
}
+ codegen_->MarkGCCard(temp1, temp2, array, value, instruction->GetValueCanBeNull());
+
+ if (done.IsReferenced()) {
+ __ Bind(&done);
+ }
+
+ if (slow_path != nullptr) {
+ __ Bind(slow_path->GetExitLabel());
+ }
+
break;
}