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

Unified Diff: src/crankshaft/hydrogen.cc

Issue 1761023003: [crankshaft] Correctly propagate TailCallMode in case of inlining. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/crankshaft/hydrogen.cc
diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc
index a238c127a6848abb5f52258a40cd4443a0bc5078..e8e41d49fdd44d9e9a20906c73a6f84477277f64 100644
--- a/src/crankshaft/hydrogen.cc
+++ b/src/crankshaft/hydrogen.cc
@@ -3492,11 +3492,11 @@ HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
return Add<HLoadNamedField>(native_context, nullptr, function_access);
}
-
HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
: HGraphBuilder(info, CallInterfaceDescriptor()),
function_state_(NULL),
- initial_function_state_(this, info, NORMAL_RETURN, 0),
+ initial_function_state_(this, info, NORMAL_RETURN, 0,
+ TailCallMode::kAllow),
ast_context_(NULL),
break_scope_(NULL),
inlined_count_(0),
@@ -4032,11 +4032,12 @@ void HGraph::CollectPhis() {
// a (possibly inlined) function.
FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
CompilationInfo* info, InliningKind inlining_kind,
- int inlining_id)
+ int inlining_id, TailCallMode tail_call_mode)
: owner_(owner),
compilation_info_(info),
call_context_(NULL),
inlining_kind_(inlining_kind),
+ tail_call_mode_(tail_call_mode),
function_return_(NULL),
test_context_(NULL),
entry_(NULL),
@@ -6573,7 +6574,8 @@ HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
HValue* function = Add<HConstant>(info->accessor());
PushArgumentsFromEnvironment(argument_count);
return NewCallFunction(function, argument_count,
- ConvertReceiverMode::kNotNullOrUndefined);
+ ConvertReceiverMode::kNotNullOrUndefined,
+ TailCallMode::kDisallow);
} else if (FLAG_inline_accessors && can_inline_accessor) {
bool success = info->IsLoad()
? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
@@ -6588,7 +6590,7 @@ HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
return nullptr;
}
return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()),
- argument_count);
+ argument_count, TailCallMode::kDisallow);
}
DCHECK(info->IsDataConstant());
@@ -7987,11 +7989,13 @@ void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
}
HInstruction* HOptimizedGraphBuilder::NewCallFunction(
- HValue* function, int argument_count, ConvertReceiverMode convert_mode) {
+ HValue* function, int argument_count, ConvertReceiverMode convert_mode,
+ TailCallMode tail_call_mode) {
HValue* arity = Add<HConstant>(argument_count - 1);
HValue* op_vals[] = {context(), function, arity};
+ // TODO(ishell): use tail_call_mode here.
Callable callable = CodeFactory::Call(isolate(), convert_mode);
HConstant* stub = Add<HConstant>(callable.code());
@@ -8001,7 +8005,7 @@ HInstruction* HOptimizedGraphBuilder::NewCallFunction(
HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC(
HValue* function, int argument_count, ConvertReceiverMode convert_mode,
- FeedbackVectorSlot slot) {
+ TailCallMode tail_call_mode, FeedbackVectorSlot slot) {
int arity = argument_count - 1;
Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
HValue* index_val = Add<HConstant>(vector->GetIndex(slot));
@@ -8009,6 +8013,7 @@ HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC(
HValue* op_vals[] = {context(), function, index_val, vector_val};
+ // TODO(ishell): use tail_call_mode here.
Callable callable = CodeFactory::CallICInOptimizedCode(
isolate(), arity, ConvertReceiverMode::kNullOrUndefined);
HConstant* stub = Add<HConstant>(callable.code());
@@ -8018,7 +8023,9 @@ HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC(
}
HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction(
- Handle<JSFunction> function, int argument_count) {
+ Handle<JSFunction> function, int argument_count,
+ TailCallMode tail_call_mode) {
+ // TODO(ishell): use tail_call_mode here.
HValue* target = Add<HConstant>(function);
return New<HInvokeFunction>(target, function, argument_count);
}
@@ -8058,6 +8065,10 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
bool handled_string = false;
int ordered_functions = 0;
+ TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
+ TailCallMode tail_call_mode =
+ function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
+
int i;
for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
++i) {
@@ -8168,8 +8179,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
HInstruction* call =
needs_wrapping
? NewCallFunction(function, argument_count,
- ConvertReceiverMode::kNotNullOrUndefined)
- : NewCallConstantFunction(target, argument_count);
+ ConvertReceiverMode::kNotNullOrUndefined,
+ tail_call_mode)
+ : NewCallConstantFunction(target, argument_count, tail_call_mode);
PushArgumentsFromEnvironment(argument_count);
AddInstruction(call);
Drop(1); // Drop the function.
@@ -8199,7 +8211,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
CHECK_ALIVE(VisitExpressions(expr->arguments()));
HInstruction* call = NewCallFunction(
- function, argument_count, ConvertReceiverMode::kNotNullOrUndefined);
+ function, argument_count, ConvertReceiverMode::kNotNullOrUndefined,
+ tail_call_mode);
PushArgumentsFromEnvironment(argument_count);
@@ -8227,17 +8240,19 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
}
}
-
void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
Handle<JSFunction> caller,
- const char* reason) {
+ const char* reason,
+ TailCallMode tail_call_mode) {
if (FLAG_trace_inlining) {
base::SmartArrayPointer<char> target_name =
target->shared()->DebugName()->ToCString();
base::SmartArrayPointer<char> caller_name =
caller->shared()->DebugName()->ToCString();
if (reason == NULL) {
- PrintF("Inlined %s called from %s.\n", target_name.get(),
+ const char* call_mode =
+ tail_call_mode == TailCallMode::kAllow ? "tail called" : "called";
+ PrintF("Inlined %s %s from %s.\n", target_name.get(), call_mode,
caller_name.get());
} else {
PrintF("Did not inline %s called from %s (%s).\n",
@@ -8294,12 +8309,12 @@ int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
return nodes_added;
}
-
bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
int arguments_count,
HValue* implicit_return_value,
BailoutId ast_id, BailoutId return_id,
- InliningKind inlining_kind) {
+ InliningKind inlining_kind,
+ TailCallMode syntactic_tail_call_mode) {
if (target->context()->native_context() !=
top_info()->closure()->context()->native_context()) {
return false;
@@ -8308,6 +8323,10 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
if (nodes_added == kNotInlinable) return false;
Handle<JSFunction> caller = current_info()->closure();
+ if (syntactic_tail_call_mode == TailCallMode::kAllow) {
+ TraceInline(target, caller, "call is at tail position");
+ return false;
+ }
if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
TraceInline(target, caller, "target AST is too large [early]");
@@ -8469,8 +8488,9 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
// Save the pending call context. Set up new one for the inlined function.
// The function state is new-allocated because we need to delete it
// in two different places.
- FunctionState* target_state =
- new FunctionState(this, &target_info, inlining_kind, inlining_id);
+ FunctionState* target_state = new FunctionState(
+ this, &target_info, inlining_kind, inlining_id,
+ function_state()->ComputeTailCallMode(syntactic_tail_call_mode));
HConstant* undefined = graph()->GetConstantUndefined();
@@ -8540,7 +8560,7 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
graph()->update_type_change_checksum(type_info->own_type_change_checksum());
- TraceInline(target, caller, NULL);
+ TraceInline(target, caller, NULL, syntactic_tail_call_mode);
if (current_block() != NULL) {
FunctionState* state = function_state();
@@ -8624,7 +8644,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
return TryInline(expr->target(), expr->arguments()->length(), NULL,
- expr->id(), expr->ReturnId(), NORMAL_RETURN);
+ expr->id(), expr->ReturnId(), NORMAL_RETURN,
+ expr->tail_call_mode());
}
@@ -8632,7 +8653,7 @@ bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
HValue* implicit_return_value) {
return TryInline(expr->target(), expr->arguments()->length(),
implicit_return_value, expr->id(), expr->ReturnId(),
- CONSTRUCT_CALL_RETURN);
+ CONSTRUCT_CALL_RETURN, TailCallMode::kDisallow);
}
bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
@@ -8642,7 +8663,7 @@ bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
return getter->IsJSFunction() &&
TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id,
- GETTER_CALL_RETURN);
+ GETTER_CALL_RETURN, TailCallMode::kDisallow);
}
bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
@@ -8653,7 +8674,8 @@ bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
if (TryInlineApiSetter(setter, receiver_map, id)) return true;
return setter->IsJSFunction() &&
TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value,
- id, assignment_id, SETTER_CALL_RETURN);
+ id, assignment_id, SETTER_CALL_RETURN,
+ TailCallMode::kDisallow);
}
@@ -8661,13 +8683,15 @@ bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
Call* expr,
int arguments_count) {
return TryInline(function, arguments_count, NULL, expr->id(),
- expr->ReturnId(), NORMAL_RETURN);
+ expr->ReturnId(), NORMAL_RETURN, expr->tail_call_mode());
}
bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
+ // We intentionally ignore expr->tail_call_mode() here because builtins
+ // we inline here do not observe if they were tail called or not.
switch (id) {
case kMathExp:
if (!FLAG_fast_math) break;
@@ -9083,7 +9107,8 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
if_inline.Else();
{
Add<HPushArguments>(receiver);
- result = AddInstruction(NewCallConstantFunction(function, 1));
+ result = AddInstruction(
+ NewCallConstantFunction(function, 1, TailCallMode::kDisallow));
if (!ast_context()->IsEffect()) Push(result);
}
if_inline.End();
@@ -9147,12 +9172,8 @@ bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
Handle<JSFunction> function = expr->target();
int argc = expr->arguments()->length();
SmallMapList receiver_maps;
- return TryInlineApiCall(function,
- receiver,
- &receiver_maps,
- argc,
- expr->id(),
- kCallApiFunction);
+ return TryInlineApiCall(function, receiver, &receiver_maps, argc, expr->id(),
+ kCallApiFunction, expr->tail_call_mode());
}
@@ -9162,12 +9183,8 @@ bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
SmallMapList* receiver_maps) {
Handle<JSFunction> function = expr->target();
int argc = expr->arguments()->length();
- return TryInlineApiCall(function,
- receiver,
- receiver_maps,
- argc,
- expr->id(),
- kCallApiMethod);
+ return TryInlineApiCall(function, receiver, receiver_maps, argc, expr->id(),
+ kCallApiMethod, expr->tail_call_mode());
}
bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
@@ -9177,10 +9194,8 @@ bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
receiver_maps.Add(receiver_map, zone());
return TryInlineApiCall(function,
NULL, // Receiver is on expression stack.
- &receiver_maps,
- 0,
- ast_id,
- kCallApiGetter);
+ &receiver_maps, 0, ast_id, kCallApiGetter,
+ TailCallMode::kDisallow);
}
bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
@@ -9190,22 +9205,22 @@ bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
receiver_maps.Add(receiver_map, zone());
return TryInlineApiCall(function,
NULL, // Receiver is on expression stack.
- &receiver_maps,
- 1,
- ast_id,
- kCallApiSetter);
+ &receiver_maps, 1, ast_id, kCallApiSetter,
+ TailCallMode::kDisallow);
}
-bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<Object> function,
- HValue* receiver,
- SmallMapList* receiver_maps,
- int argc, BailoutId ast_id,
- ApiCallType call_type) {
+bool HOptimizedGraphBuilder::TryInlineApiCall(
+ Handle<Object> function, HValue* receiver, SmallMapList* receiver_maps,
+ int argc, BailoutId ast_id, ApiCallType call_type,
+ TailCallMode syntactic_tail_call_mode) {
if (function->IsJSFunction() &&
Handle<JSFunction>::cast(function)->context()->native_context() !=
top_info()->closure()->context()->native_context()) {
return false;
}
+ if (syntactic_tail_call_mode == TailCallMode::kAllow) {
+ return false;
+ }
CallOptimization optimization(function);
if (!optimization.is_simple_api_call()) return false;
Handle<Map> holder_map;
@@ -9359,6 +9374,12 @@ void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
}
}
+ TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
+ TailCallMode tail_call_mode =
+ function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
+ USE(tail_call_mode);
+
+ // TODO(ishell): use tail_call_mode here.
PushArgumentsFromEnvironment(arguments_count);
HInvokeFunction* call =
New<HInvokeFunction>(function, known_function, arguments_count);
@@ -9413,6 +9434,12 @@ void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
HValue* checked_function = AddCheckMap(function, function_map);
if (function_state()->outer() == NULL) {
+ TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
+ TailCallMode tail_call_mode =
+ function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
+ USE(tail_call_mode);
+
+ // TODO(ishell): use tail_call_mode here.
HInstruction* elements = Add<HArgumentsElements>(false);
HInstruction* length = Add<HArgumentsLength>(elements);
HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
@@ -9698,6 +9725,10 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
int argument_count = expr->arguments()->length() + 1; // Plus receiver.
HInstruction* call = NULL;
+ TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
+ TailCallMode tail_call_mode =
+ function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
+
Property* prop = callee->AsProperty();
if (prop != NULL) {
CHECK_ALIVE(VisitForValue(prop->obj()));
@@ -9756,11 +9787,13 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
// TODO(verwaest): Support creation of value wrappers directly in
// HWrapReceiver.
call = NewCallFunction(function, argument_count,
- ConvertReceiverMode::kNotNullOrUndefined);
+ ConvertReceiverMode::kNotNullOrUndefined,
+ tail_call_mode);
} else if (TryInlineCall(expr)) {
return;
} else {
- call = NewCallConstantFunction(known_function, argument_count);
+ call = NewCallConstantFunction(known_function, argument_count,
+ tail_call_mode);
}
} else {
@@ -9780,7 +9813,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
call = NewCallFunction(function, argument_count,
- ConvertReceiverMode::kNotNullOrUndefined);
+ ConvertReceiverMode::kNotNullOrUndefined,
+ tail_call_mode);
}
PushArgumentsFromEnvironment(argument_count);
@@ -9827,7 +9861,8 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
if (TryInlineCall(expr)) return;
PushArgumentsFromEnvironment(argument_count);
- call = NewCallConstantFunction(expr->target(), argument_count);
+ call = NewCallConstantFunction(expr->target(), argument_count,
+ tail_call_mode);
} else {
PushArgumentsFromEnvironment(argument_count);
if (expr->is_uninitialized() &&
@@ -9836,10 +9871,11 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
// through the type vector.
call = NewCallFunctionViaIC(function, argument_count,
ConvertReceiverMode::kNullOrUndefined,
- expr->CallFeedbackICSlot());
+ tail_call_mode, expr->CallFeedbackICSlot());
} else {
call = NewCallFunction(function, argument_count,
- ConvertReceiverMode::kNullOrUndefined);
+ ConvertReceiverMode::kNullOrUndefined,
+ tail_call_mode);
}
}
}
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698