Change iftable to never be null
Simplifies code generation by removing a null check. The null case
is rare.
Ritzperf code size: 13107624 -> 13095336
Also addressed comments from previous CL.
Bug: 32577579
Test: test-art-host, run ritzperf both with CC
Change-Id: I2b31e800867112869d7f0643e16c08826296979e
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c6363d1..7c3a2c6 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -6490,12 +6490,9 @@
iftable_offset,
maybe_temp2_loc,
kWithoutReadBarrier);
- // Null iftable means it is empty and will always fail the check.
- __ CompareAndBranchIfZero(temp, type_check_slow_path->GetEntryLabel());
-
- // Loop through the iftable and check if any class matches.
+ // Iftable is never null.
__ ldr(maybe_temp2_loc.AsRegister<Register>(), Address(temp, array_length_offset));
-
+ // Loop through the iftable and check if any class matches.
Label start_loop;
__ Bind(&start_loop);
__ CompareAndBranchIfZero(maybe_temp2_loc.AsRegister<Register>(),
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 4ab6065..6ec9c91 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -3802,12 +3802,9 @@
iftable_offset,
maybe_temp2_loc,
kWithoutReadBarrier);
- // Null iftable means it is empty and will always fail the check.
- __ Cbz(temp, type_check_slow_path->GetEntryLabel());
-
- // Loop through the iftable and check if any class matches.
+ // Iftable is never null.
__ Ldr(WRegisterFrom(maybe_temp2_loc), HeapOperand(temp.W(), array_length_offset));
-
+ // Loop through the iftable and check if any class matches.
vixl::aarch64::Label start_loop;
__ Bind(&start_loop);
__ Cbz(WRegisterFrom(maybe_temp2_loc), type_check_slow_path->GetEntryLabel());
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index e9827e8..c3ea3c7 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -5156,11 +5156,14 @@
__ Cbz(obj, &zero);
}
- // /* HeapReference<Class> */ out = obj->klass_
- GenerateReferenceLoadTwoRegisters(instruction, out_loc, obj_loc, class_offset, maybe_temp_loc);
-
switch (type_check_kind) {
case TypeCheckKind::kExactCheck: {
+ // /* HeapReference<Class> */ out = obj->klass_
+ GenerateReferenceLoadTwoRegisters(instruction,
+ out_loc,
+ obj_loc,
+ class_offset,
+ maybe_temp_loc);
__ Cmp(out, cls);
// Classes must be equal for the instanceof to succeed.
__ B(ne, &zero);
@@ -5170,6 +5173,12 @@
}
case TypeCheckKind::kAbstractClassCheck: {
+ // /* HeapReference<Class> */ out = obj->klass_
+ GenerateReferenceLoadTwoRegisters(instruction,
+ out_loc,
+ obj_loc,
+ class_offset,
+ maybe_temp_loc);
// If the class is abstract, we eagerly fetch the super class of the
// object to avoid doing a comparison we know will fail.
vixl32::Label loop;
@@ -5188,6 +5197,12 @@
}
case TypeCheckKind::kClassHierarchyCheck: {
+ // /* HeapReference<Class> */ out = obj->klass_
+ GenerateReferenceLoadTwoRegisters(instruction,
+ out_loc,
+ obj_loc,
+ class_offset,
+ maybe_temp_loc);
// Walk over the class hierarchy to find a match.
vixl32::Label loop, success;
__ Bind(&loop);
@@ -5207,6 +5222,12 @@
}
case TypeCheckKind::kArrayObjectCheck: {
+ // /* HeapReference<Class> */ out = obj->klass_
+ GenerateReferenceLoadTwoRegisters(instruction,
+ out_loc,
+ obj_loc,
+ class_offset,
+ maybe_temp_loc);
// Do an exact check.
vixl32::Label exact_check;
__ Cmp(out, cls);
@@ -5226,6 +5247,12 @@
}
case TypeCheckKind::kArrayCheck: {
+ // /* HeapReference<Class> */ out = obj->klass_
+ GenerateReferenceLoadTwoRegisters(instruction,
+ out_loc,
+ obj_loc,
+ class_offset,
+ maybe_temp_loc);
__ Cmp(out, cls);
DCHECK(locations->OnlyCallsOnSlowPath());
slow_path = new (GetGraph()->GetArena()) TypeCheckSlowPathARMVIXL(instruction,
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 2451b8d..7e4ad26 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -6849,24 +6849,24 @@
temp_loc,
iftable_offset,
kWithoutReadBarrier);
- // Null iftable means it is empty.
- __ testl(temp, temp);
- __ j(kZero, type_check_slow_path->GetEntryLabel());
-
- // Loop through the iftable and check if any class matches.
+ // Iftable is never null.
__ movl(maybe_temp2_loc.AsRegister<Register>(), Address(temp, array_length_offset));
-
+ // Loop through the iftable and check if any class matches.
NearLabel start_loop;
__ Bind(&start_loop);
- __ cmpl(cls.AsRegister<Register>(), Address(temp, object_array_data_offset));
- __ j(kEqual, &done); // Return if same class.
- // Go to next interface.
- __ addl(temp, Immediate(2 * kHeapReferenceSize));
+ // Need to subtract first to handle the empty array case.
__ subl(maybe_temp2_loc.AsRegister<Register>(), Immediate(2));
- __ j(kNotZero, &start_loop);
+ __ j(kNegative, type_check_slow_path->GetEntryLabel());
+ // Go to next interface if the classes do not match.
+ __ cmpl(cls.AsRegister<Register>(),
+ CodeGeneratorX86::ArrayAddress(temp,
+ maybe_temp2_loc,
+ TIMES_4,
+ object_array_data_offset));
+ __ j(kNotEqual, &start_loop);
+ } else {
+ __ jmp(type_check_slow_path->GetEntryLabel());
}
-
- __ jmp(type_check_slow_path->GetEntryLabel());
break;
}
}
@@ -7562,7 +7562,7 @@
// The value to patch is the distance from the offset in the constant area
// from the address computed by the HX86ComputeBaseMethodAddress instruction.
int32_t constant_offset = codegen_->ConstantAreaStart() + offset_into_constant_area_;
- int32_t relative_position = constant_offset - codegen_->GetMethodAddressOffset();;
+ int32_t relative_position = constant_offset - codegen_->GetMethodAddressOffset();
// Patch in the right value.
region.StoreUnaligned<int32_t>(pos - 4, relative_position);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 2425a4c..19b3019 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -6259,23 +6259,24 @@
temp_loc,
iftable_offset,
kWithoutReadBarrier);
- // Null iftable means it is empty.
- __ testl(temp, temp);
- __ j(kZero, type_check_slow_path->GetEntryLabel());
-
- // Loop through the iftable and check if any class matches.
+ // Iftable is never null.
__ movl(maybe_temp2_loc.AsRegister<CpuRegister>(), Address(temp, array_length_offset));
-
+ // Loop through the iftable and check if any class matches.
NearLabel start_loop;
__ Bind(&start_loop);
- __ cmpl(cls.AsRegister<CpuRegister>(), Address(temp, object_array_data_offset));
- __ j(kEqual, &done); // Return if same class.
- // Go to next interface.
- __ addl(temp, Immediate(2 * kHeapReferenceSize));
+ // Need to subtract first to handle the empty array case.
__ subl(maybe_temp2_loc.AsRegister<CpuRegister>(), Immediate(2));
- __ j(kNotZero, &start_loop);
+ __ j(kNegative, type_check_slow_path->GetEntryLabel());
+ // Go to next interface if the classes do not match.
+ __ cmpl(cls.AsRegister<CpuRegister>(),
+ CodeGeneratorX86_64::ArrayAddress(temp,
+ maybe_temp2_loc,
+ TIMES_4,
+ object_array_data_offset));
+ __ j(kNotEqual, &start_loop); // Return if same class.
+ } else {
+ __ jmp(type_check_slow_path->GetEntryLabel());
}
- __ jmp(type_check_slow_path->GetEntryLabel());
break;
}