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