From 2ebe24c9cb22452bc1f84744e21453b5afaf054a Mon Sep 17 00:00:00 2001 From: mstarzinger Date: Wed, 14 Jan 2015 07:24:20 -0800 Subject: [PATCH] First simple implementation of for-of in TurboFan. 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 | 6 +++--- src/compiler/ast-graph-builder.cc | 14 +++++++++++--- src/compiler/control-builders.cc | 10 ++++++++++ src/compiler/control-builders.h | 3 ++- src/compiler/pipeline.cc | 4 +--- test/cctest/compiler/test-run-jsbranches.cc | 27 +++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/ast-numbering.cc b/src/ast-numbering.cc index c2dd70e..784e605 100644 --- a/src/ast-numbering.cc +++ b/src/ast-numbering.cc @@ -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()); diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index c42d26c..c0c1886 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -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(); } diff --git a/src/compiler/control-builders.cc b/src/compiler/control-builders.cc index 2978d8b..6cf2905 100644 --- a/src/compiler/control-builders.cc +++ b/src/compiler/control-builders.cc @@ -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(); diff --git a/src/compiler/control-builders.h b/src/compiler/control-builders.h index e8e3305..ba04107 100644 --- a/src/compiler/control-builders.h +++ b/src/compiler/control-builders.h @@ -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. diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index 0ca9009..100b9bc 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -760,11 +760,9 @@ void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { Handle 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. diff --git a/test/cctest/compiler/test-run-jsbranches.cc b/test/cctest/compiler/test-run-jsbranches.cc index 7a4a0b3..5a7bdb9 100644 --- a/test/cctest/compiler/test-run-jsbranches.cc +++ b/test/cctest/compiler/test-run-jsbranches.cc @@ -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) {" -- 2.7.4