| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index 323c05d17e737cbbfdc0e5acfb1dc6625743b867..766d331333bd837b614f0a7429fadb990985d08e 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -681,16 +681,11 @@ void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
|
| Node* elements_kind = LoadMapElementsKind(map);
|
|
|
| // Bailout if receiver has slow elements.
|
| - GotoIf(
|
| - Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
|
| - if_false);
|
| + GotoUnless(IsFastElementsKind(elements_kind), if_false);
|
|
|
| // Check prototype chain if receiver does not have packed elements.
|
| - STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1));
|
| - STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1));
|
| - STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1));
|
| - Node* holey_elements = Word32And(elements_kind, Int32Constant(1));
|
| - GotoIf(Word32Equal(holey_elements, Int32Constant(0)), if_true);
|
| + GotoUnless(IsHoleyFastElementsKind(elements_kind), if_true);
|
| +
|
| BranchIfPrototypesHaveNoElements(map, if_true, if_false);
|
| }
|
|
|
| @@ -8898,19 +8893,59 @@ compiler::Node* CodeStubAssembler::CreateArrayIterator(
|
|
|
| Bind(&if_isfast);
|
| {
|
| - Node* map_index =
|
| - IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset),
|
| - LoadMapElementsKind(array_map));
|
| - CSA_ASSERT(this, IntPtrGreaterThanOrEqual(
|
| - map_index, IntPtrConstant(kBaseMapIndex +
|
| - kFastIteratorOffset)));
|
| - CSA_ASSERT(this, IntPtrLessThan(map_index,
|
| - IntPtrConstant(kBaseMapIndex +
|
| - kSlowIteratorOffset)));
|
| + Label if_ispacked(this), if_isholey(this);
|
| + Node* elements_kind = LoadMapElementsKind(array_map);
|
| + Branch(IsHoleyFastElementsKind(elements_kind), &if_isholey,
|
| + &if_ispacked);
|
|
|
| - var_map_index.Bind(map_index);
|
| - var_array_map.Bind(array_map);
|
| - Goto(&allocate_iterator);
|
| + Bind(&if_isholey);
|
| + {
|
| + // Fast holey JSArrays can treat the hole as undefined if the
|
| + // protector cell is valid, and the prototype chain is unchanged from
|
| + // its initial state (because the protector cell is only tracked for
|
| + // initial the Array and Object prototypes). Check these conditions
|
| + // here, and take the slow path if any fail.
|
| + Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
|
| + DCHECK(isolate()->heap()->array_protector()->IsPropertyCell());
|
| + GotoUnless(
|
| + WordEqual(
|
| + LoadObjectField(protector_cell, PropertyCell::kValueOffset),
|
| + SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))),
|
| + &if_isslow);
|
| +
|
| + Node* native_context = LoadNativeContext(context);
|
| +
|
| + Node* prototype = LoadMapPrototype(array_map);
|
| + Node* array_prototype = LoadContextElement(
|
| + native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
|
| + GotoUnless(WordEqual(prototype, array_prototype), &if_isslow);
|
| +
|
| + Node* map = LoadMap(prototype);
|
| + prototype = LoadMapPrototype(map);
|
| + Node* object_prototype = LoadContextElement(
|
| + native_context, Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
|
| + GotoUnless(WordEqual(prototype, object_prototype), &if_isslow);
|
| +
|
| + map = LoadMap(prototype);
|
| + prototype = LoadMapPrototype(map);
|
| + Branch(IsNull(prototype), &if_ispacked, &if_isslow);
|
| + }
|
| + Bind(&if_ispacked);
|
| + {
|
| + Node* map_index =
|
| + IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset),
|
| + LoadMapElementsKind(array_map));
|
| + CSA_ASSERT(this, IntPtrGreaterThanOrEqual(
|
| + map_index, IntPtrConstant(kBaseMapIndex +
|
| + kFastIteratorOffset)));
|
| + CSA_ASSERT(this, IntPtrLessThan(map_index,
|
| + IntPtrConstant(kBaseMapIndex +
|
| + kSlowIteratorOffset)));
|
| +
|
| + var_map_index.Bind(map_index);
|
| + var_array_map.Bind(array_map);
|
| + Goto(&allocate_iterator);
|
| + }
|
| }
|
|
|
| Bind(&if_isslow);
|
| @@ -9051,5 +9086,24 @@ void CodeStubArguments::PopAndReturn(compiler::Node* value) {
|
| value);
|
| }
|
|
|
| +compiler::Node* CodeStubAssembler::IsFastElementsKind(
|
| + compiler::Node* elements_kind) {
|
| + return Uint32LessThanOrEqual(elements_kind,
|
| + Int32Constant(LAST_FAST_ELEMENTS_KIND));
|
| +}
|
| +
|
| +compiler::Node* CodeStubAssembler::IsHoleyFastElementsKind(
|
| + compiler::Node* elements_kind) {
|
| + CSA_ASSERT(this, IsFastElementsKind(elements_kind));
|
| +
|
| + STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1));
|
| + STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1));
|
| + STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1));
|
| +
|
| + // Check prototype chain if receiver does not have packed elements.
|
| + Node* holey_elements = Word32And(elements_kind, Int32Constant(1));
|
| + return Word32Equal(holey_elements, Int32Constant(1));
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace v8
|
|
|