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

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

Issue 1760253003: [crankshaft] Support ES6 tail call elimination. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@tco-crank-2
Patch Set: Addressing comments 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/mips64/lithium-codegen-mips64.h ('k') | src/crankshaft/mips64/lithium-mips64.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 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/mips64/lithium-codegen-mips64.h" 5 #include "src/crankshaft/mips64/lithium-codegen-mips64.h"
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/code-stubs.h" 8 #include "src/code-stubs.h"
9 #include "src/crankshaft/hydrogen-osr.h" 9 #include "src/crankshaft/hydrogen-osr.h"
10 #include "src/crankshaft/mips64/lithium-gap-resolver-mips64.h" 10 #include "src/crankshaft/mips64/lithium-gap-resolver-mips64.h"
(...skipping 3296 matching lines...) Expand 10 before | Expand all | Expand 10 after
3307 __ dsll(scratch, length, kPointerSizeLog2); 3307 __ dsll(scratch, length, kPointerSizeLog2);
3308 __ bind(&loop); 3308 __ bind(&loop);
3309 __ Daddu(scratch, elements, scratch); 3309 __ Daddu(scratch, elements, scratch);
3310 __ ld(scratch, MemOperand(scratch)); 3310 __ ld(scratch, MemOperand(scratch));
3311 __ push(scratch); 3311 __ push(scratch);
3312 __ Dsubu(length, length, Operand(1)); 3312 __ Dsubu(length, length, Operand(1));
3313 __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg)); 3313 __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg));
3314 __ dsll(scratch, length, kPointerSizeLog2); 3314 __ dsll(scratch, length, kPointerSizeLog2);
3315 3315
3316 __ bind(&invoke); 3316 __ bind(&invoke);
3317
3318 InvokeFlag flag = CALL_FUNCTION;
3319 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
3320 // TODO(ishell): drop current frame before pushing arguments to the stack.
3321 flag = JUMP_FUNCTION;
3322 ParameterCount actual(a0);
3323 // It is safe to use t0, t1 and t2 as scratch registers here given that
3324 // we are not going to return to caller function anyway.
3325 PrepareForTailCall(actual, t0, t1, t2);
3326 }
3327
3317 DCHECK(instr->HasPointerMap()); 3328 DCHECK(instr->HasPointerMap());
3318 LPointerMap* pointers = instr->pointer_map(); 3329 LPointerMap* pointers = instr->pointer_map();
3319 SafepointGenerator safepoint_generator( 3330 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
3320 this, pointers, Safepoint::kLazyDeopt);
3321 // The number of arguments is stored in receiver which is a0, as expected 3331 // The number of arguments is stored in receiver which is a0, as expected
3322 // by InvokeFunction. 3332 // by InvokeFunction.
3323 ParameterCount actual(receiver); 3333 ParameterCount actual(receiver);
3324 __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION, 3334 __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
3325 safepoint_generator);
3326 } 3335 }
3327 3336
3328 3337
3329 void LCodeGen::DoPushArgument(LPushArgument* instr) { 3338 void LCodeGen::DoPushArgument(LPushArgument* instr) {
3330 LOperand* argument = instr->value(); 3339 LOperand* argument = instr->value();
3331 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { 3340 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
3332 Abort(kDoPushArgumentNotImplementedForDoubleType); 3341 Abort(kDoPushArgumentNotImplementedForDoubleType);
3333 } else { 3342 } else {
3334 Register argument_reg = EmitLoadRegister(argument, at); 3343 Register argument_reg = EmitLoadRegister(argument, at);
3335 __ push(argument_reg); 3344 __ push(argument_reg);
(...skipping 25 matching lines...) Expand all
3361 3370
3362 3371
3363 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { 3372 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3364 DCHECK(ToRegister(instr->context()).is(cp)); 3373 DCHECK(ToRegister(instr->context()).is(cp));
3365 __ li(scratch0(), instr->hydrogen()->pairs()); 3374 __ li(scratch0(), instr->hydrogen()->pairs());
3366 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); 3375 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
3367 __ Push(scratch0(), scratch1()); 3376 __ Push(scratch0(), scratch1());
3368 CallRuntime(Runtime::kDeclareGlobals, instr); 3377 CallRuntime(Runtime::kDeclareGlobals, instr);
3369 } 3378 }
3370 3379
3371
3372 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 3380 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3373 int formal_parameter_count, int arity, 3381 int formal_parameter_count, int arity,
3374 LInstruction* instr) { 3382 bool is_tail_call, LInstruction* instr) {
3375 bool dont_adapt_arguments = 3383 bool dont_adapt_arguments =
3376 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; 3384 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3377 bool can_invoke_directly = 3385 bool can_invoke_directly =
3378 dont_adapt_arguments || formal_parameter_count == arity; 3386 dont_adapt_arguments || formal_parameter_count == arity;
3379 3387
3380 Register function_reg = a1; 3388 Register function_reg = a1;
3381 LPointerMap* pointers = instr->pointer_map(); 3389 LPointerMap* pointers = instr->pointer_map();
3382 3390
3383 if (can_invoke_directly) { 3391 if (can_invoke_directly) {
3384 // Change context. 3392 // Change context.
3385 __ ld(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); 3393 __ ld(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
3386 3394
3387 // Always initialize new target and number of actual arguments. 3395 // Always initialize new target and number of actual arguments.
3388 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); 3396 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
3389 __ li(a0, Operand(arity)); 3397 __ li(a0, Operand(arity));
3390 3398
3399 bool is_self_call = function.is_identical_to(info()->closure());
3400
3391 // Invoke function. 3401 // Invoke function.
3392 __ ld(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); 3402 if (is_self_call) {
3393 __ Call(at); 3403 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
3404 if (is_tail_call) {
3405 __ Jump(self, RelocInfo::CODE_TARGET);
3406 } else {
3407 __ Call(self, RelocInfo::CODE_TARGET);
3408 }
3409 } else {
3410 __ ld(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
3411 if (is_tail_call) {
3412 __ Jump(at);
3413 } else {
3414 __ Call(at);
3415 }
3416 }
3394 3417
3395 // Set up deoptimization. 3418 if (!is_tail_call) {
3396 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3419 // Set up deoptimization.
3420 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3421 }
3397 } else { 3422 } else {
3398 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3423 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3399 ParameterCount count(arity); 3424 ParameterCount actual(arity);
3400 ParameterCount expected(formal_parameter_count); 3425 ParameterCount expected(formal_parameter_count);
3401 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); 3426 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
3427 __ InvokeFunction(function_reg, expected, actual, flag, generator);
3402 } 3428 }
3403 } 3429 }
3404 3430
3405 3431
3406 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3432 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3407 DCHECK(instr->context() != NULL); 3433 DCHECK(instr->context() != NULL);
3408 DCHECK(ToRegister(instr->context()).is(cp)); 3434 DCHECK(ToRegister(instr->context()).is(cp));
3409 Register input = ToRegister(instr->value()); 3435 Register input = ToRegister(instr->value());
3410 Register result = ToRegister(instr->result()); 3436 Register result = ToRegister(instr->result());
3411 Register scratch = scratch0(); 3437 Register scratch = scratch0();
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
3744 __ MovFromFloatResult(ToDoubleRegister(instr->result())); 3770 __ MovFromFloatResult(ToDoubleRegister(instr->result()));
3745 } 3771 }
3746 3772
3747 3773
3748 void LCodeGen::DoMathClz32(LMathClz32* instr) { 3774 void LCodeGen::DoMathClz32(LMathClz32* instr) {
3749 Register input = ToRegister(instr->value()); 3775 Register input = ToRegister(instr->value());
3750 Register result = ToRegister(instr->result()); 3776 Register result = ToRegister(instr->result());
3751 __ Clz(result, input); 3777 __ Clz(result, input);
3752 } 3778 }
3753 3779
3780 void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
3781 Register scratch1, Register scratch2,
3782 Register scratch3) {
3783 #if DEBUG
3784 if (actual.is_reg()) {
3785 DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
3786 } else {
3787 DCHECK(!AreAliased(scratch1, scratch2, scratch3));
3788 }
3789 #endif
3790 if (FLAG_code_comments) {
3791 if (actual.is_reg()) {
3792 Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
3793 } else {
3794 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
3795 }
3796 }
3797
3798 // Check if next frame is an arguments adaptor frame.
3799 Register caller_args_count_reg = scratch1;
3800 Label no_arguments_adaptor, formal_parameter_count_loaded;
3801 __ ld(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3802 __ ld(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset));
3803 __ Branch(&no_arguments_adaptor, ne, scratch3,
3804 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3805
3806 // Drop current frame and load arguments count from arguments adaptor frame.
3807 __ mov(fp, scratch2);
3808 __ ld(caller_args_count_reg,
3809 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
3810 __ SmiUntag(caller_args_count_reg);
3811 __ Branch(&formal_parameter_count_loaded);
3812
3813 __ bind(&no_arguments_adaptor);
3814 // Load caller's formal parameter count
3815 __ li(caller_args_count_reg, Operand(info()->literal()->parameter_count()));
3816
3817 __ bind(&formal_parameter_count_loaded);
3818 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3);
3819
3820 Comment(";;; }");
3821 }
3754 3822
3755 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 3823 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
3824 HInvokeFunction* hinstr = instr->hydrogen();
3756 DCHECK(ToRegister(instr->context()).is(cp)); 3825 DCHECK(ToRegister(instr->context()).is(cp));
3757 DCHECK(ToRegister(instr->function()).is(a1)); 3826 DCHECK(ToRegister(instr->function()).is(a1));
3758 DCHECK(instr->HasPointerMap()); 3827 DCHECK(instr->HasPointerMap());
3759 3828
3760 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); 3829 bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
3830
3831 if (is_tail_call) {
3832 ParameterCount actual(instr->arity());
3833 // It is safe to use t0, t1 and t2 as scratch registers here given that
3834 // we are not going to return to caller function anyway.
3835 PrepareForTailCall(actual, t0, t1, t2);
3836 }
3837
3838 Handle<JSFunction> known_function = hinstr->known_function();
3761 if (known_function.is_null()) { 3839 if (known_function.is_null()) {
3762 LPointerMap* pointers = instr->pointer_map(); 3840 LPointerMap* pointers = instr->pointer_map();
3763 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3841 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3764 ParameterCount count(instr->arity()); 3842 ParameterCount actual(instr->arity());
3765 __ InvokeFunction(a1, no_reg, count, CALL_FUNCTION, generator); 3843 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
3844 __ InvokeFunction(a1, no_reg, actual, flag, generator);
3766 } else { 3845 } else {
3767 CallKnownFunction(known_function, 3846 CallKnownFunction(known_function, hinstr->formal_parameter_count(),
3768 instr->hydrogen()->formal_parameter_count(), 3847 instr->arity(), is_tail_call, instr);
3769 instr->arity(), instr);
3770 } 3848 }
3771 } 3849 }
3772 3850
3773 3851
3774 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { 3852 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3775 DCHECK(ToRegister(instr->result()).is(v0)); 3853 DCHECK(ToRegister(instr->result()).is(v0));
3776 3854
3777 if (instr->hydrogen()->IsTailCall()) { 3855 if (instr->hydrogen()->IsTailCall()) {
3778 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); 3856 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL);
3779 3857
(...skipping 1921 matching lines...) Expand 10 before | Expand all | Expand 10 after
5701 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { 5779 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
5702 Register context = ToRegister(instr->context()); 5780 Register context = ToRegister(instr->context());
5703 __ sd(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); 5781 __ sd(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
5704 } 5782 }
5705 5783
5706 5784
5707 #undef __ 5785 #undef __
5708 5786
5709 } // namespace internal 5787 } // namespace internal
5710 } // namespace v8 5788 } // namespace v8
OLDNEW
« no previous file with comments | « src/crankshaft/mips64/lithium-codegen-mips64.h ('k') | src/crankshaft/mips64/lithium-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698