Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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, ¬_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(¬_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, ¬_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, ¬_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(¬_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, ¬_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(¬_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 Loading... | |
| 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 |
| OLD | NEW |