Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 2f84975d6fa77d9ecf1e3f0aa9aaa9378027f24f..d2b988acf6d2ecd0c99ba6816b32bfee49190462 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -2923,6 +2923,25 @@ Handle<Object> JSReceiver::SetPropertyWithDefinedSetter( |
| } |
| +bool JSReceiver::MayHaveIndexedCallbacksInPrototypeChain() { |
| + Heap* heap = GetHeap(); |
| + for (Object* pt = GetPrototype(); |
| + pt != heap->null_value(); |
| + pt = pt->GetPrototype(GetIsolate())) { |
| + if (pt->IsJSProxy()) { |
| + // Be conservative, don't walk into proxies. |
| + return true; |
| + } |
| + |
| + if (JSObject::cast(pt)->map()->has_element_callbacks()) { |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
| + |
| MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( |
| uint32_t index, |
| Object* value, |
| @@ -6204,12 +6223,14 @@ void JSObject::SetElementCallback(Handle<JSObject> object, |
| Handle<Object> structure, |
| PropertyAttributes attributes) { |
| Heap* heap = object->GetHeap(); |
| + Handle<Map> old_map(object->map()); |
| PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| // Normalize elements to make this operation simple. |
| Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| ASSERT(object->HasDictionaryElements() || |
| object->HasDictionaryArgumentsElements()); |
| + bool map_changed = object->map() != *old_map; |
| // Update the dictionary with the new CALLBACKS property. |
| dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| @@ -6231,6 +6252,34 @@ void JSObject::SetElementCallback(Handle<JSObject> object, |
| } else { |
| object->set_elements(*dictionary); |
| } |
| + |
| + if (!object->map()->has_element_callbacks()) { |
| + if (!map_changed) { |
| + Handle<Map> new_map = Map::Copy(handle(object->map())); |
| + object->set_map(*new_map); |
| + } |
| + object->map()->set_has_element_callbacks(true); |
|
danno
2013/10/23 12:22:11
This isn't quite right. You might "pollute" normal
|
| + } |
| + |
| + // If we are the array prototype object, rebuild the cache. |
| + Isolate* isolate = object->GetIsolate(); |
| + if (isolate->initial_array_prototype().is_identical_to(object)) { |
| + // Install the initial map, new_ek_map in the function prototype for |
|
danno
2013/10/23 12:22:11
Is this comment correct?
|
| + // array. |
| + Handle<JSFunction> array_function( |
| + isolate->global_context()->array_function(), isolate); |
| + JSFunction::SetPrototype(array_function, object); |
|
danno
2013/10/23 12:22:11
You are "rebuilding the cache" by side effect, whi
|
| + } else if (isolate->initial_object_prototype().is_identical_to(object)) { |
| + Handle<JSFunction> object_function( |
| + isolate->global_context()->object_function(), isolate); |
| + JSFunction::SetPrototype(object_function, object); |
| + } |
| + |
| + // TODO(mvstanton): With a dependency group we can avoid the need to |
| + // deoptimize code that doesn't depend on the changed maps. Address this |
| + // in a follow-up checkin. |
| + Deoptimizer::DeoptimizeAll(object->GetIsolate()); |
|
danno
2013/10/23 12:22:11
Oh, *the humanity* Are you sure it can't be in thi
|
| + object->GetHeap()->ClearAllKeyedStoreICs(); |
| } |
| @@ -10560,6 +10609,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) | |
| @@ -10568,7 +10627,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()); |
| + } |
| } |
| } |
| } |
| @@ -12738,8 +12799,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() || |