Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index 692eb3570f62b69cce020986a2832e7449627b0f..e8c789856041354d655889586a9a7333e86e11e7 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -855,7 +855,6 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
EffectResultScope statement_result_scope(this); |
- |
if (stmt->subject()->IsNullLiteral() || |
stmt->subject()->IsUndefinedLiteral(isolate())) { |
// ForIn generates lots of code, skip if it wouldn't produce any effects. |
@@ -864,41 +863,43 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
LoopBuilder loop_builder(builder()); |
ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
+ BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; |
// Prepare the state for executing ForIn. |
VisitForAccumulatorValue(stmt->subject()); |
- loop_builder.BreakIfUndefined(); |
- loop_builder.BreakIfNull(); |
- |
+ builder()->JumpIfUndefined(&subject_undefined_label); |
+ builder()->JumpIfNull(&subject_null_label); |
Register receiver = execution_result()->NewRegister(); |
builder()->CastAccumulatorToJSObject(); |
+ builder()->JumpIfNull(¬_object_label); |
builder()->StoreAccumulatorInRegister(receiver); |
- builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); |
- builder()->ForInPrepare(receiver); |
- loop_builder.BreakIfUndefined(); |
- |
- Register for_in_state = execution_result()->NewRegister(); |
- builder()->StoreAccumulatorInRegister(for_in_state); |
+ Register cache_type = execution_result()->NewRegister(); |
+ Register cache_array = execution_result()->NewRegister(); |
+ Register cache_length = execution_result()->NewRegister(); |
+ builder()->ForInPrepare(cache_type, cache_array, cache_length); |
- // Check loop termination (accumulator holds index). |
- Register index = receiver; // Re-using register as receiver no longer used. |
+ // Set up loop counter |
+ Register index = execution_result()->NewRegister(); |
builder()->LoadLiteral(Smi::FromInt(0)); |
+ builder()->StoreAccumulatorInRegister(index); |
+ |
+ // The loop |
loop_builder.LoopHeader(); |
loop_builder.Condition(); |
- builder()->StoreAccumulatorInRegister(index).ForInDone(for_in_state); |
+ builder()->ForInDone(index, cache_length); |
loop_builder.BreakIfTrue(); |
- builder()->ForInNext(for_in_state, index); |
+ builder()->ForInNext(receiver, cache_type, cache_array, index); |
loop_builder.ContinueIfUndefined(); |
- |
VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
Visit(stmt->body()); |
- |
- // TODO(oth): replace CountOperation here with ForInStep. |
loop_builder.Next(); |
- builder()->LoadAccumulatorWithRegister(index).CountOperation( |
- Token::Value::ADD, language_mode_strength()); |
+ builder()->ForInStep(index); |
+ builder()->StoreAccumulatorInRegister(index); |
loop_builder.JumpToHeader(); |
loop_builder.EndLoop(); |
+ builder()->Bind(¬_object_label); |
+ builder()->Bind(&subject_null_label); |
+ builder()->Bind(&subject_undefined_label); |
} |