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 |