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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 Label no_parameter_map; | 511 Label no_parameter_map; |
512 __ test(ebx, ebx); | 512 __ test(ebx, ebx); |
513 __ j(zero, &no_parameter_map, Label::kNear); | 513 __ j(zero, &no_parameter_map, Label::kNear); |
514 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); | 514 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); |
515 __ bind(&no_parameter_map); | 515 __ bind(&no_parameter_map); |
516 | 516 |
517 // 2. Backing store. | 517 // 2. Backing store. |
518 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); | 518 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); |
519 | 519 |
520 // 3. Arguments object. | 520 // 3. Arguments object. |
521 __ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize)); | 521 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); |
522 | 522 |
523 // Do the allocation of all three objects in one go. | 523 // Do the allocation of all three objects in one go. |
524 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); | 524 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); |
525 | 525 |
526 // eax = address of new object(s) (tagged) | 526 // eax = address of new object(s) (tagged) |
527 // ecx = argument count (smi-tagged) | 527 // ecx = argument count (smi-tagged) |
528 // esp[0] = mapped parameter count (tagged) | 528 // esp[0] = mapped parameter count (tagged) |
529 // esp[4] = function | 529 // esp[4] = function |
530 // esp[8] = parameter count (tagged) | 530 // esp[8] = parameter count (tagged) |
531 // Get the arguments map from the current native context into edi. | 531 // Get the arguments map from the current native context into edi. |
(...skipping 20 matching lines...) Expand all Loading... |
552 // esp[4] = function | 552 // esp[4] = function |
553 // esp[8] = parameter count (tagged) | 553 // esp[8] = parameter count (tagged) |
554 // Copy the JS object part. | 554 // Copy the JS object part. |
555 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); | 555 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); |
556 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 556 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
557 masm->isolate()->factory()->empty_fixed_array()); | 557 masm->isolate()->factory()->empty_fixed_array()); |
558 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 558 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
559 masm->isolate()->factory()->empty_fixed_array()); | 559 masm->isolate()->factory()->empty_fixed_array()); |
560 | 560 |
561 // Set up the callee in-object property. | 561 // Set up the callee in-object property. |
562 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 562 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); |
563 __ mov(edi, Operand(esp, 1 * kPointerSize)); | 563 __ mov(edi, Operand(esp, 1 * kPointerSize)); |
564 __ AssertNotSmi(edi); | 564 __ AssertNotSmi(edi); |
565 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 565 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); |
566 Heap::kArgumentsCalleeIndex * kPointerSize), | |
567 edi); | |
568 | 566 |
569 // Use the length (smi tagged) and set that as an in-object property too. | 567 // Use the length (smi tagged) and set that as an in-object property too. |
570 __ AssertSmi(ecx); | 568 __ AssertSmi(ecx); |
571 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 569 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); |
572 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | |
573 Heap::kArgumentsLengthIndex * kPointerSize), | |
574 ecx); | |
575 | 570 |
576 // Set up the elements pointer in the allocated arguments object. | 571 // Set up the elements pointer in the allocated arguments object. |
577 // If we allocated a parameter map, edi will point there, otherwise to the | 572 // If we allocated a parameter map, edi will point there, otherwise to the |
578 // backing store. | 573 // backing store. |
579 __ lea(edi, Operand(eax, Heap::kSloppyArgumentsObjectSize)); | 574 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); |
580 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 575 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
581 | 576 |
582 // eax = address of new object (tagged) | 577 // eax = address of new object (tagged) |
583 // ebx = mapped parameter count (tagged) | 578 // ebx = mapped parameter count (tagged) |
584 // ecx = argument count (tagged) | 579 // ecx = argument count (tagged) |
585 // edx = address of receiver argument | 580 // edx = address of receiver argument |
586 // edi = address of parameter map or backing store (tagged) | 581 // edi = address of parameter map or backing store (tagged) |
587 // esp[0] = mapped parameter count (tagged) | 582 // esp[0] = mapped parameter count (tagged) |
588 // esp[4] = function | 583 // esp[4] = function |
589 // esp[8] = parameter count (tagged) | 584 // esp[8] = parameter count (tagged) |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 __ pop(eax); // Remove saved parameter count. | 684 __ pop(eax); // Remove saved parameter count. |
690 __ pop(eax); // Pop return address. | 685 __ pop(eax); // Pop return address. |
691 __ push(edi); // Push function. | 686 __ push(edi); // Push function. |
692 __ push(edx); // Push parameters pointer. | 687 __ push(edx); // Push parameters pointer. |
693 __ push(ecx); // Push parameter count. | 688 __ push(ecx); // Push parameter count. |
694 __ push(eax); // Push return address. | 689 __ push(eax); // Push return address. |
695 __ TailCallRuntime(Runtime::kNewSloppyArguments); | 690 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
696 } | 691 } |
697 | 692 |
698 | 693 |
699 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | |
700 // ecx : number of parameters (tagged) | |
701 // edx : parameters pointer | |
702 // edi : function | |
703 // esp[0] : return address | |
704 | |
705 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | |
706 DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
707 DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
708 | |
709 // Check if the calling frame is an arguments adaptor frame. | |
710 Label try_allocate, runtime; | |
711 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
712 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); | |
713 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
714 __ j(not_equal, &try_allocate, Label::kNear); | |
715 | |
716 // Patch the arguments.length and the parameters pointer. | |
717 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
718 __ lea(edx, | |
719 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | |
720 | |
721 // Try the new space allocation. Start out with computing the size of | |
722 // the arguments object and the elements array. | |
723 Label add_arguments_object; | |
724 __ bind(&try_allocate); | |
725 __ mov(eax, ecx); | |
726 __ test(eax, eax); | |
727 __ j(zero, &add_arguments_object, Label::kNear); | |
728 __ lea(eax, Operand(eax, times_2, FixedArray::kHeaderSize)); | |
729 __ bind(&add_arguments_object); | |
730 __ add(eax, Immediate(Heap::kStrictArgumentsObjectSize)); | |
731 | |
732 // Do the allocation of both objects in one go. | |
733 __ Allocate(eax, eax, ebx, no_reg, &runtime, TAG_OBJECT); | |
734 | |
735 // Get the arguments map from the current native context. | |
736 __ mov(edi, NativeContextOperand()); | |
737 __ mov(edi, ContextOperand(edi, Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
738 | |
739 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); | |
740 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | |
741 masm->isolate()->factory()->empty_fixed_array()); | |
742 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | |
743 masm->isolate()->factory()->empty_fixed_array()); | |
744 | |
745 // Get the length (smi tagged) and set that as an in-object property too. | |
746 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | |
747 __ AssertSmi(ecx); | |
748 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | |
749 Heap::kArgumentsLengthIndex * kPointerSize), | |
750 ecx); | |
751 | |
752 // If there are no actual arguments, we're done. | |
753 Label done; | |
754 __ test(ecx, ecx); | |
755 __ j(zero, &done, Label::kNear); | |
756 | |
757 // Set up the elements pointer in the allocated arguments object and | |
758 // initialize the header in the elements fixed array. | |
759 __ lea(edi, Operand(eax, Heap::kStrictArgumentsObjectSize)); | |
760 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
761 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
762 Immediate(isolate()->factory()->fixed_array_map())); | |
763 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | |
764 | |
765 // Untag the length for the loop below. | |
766 __ SmiUntag(ecx); | |
767 | |
768 // Copy the fixed array slots. | |
769 Label loop; | |
770 __ bind(&loop); | |
771 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | |
772 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | |
773 __ add(edi, Immediate(kPointerSize)); | |
774 __ sub(edx, Immediate(kPointerSize)); | |
775 __ dec(ecx); | |
776 __ j(not_zero, &loop); | |
777 | |
778 // Return. | |
779 __ bind(&done); | |
780 __ ret(0); | |
781 | |
782 // Do the runtime call to allocate the arguments object. | |
783 __ bind(&runtime); | |
784 __ pop(eax); // Pop return address. | |
785 __ push(edi); // Push function. | |
786 __ push(edx); // Push parameters pointer. | |
787 __ push(ecx); // Push parameter count. | |
788 __ push(eax); // Push return address. | |
789 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
790 } | |
791 | |
792 | |
793 void RegExpExecStub::Generate(MacroAssembler* masm) { | 694 void RegExpExecStub::Generate(MacroAssembler* masm) { |
794 // Just jump directly to runtime if native RegExp is not selected at compile | 695 // Just jump directly to runtime if native RegExp is not selected at compile |
795 // time or if regexp entry in generated code is turned off runtime switch or | 696 // time or if regexp entry in generated code is turned off runtime switch or |
796 // at compilation. | 697 // at compilation. |
797 #ifdef V8_INTERPRETED_REGEXP | 698 #ifdef V8_INTERPRETED_REGEXP |
798 __ TailCallRuntime(Runtime::kRegExpExec); | 699 __ TailCallRuntime(Runtime::kRegExpExec); |
799 #else // V8_INTERPRETED_REGEXP | 700 #else // V8_INTERPRETED_REGEXP |
800 | 701 |
801 // Stack frame on entry. | 702 // Stack frame on entry. |
802 // esp[0]: return address | 703 // esp[0]: return address |
(...skipping 4107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4910 __ Push(ecx); | 4811 __ Push(ecx); |
4911 __ CallRuntime(Runtime::kAllocateInNewSpace); | 4812 __ CallRuntime(Runtime::kAllocateInNewSpace); |
4912 __ mov(edx, eax); | 4813 __ mov(edx, eax); |
4913 __ Pop(ebx); | 4814 __ Pop(ebx); |
4914 __ Pop(eax); | 4815 __ Pop(eax); |
4915 } | 4816 } |
4916 __ jmp(&done_allocate); | 4817 __ jmp(&done_allocate); |
4917 } | 4818 } |
4918 } | 4819 } |
4919 | 4820 |
| 4821 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |
| 4822 // ----------- S t a t e ------------- |
| 4823 // -- edi : function |
| 4824 // -- esi : context |
| 4825 // -- ebp : frame pointer |
| 4826 // -- esp[0] : return address |
| 4827 // ----------------------------------- |
| 4828 __ AssertFunction(edi); |
| 4829 |
| 4830 // For Ignition we need to skip all possible handler/stub frames until |
| 4831 // we reach the JavaScript frame for the function (similar to what the |
| 4832 // runtime fallback implementation does). So make edx point to that |
| 4833 // JavaScript frame. |
| 4834 { |
| 4835 Label loop, loop_entry; |
| 4836 __ mov(edx, ebp); |
| 4837 __ jmp(&loop_entry, Label::kNear); |
| 4838 __ bind(&loop); |
| 4839 __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |
| 4840 __ bind(&loop_entry); |
| 4841 __ cmp(edi, Operand(edx, StandardFrameConstants::kMarkerOffset)); |
| 4842 __ j(not_equal, &loop); |
| 4843 } |
| 4844 |
| 4845 // Check if we have an arguments adaptor frame below the function frame. |
| 4846 Label arguments_adaptor, arguments_done; |
| 4847 __ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |
| 4848 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), |
| 4849 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 4850 __ j(equal, &arguments_adaptor, Label::kNear); |
| 4851 { |
| 4852 __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 4853 __ mov(eax, |
| 4854 FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 4855 __ lea(ebx, |
| 4856 Operand(edx, eax, times_half_pointer_size, |
| 4857 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |
| 4858 } |
| 4859 __ jmp(&arguments_done, Label::kNear); |
| 4860 __ bind(&arguments_adaptor); |
| 4861 { |
| 4862 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 4863 __ lea(ebx, |
| 4864 Operand(ebx, eax, times_half_pointer_size, |
| 4865 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |
| 4866 } |
| 4867 __ bind(&arguments_done); |
| 4868 |
| 4869 // ----------- S t a t e ------------- |
| 4870 // -- eax : number of arguments (tagged) |
| 4871 // -- ebx : pointer to the first argument |
| 4872 // -- esi : context |
| 4873 // -- esp[0] : return address |
| 4874 // ----------------------------------- |
| 4875 |
| 4876 // Allocate space for the strict arguments object plus the backing store. |
| 4877 Label allocate, done_allocate; |
| 4878 __ lea(ecx, |
| 4879 Operand(eax, times_half_pointer_size, |
| 4880 JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); |
| 4881 __ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT); |
| 4882 __ bind(&done_allocate); |
| 4883 |
| 4884 // Setup the elements array in edx. |
| 4885 __ mov(FieldOperand(edx, FixedArray::kMapOffset), |
| 4886 isolate()->factory()->fixed_array_map()); |
| 4887 __ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax); |
| 4888 { |
| 4889 Label loop, done_loop; |
| 4890 __ Move(ecx, Smi::FromInt(0)); |
| 4891 __ bind(&loop); |
| 4892 __ cmp(ecx, eax); |
| 4893 __ j(equal, &done_loop, Label::kNear); |
| 4894 __ mov(edi, Operand(ebx, 0 * kPointerSize)); |
| 4895 __ mov(FieldOperand(edx, ecx, times_half_pointer_size, |
| 4896 FixedArray::kHeaderSize), |
| 4897 edi); |
| 4898 __ sub(ebx, Immediate(1 * kPointerSize)); |
| 4899 __ add(ecx, Immediate(Smi::FromInt(1))); |
| 4900 __ jmp(&loop); |
| 4901 __ bind(&done_loop); |
| 4902 } |
| 4903 |
| 4904 // Setup the rest parameter array in edi. |
| 4905 __ lea(edi, |
| 4906 Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize)); |
| 4907 __ LoadGlobalFunction(Context::STRICT_ARGUMENTS_MAP_INDEX, ecx); |
| 4908 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kMapOffset), ecx); |
| 4909 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kPropertiesOffset), |
| 4910 isolate()->factory()->empty_fixed_array()); |
| 4911 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kElementsOffset), edx); |
| 4912 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kLengthOffset), eax); |
| 4913 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); |
| 4914 __ mov(eax, edi); |
| 4915 __ Ret(); |
| 4916 |
| 4917 // Fall back to %AllocateInNewSpace. |
| 4918 __ bind(&allocate); |
| 4919 { |
| 4920 FrameScope scope(masm, StackFrame::INTERNAL); |
| 4921 __ SmiTag(ecx); |
| 4922 __ Push(eax); |
| 4923 __ Push(ebx); |
| 4924 __ Push(ecx); |
| 4925 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| 4926 __ mov(edx, eax); |
| 4927 __ Pop(ebx); |
| 4928 __ Pop(eax); |
| 4929 } |
| 4930 __ jmp(&done_allocate); |
| 4931 } |
| 4932 |
4920 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | 4933 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { |
4921 Register context_reg = esi; | 4934 Register context_reg = esi; |
4922 Register slot_reg = ebx; | 4935 Register slot_reg = ebx; |
4923 Register result_reg = eax; | 4936 Register result_reg = eax; |
4924 Label slow_case; | 4937 Label slow_case; |
4925 | 4938 |
4926 // Go up context chain to the script context. | 4939 // Go up context chain to the script context. |
4927 for (int i = 0; i < depth(); ++i) { | 4940 for (int i = 0; i < depth(); ++i) { |
4928 __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | 4941 __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); |
4929 context_reg = result_reg; | 4942 context_reg = result_reg; |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5468 return_value_operand, NULL); | 5481 return_value_operand, NULL); |
5469 } | 5482 } |
5470 | 5483 |
5471 | 5484 |
5472 #undef __ | 5485 #undef __ |
5473 | 5486 |
5474 } // namespace internal | 5487 } // namespace internal |
5475 } // namespace v8 | 5488 } // namespace v8 |
5476 | 5489 |
5477 #endif // V8_TARGET_ARCH_X87 | 5490 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |