Commit 5acc31d8 authored by ishell's avatar ishell Committed by Commit bot

[ic] Support data handlers that represent loads of constants from prototypes.

BUG=

Review-Url: https://codereview.chromium.org/2421883002
Cr-Commit-Position: refs/heads/master@{#40325}
parent d4a47fe6
......@@ -730,6 +730,7 @@ class RuntimeCallTimer {
V(LoadIC_LoadApiGetterStub) \
V(LoadIC_LoadCallback) \
V(LoadIC_LoadConstantDH) \
V(LoadIC_LoadConstantFromPrototypeDH) \
V(LoadIC_LoadConstant) \
V(LoadIC_LoadConstantStub) \
V(LoadIC_LoadFieldDH) \
......
......@@ -857,18 +857,15 @@ Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
return stub.GetCode();
}
Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index,
Handle<Map> receiver_map,
Handle<JSObject> holder) {
if (!FLAG_tf_load_ic_stub) return Handle<Object>::null();
bool LoadIC::IsPrototypeValidityCellCheckEnough(Handle<Map> receiver_map,
Handle<JSObject> holder) {
DCHECK(holder->HasFastProperties());
// The following kinds of receiver maps require custom handler compilation.
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() ||
receiver_map->IsJSGlobalObjectMap() ||
receiver_map->is_dictionary_map()) {
return Handle<Object>::null();
return false;
}
// Switch to custom compiled handler if the prototype chain contains global
......@@ -879,21 +876,27 @@ Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index,
Map* current_map = current->map();
if (current_map->IsJSGlobalObjectMap() ||
current_map->IsJSGlobalProxyMap() || current_map->is_dictionary_map()) {
return Handle<Object>::null();
return false;
}
// Only objects that do not require access checks are allowed in stubs.
DCHECK(!current_map->is_access_check_needed());
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
return true;
}
Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map,
Handle<JSObject> holder,
Handle<Object> smi_handler) {
DCHECK(IsPrototypeValidityCellCheckEnough(receiver_map, holder));
Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
DCHECK(!validity_cell.is_null());
Handle<Object> handler(SmiHandler::MakeLoadFieldHandler(isolate(), index));
Factory* factory = isolate()->factory();
Handle<WeakCell> holder_cell = factory->NewWeakCell(holder);
return factory->NewTuple3(validity_cell, holder_cell, handler);
return factory->NewTuple3(validity_cell, holder_cell, smi_handler);
}
bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
......@@ -1196,28 +1199,37 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
// -------------- Fields --------------
if (lookup->property_details().type() == DATA) {
FieldIndex field = lookup->GetFieldIndex();
Handle<Object> smi_handler = SimpleFieldLoad(field);
if (receiver_is_holder) {
return SimpleFieldLoad(field);
return smi_handler;
}
Handle<Object> handler =
SimpleFieldLoadFromPrototype(field, map, holder);
if (!handler.is_null()) {
return handler;
if (FLAG_tf_load_ic_stub &&
IsPrototypeValidityCellCheckEnough(map, holder)) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
return SimpleLoadFromPrototype(map, holder, smi_handler);
}
break; // Custom-compiled handler.
}
// -------------- Constant properties --------------
DCHECK(lookup->property_details().type() == DATA_CONSTANT);
if (receiver_is_holder) {
if (FLAG_tf_load_ic_stub) {
if (FLAG_tf_load_ic_stub) {
Handle<Object> smi_handler = SmiHandler::MakeLoadConstantHandler(
isolate(), lookup->GetConstantIndex());
if (receiver_is_holder) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
return SmiHandler::MakeLoadConstantHandler(
isolate(), lookup->GetConstantIndex());
return smi_handler;
}
if (IsPrototypeValidityCellCheckEnough(map, holder)) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
return SimpleLoadFromPrototype(map, holder, smi_handler);
}
} else {
if (receiver_is_holder) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
return stub.GetCode();
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
return stub.GetCode();
}
break; // Custom-compiled handler.
}
......
......@@ -310,9 +310,18 @@ class LoadIC : public IC {
private:
Handle<Object> SimpleFieldLoad(FieldIndex index);
Handle<Object> SimpleFieldLoadFromPrototype(FieldIndex index,
Handle<Map> receiver_map,
Handle<JSObject> holder);
// Returns true if the validity cell check is enough to ensure that the
// prototype chain from |receiver_map| till |holder| did not change.
bool IsPrototypeValidityCellCheckEnough(Handle<Map> receiver_map,
Handle<JSObject> holder);
// Creates a data handler that represents a prototype chain check followed
// by given Smi-handler that encoded a load from the holder.
// Can be used only if IsPrototypeValidityCellCheckEnough() predicate is true.
Handle<Object> SimpleLoadFromPrototype(Handle<Map> receiver_map,
Handle<JSObject> holder,
Handle<Object> smi_handler);
friend class IC;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment