First simple implementation of for-of in TurboFan.
authormstarzinger <mstarzinger@chromium.org>
Wed, 14 Jan 2015 15:24:20 +0000 (07:24 -0800)
committerCommit bot <commit-bot@chromium.org>
Wed, 14 Jan 2015 15:24:29 +0000 (15:24 +0000)
R=rossberg@chromium.org
TEST=cctest/test-run-jsbranches/ForOfContinueStatement

Review URL: https://codereview.chromium.org/850803002

Cr-Commit-Position: refs/heads/master@{#26060}

src/ast-numbering.cc
src/compiler/ast-graph-builder.cc
src/compiler/control-builders.cc
src/compiler/control-builders.h
src/compiler/pipeline.cc
test/cctest/compiler/test-run-jsbranches.cc

index c2dd70e..784e605 100644 (file)
@@ -47,10 +47,10 @@ class AstNumberingVisitor FINAL : public AstVisitor {
   void IncrementNodeCount() { properties_.add_node_count(1); }
   void DisableCrankshaft(BailoutReason reason) {
     dont_crankshaft_reason_ = reason;
-    properties_.flags()->Add(kDontSelfOptimize);
+    DisableSelfOptimization();
   }
   // TODO(turbofan): Remove the dont_turbofan_reason once no nodes are
-  // DontTurbofanNode.  That set of nodes must be kept in sync with
+  // DisableTurbofan.  That set of nodes must be kept in sync with
   // Pipeline::GenerateCode.
   void DisableTurbofan(BailoutReason reason) {
     dont_crankshaft_reason_ = reason;
@@ -390,7 +390,7 @@ void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
 
 void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
   IncrementNodeCount();
-  DisableTurbofan(kForOfStatement);
+  DisableCrankshaft(kForOfStatement);
   node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
   Visit(node->assign_iterator());
   Visit(node->next_result());
index c42d26c..c0c1886 100644 (file)
@@ -789,9 +789,17 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
 
 
 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
-  VisitForValue(stmt->subject());
-  environment()->Pop();
-  // TODO(turbofan): create and use loop builder.
+  LoopBuilder for_loop(this);
+  VisitForEffect(stmt->assign_iterator());
+  for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), IsOsrLoopEntry(stmt));
+  VisitForEffect(stmt->next_result());
+  VisitForTest(stmt->result_done());
+  Node* condition = environment()->Pop();
+  for_loop.BreakWhen(condition);
+  VisitForEffect(stmt->assign_each());
+  VisitIterationBody(stmt, &for_loop, 0);
+  for_loop.EndBody();
+  for_loop.EndLoop();
 }
 
 
index 2978d8b..6cf2905 100644 (file)
@@ -73,6 +73,16 @@ void LoopBuilder::BreakUnless(Node* condition) {
 }
 
 
+void LoopBuilder::BreakWhen(Node* condition) {
+  IfBuilder control_if(builder_);
+  control_if.If(condition);
+  control_if.Then();
+  Break();
+  control_if.Else();
+  control_if.End();
+}
+
+
 void SwitchBuilder::BeginSwitch() {
   body_environment_ = environment()->CopyAsUnreachable();
   label_environment_ = environment()->CopyAsUnreachable();
index e8e3305..ba04107 100644 (file)
@@ -77,8 +77,9 @@ class LoopBuilder FINAL : public ControlBuilder {
   void Continue() FINAL;
   void Break() FINAL;
 
-  // Compound control command for conditional break.
+  // Compound control commands for conditional break.
   void BreakUnless(Node* condition);
+  void BreakWhen(Node* condition);
 
  private:
   Environment* loop_environment_;      // Environment of the loop header.
index 0ca9009..100b9bc 100644 (file)
@@ -760,11 +760,9 @@ void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
 
 
 Handle<Code> Pipeline::GenerateCode() {
-  // This list must be kept in sync with DONT_TURBOFAN_NODE in ast.cc.
+  // This list must be kept in sync with DisableTurbofan in ast-numbering.cc.
   if (info()->function()->dont_optimize_reason() == kTryCatchStatement ||
       info()->function()->dont_optimize_reason() == kTryFinallyStatement ||
-      // TODO(turbofan): Make ES6 for-of work and remove this bailout.
-      info()->function()->dont_optimize_reason() == kForOfStatement ||
       // TODO(turbofan): Make super work and remove this bailout.
       info()->function()->dont_optimize_reason() == kSuperReference ||
       // TODO(turbofan): Make class literals work and remove this bailout.
index 7a4a0b3..5a7bdb9 100644 (file)
@@ -168,6 +168,33 @@ TEST(ForInContinueStatement) {
 }
 
 
+TEST(ForOfContinueStatement) {
+  const char* src =
+      "(function(a,b) {"
+      "  var r = '-';"
+      "  for (var x of a) {"
+      "    r += x + '-';"
+      "    if (b) continue;"
+      "    r += 'X-';"
+      "  }"
+      "  return r;"
+      "})";
+  FunctionTester T(src);
+
+  CompileRun(
+      "function wrap(v) {"
+      "  var iterable = {};"
+      "  function next() { return { done:!v.length, value:v.shift() }; };"
+      "  iterable[Symbol.iterator] = function() { return { next:next }; };"
+      "  return iterable;"
+      "}");
+
+  T.CheckCall(T.Val("-"), T.NewObject("wrap([])"), T.true_value());
+  T.CheckCall(T.Val("-1-2-"), T.NewObject("wrap([1,2])"), T.true_value());
+  T.CheckCall(T.Val("-1-X-2-X-"), T.NewObject("wrap([1,2])"), T.false_value());
+}
+
+
 TEST(SwitchStatement) {
   const char* src =
       "(function(a,b) {"