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