| 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();
|
| }
|
|
|