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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
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/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 3291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3302 } | 3302 } |
3303 | 3303 |
3304 Label fast_elements_case; | 3304 Label fast_elements_case; |
3305 __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); | 3305 __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); |
3306 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 3306 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
3307 | 3307 |
3308 __ bind(&fast_elements_case); | 3308 __ bind(&fast_elements_case); |
3309 GenerateCase(masm, FAST_ELEMENTS); | 3309 GenerateCase(masm, FAST_ELEMENTS); |
3310 } | 3310 } |
3311 | 3311 |
3312 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { | |
3313 // ----------- S t a t e ------------- | |
3314 // -- a1 : function | |
3315 // -- cp : context | |
3316 // -- fp : frame pointer | |
3317 // -- ra : return address | |
3318 // ----------------------------------- | |
3319 __ AssertFunction(a1); | |
3320 | |
3321 // Make a2 point to the JavaScript frame. | |
3322 __ mov(a2, fp); | |
3323 if (skip_stub_frame()) { | |
3324 // For Ignition we need to skip the handler/stub frame to reach the | |
3325 // JavaScript frame for the function. | |
3326 __ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3327 } | |
3328 if (FLAG_debug_code) { | |
3329 Label ok; | |
3330 __ ld(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset)); | |
3331 __ Branch(&ok, eq, a1, Operand(a3)); | |
3332 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3333 __ bind(&ok); | |
3334 } | |
3335 | |
3336 // Check if we have rest parameters (only possible if we have an | |
3337 // arguments adaptor frame below the function frame). | |
3338 Label no_rest_parameters; | |
3339 __ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3340 __ ld(a3, MemOperand(a2, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3341 __ Branch(&no_rest_parameters, ne, a3, | |
3342 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3343 | |
3344 // Check if the arguments adaptor frame contains more arguments than | |
3345 // specified by the function's internal formal parameter count. | |
3346 Label rest_parameters; | |
3347 __ SmiLoadUntag( | |
3348 a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3349 __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
3350 __ lw(a3, | |
3351 FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3352 __ Dsubu(a0, a0, Operand(a3)); | |
3353 __ Branch(&rest_parameters, gt, a0, Operand(zero_reg)); | |
3354 | |
3355 // Return an empty rest parameter array. | |
3356 __ bind(&no_rest_parameters); | |
3357 { | |
3358 // ----------- S t a t e ------------- | |
3359 // -- cp : context | |
3360 // -- ra : return address | |
3361 // ----------------------------------- | |
3362 | |
3363 // Allocate an empty rest parameter array. | |
3364 Label allocate, done_allocate; | |
3365 __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, NO_ALLOCATION_FLAGS); | |
3366 __ bind(&done_allocate); | |
3367 | |
3368 // Setup the rest parameter array in v0. | |
3369 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, a1); | |
3370 __ sd(a1, FieldMemOperand(v0, JSArray::kMapOffset)); | |
3371 __ LoadRoot(a1, Heap::kEmptyFixedArrayRootIndex); | |
3372 __ sd(a1, FieldMemOperand(v0, JSArray::kPropertiesOffset)); | |
3373 __ sd(a1, FieldMemOperand(v0, JSArray::kElementsOffset)); | |
3374 __ Move(a1, Smi::kZero); | |
3375 __ Ret(USE_DELAY_SLOT); | |
3376 __ sd(a1, FieldMemOperand(v0, JSArray::kLengthOffset)); // In delay slot | |
3377 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3378 | |
3379 // Fall back to %AllocateInNewSpace. | |
3380 __ bind(&allocate); | |
3381 { | |
3382 FrameScope scope(masm, StackFrame::INTERNAL); | |
3383 __ Push(Smi::FromInt(JSArray::kSize)); | |
3384 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3385 } | |
3386 __ jmp(&done_allocate); | |
3387 } | |
3388 | |
3389 __ bind(&rest_parameters); | |
3390 { | |
3391 // Compute the pointer to the first rest parameter (skippping the receiver). | |
3392 __ Dlsa(a2, a2, a0, kPointerSizeLog2); | |
3393 __ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset - | |
3394 1 * kPointerSize)); | |
3395 | |
3396 // ----------- S t a t e ------------- | |
3397 // -- cp : context | |
3398 // -- a0 : number of rest parameters | |
3399 // -- a1 : function | |
3400 // -- a2 : pointer to first rest parameters | |
3401 // -- ra : return address | |
3402 // ----------------------------------- | |
3403 | |
3404 // Allocate space for the rest parameter array plus the backing store. | |
3405 Label allocate, done_allocate; | |
3406 __ li(a5, Operand(JSArray::kSize + FixedArray::kHeaderSize)); | |
3407 __ Dlsa(a5, a5, a0, kPointerSizeLog2); | |
3408 __ Allocate(a5, v0, a3, a4, &allocate, NO_ALLOCATION_FLAGS); | |
3409 __ bind(&done_allocate); | |
3410 | |
3411 // Compute arguments.length in a4. | |
3412 __ SmiTag(a4, a0); | |
3413 | |
3414 // Setup the elements array in v0. | |
3415 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); | |
3416 __ sd(at, FieldMemOperand(v0, FixedArray::kMapOffset)); | |
3417 __ sd(a4, FieldMemOperand(v0, FixedArray::kLengthOffset)); | |
3418 __ Daddu(a3, v0, Operand(FixedArray::kHeaderSize)); | |
3419 { | |
3420 Label loop, done_loop; | |
3421 __ Dlsa(a1, a3, a0, kPointerSizeLog2); | |
3422 __ bind(&loop); | |
3423 __ Branch(&done_loop, eq, a1, Operand(a3)); | |
3424 __ ld(at, MemOperand(a2, 0 * kPointerSize)); | |
3425 __ sd(at, FieldMemOperand(a3, 0 * kPointerSize)); | |
3426 __ Dsubu(a2, a2, Operand(1 * kPointerSize)); | |
3427 __ Daddu(a3, a3, Operand(1 * kPointerSize)); | |
3428 __ Branch(&loop); | |
3429 __ bind(&done_loop); | |
3430 } | |
3431 | |
3432 // Setup the rest parameter array in a3. | |
3433 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, at); | |
3434 __ sd(at, FieldMemOperand(a3, JSArray::kMapOffset)); | |
3435 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); | |
3436 __ sd(at, FieldMemOperand(a3, JSArray::kPropertiesOffset)); | |
3437 __ sd(v0, FieldMemOperand(a3, JSArray::kElementsOffset)); | |
3438 __ sd(a4, FieldMemOperand(a3, JSArray::kLengthOffset)); | |
3439 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3440 __ Ret(USE_DELAY_SLOT); | |
3441 __ mov(v0, a3); // In delay slot | |
3442 | |
3443 // Fall back to %AllocateInNewSpace (if not too big). | |
3444 Label too_big_for_new_space; | |
3445 __ bind(&allocate); | |
3446 __ Branch(&too_big_for_new_space, gt, a5, | |
3447 Operand(kMaxRegularHeapObjectSize)); | |
3448 { | |
3449 FrameScope scope(masm, StackFrame::INTERNAL); | |
3450 __ SmiTag(a0); | |
3451 __ SmiTag(a5); | |
3452 __ Push(a0, a2, a5); | |
3453 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3454 __ Pop(a0, a2); | |
3455 __ SmiUntag(a0); | |
3456 } | |
3457 __ jmp(&done_allocate); | |
3458 | |
3459 // Fall back to %NewStrictArguments. | |
3460 __ bind(&too_big_for_new_space); | |
3461 __ Push(a1); | |
3462 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
3463 } | |
3464 } | |
3465 | |
3466 | |
3467 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { | |
3468 // ----------- S t a t e ------------- | |
3469 // -- a1 : function | |
3470 // -- cp : context | |
3471 // -- fp : frame pointer | |
3472 // -- ra : return address | |
3473 // ----------------------------------- | |
3474 __ AssertFunction(a1); | |
3475 | |
3476 // Make t0 point to the JavaScript frame. | |
3477 __ mov(t0, fp); | |
3478 if (skip_stub_frame()) { | |
3479 // For Ignition we need to skip the handler/stub frame to reach the | |
3480 // JavaScript frame for the function. | |
3481 __ ld(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset)); | |
3482 } | |
3483 if (FLAG_debug_code) { | |
3484 Label ok; | |
3485 __ ld(a3, MemOperand(t0, StandardFrameConstants::kFunctionOffset)); | |
3486 __ Branch(&ok, eq, a1, Operand(a3)); | |
3487 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3488 __ bind(&ok); | |
3489 } | |
3490 | |
3491 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. | |
3492 __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
3493 __ lw(a2, | |
3494 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3495 __ Lsa(a3, t0, a2, kPointerSizeLog2); | |
3496 __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); | |
3497 __ SmiTag(a2); | |
3498 | |
3499 // a1 : function | |
3500 // a2 : number of parameters (tagged) | |
3501 // a3 : parameters pointer | |
3502 // t0 : Javascript frame pointer | |
3503 // Registers used over whole function: | |
3504 // a5 : arguments count (tagged) | |
3505 // a6 : mapped parameter count (tagged) | |
3506 | |
3507 // Check if the calling frame is an arguments adaptor frame. | |
3508 Label adaptor_frame, try_allocate, runtime; | |
3509 __ ld(a4, MemOperand(t0, StandardFrameConstants::kCallerFPOffset)); | |
3510 __ ld(a0, MemOperand(a4, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3511 __ Branch(&adaptor_frame, eq, a0, | |
3512 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3513 | |
3514 // No adaptor, parameter count = argument count. | |
3515 __ mov(a5, a2); | |
3516 __ Branch(USE_DELAY_SLOT, &try_allocate); | |
3517 __ mov(a6, a2); // In delay slot. | |
3518 | |
3519 // We have an adaptor frame. Patch the parameters pointer. | |
3520 __ bind(&adaptor_frame); | |
3521 __ ld(a5, MemOperand(a4, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3522 __ SmiScale(t2, a5, kPointerSizeLog2); | |
3523 __ Daddu(a4, a4, Operand(t2)); | |
3524 __ Daddu(a3, a4, Operand(StandardFrameConstants::kCallerSPOffset)); | |
3525 | |
3526 // a5 = argument count (tagged) | |
3527 // a6 = parameter count (tagged) | |
3528 // Compute the mapped parameter count = min(a6, a5) in a6. | |
3529 __ mov(a6, a2); | |
3530 __ Branch(&try_allocate, le, a6, Operand(a5)); | |
3531 __ mov(a6, a5); | |
3532 | |
3533 __ bind(&try_allocate); | |
3534 | |
3535 // Compute the sizes of backing store, parameter map, and arguments object. | |
3536 // 1. Parameter map, has 2 extra words containing context and backing store. | |
3537 const int kParameterMapHeaderSize = | |
3538 FixedArray::kHeaderSize + 2 * kPointerSize; | |
3539 // If there are no mapped parameters, we do not need the parameter_map. | |
3540 Label param_map_size; | |
3541 DCHECK_EQ(static_cast<Smi*>(0), Smi::kZero); | |
3542 __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a6, Operand(zero_reg)); | |
3543 __ mov(t1, zero_reg); // In delay slot: param map size = 0 when a6 == 0. | |
3544 __ SmiScale(t1, a6, kPointerSizeLog2); | |
3545 __ daddiu(t1, t1, kParameterMapHeaderSize); | |
3546 __ bind(¶m_map_size); | |
3547 | |
3548 // 2. Backing store. | |
3549 __ SmiScale(t2, a5, kPointerSizeLog2); | |
3550 __ Daddu(t1, t1, Operand(t2)); | |
3551 __ Daddu(t1, t1, Operand(FixedArray::kHeaderSize)); | |
3552 | |
3553 // 3. Arguments object. | |
3554 __ Daddu(t1, t1, Operand(JSSloppyArgumentsObject::kSize)); | |
3555 | |
3556 // Do the allocation of all three objects in one go. | |
3557 __ Allocate(t1, v0, t1, a4, &runtime, NO_ALLOCATION_FLAGS); | |
3558 | |
3559 // v0 = address of new object(s) (tagged) | |
3560 // a2 = argument count (smi-tagged) | |
3561 // Get the arguments boilerplate from the current native context into a4. | |
3562 const int kNormalOffset = | |
3563 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | |
3564 const int kAliasedOffset = | |
3565 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | |
3566 | |
3567 __ ld(a4, NativeContextMemOperand()); | |
3568 Label skip2_ne, skip2_eq; | |
3569 __ Branch(&skip2_ne, ne, a6, Operand(zero_reg)); | |
3570 __ ld(a4, MemOperand(a4, kNormalOffset)); | |
3571 __ bind(&skip2_ne); | |
3572 | |
3573 __ Branch(&skip2_eq, eq, a6, Operand(zero_reg)); | |
3574 __ ld(a4, MemOperand(a4, kAliasedOffset)); | |
3575 __ bind(&skip2_eq); | |
3576 | |
3577 // v0 = address of new object (tagged) | |
3578 // a2 = argument count (smi-tagged) | |
3579 // a4 = address of arguments map (tagged) | |
3580 // a6 = mapped parameter count (tagged) | |
3581 __ sd(a4, FieldMemOperand(v0, JSObject::kMapOffset)); | |
3582 __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex); | |
3583 __ sd(t1, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | |
3584 __ sd(t1, FieldMemOperand(v0, JSObject::kElementsOffset)); | |
3585 | |
3586 // Set up the callee in-object property. | |
3587 __ AssertNotSmi(a1); | |
3588 __ sd(a1, FieldMemOperand(v0, JSSloppyArgumentsObject::kCalleeOffset)); | |
3589 | |
3590 // Use the length (smi tagged) and set that as an in-object property too. | |
3591 __ AssertSmi(a5); | |
3592 __ sd(a5, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset)); | |
3593 | |
3594 // Set up the elements pointer in the allocated arguments object. | |
3595 // If we allocated a parameter map, a4 will point there, otherwise | |
3596 // it will point to the backing store. | |
3597 __ Daddu(a4, v0, Operand(JSSloppyArgumentsObject::kSize)); | |
3598 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); | |
3599 | |
3600 // v0 = address of new object (tagged) | |
3601 // a2 = argument count (tagged) | |
3602 // a4 = address of parameter map or backing store (tagged) | |
3603 // a6 = mapped parameter count (tagged) | |
3604 // Initialize parameter map. If there are no mapped arguments, we're done. | |
3605 Label skip_parameter_map; | |
3606 Label skip3; | |
3607 __ Branch(&skip3, ne, a6, Operand(Smi::kZero)); | |
3608 // Move backing store address to a1, because it is | |
3609 // expected there when filling in the unmapped arguments. | |
3610 __ mov(a1, a4); | |
3611 __ bind(&skip3); | |
3612 | |
3613 __ Branch(&skip_parameter_map, eq, a6, Operand(Smi::kZero)); | |
3614 | |
3615 __ LoadRoot(a5, Heap::kSloppyArgumentsElementsMapRootIndex); | |
3616 __ sd(a5, FieldMemOperand(a4, FixedArray::kMapOffset)); | |
3617 __ Daddu(a5, a6, Operand(Smi::FromInt(2))); | |
3618 __ sd(a5, FieldMemOperand(a4, FixedArray::kLengthOffset)); | |
3619 __ sd(cp, FieldMemOperand(a4, FixedArray::kHeaderSize + 0 * kPointerSize)); | |
3620 __ SmiScale(t2, a6, kPointerSizeLog2); | |
3621 __ Daddu(a5, a4, Operand(t2)); | |
3622 __ Daddu(a5, a5, Operand(kParameterMapHeaderSize)); | |
3623 __ sd(a5, FieldMemOperand(a4, FixedArray::kHeaderSize + 1 * kPointerSize)); | |
3624 | |
3625 // Copy the parameter slots and the holes in the arguments. | |
3626 // We need to fill in mapped_parameter_count slots. They index the context, | |
3627 // where parameters are stored in reverse order, at | |
3628 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
3629 // The mapped parameter thus need to get indices | |
3630 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
3631 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
3632 // We loop from right to left. | |
3633 Label parameters_loop, parameters_test; | |
3634 __ mov(a5, a6); | |
3635 __ Daddu(t1, a2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | |
3636 __ Dsubu(t1, t1, Operand(a6)); | |
3637 __ LoadRoot(a7, Heap::kTheHoleValueRootIndex); | |
3638 __ SmiScale(t2, a5, kPointerSizeLog2); | |
3639 __ Daddu(a1, a4, Operand(t2)); | |
3640 __ Daddu(a1, a1, Operand(kParameterMapHeaderSize)); | |
3641 | |
3642 // a1 = address of backing store (tagged) | |
3643 // a4 = address of parameter map (tagged) | |
3644 // a0 = temporary scratch (a.o., for address calculation) | |
3645 // t1 = loop variable (tagged) | |
3646 // a7 = the hole value | |
3647 __ jmp(¶meters_test); | |
3648 | |
3649 __ bind(¶meters_loop); | |
3650 __ Dsubu(a5, a5, Operand(Smi::FromInt(1))); | |
3651 __ SmiScale(a0, a5, kPointerSizeLog2); | |
3652 __ Daddu(a0, a0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); | |
3653 __ Daddu(t2, a4, a0); | |
3654 __ sd(t1, MemOperand(t2)); | |
3655 __ Dsubu(a0, a0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); | |
3656 __ Daddu(t2, a1, a0); | |
3657 __ sd(a7, MemOperand(t2)); | |
3658 __ Daddu(t1, t1, Operand(Smi::FromInt(1))); | |
3659 __ bind(¶meters_test); | |
3660 __ Branch(¶meters_loop, ne, a5, Operand(Smi::kZero)); | |
3661 | |
3662 // Restore t1 = argument count (tagged). | |
3663 __ ld(a5, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset)); | |
3664 | |
3665 __ bind(&skip_parameter_map); | |
3666 // v0 = address of new object (tagged) | |
3667 // a1 = address of backing store (tagged) | |
3668 // a5 = argument count (tagged) | |
3669 // a6 = mapped parameter count (tagged) | |
3670 // t1 = scratch | |
3671 // Copy arguments header and remaining slots (if there are any). | |
3672 __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex); | |
3673 __ sd(t1, FieldMemOperand(a1, FixedArray::kMapOffset)); | |
3674 __ sd(a5, FieldMemOperand(a1, FixedArray::kLengthOffset)); | |
3675 | |
3676 Label arguments_loop, arguments_test; | |
3677 __ SmiScale(t2, a6, kPointerSizeLog2); | |
3678 __ Dsubu(a3, a3, Operand(t2)); | |
3679 __ jmp(&arguments_test); | |
3680 | |
3681 __ bind(&arguments_loop); | |
3682 __ Dsubu(a3, a3, Operand(kPointerSize)); | |
3683 __ ld(a4, MemOperand(a3, 0)); | |
3684 __ SmiScale(t2, a6, kPointerSizeLog2); | |
3685 __ Daddu(t1, a1, Operand(t2)); | |
3686 __ sd(a4, FieldMemOperand(t1, FixedArray::kHeaderSize)); | |
3687 __ Daddu(a6, a6, Operand(Smi::FromInt(1))); | |
3688 | |
3689 __ bind(&arguments_test); | |
3690 __ Branch(&arguments_loop, lt, a6, Operand(a5)); | |
3691 | |
3692 // Return. | |
3693 __ Ret(); | |
3694 | |
3695 // Do the runtime call to allocate the arguments object. | |
3696 // a5 = argument count (tagged) | |
3697 __ bind(&runtime); | |
3698 __ Push(a1, a3, a5); | |
3699 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
3700 } | |
3701 | |
3702 | |
3703 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | |
3704 // ----------- S t a t e ------------- | |
3705 // -- a1 : function | |
3706 // -- cp : context | |
3707 // -- fp : frame pointer | |
3708 // -- ra : return address | |
3709 // ----------------------------------- | |
3710 __ AssertFunction(a1); | |
3711 | |
3712 // Make a2 point to the JavaScript frame. | |
3713 __ mov(a2, fp); | |
3714 if (skip_stub_frame()) { | |
3715 // For Ignition we need to skip the handler/stub frame to reach the | |
3716 // JavaScript frame for the function. | |
3717 __ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3718 } | |
3719 if (FLAG_debug_code) { | |
3720 Label ok; | |
3721 __ ld(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset)); | |
3722 __ Branch(&ok, eq, a1, Operand(a3)); | |
3723 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3724 __ bind(&ok); | |
3725 } | |
3726 | |
3727 // Check if we have an arguments adaptor frame below the function frame. | |
3728 Label arguments_adaptor, arguments_done; | |
3729 __ ld(a3, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3730 __ ld(a0, MemOperand(a3, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3731 __ Branch(&arguments_adaptor, eq, a0, | |
3732 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3733 { | |
3734 __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
3735 __ lw(a0, | |
3736 FieldMemOperand(a4, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3737 __ Dlsa(a2, a2, a0, kPointerSizeLog2); | |
3738 __ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset - | |
3739 1 * kPointerSize)); | |
3740 } | |
3741 __ Branch(&arguments_done); | |
3742 __ bind(&arguments_adaptor); | |
3743 { | |
3744 __ SmiLoadUntag( | |
3745 a0, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3746 __ Dlsa(a2, a3, a0, kPointerSizeLog2); | |
3747 __ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset - | |
3748 1 * kPointerSize)); | |
3749 } | |
3750 __ bind(&arguments_done); | |
3751 | |
3752 // ----------- S t a t e ------------- | |
3753 // -- cp : context | |
3754 // -- a0 : number of rest parameters | |
3755 // -- a1 : function | |
3756 // -- a2 : pointer to first rest parameters | |
3757 // -- ra : return address | |
3758 // ----------------------------------- | |
3759 | |
3760 // Allocate space for the rest parameter array plus the backing store. | |
3761 Label allocate, done_allocate; | |
3762 __ li(a5, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); | |
3763 __ Dlsa(a5, a5, a0, kPointerSizeLog2); | |
3764 __ Allocate(a5, v0, a3, a4, &allocate, NO_ALLOCATION_FLAGS); | |
3765 __ bind(&done_allocate); | |
3766 | |
3767 // Compute arguments.length in a4. | |
3768 __ SmiTag(a4, a0); | |
3769 | |
3770 // Setup the elements array in v0. | |
3771 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); | |
3772 __ sd(at, FieldMemOperand(v0, FixedArray::kMapOffset)); | |
3773 __ sd(a4, FieldMemOperand(v0, FixedArray::kLengthOffset)); | |
3774 __ Daddu(a3, v0, Operand(FixedArray::kHeaderSize)); | |
3775 { | |
3776 Label loop, done_loop; | |
3777 __ Dlsa(a1, a3, a0, kPointerSizeLog2); | |
3778 __ bind(&loop); | |
3779 __ Branch(&done_loop, eq, a1, Operand(a3)); | |
3780 __ ld(at, MemOperand(a2, 0 * kPointerSize)); | |
3781 __ sd(at, FieldMemOperand(a3, 0 * kPointerSize)); | |
3782 __ Dsubu(a2, a2, Operand(1 * kPointerSize)); | |
3783 __ Daddu(a3, a3, Operand(1 * kPointerSize)); | |
3784 __ Branch(&loop); | |
3785 __ bind(&done_loop); | |
3786 } | |
3787 | |
3788 // Setup the strict arguments object in a3. | |
3789 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, at); | |
3790 __ sd(at, FieldMemOperand(a3, JSStrictArgumentsObject::kMapOffset)); | |
3791 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); | |
3792 __ sd(at, FieldMemOperand(a3, JSStrictArgumentsObject::kPropertiesOffset)); | |
3793 __ sd(v0, FieldMemOperand(a3, JSStrictArgumentsObject::kElementsOffset)); | |
3794 __ sd(a4, FieldMemOperand(a3, JSStrictArgumentsObject::kLengthOffset)); | |
3795 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); | |
3796 __ Ret(USE_DELAY_SLOT); | |
3797 __ mov(v0, a3); // In delay slot | |
3798 | |
3799 // Fall back to %AllocateInNewSpace (if not too big). | |
3800 Label too_big_for_new_space; | |
3801 __ bind(&allocate); | |
3802 __ Branch(&too_big_for_new_space, gt, a5, Operand(kMaxRegularHeapObjectSize)); | |
3803 { | |
3804 FrameScope scope(masm, StackFrame::INTERNAL); | |
3805 __ SmiTag(a0); | |
3806 __ SmiTag(a5); | |
3807 __ Push(a0, a2, a5); | |
3808 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3809 __ Pop(a0, a2); | |
3810 __ SmiUntag(a0); | |
3811 } | |
3812 __ jmp(&done_allocate); | |
3813 | |
3814 // Fall back to %NewStrictArguments. | |
3815 __ bind(&too_big_for_new_space); | |
3816 __ Push(a1); | |
3817 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
3818 } | |
3819 | |
3820 | |
3821 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 3312 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
3822 int64_t offset = (ref0.address() - ref1.address()); | 3313 int64_t offset = (ref0.address() - ref1.address()); |
3823 DCHECK(static_cast<int>(offset) == offset); | 3314 DCHECK(static_cast<int>(offset) == offset); |
3824 return static_cast<int>(offset); | 3315 return static_cast<int>(offset); |
3825 } | 3316 } |
3826 | 3317 |
3827 | 3318 |
3828 // Calls an API function. Allocates HandleScope, extracts returned value | 3319 // Calls an API function. Allocates HandleScope, extracts returned value |
3829 // from handle and propagates exceptions. Restores context. stack_space | 3320 // from handle and propagates exceptions. Restores context. stack_space |
3830 // - space to be unwound on exit (includes the call JS arguments space and | 3321 // - space to be unwound on exit (includes the call JS arguments space and |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4128 kStackUnwindSpace, kInvalidStackOffset, | 3619 kStackUnwindSpace, kInvalidStackOffset, |
4129 return_value_operand, NULL); | 3620 return_value_operand, NULL); |
4130 } | 3621 } |
4131 | 3622 |
4132 #undef __ | 3623 #undef __ |
4133 | 3624 |
4134 } // namespace internal | 3625 } // namespace internal |
4135 } // namespace v8 | 3626 } // namespace v8 |
4136 | 3627 |
4137 #endif // V8_TARGET_ARCH_MIPS64 | 3628 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |