Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index cfeecadf7b581b87006fcab43eb6963099e2e5d3..3caaf2f0baa853f2a2353e64ee7dd01c5fde4390 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -634,7 +634,7 @@ Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) { |
| if (IsGlobalObject()) { |
| PropertyCell* cell = PropertyCell::cast( |
| property_dictionary()->ValueAt(result->GetDictionaryEntry())); |
| - cell->set_value(value); |
| + cell->set_value_infer_type(value); |
| } else { |
| property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
| } |
| @@ -661,8 +661,7 @@ MaybeObject* JSObject::SetNormalizedProperty(Name* name, |
| Object* store_value = value; |
| if (IsGlobalObject()) { |
| Heap* heap = name->GetHeap(); |
| - MaybeObject* maybe_store_value = |
| - heap->AllocatePropertyCell(value); |
| + MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value); |
| if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| } |
| Object* dict; |
| @@ -691,7 +690,7 @@ MaybeObject* JSObject::SetNormalizedProperty(Name* name, |
| if (IsGlobalObject()) { |
| PropertyCell* cell = |
| PropertyCell::cast(property_dictionary()->ValueAt(entry)); |
| - cell->set_value(value); |
| + cell->set_value_infer_type(value); |
| // Please note we have to update the property details. |
| property_dictionary()->DetailsAtPut(entry, details); |
| } else { |
| @@ -723,7 +722,7 @@ MaybeObject* JSObject::DeleteNormalizedProperty(Name* name, DeleteMode mode) { |
| set_map(new_map); |
| } |
| PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); |
| - cell->set_value(cell->GetHeap()->the_hole_value()); |
| + cell->set_value_infer_type(cell->GetHeap()->the_hole_value()); |
| dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| } else { |
| Object* deleted = dictionary->DeleteProperty(entry, mode); |
| @@ -1930,7 +1929,7 @@ MaybeObject* JSObject::AddSlowProperty(Name* name, |
| int entry = dict->FindEntry(name); |
| if (entry != NameDictionary::kNotFound) { |
| store_value = dict->ValueAt(entry); |
| - PropertyCell::cast(store_value)->set_value(value); |
| + PropertyCell::cast(store_value)->set_value_infer_type(value); |
| // Assign an enumeration index to the property and update |
| // SetNextEnumerationIndex. |
| int index = dict->NextEnumerationIndex(); |
| @@ -1944,7 +1943,7 @@ MaybeObject* JSObject::AddSlowProperty(Name* name, |
| heap->AllocatePropertyCell(value); |
| if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| } |
| - PropertyCell::cast(store_value)->set_value(value); |
| + PropertyCell::cast(store_value)->set_value_infer_type(value); |
| } |
| PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
| Object* result; |
| @@ -10111,29 +10110,46 @@ SafepointEntry Code::GetSafepointEntry(Address pc) { |
| } |
| -Map* Code::FindFirstMap() { |
| +Object* Code::FindNthObject(int n, Map* match_map) { |
| ASSERT(is_inline_cache_stub()); |
| DisallowHeapAllocation no_allocation; |
| int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| RelocInfo* info = it.rinfo(); |
| Object* object = info->target_object(); |
| - if (object->IsMap()) return Map::cast(object); |
| + if (object->IsHeapObject()) { |
| + if (HeapObject::cast(object)->map() == match_map) { |
| + if (--n == 0) return object; |
| + } |
| + } |
| } |
| return NULL; |
| } |
| -void Code::ReplaceFirstMap(Map* replace_with) { |
| +Map* Code::FindFirstMap() { |
| + Object* result = FindNthObject(1, GetHeap()->meta_map()); |
| + if (result == NULL) return NULL; |
|
rossberg
2013/06/25 10:47:38
Nit: could avoid the extra return using ?:
danno
2013/06/28 13:56:05
Done.
|
| + return Map::cast(result); |
| +} |
| + |
| + |
| +void Code::ReplaceNthObject(int n, |
| + Map* match_map, |
| + Object* replace_with) { |
| ASSERT(is_inline_cache_stub()); |
| DisallowHeapAllocation no_allocation; |
| int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| RelocInfo* info = it.rinfo(); |
| Object* object = info->target_object(); |
| - if (object->IsMap()) { |
| - info->set_target_object(replace_with); |
| - return; |
| + if (object->IsHeapObject()) { |
| + if (HeapObject::cast(object)->map() == match_map) { |
| + if (--n == 0) { |
| + info->set_target_object(replace_with); |
| + return; |
| + } |
| + } |
| } |
| } |
| UNREACHABLE(); |
| @@ -10152,6 +10168,11 @@ void Code::FindAllMaps(MapHandleList* maps) { |
| } |
| +void Code::ReplaceFirstMap(Map* replace_with) { |
| + ReplaceNthObject(1, GetHeap()->meta_map(), replace_with); |
| +} |
| + |
| + |
| Code* Code::FindFirstCode() { |
| ASSERT(is_inline_cache_stub()); |
| DisallowHeapAllocation no_allocation; |
| @@ -10193,6 +10214,22 @@ Name* Code::FindFirstName() { |
| } |
| +void Code::ReplaceNthCell(int n, |
| + Cell* replace_with) { |
|
rossberg
2013/06/25 10:47:38
Nit: this fits on the previous line
danno
2013/06/28 13:56:05
Done.
|
| + ASSERT(is_inline_cache_stub()); |
| + DisallowHeapAllocation no_allocation; |
| + int mask = RelocInfo::ModeMask(RelocInfo::CELL); |
| + for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| + RelocInfo* info = it.rinfo(); |
| + if (--n == 0) { |
| + info->set_target_cell(replace_with); |
| + return; |
| + } |
| + } |
| + UNREACHABLE(); |
| +} |
| + |
| + |
| void Code::ClearInlineCaches() { |
| int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
| @@ -11076,7 +11113,7 @@ void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group, |
| Handle<DependentCode> codes = |
| DependentCode::Insert(dep, group, info->object_wrapper()); |
| if (*codes != dependent_code()) set_dependent_code(*codes); |
| - info->dependent_maps(group)->Add(Handle<Map>(this), info->zone()); |
| + info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone()); |
| } |
| @@ -11102,6 +11139,16 @@ void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) { |
| } |
| +DependentCode* DependentCode::ForObject(Handle<HeapObject> object, |
| + DependencyGroup group) { |
| + AllowDeferredHandleDereference dependencies_are_safe; |
| + if (group == DependentCode::kPropertyCellChangedGroup) { |
| + return Handle<PropertyCell>::cast(object)->dependent_code(); |
| + } |
| + return Handle<Map>::cast(object)->dependent_code(); |
| +} |
| + |
| + |
| Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries, |
| DependencyGroup group, |
| Handle<Object> object) { |
| @@ -11240,7 +11287,7 @@ void DependentCode::DeoptimizeDependentCodeGroup( |
| code->set_marked_for_deoptimization(true); |
| } else { |
| CompilationInfo* info = compilation_info_at(i); |
| - info->AbortDueToDependentMap(); |
| + info->AbortDueToDependencyChange(); |
| } |
| } |
| // Compact the array by moving all subsequent groups to fill in the new holes. |
| @@ -15773,4 +15820,55 @@ void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { |
| } |
| +Type* PropertyCell::UnionType(Object* value) { |
|
rossberg
2013/06/25 10:47:38
I'm not sure I fully understand the logic of this
danno
2013/06/28 13:56:05
Done.
|
| + Isolate* isolate = GetIsolate(); |
| + Handle<Object> value_handle(value, isolate); |
| + Handle<Type> old_type(type(), isolate); |
| + Handle<Type> new_type(Type::Constant(value_handle, isolate), isolate); |
| + |
| + if (new_type->Is(old_type) && !value->IsTheHole()) { |
|
rossberg
2013/06/25 10:47:38
There is repeated special-casing for the hole. May
danno
2013/06/28 13:56:05
Done.
|
| + return *old_type; |
| + } |
| + |
| + dependent_code()->DeoptimizeDependentCodeGroup( |
| + isolate, DependentCode::kPropertyCellChangedGroup); |
| + |
| + if (*old_type == Type::None()) { |
|
rossberg
2013/06/25 10:47:38
Please don't rely on pointer equality for types. T
danno
2013/06/28 13:56:05
Done.
|
| + if (new_type->IsConstant() && !value->IsTheHole()) { |
|
rossberg
2013/06/25 10:47:38
Given that new_type is initialised to a Constant a
danno
2013/06/28 13:56:05
Done.
|
| + return *new_type; |
| + } |
| + } else if (old_type->IsConstant() && old_type->AsConstant()->IsUndefined()) { |
|
rossberg
2013/06/25 10:47:38
I think you can just as well test "old_type->Is(Ty
danno
2013/06/28 13:56:05
Done.
|
| + return *new_type; |
| + } |
| + |
| + return Type::Any(); |
| +} |
| + |
| + |
| +void PropertyCell::set_value_infer_type(Object* value, |
| + WriteBarrierMode ignored) { |
| + set_value(value, ignored); |
| + set_type(UnionType(value)); |
| +} |
| + |
| + |
| +void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) { |
| + Handle<DependentCode> dep(dependent_code()); |
| + Handle<DependentCode> codes = |
| + DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, |
| + info->object_wrapper()); |
| + if (*codes != dependent_code()) set_dependent_code(*codes); |
| + info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| + Handle<HeapObject>(this), info->zone()); |
| +} |
| + |
| + |
| +void PropertyCell::AddDependentCode(Handle<Code> code) { |
| + Handle<DependentCode> codes = DependentCode::Insert( |
| + Handle<DependentCode>(dependent_code()), |
| + DependentCode::kPropertyCellChangedGroup, code); |
| + if (*codes != dependent_code()) set_dependent_code(*codes); |
| +} |
| + |
| + |
| } } // namespace v8::internal |