| 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_IA32 |     5 #if V8_TARGET_ARCH_IA32 | 
|     6  |     6  | 
|     7 #include "src/code-factory.h" |     7 #include "src/code-factory.h" | 
|     8 #include "src/codegen.h" |     8 #include "src/codegen.h" | 
|     9 #include "src/deoptimizer.h" |     9 #include "src/deoptimizer.h" | 
|    10 #include "src/full-codegen/full-codegen.h" |    10 #include "src/full-codegen/full-codegen.h" | 
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   685   __ bind(&loop_header); |   685   __ bind(&loop_header); | 
|   686   __ Push(Operand(start_address, 0)); |   686   __ Push(Operand(start_address, 0)); | 
|   687   __ sub(start_address, Immediate(kPointerSize)); |   687   __ sub(start_address, Immediate(kPointerSize)); | 
|   688   __ bind(&loop_check); |   688   __ bind(&loop_check); | 
|   689   __ cmp(start_address, array_limit); |   689   __ cmp(start_address, array_limit); | 
|   690   __ j(greater, &loop_header, Label::kNear); |   690   __ j(greater, &loop_header, Label::kNear); | 
|   691 } |   691 } | 
|   692  |   692  | 
|   693 // static |   693 // static | 
|   694 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |   694 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 
|   695     MacroAssembler* masm, TailCallMode tail_call_mode, |   695     MacroAssembler* masm, TailCallMode tail_call_mode, PushArgsMode mode) { | 
|   696     CallableType function_type) { |  | 
|   697   // ----------- S t a t e ------------- |   696   // ----------- S t a t e ------------- | 
|   698   //  -- eax : the number of arguments (not including the receiver) |   697   //  -- eax : the number of arguments (not including the receiver) | 
|   699   //  -- ebx : the address of the first argument to be pushed. Subsequent |   698   //  -- ebx : the address of the first argument to be pushed. Subsequent | 
|   700   //           arguments should be consecutive above this, in the same order as |   699   //           arguments should be consecutive above this, in the same order as | 
|   701   //           they are to be pushed onto the stack. |   700   //           they are to be pushed onto the stack. | 
|   702   //  -- edi : the target to call (can be any Object). |   701   //  -- edi : the target to call (can be any Object). | 
|   703   // ----------------------------------- |   702   // ----------------------------------- | 
|   704   Label stack_overflow; |   703   Label stack_overflow; | 
|   705   // Compute the expected number of arguments. |   704   // Compute the expected number of arguments. | 
|   706   __ mov(ecx, eax); |   705   __ mov(ecx, eax); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   718  |   717  | 
|   719   // Find the address of the last argument. |   718   // Find the address of the last argument. | 
|   720   __ shl(ecx, kPointerSizeLog2); |   719   __ shl(ecx, kPointerSizeLog2); | 
|   721   __ neg(ecx); |   720   __ neg(ecx); | 
|   722   __ add(ecx, ebx); |   721   __ add(ecx, ebx); | 
|   723   Generate_InterpreterPushArgs(masm, ecx, ebx); |   722   Generate_InterpreterPushArgs(masm, ecx, ebx); | 
|   724  |   723  | 
|   725   // Call the target. |   724   // Call the target. | 
|   726   __ Push(edx);  // Re-push return address. |   725   __ Push(edx);  // Re-push return address. | 
|   727  |   726  | 
|   728   if (function_type == CallableType::kJSFunction) { |   727   if (mode == PushArgsMode::kJSFunction) { | 
|   729     __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, |   728     __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, | 
|   730                                                       tail_call_mode), |   729                                                       tail_call_mode), | 
|   731             RelocInfo::CODE_TARGET); |   730             RelocInfo::CODE_TARGET); | 
 |   731   } else if (mode == PushArgsMode::kWithFinalSpread) { | 
 |   732     __ Jump(masm->isolate()->builtins()->CallWithSpread(), | 
 |   733             RelocInfo::CODE_TARGET); | 
|   732   } else { |   734   } else { | 
|   733     DCHECK_EQ(function_type, CallableType::kAny); |  | 
|   734     __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |   735     __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 
|   735                                               tail_call_mode), |   736                                               tail_call_mode), | 
|   736             RelocInfo::CODE_TARGET); |   737             RelocInfo::CODE_TARGET); | 
|   737   } |   738   } | 
|   738  |   739  | 
|   739   __ bind(&stack_overflow); |   740   __ bind(&stack_overflow); | 
|   740   { |   741   { | 
|   741     // Pop the temporary registers, so that return address is on top of stack. |   742     // Pop the temporary registers, so that return address is on top of stack. | 
|   742     __ Pop(edi); |   743     __ Pop(edi); | 
|   743  |   744  | 
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   836   __ sub(scratch1, Immediate(1)); |   837   __ sub(scratch1, Immediate(1)); | 
|   837   __ bind(&loop_check); |   838   __ bind(&loop_check); | 
|   838   __ cmp(scratch1, Immediate(0)); |   839   __ cmp(scratch1, Immediate(0)); | 
|   839   __ j(greater, &loop_header, Label::kNear); |   840   __ j(greater, &loop_header, Label::kNear); | 
|   840 } |   841 } | 
|   841  |   842  | 
|   842 }  // end anonymous namespace |   843 }  // end anonymous namespace | 
|   843  |   844  | 
|   844 // static |   845 // static | 
|   845 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( |   846 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( | 
|   846     MacroAssembler* masm, PushArgsConstructMode mode) { |   847     MacroAssembler* masm, PushArgsMode mode) { | 
|   847   // ----------- S t a t e ------------- |   848   // ----------- S t a t e ------------- | 
|   848   //  -- eax : the number of arguments (not including the receiver) |   849   //  -- eax : the number of arguments (not including the receiver) | 
|   849   //  -- edx : the new target |   850   //  -- edx : the new target | 
|   850   //  -- edi : the constructor |   851   //  -- edi : the constructor | 
|   851   //  -- ebx : allocation site feedback (if available or undefined) |   852   //  -- ebx : allocation site feedback (if available or undefined) | 
|   852   //  -- ecx : the address of the first argument to be pushed. Subsequent |   853   //  -- ecx : the address of the first argument to be pushed. Subsequent | 
|   853   //           arguments should be consecutive above this, in the same order as |   854   //           arguments should be consecutive above this, in the same order as | 
|   854   //           they are to be pushed onto the stack. |   855   //           they are to be pushed onto the stack. | 
|   855   // ----------------------------------- |   856   // ----------------------------------- | 
|   856   Label stack_overflow; |   857   Label stack_overflow; | 
|   857   // We need two scratch registers. Push edi and edx onto stack. |   858   // We need two scratch registers. Push edi and edx onto stack. | 
|   858   __ Push(edi); |   859   __ Push(edi); | 
|   859   __ Push(edx); |   860   __ Push(edx); | 
|   860  |   861  | 
|   861   // Push arguments and move return address to the top of stack. |   862   // Push arguments and move return address to the top of stack. | 
|   862   // The eax register is readonly. The ecx register will be modified. The edx |   863   // The eax register is readonly. The ecx register will be modified. The edx | 
|   863   // and edi registers will be modified but restored to their original values. |   864   // and edi registers will be modified but restored to their original values. | 
|   864   Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, |   865   Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, | 
|   865                                                2, &stack_overflow); |   866                                                2, &stack_overflow); | 
|   866  |   867  | 
|   867   // Restore edi and edx |   868   // Restore edi and edx | 
|   868   __ Pop(edx); |   869   __ Pop(edx); | 
|   869   __ Pop(edi); |   870   __ Pop(edi); | 
|   870  |   871  | 
|   871   __ AssertUndefinedOrAllocationSite(ebx); |   872   __ AssertUndefinedOrAllocationSite(ebx); | 
|   872   if (mode == PushArgsConstructMode::kJSFunction) { |   873   if (mode == PushArgsMode::kJSFunction) { | 
|   873     // Tail call to the function-specific construct stub (still in the caller |   874     // Tail call to the function-specific construct stub (still in the caller | 
|   874     // context at this point). |   875     // context at this point). | 
|   875     __ AssertFunction(edi); |   876     __ AssertFunction(edi); | 
|   876  |   877  | 
|   877     __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |   878     __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 
|   878     __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |   879     __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | 
|   879     __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |   880     __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 
|   880     __ jmp(ecx); |   881     __ jmp(ecx); | 
|   881   } else if (mode == PushArgsConstructMode::kWithFinalSpread) { |   882   } else if (mode == PushArgsMode::kWithFinalSpread) { | 
|   882     // Call the constructor with unmodified eax, edi, edx values. |   883     // Call the constructor with unmodified eax, edi, edx values. | 
|   883     __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), |   884     __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), | 
|   884             RelocInfo::CODE_TARGET); |   885             RelocInfo::CODE_TARGET); | 
|   885   } else { |   886   } else { | 
|   886     DCHECK_EQ(PushArgsConstructMode::kOther, mode); |   887     DCHECK_EQ(PushArgsMode::kOther, mode); | 
|   887     // Call the constructor with unmodified eax, edi, edx values. |   888     // Call the constructor with unmodified eax, edi, edx values. | 
|   888     __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |   889     __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 
|   889   } |   890   } | 
|   890  |   891  | 
|   891   __ bind(&stack_overflow); |   892   __ bind(&stack_overflow); | 
|   892   { |   893   { | 
|   893     // Pop the temporary registers, so that return address is on top of stack. |   894     // Pop the temporary registers, so that return address is on top of stack. | 
|   894     __ Pop(edx); |   895     __ Pop(edx); | 
|   895     __ Pop(edi); |   896     __ Pop(edi); | 
|   896  |   897  | 
| (...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2666  |  2667  | 
|  2667   // 3. Call to something that is not callable. |  2668   // 3. Call to something that is not callable. | 
|  2668   __ bind(&non_callable); |  2669   __ bind(&non_callable); | 
|  2669   { |  2670   { | 
|  2670     FrameScope scope(masm, StackFrame::INTERNAL); |  2671     FrameScope scope(masm, StackFrame::INTERNAL); | 
|  2671     __ Push(edi); |  2672     __ Push(edi); | 
|  2672     __ CallRuntime(Runtime::kThrowCalledNonCallable); |  2673     __ CallRuntime(Runtime::kThrowCalledNonCallable); | 
|  2673   } |  2674   } | 
|  2674 } |  2675 } | 
|  2675  |  2676  | 
|  2676 // static |  2677 static void CheckSpreadAndPushToStack(MacroAssembler* masm) { | 
|  2677 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |  | 
|  2678   // ----------- S t a t e ------------- |  | 
|  2679   //  -- eax : the number of arguments (not including the receiver) |  | 
|  2680   //  -- edx : the new target (checked to be a constructor) |  | 
|  2681   //  -- edi : the constructor to call (checked to be a JSFunction) |  | 
|  2682   // ----------------------------------- |  | 
|  2683   __ AssertFunction(edi); |  | 
|  2684  |  | 
|  2685   // Calling convention for function specific ConstructStubs require |  | 
|  2686   // ebx to contain either an AllocationSite or undefined. |  | 
|  2687   __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); |  | 
|  2688  |  | 
|  2689   // Tail call to the function-specific construct stub (still in the caller |  | 
|  2690   // context at this point). |  | 
|  2691   __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |  | 
|  2692   __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |  | 
|  2693   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |  | 
|  2694   __ jmp(ecx); |  | 
|  2695 } |  | 
|  2696  |  | 
|  2697 // static |  | 
|  2698 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { |  | 
|  2699   // ----------- S t a t e ------------- |  | 
|  2700   //  -- eax : the number of arguments (not including the receiver) |  | 
|  2701   //  -- edx : the new target (checked to be a constructor) |  | 
|  2702   //  -- edi : the constructor to call (checked to be a JSBoundFunction) |  | 
|  2703   // ----------------------------------- |  | 
|  2704   __ AssertBoundFunction(edi); |  | 
|  2705  |  | 
|  2706   // Push the [[BoundArguments]] onto the stack. |  | 
|  2707   Generate_PushBoundArguments(masm); |  | 
|  2708  |  | 
|  2709   // Patch new.target to [[BoundTargetFunction]] if new.target equals target. |  | 
|  2710   { |  | 
|  2711     Label done; |  | 
|  2712     __ cmp(edi, edx); |  | 
|  2713     __ j(not_equal, &done, Label::kNear); |  | 
|  2714     __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |  | 
|  2715     __ bind(&done); |  | 
|  2716   } |  | 
|  2717  |  | 
|  2718   // Construct the [[BoundTargetFunction]] via the Construct builtin. |  | 
|  2719   __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |  | 
|  2720   __ mov(ecx, Operand::StaticVariable( |  | 
|  2721                   ExternalReference(Builtins::kConstruct, masm->isolate()))); |  | 
|  2722   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |  | 
|  2723   __ jmp(ecx); |  | 
|  2724 } |  | 
|  2725  |  | 
|  2726 // static |  | 
|  2727 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |  | 
|  2728   // ----------- S t a t e ------------- |  | 
|  2729   //  -- eax : the number of arguments (not including the receiver) |  | 
|  2730   //  -- edi : the constructor to call (checked to be a JSProxy) |  | 
|  2731   //  -- edx : the new target (either the same as the constructor or |  | 
|  2732   //           the JSFunction on which new was invoked initially) |  | 
|  2733   // ----------------------------------- |  | 
|  2734  |  | 
|  2735   // Call into the Runtime for Proxy [[Construct]]. |  | 
|  2736   __ PopReturnAddressTo(ecx); |  | 
|  2737   __ Push(edi); |  | 
|  2738   __ Push(edx); |  | 
|  2739   __ PushReturnAddressFrom(ecx); |  | 
|  2740   // Include the pushed new_target, constructor and the receiver. |  | 
|  2741   __ add(eax, Immediate(3)); |  | 
|  2742   // Tail-call to the runtime. |  | 
|  2743   __ JumpToExternalReference( |  | 
|  2744       ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); |  | 
|  2745 } |  | 
|  2746  |  | 
|  2747 // static |  | 
|  2748 void Builtins::Generate_Construct(MacroAssembler* masm) { |  | 
|  2749   // ----------- S t a t e ------------- |  | 
|  2750   //  -- eax : the number of arguments (not including the receiver) |  | 
|  2751   //  -- edx : the new target (either the same as the constructor or |  | 
|  2752   //           the JSFunction on which new was invoked initially) |  | 
|  2753   //  -- edi : the constructor to call (can be any Object) |  | 
|  2754   // ----------------------------------- |  | 
|  2755  |  | 
|  2756   // Check if target is a Smi. |  | 
|  2757   Label non_constructor; |  | 
|  2758   __ JumpIfSmi(edi, &non_constructor, Label::kNear); |  | 
|  2759  |  | 
|  2760   // Dispatch based on instance type. |  | 
|  2761   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |  | 
|  2762   __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |  | 
|  2763        RelocInfo::CODE_TARGET); |  | 
|  2764  |  | 
|  2765   // Check if target has a [[Construct]] internal method. |  | 
|  2766   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |  | 
|  2767             Immediate(1 << Map::kIsConstructor)); |  | 
|  2768   __ j(zero, &non_constructor, Label::kNear); |  | 
|  2769  |  | 
|  2770   // Only dispatch to bound functions after checking whether they are |  | 
|  2771   // constructors. |  | 
|  2772   __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |  | 
|  2773   __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |  | 
|  2774        RelocInfo::CODE_TARGET); |  | 
|  2775  |  | 
|  2776   // Only dispatch to proxies after checking whether they are constructors. |  | 
|  2777   __ CmpInstanceType(ecx, JS_PROXY_TYPE); |  | 
|  2778   __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |  | 
|  2779        RelocInfo::CODE_TARGET); |  | 
|  2780  |  | 
|  2781   // Called Construct on an exotic Object with a [[Construct]] internal method. |  | 
|  2782   { |  | 
|  2783     // Overwrite the original receiver with the (original) target. |  | 
|  2784     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); |  | 
|  2785     // Let the "call_as_constructor_delegate" take care of the rest. |  | 
|  2786     __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); |  | 
|  2787     __ Jump(masm->isolate()->builtins()->CallFunction(), |  | 
|  2788             RelocInfo::CODE_TARGET); |  | 
|  2789   } |  | 
|  2790  |  | 
|  2791   // Called Construct on an Object that doesn't have a [[Construct]] internal |  | 
|  2792   // method. |  | 
|  2793   __ bind(&non_constructor); |  | 
|  2794   __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), |  | 
|  2795           RelocInfo::CODE_TARGET); |  | 
|  2796 } |  | 
|  2797  |  | 
|  2798 // static |  | 
|  2799 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { |  | 
|  2800   // ----------- S t a t e ------------- |  | 
|  2801   //  -- eax : the number of arguments (not including the receiver) |  | 
|  2802   //  -- edx : the new target (either the same as the constructor or |  | 
|  2803   //           the JSFunction on which new was invoked initially) |  | 
|  2804   //  -- edi : the constructor to call (can be any Object) |  | 
|  2805   // ----------------------------------- |  | 
|  2806  |  | 
|  2807   // Free up some registers. |  2678   // Free up some registers. | 
|  2808   __ movd(xmm0, edx); |  2679   __ movd(xmm0, edx); | 
|  2809   __ movd(xmm1, edi); |  2680   __ movd(xmm1, edi); | 
|  2810  |  2681  | 
|  2811   Register argc = eax; |  2682   Register argc = eax; | 
|  2812  |  2683  | 
|  2813   Register scratch = ecx; |  2684   Register scratch = ecx; | 
|  2814   Register scratch2 = edi; |  2685   Register scratch2 = edi; | 
|  2815  |  2686  | 
|  2816   Register spread = ebx; |  2687   Register spread = ebx; | 
|  2817   Register spread_map = edx; |  2688   Register spread_map = edx; | 
|  2818  |  2689  | 
 |  2690   Register spread_len = edx; | 
 |  2691  | 
|  2819   __ mov(spread, Operand(esp, kPointerSize)); |  2692   __ mov(spread, Operand(esp, kPointerSize)); | 
|  2820   __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); |  2693   __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); | 
|  2821  |  2694  | 
|  2822   Label runtime_call, push_args; |  2695   Label runtime_call, push_args; | 
|  2823   // Check that the spread is an array. |  2696   // Check that the spread is an array. | 
|  2824   __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); |  2697   __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); | 
|  2825   __ j(not_equal, &runtime_call); |  2698   __ j(not_equal, &runtime_call); | 
|  2826  |  2699  | 
|  2827   // Check that we have the original ArrayPrototype. |  2700   // Check that we have the original ArrayPrototype. | 
|  2828   __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); |  2701   __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2861   __ j(equal, &no_protector_check); |  2734   __ j(equal, &no_protector_check); | 
|  2862   __ cmp(scratch, Immediate(FAST_ELEMENTS)); |  2735   __ cmp(scratch, Immediate(FAST_ELEMENTS)); | 
|  2863   __ j(equal, &no_protector_check); |  2736   __ j(equal, &no_protector_check); | 
|  2864   // Check the ArrayProtector cell. |  2737   // Check the ArrayProtector cell. | 
|  2865   __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); |  2738   __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); | 
|  2866   __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |  2739   __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 
|  2867          Immediate(Smi::FromInt(Isolate::kProtectorValid))); |  2740          Immediate(Smi::FromInt(Isolate::kProtectorValid))); | 
|  2868   __ j(not_equal, &runtime_call); |  2741   __ j(not_equal, &runtime_call); | 
|  2869  |  2742  | 
|  2870   __ bind(&no_protector_check); |  2743   __ bind(&no_protector_check); | 
|  2871   // Load the FixedArray backing store. |  2744   // Load the FixedArray backing store, but use the length from the array. | 
 |  2745   __ mov(spread_len, FieldOperand(spread, JSArray::kLengthOffset)); | 
 |  2746   __ SmiUntag(spread_len); | 
