| Index: src/interpreter/interpreter.cc
|
| diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
|
| index 046513700e56b48a381585499b6b54e4126fd7c9..3b12815e19605fb1472e3efbb609d017d2b445ef 100644
|
| --- a/src/interpreter/interpreter.cc
|
| +++ b/src/interpreter/interpreter.cc
|
| @@ -1910,67 +1910,45 @@ void Interpreter::BuildForInPrepareResult(Node* output_register,
|
| __ StoreRegister(cache_length, output_register);
|
| }
|
|
|
| -// ForInPrepare <cache_info_triple>
|
| +// ForInPrepare <receiver> <cache_info_triple>
|
| //
|
| -// Returns state for for..in loop execution based on the object in the
|
| -// accumulator. The result is output in registers |cache_info_triple| to
|
| +// Returns state for for..in loop execution based on the object in the register
|
| +// |receiver|. The object must not be null or undefined and must have been
|
| +// converted to a receiver already.
|
| +// The result is output in registers |cache_info_triple| to
|
| // |cache_info_triple + 2|, with the registers holding cache_type, cache_array,
|
| // and cache_length respectively.
|
| void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) {
|
| Node* object_reg = __ BytecodeOperandReg(0);
|
| - Node* object = __ LoadRegister(object_reg);
|
| + Node* receiver = __ LoadRegister(object_reg);
|
| Node* context = __ GetContext();
|
| Node* const zero_smi = __ SmiConstant(Smi::FromInt(0));
|
|
|
| - Label test_if_null(assembler), test_if_undefined(assembler),
|
| - nothing_to_iterate(assembler, Label::kDeferred),
|
| - convert_to_receiver(assembler, Label::kDeferred),
|
| - already_receiver(assembler), check_enum_cache(assembler);
|
| + Label nothing_to_iterate(assembler, Label::kDeferred),
|
| + use_enum_cache(assembler), use_runtime(assembler, Label::kDeferred);
|
|
|
| - Variable receiver(assembler, MachineRepresentation::kTagged);
|
| -
|
| - // Test if object is already a receiver, no conversion necessary if so.
|
| - Node* instance_type = __ LoadInstanceType(object);
|
| - Node* first_receiver_type = __ Int32Constant(FIRST_JS_RECEIVER_TYPE);
|
| - __ BranchIfInt32GreaterThanOrEqual(instance_type, first_receiver_type,
|
| - &already_receiver, &test_if_null);
|
| -
|
| - __ Bind(&test_if_null);
|
| - {
|
| - __ BranchIfWordEqual(object, assembler->NullConstant(), ¬hing_to_iterate,
|
| - &test_if_undefined);
|
| - }
|
| -
|
| - __ Bind(&test_if_undefined);
|
| - {
|
| - __ BranchIfWordEqual(object, assembler->UndefinedConstant(),
|
| - ¬hing_to_iterate, &convert_to_receiver);
|
| - }
|
| -
|
| - __ Bind(&convert_to_receiver);
|
| - {
|
| - Callable callable = CodeFactory::ToObject(assembler->isolate());
|
| - Node* target = __ HeapConstant(callable.code());
|
| - Node* result = __ CallStub(callable.descriptor(), target, context, object);
|
| - receiver.Bind(result);
|
| - __ Goto(&check_enum_cache);
|
| - }
|
| -
|
| - __ Bind(&already_receiver);
|
| - {
|
| - receiver.Bind(object);
|
| - __ Goto(&check_enum_cache);
|
| + if (FLAG_debug_code) {
|
| + Label already_receiver(assembler), abort(assembler);
|
| + Node* instance_type = __ LoadInstanceType(receiver);
|
| + Node* first_receiver_type = __ Int32Constant(FIRST_JS_RECEIVER_TYPE);
|
| + __ BranchIfInt32GreaterThanOrEqual(instance_type, first_receiver_type,
|
| + &already_receiver, &abort);
|
| + __ Bind(&abort);
|
| + {
|
| + __ Abort(kExpectedJSReceiver);
|
| + // TODO(klaasb) remove this unreachable Goto once Abort ends the block
|
| + __ Goto(&already_receiver);
|
| + }
|
| + __ Bind(&already_receiver);
|
| }
|
|
|
| - Label use_enum_cache(assembler), use_runtime(assembler, Label::kDeferred);
|
| - __ Bind(&check_enum_cache);
|
| - { __ CheckEnumCache(receiver.value(), &use_enum_cache, &use_runtime); }
|
| + __ CheckEnumCache(receiver, &use_enum_cache, &use_runtime);
|
|
|
| __ Bind(&use_enum_cache);
|
| {
|
| // The enum cache is valid. Load the map of the object being
|
| // iterated over and use the cache for the iteration.
|
| - Node* cache_type = __ LoadMap(receiver.value());
|
| + Node* cache_type = __ LoadMap(receiver);
|
| Node* cache_length = __ EnumLength(cache_type);
|
| __ GotoIf(assembler->WordEqual(cache_length, zero_smi),
|
| ¬hing_to_iterate);
|
| @@ -1988,7 +1966,7 @@ void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) {
|
| __ Bind(&use_runtime);
|
| {
|
| Node* result_triple =
|
| - __ CallRuntime(Runtime::kForInPrepare, context, object);
|
| + __ CallRuntime(Runtime::kForInPrepare, context, receiver);
|
| Node* cache_type = __ Projection(0, result_triple);
|
| Node* cache_array = __ Projection(1, result_triple);
|
| Node* cache_length = __ Projection(2, result_triple);
|
|
|