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/mips/lithium-codegen-mips.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/mips/lithium-codegen-mips.h ('k') | src/crankshaft/mips/lithium-mips.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.7 1 // Copyright 2012 the V8 project authors. All rights reserved.7
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3112 matching lines...) Expand 10 before | Expand all | Expand 10 after
3123 __ sll(scratch, length, 2); 3123 __ sll(scratch, length, 2);
3124 __ bind(&loop); 3124 __ bind(&loop);
3125 __ Addu(scratch, elements, scratch); 3125 __ Addu(scratch, elements, scratch);
3126 __ lw(scratch, MemOperand(scratch)); 3126 __ lw(scratch, MemOperand(scratch));
3127 __ push(scratch); 3127 __ push(scratch);
3128 __ Subu(length, length, Operand(1)); 3128 __ Subu(length, length, Operand(1));
3129 __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg)); 3129 __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg));
3130 __ sll(scratch, length, 2); 3130 __ sll(scratch, length, 2);
3131 3131
3132 __ bind(&invoke); 3132 __ bind(&invoke);
3133
3134 InvokeFlag flag = CALL_FUNCTION;
3135 if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
3136 // TODO(ishell): drop current frame before pushing arguments to the stack.
3137 flag = JUMP_FUNCTION;
3138 ParameterCount actual(a0);
3139 // It is safe to use t0, t1 and t2 as scratch registers here given that
3140 // we are not going to return to caller function anyway.
3141 PrepareForTailCall(actual, t0, t1, t2);
3142 }
3143
3133 DCHECK(instr->HasPointerMap()); 3144 DCHECK(instr->HasPointerMap());
3134 LPointerMap* pointers = instr->pointer_map(); 3145 LPointerMap* pointers = instr->pointer_map();
3135 SafepointGenerator safepoint_generator( 3146 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
3136 this, pointers, Safepoint::kLazyDeopt);
3137 // The number of arguments is stored in receiver which is a0, as expected 3147 // The number of arguments is stored in receiver which is a0, as expected
3138 // by InvokeFunction. 3148 // by InvokeFunction.
3139 ParameterCount actual(receiver); 3149 ParameterCount actual(receiver);
3140 __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION, 3150 __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
3141 safepoint_generator);
3142 } 3151 }
3143 3152
3144 3153
3145 void LCodeGen::DoPushArgument(LPushArgument* instr) { 3154 void LCodeGen::DoPushArgument(LPushArgument* instr) {
3146 LOperand* argument = instr->value(); 3155 LOperand* argument = instr->value();
3147 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { 3156 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
3148 Abort(kDoPushArgumentNotImplementedForDoubleType); 3157 Abort(kDoPushArgumentNotImplementedForDoubleType);
3149 } else { 3158 } else {
3150 Register argument_reg = EmitLoadRegister(argument, at); 3159 Register argument_reg = EmitLoadRegister(argument, at);
3151 __ push(argument_reg); 3160 __ push(argument_reg);
(...skipping 25 matching lines...) Expand all
3177 3186
3178 3187
3179 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { 3188 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3180 DCHECK(ToRegister(instr->context()).is(cp)); 3189 DCHECK(ToRegister(instr->context()).is(cp));
3181 __ li(scratch0(), instr->hydrogen()->pairs()); 3190 __ li(scratch0(), instr->hydrogen()->pairs());
3182 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); 3191 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
3183 __ Push(scratch0(), scratch1()); 3192 __ Push(scratch0(), scratch1());
3184 CallRuntime(Runtime::kDeclareGlobals, instr); 3193 CallRuntime(Runtime::kDeclareGlobals, instr);
3185 } 3194 }
3186 3195
3187
3188 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 3196 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3189 int formal_parameter_count, int arity, 3197 int formal_parameter_count, int arity,
3190 LInstruction* instr) { 3198 bool is_tail_call, LInstruction* instr) {
3191 bool dont_adapt_arguments = 3199 bool dont_adapt_arguments =
3192 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; 3200 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3193 bool can_invoke_directly = 3201 bool can_invoke_directly =
3194 dont_adapt_arguments || formal_parameter_count == arity; 3202 dont_adapt_arguments || formal_parameter_count == arity;
3195 3203
3196 Register function_reg = a1; 3204 Register function_reg = a1;
3197 LPointerMap* pointers = instr->pointer_map(); 3205 LPointerMap* pointers = instr->pointer_map();
3198 3206
3199 if (can_invoke_directly) { 3207 if (can_invoke_directly) {
3200 // Change context. 3208 // Change context.
3201 __ lw(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); 3209 __ lw(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
3202 3210
3203 // Always initialize new target and number of actual arguments. 3211 // Always initialize new target and number of actual arguments.
3204 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); 3212 __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
3205 __ li(a0, Operand(arity)); 3213 __ li(a0, Operand(arity));
3206 3214
3215 bool is_self_call = function.is_identical_to(info()->closure());
3216
3207 // Invoke function. 3217 // Invoke function.
3208 __ lw(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); 3218 if (is_self_call) {
3209 __ Call(at); 3219 Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
3220 if (is_tail_call) {
3221 __ Jump(self, RelocInfo::CODE_TARGET);
3222 } else {
3223 __ Call(self, RelocInfo::CODE_TARGET);
3224 }
3225 } else {
3226 __ lw(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
3227 if (is_tail_call) {
3228 __ Jump(at);
3229 } else {
3230 __ Call(at);
3231 }
3232 }
3210 3233
3211 // Set up deoptimization. 3234 if (!is_tail_call) {
3212 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3235 // Set up deoptimization.
3236 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3237 }
3213 } else { 3238 } else {
3214 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3239 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3215 ParameterCount count(arity); 3240 ParameterCount actual(arity);
3216 ParameterCount expected(formal_parameter_count); 3241 ParameterCount expected(formal_parameter_count);
3217 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); 3242 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
3243 __ InvokeFunction(function_reg, expected, actual, flag, generator);
3218 } 3244 }
3219 } 3245 }
3220 3246
3221 3247
3222 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3248 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3223 DCHECK(instr->context() != NULL); 3249 DCHECK(instr->context() != NULL);
3224 DCHECK(ToRegister(instr->context()).is(cp)); 3250 DCHECK(ToRegister(instr->context()).is(cp));
3225 Register input = ToRegister(instr->value()); 3251 Register input = ToRegister(instr->value());
3226 Register result = ToRegister(instr->result()); 3252 Register result = ToRegister(instr->result());
3227 Register scratch = scratch0(); 3253 Register scratch = scratch0();
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
3541 __ MovFromFloatResult(ToDoubleRegister(instr->result())); 3567 __ MovFromFloatResult(ToDoubleRegister(instr->result()));
3542 } 3568 }
3543 3569
3544 3570
3545 void LCodeGen::DoMathClz32(LMathClz32* instr) { 3571 void LCodeGen::DoMathClz32(LMathClz32* instr) {
3546 Register input = ToRegister(instr->value()); 3572 Register input = ToRegister(instr->value());
3547 Register result = ToRegister(instr->result()); 3573 Register result = ToRegister(instr->result());
3548 __ Clz(result, input); 3574 __ Clz(result, input);
3549 } 3575 }
3550 3576
3577 void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
3578 Register scratch1, Register scratch2,
3579 Register scratch3) {
3580 #if DEBUG
3581 if (actual.is_reg()) {
3582 DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
3583 } else {
3584 DCHECK(!AreAliased(scratch1, scratch2, scratch3));
3585 }
3586 #endif
3587 if (FLAG_code_comments) {
3588 if (actual.is_reg()) {
3589 Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
3590 } else {
3591 Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
3592 }
3593 }
3594
3595 // Check if next frame is an arguments adaptor frame.
3596 Register caller_args_count_reg = scratch1;
3597 Label no_arguments_adaptor, formal_parameter_count_loaded;
3598 __ lw(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3599 __ lw(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset));
3600 __ Branch(&no_arguments_adaptor, ne, scratch3,
3601 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3602
3603 // Drop current frame and load arguments count from arguments adaptor frame.
3604 __ mov(fp, scratch2);
3605 __ lw(caller_args_count_reg,
3606 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
3607 __ SmiUntag(caller_args_count_reg);
3608 __ Branch(&formal_parameter_count_loaded);
3609
3610 __ bind(&no_arguments_adaptor);
3611 // Load caller's formal parameter count
3612 __ lw(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3613 __ lw(scratch1,
3614 FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
3615 __ li(caller_args_count_reg, Operand(info()->literal()->parameter_count()));
3616
3617 __ bind(&formal_parameter_count_loaded);
3618 __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3);
3619
3620 Comment(";;; }");
3621 }
3551 3622
3552 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 3623 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
3624 HInvokeFunction* hinstr = instr->hydrogen();
3553 DCHECK(ToRegister(instr->context()).is(cp)); 3625 DCHECK(ToRegister(instr->context()).is(cp));
3554 DCHECK(ToRegister(instr->function()).is(a1)); 3626 DCHECK(ToRegister(instr->function()).is(a1));
3555 DCHECK(instr->HasPointerMap()); 3627 DCHECK(instr->HasPointerMap());
3556 3628
3557 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); 3629 bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
3630
3631 if (is_tail_call) {
3632 ParameterCount actual(instr->arity());
3633 // It is safe to use t0, t1 and t2 as scratch registers here given that
3634 // we are not going to return to caller function anyway.
3635 PrepareForTailCall(actual, t0, t1, t2);
3636 }
3637
3638 Handle<JSFunction> known_function = hinstr->known_function();
3558 if (known_function.is_null()) { 3639 if (known_function.is_null()) {
3559 LPointerMap* pointers = instr->pointer_map(); 3640 LPointerMap* pointers = instr->pointer_map();
3560 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3641 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3561 ParameterCount count(instr->arity()); 3642 ParameterCount actual(instr->arity());
3562 __ InvokeFunction(a1, no_reg, count, CALL_FUNCTION, generator); 3643 InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
3644 __ InvokeFunction(a1, no_reg, actual, flag, generator);
3563 } else { 3645 } else {
3564 CallKnownFunction(known_function, 3646 CallKnownFunction(known_function, hinstr->formal_parameter_count(),
3565 instr->hydrogen()->formal_parameter_count(), 3647 instr->arity(), is_tail_call, instr);
3566 instr->arity(), instr);
3567 } 3648 }
3568 } 3649 }
3569 3650
3570 3651
3571 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { 3652 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3572 DCHECK(ToRegister(instr->result()).is(v0)); 3653 DCHECK(ToRegister(instr->result()).is(v0));
3573 3654
3574 if (instr->hydrogen()->IsTailCall()) { 3655 if (instr->hydrogen()->IsTailCall()) {
3575 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); 3656 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL);
3576 3657
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after
5497 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { 5578 void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
5498 Register context = ToRegister(instr->context()); 5579 Register context = ToRegister(instr->context());
5499 __ sw(context, MemOperand(fp, StandardFrameConstants::kContextOffset)); 5580 __ sw(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
5500 } 5581 }
5501 5582
5502 5583
5503 #undef __ 5584 #undef __
5504 5585
5505 } // namespace internal 5586 } // namespace internal
5506 } // namespace v8 5587 } // namespace v8
OLDNEW
« no previous file with comments | « src/crankshaft/mips/lithium-codegen-mips.h ('k') | src/crankshaft/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698