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