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

Unified Diff: src/compiler/js-inlining.cc

Issue 573703002: Add handling for deopt and argument adaptor frames. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Adding Jarin's comments. Created 6 years, 3 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
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 {
Michael Starzinger 2014/09/16 14:12:56 While such a thing would be nice to have, spreadin
sigurds 2014/09/17 10:02:47 I absolutely agree. However, without this thing th
+ 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(), &params.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();
Michael Starzinger 2014/09/16 14:12:56 OMG, we really should try to find a way to do this
sigurds 2014/09/17 10:02:47 Done.
+ 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()) {
+ 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);
}
}
}

Powered by Google App Engine
This is Rietveld 408576698