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 { ...@@ -730,6 +730,7 @@ class RuntimeCallTimer {
V(LoadIC_LoadApiGetterStub) \ V(LoadIC_LoadApiGetterStub) \
V(LoadIC_LoadCallback) \ V(LoadIC_LoadCallback) \
V(LoadIC_LoadConstantDH) \ V(LoadIC_LoadConstantDH) \
V(LoadIC_LoadConstantFromPrototypeDH) \
V(LoadIC_LoadConstant) \ V(LoadIC_LoadConstant) \
V(LoadIC_LoadConstantStub) \ V(LoadIC_LoadConstantStub) \
V(LoadIC_LoadFieldDH) \ V(LoadIC_LoadFieldDH) \
......
...@@ -857,18 +857,15 @@ Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { ...@@ -857,18 +857,15 @@ Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
return stub.GetCode(); return stub.GetCode();
} }
Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index, bool LoadIC::IsPrototypeValidityCellCheckEnough(Handle<Map> receiver_map,
Handle<Map> receiver_map, Handle<JSObject> holder) {
Handle<JSObject> holder) {
if (!FLAG_tf_load_ic_stub) return Handle<Object>::null();
DCHECK(holder->HasFastProperties()); DCHECK(holder->HasFastProperties());
// The following kinds of receiver maps require custom handler compilation. // The following kinds of receiver maps require custom handler compilation.
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() || if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() ||
receiver_map->IsJSGlobalObjectMap() || receiver_map->IsJSGlobalObjectMap() ||
receiver_map->is_dictionary_map()) { receiver_map->is_dictionary_map()) {
return Handle<Object>::null(); return false;
} }
// Switch to custom compiled handler if the prototype chain contains global // Switch to custom compiled handler if the prototype chain contains global
...@@ -879,21 +876,27 @@ Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index, ...@@ -879,21 +876,27 @@ Handle<Object> LoadIC::SimpleFieldLoadFromPrototype(FieldIndex index,
Map* current_map = current->map(); Map* current_map = current->map();
if (current_map->IsJSGlobalObjectMap() || if (current_map->IsJSGlobalObjectMap() ||
current_map->IsJSGlobalProxyMap() || current_map->is_dictionary_map()) { 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. // Only objects that do not require access checks are allowed in stubs.
DCHECK(!current_map->is_access_check_needed()); 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 = Handle<Cell> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
DCHECK(!validity_cell.is_null()); DCHECK(!validity_cell.is_null());
Handle<Object> handler(SmiHandler::MakeLoadFieldHandler(isolate(), index));
Factory* factory = isolate()->factory(); Factory* factory = isolate()->factory();
Handle<WeakCell> holder_cell = factory->NewWeakCell(holder); 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) { bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
...@@ -1196,28 +1199,37 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1196,28 +1199,37 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
// -------------- Fields -------------- // -------------- Fields --------------
if (lookup->property_details().type() == DATA) { if (lookup->property_details().type() == DATA) {
FieldIndex field = lookup->GetFieldIndex(); FieldIndex field = lookup->GetFieldIndex();
Handle<Object> smi_handler = SimpleFieldLoad(field);
if (receiver_is_holder) { if (receiver_is_holder) {
return SimpleFieldLoad(field); return smi_handler;
} }
Handle<Object> handler = if (FLAG_tf_load_ic_stub &&
SimpleFieldLoadFromPrototype(field, map, holder); IsPrototypeValidityCellCheckEnough(map, holder)) {
if (!handler.is_null()) { TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
return handler; return SimpleLoadFromPrototype(map, holder, smi_handler);
} }
break; // Custom-compiled handler. break; // Custom-compiled handler.
} }
// -------------- Constant properties -------------- // -------------- Constant properties --------------
DCHECK(lookup->property_details().type() == DATA_CONSTANT); 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); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
return SmiHandler::MakeLoadConstantHandler( return smi_handler;
isolate(), lookup->GetConstantIndex()); }
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. break; // Custom-compiled handler.
} }
......
...@@ -310,9 +310,18 @@ class LoadIC : public IC { ...@@ -310,9 +310,18 @@ class LoadIC : public IC {
private: private:
Handle<Object> SimpleFieldLoad(FieldIndex index); Handle<Object> SimpleFieldLoad(FieldIndex index);
Handle<Object> SimpleFieldLoadFromPrototype(FieldIndex index,
Handle<Map> receiver_map, // Returns true if the validity cell check is enough to ensure that the
Handle<JSObject> holder); // 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; 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