| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 3205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3216 | 3216 |
| 3217 Label fast_elements_case; | 3217 Label fast_elements_case; |
| 3218 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); | 3218 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); |
| 3219 __ j(equal, &fast_elements_case); | 3219 __ j(equal, &fast_elements_case); |
| 3220 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 3220 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
| 3221 | 3221 |
| 3222 __ bind(&fast_elements_case); | 3222 __ bind(&fast_elements_case); |
| 3223 GenerateCase(masm, FAST_ELEMENTS); | 3223 GenerateCase(masm, FAST_ELEMENTS); |
| 3224 } | 3224 } |
| 3225 | 3225 |
| 3226 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { | |
| 3227 // ----------- S t a t e ------------- | |
| 3228 // -- rdi : function | |
| 3229 // -- rsi : context | |
| 3230 // -- rbp : frame pointer | |
| 3231 // -- rsp[0] : return address | |
| 3232 // ----------------------------------- | |
| 3233 __ AssertFunction(rdi); | |
| 3234 | |
| 3235 // Make rdx point to the JavaScript frame. | |
| 3236 __ movp(rdx, rbp); | |
| 3237 if (skip_stub_frame()) { | |
| 3238 // For Ignition we need to skip the handler/stub frame to reach the | |
| 3239 // JavaScript frame for the function. | |
| 3240 __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
| 3241 } | |
| 3242 if (FLAG_debug_code) { | |
| 3243 Label ok; | |
| 3244 __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset)); | |
| 3245 __ j(equal, &ok); | |
| 3246 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
| 3247 __ bind(&ok); | |
| 3248 } | |
| 3249 | |
| 3250 // Check if we have rest parameters (only possible if we have an | |
| 3251 // arguments adaptor frame below the function frame). | |
| 3252 Label no_rest_parameters; | |
| 3253 __ movp(rbx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
| 3254 __ Cmp(Operand(rbx, CommonFrameConstants::kContextOrFrameTypeOffset), | |
| 3255 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
| 3256 __ j(not_equal, &no_rest_parameters, Label::kNear); | |
| 3257 | |
| 3258 // Check if the arguments adaptor frame contains more arguments than | |
| 3259 // specified by the function's internal formal parameter count. | |
| 3260 Label rest_parameters; | |
| 3261 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
| 3262 __ LoadSharedFunctionInfoSpecialField( | |
| 3263 rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset); | |
| 3264 __ SmiToInteger32( | |
| 3265 rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
| 3266 __ subl(rax, rcx); | |
| 3267 __ j(greater, &rest_parameters); | |
| 3268 | |
| 3269 // Return an empty rest parameter array. | |
| 3270 __ bind(&no_rest_parameters); | |
| 3271 { | |
| 3272 // ----------- S t a t e ------------- | |
| 3273 // -- rsi : context | |
| 3274 // -- rsp[0] : return address | |
| 3275 // ----------------------------------- | |
| 3276 | |
| 3277 // Allocate an empty rest parameter array. | |
| 3278 Label allocate, done_allocate; | |
| 3279 __ Allocate(JSArray::kSize, rax, rdx, rcx, &allocate, NO_ALLOCATION_FLAGS); | |
| 3280 __ bind(&done_allocate); | |
| 3281 | |
| 3282 // Setup the rest parameter array in rax. | |
| 3283 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, rcx); | |
| 3284 __ movp(FieldOperand(rax, JSArray::kMapOffset), rcx); | |
| 3285 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
| 3286 __ movp(FieldOperand(rax, JSArray::kPropertiesOffset), rcx); | |
| 3287 __ movp(FieldOperand(rax, JSArray::kElementsOffset), rcx); | |
| 3288 __ movp(FieldOperand(rax, JSArray::kLengthOffset), Immediate(0)); | |
| 3289 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
| 3290 __ Ret(); | |
| 3291 | |
| 3292 // Fall back to %AllocateInNewSpace. | |
| 3293 __ bind(&allocate); | |
| 3294 { | |
| 3295 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 3296 __ Push(Smi::FromInt(JSArray::kSize)); | |
| 3297 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
| 3298 } | |
| 3299 __ jmp(&done_allocate); | |
| 3300 } | |
| 3301 | |
| 3302 __ bind(&rest_parameters); | |
| 3303 { | |
| 3304 // Compute the pointer to the first rest parameter (skippping the receiver). | |
| 3305 __ leap(rbx, Operand(rbx, rax, times_pointer_size, | |
| 3306 StandardFrameConstants::kCallerSPOffset - | |
| 3307 1 * kPointerSize)); | |
| 3308 | |
| 3309 // ----------- S t a t e ------------- | |
| 3310 // -- rdi : function | |
| 3311 // -- rsi : context | |
| 3312 // -- rax : number of rest parameters | |
| 3313 // -- rbx : pointer to first rest parameters | |
| 3314 // -- rsp[0] : return address | |
| 3315 // ----------------------------------- | |
| 3316 | |
| 3317 // Allocate space for the rest parameter array plus the backing store. | |
| 3318 Label allocate, done_allocate; | |
| 3319 __ leal(rcx, Operand(rax, times_pointer_size, | |
| 3320 JSArray::kSize + FixedArray::kHeaderSize)); | |
| 3321 __ Allocate(rcx, rdx, r8, no_reg, &allocate, NO_ALLOCATION_FLAGS); | |
| 3322 __ bind(&done_allocate); | |
| 3323 | |
| 3324 // Compute the arguments.length in rdi. | |
| 3325 __ Integer32ToSmi(rdi, rax); | |
| 3326 | |
| 3327 // Setup the elements array in rdx. | |
| 3328 __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); | |
| 3329 __ movp(FieldOperand(rdx, FixedArray::kMapOffset), rcx); | |
| 3330 __ movp(FieldOperand(rdx, FixedArray::kLengthOffset), rdi); | |
| 3331 { | |
| 3332 Label loop, done_loop; | |
| 3333 __ Set(rcx, 0); | |
| 3334 __ bind(&loop); | |
| 3335 __ cmpl(rcx, rax); | |
| 3336 __ j(equal, &done_loop, Label::kNear); | |
| 3337 __ movp(kScratchRegister, Operand(rbx, 0 * kPointerSize)); | |
| 3338 __ movp( | |
| 3339 FieldOperand(rdx, rcx, times_pointer_size, FixedArray::kHeaderSize), | |
| 3340 kScratchRegister); | |
| 3341 __ subp(rbx, Immediate(1 * kPointerSize)); | |
| 3342 __ addl(rcx, Immediate(1)); | |
| 3343 __ jmp(&loop); | |
| 3344 __ bind(&done_loop); | |
| 3345 } | |
| 3346 | |
| 3347 // Setup the rest parameter array in rax. | |
| 3348 __ leap(rax, | |
| 3349 Operand(rdx, rax, times_pointer_size, FixedArray::kHeaderSize)); | |
| 3350 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, rcx); | |
| 3351 __ movp(FieldOperand(rax, JSArray::kMapOffset), rcx); | |
| 3352 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
| 3353 __ movp(FieldOperand(rax, JSArray::kPropertiesOffset), rcx); | |
| 3354 __ movp(FieldOperand(rax, JSArray::kElementsOffset), rdx); | |
| 3355 __ movp(FieldOperand(rax, JSArray::kLengthOffset), rdi); | |
| 3356 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
| 3357 __ Ret(); | |
| 3358 | |
| 3359 // Fall back to %AllocateInNewSpace (if not too big). | |
| 3360 Label too_big_for_new_space; | |
| 3361 __ bind(&allocate); | |
| 3362 __ cmpl(rcx, Immediate(kMaxRegularHeapObjectSize)); | |
| 3363 __ j(greater, &too_big_for_new_space); | |
| 3364 { | |
| 3365 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 3366 __ Integer32ToSmi(rax, rax); | |
| 3367 __ Integer32ToSmi(rcx, rcx); | |
| 3368 __ Push(rax); | |
| 3369 __ Push(rbx); | |
| 3370 __ Push(rcx); | |
| 3371 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
| 3372 __ movp(rdx, rax); | |
| 3373 __ Pop(rbx); | |
| 3374 __ Pop(rax); | |
| 3375 __ SmiToInteger32(rax, rax); | |
| 3376 } | |
| 3377 __ jmp(&done_allocate); | |
| 3378 | |
| 3379 // Fall back to %NewRestParameter. | |
| 3380 __ bind(&too_big_for_new_space); | |
| 3381 __ PopReturnAddressTo(kScratchRegister); | |
| 3382 __ Push(rdi); | |
| 3383 __ PushReturnAddressFrom(kScratchRegister); | |
| 3384 __ TailCallRuntime(Runtime::kNewRestParameter); | |
| 3385 } | |
| 3386 } | |
| 3387 | |
| 3388 | |
| 3389 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { | |
| 3390 // ----------- S t a t e ------------- | |
| 3391 // -- rdi : function | |
| 3392 // -- rsi : context | |
| 3393 // -- rbp : frame pointer | |
| 3394 // -- rsp[0] : return address | |
| 3395 // ----------------------------------- | |
| 3396 __ AssertFunction(rdi); | |
| 3397 | |
| 3398 // Make r9 point to the JavaScript frame. | |
| 3399 __ movp(r9, rbp); | |
| 3400 if (skip_stub_frame()) { | |
| 3401 // For Ignition we need to skip the handler/stub frame to reach the | |
| 3402 // JavaScript frame for the function. | |
| 3403 __ movp(r9, Operand(r9, StandardFrameConstants::kCallerFPOffset)); | |
| 3404 } | |
| 3405 if (FLAG_debug_code) { | |
| 3406 Label ok; | |
| 3407 __ cmpp(rdi, Operand(r9, StandardFrameConstants::kFunctionOffset)); | |
| 3408 __ j(equal, &ok); | |
| 3409 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
| 3410 __ bind(&ok); | |
| 3411 } | |
| 3412 | |
| 3413 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. | |
| 3414 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
| 3415 __ LoadSharedFunctionInfoSpecialField( | |
| 3416 rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset); | |
| 3417 __ leap(rdx, Operand(r9, rcx, times_pointer_size, | |
| 3418 StandardFrameConstants::kCallerSPOffset)); | |
| 3419 __ Integer32ToSmi(rcx, rcx); | |
| 3420 | |
| 3421 // rcx : number of parameters (tagged) | |
| 3422 // rdx : parameters pointer | |
| 3423 // rdi : function | |
| 3424 // rsp[0] : return address | |
| 3425 // r9 : JavaScript frame pointer. | |
| 3426 // Registers used over the whole function: | |
| 3427 // rbx: the mapped parameter count (untagged) | |
| 3428 // rax: the allocated object (tagged). | |
| 3429 Factory* factory = isolate()->factory(); | |
| 3430 | |
| 3431 __ SmiToInteger64(rbx, rcx); | |
| 3432 // rbx = parameter count (untagged) | |
| 3433 | |
| 3434 // Check if the calling frame is an arguments adaptor frame. | |
| 3435 Label adaptor_frame, try_allocate, runtime; | |
| 3436 __ movp(rax, Operand(r9, StandardFrameConstants::kCallerFPOffset)); | |
| 3437 __ movp(r8, Operand(rax, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
| 3438 __ Cmp(r8, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
| 3439 __ j(equal, &adaptor_frame); | |
| 3440 | |
| 3441 // No adaptor, parameter count = argument count. | |
| 3442 __ movp(r11, rbx); | |
| 3443 __ jmp(&try_allocate, Label::kNear); | |
| 3444 | |
| 3445 // We have an adaptor frame. Patch the parameters pointer. | |
| 3446 __ bind(&adaptor_frame); | |
| 3447 __ SmiToInteger64( | |
| 3448 r11, Operand(rax, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
| 3449 __ leap(rdx, Operand(rax, r11, times_pointer_size, | |
| 3450 StandardFrameConstants::kCallerSPOffset)); | |
| 3451 | |
| 3452 // rbx = parameter count (untagged) | |
| 3453 // r11 = argument count (untagged) | |
| 3454 // Compute the mapped parameter count = min(rbx, r11) in rbx. | |
| 3455 __ cmpp(rbx, r11); | |
| 3456 __ j(less_equal, &try_allocate, Label::kNear); | |
| 3457 __ movp(rbx, r11); | |
| 3458 | |
| 3459 __ bind(&try_allocate); | |
| 3460 | |
| 3461 // Compute the sizes of backing store, parameter map, and arguments object. | |
| 3462 // 1. Parameter map, has 2 extra words containing context and backing store. | |
| 3463 const int kParameterMapHeaderSize = | |
| 3464 FixedArray::kHeaderSize + 2 * kPointerSize; | |
| 3465 Label no_parameter_map; | |
| 3466 __ xorp(r8, r8); | |
| 3467 __ testp(rbx, rbx); | |
| 3468 __ j(zero, &no_parameter_map, Label::kNear); | |
| 3469 __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); | |
| 3470 __ bind(&no_parameter_map); | |
| 3471 | |
| 3472 // 2. Backing store. | |
| 3473 __ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize)); | |
| 3474 | |
| 3475 // 3. Arguments object. | |
| 3476 __ addp(r8, Immediate(JSSloppyArgumentsObject::kSize)); | |
| 3477 | |
| 3478 // Do the allocation of all three objects in one go. | |
| 3479 __ Allocate(r8, rax, r9, no_reg, &runtime, NO_ALLOCATION_FLAGS); | |
| 3480 | |
| 3481 // rax = address of new object(s) (tagged) | |
| 3482 // r11 = argument count (untagged) | |
| 3483 // Get the arguments map from the current native context into r9. | |
| 3484 Label has_mapped_parameters, instantiate; | |
| 3485 __ movp(r9, NativeContextOperand()); | |
| 3486 __ testp(rbx, rbx); | |
| 3487 __ j(not_zero, &has_mapped_parameters, Label::kNear); | |
| 3488 | |
| 3489 const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX; | |
| 3490 __ movp(r9, Operand(r9, Context::SlotOffset(kIndex))); | |
| 3491 __ jmp(&instantiate, Label::kNear); | |
| 3492 | |
| 3493 const int kAliasedIndex = Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX; | |
| 3494 __ bind(&has_mapped_parameters); | |
| 3495 __ movp(r9, Operand(r9, Context::SlotOffset(kAliasedIndex))); | |
| 3496 __ bind(&instantiate); | |
| 3497 | |
| 3498 // rax = address of new object (tagged) | |
| 3499 // rbx = mapped parameter count (untagged) | |
| 3500 // r11 = argument count (untagged) | |
| 3501 // r9 = address of arguments map (tagged) | |
| 3502 __ movp(FieldOperand(rax, JSObject::kMapOffset), r9); | |
| 3503 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | |
| 3504 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | |
| 3505 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); | |
| 3506 | |
| 3507 // Set up the callee in-object property. | |
| 3508 __ AssertNotSmi(rdi); | |
| 3509 __ movp(FieldOperand(rax, JSSloppyArgumentsObject::kCalleeOffset), rdi); | |
| 3510 | |
| 3511 // Use the length (smi tagged) and set that as an in-object property too. | |
| 3512 // Note: r11 is tagged from here on. | |
| 3513 __ Integer32ToSmi(r11, r11); | |
| 3514 __ movp(FieldOperand(rax, JSSloppyArgumentsObject::kLengthOffset), r11); | |
| 3515 | |
| 3516 // Set up the elements pointer in the allocated arguments object. | |
| 3517 // If we allocated a parameter map, rdi will point there, otherwise to the | |
| 3518 // backing store. | |
| 3519 __ leap(rdi, Operand(rax, JSSloppyArgumentsObject::kSize)); | |
| 3520 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | |
| 3521 | |
| 3522 // rax = address of new object (tagged) | |
| 3523 // rbx = mapped parameter count (untagged) | |
| 3524 // r11 = argument count (tagged) | |
| 3525 // rdi = address of parameter map or backing store (tagged) | |
| 3526 | |
| 3527 // Initialize parameter map. If there are no mapped arguments, we're done. | |
| 3528 Label skip_parameter_map; | |
| 3529 __ testp(rbx, rbx); | |
| 3530 __ j(zero, &skip_parameter_map); | |
| 3531 | |
| 3532 __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex); | |
| 3533 // rbx contains the untagged argument count. Add 2 and tag to write. | |
| 3534 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | |
| 3535 __ Integer64PlusConstantToSmi(r9, rbx, 2); | |
| 3536 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); | |
| 3537 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); | |
| 3538 __ leap(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | |
| 3539 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); | |
| 3540 | |
| 3541 // Copy the parameter slots and the holes in the arguments. | |
| 3542 // We need to fill in mapped_parameter_count slots. They index the context, | |
| 3543 // where parameters are stored in reverse order, at | |
| 3544 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
| 3545 // The mapped parameter thus need to get indices | |
| 3546 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
| 3547 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
| 3548 // We loop from right to left. | |
| 3549 Label parameters_loop, parameters_test; | |
| 3550 | |
| 3551 // Load tagged parameter count into r9. | |
| 3552 __ Integer32ToSmi(r9, rbx); | |
| 3553 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); | |
| 3554 __ addp(r8, rcx); | |
| 3555 __ subp(r8, r9); | |
| 3556 __ movp(rcx, rdi); | |
| 3557 __ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | |
| 3558 __ SmiToInteger64(r9, r9); | |
| 3559 // r9 = loop variable (untagged) | |
| 3560 // r8 = mapping index (tagged) | |
| 3561 // rcx = address of parameter map (tagged) | |
| 3562 // rdi = address of backing store (tagged) | |
| 3563 __ jmp(¶meters_test, Label::kNear); | |
| 3564 | |
| 3565 __ bind(¶meters_loop); | |
| 3566 __ subp(r9, Immediate(1)); | |
| 3567 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | |
| 3568 __ movp(FieldOperand(rcx, r9, times_pointer_size, kParameterMapHeaderSize), | |
| 3569 r8); | |
| 3570 __ movp(FieldOperand(rdi, r9, times_pointer_size, FixedArray::kHeaderSize), | |
| 3571 kScratchRegister); | |
| 3572 __ SmiAddConstant(r8, r8, Smi::FromInt(1)); | |
| 3573 __ bind(¶meters_test); | |
| 3574 __ testp(r9, r9); | |
| 3575 __ j(not_zero, ¶meters_loop, Label::kNear); | |
| 3576 | |
| 3577 __ bind(&skip_parameter_map); | |
| 3578 | |
| 3579 // r11 = argument count (tagged) | |
| 3580 // rdi = address of backing store (tagged) | |
| 3581 // Copy arguments header and remaining slots (if there are any). | |
| 3582 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), | |
| 3583 factory->fixed_array_map()); | |
| 3584 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r11); | |
| 3585 | |
| 3586 Label arguments_loop, arguments_test; | |
| 3587 __ movp(r8, rbx); | |
| 3588 // Untag r11 for the loop below. | |
| 3589 __ SmiToInteger64(r11, r11); | |
| 3590 __ leap(kScratchRegister, Operand(r8, times_pointer_size, 0)); | |
| 3591 __ subp(rdx, kScratchRegister); | |
| 3592 __ jmp(&arguments_test, Label::kNear); | |
| 3593 | |
| 3594 __ bind(&arguments_loop); | |
| 3595 __ subp(rdx, Immediate(kPointerSize)); | |
| 3596 __ movp(r9, Operand(rdx, 0)); | |
| 3597 __ movp(FieldOperand(rdi, r8, | |
| 3598 times_pointer_size, | |
| 3599 FixedArray::kHeaderSize), | |
| 3600 r9); | |
| 3601 __ addp(r8, Immediate(1)); | |
| 3602 | |
| 3603 __ bind(&arguments_test); | |
| 3604 __ cmpp(r8, r11); | |
| 3605 __ j(less, &arguments_loop, Label::kNear); | |
| 3606 | |
| 3607 // Return. | |
| 3608 __ ret(0); | |
| 3609 | |
| 3610 // Do the runtime call to allocate the arguments object. | |
| 3611 // r11 = argument count (untagged) | |
| 3612 __ bind(&runtime); | |
| 3613 __ Integer32ToSmi(r11, r11); | |
| 3614 __ PopReturnAddressTo(rax); | |
| 3615 __ Push(rdi); // Push function. | |
| 3616 __ Push(rdx); // Push parameters pointer. | |
| 3617 __ Push(r11); // Push parameter count. | |
| 3618 __ PushReturnAddressFrom(rax); | |
| 3619 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
| 3620 } | |
| 3621 | |
| 3622 | |
| 3623 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | |
| 3624 // ----------- S t a t e ------------- | |
| 3625 // -- rdi : function | |
| 3626 // -- rsi : context | |
| 3627 // -- rbp : frame pointer | |
| 3628 // -- rsp[0] : return address | |
| 3629 // ----------------------------------- | |
| 3630 __ AssertFunction(rdi); | |
| 3631 | |
| 3632 // Make rdx point to the JavaScript frame. | |
| 3633 __ movp(rdx, rbp); | |
| 3634 if (skip_stub_frame()) { | |
| 3635 // For Ignition we need to skip the handler/stub frame to reach the | |
| 3636 // JavaScript frame for the function. | |
| 3637 __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
| 3638 } | |
| 3639 if (FLAG_debug_code) { | |
| 3640 Label ok; | |
| 3641 __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset)); | |
| 3642 __ j(equal, &ok); | |
| 3643 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
| 3644 __ bind(&ok); | |
| 3645 } | |
| 3646 | |
| 3647 // Check if we have an arguments adaptor frame below the function frame. | |
| 3648 Label arguments_adaptor, arguments_done; | |
| 3649 __ movp(rbx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
| 3650 __ Cmp(Operand(rbx, CommonFrameConstants::kContextOrFrameTypeOffset), | |
| 3651 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
| 3652 __ j(equal, &arguments_adaptor, Label::kNear); | |
| 3653 { | |
| 3654 __ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
| 3655 __ LoadSharedFunctionInfoSpecialField( | |
| 3656 rax, rax, SharedFunctionInfo::kFormalParameterCountOffset); | |
| 3657 __ leap(rbx, Operand(rdx, rax, times_pointer_size, | |
| 3658 StandardFrameConstants::kCallerSPOffset - | |
| 3659 1 * kPointerSize)); | |
| 3660 } | |
| 3661 __ jmp(&arguments_done, Label::kNear); | |
| 3662 __ bind(&arguments_adaptor); | |
| 3663 { | |
| 3664 __ SmiToInteger32( | |
| 3665 rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
| 3666 __ leap(rbx, Operand(rbx, rax, times_pointer_size, | |
| 3667 StandardFrameConstants::kCallerSPOffset - | |
| 3668 1 * kPointerSize)); | |
| 3669 } | |
| 3670 __ bind(&arguments_done); | |
| 3671 | |
| 3672 // ----------- S t a t e ------------- | |
| 3673 // -- rax : number of arguments | |
| 3674 // -- rbx : pointer to the first argument | |
| 3675 // -- rdi : function | |
| 3676 // -- rsi : context | |
| 3677 // -- rsp[0] : return address | |
| 3678 // ----------------------------------- | |
| 3679 | |
| 3680 // Allocate space for the strict arguments object plus the backing store. | |
| 3681 Label allocate, done_allocate; | |
| 3682 __ leal(rcx, Operand(rax, times_pointer_size, JSStrictArgumentsObject::kSize + | |
| 3683 FixedArray::kHeaderSize)); | |
| 3684 __ Allocate(rcx, rdx, r8, no_reg, &allocate, NO_ALLOCATION_FLAGS); | |
| 3685 __ bind(&done_allocate); | |
| 3686 | |
| 3687 // Compute the arguments.length in rdi. | |
| 3688 __ Integer32ToSmi(rdi, rax); | |
| 3689 | |
| 3690 // Setup the elements array in rdx. | |
| 3691 __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); | |
| 3692 __ movp(FieldOperand(rdx, FixedArray::kMapOffset), rcx); | |
| 3693 __ movp(FieldOperand(rdx, FixedArray::kLengthOffset), rdi); | |
| 3694 { | |
| 3695 Label loop, done_loop; | |
| 3696 __ Set(rcx, 0); | |
| 3697 __ bind(&loop); | |
| 3698 __ cmpl(rcx, rax); | |
| 3699 __ j(equal, &done_loop, Label::kNear); | |
| 3700 __ movp(kScratchRegister, Operand(rbx, 0 * kPointerSize)); | |
| 3701 __ movp( | |
| 3702 FieldOperand(rdx, rcx, times_pointer_size, FixedArray::kHeaderSize), | |
| 3703 kScratchRegister); | |
| 3704 __ subp(rbx, Immediate(1 * kPointerSize)); | |
| 3705 __ addl(rcx, Immediate(1)); | |
| 3706 __ jmp(&loop); | |
| 3707 __ bind(&done_loop); | |
| 3708 } | |
| 3709 | |
| 3710 // Setup the strict arguments object in rax. | |
| 3711 __ leap(rax, | |
| 3712 Operand(rdx, rax, times_pointer_size, FixedArray::kHeaderSize)); | |
| 3713 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, rcx); | |
| 3714 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kMapOffset), rcx); | |
| 3715 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
| 3716 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kPropertiesOffset), rcx); | |
| 3717 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kElementsOffset), rdx); | |
| 3718 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kLengthOffset), rdi); | |
| 3719 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); | |
| 3720 __ Ret(); | |
| 3721 | |
| 3722 // Fall back to %AllocateInNewSpace (if not too big). | |
| 3723 Label too_big_for_new_space; | |
| 3724 __ bind(&allocate); | |
| 3725 __ cmpl(rcx, Immediate(kMaxRegularHeapObjectSize)); | |
| 3726 __ j(greater, &too_big_for_new_space); | |
| 3727 { | |
| 3728 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 3729 __ Integer32ToSmi(rax, rax); | |
| 3730 __ Integer32ToSmi(rcx, rcx); | |
| 3731 __ Push(rax); | |
| 3732 __ Push(rbx); | |
| 3733 __ Push(rcx); | |
| 3734 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
| 3735 __ movp(rdx, rax); | |
| 3736 __ Pop(rbx); | |
| 3737 __ Pop(rax); | |
| 3738 __ SmiToInteger32(rax, rax); | |
| 3739 } | |
| 3740 __ jmp(&done_allocate); | |
| 3741 | |
| 3742 // Fall back to %NewStrictArguments. | |
| 3743 __ bind(&too_big_for_new_space); | |
| 3744 __ PopReturnAddressTo(kScratchRegister); | |
| 3745 __ Push(rdi); | |
| 3746 __ PushReturnAddressFrom(kScratchRegister); | |
| 3747 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
| 3748 } | |
| 3749 | |
| 3750 | |
| 3751 static int Offset(ExternalReference ref0, ExternalReference ref1) { | 3226 static int Offset(ExternalReference ref0, ExternalReference ref1) { |
| 3752 int64_t offset = (ref0.address() - ref1.address()); | 3227 int64_t offset = (ref0.address() - ref1.address()); |
| 3753 // Check that fits into int. | 3228 // Check that fits into int. |
| 3754 DCHECK(static_cast<int>(offset) == offset); | 3229 DCHECK(static_cast<int>(offset) == offset); |
| 3755 return static_cast<int>(offset); | 3230 return static_cast<int>(offset); |
| 3756 } | 3231 } |
| 3757 | 3232 |
| 3758 | |
| 3759 // Prepares stack to put arguments (aligns and so on). WIN64 calling | 3233 // Prepares stack to put arguments (aligns and so on). WIN64 calling |
| 3760 // convention requires to put the pointer to the return value slot into | 3234 // convention requires to put the pointer to the return value slot into |
| 3761 // rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves | 3235 // rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves |
| 3762 // context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize | 3236 // context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize |
| 3763 // inside the exit frame (not GCed) accessible via StackSpaceOperand. | 3237 // inside the exit frame (not GCed) accessible via StackSpaceOperand. |
| 3764 static void PrepareCallApiFunction(MacroAssembler* masm, int arg_stack_space) { | 3238 static void PrepareCallApiFunction(MacroAssembler* masm, int arg_stack_space) { |
| 3765 __ EnterApiExitFrame(arg_stack_space); | 3239 __ EnterApiExitFrame(arg_stack_space); |
| 3766 } | 3240 } |
| 3767 | 3241 |
| 3768 | 3242 |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4132 kStackUnwindSpace, nullptr, return_value_operand, | 3606 kStackUnwindSpace, nullptr, return_value_operand, |
| 4133 NULL); | 3607 NULL); |
| 4134 } | 3608 } |
| 4135 | 3609 |
| 4136 #undef __ | 3610 #undef __ |
| 4137 | 3611 |
| 4138 } // namespace internal | 3612 } // namespace internal |
| 4139 } // namespace v8 | 3613 } // namespace v8 |
| 4140 | 3614 |
| 4141 #endif // V8_TARGET_ARCH_X64 | 3615 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |