Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: src/codegen-ia32.cc

Issue 60085: Rewrote equality check in CompareStub to do quick pointer comparison first. (Closed)
Patch Set: Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 6495 matching lines...) Expand 10 before | Expand all | Expand 10 after
6506 6506
6507 // Do the runtime call to allocate the arguments object. 6507 // Do the runtime call to allocate the arguments object.
6508 __ bind(&runtime); 6508 __ bind(&runtime);
6509 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); 6509 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3);
6510 } 6510 }
6511 6511
6512 6512
6513 void CompareStub::Generate(MacroAssembler* masm) { 6513 void CompareStub::Generate(MacroAssembler* masm) {
6514 Label call_builtin, done; 6514 Label call_builtin, done;
6515 6515
6516 // If we're doing a strict equality comparison, we generate code 6516 // NOTICE! This code is only reached after a smi-fast-case check, so
6517 // to do fast comparison for objects and oddballs. Numbers and 6517 // it is certain that at least one operand isn't a smi.
6518 // strings still go through the usual slow-case code.
6519 if (strict_) {
6520 Label slow;
6521 __ test(eax, Immediate(kSmiTagMask));
6522 __ j(zero, &slow);
6523 6518
6524 // Get the type of the first operand. 6519 if (cc_ == equal) { // Both strict and non-strict.
6525 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 6520 Label slow; // Fallthrough label.
6526 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 6521 // Equality is almost reflexive (everything but NaN), so start by testing
6522 // for "identity and not NaN".
6523 {
6524 Label not_identical;
6525 __ cmp(eax, Operand(edx));
6526 __ j(not_equal, &not_identical);
6527 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
6528 // so we do the second best thing - test it ourselves.
6527 6529
6528 // If the first object is an object, we do pointer comparison. 6530 Label return_equal;
6529 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 6531 Label heap_number;
6530 Label non_object; 6532 // If it's not a heap number, then return equal.
6531 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 6533 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
6532 __ j(less, &non_object); 6534 Immediate(Factory::heap_number_map()));
6533 __ sub(eax, Operand(edx)); 6535 __ j(equal, &heap_number);
6534 __ ret(0); 6536 __ bind(&return_equal);
6537 __ Set(eax, Immediate(0));
6538 __ ret(0);
6535 6539
6536 // Check for oddballs: true, false, null, undefined. 6540 // Try to read the first word of the heap-number. This is the high
Erik Corry 2009/04/03 12:31:56 Comment looks wrong.
6537 __ bind(&non_object); 6541 // bits of the double number, and contains the exponent.
6538 __ cmp(ecx, ODDBALL_TYPE); 6542 __ bind(&heap_number);
6539 __ j(not_equal, &slow); 6543 // If it is a heap number, then check if it's NaN, and return not-equal
6544 // Read top bits of double representation (second word of value).
6545 __ mov(eax, FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize));
6546 // Test that exponent bits are all set.
6547 __ not_(eax);
6548 __ test(eax, Immediate(0x7ff00000));
6549 __ j(not_zero, &return_equal);
6550 __ not_(eax);
6540 6551
6541 // If the oddball isn't undefined, we do pointer comparison. For 6552 // Shift out flag and all exponent bits, retaining only mantissa.
6542 // the undefined value, we have to be careful and check for 6553 __ shl(eax, 12);
6543 // 'undetectable' objects too. 6554 // Or with all low-bits of mantissa.
6544 Label undefined; 6555 __ or_(eax, FieldOperand(edx, HeapNumber::kValueOffset));
6545 __ cmp(Operand(eax), Immediate(Factory::undefined_value())); 6556 // Return zero equal if all bits in mantissa is zero (it's an Infinity)
6546 __ j(equal, &undefined); 6557 // and non-zero if not (it's a NaN).
6547 __ sub(eax, Operand(edx)); 6558 __ ret(0);
6548 __ ret(0);
6549 6559
6550 // Undefined case: If the other operand isn't undefined too, we 6560 __ bind(&not_identical);
6551 // have to check if it's 'undetectable'. 6561 }
6552 Label check_undetectable;
6553 __ bind(&undefined);
6554 __ cmp(Operand(edx), Immediate(Factory::undefined_value()));
6555 __ j(not_equal, &check_undetectable);
6556 __ Set(eax, Immediate(0));
6557 __ ret(0);
6558 6562
6559 // Check for undetectability of the other operand. 6563 // If we're doing a strict equality comparison, we don't have to do
6560 Label not_strictly_equal; 6564 // type conversion, so we generate code to do fast comparison for objects
6561 __ bind(&check_undetectable); 6565 // and oddballs. Non-smi numbers and strings still go through the usual
6562 __ test(edx, Immediate(kSmiTagMask)); 6566 // slow-case code.
6563 __ j(zero, &not_strictly_equal); 6567 if (strict_) {
6564 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
6565 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
6566 __ and_(ecx, 1 << Map::kIsUndetectable);
6567 __ cmp(ecx, 1 << Map::kIsUndetectable);
6568 __ j(not_equal, &not_strictly_equal);
6569 __ Set(eax, Immediate(0));
6570 __ ret(0);
6571 6568
6572 // No cigar: Objects aren't strictly equal. Register eax contains 6569 // If either is a Smi (we know that not both are), then they can only
6573 // a non-smi value so it can't be 0. Just return. 6570 // be equal if the other is a HeapNumber. If so, use the slow case.
6574 ASSERT(kHeapObjectTag != 0); 6571 {
6575 __ bind(&not_strictly_equal); 6572 Label not_smis;
6576 __ ret(0); 6573 ASSERT_EQ(0, kSmiTag);
6574 ASSERT_EQ(0, Smi::FromInt(0));
6575 __ mov(ecx, Immediate(kSmiTagMask));
6576 __ and_(ecx, Operand(eax));
6577 __ test(ecx, Operand(edx));
6578 __ j(not_zero, &not_smis);
6579 // One operand is a smi.
6577 6580
6578 // Fall through to the general case. 6581 // Check whether the non-smi is a heap number.
6582 ASSERT_EQ(1, kSmiTagMask);
6583 // ecx still holds eax & kSmiTag, which is either zero or one.
6584 __ sub(Operand(ecx), Immediate(0x01));
6585 __ mov(ebx, edx);
6586 __ xor_(ebx, Operand(eax));
6587 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx.
6588 __ xor_(ebx, Operand(eax));
6589 // if eax was smi, ebx is now edx, else eax.
6590
6591 // Check if the non-smi operand is a heap number.
6592 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
6593 Immediate(Factory::heap_number_map()));
6594 // If heap number, handle it in the slow case.
6595 __ j(equal, &slow);
6596 // Return non-equal (ebx is not zero)
6597 __ mov(eax, ebx);
6598 __ ret(0);
6599
6600 __ bind(&not_smis);
6601 }
6602
6603 // If either operand is a JSObject or an oddball value, then they are not
6604 // equal since their pointers are different
6605 // There is no test for undetectability in strict equality.
6606
6607 // Get the type of the first operand.
6608 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
6609 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
6610
6611 // If the first object is a JS object, we have done pointer comparison.
6612 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
6613 Label first_non_object;
6614 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
6615 __ j(less, &first_non_object);
6616
6617 // Return non-zero (eax is not zero)
6618 Label return_not_equal;
6619 ASSERT(kHeapObjectTag != 0);
6620 __ bind(&return_not_equal);
6621 __ ret(0);
6622
6623 __ bind(&first_non_object);
6624 // Check for oddballs: true, false, null, undefined.
6625 __ cmp(ecx, ODDBALL_TYPE);
6626 __ j(equal, &return_not_equal);
6627
6628 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
6629 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
6630
6631 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
6632 __ j(greater_equal, &return_not_equal);
6633
6634 // Check for oddballs: true, false, null, undefined.
6635 __ cmp(ecx, ODDBALL_TYPE);
6636 __ j(equal, &return_not_equal);
6637
6638 // Fall through to the general case.
6639 }
6579 __ bind(&slow); 6640 __ bind(&slow);
6580 } 6641 }
6581 6642
6582 // Save the return address (and get it off the stack). 6643 // Save the return address (and get it off the stack).
6583 __ pop(ecx); 6644 __ pop(ecx);
6584 6645
6585 // Push arguments. 6646 // Push arguments.
6586 __ push(eax); 6647 __ push(eax);
6587 __ push(edx); 6648 __ push(edx);
6588 __ push(ecx); 6649 __ push(ecx);
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
7086 7147
7087 // Slow-case: Go through the JavaScript implementation. 7148 // Slow-case: Go through the JavaScript implementation.
7088 __ bind(&slow); 7149 __ bind(&slow);
7089 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7150 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7090 } 7151 }
7091 7152
7092 7153
7093 #undef __ 7154 #undef __
7094 7155
7095 } } // namespace v8::internal 7156 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698