Chromium Code Reviews| Index: src/code-stub-assembler.cc |
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
| index 85246894b778af2454ea0e7c95bdcaad1e29c1c1..179d84d8f996b9867d7269af651d46f6adaea0b4 100644 |
| --- a/src/code-stub-assembler.cc |
| +++ b/src/code-stub-assembler.cc |
| @@ -8710,17 +8710,53 @@ compiler::Node* CodeStubAssembler::CreateArrayIterator( |
| Bind(&if_isfast); |
| { |
| - Node* map_index = |
| - IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset), |
| - LoadMapElementsKind(array_map)); |
| - CSA_ASSERT(IntPtrGreaterThanOrEqual( |
| - map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset))); |
| - CSA_ASSERT(IntPtrLessThan( |
| - map_index, IntPtrConstant(kBaseMapIndex + kSlowIteratorOffset))); |
| - |
| - var_map_index.Bind(map_index); |
| - var_array_map.Bind(array_map); |
| - Goto(&allocate_iterator); |
| + Label if_ispacked(this), if_isholey(this); |
| + Node* elements_kind = LoadMapElementsKind(array_map); |
| + Branch(Word32Equal(Word32And(elements_kind, Int32Constant(1)), |
| + Int32Constant(0)), |
| + &if_ispacked, &if_isholey); |
|
Camillo Bruni
2016/11/09 12:03:49
Could you add a IsFastPackedElementsKind helper on
caitp
2016/11/09 17:40:16
Done, 2 new helpers (CSA::IsFastElementsKind() and
|
| + Bind(&if_isholey); |
| + { |
| + // Check the protector cell --- create a Generic iterator if invalid |
| + 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); |
| + |
| + // Otherwise, check that the prototype is a stable initial |
|
Benedikt Meurer
2016/11/09 05:37:05
Maybe it'd be sufficient to check for current cont
caitp
2016/11/09 17:40:16
Updated to only check the current context, and add
|
| + // Array prototype |
| + Node* prototype = LoadMapPrototype(array_map); |
| + GotoUnless(IsAnyInitialArrayPrototype(prototype), &if_isslow); |
| + GotoUnless(Word32Equal(DecodeWord32<Map::IsUnstable>( |
| + LoadMapBitField3(array_map)), |
| + Int32Constant(0)), |
| + &if_isslow); |
| + |
| + // Check that the Object prototype is stable as well. |
| + prototype = LoadMapPrototype(LoadMap(prototype)); |
|
Camillo Bruni
2016/11/09 12:03:49
object_map = LoadMap(prototype); ...
|
| + GotoUnless(IsAnyInitialObjectPrototype(prototype), &if_isslow); |
| + Branch(Word32Equal( |
| + DecodeWord32<Map::IsUnstable>(LoadMapBitField3(array_map)), |
|
Camillo Bruni
2016/11/09 12:03:49
You probably wanted to check the object_map here.
caitp
2016/11/09 17:40:16
good catch, but I guess we don't need stability ch
|
| + Int32Constant(0)), |
| + &if_ispacked, &if_isslow); |
| + } |
| + Bind(&if_ispacked); |
| + { |
| + Node* map_index = |
| + IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset), |
| + LoadMapElementsKind(array_map)); |
| + CSA_ASSERT(IntPtrGreaterThanOrEqual( |
| + map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset))); |
| + CSA_ASSERT(IntPtrLessThan( |
| + map_index, IntPtrConstant(kBaseMapIndex + kSlowIteratorOffset))); |
| + |
| + var_map_index.Bind(map_index); |
| + var_array_map.Bind(array_map); |
| + Goto(&allocate_iterator); |
| + } |
| } |
| Bind(&if_isslow); |
| @@ -8860,5 +8896,48 @@ void CodeStubArguments::PopAndReturn(compiler::Node* value) { |
| value); |
| } |
| +// Implement Isolate::IsInAnyContext() in CodeStubAssembler form. |
| +compiler::Node* CodeStubAssembler::IsInAnyNativeContext(compiler::Node* object, |
| + uint32_t index) { |
| + Variable var_context(this, MachineRepresentation::kTagged); |
| + Variable var_found(this, MachineRepresentation::kWord32); |
| + var_context.Bind(LoadFirstNativeContext()); |
| + var_found.Bind(Int32Constant(0)); |
| + |
| + Label loop(this, &var_context), done(this); |
| + Branch(WordEqual(var_context.value(), UndefinedConstant()), &done, &loop); |
|
Camillo Bruni
2016/11/09 12:03:49
nit: IsUndefined(var_context.value())
|
| + |
| + // Loop while {context} is not undefined: |
| + Bind(&loop); |
| + { |
| + Label continue_loop(this), break_loop(this); |
| + Node* context = var_context.value(); |
| + Node* value = LoadContextElement(context, index); |
| + |
| + Branch(WordEqual(value, object), &break_loop, &continue_loop); |
| + Bind(&break_loop); |
| + var_found.Bind(Int32Constant(1)); |
| + Goto(&done); |
| + |
| + Bind(&continue_loop); |
| + var_context.Bind(LoadContextElement(context, Context::NEXT_CONTEXT_LINK)); |
| + Branch(WordEqual(var_context.value(), UndefinedConstant()), &done, &loop); |
|
Camillo Bruni
2016/11/09 12:03:49
nit: IsUndefined(var_context.value())
|
| + } |
| + |
| + Bind(&done); |
| + Node* result = Word32NotEqual(var_found.value(), Int32Constant(0)); |
| + return result; |
| +} |
| + |
| +compiler::Node* CodeStubAssembler::IsAnyInitialArrayPrototype( |
| + compiler::Node* object) { |
| + return IsInAnyNativeContext(object, Context::INITIAL_ARRAY_PROTOTYPE_INDEX); |
| +} |
| + |
| +compiler::Node* CodeStubAssembler::IsAnyInitialObjectPrototype( |
| + compiler::Node* object) { |
| + return IsInAnyNativeContext(object, Context::INITIAL_OBJECT_PROTOTYPE_INDEX); |
| +} |
| + |
| } // namespace internal |
| } // namespace v8 |