Index: src/isolate.cc |
diff --git a/src/isolate.cc b/src/isolate.cc |
index 3c9a89999a7bb52191dcb2b63ea69f2bdf498eb1..47b37fa71530024bd0a8fb852c041931053f44bb 100644 |
--- a/src/isolate.cc |
+++ b/src/isolate.cc |
@@ -2478,6 +2478,31 @@ bool Isolate::use_crankshaft() const { |
CpuFeatures::SupportsCrankshaft(); |
} |
+bool Isolate::IsArrayOrObjectPrototype(Object* object) { |
+ Object* context = heap()->native_contexts_list(); |
+ while (context != heap()->undefined_value()) { |
+ Context* current_context = Context::cast(context); |
+ if (current_context->initial_object_prototype() == object || |
+ current_context->initial_array_prototype() == object) { |
+ return true; |
+ } |
+ context = current_context->next_context_link(); |
+ } |
+ return false; |
+} |
+ |
+bool Isolate::IsInContextIndex(Object* object, uint32_t index) { |
+ DisallowHeapAllocation no_gc; |
+ Object* context = heap()->native_contexts_list(); |
+ while (context != heap()->undefined_value()) { |
+ Context* current_context = Context::cast(context); |
+ if (current_context->get(index) == object) { |
+ return true; |
+ } |
+ context = current_context->next_context_link(); |
+ } |
+ return false; |
+} |
bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { |
PropertyCell* no_elements_cell = heap()->array_protector(); |
@@ -2551,56 +2576,67 @@ bool Isolate::IsArraySpeciesLookupChainIntact() { |
// done here. In place, there are mjsunit tests harmony/array-species* which |
// ensure that behavior is correct in various invalid protector cases. |
- PropertyCell* species_cell = heap()->species_protector(); |
- return species_cell->value()->IsSmi() && |
- Smi::cast(species_cell->value())->value() == kArrayProtectorValid; |
+ Cell* species_cell = heap()->species_protector(); |
+ return Smi::cast(species_cell->value())->value() == kArrayProtectorValid; |
} |
-void Isolate::InvalidateArraySpeciesProtector() { |
- DCHECK(factory()->species_protector()->value()->IsSmi()); |
- DCHECK(IsArraySpeciesLookupChainIntact()); |
- PropertyCell::SetValueWithInvalidation( |
- factory()->species_protector(), |
- handle(Smi::FromInt(kArrayProtectorInvalid), this)); |
- DCHECK(!IsArraySpeciesLookupChainIntact()); |
+bool Isolate::IsArrayIsConcatSpreadableLookupChainIntact() { |
+ Cell* is_concat_spreadable_cell = |
+ heap()->array_is_concat_spreadable_protector(); |
+ bool is_concat_spreadable_set = |
+ Smi::cast(is_concat_spreadable_cell->value())->value() == |
+ kArrayProtectorInvalid; |
+#ifdef DEBUG |
+ Map* root_array_map = get_initial_js_array_map(GetInitialFastElementsKind()); |
+ if (root_array_map == NULL) { |
+ // Ignore the value of is_concat_spreadable during bootstrap. |
+ return !is_concat_spreadable_set; |
+ } |
+ Handle<Object> array_prototype(array_function()->prototype(), this); |
+ Handle<Symbol> key = factory()->is_concat_spreadable_symbol(); |
+ Handle<Object> value; |
+ LookupIterator it(array_prototype, key); |
+ if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined()) { |
+ // TODO(cbruni): Currently we do not revert if we unset the |
+ // @@isConcatSpreadable property on Array.prototype or Object.prototype |
+ // hence the reverse implication doesn't hold. |
+ DCHECK(is_concat_spreadable_set); |
+ return false; |
+ } |
+#endif // DEBUG |
+ |
+ return !is_concat_spreadable_set; |
} |
void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) { |
DisallowHeapAllocation no_gc; |
- if (IsFastArrayConstructorPrototypeChainIntact() && |
- object->map()->is_prototype_map()) { |
- Object* context = heap()->native_contexts_list(); |
- while (!context->IsUndefined()) { |
- Context* current_context = Context::cast(context); |
- if (current_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX) == |
- *object || |
- current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) == |
- *object) { |
- CountUsage(v8::Isolate::UseCounterFeature::kArrayProtectorDirtied); |
- PropertyCell::SetValueWithInvalidation( |
- factory()->array_protector(), |
- handle(Smi::FromInt(kArrayProtectorInvalid), this)); |
- break; |
- } |
- context = current_context->get(Context::NEXT_CONTEXT_LINK); |
- } |
- } |
+ if (!object->map()->is_prototype_map()) return; |
+ if (!IsFastArrayConstructorPrototypeChainIntact()) return; |
+ if (!IsArrayOrObjectPrototype(*object)) return; |
+ PropertyCell::SetValueWithInvalidation( |
+ factory()->array_protector(), |
+ handle(Smi::FromInt(kArrayProtectorInvalid), this)); |
} |
+void Isolate::InvalidateArrayIsConcatSpreadableProtector() { |
+ DCHECK(factory()->array_is_concat_spreadable_protector()->value()->IsSmi()); |
+ DCHECK(IsArrayIsConcatSpreadableLookupChainIntact()); |
+ factory()->array_is_concat_spreadable_protector()->set_value( |
+ Smi::FromInt(kArrayProtectorInvalid)); |
+ DCHECK(!IsArrayIsConcatSpreadableLookupChainIntact()); |
+} |
+ |
+void Isolate::InvalidateArraySpeciesProtector() { |
+ DCHECK(factory()->species_protector()->value()->IsSmi()); |
+ DCHECK(IsArraySpeciesLookupChainIntact()); |
+ factory()->species_protector()->set_value( |
+ Smi::FromInt(kArrayProtectorInvalid)); |
+ DCHECK(!IsArraySpeciesLookupChainIntact()); |
+} |
bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) { |
- if (array->map()->is_prototype_map()) { |
- Object* context = heap()->native_contexts_list(); |
- while (!context->IsUndefined()) { |
- Context* current_context = Context::cast(context); |
- if (current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) == |
- *array) { |
- return true; |
- } |
- context = current_context->get(Context::NEXT_CONTEXT_LINK); |
- } |
- } |
- return false; |
+ DisallowHeapAllocation no_gc; |
+ return IsInContextIndex(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX); |
} |