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

Unified Diff: src/ic/ic.cc

Issue 2449463002: [ic] Load IC data handlers now support prototype chain checks with global and dictionary objects. (Closed)
Patch Set: Addressing comments and fixing the handlers in new space issue Created 4 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
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ic/ic.cc
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
index b75e73b5fa1f70dd9e8cd4139834448eb26cf627..82d14f147cc4e1866ce986c1a45cd09d5b139372 100644
--- a/src/ic/ic.cc
+++ b/src/ic/ic.cc
@@ -846,36 +846,77 @@ Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
return stub.GetCode();
}
-bool LoadIC::IsPrototypeValidityCellCheckEnough(Handle<Map> receiver_map,
- Handle<JSObject> holder) {
+namespace {
+
+template <bool fill_array>
+int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
+ Handle<JSObject> holder, Handle<FixedArray> array,
+ Handle<Name> name) {
DCHECK(holder->HasFastProperties());
// The following kinds of receiver maps require custom handler compilation.
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() ||
receiver_map->IsJSGlobalObjectMap()) {
- return false;
+ return -1;
}
+ HandleScope scope(isolate);
+ int checks_count = 0;
+
// Switch to custom compiled handler if the prototype chain contains global
// or dictionary objects.
- for (PrototypeIterator iter(*receiver_map); !iter.IsAtEnd(); iter.Advance()) {
- JSObject* current = iter.GetCurrent<JSObject>();
- if (current == *holder) break;
- Map* current_map = current->map();
+ for (PrototypeIterator iter(receiver_map); !iter.IsAtEnd(); iter.Advance()) {
+ Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
+ if (*current == *holder) break;
+ Handle<Map> current_map(current->map(), isolate);
+
+ // Only global objects and objects that do not require access
+ // checks are allowed in stubs.
+ DCHECK(current_map->IsJSGlobalProxyMap() ||
+ !current_map->is_access_check_needed());
+
if (current_map->IsJSGlobalObjectMap()) {
- return false;
+ if (fill_array) {
+ Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
+ Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
+ global, name, PropertyCellType::kInvalidated);
+ DCHECK(cell->value()->IsTheHole(isolate));
+ Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
+ array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
+ *weak_cell);
+ }
+ checks_count++;
+
} else if (current_map->is_dictionary_map()) {
DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
- return false;
+ if (fill_array) {
+ DCHECK_EQ(NameDictionary::kNotFound,
+ current->property_dictionary()->FindEntry(name));
+ Handle<WeakCell> weak_cell =
+ Map::GetOrCreatePrototypeWeakCell(current, isolate);
+ array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
+ *weak_cell);
+ }
+ checks_count++;
}
}
- return true;
+ return checks_count;
+}
+
+} // namespace
+
+int LoadIC::GetPrototypeCheckCount(Handle<Map> receiver_map,
+ Handle<JSObject> holder) {
+ return InitPrototypeChecks<false>(isolate(), receiver_map, holder,
+ Handle<FixedArray>(), Handle<Name>());
}
Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map,
Handle<JSObject> holder,
+ Handle<Name> name,
Handle<Object> smi_handler) {
- DCHECK(IsPrototypeValidityCellCheckEnough(receiver_map, holder));
+ int checks_count = GetPrototypeCheckCount(receiver_map, holder);
+ DCHECK_LE(0, checks_count);
if (receiver_map->IsJSGlobalProxyMap() ||
receiver_map->IsJSGlobalObjectMap()) {
@@ -891,8 +932,19 @@ Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map,
Handle<WeakCell> holder_cell =
Map::GetOrCreatePrototypeWeakCell(holder, isolate());
- return isolate()->factory()->NewTuple3(validity_cell, holder_cell,
- smi_handler);
+
+ if (checks_count == 0) {
+ return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
+ validity_cell);
+ }
+ Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
+ LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
+ handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
+ handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
+ handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
+ InitPrototypeChecks<true>(isolate(), receiver_map, holder, handler_array,
+ name);
+ return handler_array;
}
bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
@@ -1230,10 +1282,10 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
if (receiver_is_holder) {
return smi_handler;
}
- if (FLAG_tf_load_ic_stub &&
- IsPrototypeValidityCellCheckEnough(map, holder)) {
+ if (FLAG_tf_load_ic_stub && GetPrototypeCheckCount(map, holder) >= 0) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
- return SimpleLoadFromPrototype(map, holder, smi_handler);
+ return SimpleLoadFromPrototype(map, holder, lookup->name(),
+ smi_handler);
}
break; // Custom-compiled handler.
}
@@ -1247,9 +1299,10 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
return smi_handler;
}
- if (IsPrototypeValidityCellCheckEnough(map, holder)) {
+ if (GetPrototypeCheckCount(map, holder) >= 0) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
- return SimpleLoadFromPrototype(map, holder, smi_handler);
+ return SimpleLoadFromPrototype(map, holder, lookup->name(),
+ smi_handler);
}
} else {
if (receiver_is_holder) {
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698