Index: src/compiler/js-inlining.cc |
diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc |
index 7c12dd5bc1ef3dcb028dd108353afa1eedff9a8d..4fcad20384d69a6a6d6114f371eceda9ed4e4af7 100644 |
--- a/src/compiler/js-inlining.cc |
+++ b/src/compiler/js-inlining.cc |
@@ -15,6 +15,7 @@ |
#include "src/compiler/node-properties-inl.h" |
#include "src/compiler/simplified-operator.h" |
#include "src/compiler/typer.h" |
+#include "src/full-codegen.h" |
#include "src/parser.h" |
#include "src/rewriter.h" |
#include "src/scopes.h" |
@@ -56,7 +57,6 @@ static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) { |
CHECK(Parser::Parse(info)); |
StrictMode strict_mode = info->function()->strict_mode(); |
info->SetStrictMode(strict_mode); |
- info->SetOptimizing(BailoutId::None(), Handle<Code>(function->code())); |
CHECK(Rewriter::Rewrite(info)); |
CHECK(Scope::Analyze(info)); |
CHECK_NE(NULL, info->scope()); |
@@ -92,6 +92,16 @@ class Inlinee { |
DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode()); |
return unique_return; |
} |
+ |
+ // Counts JSFunction, Receiver, arguments, context but not effect, control. |
+ size_t total_parameters() { return start_->op()->OutputCount(); } |
+ |
+ // Counts only formal parameters. |
+ size_t formal_parameters() { |
+ DCHECK_GE(total_parameters(), 3); |
+ return total_parameters() - 3; |
+ } |
+ |
// Inline this graph at {call}, use {jsgraph} and its zone to create |
// any new nodes. |
void InlineAtCall(JSGraph* jsgraph, Node* call); |
@@ -198,7 +208,7 @@ class CopyVisitor : public NullNodeVisitor { |
private: |
void ReplaceSentinels() { |
- for (int id = 0; id < source_graph_->NodeCount(); ++id) { |
+ for (NodeId id = 0; id < source_graph_->NodeCount(); ++id) { |
Node* sentinel = sentinels_[id]; |
if (sentinel == NULL) continue; |
Node* copy = copies_[id]; |
@@ -237,11 +247,8 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { |
NodeProperties::GetValueInput(call, 0), |
NodeProperties::GetEffectInput(call)); |
- // {inlinee_inputs} counts JSFunction, Receiver, arguments, context, |
- // but not effect, control. |
- int inlinee_inputs = start_->op()->OutputCount(); |
// Context is last argument. |
- int inlinee_context_index = inlinee_inputs - 1; |
+ int inlinee_context_index = total_parameters() - 1; |
// {inliner_inputs} counts JSFunction, Receiver, arguments, but not |
// context, effect, control. |
int inliner_inputs = OperatorProperties::GetValueInputCount(call->op()); |
@@ -301,10 +308,73 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { |
} |
-void JSInliner::TryInlineCall(Node* call) { |
- DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); |
+class JSCallFunctionAccessor { |
+ public: |
+ explicit JSCallFunctionAccessor(Node* call) : call_(call) { |
+ DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); |
+ } |
+ |
+ Node* jsfunction() { return call_->InputAt(0); } |
+ |
+ Node* receiver() { return call_->InputAt(1); } |
+ |
+ Node* formal_argument(size_t index) { |
+ DCHECK(index < formal_arguments()); |
+ return call_->InputAt(2 + index); |
+ } |
+ |
+ size_t formal_arguments() { |
+ // {value_inputs} includes jsfunction and receiver. |
+ size_t value_inputs = OperatorProperties::GetValueInputCount(call_->op()); |
+ DCHECK_GE(call_->InputCount(), 2); |
+ return value_inputs - 2; |
+ } |
+ |
+ Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); } |
+ |
+ private: |
+ Node* call_; |
+}; |
+ |
+ |
+static void AddClosureToFrameState(JSGraph* jsgraph, Node* frame_state, |
+ Handle<JSFunction> jsfunction) { |
+ FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state); |
+ const Operator* op = jsgraph->common()->FrameState( |
+ FrameStateType::JS_FRAME, call_info.bailout_id(), |
+ call_info.state_combine(), |
+ Unique<JSFunction>::CreateImmovable(jsfunction)); |
+ frame_state->set_op(op); |
+} |
+ |
+ |
+static Node* CreateArgumentsAdaptorFrameState(JSGraph* jsgraph, |
+ JSCallFunctionAccessor* call, |
+ Handle<JSFunction> jsfunction, |
+ Zone* temp_zone) { |
+ const Operator* op = jsgraph->common()->FrameState( |
+ FrameStateType::ARGUMENTS_ADAPTOR, BailoutId(-1), kIgnoreOutput, |
+ Unique<JSFunction>::CreateImmovable(jsfunction)); |
+ const Operator* op0 = jsgraph->common()->StateValues(0); |
+ Node* node0 = jsgraph->graph()->NewNode(op0); |
+ NodeVector params(temp_zone); |
+ params.push_back(call->receiver()); |
+ for (size_t argument = 0; argument != call->formal_arguments(); ++argument) { |
+ params.push_back(call->formal_argument(argument)); |
+ } |
+ const Operator* op_param = jsgraph->common()->StateValues(params.size()); |
+ Node* params_node = |
+ jsgraph->graph()->NewNode(op_param, params.size(), ¶ms.front()); |
+ return jsgraph->graph()->NewNode(op, params_node, node0, node0, |
+ jsgraph->UndefinedConstant(), |
+ call->frame_state()); |
+} |
+ |
- HeapObjectMatcher<JSFunction> match(call->InputAt(0)); |
+void JSInliner::TryInlineCall(Node* call_node) { |
+ JSCallFunctionAccessor call(call_node); |
+ |
+ HeapObjectMatcher<JSFunction> match(call.jsfunction()); |
if (!match.HasValue()) { |
return; |
} |
@@ -324,6 +394,16 @@ void JSInliner::TryInlineCall(Node* call) { |
CompilationInfoWithZone info(function); |
Parse(function, &info); |
+ if (!function->shared()->has_deoptimization_support()) { |
+ info.EnableDeoptimizationSupport(); |
+ if (!FullCodeGenerator::MakeCode(&info)) { |
+ DCHECK(false); |
+ return; |
+ } |
+ function->shared()->EnableDeoptimizationSupport(*info.code()); |
+ function->shared()->set_feedback_vector(*info.feedback_vector()); |
+ } |
+ |
if (info.scope()->arguments() != NULL) { |
// For now do not inline functions that use their arguments array. |
SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); |
@@ -355,7 +435,22 @@ void JSInliner::TryInlineCall(Node* call) { |
visitor.CopyGraph(); |
Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end())); |
- inlinee.InlineAtCall(jsgraph_, call); |
+ |
+ for (Node* node : visitor.copies()) { |
Jarin
2014/09/15 13:37:51
Are we allowed to use C++11? I think not yet.
|
+ if (node != NULL && node->opcode() == IrOpcode::kFrameState) { |
+ AddClosureToFrameState(jsgraph_, node, function); |
+ Node* outer_frame_state = call.frame_state(); |
+ // Insert argument adaptor frame if required. |
+ if (call.formal_arguments() != inlinee.formal_parameters()) { |
+ outer_frame_state = CreateArgumentsAdaptorFrameState( |
+ jsgraph_, &call, function, info.zone()); |
+ } |
+ NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); |
+ } |
+ } |
+ |
+ |
+ inlinee.InlineAtCall(jsgraph_, call_node); |
} |
} |
} |