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 3004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3015 | 3015 |
3016 Label fast_elements_case; | 3016 Label fast_elements_case; |
3017 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); | 3017 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); |
3018 __ j(equal, &fast_elements_case); | 3018 __ j(equal, &fast_elements_case); |
3019 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 3019 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
3020 | 3020 |
3021 __ bind(&fast_elements_case); | 3021 __ bind(&fast_elements_case); |
3022 GenerateCase(masm, FAST_ELEMENTS); | 3022 GenerateCase(masm, FAST_ELEMENTS); |
3023 } | 3023 } |
3024 | 3024 |
3025 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { | |
3026 // ----------- S t a t e ------------- | |
3027 // -- rdi : function | |
3028 // -- rsi : context | |
3029 // -- rbp : frame pointer | |
3030 // -- rsp[0] : return address | |
3031 // ----------------------------------- | |
3032 __ AssertFunction(rdi); | |
3033 | |
3034 // Make rdx point to the JavaScript frame. | |
3035 __ movp(rdx, rbp); | |
3036 if (skip_stub_frame()) { | |
3037 // For Ignition we need to skip the handler/stub frame to reach the | |
3038 // JavaScript frame for the function. | |
3039 __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
3040 } | |
3041 if (FLAG_debug_code) { | |
3042 Label ok; | |
3043 __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset)); | |
3044 __ j(equal, &ok); | |
3045 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3046 __ bind(&ok); | |
3047 } | |
3048 | |
3049 // Check if we have rest parameters (only possible if we have an | |
3050 // arguments adaptor frame below the function frame). | |
3051 Label no_rest_parameters; | |
3052 __ movp(rbx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
3053 __ Cmp(Operand(rbx, CommonFrameConstants::kContextOrFrameTypeOffset), | |
3054 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
3055 __ j(not_equal, &no_rest_parameters, Label::kNear); | |
3056 | |
3057 // Check if the arguments adaptor frame contains more arguments than | |
3058 // specified by the function's internal formal parameter count. | |
3059 Label rest_parameters; | |
3060 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
3061 __ LoadSharedFunctionInfoSpecialField( | |
3062 rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset); | |
3063 __ SmiToInteger32( | |
3064 rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3065 __ subl(rax, rcx); | |
3066 __ j(greater, &rest_parameters); | |
3067 | |
3068 // Return an empty rest parameter array. | |
3069 __ bind(&no_rest_parameters); | |
3070 { | |
3071 // ----------- S t a t e ------------- | |
3072 // -- rsi : context | |
3073 // -- rsp[0] : return address | |
3074 // ----------------------------------- | |
3075 | |
3076 // Allocate an empty rest parameter array. | |
3077 Label allocate, done_allocate; | |
3078 __ Allocate(JSArray::kSize, rax, rdx, rcx, &allocate, NO_ALLOCATION_FLAGS); | |
3079 __ bind(&done_allocate); | |
3080 | |
3081 // Setup the rest parameter array in rax. | |
3082 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, rcx); | |
3083 __ movp(FieldOperand(rax, JSArray::kMapOffset), rcx); | |
3084 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
3085 __ movp(FieldOperand(rax, JSArray::kPropertiesOffset), rcx); | |
3086 __ movp(FieldOperand(rax, JSArray::kElementsOffset), rcx); | |
3087 __ movp(FieldOperand(rax, JSArray::kLengthOffset), Immediate(0)); | |
3088 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3089 __ Ret(); | |
3090 | |
3091 // Fall back to %AllocateInNewSpace. | |
3092 __ bind(&allocate); | |
3093 { | |
3094 FrameScope scope(masm, StackFrame::INTERNAL); | |
3095 __ Push(Smi::FromInt(JSArray::kSize)); | |
3096 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3097 } | |
3098 __ jmp(&done_allocate); | |
3099 } | |
3100 | |
3101 __ bind(&rest_parameters); | |
3102 { | |
3103 // Compute the pointer to the first rest parameter (skippping the receiver). | |
3104 __ leap(rbx, Operand(rbx, rax, times_pointer_size, | |
3105 StandardFrameConstants::kCallerSPOffset - | |
3106 1 * kPointerSize)); | |
3107 | |
3108 // ----------- S t a t e ------------- | |
3109 // -- rdi : function | |
3110 // -- rsi : context | |
3111 // -- rax : number of rest parameters | |
3112 // -- rbx : pointer to first rest parameters | |
3113 // -- rsp[0] : return address | |
3114 // ----------------------------------- | |
3115 | |
3116 // Allocate space for the rest parameter array plus the backing store. | |
3117 Label allocate, done_allocate; | |
3118 __ leal(rcx, Operand(rax, times_pointer_size, | |
3119 JSArray::kSize + FixedArray::kHeaderSize)); | |
3120 __ Allocate(rcx, rdx, r8, no_reg, &allocate, NO_ALLOCATION_FLAGS); | |
3121 __ bind(&done_allocate); | |
3122 | |
3123 // Compute the arguments.length in rdi. | |
3124 __ Integer32ToSmi(rdi, rax); | |
3125 | |
3126 // Setup the elements array in rdx. | |
3127 __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); | |
3128 __ movp(FieldOperand(rdx, FixedArray::kMapOffset), rcx); | |
3129 __ movp(FieldOperand(rdx, FixedArray::kLengthOffset), rdi); | |
3130 { | |
3131 Label loop, done_loop; | |
3132 __ Set(rcx, 0); | |
3133 __ bind(&loop); | |
3134 __ cmpl(rcx, rax); | |
3135 __ j(equal, &done_loop, Label::kNear); | |
3136 __ movp(kScratchRegister, Operand(rbx, 0 * kPointerSize)); | |
3137 __ movp( | |
3138 FieldOperand(rdx, rcx, times_pointer_size, FixedArray::kHeaderSize), | |
3139 kScratchRegister); | |
3140 __ subp(rbx, Immediate(1 * kPointerSize)); | |
3141 __ addl(rcx, Immediate(1)); | |
3142 __ jmp(&loop); | |
3143 __ bind(&done_loop); | |
3144 } | |
3145 | |
3146 // Setup the rest parameter array in rax. | |
3147 __ leap(rax, | |
3148 Operand(rdx, rax, times_pointer_size, FixedArray::kHeaderSize)); | |
3149 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, rcx); | |
3150 __ movp(FieldOperand(rax, JSArray::kMapOffset), rcx); | |
3151 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
3152 __ movp(FieldOperand(rax, JSArray::kPropertiesOffset), rcx); | |
3153 __ movp(FieldOperand(rax, JSArray::kElementsOffset), rdx); | |
3154 __ movp(FieldOperand(rax, JSArray::kLengthOffset), rdi); | |
3155 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3156 __ Ret(); | |
3157 | |
3158 // Fall back to %AllocateInNewSpace (if not too big). | |
3159 Label too_big_for_new_space; | |
3160 __ bind(&allocate); | |
3161 __ cmpl(rcx, Immediate(kMaxRegularHeapObjectSize)); | |
3162 __ j(greater, &too_big_for_new_space); | |
3163 { | |
3164 FrameScope scope(masm, StackFrame::INTERNAL); | |
3165 __ Integer32ToSmi(rax, rax); | |
3166 __ Integer32ToSmi(rcx, rcx); | |
3167 __ Push(rax); | |
3168 __ Push(rbx); | |
3169 __ Push(rcx); | |
3170 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3171 __ movp(rdx, rax); | |
3172 __ Pop(rbx); | |
3173 __ Pop(rax); | |
3174 __ SmiToInteger32(rax, rax); | |
3175 } | |
3176 __ jmp(&done_allocate); | |
3177 | |
3178 // Fall back to %NewRestParameter. | |
3179 __ bind(&too_big_for_new_space); | |
3180 __ PopReturnAddressTo(kScratchRegister); | |
3181 __ Push(rdi); | |
3182 __ PushReturnAddressFrom(kScratchRegister); | |
3183 __ TailCallRuntime(Runtime::kNewRestParameter); | |
3184 } | |
3185 } | |
3186 | |
3187 | |
3188 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { | |
3189 // ----------- S t a t e ------------- | |
3190 // -- rdi : function | |
3191 // -- rsi : context | |
3192 // -- rbp : frame pointer | |
3193 // -- rsp[0] : return address | |
3194 // ----------------------------------- | |
3195 __ AssertFunction(rdi); | |
3196 | |
3197 // Make r9 point to the JavaScript frame. | |
3198 __ movp(r9, rbp); | |
3199 if (skip_stub_frame()) { | |
3200 // For Ignition we need to skip the handler/stub frame to reach the | |
3201 // JavaScript frame for the function. | |
3202 __ movp(r9, Operand(r9, StandardFrameConstants::kCallerFPOffset)); | |
3203 } | |
3204 if (FLAG_debug_code) { | |
3205 Label ok; | |
3206 __ cmpp(rdi, Operand(r9, StandardFrameConstants::kFunctionOffset)); | |
3207 __ j(equal, &ok); | |
3208 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3209 __ bind(&ok); | |
3210 } | |
3211 | |
3212 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. | |
3213 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
3214 __ LoadSharedFunctionInfoSpecialField( | |
3215 rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset); | |
3216 __ leap(rdx, Operand(r9, rcx, times_pointer_size, | |
3217 StandardFrameConstants::kCallerSPOffset)); | |
3218 __ Integer32ToSmi(rcx, rcx); | |
3219 | |
3220 // rcx : number of parameters (tagged) | |
3221 // rdx : parameters pointer | |
3222 // rdi : function | |
3223 // rsp[0] : return address | |
3224 // r9 : JavaScript frame pointer. | |
3225 // Registers used over the whole function: | |
3226 // rbx: the mapped parameter count (untagged) | |
3227 // rax: the allocated object (tagged). | |
3228 Factory* factory = isolate()->factory(); | |
3229 | |
3230 __ SmiToInteger64(rbx, rcx); | |
3231 // rbx = parameter count (untagged) | |
3232 | |
3233 // Check if the calling frame is an arguments adaptor frame. | |
3234 Label adaptor_frame, try_allocate, runtime; | |
3235 __ movp(rax, Operand(r9, StandardFrameConstants::kCallerFPOffset)); | |
3236 __ movp(r8, Operand(rax, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3237 __ Cmp(r8, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
3238 __ j(equal, &adaptor_frame); | |
3239 | |
3240 // No adaptor, parameter count = argument count. | |
3241 __ movp(r11, rbx); | |
3242 __ jmp(&try_allocate, Label::kNear); | |
3243 | |
3244 // We have an adaptor frame. Patch the parameters pointer. | |
3245 __ bind(&adaptor_frame); | |
3246 __ SmiToInteger64( | |
3247 r11, Operand(rax, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3248 __ leap(rdx, Operand(rax, r11, times_pointer_size, | |
3249 StandardFrameConstants::kCallerSPOffset)); | |
3250 | |
3251 // rbx = parameter count (untagged) | |
3252 // r11 = argument count (untagged) | |
3253 // Compute the mapped parameter count = min(rbx, r11) in rbx. | |
3254 __ cmpp(rbx, r11); | |
3255 __ j(less_equal, &try_allocate, Label::kNear); | |
3256 __ movp(rbx, r11); | |
3257 | |
3258 __ bind(&try_allocate); | |
3259 | |
3260 // Compute the sizes of backing store, parameter map, and arguments object. | |
3261 // 1. Parameter map, has 2 extra words containing context and backing store. | |
3262 const int kParameterMapHeaderSize = | |
3263 FixedArray::kHeaderSize + 2 * kPointerSize; | |
3264 Label no_parameter_map; | |
3265 __ xorp(r8, r8); | |
3266 __ testp(rbx, rbx); | |
3267 __ j(zero, &no_parameter_map, Label::kNear); | |
3268 __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); | |
3269 __ bind(&no_parameter_map); | |
3270 | |
3271 // 2. Backing store. | |
3272 __ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize)); | |
3273 | |
3274 // 3. Arguments object. | |
3275 __ addp(r8, Immediate(JSSloppyArgumentsObject::kSize)); | |
3276 | |
3277 // Do the allocation of all three objects in one go. | |
3278 __ Allocate(r8, rax, r9, no_reg, &runtime, NO_ALLOCATION_FLAGS); | |
3279 | |
3280 // rax = address of new object(s) (tagged) | |
3281 // r11 = argument count (untagged) | |
3282 // Get the arguments map from the current native context into r9. | |
3283 Label has_mapped_parameters, instantiate; | |
3284 __ movp(r9, NativeContextOperand()); | |
3285 __ testp(rbx, rbx); | |
3286 __ j(not_zero, &has_mapped_parameters, Label::kNear); | |
3287 | |
3288 const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX; | |
3289 __ movp(r9, Operand(r9, Context::SlotOffset(kIndex))); | |
3290 __ jmp(&instantiate, Label::kNear); | |
3291 | |
3292 const int kAliasedIndex = Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX; | |
3293 __ bind(&has_mapped_parameters); | |
3294 __ movp(r9, Operand(r9, Context::SlotOffset(kAliasedIndex))); | |
3295 __ bind(&instantiate); | |
3296 | |
3297 // rax = address of new object (tagged) | |
3298 // rbx = mapped parameter count (untagged) | |
3299 // r11 = argument count (untagged) | |
3300 // r9 = address of arguments map (tagged) | |
3301 __ movp(FieldOperand(rax, JSObject::kMapOffset), r9); | |
3302 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | |
3303 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | |
3304 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); | |
3305 | |
3306 // Set up the callee in-object property. | |
3307 __ AssertNotSmi(rdi); | |
3308 __ movp(FieldOperand(rax, JSSloppyArgumentsObject::kCalleeOffset), rdi); | |
3309 | |
3310 // Use the length (smi tagged) and set that as an in-object property too. | |
3311 // Note: r11 is tagged from here on. | |
3312 __ Integer32ToSmi(r11, r11); | |
3313 __ movp(FieldOperand(rax, JSSloppyArgumentsObject::kLengthOffset), r11); | |
3314 | |
3315 // Set up the elements pointer in the allocated arguments object. | |
3316 // If we allocated a parameter map, rdi will point there, otherwise to the | |
3317 // backing store. | |
3318 __ leap(rdi, Operand(rax, JSSloppyArgumentsObject::kSize)); | |
3319 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | |
3320 | |
3321 // rax = address of new object (tagged) | |
3322 // rbx = mapped parameter count (untagged) | |
3323 // r11 = argument count (tagged) | |
3324 // rdi = address of parameter map or backing store (tagged) | |
3325 | |
3326 // Initialize parameter map. If there are no mapped arguments, we're done. | |
3327 Label skip_parameter_map; | |
3328 __ testp(rbx, rbx); | |
3329 __ j(zero, &skip_parameter_map); | |
3330 | |
3331 __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex); | |
3332 // rbx contains the untagged argument count. Add 2 and tag to write. | |
3333 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | |
3334 __ Integer64PlusConstantToSmi(r9, rbx, 2); | |
3335 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); | |
3336 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); | |
3337 __ leap(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | |
3338 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); | |
3339 | |
3340 // Copy the parameter slots and the holes in the arguments. | |
3341 // We need to fill in mapped_parameter_count slots. They index the context, | |
3342 // where parameters are stored in reverse order, at | |
3343 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
3344 // The mapped parameter thus need to get indices | |
3345 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
3346 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
3347 // We loop from right to left. | |
3348 Label parameters_loop, parameters_test; | |
3349 | |
3350 // Load tagged parameter count into r9. | |
3351 __ Integer32ToSmi(r9, rbx); | |
3352 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); | |
3353 __ addp(r8, rcx); | |
3354 __ subp(r8, r9); | |
3355 __ movp(rcx, rdi); | |
3356 __ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | |
3357 __ SmiToInteger64(r9, r9); | |
3358 // r9 = loop variable (untagged) | |
3359 // r8 = mapping index (tagged) | |
3360 // rcx = address of parameter map (tagged) | |
3361 // rdi = address of backing store (tagged) | |
3362 __ jmp(¶meters_test, Label::kNear); | |
3363 | |
3364 __ bind(¶meters_loop); | |
3365 __ subp(r9, Immediate(1)); | |
3366 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | |
3367 __ movp(FieldOperand(rcx, r9, times_pointer_size, kParameterMapHeaderSize), | |
3368 r8); | |
3369 __ movp(FieldOperand(rdi, r9, times_pointer_size, FixedArray::kHeaderSize), | |
3370 kScratchRegister); | |
3371 __ SmiAddConstant(r8, r8, Smi::FromInt(1)); | |
3372 __ bind(¶meters_test); | |
3373 __ testp(r9, r9); | |
3374 __ j(not_zero, ¶meters_loop, Label::kNear); | |
3375 | |
3376 __ bind(&skip_parameter_map); | |
3377 | |
3378 // r11 = argument count (tagged) | |
3379 // rdi = address of backing store (tagged) | |
3380 // Copy arguments header and remaining slots (if there are any). | |
3381 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), | |
3382 factory->fixed_array_map()); | |
3383 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r11); | |
3384 | |
3385 Label arguments_loop, arguments_test; | |
3386 __ movp(r8, rbx); | |
3387 // Untag r11 for the loop below. | |
3388 __ SmiToInteger64(r11, r11); | |
3389 __ leap(kScratchRegister, Operand(r8, times_pointer_size, 0)); | |
3390 __ subp(rdx, kScratchRegister); | |
3391 __ jmp(&arguments_test, Label::kNear); | |
3392 | |
3393 __ bind(&arguments_loop); | |
3394 __ subp(rdx, Immediate(kPointerSize)); | |
3395 __ movp(r9, Operand(rdx, 0)); | |
3396 __ movp(FieldOperand(rdi, r8, | |
3397 times_pointer_size, | |
3398 FixedArray::kHeaderSize), | |
3399 r9); | |
3400 __ addp(r8, Immediate(1)); | |
3401 | |
3402 __ bind(&arguments_test); | |
3403 __ cmpp(r8, r11); | |
3404 __ j(less, &arguments_loop, Label::kNear); | |
3405 | |
3406 // Return. | |
3407 __ ret(0); | |
3408 | |
3409 // Do the runtime call to allocate the arguments object. | |
3410 // r11 = argument count (untagged) | |
3411 __ bind(&runtime); | |
3412 __ Integer32ToSmi(r11, r11); | |
3413 __ PopReturnAddressTo(rax); | |
3414 __ Push(rdi); // Push function. | |
3415 __ Push(rdx); // Push parameters pointer. | |
3416 __ Push(r11); // Push parameter count. | |
3417 __ PushReturnAddressFrom(rax); | |
3418 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
3419 } | |
3420 | |
3421 | |
3422 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | |
3423 // ----------- S t a t e ------------- | |
3424 // -- rdi : function | |
3425 // -- rsi : context | |
3426 // -- rbp : frame pointer | |
3427 // -- rsp[0] : return address | |
3428 // ----------------------------------- | |
3429 __ AssertFunction(rdi); | |
3430 | |
3431 // Make rdx point to the JavaScript frame. | |
3432 __ movp(rdx, rbp); | |
3433 if (skip_stub_frame()) { | |
3434 // For Ignition we need to skip the handler/stub frame to reach the | |
3435 // JavaScript frame for the function. | |
3436 __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
3437 } | |
3438 if (FLAG_debug_code) { | |
3439 Label ok; | |
3440 __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset)); | |
3441 __ j(equal, &ok); | |
3442 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3443 __ bind(&ok); | |
3444 } | |
3445 | |
3446 // Check if we have an arguments adaptor frame below the function frame. | |
3447 Label arguments_adaptor, arguments_done; | |
3448 __ movp(rbx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); | |
3449 __ Cmp(Operand(rbx, CommonFrameConstants::kContextOrFrameTypeOffset), | |
3450 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
3451 __ j(equal, &arguments_adaptor, Label::kNear); | |
3452 { | |
3453 __ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
3454 __ LoadSharedFunctionInfoSpecialField( | |
3455 rax, rax, SharedFunctionInfo::kFormalParameterCountOffset); | |
3456 __ leap(rbx, Operand(rdx, rax, times_pointer_size, | |
3457 StandardFrameConstants::kCallerSPOffset - | |
3458 1 * kPointerSize)); | |
3459 } | |
3460 __ jmp(&arguments_done, Label::kNear); | |
3461 __ bind(&arguments_adaptor); | |
3462 { | |
3463 __ SmiToInteger32( | |
3464 rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3465 __ leap(rbx, Operand(rbx, rax, times_pointer_size, | |
3466 StandardFrameConstants::kCallerSPOffset - | |
3467 1 * kPointerSize)); | |
3468 } | |
3469 __ bind(&arguments_done); | |
3470 | |
3471 // ----------- S t a t e ------------- | |
3472 // -- rax : number of arguments | |
3473 // -- rbx : pointer to the first argument | |
3474 // -- rdi : function | |
3475 // -- rsi : context | |
3476 // -- rsp[0] : return address | |
3477 // ----------------------------------- | |
3478 | |
3479 // Allocate space for the strict arguments object plus the backing store. | |
3480 Label allocate, done_allocate; | |
3481 __ leal(rcx, Operand(rax, times_pointer_size, JSStrictArgumentsObject::kSize + | |
3482 FixedArray::kHeaderSize)); | |
3483 __ Allocate(rcx, rdx, r8, no_reg, &allocate, NO_ALLOCATION_FLAGS); | |
3484 __ bind(&done_allocate); | |
3485 | |
3486 // Compute the arguments.length in rdi. | |
3487 __ Integer32ToSmi(rdi, rax); | |
3488 | |
3489 // Setup the elements array in rdx. | |
3490 __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); | |
3491 __ movp(FieldOperand(rdx, FixedArray::kMapOffset), rcx); | |
3492 __ movp(FieldOperand(rdx, FixedArray::kLengthOffset), rdi); | |
3493 { | |
3494 Label loop, done_loop; | |
3495 __ Set(rcx, 0); | |
3496 __ bind(&loop); | |
3497 __ cmpl(rcx, rax); | |
3498 __ j(equal, &done_loop, Label::kNear); | |
3499 __ movp(kScratchRegister, Operand(rbx, 0 * kPointerSize)); | |
3500 __ movp( | |
3501 FieldOperand(rdx, rcx, times_pointer_size, FixedArray::kHeaderSize), | |
3502 kScratchRegister); | |
3503 __ subp(rbx, Immediate(1 * kPointerSize)); | |
3504 __ addl(rcx, Immediate(1)); | |
3505 __ jmp(&loop); | |
3506 __ bind(&done_loop); | |
3507 } | |
3508 | |
3509 // Setup the strict arguments object in rax. | |
3510 __ leap(rax, | |
3511 Operand(rdx, rax, times_pointer_size, FixedArray::kHeaderSize)); | |
3512 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, rcx); | |
3513 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kMapOffset), rcx); | |
3514 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | |
3515 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kPropertiesOffset), rcx); | |
3516 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kElementsOffset), rdx); | |
3517 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kLengthOffset), rdi); | |
3518 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); | |
3519 __ Ret(); | |
3520 | |
3521 // Fall back to %AllocateInNewSpace (if not too big). | |
3522 Label too_big_for_new_space; | |
3523 __ bind(&allocate); | |
3524 __ cmpl(rcx, Immediate(kMaxRegularHeapObjectSize)); | |
3525 __ j(greater, &too_big_for_new_space); | |
3526 { | |
3527 FrameScope scope(masm, StackFrame::INTERNAL); | |
3528 __ Integer32ToSmi(rax, rax); | |
3529 __ Integer32ToSmi(rcx, rcx); | |
3530 __ Push(rax); | |
3531 __ Push(rbx); | |
3532 __ Push(rcx); | |
3533 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3534 __ movp(rdx, rax); | |
3535 __ Pop(rbx); | |
3536 __ Pop(rax); | |
3537 __ SmiToInteger32(rax, rax); | |
3538 } | |
3539 __ jmp(&done_allocate); | |
3540 | |
3541 // Fall back to %NewStrictArguments. | |
3542 __ bind(&too_big_for_new_space); | |
3543 __ PopReturnAddressTo(kScratchRegister); | |
3544 __ Push(rdi); | |
3545 __ PushReturnAddressFrom(kScratchRegister); | |
3546 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
3547 } | |
3548 | |
3549 | |
3550 static int Offset(ExternalReference ref0, ExternalReference ref1) { | 3025 static int Offset(ExternalReference ref0, ExternalReference ref1) { |
3551 int64_t offset = (ref0.address() - ref1.address()); | 3026 int64_t offset = (ref0.address() - ref1.address()); |
3552 // Check that fits into int. | 3027 // Check that fits into int. |
3553 DCHECK(static_cast<int>(offset) == offset); | 3028 DCHECK(static_cast<int>(offset) == offset); |
3554 return static_cast<int>(offset); | 3029 return static_cast<int>(offset); |
3555 } | 3030 } |
3556 | 3031 |
3557 | |
3558 // Prepares stack to put arguments (aligns and so on). WIN64 calling | 3032 // Prepares stack to put arguments (aligns and so on). WIN64 calling |
3559 // convention requires to put the pointer to the return value slot into | 3033 // convention requires to put the pointer to the return value slot into |
3560 // rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves | 3034 // rcx (rcx must be preserverd until CallApiFunctionAndReturn). Saves |
3561 // context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize | 3035 // context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize |
3562 // inside the exit frame (not GCed) accessible via StackSpaceOperand. | 3036 // inside the exit frame (not GCed) accessible via StackSpaceOperand. |
3563 static void PrepareCallApiFunction(MacroAssembler* masm, int arg_stack_space) { | 3037 static void PrepareCallApiFunction(MacroAssembler* masm, int arg_stack_space) { |
3564 __ EnterApiExitFrame(arg_stack_space); | 3038 __ EnterApiExitFrame(arg_stack_space); |
3565 } | 3039 } |
3566 | 3040 |
3567 | 3041 |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3931 kStackUnwindSpace, nullptr, return_value_operand, | 3405 kStackUnwindSpace, nullptr, return_value_operand, |
3932 NULL); | 3406 NULL); |
3933 } | 3407 } |
3934 | 3408 |
3935 #undef __ | 3409 #undef __ |
3936 | 3410 |
3937 } // namespace internal | 3411 } // namespace internal |
3938 } // namespace v8 | 3412 } // namespace v8 |
3939 | 3413 |
3940 #endif // V8_TARGET_ARCH_X64 | 3414 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |