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

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: simplifications Created 5 years, 2 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 aeaf82ed829f5525edc4384f3bd361d307177876..6d37d1d7d7634e9b24f37fdea2f85b3d26d4b750 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -2433,20 +2433,83 @@ bool Isolate::use_crankshaft() const {
}
+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) {
+ //
+ return is_concat_spreadable_set;
+ }
+
+ Handle<Object> array_prototype(array_function()->prototype(), this);
+ Handle<Symbol> key(factory()->is_concat_spreadable_symbol());
+ Handle<Object> value;
+ MaybeHandle<Object> maybeValue =
+ i::Runtime::GetObjectProperty(this, array_prototype, key);
+ if (maybeValue.ToHandle(&value) && !value->IsUndefined()) {
Toon Verwaest 2015/11/02 12:32:45 Plus o[@@isConcatSpreadable] = undefined
Camillo Bruni 2015/11/03 14:49:25 ?
+ // 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());
Toon Verwaest 2015/11/02 12:32:45 key = factory()->is_concat_spreadable_symbol();
Camillo Bruni 2015/11/03 14:49:25 right
+ 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(kArrayElementsProtectorInvalid), this));
+}
+
+
bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
- PropertyCell* no_elements_cell = heap()->array_protector();
- bool cell_reports_intact =
- no_elements_cell->value()->IsSmi() &&
- Smi::cast(no_elements_cell->value())->value() == kArrayProtectorValid;
+ PropertyCell* no_elements_cell = heap()->array_elements_protector();
+ bool cell_reports_intact = no_elements_cell->value()->IsSmi() &&
+ Smi::cast(no_elements_cell->value())->value() ==
+ kArrayElementsProtectorValid;
#ifdef DEBUG
Map* root_array_map =
get_initial_js_array_map(GetInitialFastElementsKind());
Context* native_context = context()->native_context();
- JSObject* initial_array_proto = JSObject::cast(
- native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
- JSObject* initial_object_proto = JSObject::cast(
- native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
+ JSObject* initial_array_proto =
+ JSObject::cast(native_context->initial_array_prototype());
+ JSObject* initial_object_proto =
+ JSObject::cast(native_context->initial_object_prototype());
if (root_array_map == NULL || initial_array_proto == initial_object_proto) {
// We are in the bootstrapping process, and the entire check sequence
@@ -2457,34 +2520,34 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
// Check that the array prototype hasn't been altered WRT empty elements.
if (root_array_map->prototype() != initial_array_proto) {
DCHECK_EQ(false, cell_reports_intact);
- return cell_reports_intact;
+ return false;
}
FixedArrayBase* elements = initial_array_proto->elements();
if (elements != heap()->empty_fixed_array() &&
elements != heap()->empty_slow_element_dictionary()) {
DCHECK_EQ(false, cell_reports_intact);
- return cell_reports_intact;
+ return false;
}
// Check that the object prototype hasn't been altered WRT empty elements.
PrototypeIterator iter(this, initial_array_proto);
if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
DCHECK_EQ(false, cell_reports_intact);
- return cell_reports_intact;
+ return false;
}
elements = initial_object_proto->elements();
if (elements != heap()->empty_fixed_array() &&
elements != heap()->empty_slow_element_dictionary()) {
DCHECK_EQ(false, cell_reports_intact);
- return cell_reports_intact;
+ return false;
}
iter.Advance();
if (!iter.IsAtEnd()) {
DCHECK_EQ(false, cell_reports_intact);
- return cell_reports_intact;
+ return false;
}
#endif
@@ -2494,37 +2557,25 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
- 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) {
- 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_elements_protector(),
+ handle(Smi::FromInt(kArrayElementsProtectorInvalid), 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);
+ if (!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() == *array) {
+ return true;
}
+ context = current_context->get(Context::NEXT_CONTEXT_LINK);
}
return false;
}

Powered by Google App Engine
This is Rietveld 408576698