| Index: src/interpreter/bytecode-generator.cc
|
| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
| index a8407294a7c112cbef29fcd734722faf65331657..568476e3bca0c8cfea0a06a137b3d5797b0e161a 100644
|
| --- a/src/interpreter/bytecode-generator.cc
|
| +++ b/src/interpreter/bytecode-generator.cc
|
| @@ -613,8 +613,117 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
|
| }
|
|
|
|
|
| +void BytecodeGenerator::VisitForInAssignment(Expression* expr,
|
| + FeedbackVectorSlot slot) {
|
| + DCHECK(expr->IsValidReferenceExpression());
|
| +
|
| + // Evaluate assignment starting with the value to be stored in the
|
| + // accumulator.
|
| + Property* property = expr->AsProperty();
|
| + LhsKind assign_type = Property::GetAssignType(property);
|
| + switch (assign_type) {
|
| + case VARIABLE: {
|
| + Variable* variable = expr->AsVariableProxy()->var();
|
| + VisitVariableAssignment(variable, slot);
|
| + break;
|
| + }
|
| + case NAMED_PROPERTY: {
|
| + TemporaryRegisterScope temporary_register_scope(builder());
|
| + Register value = temporary_register_scope.NewRegister();
|
| + builder()->StoreAccumulatorInRegister(value);
|
| + Register object = VisitForRegisterValue(property->obj());
|
| + size_t name_index = builder()->GetConstantPoolEntry(
|
| + property->key()->AsLiteral()->AsPropertyName());
|
| + builder()->StoreNamedProperty(object, name_index, feedback_index(slot),
|
| + language_mode());
|
| + break;
|
| + }
|
| + case KEYED_PROPERTY: {
|
| + TemporaryRegisterScope temporary_register_scope(builder());
|
| + Register value = temporary_register_scope.NewRegister();
|
| + builder()->StoreAccumulatorInRegister(value);
|
| + Register object = VisitForRegisterValue(property->obj());
|
| + Register key = VisitForRegisterValue(property->key());
|
| + builder()->LoadAccumulatorWithRegister(value);
|
| + builder()->StoreKeyedProperty(object, key, feedback_index(slot),
|
| + language_mode());
|
| + break;
|
| + }
|
| + case NAMED_SUPER_PROPERTY:
|
| + case KEYED_SUPER_PROPERTY:
|
| + UNIMPLEMENTED();
|
| + }
|
| +}
|
| +
|
| +
|
| void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
| - UNIMPLEMENTED();
|
| + // TODO(oth): For now we need a parent scope for paths that end up
|
| + // in VisitLiteral which can allocate in the parent scope. A future
|
| + // CL in preparation will add a StatementResultScope that will
|
| + // remove the need for this EffectResultScope.
|
| + EffectResultScope result_scope(this);
|
| +
|
| + if (stmt->subject()->IsNullLiteral() ||
|
| + stmt->subject()->IsUndefinedLiteral(isolate())) {
|
| + // ForIn generates lots of code, skip if it wouldn't produce any effects.
|
| + return;
|
| + }
|
| +
|
| + LoopBuilder loop_builder(builder());
|
| + ControlScopeForIteration control_scope(this, stmt, &loop_builder);
|
| +
|
| + // Prepare the state for executing ForIn.
|
| + builder()->EnterBlock();
|
| + VisitForAccumulatorValue(stmt->subject());
|
| + loop_builder.BreakIfUndefined();
|
| + loop_builder.BreakIfNull();
|
| +
|
| + Register receiver = execution_result()->NewRegister();
|
| + builder()->CastAccumulatorToJSObject();
|
| + 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);
|
| +
|
| + // The loop.
|
| + BytecodeLabel condition_label, break_label, continue_label;
|
| + Register index = receiver; // Re-using register as receiver no longer used.
|
| + builder()->LoadLiteral(Smi::FromInt(0));
|
| +
|
| + // Check loop termination (accumulator holds index).
|
| + builder()
|
| + ->Bind(&condition_label)
|
| + .StoreAccumulatorInRegister(index)
|
| + .ForInDone(for_in_state);
|
| + loop_builder.BreakIfTrue();
|
| +
|
| + // Get the next item.
|
| + builder()->ForInNext(for_in_state, index);
|
| +
|
| + // Start again if the item, currently in the accumulator, is undefined.
|
| + loop_builder.ContinueIfUndefined();
|
| +
|
| + // Store the value in the each variable.
|
| + VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
|
| + // NB the user's loop variable will be assigned the value of each so
|
| + // even an empty body will have this assignment.
|
| + Visit(stmt->body());
|
| +
|
| + // Increment the index and start loop again.
|
| + builder()
|
| + ->Bind(&continue_label)
|
| + .LoadAccumulatorWithRegister(index)
|
| + .CountOperation(Token::Value::ADD, language_mode_strength())
|
| + .Jump(&condition_label);
|
| +
|
| + // End of loop
|
| + builder()->Bind(&break_label).LeaveBlock();
|
| +
|
| + loop_builder.SetBreakTarget(break_label);
|
| + loop_builder.SetContinueTarget(continue_label);
|
| }
|
|
|
|
|
|
|