summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2015-09-21 18:41:21 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2015-09-22 10:38:46 +0100
commitabfcf18fa2fe723bd683edcb685ed5058d9c7cf3 (patch)
tree98f8c9be7b4cb6bdcfd7ce7fc817f6a0750f30d5
parent47d89c7376090a3a4b8eb114e2c861afe27d01d0 (diff)
Further refinements to checkcast/instanceof.
- Use setcc when possible. - Do an exact check in the Object[] case before checking the component type. Change-Id: Ic11c60643af9b41fe4ef2beb59dfe7769bef388f
-rw-r--r--compiler/optimizing/code_generator_arm.cc17
-rw-r--r--compiler/optimizing/code_generator_arm64.cc17
-rw-r--r--compiler/optimizing/code_generator_x86.cc30
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc41
4 files changed, 80 insertions, 25 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index d431acfb53..411e05f443 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -4477,7 +4477,11 @@ void InstructionCodeGeneratorARM::VisitInstanceOf(HInstanceOf* instruction) {
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ Label exact_check;
+ __ cmp(out, ShifterOperand(cls));
+ __ b(&exact_check, EQ);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ LoadFromOffset(kLoadWord, out, out, component_offset);
__ MaybeUnpoisonHeapReference(out);
// If `out` is null, we use it for the result, and jump to `done`.
@@ -4485,6 +4489,7 @@ void InstructionCodeGeneratorARM::VisitInstanceOf(HInstanceOf* instruction) {
__ LoadFromOffset(kLoadUnsignedHalfword, out, out, primitive_offset);
static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
__ CompareAndBranchIfNonZero(out, &zero);
+ __ Bind(&exact_check);
__ LoadImmediate(out, 1);
__ b(&done);
break;
@@ -4623,20 +4628,22 @@ void InstructionCodeGeneratorARM::VisitCheckCast(HCheckCast* instruction) {
}
case TypeCheckKind::kClassHierarchyCheck: {
// Walk over the class hierarchy to find a match.
- Label loop, success;
+ Label loop;
__ Bind(&loop);
__ cmp(temp, ShifterOperand(cls));
- __ b(&success, EQ);
+ __ b(&done, EQ);
__ LoadFromOffset(kLoadWord, temp, temp, super_offset);
__ MaybeUnpoisonHeapReference(temp);
__ CompareAndBranchIfNonZero(temp, &loop);
// Jump to the slow path to throw the exception.
__ b(slow_path->GetEntryLabel());
- __ Bind(&success);
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ __ cmp(temp, ShifterOperand(cls));
+ __ b(&done, EQ);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ LoadFromOffset(kLoadWord, temp, temp, component_offset);
__ MaybeUnpoisonHeapReference(temp);
__ CompareAndBranchIfZero(temp, slow_path->GetEntryLabel());
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 580e93e9c4..8e1260e821 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2342,7 +2342,11 @@ void InstructionCodeGeneratorARM64::VisitInstanceOf(HInstanceOf* instruction) {
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ vixl::Label exact_check;
+ __ Cmp(out, cls);
+ __ B(eq, &exact_check);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ Ldr(out, HeapOperand(out, component_offset));
GetAssembler()->MaybeUnpoisonHeapReference(out);
// If `out` is null, we use it for the result, and jump to `done`.
@@ -2350,6 +2354,7 @@ void InstructionCodeGeneratorARM64::VisitInstanceOf(HInstanceOf* instruction) {
__ Ldrh(out, HeapOperand(out, primitive_offset));
static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
__ Cbnz(out, &zero);
+ __ Bind(&exact_check);
__ Mov(out, 1);
__ B(&done);
break;
@@ -2489,20 +2494,22 @@ void InstructionCodeGeneratorARM64::VisitCheckCast(HCheckCast* instruction) {
}
case TypeCheckKind::kClassHierarchyCheck: {
// Walk over the class hierarchy to find a match.
- vixl::Label loop, success;
+ vixl::Label loop;
__ Bind(&loop);
__ Cmp(temp, cls);
- __ B(eq, &success);
+ __ B(eq, &done);
__ Ldr(temp, HeapOperand(temp, super_offset));
GetAssembler()->MaybeUnpoisonHeapReference(temp);
__ Cbnz(temp, &loop);
// Jump to the slow path to throw the exception.
__ B(slow_path->GetEntryLabel());
- __ Bind(&success);
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ __ Cmp(temp, cls);
+ __ B(eq, &done);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ Ldr(temp, HeapOperand(temp, component_offset));
GetAssembler()->MaybeUnpoisonHeapReference(temp);
__ Cbz(temp, slow_path->GetEntryLabel());
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 3d03dd8146..86cdbdde8c 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1314,7 +1314,7 @@ void InstructionCodeGeneratorX86::VisitCondition(HCondition* cond) {
default: {
// Integer case.
- // Clear output register: setcc only sets the low byte.
+ // Clear output register: setb only sets the low byte.
__ xorl(reg, reg);
if (rhs.IsRegister()) {
@@ -5038,6 +5038,7 @@ void InstructionCodeGeneratorX86::VisitInstanceOf(HInstanceOf* instruction) {
DCHECK(cls.IsStackSlot()) << cls;
__ cmpl(out, Address(ESP, cls.GetStackIndex()));
}
+
// Classes must be equal for the instanceof to succeed.
__ j(kNotEqual, &zero);
__ movl(out, Immediate(1));
@@ -5092,7 +5093,16 @@ void InstructionCodeGeneratorX86::VisitInstanceOf(HInstanceOf* instruction) {
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ NearLabel exact_check;
+ if (cls.IsRegister()) {
+ __ cmpl(out, cls.AsRegister<Register>());
+ } else {
+ DCHECK(cls.IsStackSlot()) << cls;
+ __ cmpl(out, Address(ESP, cls.GetStackIndex()));
+ }
+ __ j(kEqual, &exact_check);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ movl(out, Address(out, component_offset));
__ MaybeUnpoisonHeapReference(out);
__ testl(out, out);
@@ -5100,6 +5110,7 @@ void InstructionCodeGeneratorX86::VisitInstanceOf(HInstanceOf* instruction) {
__ j(kEqual, &done);
__ cmpw(Address(out, primitive_offset), Immediate(Primitive::kPrimNot));
__ j(kNotEqual, &zero);
+ __ Bind(&exact_check);
__ movl(out, Immediate(1));
__ jmp(&done);
break;
@@ -5255,7 +5266,7 @@ void InstructionCodeGeneratorX86::VisitCheckCast(HCheckCast* instruction) {
}
case TypeCheckKind::kClassHierarchyCheck: {
// Walk over the class hierarchy to find a match.
- NearLabel loop, success;
+ NearLabel loop;
__ Bind(&loop);
if (cls.IsRegister()) {
__ cmpl(temp, cls.AsRegister<Register>());
@@ -5263,18 +5274,25 @@ void InstructionCodeGeneratorX86::VisitCheckCast(HCheckCast* instruction) {
DCHECK(cls.IsStackSlot()) << cls;
__ cmpl(temp, Address(ESP, cls.GetStackIndex()));
}
- __ j(kEqual, &success);
+ __ j(kEqual, &done);
__ movl(temp, Address(temp, super_offset));
__ MaybeUnpoisonHeapReference(temp);
__ testl(temp, temp);
__ j(kNotEqual, &loop);
// Jump to the slow path to throw the exception.
__ jmp(slow_path->GetEntryLabel());
- __ Bind(&success);
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ if (cls.IsRegister()) {
+ __ cmpl(temp, cls.AsRegister<Register>());
+ } else {
+ DCHECK(cls.IsStackSlot()) << cls;
+ __ cmpl(temp, Address(ESP, cls.GetStackIndex()));
+ }
+ __ j(kEqual, &done);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ movl(temp, Address(temp, component_offset));
__ MaybeUnpoisonHeapReference(temp);
__ testl(temp, temp);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 32a1db5475..b78b017e23 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4766,10 +4766,16 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) {
DCHECK(cls.IsStackSlot()) << cls;
__ cmpl(out, Address(CpuRegister(RSP), cls.GetStackIndex()));
}
- // Classes must be equal for the instanceof to succeed.
- __ j(kNotEqual, &zero);
- __ movl(out, Immediate(1));
- __ jmp(&done);
+ if (zero.IsLinked()) {
+ // Classes must be equal for the instanceof to succeed.
+ __ j(kNotEqual, &zero);
+ __ movl(out, Immediate(1));
+ __ jmp(&done);
+ } else {
+ __ setcc(kEqual, out);
+ // setcc only sets the low byte.
+ __ andl(out, Immediate(1));
+ }
break;
}
case TypeCheckKind::kAbstractClassCheck: {
@@ -4820,7 +4826,16 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) {
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ NearLabel exact_check;
+ if (cls.IsRegister()) {
+ __ cmpl(out, cls.AsRegister<CpuRegister>());
+ } else {
+ DCHECK(cls.IsStackSlot()) << cls;
+ __ cmpl(out, Address(CpuRegister(RSP), cls.GetStackIndex()));
+ }
+ __ j(kEqual, &exact_check);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ movl(out, Address(out, component_offset));
__ MaybeUnpoisonHeapReference(out);
__ testl(out, out);
@@ -4828,6 +4843,7 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) {
__ j(kEqual, &done);
__ cmpw(Address(out, primitive_offset), Immediate(Primitive::kPrimNot));
__ j(kNotEqual, &zero);
+ __ Bind(&exact_check);
__ movl(out, Immediate(1));
__ jmp(&done);
break;
@@ -4983,7 +4999,7 @@ void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) {
}
case TypeCheckKind::kClassHierarchyCheck: {
// Walk over the class hierarchy to find a match.
- NearLabel loop, success;
+ NearLabel loop;
__ Bind(&loop);
if (cls.IsRegister()) {
__ cmpl(temp, cls.AsRegister<CpuRegister>());
@@ -4991,18 +5007,25 @@ void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) {
DCHECK(cls.IsStackSlot()) << cls;
__ cmpl(temp, Address(CpuRegister(RSP), cls.GetStackIndex()));
}
- __ j(kEqual, &success);
+ __ j(kEqual, &done);
__ movl(temp, Address(temp, super_offset));
__ MaybeUnpoisonHeapReference(temp);
__ testl(temp, temp);
__ j(kNotEqual, &loop);
// Jump to the slow path to throw the exception.
__ jmp(slow_path->GetEntryLabel());
- __ Bind(&success);
break;
}
case TypeCheckKind::kArrayObjectCheck: {
- // Just need to check that the object's class is a non primitive array.
+ // Do an exact check.
+ if (cls.IsRegister()) {
+ __ cmpl(temp, cls.AsRegister<CpuRegister>());
+ } else {
+ DCHECK(cls.IsStackSlot()) << cls;
+ __ cmpl(temp, Address(CpuRegister(RSP), cls.GetStackIndex()));
+ }
+ __ j(kEqual, &done);
+ // Otherwise, we need to check that the object's class is a non primitive array.
__ movl(temp, Address(temp, component_offset));
__ MaybeUnpoisonHeapReference(temp);
__ testl(temp, temp);