Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index f7c89175da75c2fb7916015a34adf9954b565eef..cd5a5ee7d79aa40d6d6748465c4dc657f1b5dacf 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -6230,6 +6230,30 @@ bool JSObject::CanSetCallback(Name* name) { |
| } |
| +bool Map::DictionaryElementsInPrototypeChain() { |
| + Heap* heap = GetHeap(); |
| + |
| + if (IsDictionaryElementsKind(elements_kind())) { |
| + return true; |
| + } |
| + |
| + for (Object* prototype = this->prototype(); |
| + prototype != heap->null_value(); |
| + prototype = prototype->GetPrototype(GetIsolate())) { |
| + if (prototype->IsJSProxy()) { |
| + // Be conservative, don't walk into proxies. |
| + return true; |
| + } |
| + |
| + if (IsDictionaryElementsKind( |
| + JSObject::cast(prototype)->map()->elements_kind())) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
|
danno
2013/11/04 17:44:44
nit: two returns between functions
mvstanton
2013/11/05 09:06:51
Done.
|
| void JSObject::SetElementCallback(Handle<JSObject> object, |
| uint32_t index, |
| Handle<Object> structure, |
| @@ -10577,6 +10601,16 @@ void Code::ReplaceNthCell(int n, Cell* replace_with) { |
| void Code::ClearInlineCaches() { |
| + ClearInlineCaches(NULL); |
| +} |
| + |
| + |
| +void Code::ClearInlineCaches(Code::Kind kind) { |
| + ClearInlineCaches(&kind); |
| +} |
| + |
| + |
| +void Code::ClearInlineCaches(Code::Kind* kind) { |
| int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
| RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | |
| @@ -10585,7 +10619,9 @@ void Code::ClearInlineCaches() { |
| RelocInfo* info = it.rinfo(); |
| Code* target(Code::GetCodeFromTargetAddress(info->target_address())); |
| if (target->is_inline_cache_stub()) { |
| - IC::Clear(this->GetIsolate(), info->pc()); |
| + if (kind == NULL || *kind == target->kind()) { |
| + IC::Clear(this->GetIsolate(), info->pc()); |
| + } |
| } |
| } |
| } |
| @@ -11758,6 +11794,8 @@ Handle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
| } |
| } |
| + bool dictionary_elements_in_chain = |
| + object->map()->DictionaryElementsInPrototypeChain(); |
| Handle<JSObject> real_receiver = object; |
| if (skip_hidden_prototypes) { |
| @@ -11790,6 +11828,14 @@ Handle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
| ASSERT(new_map->prototype() == *value); |
| real_receiver->set_map(*new_map); |
| + if (!dictionary_elements_in_chain && |
| + new_map->DictionaryElementsInPrototypeChain()) { |
| + // If the prototype chain didn't previously have element callbacks, then |
| + // KeyedStoreICs need to be cleared to ensure any that involve this |
| + // map go generic. |
| + object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); |
| + } |
| + |
| heap->ClearInstanceofCache(); |
| ASSERT(size == object->Size()); |
| return value; |
| @@ -12778,9 +12824,11 @@ MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
| } |
| if (from_kind == to_kind) return this; |
| - |
| - MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| - if (maybe_failure->IsFailure()) return maybe_failure; |
| + // Don't update the site if to_kind isn't fast |
| + if (IsFastElementsKind(to_kind)) { |
| + MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| + if (maybe_failure->IsFailure()) return maybe_failure; |
| + } |
| Isolate* isolate = GetIsolate(); |
| if (elements() == isolate->heap()->empty_fixed_array() || |