OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
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 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 const XMMRegister double_base = xmm2; | 635 const XMMRegister double_base = xmm2; |
636 const XMMRegister double_exponent = xmm1; | 636 const XMMRegister double_exponent = xmm1; |
637 const XMMRegister double_scratch = xmm4; | 637 const XMMRegister double_scratch = xmm4; |
638 | 638 |
639 Label call_runtime, done, exponent_not_smi, int_exponent; | 639 Label call_runtime, done, exponent_not_smi, int_exponent; |
640 | 640 |
641 // Save 1 in double_result - we need this several times later on. | 641 // Save 1 in double_result - we need this several times later on. |
642 __ mov(scratch, Immediate(1)); | 642 __ mov(scratch, Immediate(1)); |
643 __ Cvtsi2sd(double_result, scratch); | 643 __ Cvtsi2sd(double_result, scratch); |
644 | 644 |
645 if (exponent_type_ == ON_STACK) { | 645 if (exponent_type() == ON_STACK) { |
646 Label base_is_smi, unpack_exponent; | 646 Label base_is_smi, unpack_exponent; |
647 // The exponent and base are supplied as arguments on the stack. | 647 // The exponent and base are supplied as arguments on the stack. |
648 // This can only happen if the stub is called from non-optimized code. | 648 // This can only happen if the stub is called from non-optimized code. |
649 // Load input parameters from stack. | 649 // Load input parameters from stack. |
650 __ mov(base, Operand(esp, 2 * kPointerSize)); | 650 __ mov(base, Operand(esp, 2 * kPointerSize)); |
651 __ mov(exponent, Operand(esp, 1 * kPointerSize)); | 651 __ mov(exponent, Operand(esp, 1 * kPointerSize)); |
652 | 652 |
653 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 653 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
654 __ cmp(FieldOperand(base, HeapObject::kMapOffset), | 654 __ cmp(FieldOperand(base, HeapObject::kMapOffset), |
655 factory->heap_number_map()); | 655 factory->heap_number_map()); |
(...skipping 10 matching lines...) Expand all Loading... |
666 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 666 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
667 __ SmiUntag(exponent); | 667 __ SmiUntag(exponent); |
668 __ jmp(&int_exponent); | 668 __ jmp(&int_exponent); |
669 | 669 |
670 __ bind(&exponent_not_smi); | 670 __ bind(&exponent_not_smi); |
671 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), | 671 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), |
672 factory->heap_number_map()); | 672 factory->heap_number_map()); |
673 __ j(not_equal, &call_runtime); | 673 __ j(not_equal, &call_runtime); |
674 __ movsd(double_exponent, | 674 __ movsd(double_exponent, |
675 FieldOperand(exponent, HeapNumber::kValueOffset)); | 675 FieldOperand(exponent, HeapNumber::kValueOffset)); |
676 } else if (exponent_type_ == TAGGED) { | 676 } else if (exponent_type() == TAGGED) { |
677 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 677 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
678 __ SmiUntag(exponent); | 678 __ SmiUntag(exponent); |
679 __ jmp(&int_exponent); | 679 __ jmp(&int_exponent); |
680 | 680 |
681 __ bind(&exponent_not_smi); | 681 __ bind(&exponent_not_smi); |
682 __ movsd(double_exponent, | 682 __ movsd(double_exponent, |
683 FieldOperand(exponent, HeapNumber::kValueOffset)); | 683 FieldOperand(exponent, HeapNumber::kValueOffset)); |
684 } | 684 } |
685 | 685 |
686 if (exponent_type_ != INTEGER) { | 686 if (exponent_type() != INTEGER) { |
687 Label fast_power, try_arithmetic_simplification; | 687 Label fast_power, try_arithmetic_simplification; |
688 __ DoubleToI(exponent, double_exponent, double_scratch, | 688 __ DoubleToI(exponent, double_exponent, double_scratch, |
689 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); | 689 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); |
690 __ jmp(&int_exponent); | 690 __ jmp(&int_exponent); |
691 | 691 |
692 __ bind(&try_arithmetic_simplification); | 692 __ bind(&try_arithmetic_simplification); |
693 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | 693 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
694 __ cvttsd2si(exponent, Operand(double_exponent)); | 694 __ cvttsd2si(exponent, Operand(double_exponent)); |
695 __ cmp(exponent, Immediate(0x1)); | 695 __ cmp(exponent, Immediate(0x1)); |
696 __ j(overflow, &call_runtime); | 696 __ j(overflow, &call_runtime); |
697 | 697 |
698 if (exponent_type_ == ON_STACK) { | 698 if (exponent_type() == ON_STACK) { |
699 // Detect square root case. Crankshaft detects constant +/-0.5 at | 699 // Detect square root case. Crankshaft detects constant +/-0.5 at |
700 // compile time and uses DoMathPowHalf instead. We then skip this check | 700 // compile time and uses DoMathPowHalf instead. We then skip this check |
701 // for non-constant cases of +/-0.5 as these hardly occur. | 701 // for non-constant cases of +/-0.5 as these hardly occur. |
702 Label continue_sqrt, continue_rsqrt, not_plus_half; | 702 Label continue_sqrt, continue_rsqrt, not_plus_half; |
703 // Test for 0.5. | 703 // Test for 0.5. |
704 // Load double_scratch with 0.5. | 704 // Load double_scratch with 0.5. |
705 __ mov(scratch, Immediate(0x3F000000u)); | 705 __ mov(scratch, Immediate(0x3F000000u)); |
706 __ movd(double_scratch, scratch); | 706 __ movd(double_scratch, scratch); |
707 __ cvtss2sd(double_scratch, double_scratch); | 707 __ cvtss2sd(double_scratch, double_scratch); |
708 // Already ruled out NaNs for exponent. | 708 // Already ruled out NaNs for exponent. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 __ xorps(double_scratch2, double_scratch2); | 850 __ xorps(double_scratch2, double_scratch2); |
851 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. | 851 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. |
852 // double_exponent aliased as double_scratch2 has already been overwritten | 852 // double_exponent aliased as double_scratch2 has already been overwritten |
853 // and may not have contained the exponent value in the first place when the | 853 // and may not have contained the exponent value in the first place when the |
854 // exponent is a smi. We reset it with exponent value before bailing out. | 854 // exponent is a smi. We reset it with exponent value before bailing out. |
855 __ j(not_equal, &done); | 855 __ j(not_equal, &done); |
856 __ Cvtsi2sd(double_exponent, exponent); | 856 __ Cvtsi2sd(double_exponent, exponent); |
857 | 857 |
858 // Returning or bailing out. | 858 // Returning or bailing out. |
859 Counters* counters = isolate()->counters(); | 859 Counters* counters = isolate()->counters(); |
860 if (exponent_type_ == ON_STACK) { | 860 if (exponent_type() == ON_STACK) { |
861 // The arguments are still on the stack. | 861 // The arguments are still on the stack. |
862 __ bind(&call_runtime); | 862 __ bind(&call_runtime); |
863 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); | 863 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); |
864 | 864 |
865 // The stub is called from non-optimized code, which expects the result | 865 // The stub is called from non-optimized code, which expects the result |
866 // as heap number in exponent. | 866 // as heap number in exponent. |
867 __ bind(&done); | 867 __ bind(&done); |
868 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); | 868 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); |
869 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result); | 869 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result); |
870 __ IncrementCounter(counters->math_pow(), 1); | 870 __ IncrementCounter(counters->math_pow(), 1); |
(...skipping 1404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2275 } | 2275 } |
2276 | 2276 |
2277 if (call_as_method) { | 2277 if (call_as_method) { |
2278 __ bind(&wrap); | 2278 __ bind(&wrap); |
2279 EmitWrapCase(masm, argc, &cont); | 2279 EmitWrapCase(masm, argc, &cont); |
2280 } | 2280 } |
2281 } | 2281 } |
2282 | 2282 |
2283 | 2283 |
2284 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2284 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2285 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | 2285 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); |
2286 } | 2286 } |
2287 | 2287 |
2288 | 2288 |
2289 void CallConstructStub::Generate(MacroAssembler* masm) { | 2289 void CallConstructStub::Generate(MacroAssembler* masm) { |
2290 // eax : number of arguments | 2290 // eax : number of arguments |
2291 // ebx : feedback vector | 2291 // ebx : feedback vector |
2292 // edx : (only if ebx is not the megamorphic symbol) slot in feedback | 2292 // edx : (only if ebx is not the megamorphic symbol) slot in feedback |
2293 // vector (Smi) | 2293 // vector (Smi) |
2294 // edi : constructor function | 2294 // edi : constructor function |
2295 Label slow, non_function_call; | 2295 Label slow, non_function_call; |
(...skipping 2190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4486 | 4486 |
4487 | 4487 |
4488 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4488 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
4489 CEntryStub ces(isolate(), 1, kSaveFPRegs); | 4489 CEntryStub ces(isolate(), 1, kSaveFPRegs); |
4490 __ call(ces.GetCode(), RelocInfo::CODE_TARGET); | 4490 __ call(ces.GetCode(), RelocInfo::CODE_TARGET); |
4491 int parameter_count_offset = | 4491 int parameter_count_offset = |
4492 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4492 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
4493 __ mov(ebx, MemOperand(ebp, parameter_count_offset)); | 4493 __ mov(ebx, MemOperand(ebp, parameter_count_offset)); |
4494 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4494 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4495 __ pop(ecx); | 4495 __ pop(ecx); |
4496 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 4496 int additional_offset = |
4497 ? kPointerSize | 4497 function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; |
4498 : 0; | |
4499 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); | 4498 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); |
4500 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. | 4499 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. |
4501 } | 4500 } |
4502 | 4501 |
4503 | 4502 |
4504 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4503 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4505 if (masm->isolate()->function_entry_hook() != NULL) { | 4504 if (masm->isolate()->function_entry_hook() != NULL) { |
4506 ProfileEntryHookStub stub(masm->isolate()); | 4505 ProfileEntryHookStub stub(masm->isolate()); |
4507 masm->CallStub(&stub); | 4506 masm->CallStub(&stub); |
4508 } | 4507 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4688 stubh2.GetCode(); | 4687 stubh2.GetCode(); |
4689 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 4688 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
4690 stubh3.GetCode(); | 4689 stubh3.GetCode(); |
4691 } | 4690 } |
4692 } | 4691 } |
4693 | 4692 |
4694 | 4693 |
4695 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 4694 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
4696 MacroAssembler* masm, | 4695 MacroAssembler* masm, |
4697 AllocationSiteOverrideMode mode) { | 4696 AllocationSiteOverrideMode mode) { |
4698 if (argument_count_ == ANY) { | 4697 if (argument_count() == ANY) { |
4699 Label not_zero_case, not_one_case; | 4698 Label not_zero_case, not_one_case; |
4700 __ test(eax, eax); | 4699 __ test(eax, eax); |
4701 __ j(not_zero, ¬_zero_case); | 4700 __ j(not_zero, ¬_zero_case); |
4702 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4701 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
4703 | 4702 |
4704 __ bind(¬_zero_case); | 4703 __ bind(¬_zero_case); |
4705 __ cmp(eax, 1); | 4704 __ cmp(eax, 1); |
4706 __ j(greater, ¬_one_case); | 4705 __ j(greater, ¬_one_case); |
4707 CreateArrayDispatchOneArgument(masm, mode); | 4706 CreateArrayDispatchOneArgument(masm, mode); |
4708 | 4707 |
4709 __ bind(¬_one_case); | 4708 __ bind(¬_one_case); |
4710 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4709 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4711 } else if (argument_count_ == NONE) { | 4710 } else if (argument_count() == NONE) { |
4712 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4711 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
4713 } else if (argument_count_ == ONE) { | 4712 } else if (argument_count() == ONE) { |
4714 CreateArrayDispatchOneArgument(masm, mode); | 4713 CreateArrayDispatchOneArgument(masm, mode); |
4715 } else if (argument_count_ == MORE_THAN_ONE) { | 4714 } else if (argument_count() == MORE_THAN_ONE) { |
4716 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4715 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4717 } else { | 4716 } else { |
4718 UNREACHABLE(); | 4717 UNREACHABLE(); |
4719 } | 4718 } |
4720 } | 4719 } |
4721 | 4720 |
4722 | 4721 |
4723 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 4722 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
4724 // ----------- S t a t e ------------- | 4723 // ----------- S t a t e ------------- |
4725 // -- eax : argc (only if argument_count_ == ANY) | 4724 // -- eax : argc (only if argument_count() == ANY) |
4726 // -- ebx : AllocationSite or undefined | 4725 // -- ebx : AllocationSite or undefined |
4727 // -- edi : constructor | 4726 // -- edi : constructor |
4728 // -- esp[0] : return address | 4727 // -- esp[0] : return address |
4729 // -- esp[4] : last argument | 4728 // -- esp[4] : last argument |
4730 // ----------------------------------- | 4729 // ----------------------------------- |
4731 if (FLAG_debug_code) { | 4730 if (FLAG_debug_code) { |
4732 // The array construct code is only set for the global and natives | 4731 // The array construct code is only set for the global and natives |
4733 // builtin Array functions which always have maps. | 4732 // builtin Array functions which always have maps. |
4734 | 4733 |
4735 // Initial map for the builtin Array function should be a map. | 4734 // Initial map for the builtin Array function should be a map. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4863 // -- esp[(argc + 1) * 4] : receiver | 4862 // -- esp[(argc + 1) * 4] : receiver |
4864 // ----------------------------------- | 4863 // ----------------------------------- |
4865 | 4864 |
4866 Register callee = eax; | 4865 Register callee = eax; |
4867 Register call_data = ebx; | 4866 Register call_data = ebx; |
4868 Register holder = ecx; | 4867 Register holder = ecx; |
4869 Register api_function_address = edx; | 4868 Register api_function_address = edx; |
4870 Register return_address = edi; | 4869 Register return_address = edi; |
4871 Register context = esi; | 4870 Register context = esi; |
4872 | 4871 |
4873 int argc = ArgumentBits::decode(bit_field_); | 4872 int argc = this->argc(); |
4874 bool is_store = IsStoreBits::decode(bit_field_); | 4873 bool is_store = this->is_store(); |
4875 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 4874 bool call_data_undefined = this->call_data_undefined(); |
4876 | 4875 |
4877 typedef FunctionCallbackArguments FCA; | 4876 typedef FunctionCallbackArguments FCA; |
4878 | 4877 |
4879 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 4878 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
4880 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 4879 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
4881 STATIC_ASSERT(FCA::kDataIndex == 4); | 4880 STATIC_ASSERT(FCA::kDataIndex == 4); |
4882 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 4881 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
4883 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 4882 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
4884 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 4883 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
4885 STATIC_ASSERT(FCA::kHolderIndex == 0); | 4884 STATIC_ASSERT(FCA::kHolderIndex == 0); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5005 Operand(ebp, 7 * kPointerSize), | 5004 Operand(ebp, 7 * kPointerSize), |
5006 NULL); | 5005 NULL); |
5007 } | 5006 } |
5008 | 5007 |
5009 | 5008 |
5010 #undef __ | 5009 #undef __ |
5011 | 5010 |
5012 } } // namespace v8::internal | 5011 } } // namespace v8::internal |
5013 | 5012 |
5014 #endif // V8_TARGET_ARCH_IA32 | 5013 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |