Index: src/isolate.cc |
diff --git a/src/isolate.cc b/src/isolate.cc |
index 5d261d4983e5d1f079aa07482b38f4cfff1b376a..2d13f25b620dafb63f60fa98cca1ff2e089f2792 100644 |
--- a/src/isolate.cc |
+++ b/src/isolate.cc |
@@ -2533,6 +2533,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::IsInAnyContext(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(); |
@@ -2593,52 +2618,63 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { |
return cell_reports_intact; |
} |
-void Isolate::InvalidateArraySpeciesProtector() { |
- if (!FLAG_harmony_species) return; |
- DCHECK(factory()->species_protector()->value()->IsSmi()); |
- DCHECK(IsArraySpeciesLookupChainIntact()); |
- PropertyCell::SetValueWithInvalidation( |
- factory()->species_protector(), |
- handle(Smi::FromInt(kArrayProtectorInvalid), this)); |
- DCHECK(!IsArraySpeciesLookupChainIntact()); |
+bool Isolate::IsIsConcatSpreadableLookupChainIntact() { |
+ Cell* is_concat_spreadable_cell = heap()->is_concat_spreadable_protector(); |
+ bool is_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_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_is_concat_spreadable_set); |
+ return false; |
+ } |
+#endif // DEBUG |
+ |
+ return !is_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::InvalidateIsConcatSpreadableProtector() { |
+ DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi()); |
+ DCHECK(IsIsConcatSpreadableLookupChainIntact()); |
+ factory()->is_concat_spreadable_protector()->set_value( |
+ Smi::FromInt(kArrayProtectorInvalid)); |
+ DCHECK(!IsIsConcatSpreadableLookupChainIntact()); |
+} |
+ |
+void Isolate::InvalidateArraySpeciesProtector() { |
+ if (!FLAG_harmony_species) return; |
+ 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 IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX); |
} |