OSDN Git Service

Further refinements to checkcast/instanceof.
authorNicolas Geoffray <ngeoffray@google.com>
Mon, 21 Sep 2015 17:41:21 +0000 (18:41 +0100)
committerNicolas Geoffray <ngeoffray@google.com>
Tue, 22 Sep 2015 09:38:46 +0000 (10:38 +0100)
- Use setcc when possible.
- Do an exact check in the Object[] case before checking the
  component type.

Change-Id: Ic11c60643af9b41fe4ef2beb59dfe7769bef388f

compiler/optimizing/code_generator_arm.cc
compiler/optimizing/code_generator_arm64.cc
compiler/optimizing/code_generator_x86.cc
compiler/optimizing/code_generator_x86_64.cc

index d431acf..411e05f 100644 (file)
@@ -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());
index 580e93e..8e1260e 100644 (file)
@@ -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());
index 3d03dd8..86cdbdd 100644 (file)
@@ -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);
index 32a1db5..b78b017 100644 (file)
@@ -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);