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 #include "src/crankshaft/ppc/lithium-codegen-ppc.h" | 5 #include "src/crankshaft/ppc/lithium-codegen-ppc.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/hydrogen-osr.h" | 10 #include "src/crankshaft/hydrogen-osr.h" |
(...skipping 3330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3341 __ beq(&invoke); | 3341 __ beq(&invoke); |
3342 __ mtctr(length); | 3342 __ mtctr(length); |
3343 __ bind(&loop); | 3343 __ bind(&loop); |
3344 __ ShiftLeftImm(r0, length, Operand(kPointerSizeLog2)); | 3344 __ ShiftLeftImm(r0, length, Operand(kPointerSizeLog2)); |
3345 __ LoadPX(scratch, MemOperand(elements, r0)); | 3345 __ LoadPX(scratch, MemOperand(elements, r0)); |
3346 __ push(scratch); | 3346 __ push(scratch); |
3347 __ addi(length, length, Operand(-1)); | 3347 __ addi(length, length, Operand(-1)); |
3348 __ bdnz(&loop); | 3348 __ bdnz(&loop); |
3349 | 3349 |
3350 __ bind(&invoke); | 3350 __ bind(&invoke); |
| 3351 |
| 3352 InvokeFlag flag = CALL_FUNCTION; |
| 3353 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) { |
| 3354 // TODO(ishell): drop current frame before pushing arguments to the stack. |
| 3355 flag = JUMP_FUNCTION; |
| 3356 ParameterCount actual(r3); |
| 3357 // It is safe to use r6, r7 and r8 as scratch registers here given that |
| 3358 // 1) we are not going to return to caller function anyway, |
| 3359 // 2) r6 (new.target) will be initialized below. |
| 3360 PrepareForTailCall(actual, r6, r7, r8); |
| 3361 } |
| 3362 |
3351 DCHECK(instr->HasPointerMap()); | 3363 DCHECK(instr->HasPointerMap()); |
3352 LPointerMap* pointers = instr->pointer_map(); | 3364 LPointerMap* pointers = instr->pointer_map(); |
3353 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); | 3365 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); |
3354 // The number of arguments is stored in receiver which is r3, as expected | 3366 // The number of arguments is stored in receiver which is r3, as expected |
3355 // by InvokeFunction. | 3367 // by InvokeFunction. |
3356 ParameterCount actual(receiver); | 3368 ParameterCount actual(receiver); |
3357 __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION, | 3369 __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator); |
3358 safepoint_generator); | |
3359 } | 3370 } |
3360 | 3371 |
3361 | 3372 |
3362 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3373 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3363 LOperand* argument = instr->value(); | 3374 LOperand* argument = instr->value(); |
3364 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3375 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
3365 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3376 Abort(kDoPushArgumentNotImplementedForDoubleType); |
3366 } else { | 3377 } else { |
3367 Register argument_reg = EmitLoadRegister(argument, ip); | 3378 Register argument_reg = EmitLoadRegister(argument, ip); |
3368 __ push(argument_reg); | 3379 __ push(argument_reg); |
(...skipping 24 matching lines...) Expand all Loading... |
3393 | 3404 |
3394 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3405 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3395 DCHECK(ToRegister(instr->context()).is(cp)); | 3406 DCHECK(ToRegister(instr->context()).is(cp)); |
3396 __ Move(scratch0(), instr->hydrogen()->pairs()); | 3407 __ Move(scratch0(), instr->hydrogen()->pairs()); |
3397 __ push(scratch0()); | 3408 __ push(scratch0()); |
3398 __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags())); | 3409 __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags())); |
3399 __ push(scratch0()); | 3410 __ push(scratch0()); |
3400 CallRuntime(Runtime::kDeclareGlobals, instr); | 3411 CallRuntime(Runtime::kDeclareGlobals, instr); |
3401 } | 3412 } |
3402 | 3413 |
3403 | |
3404 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3414 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
3405 int formal_parameter_count, int arity, | 3415 int formal_parameter_count, int arity, |
3406 LInstruction* instr) { | 3416 bool is_tail_call, LInstruction* instr) { |
3407 bool dont_adapt_arguments = | 3417 bool dont_adapt_arguments = |
3408 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3418 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
3409 bool can_invoke_directly = | 3419 bool can_invoke_directly = |
3410 dont_adapt_arguments || formal_parameter_count == arity; | 3420 dont_adapt_arguments || formal_parameter_count == arity; |
3411 | 3421 |
3412 Register function_reg = r4; | 3422 Register function_reg = r4; |
3413 | 3423 |
3414 LPointerMap* pointers = instr->pointer_map(); | 3424 LPointerMap* pointers = instr->pointer_map(); |
3415 | 3425 |
3416 if (can_invoke_directly) { | 3426 if (can_invoke_directly) { |
3417 // Change context. | 3427 // Change context. |
3418 __ LoadP(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 3428 __ LoadP(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
3419 | 3429 |
3420 // Always initialize new target and number of actual arguments. | 3430 // Always initialize new target and number of actual arguments. |
3421 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); | 3431 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); |
3422 __ mov(r3, Operand(arity)); | 3432 __ mov(r3, Operand(arity)); |
3423 | 3433 |
3424 bool is_self_call = function.is_identical_to(info()->closure()); | 3434 bool is_self_call = function.is_identical_to(info()->closure()); |
3425 | 3435 |
3426 // Invoke function. | 3436 // Invoke function. |
3427 if (is_self_call) { | 3437 if (is_self_call) { |
3428 __ CallSelf(); | 3438 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location())); |
| 3439 if (is_tail_call) { |
| 3440 __ Jump(self, RelocInfo::CODE_TARGET); |
| 3441 } else { |
| 3442 __ Call(self, RelocInfo::CODE_TARGET); |
| 3443 } |
3429 } else { | 3444 } else { |
3430 __ LoadP(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | 3445 __ LoadP(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
3431 __ CallJSEntry(ip); | 3446 if (is_tail_call) { |
| 3447 __ JumpToJSEntry(ip); |
| 3448 } else { |
| 3449 __ CallJSEntry(ip); |
| 3450 } |
3432 } | 3451 } |
3433 | 3452 |
3434 // Set up deoptimization. | 3453 if (!is_tail_call) { |
3435 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3454 // Set up deoptimization. |
| 3455 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3456 } |
3436 } else { | 3457 } else { |
3437 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3458 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3438 ParameterCount count(arity); | 3459 ParameterCount actual(arity); |
3439 ParameterCount expected(formal_parameter_count); | 3460 ParameterCount expected(formal_parameter_count); |
3440 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); | 3461 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 3462 __ InvokeFunction(function_reg, expected, actual, flag, generator); |
3441 } | 3463 } |
3442 } | 3464 } |
3443 | 3465 |
3444 | 3466 |
3445 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3467 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3446 DCHECK(instr->context() != NULL); | 3468 DCHECK(instr->context() != NULL); |
3447 DCHECK(ToRegister(instr->context()).is(cp)); | 3469 DCHECK(ToRegister(instr->context()).is(cp)); |
3448 Register input = ToRegister(instr->value()); | 3470 Register input = ToRegister(instr->value()); |
3449 Register result = ToRegister(instr->result()); | 3471 Register result = ToRegister(instr->result()); |
3450 Register scratch = scratch0(); | 3472 Register scratch = scratch0(); |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3759 __ MovFromFloatResult(ToDoubleRegister(instr->result())); | 3781 __ MovFromFloatResult(ToDoubleRegister(instr->result())); |
3760 } | 3782 } |
3761 | 3783 |
3762 | 3784 |
3763 void LCodeGen::DoMathClz32(LMathClz32* instr) { | 3785 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
3764 Register input = ToRegister(instr->value()); | 3786 Register input = ToRegister(instr->value()); |
3765 Register result = ToRegister(instr->result()); | 3787 Register result = ToRegister(instr->result()); |
3766 __ cntlzw_(result, input); | 3788 __ cntlzw_(result, input); |
3767 } | 3789 } |
3768 | 3790 |
| 3791 void LCodeGen::PrepareForTailCall(const ParameterCount& actual, |
| 3792 Register scratch1, Register scratch2, |
| 3793 Register scratch3) { |
| 3794 #if DEBUG |
| 3795 if (actual.is_reg()) { |
| 3796 DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3)); |
| 3797 } else { |
| 3798 DCHECK(!AreAliased(scratch1, scratch2, scratch3)); |
| 3799 } |
| 3800 #endif |
| 3801 if (FLAG_code_comments) { |
| 3802 if (actual.is_reg()) { |
| 3803 Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString()); |
| 3804 } else { |
| 3805 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate()); |
| 3806 } |
| 3807 } |
| 3808 |
| 3809 // Check if next frame is an arguments adaptor frame. |
| 3810 Register caller_args_count_reg = scratch1; |
| 3811 Label no_arguments_adaptor, formal_parameter_count_loaded; |
| 3812 __ LoadP(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3813 __ LoadP(scratch3, |
| 3814 MemOperand(scratch2, StandardFrameConstants::kContextOffset)); |
| 3815 __ CmpSmiLiteral(scratch3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); |
| 3816 __ bne(&no_arguments_adaptor); |
| 3817 |
| 3818 // Drop current frame and load arguments count from arguments adaptor frame. |
| 3819 __ mr(fp, scratch2); |
| 3820 __ LoadP(caller_args_count_reg, |
| 3821 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3822 __ SmiUntag(caller_args_count_reg); |
| 3823 __ b(&formal_parameter_count_loaded); |
| 3824 |
| 3825 __ bind(&no_arguments_adaptor); |
| 3826 // Load caller's formal parameter count |
| 3827 __ mov(caller_args_count_reg, Operand(info()->literal()->parameter_count())); |
| 3828 |
| 3829 __ bind(&formal_parameter_count_loaded); |
| 3830 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3); |
| 3831 |
| 3832 Comment(";;; }"); |
| 3833 } |
3769 | 3834 |
3770 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3835 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3836 HInvokeFunction* hinstr = instr->hydrogen(); |
3771 DCHECK(ToRegister(instr->context()).is(cp)); | 3837 DCHECK(ToRegister(instr->context()).is(cp)); |
3772 DCHECK(ToRegister(instr->function()).is(r4)); | 3838 DCHECK(ToRegister(instr->function()).is(r4)); |
3773 DCHECK(instr->HasPointerMap()); | 3839 DCHECK(instr->HasPointerMap()); |
3774 | 3840 |
3775 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3841 bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow; |
| 3842 |
| 3843 if (is_tail_call) { |
| 3844 ParameterCount actual(instr->arity()); |
| 3845 // It is safe to use r6, r7 and r8 as scratch registers here given that |
| 3846 // 1) we are not going to return to caller function anyway, |
| 3847 // 2) r6 (new.target) will be initialized below. |
| 3848 PrepareForTailCall(actual, r6, r7, r8); |
| 3849 } |
| 3850 |
| 3851 Handle<JSFunction> known_function = hinstr->known_function(); |
3776 if (known_function.is_null()) { | 3852 if (known_function.is_null()) { |
3777 LPointerMap* pointers = instr->pointer_map(); | 3853 LPointerMap* pointers = instr->pointer_map(); |
3778 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3854 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3779 ParameterCount count(instr->arity()); | 3855 ParameterCount actual(instr->arity()); |
3780 __ InvokeFunction(r4, no_reg, count, CALL_FUNCTION, generator); | 3856 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION; |
| 3857 __ InvokeFunction(r4, no_reg, actual, flag, generator); |
3781 } else { | 3858 } else { |
3782 CallKnownFunction(known_function, | 3859 CallKnownFunction(known_function, hinstr->formal_parameter_count(), |
3783 instr->hydrogen()->formal_parameter_count(), | 3860 instr->arity(), is_tail_call, instr); |
3784 instr->arity(), instr); | |
3785 } | 3861 } |
3786 } | 3862 } |
3787 | 3863 |
3788 | 3864 |
3789 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { | 3865 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
3790 DCHECK(ToRegister(instr->result()).is(r3)); | 3866 DCHECK(ToRegister(instr->result()).is(r3)); |
3791 | 3867 |
3792 if (instr->hydrogen()->IsTailCall()) { | 3868 if (instr->hydrogen()->IsTailCall()) { |
3793 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); | 3869 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); |
3794 | 3870 |
(...skipping 1889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5684 | 5760 |
5685 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { | 5761 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { |
5686 Register context = ToRegister(instr->context()); | 5762 Register context = ToRegister(instr->context()); |
5687 __ StoreP(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 5763 __ StoreP(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
5688 } | 5764 } |
5689 | 5765 |
5690 | 5766 |
5691 #undef __ | 5767 #undef __ |
5692 } // namespace internal | 5768 } // namespace internal |
5693 } // namespace v8 | 5769 } // namespace v8 |
OLD | NEW |