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