Index: src/mips/full-codegen-mips.cc |
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc |
index fa85da680fcb5f2b4f555c1147a55c732b669d31..10afeb1fcb636555ddd5424be3e480a6a69f6924 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<SharedFunctionInfo> info, |
bool pretenure) { |
// Use the fast case closure allocation code that allocates in new |