|  2872   __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); |  2747   __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); | 
|  2873   // Free up some registers. |  | 
|  2874   __ jmp(&push_args); |  2748   __ jmp(&push_args); | 
|  2875  |  2749  | 
|  2876   __ bind(&runtime_call); |  2750   __ bind(&runtime_call); | 
|  2877   { |  2751   { | 
|  2878     // Call the builtin for the result of the spread. |  2752     // Call the builtin for the result of the spread. | 
|  2879     FrameScope scope(masm, StackFrame::INTERNAL); |  2753     FrameScope scope(masm, StackFrame::INTERNAL); | 
|  2880     // Need to save these on the stack. |  2754     // Need to save these on the stack. | 
|  2881     __ movd(edi, xmm1); |  2755     __ movd(edi, xmm1); | 
|  2882     __ movd(edx, xmm0); |  2756     __ movd(edx, xmm0); | 
|  2883     __ Push(edi); |  2757     __ Push(edi); | 
|  2884     __ Push(edx); |  2758     __ Push(edx); | 
|  2885     __ SmiTag(argc); |  2759     __ SmiTag(argc); | 
|  2886     __ Push(argc); |  2760     __ Push(argc); | 
|  2887     __ Push(spread); |  2761     __ Push(spread); | 
|  2888     __ CallRuntime(Runtime::kSpreadIterableFixed); |  2762     __ CallRuntime(Runtime::kSpreadIterableFixed); | 
|  2889     __ mov(spread, eax); |  2763     __ mov(spread, eax); | 
|  2890     __ Pop(argc); |  2764     __ Pop(argc); | 
|  2891     __ SmiUntag(argc); |  2765     __ SmiUntag(argc); | 
|  2892     __ Pop(edx); |  2766     __ Pop(edx); | 
|  2893     __ Pop(edi); |  2767     __ Pop(edi); | 
|  2894     // Free up some registers. |  2768     // Free up some registers. | 
|  2895     __ movd(xmm0, edx); |  2769     __ movd(xmm0, edx); | 
|  2896     __ movd(xmm1, edi); |  2770     __ movd(xmm1, edi); | 
|  2897   } |  2771   } | 
|  2898  |  2772  | 
|  2899   Register spread_len = edx; |  | 
|  2900   Register return_address = edi; |  2773   Register return_address = edi; | 
|  2901   __ bind(&push_args); |  | 
|  2902   { |  2774   { | 
 |  2775     // Calculate the new nargs including the result of the spread. | 
 |  2776     __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); | 
 |  2777     __ SmiUntag(spread_len); | 
 |  2778  | 
 |  2779     __ bind(&push_args); | 
 |  2780     // argc += spread_len - 1. Subtract 1 for the spread itself. | 
 |  2781     __ lea(argc, Operand(argc, spread_len, times_1, -1)); | 
 |  2782  | 
|  2903     // Pop the return address and spread argument. |  2783     // Pop the return address and spread argument. | 
|  2904     __ PopReturnAddressTo(return_address); |  2784     __ PopReturnAddressTo(return_address); | 
|  2905     __ Pop(scratch); |  2785     __ Pop(scratch); | 
|  2906  |  | 
|  2907     // Calculate the new nargs including the result of the spread. |  | 
|  2908     __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); |  | 
|  2909     __ SmiUntag(spread_len); |  | 
|  2910     // argc += spread_len - 1. Subtract 1 for the spread itself. |  | 
|  2911     __ lea(argc, Operand(argc, spread_len, times_1, -1)); |  | 
|  2912   } |  2786   } | 
|  2913  |  2787  | 
|  2914   // Check for stack overflow. |  2788   // Check for stack overflow. | 
|  2915   { |  2789   { | 
|  2916     // Check the stack for overflow. We are not trying to catch interruptions |  2790     // Check the stack for overflow. We are not trying to catch interruptions | 
|  2917     // (i.e. debug break and preemption) here, so check the "real stack limit". |  2791     // (i.e. debug break and preemption) here, so check the "real stack limit". | 
|  2918     Label done; |  2792     Label done; | 
|  2919     __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); |  2793     __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); | 
|  2920     // Make scratch the space we have left. The stack might already be |  2794     // Make scratch the space we have left. The stack might already be | 
|  2921     // overflowed here which will cause scratch to become negative. |  2795     // overflowed here which will cause scratch to become negative. | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|  2943                                   FixedArray::kHeaderSize)); |  2817                                   FixedArray::kHeaderSize)); | 
|  2944     __ Push(scratch2); |  2818     __ Push(scratch2); | 
|  2945     __ inc(scratch); |  2819     __ inc(scratch); | 
|  2946     __ jmp(&loop); |  2820     __ jmp(&loop); | 
|  2947     __ bind(&done); |  2821     __ bind(&done); | 
|  2948     __ PushReturnAddressFrom(return_address); |  2822     __ PushReturnAddressFrom(return_address); | 
|  2949     __ movd(esi, xmm2); |  2823     __ movd(esi, xmm2); | 
|  2950     __ movd(edi, xmm1); |  2824     __ movd(edi, xmm1); | 
|  2951     __ movd(edx, xmm0); |  2825     __ movd(edx, xmm0); | 
|  2952   } |  2826   } | 
 |  2827 } | 
