| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index be362d2a4b90967be70fa4d46939123a37006be0..07ab99442c7209545efa7c2a080cca0732403291 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -300,7 +300,8 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
|
| break;
|
| }
|
|
|
| - Map* map = IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map();
|
| + Handle<Map> map(
|
| + IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map());
|
|
|
| // Decide whether the inline cache failed because of changes to the
|
| // receiver itself or changes to one of its prototypes.
|
| @@ -314,13 +315,7 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
|
| if (index >= 0) {
|
| map->RemoveFromCodeCache(*name, *target(), index);
|
| // Handlers are stored in addition to the ICs on the map. Remove those, too.
|
| - Code* handler = target()->FindFirstHandler();
|
| - if (handler != NULL) {
|
| - index = map->IndexInCodeCache(*name, handler);
|
| - if (index >= 0) {
|
| - map->RemoveFromCodeCache(*name, handler, index);
|
| - }
|
| - }
|
| + TryRemoveInvalidHandlers(map, name);
|
| return true;
|
| }
|
|
|
| @@ -334,7 +329,7 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
|
| // the map cannot be deprecated and the stub invalidated.
|
| if (cache_holder == OWN_MAP) {
|
| Map* old_map = target()->FindFirstMap();
|
| - if (old_map == map) return true;
|
| + if (old_map == *map) return true;
|
| if (old_map != NULL) {
|
| if (old_map->is_deprecated()) return true;
|
| if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
|
| @@ -357,8 +352,30 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
|
| }
|
|
|
|
|
| +void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
|
| + CodeHandleList handlers;
|
| + target()->FindHandlers(&handlers);
|
| + for (int i = 0; i < handlers.length(); i++) {
|
| + Handle<Code> handler = handlers.at(i);
|
| + int index = map->IndexInCodeCache(*name, *handler);
|
| + if (index >= 0) {
|
| + map->RemoveFromCodeCache(*name, *handler, index);
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
|
| - if (state() != MONOMORPHIC || !name->IsString()) return;
|
| + if (!name->IsString()) return;
|
| + if (state() != MONOMORPHIC) {
|
| + if (state() == POLYMORPHIC && receiver->IsHeapObject()) {
|
| + TryRemoveInvalidHandlers(
|
| + handle(Handle<HeapObject>::cast(receiver)->map()),
|
| + Handle<String>::cast(name));
|
| + }
|
| + return;
|
| + }
|
| if (receiver->IsUndefined() || receiver->IsNull()) return;
|
|
|
| // Remove the target from the code cache if it became invalid
|
| @@ -1122,7 +1139,6 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
| code = slow_stub();
|
| } else {
|
| code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name);
|
| - if (code.is_null()) code = slow_stub();
|
| }
|
|
|
| PatchCache(receiver, name, code);
|
| @@ -1141,11 +1157,29 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
| Handle<JSObject> receiver,
|
| Handle<String> name) {
|
| if (!lookup->IsProperty()) {
|
| - // Nonexistent property. The result is undefined.
|
| - return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
|
| + return kind() == Code::LOAD_IC
|
| + ? isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver)
|
| + : generic_stub();
|
| }
|
|
|
| - // Compute monomorphic stub.
|
| + Handle<Code> code = isolate()->stub_cache()->FindHandler(
|
| + name, receiver, kind());
|
| + if (!code.is_null()) return code;
|
| +
|
| + code = CompileLoadHandler(lookup, receiver, name);
|
| + if (code.is_null()) return slow_stub();
|
| +
|
| + if (code->is_handler() && code->type() != Code::NORMAL) {
|
| + HeapObject::UpdateMapCodeCache(receiver, name, code);
|
| + }
|
| +
|
| + return code;
|
| +}
|
| +
|
| +
|
| +Handle<Code> LoadIC::CompileLoadHandler(LookupResult* lookup,
|
| + Handle<JSObject> receiver,
|
| + Handle<String> name) {
|
| Handle<JSObject> holder(lookup->holder());
|
| switch (lookup->type()) {
|
| case FIELD:
|
| @@ -1356,12 +1390,9 @@ MaybeObject* KeyedLoadIC::Load(Handle<Object> object,
|
| }
|
|
|
|
|
| -Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
|
| +Handle<Code> KeyedLoadIC::CompileLoadHandler(LookupResult* lookup,
|
| Handle<JSObject> receiver,
|
| Handle<String> name) {
|
| - // Bail out if we didn't find a result.
|
| - if (!lookup->IsProperty()) return Handle<Code>::null();
|
| -
|
| // Compute a monomorphic stub.
|
| Handle<JSObject> holder(lookup->holder(), isolate());
|
| switch (lookup->type()) {
|
| @@ -1603,10 +1634,6 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| ASSERT(!lookup->IsHandler());
|
|
|
| Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value);
|
| - if (code.is_null()) {
|
| - set_target(*generic_stub());
|
| - return;
|
| - }
|
|
|
| PatchCache(receiver, name, code);
|
| TRACE_IC("StoreIC", name);
|
| @@ -1617,6 +1644,25 @@ Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup,
|
| Handle<JSObject> receiver,
|
| Handle<String> name,
|
| Handle<Object> value) {
|
| + Handle<Code> code = isolate()->stub_cache()->FindHandler(
|
| + name, receiver, kind(), strict_mode());
|
| + if (!code.is_null()) return code;
|
| +
|
| + code = CompileStoreHandler(lookup, receiver, name, value);
|
| + if (code.is_null()) return generic_stub();
|
| +
|
| + if (code->is_handler() && code->type() != Code::NORMAL) {
|
| + HeapObject::UpdateMapCodeCache(receiver, name, code);
|
| + }
|
| +
|
| + return code;
|
| +}
|
| +
|
| +
|
| +Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
|
| + Handle<JSObject> receiver,
|
| + Handle<String> name,
|
| + Handle<Object> value) {
|
| Handle<JSObject> holder(lookup->holder());
|
| switch (lookup->type()) {
|
| case FIELD:
|
| @@ -2005,7 +2051,7 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
|
| }
|
|
|
|
|
| -Handle<Code> KeyedStoreIC::ComputeStoreHandler(LookupResult* lookup,
|
| +Handle<Code> KeyedStoreIC::CompileStoreHandler(LookupResult* lookup,
|
| Handle<JSObject> receiver,
|
| Handle<String> name,
|
| Handle<Object> value) {
|
|
|