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