Index: src/crankshaft/hydrogen.cc |
diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc |
index 0b1dacec1a8caf6cb46325554f8a98d78e78ed22..306b6a72883f3d0111b1e9a8f6e34490a9936129 100644 |
--- a/src/crankshaft/hydrogen.cc |
+++ b/src/crankshaft/hydrogen.cc |
@@ -4111,7 +4111,7 @@ AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) |
typeof_mode_(NOT_INSIDE_TYPEOF) { |
owner->set_ast_context(this); // Push. |
#ifdef DEBUG |
- DCHECK(owner->environment()->frame_type() == JS_FUNCTION); |
+ DCHECK_EQ(JS_FUNCTION, owner->environment()->frame_type()); |
original_length_ = owner->environment()->length(); |
#endif |
} |
@@ -4123,18 +4123,18 @@ AstContext::~AstContext() { |
EffectContext::~EffectContext() { |
- DCHECK(owner()->HasStackOverflow() || |
- owner()->current_block() == NULL || |
+ DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL || |
(owner()->environment()->length() == original_length_ && |
- owner()->environment()->frame_type() == JS_FUNCTION)); |
+ (owner()->environment()->frame_type() == JS_FUNCTION || |
+ owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION))); |
} |
ValueContext::~ValueContext() { |
- DCHECK(owner()->HasStackOverflow() || |
- owner()->current_block() == NULL || |
+ DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL || |
(owner()->environment()->length() == original_length_ + 1 && |
- owner()->environment()->frame_type() == JS_FUNCTION)); |
+ (owner()->environment()->frame_type() == JS_FUNCTION || |
+ owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION))); |
} |
@@ -8339,11 +8339,6 @@ 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]"); |
return false; |
@@ -8510,12 +8505,9 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, |
HConstant* undefined = graph()->GetConstantUndefined(); |
- HEnvironment* inner_env = |
- environment()->CopyForInlining(target, |
- arguments_count, |
- function, |
- undefined, |
- function_state()->inlining_kind()); |
+ HEnvironment* inner_env = environment()->CopyForInlining( |
+ target, arguments_count, function, undefined, |
+ function_state()->inlining_kind(), syntactic_tail_call_mode); |
HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
inner_env->BindContext(context); |
@@ -8545,10 +8537,10 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, |
current_block()->UpdateEnvironment(inner_env); |
Scope* saved_scope = scope(); |
set_scope(target_info.scope()); |
- HEnterInlined* enter_inlined = |
- Add<HEnterInlined>(return_id, target, context, arguments_count, function, |
- function_state()->inlining_kind(), |
- function->scope()->arguments(), arguments_object); |
+ HEnterInlined* enter_inlined = Add<HEnterInlined>( |
+ return_id, target, context, arguments_count, function, |
+ function_state()->inlining_kind(), function->scope()->arguments(), |
+ arguments_object, syntactic_tail_call_mode); |
if (top_info()->is_tracking_positions()) { |
enter_inlined->set_inlining_id(inlining_id); |
} |
@@ -9234,9 +9226,6 @@ bool HOptimizedGraphBuilder::TryInlineApiCall( |
top_info()->closure()->context()->native_context()) { |
return false; |
} |
- if (syntactic_tail_call_mode == TailCallMode::kAllow) { |
- return false; |
- } |
if (argc > CallApiCallbackStub::kArgMax) { |
return false; |
} |
@@ -9344,14 +9333,16 @@ bool HOptimizedGraphBuilder::TryInlineApiCall( |
HConstant* code_value = Add<HConstant>(code); |
call = New<HCallWithDescriptor>( |
code_value, argc + 1, stub.GetCallInterfaceDescriptor(), |
- Vector<HValue*>(op_vals, arraysize(op_vals) - 1)); |
+ Vector<HValue*>(op_vals, arraysize(op_vals) - 1), |
+ syntactic_tail_call_mode); |
} else { |
CallApiCallbackStub stub(isolate(), argc, call_data_undefined); |
Handle<Code> code = stub.GetCode(); |
HConstant* code_value = Add<HConstant>(code); |
call = New<HCallWithDescriptor>( |
code_value, argc + 1, stub.GetCallInterfaceDescriptor(), |
- Vector<HValue*>(op_vals, arraysize(op_vals) - 1)); |
+ Vector<HValue*>(op_vals, arraysize(op_vals) - 1), |
+ syntactic_tail_call_mode); |
Drop(1); // Drop function. |
} |
@@ -13122,14 +13113,16 @@ HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer, |
return new_env; |
} |
+void HEnvironment::MarkAsTailCaller() { |
+ DCHECK_EQ(JS_FUNCTION, frame_type()); |
+ frame_type_ = TAIL_CALLER_FUNCTION; |
+} |
HEnvironment* HEnvironment::CopyForInlining( |
- Handle<JSFunction> target, |
- int arguments, |
- FunctionLiteral* function, |
- HConstant* undefined, |
- InliningKind inlining_kind) const { |
- DCHECK(frame_type() == JS_FUNCTION); |
+ Handle<JSFunction> target, int arguments, FunctionLiteral* function, |
+ HConstant* undefined, InliningKind inlining_kind, |
+ TailCallMode syntactic_tail_call_mode) const { |
+ DCHECK_EQ(JS_FUNCTION, frame_type()); |
// Outer environment is a copy of this one without the arguments. |
int arity = function->scope()->num_parameters(); |
@@ -13138,6 +13131,11 @@ HEnvironment* HEnvironment::CopyForInlining( |
outer->Drop(arguments + 1); // Including receiver. |
outer->ClearHistory(); |
+ if (syntactic_tail_call_mode == TailCallMode::kAllow) { |
+ DCHECK_EQ(NORMAL_RETURN, inlining_kind); |
+ outer->MarkAsTailCaller(); |
+ } |
+ |
if (inlining_kind == CONSTRUCT_CALL_RETURN) { |
// Create artificial constructor stub environment. The receiver should |
// actually be the constructor function, but we pass the newly allocated |