| 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 #include "src/crankshaft/arm/lithium-codegen-arm.h" | 5 #include "src/crankshaft/arm/lithium-codegen-arm.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/crankshaft/arm/lithium-gap-resolver-arm.h" | 10 #include "src/crankshaft/arm/lithium-gap-resolver-arm.h" |
| (...skipping 3177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3188 // length is a small non-negative integer, due to the test above. | 3188 // length is a small non-negative integer, due to the test above. |
| 3189 __ cmp(length, Operand::Zero()); | 3189 __ cmp(length, Operand::Zero()); |
| 3190 __ b(eq, &invoke); | 3190 __ b(eq, &invoke); |
| 3191 __ bind(&loop); | 3191 __ bind(&loop); |
| 3192 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); | 3192 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); |
| 3193 __ push(scratch); | 3193 __ push(scratch); |
| 3194 __ sub(length, length, Operand(1), SetCC); | 3194 __ sub(length, length, Operand(1), SetCC); |
| 3195 __ b(ne, &loop); | 3195 __ b(ne, &loop); |
| 3196 | 3196 |
| 3197 __ bind(&invoke); | 3197 __ bind(&invoke); |
| 3198 |
| 3199 InvokeFlag flag = CALL_FUNCTION; |
| 3200 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) { |
| 3201 // TODO(ishell): drop current frame before pushing arguments to the stack. |
| 3202 flag = JUMP_FUNCTION; |
| 3203 ParameterCount actual(r0); |
| 3204 // It is safe to use r3, r4 and r5 as scratch registers here given that |
| 3205 // 1) we are not going to return to caller function anyway, |
| 3206 // 2) r3 (new.target) will be initialized below. |
| 3207 PrepareForTailCall(actual, r3, r4, r5); |
| 3208 } |
| 3209 |
| 3198 DCHECK(instr->HasPointerMap()); | 3210 DCHECK(instr->HasPointerMap()); |
| 3199 LPointerMap* pointers = instr->pointer_map(); | 3211 LPointerMap* pointers = instr->pointer_map(); |
| 3200 SafepointGenerator safepoint_generator( | 3212 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); |
| 3201 this, pointers, Safepoint::kLazyDeopt); | |
| 3202 // The number of arguments is stored in receiver which is r0, as expected | 3213 // The number of arguments is stored in receiver which is r0, as expected |
| 3203 // by InvokeFunction. | 3214 // by InvokeFunction. |
| 3204 ParameterCount actual(receiver); | 3215 ParameterCount actual(receiver); |
| 3205 __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION, | 3216 __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator); |
| 3206 safepoint_generator); | |
| 3207 } | 3217 } |
| 3208 | 3218 |
| 3209 | 3219 |
| 3210 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3220 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3211 LOperand* argument = instr->value(); | 3221 LOperand* argument = instr->value(); |
| 3212 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3222 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 3213 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3223 Abort(kDoPushArgumentNotImplementedForDoubleType); |
| 3214 } else { | 3224 } else { |
| 3215 Register argument_reg = EmitLoadRegister(argument, ip); | 3225 Register argument_reg = EmitLoadRegister(argument, ip); |
| 3216 __ push(argument_reg); | 3226 __ push(argument_reg); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3243 | 3253 |
| 3244 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3254 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3245 DCHECK(ToRegister(instr->context()).is(cp)); | 3255 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3246 __ Move(scratch0(), instr->hydrogen()->pairs()); | 3256 __ Move(scratch0(), instr->hydrogen()->pairs()); |
| 3247 __ push(scratch0()); | 3257 __ push(scratch0()); |
| 3248 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3258 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
| 3249 __ push(scratch0()); | 3259 __ push(scratch0()); |
| 3250 CallRuntime(Runtime::kDeclareGlobals, instr); | 3260 CallRuntime(Runtime::kDeclareGlobals, instr); |
| 3251 } | 3261 } |
| 3252 | 3262 |
| 3253 | |
| 3254 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3263 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3255 int formal_parameter_count, int arity, | 3264 int formal_parameter_count, int arity, |
| 3256 LInstruction* instr) { | 3265 bool is_tail_call, LInstruction* instr) { |
| 3257 bool dont_adapt_arguments = | 3266 bool dont_adapt_arguments = |
| 3258 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3267 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3259 bool can_invoke_directly = | 3268 bool can_invoke_directly = |
| 3260 dont_adapt_arguments || formal_parameter_count == arity; | 3269 dont_adapt_arguments || formal_parameter_count == arity; |
| 3261 | 3270 |
| 3262 Register function_reg = r1; | 3271 Register function_reg = r1; |
| 3263 | 3272 |
| 3264 LPointerMap* pointers = instr->pointer_map(); | 3273 LPointerMap* pointers = instr->pointer_map(); |
| 3265 | 3274 |
| 3266 if (can_invoke_directly) { | 3275 if (can_invoke_directly) { |
| 3267 // Change context. | 3276 // Change context. |
| 3268 __ ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 3277 __ ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
| 3269 | 3278 |
| 3270 // Always initialize new target and number of actual arguments. | 3279 // Always initialize new target and number of actual arguments. |
| 3271 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 3280 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
| 3272 __ mov(r0, Operand(arity)); | 3281 __ mov(r0, Operand(arity)); |
| 3273 | 3282 |
| 3283 bool is_self_call = function.is_identical_to(info()->closure()); |
| 3284 |
| 3274 // Invoke function. | 3285 // Invoke function. |
| 3275 __ ldr(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | 3286 if (is_self_call) { |
| 3276 __ Call(ip); | 3287 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location())); |
| 3288 if (is_tail_call) { |
| 3289 __ Jump(self, RelocInfo::CODE_TARGET); |
| 3290 } else { |
| 3291 __ Call(self, RelocInfo::CODE_TARGET); |
| 3292 } |
| 3293 } else { |
| 3294 __ ldr(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
| 3295 if (is_tail_call) { |
| 3296 __ Jump(ip); |
| 3297 } else { |
| 3298 __ Call(ip); |
| 3299 } |
| 3300 } |
| 3277 | 3301 |
| 3278 // Set up deoptimization. | 3302 if (!is_tail_call) { |
| 3279 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3303 // Set up deoptimization. |
| 3304 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3305 } |
| 3280 } else { | 3306 } else { |
| 3281 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3307 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3282 ParameterCount count(arity); | 3308 ParameterCount actual(arity); |
| 3283 ParameterCount expected(formal_parameter_count); | 3309 ParameterCount expected(formal_parameter_count); |
| 3284 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); | 3310 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 3311 __ InvokeFunction(function_reg, expected, actual, flag, generator); |
| 3285 } | 3312 } |
| 3286 } | 3313 } |
| 3287 | 3314 |
| 3288 | 3315 |
| 3289 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3316 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3290 DCHECK(instr->context() != NULL); | 3317 DCHECK(instr->context() != NULL); |
| 3291 DCHECK(ToRegister(instr->context()).is(cp)); | 3318 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3292 Register input = ToRegister(instr->value()); | 3319 Register input = ToRegister(instr->value()); |
| 3293 Register result = ToRegister(instr->result()); | 3320 Register result = ToRegister(instr->result()); |
| 3294 Register scratch = scratch0(); | 3321 Register scratch = scratch0(); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3561 __ MovFromFloatResult(ToDoubleRegister(instr->result())); | 3588 __ MovFromFloatResult(ToDoubleRegister(instr->result())); |
| 3562 } | 3589 } |
| 3563 | 3590 |
| 3564 | 3591 |
| 3565 void LCodeGen::DoMathClz32(LMathClz32* instr) { | 3592 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
| 3566 Register input = ToRegister(instr->value()); | 3593 Register input = ToRegister(instr->value()); |
| 3567 Register result = ToRegister(instr->result()); | 3594 Register result = ToRegister(instr->result()); |
| 3568 __ clz(result, input); | 3595 __ clz(result, input); |
| 3569 } | 3596 } |
| 3570 | 3597 |
| 3598 void LCodeGen::PrepareForTailCall(const ParameterCount& actual, |
| 3599 Register scratch1, Register scratch2, |
| 3600 Register scratch3) { |
| 3601 #if DEBUG |
| 3602 if (actual.is_reg()) { |
| 3603 DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3)); |
| 3604 } else { |
| 3605 DCHECK(!AreAliased(scratch1, scratch2, scratch3)); |
| 3606 } |
| 3607 #endif |
| 3608 if (FLAG_code_comments) { |
| 3609 if (actual.is_reg()) { |
| 3610 Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString()); |
| 3611 } else { |
| 3612 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate()); |
| 3613 } |
| 3614 } |
| 3615 |
| 3616 // Check if next frame is an arguments adaptor frame. |
| 3617 Register caller_args_count_reg = scratch1; |
| 3618 Label no_arguments_adaptor, formal_parameter_count_loaded; |
| 3619 __ ldr(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3620 __ ldr(scratch3, |
| 3621 MemOperand(scratch2, StandardFrameConstants::kContextOffset)); |
| 3622 __ cmp(scratch3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3623 __ b(ne, &no_arguments_adaptor); |
| 3624 |
| 3625 // Drop current frame and load arguments count from arguments adaptor frame. |
| 3626 __ mov(fp, scratch2); |
| 3627 __ ldr(caller_args_count_reg, |
| 3628 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3629 __ SmiUntag(caller_args_count_reg); |
| 3630 __ b(&formal_parameter_count_loaded); |
| 3631 |
| 3632 __ bind(&no_arguments_adaptor); |
| 3633 // Load caller's formal parameter count |
| 3634 __ mov(caller_args_count_reg, Operand(info()->literal()->parameter_count())); |
| 3635 |
| 3636 __ bind(&formal_parameter_count_loaded); |
| 3637 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3); |
| 3638 |
| 3639 Comment(";;; }"); |
| 3640 } |
| 3571 | 3641 |
| 3572 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3642 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3643 HInvokeFunction* hinstr = instr->hydrogen(); |
| 3573 DCHECK(ToRegister(instr->context()).is(cp)); | 3644 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3574 DCHECK(ToRegister(instr->function()).is(r1)); | 3645 DCHECK(ToRegister(instr->function()).is(r1)); |
| 3575 DCHECK(instr->HasPointerMap()); | 3646 DCHECK(instr->HasPointerMap()); |
| 3576 | 3647 |
| 3577 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3648 bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow; |
| 3649 |
| 3650 if (is_tail_call) { |
| 3651 ParameterCount actual(instr->arity()); |
| 3652 // It is safe to use r3, r4 and r5 as scratch registers here given that |
| 3653 // 1) we are not going to return to caller function anyway, |
| 3654 // 2) r3 (new.target) will be initialized below. |
| 3655 PrepareForTailCall(actual, r3, r4, r5); |
| 3656 } |
| 3657 |
| 3658 Handle<JSFunction> known_function = hinstr->known_function(); |
| 3578 if (known_function.is_null()) { | 3659 if (known_function.is_null()) { |
| 3579 LPointerMap* pointers = instr->pointer_map(); | 3660 LPointerMap* pointers = instr->pointer_map(); |
| 3580 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3661 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3581 ParameterCount count(instr->arity()); | 3662 ParameterCount actual(instr->arity()); |
| 3582 __ InvokeFunction(r1, no_reg, count, CALL_FUNCTION, generator); | 3663 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 3664 __ InvokeFunction(r1, no_reg, actual, flag, generator); |
| 3583 } else { | 3665 } else { |
| 3584 CallKnownFunction(known_function, | 3666 CallKnownFunction(known_function, hinstr->formal_parameter_count(), |
| 3585 instr->hydrogen()->formal_parameter_count(), | 3667 instr->arity(), is_tail_call, instr); |
| 3586 instr->arity(), instr); | |
| 3587 } | 3668 } |
| 3588 } | 3669 } |
| 3589 | 3670 |
| 3590 | 3671 |
| 3591 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { | 3672 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
| 3592 DCHECK(ToRegister(instr->result()).is(r0)); | 3673 DCHECK(ToRegister(instr->result()).is(r0)); |
| 3593 | 3674 |
| 3594 if (instr->hydrogen()->IsTailCall()) { | 3675 if (instr->hydrogen()->IsTailCall()) { |
| 3595 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); | 3676 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); |
| 3596 | 3677 |
| (...skipping 1880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5477 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { | 5558 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { |
| 5478 Register context = ToRegister(instr->context()); | 5559 Register context = ToRegister(instr->context()); |
| 5479 __ str(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 5560 __ str(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 5480 } | 5561 } |
| 5481 | 5562 |
| 5482 | 5563 |
| 5483 #undef __ | 5564 #undef __ |
| 5484 | 5565 |
| 5485 } // namespace internal | 5566 } // namespace internal |
| 5486 } // namespace v8 | 5567 } // namespace v8 |
| OLD | NEW |