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

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: Remove stray change 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
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 3254 matching lines...) Expand 10 before | Expand all | Expand 10 after
3265 3265
3266 Label fast_elements_case; 3266 Label fast_elements_case;
3267 __ cmp(ecx, Immediate(FAST_ELEMENTS)); 3267 __ cmp(ecx, Immediate(FAST_ELEMENTS));
3268 __ j(equal, &fast_elements_case); 3268 __ j(equal, &fast_elements_case);
3269 GenerateCase(masm, FAST_HOLEY_ELEMENTS); 3269 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
3270 3270
3271 __ bind(&fast_elements_case); 3271 __ bind(&fast_elements_case);
3272 GenerateCase(masm, FAST_ELEMENTS); 3272 GenerateCase(masm, FAST_ELEMENTS);
3273 } 3273 }
3274 3274
3275 void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
3276 // ----------- S t a t e -------------
3277 // -- edi : function
3278 // -- esi : context
3279 // -- ebp : frame pointer
3280 // -- esp[0] : return address
3281 // -----------------------------------
3282 __ AssertFunction(edi);
3283
3284 // Make edx point to the JavaScript frame.
3285 __ mov(edx, ebp);
3286 if (skip_stub_frame()) {
3287 // For Ignition we need to skip the handler/stub frame to reach the
3288 // JavaScript frame for the function.
3289 __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
3290 }
3291 if (FLAG_debug_code) {
3292 Label ok;
3293 __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset));
3294 __ j(equal, &ok);
3295 __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
3296 __ bind(&ok);
3297 }
3298
3299 // Check if we have rest parameters (only possible if we have an
3300 // arguments adaptor frame below the function frame).
3301 Label no_rest_parameters;
3302 __ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
3303 __ cmp(Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset),
3304 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3305 __ j(not_equal, &no_rest_parameters, Label::kNear);
3306
3307 // Check if the arguments adaptor frame contains more arguments than
3308 // specified by the function's internal formal parameter count.
3309 Label rest_parameters;
3310 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3311 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3312 __ sub(eax,
3313 FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
3314 __ j(greater, &rest_parameters);
3315
3316 // Return an empty rest parameter array.
3317 __ bind(&no_rest_parameters);
3318 {
3319 // ----------- S t a t e -------------
3320 // -- esi : context
3321 // -- esp[0] : return address
3322 // -----------------------------------
3323
3324 // Allocate an empty rest parameter array.
3325 Label allocate, done_allocate;
3326 __ Allocate(JSArray::kSize, eax, edx, ecx, &allocate, NO_ALLOCATION_FLAGS);
3327 __ bind(&done_allocate);
3328
3329 // Setup the rest parameter array in rax.
3330 __ LoadGlobalFunction(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, ecx);
3331 __ mov(FieldOperand(eax, JSArray::kMapOffset), ecx);
3332 __ mov(ecx, isolate()->factory()->empty_fixed_array());
3333 __ mov(FieldOperand(eax, JSArray::kPropertiesOffset), ecx);
3334 __ mov(FieldOperand(eax, JSArray::kElementsOffset), ecx);
3335 __ mov(FieldOperand(eax, JSArray::kLengthOffset), Immediate(Smi::kZero));
3336 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
3337 __ Ret();
3338
3339 // Fall back to %AllocateInNewSpace.
3340 __ bind(&allocate);
3341 {
3342 FrameScope scope(masm, StackFrame::INTERNAL);
3343 __ Push(Smi::FromInt(JSArray::kSize));
3344 __ CallRuntime(Runtime::kAllocateInNewSpace);
3345 }
3346 __ jmp(&done_allocate);
3347 }
3348
3349 __ bind(&rest_parameters);
3350 {
3351 // Compute the pointer to the first rest parameter (skippping the receiver).
3352 __ lea(ebx,
3353 Operand(ebx, eax, times_half_pointer_size,
3354 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
3355
3356 // ----------- S t a t e -------------
3357 // -- esi : context
3358 // -- eax : number of rest parameters (tagged)
3359 // -- ebx : pointer to first rest parameters
3360 // -- esp[0] : return address
3361 // -----------------------------------
3362
3363 // Allocate space for the rest parameter array plus the backing store.
3364 Label allocate, done_allocate;
3365 __ lea(ecx, Operand(eax, times_half_pointer_size,
3366 JSArray::kSize + FixedArray::kHeaderSize));
3367 __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
3368 __ bind(&done_allocate);
3369
3370 // Setup the elements array in edx.
3371 __ mov(FieldOperand(edx, FixedArray::kMapOffset),
3372 isolate()->factory()->fixed_array_map());
3373 __ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax);
3374 {
3375 Label loop, done_loop;
3376 __ Move(ecx, Smi::kZero);
3377 __ bind(&loop);
3378 __ cmp(ecx, eax);
3379 __ j(equal, &done_loop, Label::kNear);
3380 __ mov(edi, Operand(ebx, 0 * kPointerSize));
3381 __ mov(FieldOperand(edx, ecx, times_half_pointer_size,
3382 FixedArray::kHeaderSize),
3383 edi);
3384 __ sub(ebx, Immediate(1 * kPointerSize));
3385 __ add(ecx, Immediate(Smi::FromInt(1)));
3386 __ jmp(&loop);
3387 __ bind(&done_loop);
3388 }
3389
3390 // Setup the rest parameter array in edi.
3391 __ lea(edi,
3392 Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize));
3393 __ LoadGlobalFunction(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, ecx);
3394 __ mov(FieldOperand(edi, JSArray::kMapOffset), ecx);
3395 __ mov(FieldOperand(edi, JSArray::kPropertiesOffset),
3396 isolate()->factory()->empty_fixed_array());
3397 __ mov(FieldOperand(edi, JSArray::kElementsOffset), edx);
3398 __ mov(FieldOperand(edi, JSArray::kLengthOffset), eax);
3399 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
3400 __ mov(eax, edi);
3401 __ Ret();
3402
3403 // Fall back to %AllocateInNewSpace (if not too big).
3404 Label too_big_for_new_space;
3405 __ bind(&allocate);
3406 __ cmp(ecx, Immediate(kMaxRegularHeapObjectSize));
3407 __ j(greater, &too_big_for_new_space);
3408 {
3409 FrameScope scope(masm, StackFrame::INTERNAL);
3410 __ SmiTag(ecx);
3411 __ Push(eax);
3412 __ Push(ebx);
3413 __ Push(ecx);
3414 __ CallRuntime(Runtime::kAllocateInNewSpace);
3415 __ mov(edx, eax);
3416 __ Pop(ebx);
3417 __ Pop(eax);
3418 }
3419 __ jmp(&done_allocate);
3420
3421 // Fall back to %NewRestParameter.
3422 __ bind(&too_big_for_new_space);
3423 __ PopReturnAddressTo(ecx);
3424 // We reload the function from the caller frame due to register pressure
3425 // within this stub. This is the slow path, hence reloading is preferable.
3426 if (skip_stub_frame()) {
3427 // For Ignition we need to skip the handler/stub frame to reach the
3428 // JavaScript frame for the function.
3429 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3430 __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset));
3431 } else {
3432 __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset));
3433 }
3434 __ PushReturnAddressFrom(ecx);
3435 __ TailCallRuntime(Runtime::kNewRestParameter);
3436 }
3437 }
3438
3439
3440 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) {
3441 // ----------- S t a t e -------------
3442 // -- edi : function
3443 // -- esi : context
3444 // -- ebp : frame pointer
3445 // -- esp[0] : return address
3446 // -----------------------------------
3447 __ AssertFunction(edi);
3448
3449 // Make ecx point to the JavaScript frame.
3450 __ mov(ecx, ebp);
3451 if (skip_stub_frame()) {
3452 // For Ignition we need to skip the handler/stub frame to reach the
3453 // JavaScript frame for the function.
3454 __ mov(ecx, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
3455 }
3456 if (FLAG_debug_code) {
3457 Label ok;
3458 __ cmp(edi, Operand(ecx, StandardFrameConstants::kFunctionOffset));
3459 __ j(equal, &ok);
3460 __ Abort(kInvalidFrameForFastNewSloppyArgumentsStub);
3461 __ bind(&ok);
3462 }
3463
3464 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
3465 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3466 __ mov(ebx,
3467 FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
3468 __ lea(edx, Operand(ecx, ebx, times_half_pointer_size,
3469 StandardFrameConstants::kCallerSPOffset));
3470
3471 // ebx : number of parameters (tagged)
3472 // edx : parameters pointer
3473 // edi : function
3474 // ecx : JavaScript frame pointer.
3475 // esp[0] : return address
3476
3477 // Check if the calling frame is an arguments adaptor frame.
3478 Label adaptor_frame, try_allocate, runtime;
3479 __ mov(eax, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
3480 __ mov(eax, Operand(eax, CommonFrameConstants::kContextOrFrameTypeOffset));
3481 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3482 __ j(equal, &adaptor_frame, Label::kNear);
3483
3484 // No adaptor, parameter count = argument count.
3485 __ mov(ecx, ebx);
3486 __ push(ebx);
3487 __ jmp(&try_allocate, Label::kNear);
3488
3489 // We have an adaptor frame. Patch the parameters pointer.
3490 __ bind(&adaptor_frame);
3491 __ push(ebx);
3492 __ mov(edx, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
3493 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3494 __ lea(edx, Operand(edx, ecx, times_2,
3495 StandardFrameConstants::kCallerSPOffset));
3496
3497 // ebx = parameter count (tagged)
3498 // ecx = argument count (smi-tagged)
3499 // Compute the mapped parameter count = min(ebx, ecx) in ebx.
3500 __ cmp(ebx, ecx);
3501 __ j(less_equal, &try_allocate, Label::kNear);
3502 __ mov(ebx, ecx);
3503
3504 // Save mapped parameter count and function.
3505 __ bind(&try_allocate);
3506 __ push(edi);
3507 __ push(ebx);
3508
3509 // Compute the sizes of backing store, parameter map, and arguments object.
3510 // 1. Parameter map, has 2 extra words containing context and backing store.
3511 const int kParameterMapHeaderSize =
3512 FixedArray::kHeaderSize + 2 * kPointerSize;
3513 Label no_parameter_map;
3514 __ test(ebx, ebx);
3515 __ j(zero, &no_parameter_map, Label::kNear);
3516 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize));
3517 __ bind(&no_parameter_map);
3518
3519 // 2. Backing store.
3520 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
3521
3522 // 3. Arguments object.
3523 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize));
3524
3525 // Do the allocation of all three objects in one go.
3526 __ Allocate(ebx, eax, edi, no_reg, &runtime, NO_ALLOCATION_FLAGS);
3527
3528 // eax = address of new object(s) (tagged)
3529 // ecx = argument count (smi-tagged)
3530 // esp[0] = mapped parameter count (tagged)
3531 // esp[4] = function
3532 // esp[8] = parameter count (tagged)
3533 // Get the arguments map from the current native context into edi.
3534 Label has_mapped_parameters, instantiate;
3535 __ mov(edi, NativeContextOperand());
3536 __ mov(ebx, Operand(esp, 0 * kPointerSize));
3537 __ test(ebx, ebx);
3538 __ j(not_zero, &has_mapped_parameters, Label::kNear);
3539 __ mov(
3540 edi,
3541 Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX)));
3542 __ jmp(&instantiate, Label::kNear);
3543
3544 __ bind(&has_mapped_parameters);
3545 __ mov(edi, Operand(edi, Context::SlotOffset(
3546 Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX)));
3547 __ bind(&instantiate);
3548
3549 // eax = address of new object (tagged)
3550 // ebx = mapped parameter count (tagged)
3551 // ecx = argument count (smi-tagged)
3552 // edi = address of arguments map (tagged)
3553 // esp[0] = mapped parameter count (tagged)
3554 // esp[4] = function
3555 // esp[8] = parameter count (tagged)
3556 // Copy the JS object part.
3557 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi);
3558 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
3559 masm->isolate()->factory()->empty_fixed_array());
3560 __ mov(FieldOperand(eax, JSObject::kElementsOffset),
3561 masm->isolate()->factory()->empty_fixed_array());
3562
3563 // Set up the callee in-object property.
3564 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1);
3565 __ mov(edi, Operand(esp, 1 * kPointerSize));
3566 __ AssertNotSmi(edi);
3567 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi);
3568
3569 // Use the length (smi tagged) and set that as an in-object property too.
3570 __ AssertSmi(ecx);
3571 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx);
3572
3573 // Set up the elements pointer in the allocated arguments object.
3574 // If we allocated a parameter map, edi will point there, otherwise to the
3575 // backing store.
3576 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize));
3577 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
3578
3579 // eax = address of new object (tagged)
3580 // ebx = mapped parameter count (tagged)
3581 // ecx = argument count (tagged)
3582 // edx = address of receiver argument
3583 // edi = address of parameter map or backing store (tagged)
3584 // esp[0] = mapped parameter count (tagged)
3585 // esp[4] = function
3586 // esp[8] = parameter count (tagged)
3587 // Free two registers.
3588 __ push(edx);
3589 __ push(eax);
3590
3591 // Initialize parameter map. If there are no mapped arguments, we're done.
3592 Label skip_parameter_map;
3593 __ test(ebx, ebx);
3594 __ j(zero, &skip_parameter_map);
3595
3596 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
3597 Immediate(isolate()->factory()->sloppy_arguments_elements_map()));
3598 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2))));
3599 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax);
3600 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi);
3601 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize));
3602 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax);
3603
3604 // Copy the parameter slots and the holes in the arguments.
3605 // We need to fill in mapped_parameter_count slots. They index the context,
3606 // where parameters are stored in reverse order, at
3607 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
3608 // The mapped parameter thus need to get indices
3609 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
3610 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
3611 // We loop from right to left.
3612 Label parameters_loop, parameters_test;
3613 __ push(ecx);
3614 __ mov(eax, Operand(esp, 3 * kPointerSize));
3615 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
3616 __ add(ebx, Operand(esp, 5 * kPointerSize));
3617 __ sub(ebx, eax);
3618 __ mov(ecx, isolate()->factory()->the_hole_value());
3619 __ mov(edx, edi);
3620 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize));
3621 // eax = loop variable (tagged)
3622 // ebx = mapping index (tagged)
3623 // ecx = the hole value
3624 // edx = address of parameter map (tagged)
3625 // edi = address of backing store (tagged)
3626 // esp[0] = argument count (tagged)
3627 // esp[4] = address of new object (tagged)
3628 // esp[8] = address of receiver argument
3629 // esp[12] = mapped parameter count (tagged)
3630 // esp[16] = function
3631 // esp[20] = parameter count (tagged)
3632 __ jmp(&parameters_test, Label::kNear);
3633
3634 __ bind(&parameters_loop);
3635 __ sub(eax, Immediate(Smi::FromInt(1)));
3636 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx);
3637 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx);
3638 __ add(ebx, Immediate(Smi::FromInt(1)));
3639 __ bind(&parameters_test);
3640 __ test(eax, eax);
3641 __ j(not_zero, &parameters_loop, Label::kNear);
3642 __ pop(ecx);
3643
3644 __ bind(&skip_parameter_map);
3645
3646 // ecx = argument count (tagged)
3647 // edi = address of backing store (tagged)
3648 // esp[0] = address of new object (tagged)
3649 // esp[4] = address of receiver argument
3650 // esp[8] = mapped parameter count (tagged)
3651 // esp[12] = function
3652 // esp[16] = parameter count (tagged)
3653 // Copy arguments header and remaining slots (if there are any).
3654 __ mov(FieldOperand(edi, FixedArray::kMapOffset),
3655 Immediate(isolate()->factory()->fixed_array_map()));
3656 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
3657
3658 Label arguments_loop, arguments_test;
3659 __ mov(ebx, Operand(esp, 2 * kPointerSize));
3660 __ mov(edx, Operand(esp, 1 * kPointerSize));
3661 __ sub(edx, ebx); // Is there a smarter way to do negative scaling?
3662 __ sub(edx, ebx);
3663 __ jmp(&arguments_test, Label::kNear);
3664
3665 __ bind(&arguments_loop);
3666 __ sub(edx, Immediate(kPointerSize));
3667 __ mov(eax, Operand(edx, 0));
3668 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax);
3669 __ add(ebx, Immediate(Smi::FromInt(1)));
3670
3671 __ bind(&arguments_test);
3672 __ cmp(ebx, ecx);
3673 __ j(less, &arguments_loop, Label::kNear);
3674
3675 // Restore.
3676 __ pop(eax); // Address of arguments object.
3677 __ Drop(4);
3678
3679 // Return.
3680 __ ret(0);
3681
3682 // Do the runtime call to allocate the arguments object.
3683 __ bind(&runtime);
3684 __ pop(eax); // Remove saved mapped parameter count.
3685 __ pop(edi); // Pop saved function.
3686 __ pop(eax); // Remove saved parameter count.
3687 __ pop(eax); // Pop return address.
3688 __ push(edi); // Push function.
3689 __ push(edx); // Push parameters pointer.
3690 __ push(ecx); // Push parameter count.
3691 __ push(eax); // Push return address.
3692 __ TailCallRuntime(Runtime::kNewSloppyArguments);
3693 }
3694
3695 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
3696 // ----------- S t a t e -------------
3697 // -- edi : function
3698 // -- esi : context
3699 // -- ebp : frame pointer
3700 // -- esp[0] : return address
3701 // -----------------------------------
3702 __ AssertFunction(edi);
3703
3704 // Make edx point to the JavaScript frame.
3705 __ mov(edx, ebp);
3706 if (skip_stub_frame()) {
3707 // For Ignition we need to skip the handler/stub frame to reach the
3708 // JavaScript frame for the function.
3709 __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
3710 }
3711 if (FLAG_debug_code) {
3712 Label ok;
3713 __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset));
3714 __ j(equal, &ok);
3715 __ Abort(kInvalidFrameForFastNewStrictArgumentsStub);
3716 __ bind(&ok);
3717 }
3718
3719 // Check if we have an arguments adaptor frame below the function frame.
3720 Label arguments_adaptor, arguments_done;
3721 __ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
3722 __ cmp(Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset),
3723 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3724 __ j(equal, &arguments_adaptor, Label::kNear);
3725 {
3726 __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3727 __ mov(eax,
3728 FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset));
3729 __ lea(ebx,
3730 Operand(edx, eax, times_half_pointer_size,
3731 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
3732 }
3733 __ jmp(&arguments_done, Label::kNear);
3734 __ bind(&arguments_adaptor);
3735 {
3736 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3737 __ lea(ebx,
3738 Operand(ebx, eax, times_half_pointer_size,
3739 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
3740 }
3741 __ bind(&arguments_done);
3742
3743 // ----------- S t a t e -------------
3744 // -- eax : number of arguments (tagged)
3745 // -- ebx : pointer to the first argument
3746 // -- esi : context
3747 // -- esp[0] : return address
3748 // -----------------------------------
3749
3750 // Allocate space for the strict arguments object plus the backing store.
3751 Label allocate, done_allocate;
3752 __ lea(ecx,
3753 Operand(eax, times_half_pointer_size,
3754 JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
3755 __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
3756 __ bind(&done_allocate);
3757
3758 // Setup the elements array in edx.
3759 __ mov(FieldOperand(edx, FixedArray::kMapOffset),
3760 isolate()->factory()->fixed_array_map());
3761 __ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax);
3762 {
3763 Label loop, done_loop;
3764 __ Move(ecx, Smi::kZero);
3765 __ bind(&loop);
3766 __ cmp(ecx, eax);
3767 __ j(equal, &done_loop, Label::kNear);
3768 __ mov(edi, Operand(ebx, 0 * kPointerSize));
3769 __ mov(FieldOperand(edx, ecx, times_half_pointer_size,
3770 FixedArray::kHeaderSize),
3771 edi);
3772 __ sub(ebx, Immediate(1 * kPointerSize));
3773 __ add(ecx, Immediate(Smi::FromInt(1)));
3774 __ jmp(&loop);
3775 __ bind(&done_loop);
3776 }
3777
3778 // Setup the rest parameter array in edi.
3779 __ lea(edi,
3780 Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize));
3781 __ LoadGlobalFunction(Context::STRICT_ARGUMENTS_MAP_INDEX, ecx);
3782 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kMapOffset), ecx);
3783 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kPropertiesOffset),
3784 isolate()->factory()->empty_fixed_array());
3785 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kElementsOffset), edx);
3786 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kLengthOffset), eax);
3787 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
3788 __ mov(eax, edi);
3789 __ Ret();
3790
3791 // Fall back to %AllocateInNewSpace (if not too big).
3792 Label too_big_for_new_space;
3793 __ bind(&allocate);
3794 __ cmp(ecx, Immediate(kMaxRegularHeapObjectSize));
3795 __ j(greater, &too_big_for_new_space);
3796 {
3797 FrameScope scope(masm, StackFrame::INTERNAL);
3798 __ SmiTag(ecx);
3799 __ Push(eax);
3800 __ Push(ebx);
3801 __ Push(ecx);
3802 __ CallRuntime(Runtime::kAllocateInNewSpace);
3803 __ mov(edx, eax);
3804 __ Pop(ebx);
3805 __ Pop(eax);
3806 }
3807 __ jmp(&done_allocate);
3808
3809 // Fall back to %NewStrictArguments.
3810 __ bind(&too_big_for_new_space);
3811 __ PopReturnAddressTo(ecx);
3812 // We reload the function from the caller frame due to register pressure
3813 // within this stub. This is the slow path, hence reloading is preferable.
3814 if (skip_stub_frame()) {
3815 // For Ignition we need to skip the handler/stub frame to reach the
3816 // JavaScript frame for the function.
3817 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3818 __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset));
3819 } else {
3820 __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset));
3821 }
3822 __ PushReturnAddressFrom(ecx);
3823 __ TailCallRuntime(Runtime::kNewStrictArguments);
3824 }
3825
3826
3827 // Generates an Operand for saving parameters after PrepareCallApiFunction. 3275 // Generates an Operand for saving parameters after PrepareCallApiFunction.
3828 static Operand ApiParameterOperand(int index) { 3276 static Operand ApiParameterOperand(int index) {
3829 return Operand(esp, index * kPointerSize); 3277 return Operand(esp, index * kPointerSize);
3830 } 3278 }
3831 3279
3832 3280
3833 // Prepares stack to put arguments (aligns and so on). Reserves 3281 // Prepares stack to put arguments (aligns and so on). Reserves
3834 // space for return value if needed (assumes the return value is a handle). 3282 // space for return value if needed (assumes the return value is a handle).
3835 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1) 3283 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
3836 // etc. Saves context (esi). If space was reserved for return value then 3284 // etc. Saves context (esi). If space was reserved for return value then
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
4201 kStackUnwindSpace, nullptr, return_value_operand, 3649 kStackUnwindSpace, nullptr, return_value_operand,
4202 NULL); 3650 NULL);
4203 } 3651 }
4204 3652
4205 #undef __ 3653 #undef __
4206 3654
4207 } // namespace internal 3655 } // namespace internal
4208 } // namespace v8 3656 } // namespace v8
4209 3657
4210 #endif // V8_TARGET_ARCH_IA32 3658 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698