OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 344 |
345 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 345 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
346 // Update the static counter each time a new code stub is generated. | 346 // Update the static counter each time a new code stub is generated. |
347 isolate()->counters()->code_stubs()->Increment(); | 347 isolate()->counters()->code_stubs()->Increment(); |
348 | 348 |
349 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(); | 349 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(); |
350 int param_count = descriptor->GetEnvironmentParameterCount(); | 350 int param_count = descriptor->GetEnvironmentParameterCount(); |
351 { | 351 { |
352 // Call the runtime system in a fresh internal frame. | 352 // Call the runtime system in a fresh internal frame. |
353 FrameScope scope(masm, StackFrame::INTERNAL); | 353 FrameScope scope(masm, StackFrame::INTERNAL); |
354 ASSERT(param_count == 0 || | 354 DCHECK(param_count == 0 || |
355 rax.is(descriptor->GetEnvironmentParameterRegister( | 355 rax.is(descriptor->GetEnvironmentParameterRegister( |
356 param_count - 1))); | 356 param_count - 1))); |
357 // Push arguments | 357 // Push arguments |
358 for (int i = 0; i < param_count; ++i) { | 358 for (int i = 0; i < param_count; ++i) { |
359 __ Push(descriptor->GetEnvironmentParameterRegister(i)); | 359 __ Push(descriptor->GetEnvironmentParameterRegister(i)); |
360 } | 360 } |
361 ExternalReference miss = descriptor->miss_handler(); | 361 ExternalReference miss = descriptor->miss_handler(); |
362 __ CallExternalReference(miss, param_count); | 362 __ CallExternalReference(miss, param_count); |
363 } | 363 } |
364 | 364 |
(...skipping 28 matching lines...) Expand all Loading... |
393 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. | 393 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. |
394 // NumberOperands assumes both are smis or heap numbers. | 394 // NumberOperands assumes both are smis or heap numbers. |
395 static void LoadSSE2UnknownOperands(MacroAssembler* masm, | 395 static void LoadSSE2UnknownOperands(MacroAssembler* masm, |
396 Label* not_numbers); | 396 Label* not_numbers); |
397 }; | 397 }; |
398 | 398 |
399 | 399 |
400 void DoubleToIStub::Generate(MacroAssembler* masm) { | 400 void DoubleToIStub::Generate(MacroAssembler* masm) { |
401 Register input_reg = this->source(); | 401 Register input_reg = this->source(); |
402 Register final_result_reg = this->destination(); | 402 Register final_result_reg = this->destination(); |
403 ASSERT(is_truncating()); | 403 DCHECK(is_truncating()); |
404 | 404 |
405 Label check_negative, process_64_bits, done; | 405 Label check_negative, process_64_bits, done; |
406 | 406 |
407 int double_offset = offset(); | 407 int double_offset = offset(); |
408 | 408 |
409 // Account for return address and saved regs if input is rsp. | 409 // Account for return address and saved regs if input is rsp. |
410 if (input_reg.is(rsp)) double_offset += 3 * kRegisterSize; | 410 if (input_reg.is(rsp)) double_offset += 3 * kRegisterSize; |
411 | 411 |
412 MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); | 412 MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); |
413 MemOperand exponent_operand(MemOperand(input_reg, | 413 MemOperand exponent_operand(MemOperand(input_reg, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 __ cmpl(exponent_operand, Immediate(0)); | 465 __ cmpl(exponent_operand, Immediate(0)); |
466 } | 466 } |
467 __ cmovl(greater, result_reg, scratch1); | 467 __ cmovl(greater, result_reg, scratch1); |
468 | 468 |
469 // Restore registers | 469 // Restore registers |
470 __ bind(&done); | 470 __ bind(&done); |
471 if (stash_exponent_copy) { | 471 if (stash_exponent_copy) { |
472 __ addp(rsp, Immediate(kDoubleSize)); | 472 __ addp(rsp, Immediate(kDoubleSize)); |
473 } | 473 } |
474 if (!final_result_reg.is(result_reg)) { | 474 if (!final_result_reg.is(result_reg)) { |
475 ASSERT(final_result_reg.is(rcx)); | 475 DCHECK(final_result_reg.is(rcx)); |
476 __ movl(final_result_reg, result_reg); | 476 __ movl(final_result_reg, result_reg); |
477 } | 477 } |
478 __ popq(save_reg); | 478 __ popq(save_reg); |
479 __ popq(scratch1); | 479 __ popq(scratch1); |
480 __ ret(0); | 480 __ ret(0); |
481 } | 481 } |
482 | 482 |
483 | 483 |
484 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, | 484 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, |
485 Label* not_numbers) { | 485 Label* not_numbers) { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 // as heap number in rax. | 746 // as heap number in rax. |
747 __ bind(&done); | 747 __ bind(&done); |
748 __ AllocateHeapNumber(rax, rcx, &call_runtime); | 748 __ AllocateHeapNumber(rax, rcx, &call_runtime); |
749 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); | 749 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); |
750 __ IncrementCounter(counters->math_pow(), 1); | 750 __ IncrementCounter(counters->math_pow(), 1); |
751 __ ret(2 * kPointerSize); | 751 __ ret(2 * kPointerSize); |
752 } else { | 752 } else { |
753 __ bind(&call_runtime); | 753 __ bind(&call_runtime); |
754 // Move base to the correct argument register. Exponent is already in xmm1. | 754 // Move base to the correct argument register. Exponent is already in xmm1. |
755 __ movsd(xmm0, double_base); | 755 __ movsd(xmm0, double_base); |
756 ASSERT(double_exponent.is(xmm1)); | 756 DCHECK(double_exponent.is(xmm1)); |
757 { | 757 { |
758 AllowExternalCallThatCantCauseGC scope(masm); | 758 AllowExternalCallThatCantCauseGC scope(masm); |
759 __ PrepareCallCFunction(2); | 759 __ PrepareCallCFunction(2); |
760 __ CallCFunction( | 760 __ CallCFunction( |
761 ExternalReference::power_double_double_function(isolate()), 2); | 761 ExternalReference::power_double_double_function(isolate()), 2); |
762 } | 762 } |
763 // Return value is in xmm0. | 763 // Return value is in xmm0. |
764 __ movsd(double_result, xmm0); | 764 __ movsd(double_result, xmm0); |
765 | 765 |
766 __ bind(&done); | 766 __ bind(&done); |
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 // (11) Sliced string. Replace subject with parent. Go to (5a). | 1625 // (11) Sliced string. Replace subject with parent. Go to (5a). |
1626 // Load offset into r14 and replace subject string with parent. | 1626 // Load offset into r14 and replace subject string with parent. |
1627 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); | 1627 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
1628 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | 1628 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
1629 __ jmp(&check_underlying); | 1629 __ jmp(&check_underlying); |
1630 #endif // V8_INTERPRETED_REGEXP | 1630 #endif // V8_INTERPRETED_REGEXP |
1631 } | 1631 } |
1632 | 1632 |
1633 | 1633 |
1634 static int NegativeComparisonResult(Condition cc) { | 1634 static int NegativeComparisonResult(Condition cc) { |
1635 ASSERT(cc != equal); | 1635 DCHECK(cc != equal); |
1636 ASSERT((cc == less) || (cc == less_equal) | 1636 DCHECK((cc == less) || (cc == less_equal) |
1637 || (cc == greater) || (cc == greater_equal)); | 1637 || (cc == greater) || (cc == greater_equal)); |
1638 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 1638 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
1639 } | 1639 } |
1640 | 1640 |
1641 | 1641 |
1642 static void CheckInputType(MacroAssembler* masm, | 1642 static void CheckInputType(MacroAssembler* masm, |
1643 Register input, | 1643 Register input, |
1644 CompareIC::State expected, | 1644 CompareIC::State expected, |
1645 Label* fail) { | 1645 Label* fail) { |
1646 Label ok; | 1646 Label ok; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 __ j(parity_even, &unordered, Label::kNear); | 1816 __ j(parity_even, &unordered, Label::kNear); |
1817 // Return a result of -1, 0, or 1, based on EFLAGS. | 1817 // Return a result of -1, 0, or 1, based on EFLAGS. |
1818 __ setcc(above, rax); | 1818 __ setcc(above, rax); |
1819 __ setcc(below, rcx); | 1819 __ setcc(below, rcx); |
1820 __ subp(rax, rcx); | 1820 __ subp(rax, rcx); |
1821 __ ret(0); | 1821 __ ret(0); |
1822 | 1822 |
1823 // If one of the numbers was NaN, then the result is always false. | 1823 // If one of the numbers was NaN, then the result is always false. |
1824 // The cc is never not-equal. | 1824 // The cc is never not-equal. |
1825 __ bind(&unordered); | 1825 __ bind(&unordered); |
1826 ASSERT(cc != not_equal); | 1826 DCHECK(cc != not_equal); |
1827 if (cc == less || cc == less_equal) { | 1827 if (cc == less || cc == less_equal) { |
1828 __ Set(rax, 1); | 1828 __ Set(rax, 1); |
1829 } else { | 1829 } else { |
1830 __ Set(rax, -1); | 1830 __ Set(rax, -1); |
1831 } | 1831 } |
1832 __ ret(0); | 1832 __ ret(0); |
1833 | 1833 |
1834 // The number comparison code did not provide a valid result. | 1834 // The number comparison code did not provide a valid result. |
1835 __ bind(&non_number_comparison); | 1835 __ bind(&non_number_comparison); |
1836 | 1836 |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2458 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. | 2458 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. |
2459 // Pass argv and argc as two parameters. The arguments object will | 2459 // Pass argv and argc as two parameters. The arguments object will |
2460 // be created by stubs declared by DECLARE_RUNTIME_FUNCTION(). | 2460 // be created by stubs declared by DECLARE_RUNTIME_FUNCTION(). |
2461 if (result_size_ < 2) { | 2461 if (result_size_ < 2) { |
2462 // Pass a pointer to the Arguments object as the first argument. | 2462 // Pass a pointer to the Arguments object as the first argument. |
2463 // Return result in single register (rax). | 2463 // Return result in single register (rax). |
2464 __ movp(rcx, r14); // argc. | 2464 __ movp(rcx, r14); // argc. |
2465 __ movp(rdx, r15); // argv. | 2465 __ movp(rdx, r15); // argv. |
2466 __ Move(r8, ExternalReference::isolate_address(isolate())); | 2466 __ Move(r8, ExternalReference::isolate_address(isolate())); |
2467 } else { | 2467 } else { |
2468 ASSERT_EQ(2, result_size_); | 2468 DCHECK_EQ(2, result_size_); |
2469 // Pass a pointer to the result location as the first argument. | 2469 // Pass a pointer to the result location as the first argument. |
2470 __ leap(rcx, StackSpaceOperand(2)); | 2470 __ leap(rcx, StackSpaceOperand(2)); |
2471 // Pass a pointer to the Arguments object as the second argument. | 2471 // Pass a pointer to the Arguments object as the second argument. |
2472 __ movp(rdx, r14); // argc. | 2472 __ movp(rdx, r14); // argc. |
2473 __ movp(r8, r15); // argv. | 2473 __ movp(r8, r15); // argv. |
2474 __ Move(r9, ExternalReference::isolate_address(isolate())); | 2474 __ Move(r9, ExternalReference::isolate_address(isolate())); |
2475 } | 2475 } |
2476 | 2476 |
2477 #else // _WIN64 | 2477 #else // _WIN64 |
2478 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. | 2478 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. |
2479 __ movp(rdi, r14); // argc. | 2479 __ movp(rdi, r14); // argc. |
2480 __ movp(rsi, r15); // argv. | 2480 __ movp(rsi, r15); // argv. |
2481 __ Move(rdx, ExternalReference::isolate_address(isolate())); | 2481 __ Move(rdx, ExternalReference::isolate_address(isolate())); |
2482 #endif | 2482 #endif |
2483 __ call(rbx); | 2483 __ call(rbx); |
2484 // Result is in rax - do not destroy this register! | 2484 // Result is in rax - do not destroy this register! |
2485 | 2485 |
2486 #ifdef _WIN64 | 2486 #ifdef _WIN64 |
2487 // If return value is on the stack, pop it to registers. | 2487 // If return value is on the stack, pop it to registers. |
2488 if (result_size_ > 1) { | 2488 if (result_size_ > 1) { |
2489 ASSERT_EQ(2, result_size_); | 2489 DCHECK_EQ(2, result_size_); |
2490 // Read result values stored on stack. Result is stored | 2490 // Read result values stored on stack. Result is stored |
2491 // above the four argument mirror slots and the two | 2491 // above the four argument mirror slots and the two |
2492 // Arguments object slots. | 2492 // Arguments object slots. |
2493 __ movq(rax, Operand(rsp, 6 * kRegisterSize)); | 2493 __ movq(rax, Operand(rsp, 6 * kRegisterSize)); |
2494 __ movq(rdx, Operand(rsp, 7 * kRegisterSize)); | 2494 __ movq(rdx, Operand(rsp, 7 * kRegisterSize)); |
2495 } | 2495 } |
2496 #endif | 2496 #endif |
2497 | 2497 |
2498 // Runtime functions should not return 'the hole'. Allowing it to escape may | 2498 // Runtime functions should not return 'the hole'. Allowing it to escape may |
2499 // lead to crashes in the IC code later. | 2499 // lead to crashes in the IC code later. |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2753 kPointerSize == kInt64Size ? 0xBA49FF78 : 0xBA41FF78; | 2753 kPointerSize == kInt64Size ? 0xBA49FF78 : 0xBA41FF78; |
2754 // The last 4 bytes of the instruction sequence | 2754 // The last 4 bytes of the instruction sequence |
2755 // __ j(not_equal, &cache_miss); | 2755 // __ j(not_equal, &cache_miss); |
2756 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2756 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
2757 // before the offset of the hole value in the root array. | 2757 // before the offset of the hole value in the root array. |
2758 static const unsigned int kWordBeforeResultValue = | 2758 static const unsigned int kWordBeforeResultValue = |
2759 kPointerSize == kInt64Size ? 0x458B4906 : 0x458B4106; | 2759 kPointerSize == kInt64Size ? 0x458B4906 : 0x458B4106; |
2760 | 2760 |
2761 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; | 2761 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; |
2762 | 2762 |
2763 ASSERT_EQ(object.code(), InstanceofStub::left().code()); | 2763 DCHECK_EQ(object.code(), InstanceofStub::left().code()); |
2764 ASSERT_EQ(function.code(), InstanceofStub::right().code()); | 2764 DCHECK_EQ(function.code(), InstanceofStub::right().code()); |
2765 | 2765 |
2766 // Get the object and function - they are always both needed. | 2766 // Get the object and function - they are always both needed. |
2767 // Go slow case if the object is a smi. | 2767 // Go slow case if the object is a smi. |
2768 Label slow; | 2768 Label slow; |
2769 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, | 2769 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, |
2770 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 2770 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
2771 if (!HasArgsInRegisters()) { | 2771 if (!HasArgsInRegisters()) { |
2772 __ movp(object, args.GetArgumentOperand(0)); | 2772 __ movp(object, args.GetArgumentOperand(0)); |
2773 __ movp(function, args.GetArgumentOperand(1)); | 2773 __ movp(function, args.GetArgumentOperand(1)); |
2774 } | 2774 } |
(...skipping 30 matching lines...) Expand all Loading... |
2805 __ j(above, &slow); | 2805 __ j(above, &slow); |
2806 | 2806 |
2807 // Update the global instanceof or call site inlined cache with the current | 2807 // Update the global instanceof or call site inlined cache with the current |
2808 // map and function. The cached answer will be set when it is known below. | 2808 // map and function. The cached answer will be set when it is known below. |
2809 if (!HasCallSiteInlineCheck()) { | 2809 if (!HasCallSiteInlineCheck()) { |
2810 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); | 2810 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
2811 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); | 2811 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); |
2812 } else { | 2812 } else { |
2813 // The constants for the code patching are based on push instructions | 2813 // The constants for the code patching are based on push instructions |
2814 // at the call site. | 2814 // at the call site. |
2815 ASSERT(!HasArgsInRegisters()); | 2815 DCHECK(!HasArgsInRegisters()); |
2816 // Get return address and delta to inlined map check. | 2816 // Get return address and delta to inlined map check. |
2817 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); | 2817 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
2818 __ subp(kScratchRegister, args.GetArgumentOperand(2)); | 2818 __ subp(kScratchRegister, args.GetArgumentOperand(2)); |
2819 if (FLAG_debug_code) { | 2819 if (FLAG_debug_code) { |
2820 __ movl(scratch, Immediate(kWordBeforeMapCheckValue)); | 2820 __ movl(scratch, Immediate(kWordBeforeMapCheckValue)); |
2821 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), scratch); | 2821 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), scratch); |
2822 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); | 2822 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); |
2823 } | 2823 } |
2824 __ movp(kScratchRegister, | 2824 __ movp(kScratchRegister, |
2825 Operand(kScratchRegister, kOffsetToMapCheckValue)); | 2825 Operand(kScratchRegister, kOffsetToMapCheckValue)); |
(...skipping 22 matching lines...) Expand all Loading... |
2848 STATIC_ASSERT(kSmiTag == 0); | 2848 STATIC_ASSERT(kSmiTag == 0); |
2849 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); | 2849 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
2850 if (ReturnTrueFalseObject()) { | 2850 if (ReturnTrueFalseObject()) { |
2851 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 2851 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
2852 } | 2852 } |
2853 } else { | 2853 } else { |
2854 // Store offset of true in the root array at the inline check site. | 2854 // Store offset of true in the root array at the inline check site. |
2855 int true_offset = 0x100 + | 2855 int true_offset = 0x100 + |
2856 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; | 2856 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
2857 // Assert it is a 1-byte signed value. | 2857 // Assert it is a 1-byte signed value. |
2858 ASSERT(true_offset >= 0 && true_offset < 0x100); | 2858 DCHECK(true_offset >= 0 && true_offset < 0x100); |
2859 __ movl(rax, Immediate(true_offset)); | 2859 __ movl(rax, Immediate(true_offset)); |
2860 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); | 2860 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
2861 __ subp(kScratchRegister, args.GetArgumentOperand(2)); | 2861 __ subp(kScratchRegister, args.GetArgumentOperand(2)); |
2862 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 2862 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
2863 if (FLAG_debug_code) { | 2863 if (FLAG_debug_code) { |
2864 __ movl(rax, Immediate(kWordBeforeResultValue)); | 2864 __ movl(rax, Immediate(kWordBeforeResultValue)); |
2865 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 2865 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
2866 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2866 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
2867 } | 2867 } |
2868 if (!ReturnTrueFalseObject()) { | 2868 if (!ReturnTrueFalseObject()) { |
2869 __ Set(rax, 0); | 2869 __ Set(rax, 0); |
2870 } | 2870 } |
2871 } | 2871 } |
2872 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * | 2872 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * |
2873 kPointerSize); | 2873 kPointerSize); |
2874 | 2874 |
2875 __ bind(&is_not_instance); | 2875 __ bind(&is_not_instance); |
2876 if (!HasCallSiteInlineCheck()) { | 2876 if (!HasCallSiteInlineCheck()) { |
2877 // We have to store a non-zero value in the cache. | 2877 // We have to store a non-zero value in the cache. |
2878 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); | 2878 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); |
2879 if (ReturnTrueFalseObject()) { | 2879 if (ReturnTrueFalseObject()) { |
2880 __ LoadRoot(rax, Heap::kFalseValueRootIndex); | 2880 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
2881 } | 2881 } |
2882 } else { | 2882 } else { |
2883 // Store offset of false in the root array at the inline check site. | 2883 // Store offset of false in the root array at the inline check site. |
2884 int false_offset = 0x100 + | 2884 int false_offset = 0x100 + |
2885 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; | 2885 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
2886 // Assert it is a 1-byte signed value. | 2886 // Assert it is a 1-byte signed value. |
2887 ASSERT(false_offset >= 0 && false_offset < 0x100); | 2887 DCHECK(false_offset >= 0 && false_offset < 0x100); |
2888 __ movl(rax, Immediate(false_offset)); | 2888 __ movl(rax, Immediate(false_offset)); |
2889 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); | 2889 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
2890 __ subp(kScratchRegister, args.GetArgumentOperand(2)); | 2890 __ subp(kScratchRegister, args.GetArgumentOperand(2)); |
2891 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 2891 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
2892 if (FLAG_debug_code) { | 2892 if (FLAG_debug_code) { |
2893 __ movl(rax, Immediate(kWordBeforeResultValue)); | 2893 __ movl(rax, Immediate(kWordBeforeResultValue)); |
2894 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 2894 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
2895 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2895 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
2896 } | 2896 } |
2897 } | 2897 } |
2898 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * | 2898 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * |
2899 kPointerSize); | 2899 kPointerSize); |
2900 | 2900 |
2901 // Slow-case: Go through the JavaScript implementation. | 2901 // Slow-case: Go through the JavaScript implementation. |
2902 __ bind(&slow); | 2902 __ bind(&slow); |
2903 if (!ReturnTrueFalseObject()) { | 2903 if (!ReturnTrueFalseObject()) { |
2904 // Tail call the builtin which returns 0 or 1. | 2904 // Tail call the builtin which returns 0 or 1. |
2905 ASSERT(!HasArgsInRegisters()); | 2905 DCHECK(!HasArgsInRegisters()); |
2906 if (HasCallSiteInlineCheck()) { | 2906 if (HasCallSiteInlineCheck()) { |
2907 // Remove extra value from the stack. | 2907 // Remove extra value from the stack. |
2908 __ PopReturnAddressTo(rcx); | 2908 __ PopReturnAddressTo(rcx); |
2909 __ Pop(rax); | 2909 __ Pop(rax); |
2910 __ PushReturnAddressFrom(rcx); | 2910 __ PushReturnAddressFrom(rcx); |
2911 } | 2911 } |
2912 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 2912 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
2913 } else { | 2913 } else { |
2914 // Call the builtin and convert 0/1 to true/false. | 2914 // Call the builtin and convert 0/1 to true/false. |
2915 { | 2915 { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2988 __ CheckMap(index_, | 2988 __ CheckMap(index_, |
2989 factory->heap_number_map(), | 2989 factory->heap_number_map(), |
2990 index_not_number_, | 2990 index_not_number_, |
2991 DONT_DO_SMI_CHECK); | 2991 DONT_DO_SMI_CHECK); |
2992 call_helper.BeforeCall(masm); | 2992 call_helper.BeforeCall(masm); |
2993 __ Push(object_); | 2993 __ Push(object_); |
2994 __ Push(index_); // Consumed by runtime conversion function. | 2994 __ Push(index_); // Consumed by runtime conversion function. |
2995 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 2995 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
2996 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 2996 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); |
2997 } else { | 2997 } else { |
2998 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 2998 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
2999 // NumberToSmi discards numbers that are not exact integers. | 2999 // NumberToSmi discards numbers that are not exact integers. |
3000 __ CallRuntime(Runtime::kNumberToSmi, 1); | 3000 __ CallRuntime(Runtime::kNumberToSmi, 1); |
3001 } | 3001 } |
3002 if (!index_.is(rax)) { | 3002 if (!index_.is(rax)) { |
3003 // Save the conversion result before the pop instructions below | 3003 // Save the conversion result before the pop instructions below |
3004 // have a chance to overwrite it. | 3004 // have a chance to overwrite it. |
3005 __ movp(index_, rax); | 3005 __ movp(index_, rax); |
3006 } | 3006 } |
3007 __ Pop(object_); | 3007 __ Pop(object_); |
3008 // Reload the instance type. | 3008 // Reload the instance type. |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3589 } | 3589 } |
3590 | 3590 |
3591 // Tail call into the stub that handles binary operations with allocation | 3591 // Tail call into the stub that handles binary operations with allocation |
3592 // sites. | 3592 // sites. |
3593 BinaryOpWithAllocationSiteStub stub(isolate(), state_); | 3593 BinaryOpWithAllocationSiteStub stub(isolate(), state_); |
3594 __ TailCallStub(&stub); | 3594 __ TailCallStub(&stub); |
3595 } | 3595 } |
3596 | 3596 |
3597 | 3597 |
3598 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3598 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
3599 ASSERT(state_ == CompareIC::SMI); | 3599 DCHECK(state_ == CompareIC::SMI); |
3600 Label miss; | 3600 Label miss; |
3601 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); | 3601 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); |
3602 | 3602 |
3603 if (GetCondition() == equal) { | 3603 if (GetCondition() == equal) { |
3604 // For equality we do not care about the sign of the result. | 3604 // For equality we do not care about the sign of the result. |
3605 __ subp(rax, rdx); | 3605 __ subp(rax, rdx); |
3606 } else { | 3606 } else { |
3607 Label done; | 3607 Label done; |
3608 __ subp(rdx, rax); | 3608 __ subp(rdx, rax); |
3609 __ j(no_overflow, &done, Label::kNear); | 3609 __ j(no_overflow, &done, Label::kNear); |
3610 // Correct sign of result in case of overflow. | 3610 // Correct sign of result in case of overflow. |
3611 __ notp(rdx); | 3611 __ notp(rdx); |
3612 __ bind(&done); | 3612 __ bind(&done); |
3613 __ movp(rax, rdx); | 3613 __ movp(rax, rdx); |
3614 } | 3614 } |
3615 __ ret(0); | 3615 __ ret(0); |
3616 | 3616 |
3617 __ bind(&miss); | 3617 __ bind(&miss); |
3618 GenerateMiss(masm); | 3618 GenerateMiss(masm); |
3619 } | 3619 } |
3620 | 3620 |
3621 | 3621 |
3622 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3622 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { |
3623 ASSERT(state_ == CompareIC::NUMBER); | 3623 DCHECK(state_ == CompareIC::NUMBER); |
3624 | 3624 |
3625 Label generic_stub; | 3625 Label generic_stub; |
3626 Label unordered, maybe_undefined1, maybe_undefined2; | 3626 Label unordered, maybe_undefined1, maybe_undefined2; |
3627 Label miss; | 3627 Label miss; |
3628 | 3628 |
3629 if (left_ == CompareIC::SMI) { | 3629 if (left_ == CompareIC::SMI) { |
3630 __ JumpIfNotSmi(rdx, &miss); | 3630 __ JumpIfNotSmi(rdx, &miss); |
3631 } | 3631 } |
3632 if (right_ == CompareIC::SMI) { | 3632 if (right_ == CompareIC::SMI) { |
3633 __ JumpIfNotSmi(rax, &miss); | 3633 __ JumpIfNotSmi(rax, &miss); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3690 __ Cmp(rdx, isolate()->factory()->undefined_value()); | 3690 __ Cmp(rdx, isolate()->factory()->undefined_value()); |
3691 __ j(equal, &unordered); | 3691 __ j(equal, &unordered); |
3692 } | 3692 } |
3693 | 3693 |
3694 __ bind(&miss); | 3694 __ bind(&miss); |
3695 GenerateMiss(masm); | 3695 GenerateMiss(masm); |
3696 } | 3696 } |
3697 | 3697 |
3698 | 3698 |
3699 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3699 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3700 ASSERT(state_ == CompareIC::INTERNALIZED_STRING); | 3700 DCHECK(state_ == CompareIC::INTERNALIZED_STRING); |
3701 ASSERT(GetCondition() == equal); | 3701 DCHECK(GetCondition() == equal); |
3702 | 3702 |
3703 // Registers containing left and right operands respectively. | 3703 // Registers containing left and right operands respectively. |
3704 Register left = rdx; | 3704 Register left = rdx; |
3705 Register right = rax; | 3705 Register right = rax; |
3706 Register tmp1 = rcx; | 3706 Register tmp1 = rcx; |
3707 Register tmp2 = rbx; | 3707 Register tmp2 = rbx; |
3708 | 3708 |
3709 // Check that both operands are heap objects. | 3709 // Check that both operands are heap objects. |
3710 Label miss; | 3710 Label miss; |
3711 Condition cond = masm->CheckEitherSmi(left, right, tmp1); | 3711 Condition cond = masm->CheckEitherSmi(left, right, tmp1); |
3712 __ j(cond, &miss, Label::kNear); | 3712 __ j(cond, &miss, Label::kNear); |
3713 | 3713 |
3714 // Check that both operands are internalized strings. | 3714 // Check that both operands are internalized strings. |
3715 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); | 3715 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); |
3716 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); | 3716 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); |
3717 __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); | 3717 __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); |
3718 __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); | 3718 __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); |
3719 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 3719 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
3720 __ orp(tmp1, tmp2); | 3720 __ orp(tmp1, tmp2); |
3721 __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 3721 __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
3722 __ j(not_zero, &miss, Label::kNear); | 3722 __ j(not_zero, &miss, Label::kNear); |
3723 | 3723 |
3724 // Internalized strings are compared by identity. | 3724 // Internalized strings are compared by identity. |
3725 Label done; | 3725 Label done; |
3726 __ cmpp(left, right); | 3726 __ cmpp(left, right); |
3727 // Make sure rax is non-zero. At this point input operands are | 3727 // Make sure rax is non-zero. At this point input operands are |
3728 // guaranteed to be non-zero. | 3728 // guaranteed to be non-zero. |
3729 ASSERT(right.is(rax)); | 3729 DCHECK(right.is(rax)); |
3730 __ j(not_equal, &done, Label::kNear); | 3730 __ j(not_equal, &done, Label::kNear); |
3731 STATIC_ASSERT(EQUAL == 0); | 3731 STATIC_ASSERT(EQUAL == 0); |
3732 STATIC_ASSERT(kSmiTag == 0); | 3732 STATIC_ASSERT(kSmiTag == 0); |
3733 __ Move(rax, Smi::FromInt(EQUAL)); | 3733 __ Move(rax, Smi::FromInt(EQUAL)); |
3734 __ bind(&done); | 3734 __ bind(&done); |
3735 __ ret(0); | 3735 __ ret(0); |
3736 | 3736 |
3737 __ bind(&miss); | 3737 __ bind(&miss); |
3738 GenerateMiss(masm); | 3738 GenerateMiss(masm); |
3739 } | 3739 } |
3740 | 3740 |
3741 | 3741 |
3742 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3742 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { |
3743 ASSERT(state_ == CompareIC::UNIQUE_NAME); | 3743 DCHECK(state_ == CompareIC::UNIQUE_NAME); |
3744 ASSERT(GetCondition() == equal); | 3744 DCHECK(GetCondition() == equal); |
3745 | 3745 |
3746 // Registers containing left and right operands respectively. | 3746 // Registers containing left and right operands respectively. |
3747 Register left = rdx; | 3747 Register left = rdx; |
3748 Register right = rax; | 3748 Register right = rax; |
3749 Register tmp1 = rcx; | 3749 Register tmp1 = rcx; |
3750 Register tmp2 = rbx; | 3750 Register tmp2 = rbx; |
3751 | 3751 |
3752 // Check that both operands are heap objects. | 3752 // Check that both operands are heap objects. |
3753 Label miss; | 3753 Label miss; |
3754 Condition cond = masm->CheckEitherSmi(left, right, tmp1); | 3754 Condition cond = masm->CheckEitherSmi(left, right, tmp1); |
3755 __ j(cond, &miss, Label::kNear); | 3755 __ j(cond, &miss, Label::kNear); |
3756 | 3756 |
3757 // Check that both operands are unique names. This leaves the instance | 3757 // Check that both operands are unique names. This leaves the instance |
3758 // types loaded in tmp1 and tmp2. | 3758 // types loaded in tmp1 and tmp2. |
3759 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); | 3759 __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset)); |
3760 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); | 3760 __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset)); |
3761 __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); | 3761 __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); |
3762 __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); | 3762 __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); |
3763 | 3763 |
3764 __ JumpIfNotUniqueName(tmp1, &miss, Label::kNear); | 3764 __ JumpIfNotUniqueName(tmp1, &miss, Label::kNear); |
3765 __ JumpIfNotUniqueName(tmp2, &miss, Label::kNear); | 3765 __ JumpIfNotUniqueName(tmp2, &miss, Label::kNear); |
3766 | 3766 |
3767 // Unique names are compared by identity. | 3767 // Unique names are compared by identity. |
3768 Label done; | 3768 Label done; |
3769 __ cmpp(left, right); | 3769 __ cmpp(left, right); |
3770 // Make sure rax is non-zero. At this point input operands are | 3770 // Make sure rax is non-zero. At this point input operands are |
3771 // guaranteed to be non-zero. | 3771 // guaranteed to be non-zero. |
3772 ASSERT(right.is(rax)); | 3772 DCHECK(right.is(rax)); |
3773 __ j(not_equal, &done, Label::kNear); | 3773 __ j(not_equal, &done, Label::kNear); |
3774 STATIC_ASSERT(EQUAL == 0); | 3774 STATIC_ASSERT(EQUAL == 0); |
3775 STATIC_ASSERT(kSmiTag == 0); | 3775 STATIC_ASSERT(kSmiTag == 0); |
3776 __ Move(rax, Smi::FromInt(EQUAL)); | 3776 __ Move(rax, Smi::FromInt(EQUAL)); |
3777 __ bind(&done); | 3777 __ bind(&done); |
3778 __ ret(0); | 3778 __ ret(0); |
3779 | 3779 |
3780 __ bind(&miss); | 3780 __ bind(&miss); |
3781 GenerateMiss(masm); | 3781 GenerateMiss(masm); |
3782 } | 3782 } |
3783 | 3783 |
3784 | 3784 |
3785 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3785 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { |
3786 ASSERT(state_ == CompareIC::STRING); | 3786 DCHECK(state_ == CompareIC::STRING); |
3787 Label miss; | 3787 Label miss; |
3788 | 3788 |
3789 bool equality = Token::IsEqualityOp(op_); | 3789 bool equality = Token::IsEqualityOp(op_); |
3790 | 3790 |
3791 // Registers containing left and right operands respectively. | 3791 // Registers containing left and right operands respectively. |
3792 Register left = rdx; | 3792 Register left = rdx; |
3793 Register right = rax; | 3793 Register right = rax; |
3794 Register tmp1 = rcx; | 3794 Register tmp1 = rcx; |
3795 Register tmp2 = rbx; | 3795 Register tmp2 = rbx; |
3796 Register tmp3 = rdi; | 3796 Register tmp3 = rdi; |
(...skipping 30 matching lines...) Expand all Loading... |
3827 // because we already know they are not identical. We also know they are both | 3827 // because we already know they are not identical. We also know they are both |
3828 // strings. | 3828 // strings. |
3829 if (equality) { | 3829 if (equality) { |
3830 Label do_compare; | 3830 Label do_compare; |
3831 STATIC_ASSERT(kInternalizedTag == 0); | 3831 STATIC_ASSERT(kInternalizedTag == 0); |
3832 __ orp(tmp1, tmp2); | 3832 __ orp(tmp1, tmp2); |
3833 __ testb(tmp1, Immediate(kIsNotInternalizedMask)); | 3833 __ testb(tmp1, Immediate(kIsNotInternalizedMask)); |
3834 __ j(not_zero, &do_compare, Label::kNear); | 3834 __ j(not_zero, &do_compare, Label::kNear); |
3835 // Make sure rax is non-zero. At this point input operands are | 3835 // Make sure rax is non-zero. At this point input operands are |
3836 // guaranteed to be non-zero. | 3836 // guaranteed to be non-zero. |
3837 ASSERT(right.is(rax)); | 3837 DCHECK(right.is(rax)); |
3838 __ ret(0); | 3838 __ ret(0); |
3839 __ bind(&do_compare); | 3839 __ bind(&do_compare); |
3840 } | 3840 } |
3841 | 3841 |
3842 // Check that both strings are sequential ASCII. | 3842 // Check that both strings are sequential ASCII. |
3843 Label runtime; | 3843 Label runtime; |
3844 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime); | 3844 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime); |
3845 | 3845 |
3846 // Compare flat ASCII strings. Returns when done. | 3846 // Compare flat ASCII strings. Returns when done. |
3847 if (equality) { | 3847 if (equality) { |
(...skipping 15 matching lines...) Expand all Loading... |
3863 } else { | 3863 } else { |
3864 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3864 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3865 } | 3865 } |
3866 | 3866 |
3867 __ bind(&miss); | 3867 __ bind(&miss); |
3868 GenerateMiss(masm); | 3868 GenerateMiss(masm); |
3869 } | 3869 } |
3870 | 3870 |
3871 | 3871 |
3872 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3872 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
3873 ASSERT(state_ == CompareIC::OBJECT); | 3873 DCHECK(state_ == CompareIC::OBJECT); |
3874 Label miss; | 3874 Label miss; |
3875 Condition either_smi = masm->CheckEitherSmi(rdx, rax); | 3875 Condition either_smi = masm->CheckEitherSmi(rdx, rax); |
3876 __ j(either_smi, &miss, Label::kNear); | 3876 __ j(either_smi, &miss, Label::kNear); |
3877 | 3877 |
3878 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); | 3878 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); |
3879 __ j(not_equal, &miss, Label::kNear); | 3879 __ j(not_equal, &miss, Label::kNear); |
3880 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); | 3880 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); |
3881 __ j(not_equal, &miss, Label::kNear); | 3881 __ j(not_equal, &miss, Label::kNear); |
3882 | 3882 |
3883 ASSERT(GetCondition() == equal); | 3883 DCHECK(GetCondition() == equal); |
3884 __ subp(rax, rdx); | 3884 __ subp(rax, rdx); |
3885 __ ret(0); | 3885 __ ret(0); |
3886 | 3886 |
3887 __ bind(&miss); | 3887 __ bind(&miss); |
3888 GenerateMiss(masm); | 3888 GenerateMiss(masm); |
3889 } | 3889 } |
3890 | 3890 |
3891 | 3891 |
3892 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3892 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { |
3893 Label miss; | 3893 Label miss; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3933 __ jmp(rdi); | 3933 __ jmp(rdi); |
3934 } | 3934 } |
3935 | 3935 |
3936 | 3936 |
3937 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, | 3937 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
3938 Label* miss, | 3938 Label* miss, |
3939 Label* done, | 3939 Label* done, |
3940 Register properties, | 3940 Register properties, |
3941 Handle<Name> name, | 3941 Handle<Name> name, |
3942 Register r0) { | 3942 Register r0) { |
3943 ASSERT(name->IsUniqueName()); | 3943 DCHECK(name->IsUniqueName()); |
3944 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 3944 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
3945 // not equal to the name and kProbes-th slot is not used (its name is the | 3945 // not equal to the name and kProbes-th slot is not used (its name is the |
3946 // undefined value), it guarantees the hash table doesn't contain the | 3946 // undefined value), it guarantees the hash table doesn't contain the |
3947 // property. It's true even if some slots represent deleted properties | 3947 // property. It's true even if some slots represent deleted properties |
3948 // (their names are the hole value). | 3948 // (their names are the hole value). |
3949 for (int i = 0; i < kInlinedProbes; i++) { | 3949 for (int i = 0; i < kInlinedProbes; i++) { |
3950 // r0 points to properties hash. | 3950 // r0 points to properties hash. |
3951 // Compute the masked index: (hash + i + i * i) & mask. | 3951 // Compute the masked index: (hash + i + i * i) & mask. |
3952 Register index = r0; | 3952 Register index = r0; |
3953 // Capacity is smi 2^n. | 3953 // Capacity is smi 2^n. |
3954 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); | 3954 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); |
3955 __ decl(index); | 3955 __ decl(index); |
3956 __ andp(index, | 3956 __ andp(index, |
3957 Immediate(name->Hash() + NameDictionary::GetProbeOffset(i))); | 3957 Immediate(name->Hash() + NameDictionary::GetProbeOffset(i))); |
3958 | 3958 |
3959 // Scale the index by multiplying by the entry size. | 3959 // Scale the index by multiplying by the entry size. |
3960 ASSERT(NameDictionary::kEntrySize == 3); | 3960 DCHECK(NameDictionary::kEntrySize == 3); |
3961 __ leap(index, Operand(index, index, times_2, 0)); // index *= 3. | 3961 __ leap(index, Operand(index, index, times_2, 0)); // index *= 3. |
3962 | 3962 |
3963 Register entity_name = r0; | 3963 Register entity_name = r0; |
3964 // Having undefined at this place means the name is not contained. | 3964 // Having undefined at this place means the name is not contained. |
3965 ASSERT_EQ(kSmiTagSize, 1); | 3965 DCHECK_EQ(kSmiTagSize, 1); |
3966 __ movp(entity_name, Operand(properties, | 3966 __ movp(entity_name, Operand(properties, |
3967 index, | 3967 index, |
3968 times_pointer_size, | 3968 times_pointer_size, |
3969 kElementsStartOffset - kHeapObjectTag)); | 3969 kElementsStartOffset - kHeapObjectTag)); |
3970 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); | 3970 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); |
3971 __ j(equal, done); | 3971 __ j(equal, done); |
3972 | 3972 |
3973 // Stop if found the property. | 3973 // Stop if found the property. |
3974 __ Cmp(entity_name, Handle<Name>(name)); | 3974 __ Cmp(entity_name, Handle<Name>(name)); |
3975 __ j(equal, miss); | 3975 __ j(equal, miss); |
(...skipping 25 matching lines...) Expand all Loading... |
4001 // |done| label if a property with the given name is found leaving the | 4001 // |done| label if a property with the given name is found leaving the |
4002 // index into the dictionary in |r1|. Jump to the |miss| label | 4002 // index into the dictionary in |r1|. Jump to the |miss| label |
4003 // otherwise. | 4003 // otherwise. |
4004 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, | 4004 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, |
4005 Label* miss, | 4005 Label* miss, |
4006 Label* done, | 4006 Label* done, |
4007 Register elements, | 4007 Register elements, |
4008 Register name, | 4008 Register name, |
4009 Register r0, | 4009 Register r0, |
4010 Register r1) { | 4010 Register r1) { |
4011 ASSERT(!elements.is(r0)); | 4011 DCHECK(!elements.is(r0)); |
4012 ASSERT(!elements.is(r1)); | 4012 DCHECK(!elements.is(r1)); |
4013 ASSERT(!name.is(r0)); | 4013 DCHECK(!name.is(r0)); |
4014 ASSERT(!name.is(r1)); | 4014 DCHECK(!name.is(r1)); |
4015 | 4015 |
4016 __ AssertName(name); | 4016 __ AssertName(name); |
4017 | 4017 |
4018 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); | 4018 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); |
4019 __ decl(r0); | 4019 __ decl(r0); |
4020 | 4020 |
4021 for (int i = 0; i < kInlinedProbes; i++) { | 4021 for (int i = 0; i < kInlinedProbes; i++) { |
4022 // Compute the masked index: (hash + i + i * i) & mask. | 4022 // Compute the masked index: (hash + i + i * i) & mask. |
4023 __ movl(r1, FieldOperand(name, Name::kHashFieldOffset)); | 4023 __ movl(r1, FieldOperand(name, Name::kHashFieldOffset)); |
4024 __ shrl(r1, Immediate(Name::kHashShift)); | 4024 __ shrl(r1, Immediate(Name::kHashShift)); |
4025 if (i > 0) { | 4025 if (i > 0) { |
4026 __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i))); | 4026 __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i))); |
4027 } | 4027 } |
4028 __ andp(r1, r0); | 4028 __ andp(r1, r0); |
4029 | 4029 |
4030 // Scale the index by multiplying by the entry size. | 4030 // Scale the index by multiplying by the entry size. |
4031 ASSERT(NameDictionary::kEntrySize == 3); | 4031 DCHECK(NameDictionary::kEntrySize == 3); |
4032 __ leap(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 | 4032 __ leap(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 |
4033 | 4033 |
4034 // Check if the key is identical to the name. | 4034 // Check if the key is identical to the name. |
4035 __ cmpp(name, Operand(elements, r1, times_pointer_size, | 4035 __ cmpp(name, Operand(elements, r1, times_pointer_size, |
4036 kElementsStartOffset - kHeapObjectTag)); | 4036 kElementsStartOffset - kHeapObjectTag)); |
4037 __ j(equal, done); | 4037 __ j(equal, done); |
4038 } | 4038 } |
4039 | 4039 |
4040 NameDictionaryLookupStub stub(masm->isolate(), elements, r0, r1, | 4040 NameDictionaryLookupStub stub(masm->isolate(), elements, r0, r1, |
4041 POSITIVE_LOOKUP); | 4041 POSITIVE_LOOKUP); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4083 kPointerSize); | 4083 kPointerSize); |
4084 for (int i = kInlinedProbes; i < kTotalProbes; i++) { | 4084 for (int i = kInlinedProbes; i < kTotalProbes; i++) { |
4085 // Compute the masked index: (hash + i + i * i) & mask. | 4085 // Compute the masked index: (hash + i + i * i) & mask. |
4086 __ movp(scratch, args.GetArgumentOperand(1)); | 4086 __ movp(scratch, args.GetArgumentOperand(1)); |
4087 if (i > 0) { | 4087 if (i > 0) { |
4088 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); | 4088 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); |
4089 } | 4089 } |
4090 __ andp(scratch, Operand(rsp, 0)); | 4090 __ andp(scratch, Operand(rsp, 0)); |
4091 | 4091 |
4092 // Scale the index by multiplying by the entry size. | 4092 // Scale the index by multiplying by the entry size. |
4093 ASSERT(NameDictionary::kEntrySize == 3); | 4093 DCHECK(NameDictionary::kEntrySize == 3); |
4094 __ leap(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. | 4094 __ leap(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. |
4095 | 4095 |
4096 // Having undefined at this place means the name is not contained. | 4096 // Having undefined at this place means the name is not contained. |
4097 __ movp(scratch, Operand(dictionary_, | 4097 __ movp(scratch, Operand(dictionary_, |
4098 index_, | 4098 index_, |
4099 times_pointer_size, | 4099 times_pointer_size, |
4100 kElementsStartOffset - kHeapObjectTag)); | 4100 kElementsStartOffset - kHeapObjectTag)); |
4101 | 4101 |
4102 __ Cmp(scratch, isolate()->factory()->undefined_value()); | 4102 __ Cmp(scratch, isolate()->factory()->undefined_value()); |
4103 __ j(equal, ¬_in_dictionary); | 4103 __ j(equal, ¬_in_dictionary); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4225 InformIncrementalMarker(masm); | 4225 InformIncrementalMarker(masm); |
4226 regs_.Restore(masm); | 4226 regs_.Restore(masm); |
4227 __ ret(0); | 4227 __ ret(0); |
4228 } | 4228 } |
4229 | 4229 |
4230 | 4230 |
4231 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { | 4231 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { |
4232 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 4232 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); |
4233 Register address = | 4233 Register address = |
4234 arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); | 4234 arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); |
4235 ASSERT(!address.is(regs_.object())); | 4235 DCHECK(!address.is(regs_.object())); |
4236 ASSERT(!address.is(arg_reg_1)); | 4236 DCHECK(!address.is(arg_reg_1)); |
4237 __ Move(address, regs_.address()); | 4237 __ Move(address, regs_.address()); |
4238 __ Move(arg_reg_1, regs_.object()); | 4238 __ Move(arg_reg_1, regs_.object()); |
4239 // TODO(gc) Can we just set address arg2 in the beginning? | 4239 // TODO(gc) Can we just set address arg2 in the beginning? |
4240 __ Move(arg_reg_2, address); | 4240 __ Move(arg_reg_2, address); |
4241 __ LoadAddress(arg_reg_3, | 4241 __ LoadAddress(arg_reg_3, |
4242 ExternalReference::isolate_address(isolate())); | 4242 ExternalReference::isolate_address(isolate())); |
4243 int argument_count = 3; | 4243 int argument_count = 3; |
4244 | 4244 |
4245 AllowExternalCallThatCantCauseGC scope(masm); | 4245 AllowExternalCallThatCantCauseGC scope(masm); |
4246 __ PrepareCallCFunction(argument_count); | 4246 __ PrepareCallCFunction(argument_count); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4517 // rax - number of arguments | 4517 // rax - number of arguments |
4518 // rdi - constructor? | 4518 // rdi - constructor? |
4519 // rsp[0] - return address | 4519 // rsp[0] - return address |
4520 // rsp[8] - last argument | 4520 // rsp[8] - last argument |
4521 Handle<Object> undefined_sentinel( | 4521 Handle<Object> undefined_sentinel( |
4522 masm->isolate()->heap()->undefined_value(), | 4522 masm->isolate()->heap()->undefined_value(), |
4523 masm->isolate()); | 4523 masm->isolate()); |
4524 | 4524 |
4525 Label normal_sequence; | 4525 Label normal_sequence; |
4526 if (mode == DONT_OVERRIDE) { | 4526 if (mode == DONT_OVERRIDE) { |
4527 ASSERT(FAST_SMI_ELEMENTS == 0); | 4527 DCHECK(FAST_SMI_ELEMENTS == 0); |
4528 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 4528 DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1); |
4529 ASSERT(FAST_ELEMENTS == 2); | 4529 DCHECK(FAST_ELEMENTS == 2); |
4530 ASSERT(FAST_HOLEY_ELEMENTS == 3); | 4530 DCHECK(FAST_HOLEY_ELEMENTS == 3); |
4531 ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 4531 DCHECK(FAST_DOUBLE_ELEMENTS == 4); |
4532 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 4532 DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
4533 | 4533 |
4534 // is the low bit set? If so, we are holey and that is good. | 4534 // is the low bit set? If so, we are holey and that is good. |
4535 __ testb(rdx, Immediate(1)); | 4535 __ testb(rdx, Immediate(1)); |
4536 __ j(not_zero, &normal_sequence); | 4536 __ j(not_zero, &normal_sequence); |
4537 } | 4537 } |
4538 | 4538 |
4539 // look at the first argument | 4539 // look at the first argument |
4540 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 4540 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
4541 __ movp(rcx, args.GetArgumentOperand(0)); | 4541 __ movp(rcx, args.GetArgumentOperand(0)); |
4542 __ testp(rcx, rcx); | 4542 __ testp(rcx, rcx); |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4881 #if defined(__MINGW64__) || defined(_WIN64) | 4881 #if defined(__MINGW64__) || defined(_WIN64) |
4882 Register arguments_arg = rcx; | 4882 Register arguments_arg = rcx; |
4883 Register callback_arg = rdx; | 4883 Register callback_arg = rdx; |
4884 #else | 4884 #else |
4885 Register arguments_arg = rdi; | 4885 Register arguments_arg = rdi; |
4886 Register callback_arg = rsi; | 4886 Register callback_arg = rsi; |
4887 #endif | 4887 #endif |
4888 | 4888 |
4889 // It's okay if api_function_address == callback_arg | 4889 // It's okay if api_function_address == callback_arg |
4890 // but not arguments_arg | 4890 // but not arguments_arg |
4891 ASSERT(!api_function_address.is(arguments_arg)); | 4891 DCHECK(!api_function_address.is(arguments_arg)); |
4892 | 4892 |
4893 // v8::InvocationCallback's argument. | 4893 // v8::InvocationCallback's argument. |
4894 __ leap(arguments_arg, StackSpaceOperand(0)); | 4894 __ leap(arguments_arg, StackSpaceOperand(0)); |
4895 | 4895 |
4896 ExternalReference thunk_ref = | 4896 ExternalReference thunk_ref = |
4897 ExternalReference::invoke_function_callback(isolate()); | 4897 ExternalReference::invoke_function_callback(isolate()); |
4898 | 4898 |
4899 // Accessor for FunctionCallbackInfo and first js arg. | 4899 // Accessor for FunctionCallbackInfo and first js arg. |
4900 StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, | 4900 StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, |
4901 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 4901 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4951 | 4951 |
4952 // The context register (rsi) has been saved in PrepareCallApiFunction and | 4952 // The context register (rsi) has been saved in PrepareCallApiFunction and |
4953 // could be used to pass arguments. | 4953 // could be used to pass arguments. |
4954 __ leap(accessor_info_arg, StackSpaceOperand(0)); | 4954 __ leap(accessor_info_arg, StackSpaceOperand(0)); |
4955 | 4955 |
4956 ExternalReference thunk_ref = | 4956 ExternalReference thunk_ref = |
4957 ExternalReference::invoke_accessor_getter_callback(isolate()); | 4957 ExternalReference::invoke_accessor_getter_callback(isolate()); |
4958 | 4958 |
4959 // It's okay if api_function_address == getter_arg | 4959 // It's okay if api_function_address == getter_arg |
4960 // but not accessor_info_arg or name_arg | 4960 // but not accessor_info_arg or name_arg |
4961 ASSERT(!api_function_address.is(accessor_info_arg) && | 4961 DCHECK(!api_function_address.is(accessor_info_arg) && |
4962 !api_function_address.is(name_arg)); | 4962 !api_function_address.is(name_arg)); |
4963 | 4963 |
4964 // The name handler is counted as an argument. | 4964 // The name handler is counted as an argument. |
4965 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); | 4965 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); |
4966 Operand return_value_operand = args.GetArgumentOperand( | 4966 Operand return_value_operand = args.GetArgumentOperand( |
4967 PropertyCallbackArguments::kArgsLength - 1 - | 4967 PropertyCallbackArguments::kArgsLength - 1 - |
4968 PropertyCallbackArguments::kReturnValueOffset); | 4968 PropertyCallbackArguments::kReturnValueOffset); |
4969 __ CallApiFunctionAndReturn(api_function_address, | 4969 __ CallApiFunctionAndReturn(api_function_address, |
4970 thunk_ref, | 4970 thunk_ref, |
4971 getter_arg, | 4971 getter_arg, |
4972 kStackSpace, | 4972 kStackSpace, |
4973 return_value_operand, | 4973 return_value_operand, |
4974 NULL); | 4974 NULL); |
4975 } | 4975 } |
4976 | 4976 |
4977 | 4977 |
4978 #undef __ | 4978 #undef __ |
4979 | 4979 |
4980 } } // namespace v8::internal | 4980 } } // namespace v8::internal |
4981 | 4981 |
4982 #endif // V8_TARGET_ARCH_X64 | 4982 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |