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