Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: src/crankshaft/ppc/lithium-codegen-ppc.cc

Issue 1767173002: PPC: [crankshaft] Support ES6 tail call elimination. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/crankshaft/ppc/lithium-codegen-ppc.h ('k') | src/crankshaft/ppc/lithium-ppc.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/crankshaft/ppc/lithium-codegen-ppc.h ('k') | src/crankshaft/ppc/lithium-ppc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698