PPC: Mark null and undefined as undetectable, and use it to handle abstract equality comparison in the generic compare ic
Port 3ce9e808c5
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}
This commit is contained in:
parent
0ecdd93282
commit
d4bdd76726
@ -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));
|
||||
|
@ -514,7 +514,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
|
||||
void FullCodeGenerator::TestContext::Plug(Handle<Object> 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));
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user