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 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 const XMMRegister double_base = xmm2; | 522 const XMMRegister double_base = xmm2; |
523 const XMMRegister double_exponent = xmm1; | 523 const XMMRegister double_exponent = xmm1; |
524 const XMMRegister double_scratch = xmm4; | 524 const XMMRegister double_scratch = xmm4; |
525 | 525 |
526 Label call_runtime, done, exponent_not_smi, int_exponent; | 526 Label call_runtime, done, exponent_not_smi, int_exponent; |
527 | 527 |
528 // Save 1 in double_result - we need this several times later on. | 528 // Save 1 in double_result - we need this several times later on. |
529 __ movp(scratch, Immediate(1)); | 529 __ movp(scratch, Immediate(1)); |
530 __ Cvtlsi2sd(double_result, scratch); | 530 __ Cvtlsi2sd(double_result, scratch); |
531 | 531 |
532 if (exponent_type_ == ON_STACK) { | 532 if (exponent_type() == ON_STACK) { |
533 Label base_is_smi, unpack_exponent; | 533 Label base_is_smi, unpack_exponent; |
534 // The exponent and base are supplied as arguments on the stack. | 534 // The exponent and base are supplied as arguments on the stack. |
535 // This can only happen if the stub is called from non-optimized code. | 535 // This can only happen if the stub is called from non-optimized code. |
536 // Load input parameters from stack. | 536 // Load input parameters from stack. |
537 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 537 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
538 __ movp(base, args.GetArgumentOperand(0)); | 538 __ movp(base, args.GetArgumentOperand(0)); |
539 __ movp(exponent, args.GetArgumentOperand(1)); | 539 __ movp(exponent, args.GetArgumentOperand(1)); |
540 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 540 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
541 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), | 541 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), |
542 Heap::kHeapNumberMapRootIndex); | 542 Heap::kHeapNumberMapRootIndex); |
543 __ j(not_equal, &call_runtime); | 543 __ j(not_equal, &call_runtime); |
544 | 544 |
545 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); | 545 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
546 __ jmp(&unpack_exponent, Label::kNear); | 546 __ jmp(&unpack_exponent, Label::kNear); |
547 | 547 |
548 __ bind(&base_is_smi); | 548 __ bind(&base_is_smi); |
549 __ SmiToInteger32(base, base); | 549 __ SmiToInteger32(base, base); |
550 __ Cvtlsi2sd(double_base, base); | 550 __ Cvtlsi2sd(double_base, base); |
551 __ bind(&unpack_exponent); | 551 __ bind(&unpack_exponent); |
552 | 552 |
553 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 553 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
554 __ SmiToInteger32(exponent, exponent); | 554 __ SmiToInteger32(exponent, exponent); |
555 __ jmp(&int_exponent); | 555 __ jmp(&int_exponent); |
556 | 556 |
557 __ bind(&exponent_not_smi); | 557 __ bind(&exponent_not_smi); |
558 __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset), | 558 __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset), |
559 Heap::kHeapNumberMapRootIndex); | 559 Heap::kHeapNumberMapRootIndex); |
560 __ j(not_equal, &call_runtime); | 560 __ j(not_equal, &call_runtime); |
561 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); | 561 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); |
562 } else if (exponent_type_ == TAGGED) { | 562 } else if (exponent_type() == TAGGED) { |
563 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 563 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
564 __ SmiToInteger32(exponent, exponent); | 564 __ SmiToInteger32(exponent, exponent); |
565 __ jmp(&int_exponent); | 565 __ jmp(&int_exponent); |
566 | 566 |
567 __ bind(&exponent_not_smi); | 567 __ bind(&exponent_not_smi); |
568 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); | 568 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); |
569 } | 569 } |
570 | 570 |
571 if (exponent_type_ != INTEGER) { | 571 if (exponent_type() != INTEGER) { |
572 Label fast_power, try_arithmetic_simplification; | 572 Label fast_power, try_arithmetic_simplification; |
573 // Detect integer exponents stored as double. | 573 // Detect integer exponents stored as double. |
574 __ DoubleToI(exponent, double_exponent, double_scratch, | 574 __ DoubleToI(exponent, double_exponent, double_scratch, |
575 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); | 575 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); |
576 __ jmp(&int_exponent); | 576 __ jmp(&int_exponent); |
577 | 577 |
578 __ bind(&try_arithmetic_simplification); | 578 __ bind(&try_arithmetic_simplification); |
579 __ cvttsd2si(exponent, double_exponent); | 579 __ cvttsd2si(exponent, double_exponent); |
580 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | 580 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
581 __ cmpl(exponent, Immediate(0x1)); | 581 __ cmpl(exponent, Immediate(0x1)); |
582 __ j(overflow, &call_runtime); | 582 __ j(overflow, &call_runtime); |
583 | 583 |
584 if (exponent_type_ == ON_STACK) { | 584 if (exponent_type() == ON_STACK) { |
585 // Detect square root case. Crankshaft detects constant +/-0.5 at | 585 // Detect square root case. Crankshaft detects constant +/-0.5 at |
586 // compile time and uses DoMathPowHalf instead. We then skip this check | 586 // compile time and uses DoMathPowHalf instead. We then skip this check |
587 // for non-constant cases of +/-0.5 as these hardly occur. | 587 // for non-constant cases of +/-0.5 as these hardly occur. |
588 Label continue_sqrt, continue_rsqrt, not_plus_half; | 588 Label continue_sqrt, continue_rsqrt, not_plus_half; |
589 // Test for 0.5. | 589 // Test for 0.5. |
590 // Load double_scratch with 0.5. | 590 // Load double_scratch with 0.5. |
591 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000)); | 591 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000)); |
592 __ movq(double_scratch, scratch); | 592 __ movq(double_scratch, scratch); |
593 // Already ruled out NaNs for exponent. | 593 // Already ruled out NaNs for exponent. |
594 __ ucomisd(double_scratch, double_exponent); | 594 __ ucomisd(double_scratch, double_exponent); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 __ xorps(double_scratch2, double_scratch2); | 733 __ xorps(double_scratch2, double_scratch2); |
734 __ ucomisd(double_scratch2, double_result); | 734 __ ucomisd(double_scratch2, double_result); |
735 // double_exponent aliased as double_scratch2 has already been overwritten | 735 // double_exponent aliased as double_scratch2 has already been overwritten |
736 // and may not have contained the exponent value in the first place when the | 736 // and may not have contained the exponent value in the first place when the |
737 // input was a smi. We reset it with exponent value before bailing out. | 737 // input was a smi. We reset it with exponent value before bailing out. |
738 __ j(not_equal, &done); | 738 __ j(not_equal, &done); |
739 __ Cvtlsi2sd(double_exponent, exponent); | 739 __ Cvtlsi2sd(double_exponent, exponent); |
740 | 740 |
741 // Returning or bailing out. | 741 // Returning or bailing out. |
742 Counters* counters = isolate()->counters(); | 742 Counters* counters = isolate()->counters(); |
743 if (exponent_type_ == ON_STACK) { | 743 if (exponent_type() == ON_STACK) { |
744 // The arguments are still on the stack. | 744 // The arguments are still on the stack. |
745 __ bind(&call_runtime); | 745 __ bind(&call_runtime); |
746 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); | 746 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); |
747 | 747 |
748 // The stub is called from non-optimized code, which expects the result | 748 // The stub is called from non-optimized code, which expects the result |
749 // as heap number in rax. | 749 // as heap number in rax. |
750 __ bind(&done); | 750 __ bind(&done); |
751 __ AllocateHeapNumber(rax, rcx, &call_runtime); | 751 __ AllocateHeapNumber(rax, rcx, &call_runtime); |
752 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); | 752 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); |
753 __ IncrementCounter(counters->math_pow(), 1); | 753 __ IncrementCounter(counters->math_pow(), 1); |
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2159 } | 2159 } |
2160 | 2160 |
2161 if (call_as_method) { | 2161 if (call_as_method) { |
2162 __ bind(&wrap); | 2162 __ bind(&wrap); |
2163 EmitWrapCase(masm, &args, &cont); | 2163 EmitWrapCase(masm, &args, &cont); |
2164 } | 2164 } |
2165 } | 2165 } |
2166 | 2166 |
2167 | 2167 |
2168 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2168 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2169 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | 2169 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); |
2170 } | 2170 } |
2171 | 2171 |
2172 | 2172 |
2173 void CallConstructStub::Generate(MacroAssembler* masm) { | 2173 void CallConstructStub::Generate(MacroAssembler* masm) { |
2174 // rax : number of arguments | 2174 // rax : number of arguments |
2175 // rbx : feedback vector | 2175 // rbx : feedback vector |
2176 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback | 2176 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback |
2177 // vector (Smi) | 2177 // vector (Smi) |
2178 // rdi : constructor function | 2178 // rdi : constructor function |
2179 Label slow, non_function_call; | 2179 Label slow, non_function_call; |
(...skipping 2246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4426 | 4426 |
4427 | 4427 |
4428 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4428 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
4429 CEntryStub ces(isolate(), 1, kSaveFPRegs); | 4429 CEntryStub ces(isolate(), 1, kSaveFPRegs); |
4430 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); | 4430 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); |
4431 int parameter_count_offset = | 4431 int parameter_count_offset = |
4432 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4432 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
4433 __ movp(rbx, MemOperand(rbp, parameter_count_offset)); | 4433 __ movp(rbx, MemOperand(rbp, parameter_count_offset)); |
4434 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4434 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4435 __ PopReturnAddressTo(rcx); | 4435 __ PopReturnAddressTo(rcx); |
4436 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 4436 int additional_offset = |
4437 ? kPointerSize | 4437 function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; |
4438 : 0; | |
4439 __ leap(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); | 4438 __ leap(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); |
4440 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. | 4439 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. |
4441 } | 4440 } |
4442 | 4441 |
4443 | 4442 |
4444 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4443 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4445 if (masm->isolate()->function_entry_hook() != NULL) { | 4444 if (masm->isolate()->function_entry_hook() != NULL) { |
4446 ProfileEntryHookStub stub(masm->isolate()); | 4445 ProfileEntryHookStub stub(masm->isolate()); |
4447 masm->CallStub(&stub); | 4446 masm->CallStub(&stub); |
4448 } | 4447 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4636 stubh2.GetCode(); | 4635 stubh2.GetCode(); |
4637 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 4636 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
4638 stubh3.GetCode(); | 4637 stubh3.GetCode(); |
4639 } | 4638 } |
4640 } | 4639 } |
4641 | 4640 |
4642 | 4641 |
4643 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 4642 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
4644 MacroAssembler* masm, | 4643 MacroAssembler* masm, |
4645 AllocationSiteOverrideMode mode) { | 4644 AllocationSiteOverrideMode mode) { |
4646 if (argument_count_ == ANY) { | 4645 if (argument_count() == ANY) { |
4647 Label not_zero_case, not_one_case; | 4646 Label not_zero_case, not_one_case; |
4648 __ testp(rax, rax); | 4647 __ testp(rax, rax); |
4649 __ j(not_zero, ¬_zero_case); | 4648 __ j(not_zero, ¬_zero_case); |
4650 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4649 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
4651 | 4650 |
4652 __ bind(¬_zero_case); | 4651 __ bind(¬_zero_case); |
4653 __ cmpl(rax, Immediate(1)); | 4652 __ cmpl(rax, Immediate(1)); |
4654 __ j(greater, ¬_one_case); | 4653 __ j(greater, ¬_one_case); |
4655 CreateArrayDispatchOneArgument(masm, mode); | 4654 CreateArrayDispatchOneArgument(masm, mode); |
4656 | 4655 |
4657 __ bind(¬_one_case); | 4656 __ bind(¬_one_case); |
4658 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4657 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4659 } else if (argument_count_ == NONE) { | 4658 } else if (argument_count() == NONE) { |
4660 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4659 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
4661 } else if (argument_count_ == ONE) { | 4660 } else if (argument_count() == ONE) { |
4662 CreateArrayDispatchOneArgument(masm, mode); | 4661 CreateArrayDispatchOneArgument(masm, mode); |
4663 } else if (argument_count_ == MORE_THAN_ONE) { | 4662 } else if (argument_count() == MORE_THAN_ONE) { |
4664 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4663 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4665 } else { | 4664 } else { |
4666 UNREACHABLE(); | 4665 UNREACHABLE(); |
4667 } | 4666 } |
4668 } | 4667 } |
4669 | 4668 |
4670 | 4669 |
4671 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 4670 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
4672 // ----------- S t a t e ------------- | 4671 // ----------- S t a t e ------------- |
4673 // -- rax : argc | 4672 // -- rax : argc |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4814 // -- rsp[(argc + 1) * 8] : receiver | 4813 // -- rsp[(argc + 1) * 8] : receiver |
4815 // ----------------------------------- | 4814 // ----------------------------------- |
4816 | 4815 |
4817 Register callee = rax; | 4816 Register callee = rax; |
4818 Register call_data = rbx; | 4817 Register call_data = rbx; |
4819 Register holder = rcx; | 4818 Register holder = rcx; |
4820 Register api_function_address = rdx; | 4819 Register api_function_address = rdx; |
4821 Register return_address = rdi; | 4820 Register return_address = rdi; |
4822 Register context = rsi; | 4821 Register context = rsi; |
4823 | 4822 |
4824 int argc = ArgumentBits::decode(bit_field_); | 4823 int argc = this->argc(); |
4825 bool is_store = IsStoreBits::decode(bit_field_); | 4824 bool is_store = this->is_store(); |
4826 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 4825 bool call_data_undefined = this->call_data_undefined(); |
4827 | 4826 |
4828 typedef FunctionCallbackArguments FCA; | 4827 typedef FunctionCallbackArguments FCA; |
4829 | 4828 |
4830 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 4829 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
4831 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 4830 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
4832 STATIC_ASSERT(FCA::kDataIndex == 4); | 4831 STATIC_ASSERT(FCA::kDataIndex == 4); |
4833 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 4832 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
4834 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 4833 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
4835 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 4834 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
4836 STATIC_ASSERT(FCA::kHolderIndex == 0); | 4835 STATIC_ASSERT(FCA::kHolderIndex == 0); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4976 return_value_operand, | 4975 return_value_operand, |
4977 NULL); | 4976 NULL); |
4978 } | 4977 } |
4979 | 4978 |
4980 | 4979 |
4981 #undef __ | 4980 #undef __ |
4982 | 4981 |
4983 } } // namespace v8::internal | 4982 } } // namespace v8::internal |
4984 | 4983 |
4985 #endif // V8_TARGET_ARCH_X64 | 4984 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |