Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index 22972537abcbccb0e72a702ba07e9e4eb12a011a..6c0faf7b349f1af6e4b5825b563379b6113c85f1 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -849,6 +849,16 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
} |
+void BytecodeGenerator::GetForInPreparedItem(Register destination, int index, |
+ Register prepare_result, |
+ Register scratch) { |
+ builder()->LoadLiteral(Smi::FromInt(index)); |
+ builder()->StoreAccumulatorInRegister(scratch); |
+ builder()->CallRuntime(Runtime::kFixedArrayGet, prepare_result, 2); |
+ builder()->StoreAccumulatorInRegister(destination); |
+} |
+ |
+ |
void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
EffectResultScope statement_result_scope(this); |
@@ -873,26 +883,34 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
builder()->ForInPrepare(receiver); |
loop_builder.BreakIfUndefined(); |
- Register for_in_state = execution_result()->NewRegister(); |
- builder()->StoreAccumulatorInRegister(for_in_state); |
+ // Ensure prepare_result and prepare_index are consecutive for CallRuntime. |
+ execution_result()->PrepareForConsecutiveAllocations(2); |
+ Register prepare_result = execution_result()->NewRegister(); |
+ Register prepare_index = execution_result()->NewRegister(); |
+ builder()->StoreAccumulatorInRegister(prepare_result); |
+ |
+ // Spill the for_in_state to registers so we can de-opt. |
+ Register cache_array = execution_result()->NewRegister(); |
+ GetForInPreparedItem(cache_array, 0, prepare_result, prepare_index); |
+ Register cache_type = execution_result()->NewRegister(); |
+ GetForInPreparedItem(cache_type, 1, prepare_result, prepare_index); |
+ Register cache_length = execution_result()->NewRegister(); |
+ GetForInPreparedItem(cache_length, 2, prepare_result, prepare_index); |
// Check loop termination (accumulator holds index). |
- Register index = receiver; // Re-using register as receiver no longer used. |
+ Register index = prepare_result; |
builder()->LoadLiteral(Smi::FromInt(0)); |
+ builder()->StoreAccumulatorInRegister(index); |
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, index, cache_type, cache_array); |
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); |
loop_builder.JumpToHeader(); |
loop_builder.LoopEnd(); |
} |