diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index fa85da680f..10afeb1fcb 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -1084,9 +1084,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { ForIn loop_statement(this, stmt); increment_loop_depth(); - // Get the object to enumerate over. Both SpiderMonkey and JSC - // ignore null and undefined in contrast to the specification; see - // ECMA-262 section 12.6.4. + // Get the object to enumerate over. If the object is null or undefined, skip + // over the loop. See ECMA-262 version 5, section 12.6.4. VisitForAccumulatorValue(stmt->enumerable()); __ mov(a0, result_register()); // Result as param to InvokeBuiltin below. __ LoadRoot(at, Heap::kUndefinedValueRootIndex); @@ -1260,6 +1259,67 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { } +void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { + Comment cmnt(masm_, "[ ForOfStatement"); + SetStatementPosition(stmt); + + Iteration loop_statement(this, stmt); + increment_loop_depth(); + + // var iterator = iterable[@@iterator]() + VisitForAccumulatorValue(stmt->assign_iterator()); + __ mov(a0, v0); + + // As with for-in, skip the loop if the iterator is null or undefined. + __ LoadRoot(at, Heap::kUndefinedValueRootIndex); + __ Branch(loop_statement.break_label(), eq, a0, Operand(at)); + __ LoadRoot(at, Heap::kNullValueRootIndex); + __ Branch(loop_statement.break_label(), eq, a0, Operand(at)); + + // Convert the iterator to a JS object. + Label convert, done_convert; + __ JumpIfSmi(a0, &convert); + __ GetObjectType(a0, a1, a1); + __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); + __ bind(&convert); + __ push(a0); + __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(a0, v0); + __ bind(&done_convert); + __ push(a0); + + // Loop entry. + __ bind(loop_statement.continue_label()); + + // result = iterator.next() + VisitForEffect(stmt->next_result()); + + // if (result.done) break; + Label result_not_done; + VisitForControl(stmt->result_done(), + loop_statement.break_label(), + &result_not_done, + &result_not_done); + __ bind(&result_not_done); + + // each = result.value + VisitForEffect(stmt->assign_each()); + + // Generate code for the body of the loop. + Visit(stmt->body()); + + // Check stack before looping. + PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); + EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); + __ jmp(loop_statement.continue_label()); + + // Exit and decrement the loop depth. + PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); + __ bind(loop_statement.break_label()); + decrement_loop_depth(); +} + + void FullCodeGenerator::EmitNewClosure(Handle info, bool pretenure) { // Use the fast case closure allocation code that allocates in new