| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 9cee8db2ba79d92adb820c0af6800f66a58c799e..cc009c0fe83fbada12cb9be09b13a79947c03be8 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -2482,6 +2482,64 @@ bool Isolate::use_crankshaft() const {
|
| CpuFeatures::SupportsCrankshaft();
|
| }
|
|
|
| +Context* Isolate::ContextForArrayOrObjectPrototype(Handle<JSObject> object) {
|
| + Object* context = heap()->native_contexts_list();
|
| + while (!context->IsUndefined()) {
|
| + Context* current_context = Context::cast(context);
|
| + if (current_context->initial_object_prototype() == *object ||
|
| + current_context->initial_array_prototype() == *object) {
|
| + return current_context;
|
| + }
|
| + context = current_context->get(Context::NEXT_CONTEXT_LINK);
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +bool Isolate::IsArrayIsConcatSpreadableSet() {
|
| + PropertyCell* is_concat_spreadable_cell =
|
| + heap()->array_is_concat_spreadable_protector();
|
| + bool is_concat_spreadable_set =
|
| + is_concat_spreadable_cell->value()->IsSmi() &&
|
| + Smi::cast(is_concat_spreadable_cell->value())->value() ==
|
| + kArrayIsConcatSpreadableProtectorInvalid;
|
| +#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);
|
| + 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 true;
|
| + }
|
| + }
|
| +#endif // DEBUG
|
| + return is_concat_spreadable_set;
|
| +}
|
| +
|
| +void Isolate::UpdateArrayIsConcatSpreadableProtectorOnAddProperty(
|
| + Handle<JSObject> object, Handle<Name> name) {
|
| + // The invalidate the is_concat_spreadable_protector invalidation is a one-way
|
| + // action.
|
| + if (IsArrayIsConcatSpreadableSet()) return;
|
| + if (!object->map()->is_prototype_map()) return;
|
| + Handle<Name> key = factory()->is_concat_spreadable_symbol();
|
| + if (!Name::Equals(name, key)) return;
|
| + Context* context = ContextForArrayOrObjectPrototype(object);
|
| + if (context == NULL) return;
|
| + PropertyCell::SetValueWithInvalidation(
|
| + factory()->array_is_concat_spreadable_protector(),
|
| + handle(Smi::FromInt(kArrayProtectorInvalid), this));
|
| +}
|
|
|
| bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
|
| PropertyCell* no_elements_cell = heap()->array_protector();
|
| @@ -2571,38 +2629,27 @@ void Isolate::InvalidateArraySpeciesProtector() {
|
|
|
| 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;
|
| + Context* context = ContextForArrayOrObjectPrototype(object);
|
| + if (context == NULL) return;
|
| + PropertyCell::SetValueWithInvalidation(
|
| + factory()->array_protector(),
|
| + handle(Smi::FromInt(kArrayProtectorInvalid), this));
|
| }
|
|
|
|
|
| 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);
|
| + DisallowHeapAllocation no_gc;
|
| + JSArray* raw_array = *array;
|
| + if (!raw_array->map()->is_prototype_map()) return false;
|
| + Object* context = heap()->native_contexts_list();
|
| + while (!context->IsUndefined()) {
|
| + Context* current_context = Context::cast(context);
|
| + if (current_context->initial_array_prototype() == raw_array) {
|
| + return true;
|
| }
|
| + context = current_context->get(Context::NEXT_CONTEXT_LINK);
|
| }
|
| return false;
|
| }
|
|
|