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

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

Issue 1558040: Faster comparison of identical objects. (Closed)
Patch Set: Addressing comments Created 10 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 | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &not_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(&not_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, &not_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(&not_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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698