OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_ARM | 5 #if V8_TARGET_ARCH_ARM |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 3086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3097 | 3097 |
3098 Label fast_elements_case; | 3098 Label fast_elements_case; |
3099 __ cmp(r3, Operand(FAST_ELEMENTS)); | 3099 __ cmp(r3, Operand(FAST_ELEMENTS)); |
3100 __ b(eq, &fast_elements_case); | 3100 __ b(eq, &fast_elements_case); |
3101 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 3101 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
3102 | 3102 |
3103 __ bind(&fast_elements_case); | 3103 __ bind(&fast_elements_case); |
3104 GenerateCase(masm, FAST_ELEMENTS); | 3104 GenerateCase(masm, FAST_ELEMENTS); |
3105 } | 3105 } |
3106 | 3106 |
3107 | |
3108 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { | |
3109 // ----------- S t a t e ------------- | |
3110 // -- r1 : function | |
3111 // -- cp : context | |
3112 // -- fp : frame pointer | |
3113 // -- lr : return address | |
3114 // ----------------------------------- | |
3115 __ AssertFunction(r1); | |
3116 | |
3117 // Make r2 point to the JavaScript frame. | |
3118 __ mov(r2, fp); | |
3119 if (skip_stub_frame()) { | |
3120 // For Ignition we need to skip the handler/stub frame to reach the | |
3121 // JavaScript frame for the function. | |
3122 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | |
3123 } | |
3124 if (FLAG_debug_code) { | |
3125 Label ok; | |
3126 __ ldr(ip, MemOperand(r2, StandardFrameConstants::kFunctionOffset)); | |
3127 __ cmp(ip, r1); | |
3128 __ b(eq, &ok); | |
3129 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3130 __ bind(&ok); | |
3131 } | |
3132 | |
3133 // Check if we have rest parameters (only possible if we have an | |
3134 // arguments adaptor frame below the function frame). | |
3135 Label no_rest_parameters; | |
3136 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | |
3137 __ ldr(ip, MemOperand(r2, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3138 __ cmp(ip, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3139 __ b(ne, &no_rest_parameters); | |
3140 | |
3141 // Check if the arguments adaptor frame contains more arguments than | |
3142 // specified by the function's internal formal parameter count. | |
3143 Label rest_parameters; | |
3144 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3145 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
3146 __ ldr(r3, | |
3147 FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3148 __ sub(r0, r0, r3, SetCC); | |
3149 __ b(gt, &rest_parameters); | |
3150 | |
3151 // Return an empty rest parameter array. | |
3152 __ bind(&no_rest_parameters); | |
3153 { | |
3154 // ----------- S t a t e ------------- | |
3155 // -- cp : context | |
3156 // -- lr : return address | |
3157 // ----------------------------------- | |
3158 | |
3159 // Allocate an empty rest parameter array. | |
3160 Label allocate, done_allocate; | |
3161 __ Allocate(JSArray::kSize, r0, r1, r2, &allocate, NO_ALLOCATION_FLAGS); | |
3162 __ bind(&done_allocate); | |
3163 | |
3164 // Setup the rest parameter array in r0. | |
3165 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r1); | |
3166 __ str(r1, FieldMemOperand(r0, JSArray::kMapOffset)); | |
3167 __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex); | |
3168 __ str(r1, FieldMemOperand(r0, JSArray::kPropertiesOffset)); | |
3169 __ str(r1, FieldMemOperand(r0, JSArray::kElementsOffset)); | |
3170 __ mov(r1, Operand(0)); | |
3171 __ str(r1, FieldMemOperand(r0, JSArray::kLengthOffset)); | |
3172 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3173 __ Ret(); | |
3174 | |
3175 // Fall back to %AllocateInNewSpace. | |
3176 __ bind(&allocate); | |
3177 { | |
3178 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | |
3179 __ Push(Smi::FromInt(JSArray::kSize)); | |
3180 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3181 } | |
3182 __ jmp(&done_allocate); | |
3183 } | |
3184 | |
3185 __ bind(&rest_parameters); | |
3186 { | |
3187 // Compute the pointer to the first rest parameter (skippping the receiver). | |
3188 __ add(r2, r2, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3189 __ add(r2, r2, | |
3190 Operand(StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); | |
3191 | |
3192 // ----------- S t a t e ------------- | |
3193 // -- cp : context | |
3194 // -- r0 : number of rest parameters (tagged) | |
3195 // -- r1 : function | |
3196 // -- r2 : pointer to first rest parameters | |
3197 // -- lr : return address | |
3198 // ----------------------------------- | |
3199 | |
3200 // Allocate space for the rest parameter array plus the backing store. | |
3201 Label allocate, done_allocate; | |
3202 __ mov(r6, Operand(JSArray::kSize + FixedArray::kHeaderSize)); | |
3203 __ add(r6, r6, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3204 __ Allocate(r6, r3, r4, r5, &allocate, NO_ALLOCATION_FLAGS); | |
3205 __ bind(&done_allocate); | |
3206 | |
3207 // Setup the elements array in r3. | |
3208 __ LoadRoot(r1, Heap::kFixedArrayMapRootIndex); | |
3209 __ str(r1, FieldMemOperand(r3, FixedArray::kMapOffset)); | |
3210 __ str(r0, FieldMemOperand(r3, FixedArray::kLengthOffset)); | |
3211 __ add(r4, r3, Operand(FixedArray::kHeaderSize)); | |
3212 { | |
3213 Label loop, done_loop; | |
3214 __ add(r1, r4, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3215 __ bind(&loop); | |
3216 __ cmp(r4, r1); | |
3217 __ b(eq, &done_loop); | |
3218 __ ldr(ip, MemOperand(r2, 1 * kPointerSize, NegPostIndex)); | |
3219 __ str(ip, FieldMemOperand(r4, 0 * kPointerSize)); | |
3220 __ add(r4, r4, Operand(1 * kPointerSize)); | |
3221 __ b(&loop); | |
3222 __ bind(&done_loop); | |
3223 } | |
3224 | |
3225 // Setup the rest parameter array in r4. | |
3226 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r1); | |
3227 __ str(r1, FieldMemOperand(r4, JSArray::kMapOffset)); | |
3228 __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex); | |
3229 __ str(r1, FieldMemOperand(r4, JSArray::kPropertiesOffset)); | |
3230 __ str(r3, FieldMemOperand(r4, JSArray::kElementsOffset)); | |
3231 __ str(r0, FieldMemOperand(r4, JSArray::kLengthOffset)); | |
3232 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3233 __ mov(r0, r4); | |
3234 __ Ret(); | |
3235 | |
3236 // Fall back to %AllocateInNewSpace (if not too big). | |
3237 Label too_big_for_new_space; | |
3238 __ bind(&allocate); | |
3239 __ cmp(r6, Operand(kMaxRegularHeapObjectSize)); | |
3240 __ b(gt, &too_big_for_new_space); | |
3241 { | |
3242 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | |
3243 __ SmiTag(r6); | |
3244 __ Push(r0, r2, r6); | |
3245 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3246 __ mov(r3, r0); | |
3247 __ Pop(r0, r2); | |
3248 } | |
3249 __ jmp(&done_allocate); | |
3250 | |
3251 // Fall back to %NewRestParameter. | |
3252 __ bind(&too_big_for_new_space); | |
3253 __ push(r1); | |
3254 __ TailCallRuntime(Runtime::kNewRestParameter); | |
3255 } | |
3256 } | |
3257 | |
3258 | |
3259 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { | |
3260 // ----------- S t a t e ------------- | |
3261 // -- r1 : function | |
3262 // -- cp : context | |
3263 // -- fp : frame pointer | |
3264 // -- lr : return address | |
3265 // ----------------------------------- | |
3266 __ AssertFunction(r1); | |
3267 | |
3268 // Make r9 point to the JavaScript frame. | |
3269 __ mov(r9, fp); | |
3270 if (skip_stub_frame()) { | |
3271 // For Ignition we need to skip the handler/stub frame to reach the | |
3272 // JavaScript frame for the function. | |
3273 __ ldr(r9, MemOperand(r9, StandardFrameConstants::kCallerFPOffset)); | |
3274 } | |
3275 if (FLAG_debug_code) { | |
3276 Label ok; | |
3277 __ ldr(ip, MemOperand(r9, StandardFrameConstants::kFunctionOffset)); | |
3278 __ cmp(ip, r1); | |
3279 __ b(eq, &ok); | |
3280 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3281 __ bind(&ok); | |
3282 } | |
3283 | |
3284 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. | |
3285 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
3286 __ ldr(r2, | |
3287 FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3288 __ add(r3, r9, Operand(r2, LSL, kPointerSizeLog2 - 1)); | |
3289 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | |
3290 | |
3291 // r1 : function | |
3292 // r2 : number of parameters (tagged) | |
3293 // r3 : parameters pointer | |
3294 // r9 : JavaScript frame pointer | |
3295 // Registers used over whole function: | |
3296 // r5 : arguments count (tagged) | |
3297 // r6 : mapped parameter count (tagged) | |
3298 | |
3299 // Check if the calling frame is an arguments adaptor frame. | |
3300 Label adaptor_frame, try_allocate, runtime; | |
3301 __ ldr(r4, MemOperand(r9, StandardFrameConstants::kCallerFPOffset)); | |
3302 __ ldr(r0, MemOperand(r4, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3303 __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3304 __ b(eq, &adaptor_frame); | |
3305 | |
3306 // No adaptor, parameter count = argument count. | |
3307 __ mov(r5, r2); | |
3308 __ mov(r6, r2); | |
3309 __ b(&try_allocate); | |
3310 | |
3311 // We have an adaptor frame. Patch the parameters pointer. | |
3312 __ bind(&adaptor_frame); | |
3313 __ ldr(r5, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3314 __ add(r4, r4, Operand(r5, LSL, 1)); | |
3315 __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset)); | |
3316 | |
3317 // r5 = argument count (tagged) | |
3318 // r6 = parameter count (tagged) | |
3319 // Compute the mapped parameter count = min(r6, r5) in r6. | |
3320 __ mov(r6, r2); | |
3321 __ cmp(r6, Operand(r5)); | |
3322 __ mov(r6, Operand(r5), LeaveCC, gt); | |
3323 | |
3324 __ bind(&try_allocate); | |
3325 | |
3326 // Compute the sizes of backing store, parameter map, and arguments object. | |
3327 // 1. Parameter map, has 2 extra words containing context and backing store. | |
3328 const int kParameterMapHeaderSize = | |
3329 FixedArray::kHeaderSize + 2 * kPointerSize; | |
3330 // If there are no mapped parameters, we do not need the parameter_map. | |
3331 __ cmp(r6, Operand(Smi::kZero)); | |
3332 __ mov(r9, Operand::Zero(), LeaveCC, eq); | |
3333 __ mov(r9, Operand(r6, LSL, 1), LeaveCC, ne); | |
3334 __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne); | |
3335 | |
3336 // 2. Backing store. | |
3337 __ add(r9, r9, Operand(r5, LSL, 1)); | |
3338 __ add(r9, r9, Operand(FixedArray::kHeaderSize)); | |
3339 | |
3340 // 3. Arguments object. | |
3341 __ add(r9, r9, Operand(JSSloppyArgumentsObject::kSize)); | |
3342 | |
3343 // Do the allocation of all three objects in one go. | |
3344 __ Allocate(r9, r0, r9, r4, &runtime, NO_ALLOCATION_FLAGS); | |
3345 | |
3346 // r0 = address of new object(s) (tagged) | |
3347 // r2 = argument count (smi-tagged) | |
3348 // Get the arguments boilerplate from the current native context into r4. | |
3349 const int kNormalOffset = | |
3350 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | |
3351 const int kAliasedOffset = | |
3352 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | |
3353 | |
3354 __ ldr(r4, NativeContextMemOperand()); | |
3355 __ cmp(r6, Operand::Zero()); | |
3356 __ ldr(r4, MemOperand(r4, kNormalOffset), eq); | |
3357 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); | |
3358 | |
3359 // r0 = address of new object (tagged) | |
3360 // r2 = argument count (smi-tagged) | |
3361 // r4 = address of arguments map (tagged) | |
3362 // r6 = mapped parameter count (tagged) | |
3363 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); | |
3364 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); | |
3365 __ str(r9, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | |
3366 __ str(r9, FieldMemOperand(r0, JSObject::kElementsOffset)); | |
3367 | |
3368 // Set up the callee in-object property. | |
3369 __ AssertNotSmi(r1); | |
3370 __ str(r1, FieldMemOperand(r0, JSSloppyArgumentsObject::kCalleeOffset)); | |
3371 | |
3372 // Use the length (smi tagged) and set that as an in-object property too. | |
3373 __ AssertSmi(r5); | |
3374 __ str(r5, FieldMemOperand(r0, JSSloppyArgumentsObject::kLengthOffset)); | |
3375 | |
3376 // Set up the elements pointer in the allocated arguments object. | |
3377 // If we allocated a parameter map, r4 will point there, otherwise | |
3378 // it will point to the backing store. | |
3379 __ add(r4, r0, Operand(JSSloppyArgumentsObject::kSize)); | |
3380 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | |
3381 | |
3382 // r0 = address of new object (tagged) | |
3383 // r2 = argument count (tagged) | |
3384 // r4 = address of parameter map or backing store (tagged) | |
3385 // r6 = mapped parameter count (tagged) | |
3386 // Initialize parameter map. If there are no mapped arguments, we're done. | |
3387 Label skip_parameter_map; | |
3388 __ cmp(r6, Operand(Smi::kZero)); | |
3389 // Move backing store address to r1, because it is | |
3390 // expected there when filling in the unmapped arguments. | |
3391 __ mov(r1, r4, LeaveCC, eq); | |
3392 __ b(eq, &skip_parameter_map); | |
3393 | |
3394 __ LoadRoot(r5, Heap::kSloppyArgumentsElementsMapRootIndex); | |
3395 __ str(r5, FieldMemOperand(r4, FixedArray::kMapOffset)); | |
3396 __ add(r5, r6, Operand(Smi::FromInt(2))); | |
3397 __ str(r5, FieldMemOperand(r4, FixedArray::kLengthOffset)); | |
3398 __ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize)); | |
3399 __ add(r5, r4, Operand(r6, LSL, 1)); | |
3400 __ add(r5, r5, Operand(kParameterMapHeaderSize)); | |
3401 __ str(r5, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize)); | |
3402 | |
3403 // Copy the parameter slots and the holes in the arguments. | |
3404 // We need to fill in mapped_parameter_count slots. They index the context, | |
3405 // where parameters are stored in reverse order, at | |
3406 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
3407 // The mapped parameter thus need to get indices | |
3408 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
3409 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
3410 // We loop from right to left. | |
3411 Label parameters_loop, parameters_test; | |
3412 __ mov(r5, r6); | |
3413 __ add(r9, r2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | |
3414 __ sub(r9, r9, Operand(r6)); | |
3415 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
3416 __ add(r1, r4, Operand(r5, LSL, 1)); | |
3417 __ add(r1, r1, Operand(kParameterMapHeaderSize)); | |
3418 | |
3419 // r1 = address of backing store (tagged) | |
3420 // r4 = address of parameter map (tagged), which is also the address of new | |
3421 // object + Heap::kSloppyArgumentsObjectSize (tagged) | |
3422 // r0 = temporary scratch (a.o., for address calculation) | |
3423 // r5 = loop variable (tagged) | |
3424 // ip = the hole value | |
3425 __ jmp(¶meters_test); | |
3426 | |
3427 __ bind(¶meters_loop); | |
3428 __ sub(r5, r5, Operand(Smi::FromInt(1))); | |
3429 __ mov(r0, Operand(r5, LSL, 1)); | |
3430 __ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); | |
3431 __ str(r9, MemOperand(r4, r0)); | |
3432 __ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); | |
3433 __ str(ip, MemOperand(r1, r0)); | |
3434 __ add(r9, r9, Operand(Smi::FromInt(1))); | |
3435 __ bind(¶meters_test); | |
3436 __ cmp(r5, Operand(Smi::kZero)); | |
3437 __ b(ne, ¶meters_loop); | |
3438 | |
3439 // Restore r0 = new object (tagged) and r5 = argument count (tagged). | |
3440 __ sub(r0, r4, Operand(JSSloppyArgumentsObject::kSize)); | |
3441 __ ldr(r5, FieldMemOperand(r0, JSSloppyArgumentsObject::kLengthOffset)); | |
3442 | |
3443 __ bind(&skip_parameter_map); | |
3444 // r0 = address of new object (tagged) | |
3445 // r1 = address of backing store (tagged) | |
3446 // r5 = argument count (tagged) | |
3447 // r6 = mapped parameter count (tagged) | |
3448 // r9 = scratch | |
3449 // Copy arguments header and remaining slots (if there are any). | |
3450 __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex); | |
3451 __ str(r9, FieldMemOperand(r1, FixedArray::kMapOffset)); | |
3452 __ str(r5, FieldMemOperand(r1, FixedArray::kLengthOffset)); | |
3453 | |
3454 Label arguments_loop, arguments_test; | |
3455 __ sub(r3, r3, Operand(r6, LSL, 1)); | |
3456 __ jmp(&arguments_test); | |
3457 | |
3458 __ bind(&arguments_loop); | |
3459 __ sub(r3, r3, Operand(kPointerSize)); | |
3460 __ ldr(r4, MemOperand(r3, 0)); | |
3461 __ add(r9, r1, Operand(r6, LSL, 1)); | |
3462 __ str(r4, FieldMemOperand(r9, FixedArray::kHeaderSize)); | |
3463 __ add(r6, r6, Operand(Smi::FromInt(1))); | |
3464 | |
3465 __ bind(&arguments_test); | |
3466 __ cmp(r6, Operand(r5)); | |
3467 __ b(lt, &arguments_loop); | |
3468 | |
3469 // Return. | |
3470 __ Ret(); | |
3471 | |
3472 // Do the runtime call to allocate the arguments object. | |
3473 // r0 = address of new object (tagged) | |
3474 // r5 = argument count (tagged) | |
3475 __ bind(&runtime); | |
3476 __ Push(r1, r3, r5); | |
3477 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
3478 } | |
3479 | |
3480 | |
3481 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | |
3482 // ----------- S t a t e ------------- | |
3483 // -- r1 : function | |
3484 // -- cp : context | |
3485 // -- fp : frame pointer | |
3486 // -- lr : return address | |
3487 // ----------------------------------- | |
3488 __ AssertFunction(r1); | |
3489 | |
3490 // Make r2 point to the JavaScript frame. | |
3491 __ mov(r2, fp); | |
3492 if (skip_stub_frame()) { | |
3493 // For Ignition we need to skip the handler/stub frame to reach the | |
3494 // JavaScript frame for the function. | |
3495 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | |
3496 } | |
3497 if (FLAG_debug_code) { | |
3498 Label ok; | |
3499 __ ldr(ip, MemOperand(r2, StandardFrameConstants::kFunctionOffset)); | |
3500 __ cmp(ip, r1); | |
3501 __ b(eq, &ok); | |
3502 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3503 __ bind(&ok); | |
3504 } | |
3505 | |
3506 // Check if we have an arguments adaptor frame below the function frame. | |
3507 Label arguments_adaptor, arguments_done; | |
3508 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | |
3509 __ ldr(ip, MemOperand(r3, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3510 __ cmp(ip, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3511 __ b(eq, &arguments_adaptor); | |
3512 { | |
3513 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
3514 __ ldr(r0, FieldMemOperand( | |
3515 r4, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3516 __ add(r2, r2, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3517 __ add(r2, r2, | |
3518 Operand(StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); | |
3519 } | |
3520 __ b(&arguments_done); | |
3521 __ bind(&arguments_adaptor); | |
3522 { | |
3523 __ ldr(r0, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3524 __ add(r2, r3, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3525 __ add(r2, r2, | |
3526 Operand(StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); | |
3527 } | |
3528 __ bind(&arguments_done); | |
3529 | |
3530 // ----------- S t a t e ------------- | |
3531 // -- cp : context | |
3532 // -- r0 : number of rest parameters (tagged) | |
3533 // -- r1 : function | |
3534 // -- r2 : pointer to first rest parameters | |
3535 // -- lr : return address | |
3536 // ----------------------------------- | |
3537 | |
3538 // Allocate space for the strict arguments object plus the backing store. | |
3539 Label allocate, done_allocate; | |
3540 __ mov(r6, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); | |
3541 __ add(r6, r6, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3542 __ Allocate(r6, r3, r4, r5, &allocate, NO_ALLOCATION_FLAGS); | |
3543 __ bind(&done_allocate); | |
3544 | |
3545 // Setup the elements array in r3. | |
3546 __ LoadRoot(r1, Heap::kFixedArrayMapRootIndex); | |
3547 __ str(r1, FieldMemOperand(r3, FixedArray::kMapOffset)); | |
3548 __ str(r0, FieldMemOperand(r3, FixedArray::kLengthOffset)); | |
3549 __ add(r4, r3, Operand(FixedArray::kHeaderSize)); | |
3550 { | |
3551 Label loop, done_loop; | |
3552 __ add(r1, r4, Operand(r0, LSL, kPointerSizeLog2 - 1)); | |
3553 __ bind(&loop); | |
3554 __ cmp(r4, r1); | |
3555 __ b(eq, &done_loop); | |
3556 __ ldr(ip, MemOperand(r2, 1 * kPointerSize, NegPostIndex)); | |
3557 __ str(ip, FieldMemOperand(r4, 0 * kPointerSize)); | |
3558 __ add(r4, r4, Operand(1 * kPointerSize)); | |
3559 __ b(&loop); | |
3560 __ bind(&done_loop); | |
3561 } | |
3562 | |
3563 // Setup the strict arguments object in r4. | |
3564 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r1); | |
3565 __ str(r1, FieldMemOperand(r4, JSStrictArgumentsObject::kMapOffset)); | |
3566 __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex); | |
3567 __ str(r1, FieldMemOperand(r4, JSStrictArgumentsObject::kPropertiesOffset)); | |
3568 __ str(r3, FieldMemOperand(r4, JSStrictArgumentsObject::kElementsOffset)); | |
3569 __ str(r0, FieldMemOperand(r4, JSStrictArgumentsObject::kLengthOffset)); | |
3570 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); | |
3571 __ mov(r0, r4); | |
3572 __ Ret(); | |
3573 | |
3574 // Fall back to %AllocateInNewSpace (if not too big). | |
3575 Label too_big_for_new_space; | |
3576 __ bind(&allocate); | |
3577 __ cmp(r6, Operand(kMaxRegularHeapObjectSize)); | |
3578 __ b(gt, &too_big_for_new_space); | |
3579 { | |
3580 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | |
3581 __ SmiTag(r6); | |
3582 __ Push(r0, r2, r6); | |
3583 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3584 __ mov(r3, r0); | |
3585 __ Pop(r0, r2); | |
3586 } | |
3587 __ b(&done_allocate); | |
3588 | |
3589 // Fall back to %NewStrictArguments. | |
3590 __ bind(&too_big_for_new_space); | |
3591 __ push(r1); | |
3592 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
3593 } | |
3594 | |
3595 | |
3596 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 3107 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
3597 return ref0.address() - ref1.address(); | 3108 return ref0.address() - ref1.address(); |
3598 } | 3109 } |
3599 | 3110 |
3600 | 3111 |
3601 // Calls an API function. Allocates HandleScope, extracts returned value | 3112 // Calls an API function. Allocates HandleScope, extracts returned value |
3602 // from handle and propagates exceptions. Restores context. stack_space | 3113 // from handle and propagates exceptions. Restores context. stack_space |
3603 // - space to be unwound on exit (includes the call JS arguments space and | 3114 // - space to be unwound on exit (includes the call JS arguments space and |
3604 // the additional space allocated for the fast call). | 3115 // the additional space allocated for the fast call). |
3605 static void CallApiFunctionAndReturn(MacroAssembler* masm, | 3116 static void CallApiFunctionAndReturn(MacroAssembler* masm, |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3901 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 3412 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
3902 kStackUnwindSpace, NULL, return_value_operand, NULL); | 3413 kStackUnwindSpace, NULL, return_value_operand, NULL); |
3903 } | 3414 } |
3904 | 3415 |
3905 #undef __ | 3416 #undef __ |
3906 | 3417 |
3907 } // namespace internal | 3418 } // namespace internal |
3908 } // namespace v8 | 3419 } // namespace v8 |
3909 | 3420 |
3910 #endif // V8_TARGET_ARCH_ARM | 3421 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |