| Index: src/ic/ic.cc
|
| diff --git a/src/ic/ic.cc b/src/ic/ic.cc
|
| index eea4629d048ca25da6f089495ef9c3643b4aa8d3..005e3e7403b5e0508d4b291821b10b7f0c078d31 100644
|
| --- a/src/ic/ic.cc
|
| +++ b/src/ic/ic.cc
|
| @@ -831,6 +831,7 @@ Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
|
|
|
| Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
|
| if (FLAG_tf_load_ic_stub) {
|
| + TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
|
| return handle(Smi::FromInt(index.GetLoadByFieldOffset()), isolate());
|
| }
|
| TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
|
| @@ -838,6 +839,46 @@ 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();
|
| +
|
| + 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();
|
| + }
|
| +
|
| + // 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();
|
| + if (current_map->IsJSGlobalObjectMap() ||
|
| + current_map->IsJSGlobalProxyMap() || current_map->is_dictionary_map()) {
|
| + return Handle<Object>::null();
|
| + }
|
| + // 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);
|
| + Handle<Cell> validity_cell =
|
| + Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
|
| + DCHECK(!validity_cell.is_null());
|
| +
|
| + Handle<Object> handler(Smi::FromInt(index.GetLoadByFieldOffset()), isolate());
|
| + DCHECK(handler->IsSmi());
|
| +
|
| + Factory* factory = isolate()->factory();
|
| +
|
| + Handle<WeakCell> holder_cell = factory->NewWeakCell(holder);
|
| + return factory->NewTuple3(validity_cell, holder_cell, handler);
|
| +}
|
|
|
| bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
|
| DCHECK(lookup->state() == LookupIterator::ACCESSOR);
|
| @@ -1142,6 +1183,11 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
|
| if (receiver_is_holder) {
|
| return SimpleFieldLoad(field);
|
| }
|
| + Handle<Object> handler =
|
| + SimpleFieldLoadFromPrototype(field, map, holder);
|
| + if (!handler.is_null()) {
|
| + return handler;
|
| + }
|
| break; // Custom-compiled handler.
|
| }
|
|
|
|
|