| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 5ea9b5a4e490a3faae793e3da5a18e0d4d37463e..4e169cfa80cc58dff7de46bdd60982bc97fc3e80 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -6219,6 +6219,31 @@ bool JSObject::CanSetCallback(Name* name) {
|
| }
|
|
|
|
|
| +bool Map::DictionaryElementsInPrototypeChainOnly() {
|
| + Heap* heap = GetHeap();
|
| +
|
| + if (IsDictionaryElementsKind(elements_kind())) {
|
| + return false;
|
| + }
|
| +
|
| + 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;
|
| +}
|
| +
|
| +
|
| void JSObject::SetElementCallback(Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> structure,
|
| @@ -6227,6 +6252,7 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
|
| PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
|
|
|
| // Normalize elements to make this operation simple.
|
| + bool had_dictionary_elements = object->HasDictionaryElements();
|
| Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
|
| ASSERT(object->HasDictionaryElements() ||
|
| object->HasDictionaryArgumentsElements());
|
| @@ -6250,6 +6276,11 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
|
| parameter_map->set(1, *dictionary);
|
| } else {
|
| object->set_elements(*dictionary);
|
| +
|
| + if (!had_dictionary_elements) {
|
| + // KeyedStoreICs (at least the non-generic ones) need a reset.
|
| + heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
|
| + }
|
| }
|
| }
|
|
|
| @@ -10609,6 +10640,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) |
|
| @@ -10617,7 +10658,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());
|
| + }
|
| }
|
| }
|
| }
|
| @@ -11790,6 +11833,8 @@ Handle<Object> JSObject::SetPrototype(Handle<JSObject> object,
|
| }
|
| }
|
|
|
| + bool dictionary_elements_in_chain =
|
| + object->map()->DictionaryElementsInPrototypeChainOnly();
|
| Handle<JSObject> real_receiver = object;
|
|
|
| if (skip_hidden_prototypes) {
|
| @@ -11822,6 +11867,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->DictionaryElementsInPrototypeChainOnly()) {
|
| + // 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;
|
| @@ -12810,9 +12863,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() ||
|
|
|