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;
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());
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();
}
}
+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();
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.
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.
}
+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) {"