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.

Reply via email to