|  2953  |  2828  | 
|  2954   // Dispatch. |  2829 // static | 
 |  2830 void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { | 
 |  2831   // ----------- S t a t e ------------- | 
 |  2832   //  -- eax : the number of arguments (not including the receiver) | 
 |  2833   //  -- edi : the target to call (can be any Object) | 
 |  2834   // ----------------------------------- | 
 |  2835  | 
 |  2836   // CheckSpreadAndPushToStack will push edx to save it. | 
 |  2837   __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); | 
 |  2838   CheckSpreadAndPushToStack(masm); | 
 |  2839   __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 
 |  2840                                             TailCallMode::kDisallow), | 
 |  2841           RelocInfo::CODE_TARGET); | 
 |  2842 } | 
 |  2843  | 
 |  2844 // static | 
 |  2845 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | 
 |  2846   // ----------- S t a t e ------------- | 
 |  2847   //  -- eax : the number of arguments (not including the receiver) | 
 |  2848   //  -- edx : the new target (checked to be a constructor) | 
 |  2849   //  -- edi : the constructor to call (checked to be a JSFunction) | 
 |  2850   // ----------------------------------- | 
 |  2851   __ AssertFunction(edi); | 
 |  2852  | 
 |  2853   // Calling convention for function specific ConstructStubs require | 
 |  2854   // ebx to contain either an AllocationSite or undefined. | 
 |  2855   __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); | 
 |  2856  | 
 |  2857   // Tail call to the function-specific construct stub (still in the caller | 
 |  2858   // context at this point). | 
 |  2859   __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 
 |  2860   __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | 
 |  2861   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 
 |  2862   __ jmp(ecx); | 
 |  2863 } | 
 |  2864  | 
 |  2865 // static | 
 |  2866 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { | 
 |  2867   // ----------- S t a t e ------------- | 
 |  2868   //  -- eax : the number of arguments (not including the receiver) | 
 |  2869   //  -- edx : the new target (checked to be a constructor) | 
 |  2870   //  -- edi : the constructor to call (checked to be a JSBoundFunction) | 
 |  2871   // ----------------------------------- | 
 |  2872   __ AssertBoundFunction(edi); | 
 |  2873  | 
 |  2874   // Push the [[BoundArguments]] onto the stack. | 
 |  2875   Generate_PushBoundArguments(masm); | 
 |  2876  | 
 |  2877   // Patch new.target to [[BoundTargetFunction]] if new.target equals target. | 
 |  2878   { | 
 |  2879     Label done; | 
 |  2880     __ cmp(edi, edx); | 
 |  2881     __ j(not_equal, &done, Label::kNear); | 
 |  2882     __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); | 
 |  2883     __ bind(&done); | 
 |  2884   } | 
 |  2885  | 
 |  2886   // Construct the [[BoundTargetFunction]] via the Construct builtin. | 
 |  2887   __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); | 
 |  2888   __ mov(ecx, Operand::StaticVariable( | 
 |  2889                   ExternalReference(Builtins::kConstruct, masm->isolate()))); | 
 |  2890   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 
 |  2891   __ jmp(ecx); | 
 |  2892 } | 
 |  2893  | 
 |  2894 // static | 
 |  2895 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | 
 |  2896   // ----------- S t a t e ------------- | 
 |  2897   //  -- eax : the number of arguments (not including the receiver) | 
 |  2898   //  -- edi : the constructor to call (checked to be a JSProxy) | 
 |  2899   //  -- edx : the new target (either the same as the constructor or | 
 |  2900   //           the JSFunction on which new was invoked initially) | 
 |  2901   // ----------------------------------- | 
 |  2902  | 
 |  2903   // Call into the Runtime for Proxy [[Construct]]. | 
 |  2904   __ PopReturnAddressTo(ecx); | 
 |  2905   __ Push(edi); | 
 |  2906   __ Push(edx); | 
 |  2907   __ PushReturnAddressFrom(ecx); | 
 |  2908   // Include the pushed new_target, constructor and the receiver. | 
 |  2909   __ add(eax, Immediate(3)); | 
 |  2910   // Tail-call to the runtime. | 
 |  2911   __ JumpToExternalReference( | 
 |  2912       ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); | 
 |  2913 } | 
 |  2914  | 
 |  2915 // static | 
 |  2916 void Builtins::Generate_Construct(MacroAssembler* masm) { | 
 |  2917   // ----------- S t a t e ------------- | 
 |  2918   //  -- eax : the number of arguments (not including the receiver) | 
 |  2919   //  -- edx : the new target (either the same as the constructor or | 
 |  2920   //           the JSFunction on which new was invoked initially) | 
 |  2921   //  -- edi : the constructor to call (can be any Object) | 
 |  2922   // ----------------------------------- | 
 |  2923  | 
 |  2924   // Check if target is a Smi. | 
 |  2925   Label non_constructor; | 
 |  2926   __ JumpIfSmi(edi, &non_constructor, Label::kNear); | 
 |  2927  | 
 |  2928   // Dispatch based on instance type. | 
 |  2929   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 
 |  2930   __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | 
 |  2931        RelocInfo::CODE_TARGET); | 
 |  2932  | 
 |  2933   // Check if target has a [[Construct]] internal method. | 
 |  2934   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 
 |  2935             Immediate(1 << Map::kIsConstructor)); | 
 |  2936   __ j(zero, &non_constructor, Label::kNear); | 
 |  2937  | 
 |  2938   // Only dispatch to bound functions after checking whether they are | 
 |  2939   // constructors. | 
 |  2940   __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); | 
 |  2941   __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), | 
 |  2942        RelocInfo::CODE_TARGET); | 
 |  2943  | 
 |  2944   // Only dispatch to proxies after checking whether they are constructors. | 
 |  2945   __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 
 |  2946   __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | 
 |  2947        RelocInfo::CODE_TARGET); | 
 |  2948  | 
 |  2949   // Called Construct on an exotic Object with a [[Construct]] internal method. | 
 |  2950   { | 
 |  2951     // Overwrite the original receiver with the (original) target. | 
 |  2952     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); | 
 |  2953     // Let the "call_as_constructor_delegate" take care of the rest. | 
 |  2954     __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); | 
 |  2955     __ Jump(masm->isolate()->builtins()->CallFunction(), | 
 |  2956             RelocInfo::CODE_TARGET); | 
 |  2957   } | 
 |  2958  | 
 |  2959   // Called Construct on an Object that doesn't have a [[Construct]] internal | 
 |  2960   // method. | 
 |  2961   __ bind(&non_constructor); | 
 |  2962   __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), | 
 |  2963           RelocInfo::CODE_TARGET); | 
 |  2964 } | 
 |  2965  | 
 |  2966 // static | 
 |  2967 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { | 
 |  2968   // ----------- S t a t e ------------- | 
 |  2969   //  -- eax : the number of arguments (not including the receiver) | 
 |  2970   //  -- edx : the new target (either the same as the constructor or | 
 |  2971   //           the JSFunction on which new was invoked initially) | 
 |  2972   //  -- edi : the constructor to call (can be any Object) | 
 |  2973   // ----------------------------------- | 
 |  2974  | 
 |  2975   CheckSpreadAndPushToStack(masm); | 
|  2955   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |  2976   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 
|  2956 } |  2977 } | 
|  2957  |  2978  | 
|  2958 // static |  2979 // static | 
|  2959 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { |  2980 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { | 
|  2960   // ----------- S t a t e ------------- |  2981   // ----------- S t a t e ------------- | 
|  2961   //  -- edx    : requested object size (untagged) |  2982   //  -- edx    : requested object size (untagged) | 
|  2962   //  -- esp[0] : return address |  2983   //  -- esp[0] : return address | 
|  2963   // ----------------------------------- |  2984   // ----------------------------------- | 
|  2964   __ SmiTag(edx); |  2985   __ SmiTag(edx); | 
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3270  |  3291  | 
|  3271 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { |  3292 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { | 
|  3272   Generate_OnStackReplacementHelper(masm, true); |  3293   Generate_OnStackReplacementHelper(masm, true); | 
|  3273 } |  3294 } | 
|  3274  |  3295  | 
|  3275 #undef __ |  3296 #undef __ | 
|  3276 }  // namespace internal |  3297 }  // namespace internal | 
|  3277 }  // namespace v8 |  3298 }  // namespace v8 | 
|  3278  |  3299  | 
|  3279 #endif  // V8_TARGET_ARCH_IA32 |  3300 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW |