| 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-stubs.h" |     7 #include "src/code-stubs.h" | 
|     8 #include "src/api-arguments.h" |     8 #include "src/api-arguments.h" | 
|     9 #include "src/base/bits.h" |     9 #include "src/base/bits.h" | 
|    10 #include "src/bootstrapper.h" |    10 #include "src/bootstrapper.h" | 
| (...skipping 3047 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3058  |  3058  | 
|  3059   Label fast_elements_case; |  3059   Label fast_elements_case; | 
|  3060   __ cmp(ecx, Immediate(FAST_ELEMENTS)); |  3060   __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 
|  3061   __ j(equal, &fast_elements_case); |  3061   __ j(equal, &fast_elements_case); | 
|  3062   GenerateCase(masm, FAST_HOLEY_ELEMENTS); |  3062   GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 
|  3063  |  3063  | 
|  3064   __ bind(&fast_elements_case); |  3064   __ bind(&fast_elements_case); | 
|  3065   GenerateCase(masm, FAST_ELEMENTS); |  3065   GenerateCase(masm, FAST_ELEMENTS); | 
|  3066 } |  3066 } | 
|  3067  |  3067  | 
|  3068 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { |  | 
|  3069   // ----------- S t a t e ------------- |  | 
|  3070   //  -- edi    : function |  | 
|  3071   //  -- esi    : context |  | 
|  3072   //  -- ebp    : frame pointer |  | 
|  3073   //  -- esp[0] : return address |  | 
|  3074   // ----------------------------------- |  | 
|  3075   __ AssertFunction(edi); |  | 
|  3076  |  | 
|  3077   // Make edx point to the JavaScript frame. |  | 
|  3078   __ mov(edx, ebp); |  | 
|  3079   if (skip_stub_frame()) { |  | 
|  3080     // For Ignition we need to skip the handler/stub frame to reach the |  | 
|  3081     // JavaScript frame for the function. |  | 
|  3082     __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3083   } |  | 
|  3084   if (FLAG_debug_code) { |  | 
|  3085     Label ok; |  | 
|  3086     __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset)); |  | 
|  3087     __ j(equal, &ok); |  | 
|  3088     __ Abort(kInvalidFrameForFastNewRestArgumentsStub); |  | 
|  3089     __ bind(&ok); |  | 
|  3090   } |  | 
|  3091  |  | 
|  3092   // Check if we have rest parameters (only possible if we have an |  | 
|  3093   // arguments adaptor frame below the function frame). |  | 
|  3094   Label no_rest_parameters; |  | 
|  3095   __ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3096   __ cmp(Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset), |  | 
|  3097          Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |  | 
|  3098   __ j(not_equal, &no_rest_parameters, Label::kNear); |  | 
|  3099  |  | 
|  3100   // Check if the arguments adaptor frame contains more arguments than |  | 
|  3101   // specified by the function's internal formal parameter count. |  | 
|  3102   Label rest_parameters; |  | 
|  3103   __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |  | 
|  3104   __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |  | 
|  3105   __ sub(eax, |  | 
|  3106          FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset)); |  | 
|  3107   __ j(greater, &rest_parameters); |  | 
|  3108  |  | 
|  3109   // Return an empty rest parameter array. |  | 
|  3110   __ bind(&no_rest_parameters); |  | 
|  3111   { |  | 
|  3112     // ----------- S t a t e ------------- |  | 
|  3113     //  -- esi    : context |  | 
|  3114     //  -- esp[0] : return address |  | 
|  3115     // ----------------------------------- |  | 
|  3116  |  | 
|  3117     // Allocate an empty rest parameter array. |  | 
|  3118     Label allocate, done_allocate; |  | 
|  3119     __ Allocate(JSArray::kSize, eax, edx, ecx, &allocate, NO_ALLOCATION_FLAGS); |  | 
|  3120     __ bind(&done_allocate); |  | 
|  3121  |  | 
|  3122     // Setup the rest parameter array in rax. |  | 
|  3123     __ LoadGlobalFunction(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, ecx); |  | 
|  3124     __ mov(FieldOperand(eax, JSArray::kMapOffset), ecx); |  | 
|  3125     __ mov(ecx, isolate()->factory()->empty_fixed_array()); |  | 
|  3126     __ mov(FieldOperand(eax, JSArray::kPropertiesOffset), ecx); |  | 
|  3127     __ mov(FieldOperand(eax, JSArray::kElementsOffset), ecx); |  | 
|  3128     __ mov(FieldOperand(eax, JSArray::kLengthOffset), Immediate(Smi::kZero)); |  | 
|  3129     STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); |  | 
|  3130     __ Ret(); |  | 
|  3131  |  | 
|  3132     // Fall back to %AllocateInNewSpace. |  | 
|  3133     __ bind(&allocate); |  | 
|  3134     { |  | 
|  3135       FrameScope scope(masm, StackFrame::INTERNAL); |  | 
|  3136       __ Push(Smi::FromInt(JSArray::kSize)); |  | 
|  3137       __ CallRuntime(Runtime::kAllocateInNewSpace); |  | 
|  3138     } |  | 
|  3139     __ jmp(&done_allocate); |  | 
|  3140   } |  | 
|  3141  |  | 
|  3142   __ bind(&rest_parameters); |  | 
|  3143   { |  | 
|  3144     // Compute the pointer to the first rest parameter (skippping the receiver). |  | 
|  3145     __ lea(ebx, |  | 
|  3146            Operand(ebx, eax, times_half_pointer_size, |  | 
|  3147                    StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |  | 
|  3148  |  | 
|  3149     // ----------- S t a t e ------------- |  | 
|  3150     //  -- esi    : context |  | 
|  3151     //  -- eax    : number of rest parameters (tagged) |  | 
|  3152     //  -- ebx    : pointer to first rest parameters |  | 
|  3153     //  -- esp[0] : return address |  | 
|  3154     // ----------------------------------- |  | 
|  3155  |  | 
|  3156     // Allocate space for the rest parameter array plus the backing store. |  | 
|  3157     Label allocate, done_allocate; |  | 
|  3158     __ lea(ecx, Operand(eax, times_half_pointer_size, |  | 
|  3159                         JSArray::kSize + FixedArray::kHeaderSize)); |  | 
|  3160     __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS); |  | 
|  3161     __ bind(&done_allocate); |  | 
|  3162  |  | 
|  3163     // Setup the elements array in edx. |  | 
|  3164     __ mov(FieldOperand(edx, FixedArray::kMapOffset), |  | 
|  3165            isolate()->factory()->fixed_array_map()); |  | 
|  3166     __ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax); |  | 
|  3167     { |  | 
|  3168       Label loop, done_loop; |  | 
|  3169       __ Move(ecx, Smi::kZero); |  | 
|  3170       __ bind(&loop); |  | 
|  3171       __ cmp(ecx, eax); |  | 
|  3172       __ j(equal, &done_loop, Label::kNear); |  | 
|  3173       __ mov(edi, Operand(ebx, 0 * kPointerSize)); |  | 
|  3174       __ mov(FieldOperand(edx, ecx, times_half_pointer_size, |  | 
|  3175                           FixedArray::kHeaderSize), |  | 
|  3176              edi); |  | 
|  3177       __ sub(ebx, Immediate(1 * kPointerSize)); |  | 
|  3178       __ add(ecx, Immediate(Smi::FromInt(1))); |  | 
|  3179       __ jmp(&loop); |  | 
|  3180       __ bind(&done_loop); |  | 
|  3181     } |  | 
|  3182  |  | 
|  3183     // Setup the rest parameter array in edi. |  | 
|  3184     __ lea(edi, |  | 
|  3185            Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize)); |  | 
|  3186     __ LoadGlobalFunction(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, ecx); |  | 
|  3187     __ mov(FieldOperand(edi, JSArray::kMapOffset), ecx); |  | 
|  3188     __ mov(FieldOperand(edi, JSArray::kPropertiesOffset), |  | 
|  3189            isolate()->factory()->empty_fixed_array()); |  | 
|  3190     __ mov(FieldOperand(edi, JSArray::kElementsOffset), edx); |  | 
|  3191     __ mov(FieldOperand(edi, JSArray::kLengthOffset), eax); |  | 
|  3192     STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); |  | 
|  3193     __ mov(eax, edi); |  | 
|  3194     __ Ret(); |  | 
|  3195  |  | 
|  3196     // Fall back to %AllocateInNewSpace (if not too big). |  | 
|  3197     Label too_big_for_new_space; |  | 
|  3198     __ bind(&allocate); |  | 
|  3199     __ cmp(ecx, Immediate(kMaxRegularHeapObjectSize)); |  | 
|  3200     __ j(greater, &too_big_for_new_space); |  | 
|  3201     { |  | 
|  3202       FrameScope scope(masm, StackFrame::INTERNAL); |  | 
|  3203       __ SmiTag(ecx); |  | 
|  3204       __ Push(eax); |  | 
|  3205       __ Push(ebx); |  | 
|  3206       __ Push(ecx); |  | 
|  3207       __ CallRuntime(Runtime::kAllocateInNewSpace); |  | 
|  3208       __ mov(edx, eax); |  | 
|  3209       __ Pop(ebx); |  | 
|  3210       __ Pop(eax); |  | 
|  3211     } |  | 
|  3212     __ jmp(&done_allocate); |  | 
|  3213  |  | 
|  3214     // Fall back to %NewRestParameter. |  | 
|  3215     __ bind(&too_big_for_new_space); |  | 
|  3216     __ PopReturnAddressTo(ecx); |  | 
|  3217     // We reload the function from the caller frame due to register pressure |  | 
|  3218     // within this stub. This is the slow path, hence reloading is preferable. |  | 
|  3219     if (skip_stub_frame()) { |  | 
|  3220       // For Ignition we need to skip the handler/stub frame to reach the |  | 
|  3221       // JavaScript frame for the function. |  | 
|  3222       __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3223       __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset)); |  | 
|  3224     } else { |  | 
|  3225       __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset)); |  | 
|  3226     } |  | 
|  3227     __ PushReturnAddressFrom(ecx); |  | 
|  3228     __ TailCallRuntime(Runtime::kNewRestParameter); |  | 
|  3229   } |  | 
|  3230 } |  | 
|  3231  |  | 
|  3232  |  | 
|  3233 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { |  | 
|  3234   // ----------- S t a t e ------------- |  | 
|  3235   //  -- edi    : function |  | 
|  3236   //  -- esi    : context |  | 
|  3237   //  -- ebp    : frame pointer |  | 
|  3238   //  -- esp[0] : return address |  | 
|  3239   // ----------------------------------- |  | 
|  3240   __ AssertFunction(edi); |  | 
|  3241  |  | 
|  3242   // Make ecx point to the JavaScript frame. |  | 
|  3243   __ mov(ecx, ebp); |  | 
|  3244   if (skip_stub_frame()) { |  | 
|  3245     // For Ignition we need to skip the handler/stub frame to reach the |  | 
|  3246     // JavaScript frame for the function. |  | 
|  3247     __ mov(ecx, Operand(ecx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3248   } |  | 
|  3249   if (FLAG_debug_code) { |  | 
|  3250     Label ok; |  | 
|  3251     __ cmp(edi, Operand(ecx, StandardFrameConstants::kFunctionOffset)); |  | 
|  3252     __ j(equal, &ok); |  | 
|  3253     __ Abort(kInvalidFrameForFastNewSloppyArgumentsStub); |  | 
|  3254     __ bind(&ok); |  | 
|  3255   } |  | 
|  3256  |  | 
|  3257   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. |  | 
|  3258   __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |  | 
|  3259   __ mov(ebx, |  | 
|  3260          FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset)); |  | 
|  3261   __ lea(edx, Operand(ecx, ebx, times_half_pointer_size, |  | 
|  3262                       StandardFrameConstants::kCallerSPOffset)); |  | 
|  3263  |  | 
|  3264   // ebx : number of parameters (tagged) |  | 
|  3265   // edx : parameters pointer |  | 
|  3266   // edi : function |  | 
|  3267   // ecx : JavaScript frame pointer. |  | 
|  3268   // esp[0] : return address |  | 
|  3269  |  | 
|  3270   // Check if the calling frame is an arguments adaptor frame. |  | 
|  3271   Label adaptor_frame, try_allocate, runtime; |  | 
|  3272   __ mov(eax, Operand(ecx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3273   __ mov(eax, Operand(eax, CommonFrameConstants::kContextOrFrameTypeOffset)); |  | 
|  3274   __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |  | 
|  3275   __ j(equal, &adaptor_frame, Label::kNear); |  | 
|  3276  |  | 
|  3277   // No adaptor, parameter count = argument count. |  | 
|  3278   __ mov(ecx, ebx); |  | 
|  3279   __ push(ebx); |  | 
|  3280   __ jmp(&try_allocate, Label::kNear); |  | 
|  3281  |  | 
|  3282   // We have an adaptor frame. Patch the parameters pointer. |  | 
|  3283   __ bind(&adaptor_frame); |  | 
|  3284   __ push(ebx); |  | 
|  3285   __ mov(edx, Operand(ecx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3286   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |  | 
|  3287   __ lea(edx, Operand(edx, ecx, times_2, |  | 
|  3288                       StandardFrameConstants::kCallerSPOffset)); |  | 
|  3289  |  | 
|  3290   // ebx = parameter count (tagged) |  | 
|  3291   // ecx = argument count (smi-tagged) |  | 
|  3292   // Compute the mapped parameter count = min(ebx, ecx) in ebx. |  | 
|  3293   __ cmp(ebx, ecx); |  | 
|  3294   __ j(less_equal, &try_allocate, Label::kNear); |  | 
|  3295   __ mov(ebx, ecx); |  | 
|  3296  |  | 
|  3297   // Save mapped parameter count and function. |  | 
|  3298   __ bind(&try_allocate); |  | 
|  3299   __ push(edi); |  | 
|  3300   __ push(ebx); |  | 
|  3301  |  | 
|  3302   // Compute the sizes of backing store, parameter map, and arguments object. |  | 
|  3303   // 1. Parameter map, has 2 extra words containing context and backing store. |  | 
|  3304   const int kParameterMapHeaderSize = |  | 
|  3305       FixedArray::kHeaderSize + 2 * kPointerSize; |  | 
|  3306   Label no_parameter_map; |  | 
|  3307   __ test(ebx, ebx); |  | 
|  3308   __ j(zero, &no_parameter_map, Label::kNear); |  | 
|  3309   __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); |  | 
|  3310   __ bind(&no_parameter_map); |  | 
|  3311  |  | 
|  3312   // 2. Backing store. |  | 
|  3313   __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); |  | 
|  3314  |  | 
|  3315   // 3. Arguments object. |  | 
|  3316   __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); |  | 
|  3317  |  | 
|  3318   // Do the allocation of all three objects in one go. |  | 
|  3319   __ Allocate(ebx, eax, edi, no_reg, &runtime, NO_ALLOCATION_FLAGS); |  | 
|  3320  |  | 
|  3321   // eax = address of new object(s) (tagged) |  | 
|  3322   // ecx = argument count (smi-tagged) |  | 
|  3323   // esp[0] = mapped parameter count (tagged) |  | 
|  3324   // esp[4] = function |  | 
|  3325   // esp[8] = parameter count (tagged) |  | 
|  3326   // Get the arguments map from the current native context into edi. |  | 
|  3327   Label has_mapped_parameters, instantiate; |  | 
|  3328   __ mov(edi, NativeContextOperand()); |  | 
|  3329   __ mov(ebx, Operand(esp, 0 * kPointerSize)); |  | 
|  3330   __ test(ebx, ebx); |  | 
|  3331   __ j(not_zero, &has_mapped_parameters, Label::kNear); |  | 
|  3332   __ mov( |  | 
|  3333       edi, |  | 
|  3334       Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); |  | 
|  3335   __ jmp(&instantiate, Label::kNear); |  | 
|  3336  |  | 
|  3337   __ bind(&has_mapped_parameters); |  | 
|  3338   __ mov(edi, Operand(edi, Context::SlotOffset( |  | 
|  3339                                Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX))); |  | 
|  3340   __ bind(&instantiate); |  | 
|  3341  |  | 
|  3342   // eax = address of new object (tagged) |  | 
|  3343   // ebx = mapped parameter count (tagged) |  | 
|  3344   // ecx = argument count (smi-tagged) |  | 
|  3345   // edi = address of arguments map (tagged) |  | 
|  3346   // esp[0] = mapped parameter count (tagged) |  | 
|  3347   // esp[4] = function |  | 
|  3348   // esp[8] = parameter count (tagged) |  | 
|  3349   // Copy the JS object part. |  | 
|  3350   __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); |  | 
|  3351   __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |  | 
|  3352          masm->isolate()->factory()->empty_fixed_array()); |  | 
|  3353   __ mov(FieldOperand(eax, JSObject::kElementsOffset), |  | 
|  3354          masm->isolate()->factory()->empty_fixed_array()); |  | 
|  3355  |  | 
|  3356   // Set up the callee in-object property. |  | 
|  3357   STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); |  | 
|  3358   __ mov(edi, Operand(esp, 1 * kPointerSize)); |  | 
|  3359   __ AssertNotSmi(edi); |  | 
|  3360   __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); |  | 
|  3361  |  | 
|  3362   // Use the length (smi tagged) and set that as an in-object property too. |  | 
|  3363   __ AssertSmi(ecx); |  | 
|  3364   __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); |  | 
|  3365  |  | 
|  3366   // Set up the elements pointer in the allocated arguments object. |  | 
|  3367   // If we allocated a parameter map, edi will point there, otherwise to the |  | 
|  3368   // backing store. |  | 
|  3369   __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); |  | 
|  3370   __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |  | 
|  3371  |  | 
|  3372   // eax = address of new object (tagged) |  | 
|  3373   // ebx = mapped parameter count (tagged) |  | 
|  3374   // ecx = argument count (tagged) |  | 
|  3375   // edx = address of receiver argument |  | 
|  3376   // edi = address of parameter map or backing store (tagged) |  | 
|  3377   // esp[0] = mapped parameter count (tagged) |  | 
|  3378   // esp[4] = function |  | 
|  3379   // esp[8] = parameter count (tagged) |  | 
|  3380   // Free two registers. |  | 
|  3381   __ push(edx); |  | 
|  3382   __ push(eax); |  | 
|  3383  |  | 
|  3384   // Initialize parameter map. If there are no mapped arguments, we're done. |  | 
|  3385   Label skip_parameter_map; |  | 
|  3386   __ test(ebx, ebx); |  | 
|  3387   __ j(zero, &skip_parameter_map); |  | 
|  3388  |  | 
|  3389   __ mov(FieldOperand(edi, FixedArray::kMapOffset), |  | 
|  3390          Immediate(isolate()->factory()->sloppy_arguments_elements_map())); |  | 
|  3391   __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); |  | 
|  3392   __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); |  | 
|  3393   __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); |  | 
|  3394   __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); |  | 
|  3395   __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); |  | 
|  3396  |  | 
|  3397   // Copy the parameter slots and the holes in the arguments. |  | 
|  3398   // We need to fill in mapped_parameter_count slots. They index the context, |  | 
|  3399   // where parameters are stored in reverse order, at |  | 
|  3400   //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |  | 
|  3401   // The mapped parameter thus need to get indices |  | 
|  3402   //   MIN_CONTEXT_SLOTS+parameter_count-1 .. |  | 
|  3403   //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |  | 
|  3404   // We loop from right to left. |  | 
|  3405   Label parameters_loop, parameters_test; |  | 
|  3406   __ push(ecx); |  | 
|  3407   __ mov(eax, Operand(esp, 3 * kPointerSize)); |  | 
|  3408   __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); |  | 
|  3409   __ add(ebx, Operand(esp, 5 * kPointerSize)); |  | 
|  3410   __ sub(ebx, eax); |  | 
|  3411   __ mov(ecx, isolate()->factory()->the_hole_value()); |  | 
|  3412   __ mov(edx, edi); |  | 
|  3413   __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); |  | 
|  3414   // eax = loop variable (tagged) |  | 
|  3415   // ebx = mapping index (tagged) |  | 
|  3416   // ecx = the hole value |  | 
|  3417   // edx = address of parameter map (tagged) |  | 
|  3418   // edi = address of backing store (tagged) |  | 
|  3419   // esp[0] = argument count (tagged) |  | 
|  3420   // esp[4] = address of new object (tagged) |  | 
|  3421   // esp[8] = address of receiver argument |  | 
|  3422   // esp[12] = mapped parameter count (tagged) |  | 
|  3423   // esp[16] = function |  | 
|  3424   // esp[20] = parameter count (tagged) |  | 
|  3425   __ jmp(¶meters_test, Label::kNear); |  | 
|  3426  |  | 
|  3427   __ bind(¶meters_loop); |  | 
|  3428   __ sub(eax, Immediate(Smi::FromInt(1))); |  | 
|  3429   __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); |  | 
|  3430   __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); |  | 
|  3431   __ add(ebx, Immediate(Smi::FromInt(1))); |  | 
|  3432   __ bind(¶meters_test); |  | 
|  3433   __ test(eax, eax); |  | 
|  3434   __ j(not_zero, ¶meters_loop, Label::kNear); |  | 
|  3435   __ pop(ecx); |  | 
|  3436  |  | 
|  3437   __ bind(&skip_parameter_map); |  | 
|  3438  |  | 
|  3439   // ecx = argument count (tagged) |  | 
|  3440   // edi = address of backing store (tagged) |  | 
|  3441   // esp[0] = address of new object (tagged) |  | 
|  3442   // esp[4] = address of receiver argument |  | 
|  3443   // esp[8] = mapped parameter count (tagged) |  | 
|  3444   // esp[12] = function |  | 
|  3445   // esp[16] = parameter count (tagged) |  | 
|  3446   // Copy arguments header and remaining slots (if there are any). |  | 
|  3447   __ mov(FieldOperand(edi, FixedArray::kMapOffset), |  | 
|  3448          Immediate(isolate()->factory()->fixed_array_map())); |  | 
|  3449   __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |  | 
|  3450  |  | 
|  3451   Label arguments_loop, arguments_test; |  | 
|  3452   __ mov(ebx, Operand(esp, 2 * kPointerSize)); |  | 
|  3453   __ mov(edx, Operand(esp, 1 * kPointerSize)); |  | 
|  3454   __ sub(edx, ebx);  // Is there a smarter way to do negative scaling? |  | 
|  3455   __ sub(edx, ebx); |  | 
|  3456   __ jmp(&arguments_test, Label::kNear); |  | 
|  3457  |  | 
|  3458   __ bind(&arguments_loop); |  | 
|  3459   __ sub(edx, Immediate(kPointerSize)); |  | 
|  3460   __ mov(eax, Operand(edx, 0)); |  | 
|  3461   __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); |  | 
|  3462   __ add(ebx, Immediate(Smi::FromInt(1))); |  | 
|  3463  |  | 
|  3464   __ bind(&arguments_test); |  | 
|  3465   __ cmp(ebx, ecx); |  | 
|  3466   __ j(less, &arguments_loop, Label::kNear); |  | 
|  3467  |  | 
|  3468   // Restore. |  | 
|  3469   __ pop(eax);  // Address of arguments object. |  | 
|  3470   __ Drop(4); |  | 
|  3471  |  | 
|  3472   // Return. |  | 
|  3473   __ ret(0); |  | 
|  3474  |  | 
|  3475   // Do the runtime call to allocate the arguments object. |  | 
|  3476   __ bind(&runtime); |  | 
|  3477   __ pop(eax);   // Remove saved mapped parameter count. |  | 
|  3478   __ pop(edi);   // Pop saved function. |  | 
|  3479   __ pop(eax);   // Remove saved parameter count. |  | 
|  3480   __ pop(eax);   // Pop return address. |  | 
|  3481   __ push(edi);  // Push function. |  | 
|  3482   __ push(edx);  // Push parameters pointer. |  | 
|  3483   __ push(ecx);  // Push parameter count. |  | 
|  3484   __ push(eax);  // Push return address. |  | 
|  3485   __ TailCallRuntime(Runtime::kNewSloppyArguments); |  | 
|  3486 } |  | 
|  3487  |  | 
|  3488 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |  | 
|  3489   // ----------- S t a t e ------------- |  | 
|  3490   //  -- edi    : function |  | 
|  3491   //  -- esi    : context |  | 
|  3492   //  -- ebp    : frame pointer |  | 
|  3493   //  -- esp[0] : return address |  | 
|  3494   // ----------------------------------- |  | 
|  3495   __ AssertFunction(edi); |  | 
|  3496  |  | 
|  3497   // Make edx point to the JavaScript frame. |  | 
|  3498   __ mov(edx, ebp); |  | 
|  3499   if (skip_stub_frame()) { |  | 
|  3500     // For Ignition we need to skip the handler/stub frame to reach the |  | 
|  3501     // JavaScript frame for the function. |  | 
|  3502     __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3503   } |  | 
|  3504   if (FLAG_debug_code) { |  | 
|  3505     Label ok; |  | 
|  3506     __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset)); |  | 
|  3507     __ j(equal, &ok); |  | 
|  3508     __ Abort(kInvalidFrameForFastNewStrictArgumentsStub); |  | 
|  3509     __ bind(&ok); |  | 
|  3510   } |  | 
|  3511  |  | 
|  3512   // Check if we have an arguments adaptor frame below the function frame. |  | 
|  3513   Label arguments_adaptor, arguments_done; |  | 
|  3514   __ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3515   __ cmp(Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset), |  | 
|  3516          Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |  | 
|  3517   __ j(equal, &arguments_adaptor, Label::kNear); |  | 
|  3518   { |  | 
|  3519     __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |  | 
|  3520     __ mov(eax, |  | 
|  3521            FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset)); |  | 
|  3522     __ lea(ebx, |  | 
|  3523            Operand(edx, eax, times_half_pointer_size, |  | 
|  3524                    StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |  | 
|  3525   } |  | 
|  3526   __ jmp(&arguments_done, Label::kNear); |  | 
|  3527   __ bind(&arguments_adaptor); |  | 
|  3528   { |  | 
|  3529     __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |  | 
|  3530     __ lea(ebx, |  | 
|  3531            Operand(ebx, eax, times_half_pointer_size, |  | 
|  3532                    StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |  | 
|  3533   } |  | 
|  3534   __ bind(&arguments_done); |  | 
|  3535  |  | 
|  3536   // ----------- S t a t e ------------- |  | 
|  3537   //  -- eax    : number of arguments (tagged) |  | 
|  3538   //  -- ebx    : pointer to the first argument |  | 
|  3539   //  -- esi    : context |  | 
|  3540   //  -- esp[0] : return address |  | 
|  3541   // ----------------------------------- |  | 
|  3542  |  | 
|  3543   // Allocate space for the strict arguments object plus the backing store. |  | 
|  3544   Label allocate, done_allocate; |  | 
|  3545   __ lea(ecx, |  | 
|  3546          Operand(eax, times_half_pointer_size, |  | 
|  3547                  JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); |  | 
|  3548   __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS); |  | 
|  3549   __ bind(&done_allocate); |  | 
|  3550  |  | 
|  3551   // Setup the elements array in edx. |  | 
|  3552   __ mov(FieldOperand(edx, FixedArray::kMapOffset), |  | 
|  3553          isolate()->factory()->fixed_array_map()); |  | 
|  3554   __ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax); |  | 
|  3555   { |  | 
|  3556     Label loop, done_loop; |  | 
|  3557     __ Move(ecx, Smi::kZero); |  | 
|  3558     __ bind(&loop); |  | 
|  3559     __ cmp(ecx, eax); |  | 
|  3560     __ j(equal, &done_loop, Label::kNear); |  | 
|  3561     __ mov(edi, Operand(ebx, 0 * kPointerSize)); |  | 
|  3562     __ mov(FieldOperand(edx, ecx, times_half_pointer_size, |  | 
|  3563                         FixedArray::kHeaderSize), |  | 
|  3564            edi); |  | 
|  3565     __ sub(ebx, Immediate(1 * kPointerSize)); |  | 
|  3566     __ add(ecx, Immediate(Smi::FromInt(1))); |  | 
|  3567     __ jmp(&loop); |  | 
|  3568     __ bind(&done_loop); |  | 
|  3569   } |  | 
|  3570  |  | 
|  3571   // Setup the rest parameter array in edi. |  | 
|  3572   __ lea(edi, |  | 
|  3573          Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize)); |  | 
|  3574   __ LoadGlobalFunction(Context::STRICT_ARGUMENTS_MAP_INDEX, ecx); |  | 
|  3575   __ mov(FieldOperand(edi, JSStrictArgumentsObject::kMapOffset), ecx); |  | 
|  3576   __ mov(FieldOperand(edi, JSStrictArgumentsObject::kPropertiesOffset), |  | 
|  3577          isolate()->factory()->empty_fixed_array()); |  | 
|  3578   __ mov(FieldOperand(edi, JSStrictArgumentsObject::kElementsOffset), edx); |  | 
|  3579   __ mov(FieldOperand(edi, JSStrictArgumentsObject::kLengthOffset), eax); |  | 
|  3580   STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); |  | 
|  3581   __ mov(eax, edi); |  | 
|  3582   __ Ret(); |  | 
|  3583  |  | 
|  3584   // Fall back to %AllocateInNewSpace (if not too big). |  | 
|  3585   Label too_big_for_new_space; |  | 
|  3586   __ bind(&allocate); |  | 
|  3587   __ cmp(ecx, Immediate(kMaxRegularHeapObjectSize)); |  | 
|  3588   __ j(greater, &too_big_for_new_space); |  | 
|  3589   { |  | 
|  3590     FrameScope scope(masm, StackFrame::INTERNAL); |  | 
|  3591     __ SmiTag(ecx); |  | 
|  3592     __ Push(eax); |  | 
|  3593     __ Push(ebx); |  | 
|  3594     __ Push(ecx); |  | 
|  3595     __ CallRuntime(Runtime::kAllocateInNewSpace); |  | 
|  3596     __ mov(edx, eax); |  | 
|  3597     __ Pop(ebx); |  | 
|  3598     __ Pop(eax); |  | 
|  3599   } |  | 
|  3600   __ jmp(&done_allocate); |  | 
|  3601  |  | 
|  3602   // Fall back to %NewStrictArguments. |  | 
|  3603   __ bind(&too_big_for_new_space); |  | 
|  3604   __ PopReturnAddressTo(ecx); |  | 
|  3605   // We reload the function from the caller frame due to register pressure |  | 
|  3606   // within this stub. This is the slow path, hence reloading is preferable. |  | 
|  3607   if (skip_stub_frame()) { |  | 
|  3608     // For Ignition we need to skip the handler/stub frame to reach the |  | 
|  3609     // JavaScript frame for the function. |  | 
|  3610     __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |  | 
|  3611     __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset)); |  | 
|  3612   } else { |  | 
|  3613     __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset)); |  | 
|  3614   } |  | 
|  3615   __ PushReturnAddressFrom(ecx); |  | 
|  3616   __ TailCallRuntime(Runtime::kNewStrictArguments); |  | 
|  3617 } |  | 
|  3618  |  | 
|  3619  |  | 
|  3620 // Generates an Operand for saving parameters after PrepareCallApiFunction. |  3068 // Generates an Operand for saving parameters after PrepareCallApiFunction. | 
|  3621 static Operand ApiParameterOperand(int index) { |  3069 static Operand ApiParameterOperand(int index) { | 
|  3622   return Operand(esp, index * kPointerSize); |  3070   return Operand(esp, index * kPointerSize); | 
|  3623 } |  3071 } | 
|  3624  |  3072  | 
|  3625  |  3073  | 
|  3626 // Prepares stack to put arguments (aligns and so on). Reserves |  3074 // Prepares stack to put arguments (aligns and so on). Reserves | 
|  3627 // space for return value if needed (assumes the return value is a handle). |  3075 // space for return value if needed (assumes the return value is a handle). | 
|  3628 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) |  3076 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) | 
|  3629 // etc. Saves context (esi). If space was reserved for return value then |  3077 // etc. Saves context (esi). If space was reserved for return value then | 
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3994                            kStackUnwindSpace, nullptr, return_value_operand, |  3442                            kStackUnwindSpace, nullptr, return_value_operand, | 
|  3995                            NULL); |  3443                            NULL); | 
|  3996 } |  3444 } | 
|  3997  |  3445  | 
|  3998 #undef __ |  3446 #undef __ | 
|  3999  |  3447  | 
|  4000 }  // namespace internal |  3448 }  // namespace internal | 
|  4001 }  // namespace v8 |  3449 }  // namespace v8 | 
|  4002  |  3450  | 
|  4003 #endif  // V8_TARGET_ARCH_IA32 |  3451 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW |