OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 11039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11050 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); | 11050 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); |
11051 } | 11051 } |
11052 | 11052 |
11053 | 11053 |
11054 void RecordWriteStub::Generate(MacroAssembler* masm) { | 11054 void RecordWriteStub::Generate(MacroAssembler* masm) { |
11055 masm->RecordWriteHelper(object_, addr_, scratch_); | 11055 masm->RecordWriteHelper(object_, addr_, scratch_); |
11056 masm->ret(0); | 11056 masm->ret(0); |
11057 } | 11057 } |
11058 | 11058 |
11059 | 11059 |
| 11060 static int NegativeComparisonResult(Condition cc) { |
| 11061 ASSERT(cc != equal); |
| 11062 ASSERT((cc == less) || (cc == less_equal) |
| 11063 || (cc == greater) || (cc == greater_equal)); |
| 11064 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
| 11065 } |
| 11066 |
| 11067 |
11060 void CompareStub::Generate(MacroAssembler* masm) { | 11068 void CompareStub::Generate(MacroAssembler* masm) { |
11061 Label call_builtin, done; | 11069 Label call_builtin, done; |
11062 | 11070 |
11063 // NOTICE! This code is only reached after a smi-fast-case check, so | 11071 // NOTICE! This code is only reached after a smi-fast-case check, so |
11064 // it is certain that at least one operand isn't a smi. | 11072 // it is certain that at least one operand isn't a smi. |
11065 | 11073 |
| 11074 // Identical objects can be compared fast, but there are some tricky cases |
| 11075 // for NaN and undefined. |
| 11076 { |
| 11077 Label not_identical; |
| 11078 __ cmp(eax, Operand(edx)); |
| 11079 __ j(not_equal, ¬_identical); |
| 11080 |
| 11081 if (cc_ != equal) { |
| 11082 // Check for undefined. undefined OP undefined is false even though |
| 11083 // undefined == undefined. |
| 11084 Label check_for_nan; |
| 11085 __ cmp(edx, Factory::undefined_value()); |
| 11086 __ j(not_equal, &check_for_nan); |
| 11087 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
| 11088 __ ret(0); |
| 11089 __ bind(&check_for_nan); |
| 11090 } |
| 11091 |
| 11092 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
| 11093 // so we do the second best thing - test it ourselves. |
| 11094 // Note: if cc_ != equal, never_nan_nan_ is not used. |
| 11095 if (never_nan_nan_ && (cc_ == equal)) { |
| 11096 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 11097 __ ret(0); |
| 11098 } else { |
| 11099 Label return_equal; |
| 11100 Label heap_number; |
| 11101 // If it's not a heap number, then return equal. |
| 11102 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 11103 Immediate(Factory::heap_number_map())); |
| 11104 __ j(equal, &heap_number); |
| 11105 __ bind(&return_equal); |
| 11106 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 11107 __ ret(0); |
| 11108 |
| 11109 __ bind(&heap_number); |
| 11110 // It is a heap number, so return non-equal if it's NaN and equal if |
| 11111 // it's not NaN. |
| 11112 // The representation of NaN values has all exponent bits (52..62) set, |
| 11113 // and not all mantissa bits (0..51) clear. |
| 11114 // We only accept QNaNs, which have bit 51 set. |
| 11115 // Read top bits of double representation (second word of value). |
| 11116 |
| 11117 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., |
| 11118 // all bits in the mask are set. We only need to check the word |
| 11119 // that contains the exponent and high bit of the mantissa. |
| 11120 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); |
| 11121 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
| 11122 __ xor_(eax, Operand(eax)); |
| 11123 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost |
| 11124 // bits. |
| 11125 __ add(edx, Operand(edx)); |
| 11126 __ cmp(edx, kQuietNaNHighBitsMask << 1); |
| 11127 if (cc_ == equal) { |
| 11128 ASSERT_NE(1, EQUAL); |
| 11129 __ setcc(above_equal, eax); |
| 11130 __ ret(0); |
| 11131 } else { |
| 11132 Label nan; |
| 11133 __ j(above_equal, &nan); |
| 11134 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 11135 __ ret(0); |
| 11136 __ bind(&nan); |
| 11137 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
| 11138 __ ret(0); |
| 11139 } |
| 11140 } |
| 11141 |
| 11142 __ bind(¬_identical); |
| 11143 } |
| 11144 |
11066 if (cc_ == equal) { // Both strict and non-strict. | 11145 if (cc_ == equal) { // Both strict and non-strict. |
11067 Label slow; // Fallthrough label. | 11146 Label slow; // Fallthrough label. |
11068 // Equality is almost reflexive (everything but NaN), so start by testing | |
11069 // for "identity and not NaN". | |
11070 { | |
11071 Label not_identical; | |
11072 __ cmp(eax, Operand(edx)); | |
11073 __ j(not_equal, ¬_identical); | |
11074 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | |
11075 // so we do the second best thing - test it ourselves. | |
11076 | |
11077 if (never_nan_nan_) { | |
11078 __ Set(eax, Immediate(0)); | |
11079 __ ret(0); | |
11080 } else { | |
11081 Label return_equal; | |
11082 Label heap_number; | |
11083 // If it's not a heap number, then return equal. | |
11084 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | |
11085 Immediate(Factory::heap_number_map())); | |
11086 __ j(equal, &heap_number); | |
11087 __ bind(&return_equal); | |
11088 __ Set(eax, Immediate(0)); | |
11089 __ ret(0); | |
11090 | |
11091 __ bind(&heap_number); | |
11092 // It is a heap number, so return non-equal if it's NaN and equal if | |
11093 // it's not NaN. | |
11094 // The representation of NaN values has all exponent bits (52..62) set, | |
11095 // and not all mantissa bits (0..51) clear. | |
11096 // We only accept QNaNs, which have bit 51 set. | |
11097 // Read top bits of double representation (second word of value). | |
11098 | |
11099 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., | |
11100 // all bits in the mask are set. We only need to check the word | |
11101 // that contains the exponent and high bit of the mantissa. | |
11102 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); | |
11103 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); | |
11104 __ xor_(eax, Operand(eax)); | |
11105 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost | |
11106 // bits. | |
11107 __ add(edx, Operand(edx)); | |
11108 __ cmp(edx, kQuietNaNHighBitsMask << 1); | |
11109 __ setcc(above_equal, eax); | |
11110 __ ret(0); | |
11111 } | |
11112 | |
11113 __ bind(¬_identical); | |
11114 } | |
11115 | 11147 |
11116 // If we're doing a strict equality comparison, we don't have to do | 11148 // If we're doing a strict equality comparison, we don't have to do |
11117 // type conversion, so we generate code to do fast comparison for objects | 11149 // type conversion, so we generate code to do fast comparison for objects |
11118 // and oddballs. Non-smi numbers and strings still go through the usual | 11150 // and oddballs. Non-smi numbers and strings still go through the usual |
11119 // slow-case code. | 11151 // slow-case code. |
11120 if (strict_) { | 11152 if (strict_) { |
11121 // If either is a Smi (we know that not both are), then they can only | 11153 // If either is a Smi (we know that not both are), then they can only |
11122 // be equal if the other is a HeapNumber. If so, use the slow case. | 11154 // be equal if the other is a HeapNumber. If so, use the slow case. |
11123 { | 11155 { |
11124 Label not_smis; | 11156 Label not_smis; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11295 __ pop(eax); | 11327 __ pop(eax); |
11296 __ push(edx); | 11328 __ push(edx); |
11297 __ push(eax); | 11329 __ push(eax); |
11298 | 11330 |
11299 // Figure out which native to call and setup the arguments. | 11331 // Figure out which native to call and setup the arguments. |
11300 Builtins::JavaScript builtin; | 11332 Builtins::JavaScript builtin; |
11301 if (cc_ == equal) { | 11333 if (cc_ == equal) { |
11302 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; | 11334 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; |
11303 } else { | 11335 } else { |
11304 builtin = Builtins::COMPARE; | 11336 builtin = Builtins::COMPARE; |
11305 int ncr; // NaN compare result | 11337 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
11306 if (cc_ == less || cc_ == less_equal) { | |
11307 ncr = GREATER; | |
11308 } else { | |
11309 ASSERT(cc_ == greater || cc_ == greater_equal); // remaining cases | |
11310 ncr = LESS; | |
11311 } | |
11312 __ push(Immediate(Smi::FromInt(ncr))); | |
11313 } | 11338 } |
11314 | 11339 |
11315 // Restore return address on the stack. | 11340 // Restore return address on the stack. |
11316 __ push(ecx); | 11341 __ push(ecx); |
11317 | 11342 |
11318 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 11343 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
11319 // tagged as a small integer. | 11344 // tagged as a small integer. |
11320 __ InvokeBuiltin(builtin, JUMP_FUNCTION); | 11345 __ InvokeBuiltin(builtin, JUMP_FUNCTION); |
11321 } | 11346 } |
11322 | 11347 |
(...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12661 | 12686 |
12662 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 12687 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
12663 // tagged as a small integer. | 12688 // tagged as a small integer. |
12664 __ bind(&runtime); | 12689 __ bind(&runtime); |
12665 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 12690 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
12666 } | 12691 } |
12667 | 12692 |
12668 #undef __ | 12693 #undef __ |
12669 | 12694 |
12670 } } // namespace v8::internal | 12695 } } // namespace v8::internal |
OLD | NEW |