Reviewers: Michael Starzinger,
Message:
PTAL
Description:
[turbofan] Introduce JSStackCheck operator.
The key idea here is that the stack check should be explicit, such that
we can eliminate unnecessary stack checks after graph building and
potentially inlining.
Please review this at https://codereview.chromium.org/981243002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+57, -14 lines):
M src/compiler/ast-graph-builder.cc
M src/compiler/js-generic-lowering.h
M src/compiler/js-generic-lowering.cc
M src/compiler/js-operator.h
M src/compiler/js-operator.cc
M src/compiler/opcodes.h
M src/compiler/operator-properties.cc
M src/compiler/typer.cc
M src/compiler/verifier.cc
Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc
b/src/compiler/ast-graph-builder.cc
index
e87ca786b19775e1dac0d88e370b1ac7d75bb6f1..ef401cf4bd8bf9707664a616f870ba736dd8db81
100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -2966,17 +2966,7 @@ Node* AstGraphBuilder::BuildBinaryOp(Node* left,
Node* right, Token::Value op) {
Node* AstGraphBuilder::BuildStackCheck() {
- IfBuilder stack_check(this);
- Node* limit = BuildLoadExternal(
- ExternalReference::address_of_stack_limit(isolate()), kMachPtr);
- Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer());
- Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack);
- stack_check.If(tag, BranchHint::kTrue);
- stack_check.Then();
- stack_check.Else();
- Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard,
0));
- stack_check.End();
- return guard;
+ return NewNode(javascript()->StackCheck());
}
Index: src/compiler/js-generic-lowering.cc
diff --git a/src/compiler/js-generic-lowering.cc
b/src/compiler/js-generic-lowering.cc
index
b585016b2e8dafc2342bfec6df196bfc12f04e96..42c5e56dce46e3fa7451fe5c1412a46f044170b1
100644
--- a/src/compiler/js-generic-lowering.cc
+++ b/src/compiler/js-generic-lowering.cc
@@ -480,6 +480,40 @@ void JSGenericLowering::LowerJSCallRuntime(Node* node)
{
ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
}
+
+void JSGenericLowering::LowerJSStackCheck(Node* node) {
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ Node* limit = graph()->NewNode(
+ machine()->Load(kMachPtr),
+ jsgraph()->ExternalConstant(
+ ExternalReference::address_of_stack_limit(isolate())),
+ jsgraph()->IntPtrConstant(0), effect, control);
+ Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
+
+ Node* check = graph()->NewNode(machine()->UintLessThan(), limit,
pointer);
+ Node* branch =
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check,
control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = effect;
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ NodeProperties::ReplaceControlInput(node, if_false);
+ Node* efalse = node;
+
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse,
merge);
+
+ // Relax controls of {node}, i.e. make it free floating.
+ NodeProperties::ReplaceWithValue(node, node, ephi, merge);
+ NodeProperties::ReplaceEffectInput(ephi, efalse, 1);
+
+ // Turn the stack check into a runtime call.
+ ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
Index: src/compiler/js-generic-lowering.h
diff --git a/src/compiler/js-generic-lowering.h
b/src/compiler/js-generic-lowering.h
index
10057eb9e11207203931822b9f1f85cca676731c..30e8cf66559ea2984d5db335913fc26f61bbd94a
100644
--- a/src/compiler/js-generic-lowering.h
+++ b/src/compiler/js-generic-lowering.h
@@ -51,11 +51,12 @@ class JSGenericLowering FINAL : public Reducer {
JSGraph* jsgraph() const { return jsgraph_; }
Graph* graph() const { return jsgraph()->graph(); }
CommonOperatorBuilder* common() const { return jsgraph()->common(); }
+ JSOperatorBuilder* javascript() const { return jsgraph()->javascript(); }
MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
private:
bool is_typing_enabled_;
- JSGraph* jsgraph_;
+ JSGraph* const jsgraph_;
};
} // namespace compiler
Index: src/compiler/js-operator.cc
diff --git a/src/compiler/js-operator.cc b/src/compiler/js-operator.cc
index
2e0de6b375c6dc05a11a46e2c073bd0e12a29840..bc0e61f8bbdf607e0a342cdee82f4306921fa8a4
100644
--- a/src/compiler/js-operator.cc
+++ b/src/compiler/js-operator.cc
@@ -240,6 +240,7 @@ const StoreNamedParameters&
StoreNamedParametersOf(const Operator* op) {
V(TypeOf, Operator::kPure, 1, 1) \
V(InstanceOf, Operator::kNoProperties, 2, 1) \
V(Debugger, Operator::kNoProperties, 0, 0) \
+ V(StackCheck, Operator::kNoProperties, 0, 0) \
V(CreateFunctionContext, Operator::kNoProperties, 1, 1) \
V(CreateWithContext, Operator::kNoProperties, 2, 1) \
V(CreateBlockContext, Operator::kNoProperties, 2, 1) \
Index: src/compiler/js-operator.h
diff --git a/src/compiler/js-operator.h b/src/compiler/js-operator.h
index
e7fc04c1e19cab287e1d92922b011ccfc85829a2..90f69d1a816a32d27f0e445a30330e9ef5df3549
100644
--- a/src/compiler/js-operator.h
+++ b/src/compiler/js-operator.h
@@ -254,6 +254,8 @@ class JSOperatorBuilder FINAL : public ZoneObject {
const Operator* InstanceOf();
const Operator* Debugger();
+ const Operator* StackCheck();
+
// TODO(titzer): nail down the static parts of each of these context
flavors.
const Operator* CreateFunctionContext();
const Operator* CreateCatchContext(const Unique<String>& name);
Index: src/compiler/opcodes.h
diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h
index
5343c2f1c285c02ac913e54e2bc3ae77955e0ce6..28e1d485cda086518e55e5b3b36f0d278753bbef
100644
--- a/src/compiler/opcodes.h
+++ b/src/compiler/opcodes.h
@@ -131,7 +131,8 @@
V(JSCallFunction) \
V(JSCallRuntime) \
V(JSYield) \
- V(JSDebugger)
+ V(JSDebugger) \
+ V(JSStackCheck)
#define JS_OP_LIST(V) \
JS_SIMPLE_BINOP_LIST(V) \
@@ -304,7 +305,7 @@ class IrOpcode {
// Returns true if opcode for JavaScript operator.
static bool IsJsOpcode(Value value) {
- return kJSEqual <= value && value <= kJSDebugger;
+ return kJSEqual <= value && value <= kJSStackCheck;
}
// Returns true if opcode for constant operator.
Index: src/compiler/operator-properties.cc
diff --git a/src/compiler/operator-properties.cc
b/src/compiler/operator-properties.cc
index
64f384b4b41568bc852adcb4e3c1b8fc0dc050c5..9367134c0c8080fc91b97719ae9a60ff711d5d3d
100644
--- a/src/compiler/operator-properties.cc
+++ b/src/compiler/operator-properties.cc
@@ -72,6 +72,9 @@ bool OperatorProperties::HasFrameStateInput(const
Operator* op) {
case IrOpcode::kJSToNumber:
case IrOpcode::kJSToName:
+ // Misc operations
+ case IrOpcode::kJSStackCheck:
+
// Properties
case IrOpcode::kJSLoadNamed:
case IrOpcode::kJSLoadProperty:
Index: src/compiler/typer.cc
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index
c638535727f1c9593c001fb90e9333d2481dd1fa..0a7d55d82e76d8434fecf657418d78e1c09517d2
100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1519,6 +1519,12 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node)
{
Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
+ UNREACHABLE();
+ return Bounds();
+}
+
+
+Bounds Typer::Visitor::TypeJSStackCheck(Node* node) {
return Bounds::Unbounded(zone());
}
Index: src/compiler/verifier.cc
diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc
index
77e13e7d6a0e82f907a10256f60106cd5cf1f60a..63eff8041810a7c73a1986b1e53e176b6ce30c8a
100644
--- a/src/compiler/verifier.cc
+++ b/src/compiler/verifier.cc
@@ -550,6 +550,11 @@ void Verifier::Visitor::Check(Node* node) {
CheckUpperIs(node, Type::Any());
break;
+ case IrOpcode::kJSStackCheck:
+ // Type is empty.
+ CheckNotTyped(node);
+ break;
+
// Simplified operators
// -------------------------------
case IrOpcode::kAnyToBoolean:
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.