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