Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(936)

Unified Diff: src/isolate.cc

Issue 1409123003: [runtime] Avoid @@isConcatSpreadable lookup for fast path Array.prototype.concat (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: merging with master Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698