From d4bdd7672615624367aab123325d295c41d464fc Mon Sep 17 00:00:00 2001 From: mbrandy Date: Wed, 10 Feb 2016 12:08:03 -0800 Subject: [PATCH] PPC: Mark null and undefined as undetectable, and use it to handle abstract equality comparison in the generic compare ic Port 3ce9e808c5b9a6149ac987213854b5d59005f366 Original commit message: Marking as undetectable makes abstract equality of null, undefined, and other undetectable objects easier. Supporting it in the generic compare IC significantly speeds up dynamic comparison between those values and JSReceivers by not falling back to the runtime. R=verwaest@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com BUG= Review URL: https://codereview.chromium.org/1684133003 Cr-Commit-Position: refs/heads/master@{#33876} --- src/crankshaft/ppc/lithium-codegen-ppc.cc | 4 +- src/full-codegen/ppc/full-codegen-ppc.cc | 6 +-- src/ppc/code-stubs-ppc.cc | 45 ++++++++++++++--------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/crankshaft/ppc/lithium-codegen-ppc.cc b/src/crankshaft/ppc/lithium-codegen-ppc.cc index 819e2bb356..ad19ecb000 100644 --- a/src/crankshaft/ppc/lithium-codegen-ppc.cc +++ b/src/crankshaft/ppc/lithium-codegen-ppc.cc @@ -5478,8 +5478,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label, final_branch_condition = eq; } else if (String::Equals(type_name, factory->undefined_string())) { - __ CompareRoot(input, Heap::kUndefinedValueRootIndex); - __ beq(true_label); + __ CompareRoot(input, Heap::kNullValueRootIndex); + __ beq(false_label); __ JumpIfSmi(input, false_label); // Check for undetectable objects => true. __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc index 1555344b52..69e1578d1b 100644 --- a/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/src/full-codegen/ppc/full-codegen-ppc.cc @@ -514,7 +514,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle lit) const { void FullCodeGenerator::TestContext::Plug(Handle lit) const { codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); - DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. + DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectableObject()); if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { if (false_label_ != fall_through_) __ b(false_label_); } else if (lit->IsTrue() || lit->IsJSObject()) { @@ -4295,8 +4295,8 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, __ CompareRoot(r3, Heap::kFalseValueRootIndex); Split(eq, if_true, if_false, fall_through); } else if (String::Equals(check, factory->undefined_string())) { - __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); - __ beq(if_true); + __ CompareRoot(r3, Heap::kNullValueRootIndex); + __ beq(if_false); __ JumpIfSmi(r3, if_false); // Check for undetectable objects => true. __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset)); diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc index 0fc5c3bc13..014949c85e 100644 --- a/src/ppc/code-stubs-ppc.cc +++ b/src/ppc/code-stubs-ppc.cc @@ -515,40 +515,49 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs, static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, Register lhs, Register rhs, Label* possible_strings, - Label* not_both_strings) { + Label* runtime_call) { DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); // r5 is object type of rhs. - Label object_test; + Label object_test, return_unequal, undetectable; STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); __ andi(r0, r5, Operand(kIsNotStringMask)); __ bne(&object_test, cr0); __ andi(r0, r5, Operand(kIsNotInternalizedMask)); __ bne(possible_strings, cr0); __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE); - __ bge(not_both_strings); + __ bge(runtime_call); __ andi(r0, r6, Operand(kIsNotInternalizedMask)); __ bne(possible_strings, cr0); - // Both are internalized. We already checked they weren't the same pointer - // so they are not equal. - __ li(r3, Operand(NOT_EQUAL)); + // Both are internalized. We already checked they weren't the same pointer so + // they are not equal. Return non-equal by returning the non-zero object + // pointer in r3. __ Ret(); __ bind(&object_test); - __ cmpi(r5, Operand(FIRST_JS_RECEIVER_TYPE)); - __ blt(not_both_strings); - __ CompareObjectType(lhs, r5, r6, FIRST_JS_RECEIVER_TYPE); - __ blt(not_both_strings); - // If both objects are undetectable, they are equal. Otherwise, they - // are not equal, since they are different objects and an object is not - // equal to undefined. + __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset)); - __ lbz(r5, FieldMemOperand(r5, Map::kBitFieldOffset)); - __ lbz(r6, FieldMemOperand(r6, Map::kBitFieldOffset)); - __ and_(r3, r5, r6); - __ andi(r3, r3, Operand(1 << Map::kIsUndetectable)); - __ xori(r3, r3, Operand(1 << Map::kIsUndetectable)); + __ lbz(r7, FieldMemOperand(r5, Map::kBitFieldOffset)); + __ lbz(r8, FieldMemOperand(r6, Map::kBitFieldOffset)); + __ andi(r0, r7, Operand(1 << Map::kIsUndetectable)); + __ bne(&undetectable, cr0); + __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); + __ bne(&return_unequal, cr0); + + __ CompareInstanceType(r5, r5, FIRST_JS_RECEIVER_TYPE); + __ blt(runtime_call); + __ CompareInstanceType(r6, r6, FIRST_JS_RECEIVER_TYPE); + __ blt(runtime_call); + + __ bind(&return_unequal); + // Return non-equal by returning the non-zero object pointer in r3. + __ Ret(); + + __ bind(&undetectable); + __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); + __ beq(&return_unequal, cr0); + __ li(r3, Operand(EQUAL)); __ Ret(); }