Index: src/isolate.cc |
diff --git a/src/isolate.cc b/src/isolate.cc |
index 44e5ec0658f2b424cc6c37938a1d9ba1a3bf1aee..06f09487b5afbdecc3de54c2e73f906bf9aa3117 100644 |
--- a/src/isolate.cc |
+++ b/src/isolate.cc |
@@ -2486,6 +2486,31 @@ bool Isolate::use_crankshaft() const { |
CpuFeatures::SupportsCrankshaft(); |
} |
+bool Isolate::ArrayOrObjectPrototypeIsInContext(Object* object) { |
Toon Verwaest
2016/04/05 12:57:26
IsArrayOrObjectPrototype
|
+ 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(); |
@@ -2559,56 +2584,70 @@ 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() && it.state() != LookupIterator::JSPROXY) { |
+ MaybeHandle<Object> maybe_value = Object::GetProperty(&it); |
Toon Verwaest
2016/04/05 12:57:26
GetDataProperty avoids side effects. You can't jus
|
+ if (maybe_value.ToHandle(&value) && !value->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 (!IsFastArrayConstructorPrototypeChainIntact()) return; |
+ if (!object->map()->is_prototype_map()) return; |
Toon Verwaest
2016/04/05 12:57:26
This check is probably faster (and will generally
|
+ if (!ArrayOrObjectPrototypeIsInContext(*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); |
} |