| 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 |