Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 2645743002: [builtins] Port parameter and argument-related code stubs to CSA (Closed)
Patch Set: Review feedback Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/full-codegen/x64/full-codegen-x64.cc ('k') | src/ia32/interface-descriptors-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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(&parameters_test, Label::kNear);
3426
3427 __ bind(&parameters_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(&parameters_test);
3433 __ test(eax, eax);
3434 __ j(not_zero, &parameters_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
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
OLDNEW
« no previous file with comments | « src/full-codegen/x64/full-codegen-x64.cc ('k') | src/ia32/interface-descriptors-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698