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