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 10270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10281 | 10281 |
10282 // Check for oddballs: true, false, null, undefined. | 10282 // Check for oddballs: true, false, null, undefined. |
10283 __ CmpInstanceType(rcx, ODDBALL_TYPE); | 10283 __ CmpInstanceType(rcx, ODDBALL_TYPE); |
10284 __ j(equal, &return_not_equal); | 10284 __ j(equal, &return_not_equal); |
10285 | 10285 |
10286 // Fall through to the general case. | 10286 // Fall through to the general case. |
10287 } | 10287 } |
10288 __ bind(&slow); | 10288 __ bind(&slow); |
10289 } | 10289 } |
10290 | 10290 |
10291 // Push arguments below the return address to prepare jump to builtin. | |
10292 __ pop(rcx); | |
10293 __ push(rax); | |
10294 __ push(rdx); | |
10295 __ push(rcx); | |
10296 | |
10297 // Generate the number comparison code. | 10291 // Generate the number comparison code. |
10298 if (include_number_compare_) { | 10292 if (include_number_compare_) { |
10299 Label non_number_comparison; | 10293 Label non_number_comparison; |
10300 Label unordered; | 10294 Label unordered; |
10301 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); | 10295 FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison); |
10302 __ xorl(rax, rax); | 10296 __ xorl(rax, rax); |
10303 __ xorl(rcx, rcx); | 10297 __ xorl(rcx, rcx); |
10304 __ ucomisd(xmm0, xmm1); | 10298 __ ucomisd(xmm0, xmm1); |
10305 | 10299 |
10306 // Don't base result on EFLAGS when a NaN is involved. | 10300 // Don't base result on EFLAGS when a NaN is involved. |
10307 __ j(parity_even, &unordered); | 10301 __ j(parity_even, &unordered); |
10308 // Return a result of -1, 0, or 1, based on EFLAGS. | 10302 // Return a result of -1, 0, or 1, based on EFLAGS. |
10309 __ setcc(above, rax); | 10303 __ setcc(above, rax); |
10310 __ setcc(below, rcx); | 10304 __ setcc(below, rcx); |
10311 __ subq(rax, rcx); | 10305 __ subq(rax, rcx); |
10312 __ ret(2 * kPointerSize); // rax, rdx were pushed | 10306 __ ret(0); |
10313 | 10307 |
10314 // If one of the numbers was NaN, then the result is always false. | 10308 // If one of the numbers was NaN, then the result is always false. |
10315 // The cc is never not-equal. | 10309 // The cc is never not-equal. |
10316 __ bind(&unordered); | 10310 __ bind(&unordered); |
10317 ASSERT(cc_ != not_equal); | 10311 ASSERT(cc_ != not_equal); |
10318 if (cc_ == less || cc_ == less_equal) { | 10312 if (cc_ == less || cc_ == less_equal) { |
10319 __ Set(rax, 1); | 10313 __ Set(rax, 1); |
10320 } else { | 10314 } else { |
10321 __ Set(rax, -1); | 10315 __ Set(rax, -1); |
10322 } | 10316 } |
10323 __ ret(2 * kPointerSize); // rax, rdx were pushed | 10317 __ ret(0); |
10324 | 10318 |
10325 // The number comparison code did not provide a valid result. | 10319 // The number comparison code did not provide a valid result. |
10326 __ bind(&non_number_comparison); | 10320 __ bind(&non_number_comparison); |
10327 } | 10321 } |
10328 | 10322 |
10329 // Fast negative check for symbol-to-symbol equality. | 10323 // Fast negative check for symbol-to-symbol equality. |
10330 Label check_for_strings; | 10324 Label check_for_strings; |
10331 if (cc_ == equal) { | 10325 if (cc_ == equal) { |
10332 BranchIfNonSymbol(masm, &check_for_strings, rax, kScratchRegister); | 10326 BranchIfNonSymbol(masm, &check_for_strings, rax, kScratchRegister); |
10333 BranchIfNonSymbol(masm, &check_for_strings, rdx, kScratchRegister); | 10327 BranchIfNonSymbol(masm, &check_for_strings, rdx, kScratchRegister); |
10334 | 10328 |
10335 // We've already checked for object identity, so if both operands | 10329 // We've already checked for object identity, so if both operands |
10336 // are symbols they aren't equal. Register eax (not rax) already holds a | 10330 // are symbols they aren't equal. Register eax (not rax) already holds a |
10337 // non-zero value, which indicates not equal, so just return. | 10331 // non-zero value, which indicates not equal, so just return. |
10338 __ ret(2 * kPointerSize); | 10332 __ ret(0); |
10339 } | 10333 } |
10340 | 10334 |
10341 __ bind(&check_for_strings); | 10335 __ bind(&check_for_strings); |
10342 | 10336 |
10343 __ JumpIfNotBothSequentialAsciiStrings( | 10337 __ JumpIfNotBothSequentialAsciiStrings( |
10344 rdx, rax, rcx, rbx, &check_unequal_objects); | 10338 rdx, rax, rcx, rbx, &check_unequal_objects); |
10345 | 10339 |
10346 // Inline comparison of ascii strings. | 10340 // Inline comparison of ascii strings. |
10347 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | 10341 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
10348 rdx, | 10342 rdx, |
(...skipping 30 matching lines...) Expand all Loading... |
10379 __ j(zero, &return_unequal); | 10373 __ j(zero, &return_unequal); |
10380 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 10374 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
10381 Immediate(1 << Map::kIsUndetectable)); | 10375 Immediate(1 << Map::kIsUndetectable)); |
10382 __ j(zero, &return_unequal); | 10376 __ j(zero, &return_unequal); |
10383 // The objects are both undetectable, so they both compare as the value | 10377 // The objects are both undetectable, so they both compare as the value |
10384 // undefined, and are equal. | 10378 // undefined, and are equal. |
10385 __ Set(rax, EQUAL); | 10379 __ Set(rax, EQUAL); |
10386 __ bind(&return_unequal); | 10380 __ bind(&return_unequal); |
10387 // Return non-equal by returning the non-zero object pointer in eax, | 10381 // Return non-equal by returning the non-zero object pointer in eax, |
10388 // or return equal if we fell through to here. | 10382 // or return equal if we fell through to here. |
10389 __ ret(2 * kPointerSize); // rax, rdx were pushed | 10383 __ ret(0); |
10390 __ bind(¬_both_objects); | 10384 __ bind(¬_both_objects); |
10391 } | 10385 } |
10392 | 10386 |
10393 // must swap argument order | 10387 // Push arguments below the return address to prepare jump to builtin. |
10394 __ pop(rcx); | 10388 __ pop(rcx); |
10395 __ pop(rdx); | |
10396 __ pop(rax); | |
10397 __ push(rdx); | 10389 __ push(rdx); |
10398 __ push(rax); | 10390 __ push(rax); |
10399 | 10391 |
10400 // Figure out which native to call and setup the arguments. | 10392 // Figure out which native to call and setup the arguments. |
10401 Builtins::JavaScript builtin; | 10393 Builtins::JavaScript builtin; |
10402 if (cc_ == equal) { | 10394 if (cc_ == equal) { |
10403 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; | 10395 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; |
10404 } else { | 10396 } else { |
10405 builtin = Builtins::COMPARE; | 10397 builtin = Builtins::COMPARE; |
10406 __ Push(Smi::FromInt(NegativeComparisonResult(cc_))); | 10398 __ Push(Smi::FromInt(NegativeComparisonResult(cc_))); |
(...skipping 1556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11963 __ j(not_equal, &loop); | 11955 __ j(not_equal, &loop); |
11964 } | 11956 } |
11965 // Completed loop without finding different characters. | 11957 // Completed loop without finding different characters. |
11966 // Compare lengths (precomputed). | 11958 // Compare lengths (precomputed). |
11967 __ bind(&compare_lengths); | 11959 __ bind(&compare_lengths); |
11968 __ SmiTest(length_difference); | 11960 __ SmiTest(length_difference); |
11969 __ j(not_zero, &result_not_equal); | 11961 __ j(not_zero, &result_not_equal); |
11970 | 11962 |
11971 // Result is EQUAL. | 11963 // Result is EQUAL. |
11972 __ Move(rax, Smi::FromInt(EQUAL)); | 11964 __ Move(rax, Smi::FromInt(EQUAL)); |
11973 __ ret(2 * kPointerSize); | 11965 __ ret(0); |
11974 | 11966 |
11975 Label result_greater; | 11967 Label result_greater; |
11976 __ bind(&result_not_equal); | 11968 __ bind(&result_not_equal); |
11977 // Unequal comparison of left to right, either character or length. | 11969 // Unequal comparison of left to right, either character or length. |
11978 __ j(greater, &result_greater); | 11970 __ j(greater, &result_greater); |
11979 | 11971 |
11980 // Result is LESS. | 11972 // Result is LESS. |
11981 __ Move(rax, Smi::FromInt(LESS)); | 11973 __ Move(rax, Smi::FromInt(LESS)); |
11982 __ ret(2 * kPointerSize); | 11974 __ ret(0); |
11983 | 11975 |
11984 // Result is GREATER. | 11976 // Result is GREATER. |
11985 __ bind(&result_greater); | 11977 __ bind(&result_greater); |
11986 __ Move(rax, Smi::FromInt(GREATER)); | 11978 __ Move(rax, Smi::FromInt(GREATER)); |
11987 __ ret(2 * kPointerSize); | 11979 __ ret(0); |
11988 } | 11980 } |
11989 | 11981 |
11990 | 11982 |
11991 void StringCompareStub::Generate(MacroAssembler* masm) { | 11983 void StringCompareStub::Generate(MacroAssembler* masm) { |
11992 Label runtime; | 11984 Label runtime; |
11993 | 11985 |
11994 // Stack frame on entry. | 11986 // Stack frame on entry. |
11995 // rsp[0]: return address | 11987 // rsp[0]: return address |
11996 // rsp[8]: right string | 11988 // rsp[8]: right string |
11997 // rsp[16]: left string | 11989 // rsp[16]: left string |
11998 | 11990 |
11999 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left | 11991 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left |
12000 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right | 11992 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right |
12001 | 11993 |
12002 // Check for identity. | 11994 // Check for identity. |
12003 Label not_same; | 11995 Label not_same; |
12004 __ cmpq(rdx, rax); | 11996 __ cmpq(rdx, rax); |
12005 __ j(not_equal, ¬_same); | 11997 __ j(not_equal, ¬_same); |
12006 __ Move(rax, Smi::FromInt(EQUAL)); | 11998 __ Move(rax, Smi::FromInt(EQUAL)); |
12007 __ IncrementCounter(&Counters::string_compare_native, 1); | 11999 __ IncrementCounter(&Counters::string_compare_native, 1); |
12008 __ ret(2 * kPointerSize); | 12000 __ ret(2 * kPointerSize); |
12009 | 12001 |
12010 __ bind(¬_same); | 12002 __ bind(¬_same); |
12011 | 12003 |
12012 // Check that both are sequential ASCII strings. | 12004 // Check that both are sequential ASCII strings. |
12013 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); | 12005 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); |
12014 | 12006 |
12015 // Inline comparison of ascii strings. | 12007 // Inline comparison of ascii strings. |
12016 __ IncrementCounter(&Counters::string_compare_native, 1); | 12008 __ IncrementCounter(&Counters::string_compare_native, 1); |
| 12009 // Drop arguments from the stack |
| 12010 __ pop(rcx); |
| 12011 __ addq(rsp, Immediate(2 * kPointerSize)); |
| 12012 __ push(rcx); |
12017 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); | 12013 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); |
12018 | 12014 |
12019 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 12015 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
12020 // tagged as a small integer. | 12016 // tagged as a small integer. |
12021 __ bind(&runtime); | 12017 __ bind(&runtime); |
12022 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 12018 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
12023 } | 12019 } |
12024 | 12020 |
12025 #undef __ | 12021 #undef __ |
12026 | 12022 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12119 #undef __ | 12115 #undef __ |
12120 | 12116 |
12121 void RecordWriteStub::Generate(MacroAssembler* masm) { | 12117 void RecordWriteStub::Generate(MacroAssembler* masm) { |
12122 masm->RecordWriteHelper(object_, addr_, scratch_); | 12118 masm->RecordWriteHelper(object_, addr_, scratch_); |
12123 masm->ret(0); | 12119 masm->ret(0); |
12124 } | 12120 } |
12125 | 12121 |
12126 } } // namespace v8::internal | 12122 } } // namespace v8::internal |
12127 | 12123 |
12128 #endif // V8_TARGET_ARCH_X64 | 12124 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |