Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: src/objects.cc

Issue 14146005: Track representations of fields (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Only verify representation while transitioning Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 int enumeration_index; 650 int enumeration_index;
651 // Preserve the enumeration index unless the property was deleted. 651 // Preserve the enumeration index unless the property was deleted.
652 if (original_details.IsDeleted()) { 652 if (original_details.IsDeleted()) {
653 enumeration_index = property_dictionary()->NextEnumerationIndex(); 653 enumeration_index = property_dictionary()->NextEnumerationIndex();
654 property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1); 654 property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
655 } else { 655 } else {
656 enumeration_index = original_details.dictionary_index(); 656 enumeration_index = original_details.dictionary_index();
657 ASSERT(enumeration_index > 0); 657 ASSERT(enumeration_index > 0);
658 } 658 }
659 659
660 details = PropertyDetails( 660 details = PropertyDetails(details.attributes(), details.type(),
661 details.attributes(), details.type(), enumeration_index); 661 Representation::None(), enumeration_index);
662 662
663 if (IsGlobalObject()) { 663 if (IsGlobalObject()) {
664 JSGlobalPropertyCell* cell = 664 JSGlobalPropertyCell* cell =
665 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); 665 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
666 cell->set_value(value); 666 cell->set_value(value);
667 // Please note we have to update the property details. 667 // Please note we have to update the property details.
668 property_dictionary()->DetailsAtPut(entry, details); 668 property_dictionary()->DetailsAtPut(entry, details);
669 } else { 669 } else {
670 property_dictionary()->SetEntry(entry, name, value, details); 670 property_dictionary()->SetEntry(entry, name, value, details);
671 } 671 }
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 } 1708 }
1709 1709
1710 1710
1711 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, 1711 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
1712 Name* name, 1712 Name* name,
1713 Object* value, 1713 Object* value,
1714 int field_index) { 1714 int field_index) {
1715 if (map()->unused_property_fields() == 0) { 1715 if (map()->unused_property_fields() == 0) {
1716 int new_unused = new_map->unused_property_fields(); 1716 int new_unused = new_map->unused_property_fields();
1717 FixedArray* values; 1717 FixedArray* values;
1718 { MaybeObject* maybe_values = 1718 MaybeObject* maybe_values =
1719 properties()->CopySize(properties()->length() + new_unused + 1); 1719 properties()->CopySize(properties()->length() + new_unused + 1);
1720 if (!maybe_values->To(&values)) return maybe_values; 1720 if (!maybe_values->To(&values)) return maybe_values;
1721 } 1721
1722 set_properties(values); 1722 set_properties(values);
1723 } 1723 }
1724 set_map(new_map); 1724 set_map(new_map);
1725 return FastPropertyAtPut(field_index, value); 1725 return FastPropertyAtPut(field_index, value);
1726 } 1726 }
1727 1727
1728 1728
1729 static bool IsIdentifier(UnicodeCache* cache, Name* name) { 1729 static bool IsIdentifier(UnicodeCache* cache, Name* name) {
1730 // Checks whether the buffer contains an identifier (no escape). 1730 // Checks whether the buffer contains an identifier (no escape).
1731 if (!name->IsString()) return false; 1731 if (!name->IsString()) return false;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 1767 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1768 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1768 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1769 1769
1770 return AddSlowProperty(name, value, attributes); 1770 return AddSlowProperty(name, value, attributes);
1771 } 1771 }
1772 1772
1773 // Compute the new index for new field. 1773 // Compute the new index for new field.
1774 int index = map()->NextFreePropertyIndex(); 1774 int index = map()->NextFreePropertyIndex();
1775 1775
1776 // Allocate new instance descriptors with (name, index) added 1776 // Allocate new instance descriptors with (name, index) added
1777 FieldDescriptor new_field(name, index, attributes, 0); 1777 FieldDescriptor new_field(
1778 name, index, attributes, value->RequiredRepresentation(), 0);
1778 1779
1779 ASSERT(index < map()->inobject_properties() || 1780 ASSERT(index < map()->inobject_properties() ||
1780 (index - map()->inobject_properties()) < properties()->length() || 1781 (index - map()->inobject_properties()) < properties()->length() ||
1781 map()->unused_property_fields() == 0); 1782 map()->unused_property_fields() == 0);
1782 1783
1783 FixedArray* values = NULL; 1784 FixedArray* values = NULL;
1784 1785
1785 if (map()->unused_property_fields() == 0) { 1786 if (map()->unused_property_fields() == 0) {
1786 // Make room for the new value 1787 // Make room for the new value
1787 MaybeObject* maybe_values = 1788 MaybeObject* maybe_values =
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1842 Object* store_value = value; 1843 Object* store_value = value;
1843 if (IsGlobalObject()) { 1844 if (IsGlobalObject()) {
1844 // In case name is an orphaned property reuse the cell. 1845 // In case name is an orphaned property reuse the cell.
1845 int entry = dict->FindEntry(name); 1846 int entry = dict->FindEntry(name);
1846 if (entry != NameDictionary::kNotFound) { 1847 if (entry != NameDictionary::kNotFound) {
1847 store_value = dict->ValueAt(entry); 1848 store_value = dict->ValueAt(entry);
1848 JSGlobalPropertyCell::cast(store_value)->set_value(value); 1849 JSGlobalPropertyCell::cast(store_value)->set_value(value);
1849 // Assign an enumeration index to the property and update 1850 // Assign an enumeration index to the property and update
1850 // SetNextEnumerationIndex. 1851 // SetNextEnumerationIndex.
1851 int index = dict->NextEnumerationIndex(); 1852 int index = dict->NextEnumerationIndex();
1852 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); 1853 PropertyDetails details = PropertyDetails(
1854 attributes, NORMAL, Representation::None(), index);
1853 dict->SetNextEnumerationIndex(index + 1); 1855 dict->SetNextEnumerationIndex(index + 1);
1854 dict->SetEntry(entry, name, store_value, details); 1856 dict->SetEntry(entry, name, store_value, details);
1855 return value; 1857 return value;
1856 } 1858 }
1857 Heap* heap = GetHeap(); 1859 Heap* heap = GetHeap();
1858 { MaybeObject* maybe_store_value = 1860 { MaybeObject* maybe_store_value =
1859 heap->AllocateJSGlobalPropertyCell(value); 1861 heap->AllocateJSGlobalPropertyCell(value);
1860 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; 1862 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
1861 } 1863 }
1862 JSGlobalPropertyCell::cast(store_value)->set_value(value); 1864 JSGlobalPropertyCell::cast(store_value)->set_value(value);
1863 } 1865 }
1864 PropertyDetails details = PropertyDetails(attributes, NORMAL); 1866 PropertyDetails details = PropertyDetails(
1867 attributes, NORMAL, Representation::None());
1865 Object* result; 1868 Object* result;
1866 { MaybeObject* maybe_result = dict->Add(name, store_value, details); 1869 { MaybeObject* maybe_result = dict->Add(name, store_value, details);
1867 if (!maybe_result->ToObject(&result)) return maybe_result; 1870 if (!maybe_result->ToObject(&result)) return maybe_result;
1868 } 1871 }
1869 if (dict != result) set_properties(NameDictionary::cast(result)); 1872 if (dict != result) set_properties(NameDictionary::cast(result));
1870 return value; 1873 return value;
1871 } 1874 }
1872 1875
1873 1876
1874 MaybeObject* JSObject::AddProperty(Name* name, 1877 MaybeObject* JSObject::AddProperty(Name* name,
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 Object* value, 1998 Object* value,
1996 PropertyAttributes attributes) { 1999 PropertyAttributes attributes) {
1997 NameDictionary* dictionary = property_dictionary(); 2000 NameDictionary* dictionary = property_dictionary();
1998 int old_index = dictionary->FindEntry(name); 2001 int old_index = dictionary->FindEntry(name);
1999 int new_enumeration_index = 0; // 0 means "Use the next available index." 2002 int new_enumeration_index = 0; // 0 means "Use the next available index."
2000 if (old_index != -1) { 2003 if (old_index != -1) {
2001 // All calls to ReplaceSlowProperty have had all transitions removed. 2004 // All calls to ReplaceSlowProperty have had all transitions removed.
2002 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); 2005 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
2003 } 2006 }
2004 2007
2005 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); 2008 PropertyDetails new_details(
2009 attributes, NORMAL, Representation::None(), new_enumeration_index);
2006 return SetNormalizedProperty(name, value, new_details); 2010 return SetNormalizedProperty(name, value, new_details);
2007 } 2011 }
2008 2012
2009 2013
2010 MaybeObject* JSObject::ConvertTransitionToMapTransition( 2014 MaybeObject* JSObject::ConvertTransitionToMapTransition(
2011 int transition_index, 2015 int transition_index,
2012 Name* name, 2016 Name* name,
2013 Object* new_value, 2017 Object* new_value,
2014 PropertyAttributes attributes) { 2018 PropertyAttributes attributes) {
2015 Map* old_map = map(); 2019 Map* old_map = map();
2016 Map* old_target = old_map->GetTransition(transition_index); 2020 Map* old_target = old_map->GetTransition(transition_index);
2017 Object* result; 2021 Object* result;
2018 2022
2019 MaybeObject* maybe_result = 2023 MaybeObject* maybe_result =
2020 ConvertDescriptorToField(name, new_value, attributes); 2024 ConvertDescriptorToField(name, new_value, attributes);
2021 if (!maybe_result->To(&result)) return maybe_result; 2025 if (!maybe_result->To(&result)) return maybe_result;
2022 2026
2023 if (!HasFastProperties()) return result; 2027 if (!HasFastProperties()) return result;
2024 2028
2025 // This method should only be used to convert existing transitions. 2029 // This method should only be used to convert existing transitions.
2026 Map* new_map = map(); 2030 Map* new_map = map();
2027 2031
2028 // TODO(verwaest): From here on we lose existing map transitions, causing 2032 // TODO(verwaest): From here on we lose existing map transitions, causing
2029 // invalid back pointers. This will change once we can store multiple 2033 // invalid back pointers. This will change once we can store multiple
2030 // transitions with the same key. 2034 // transitions with the same key.
2031
2032 bool owned_descriptors = old_map->owns_descriptors(); 2035 bool owned_descriptors = old_map->owns_descriptors();
2033 if (owned_descriptors || 2036 if (owned_descriptors ||
2034 old_target->instance_descriptors() == old_map->instance_descriptors()) { 2037 old_target->instance_descriptors() == old_map->instance_descriptors()) {
2035 // Since the conversion above generated a new fast map with an additional 2038 // Since the conversion above generated a new fast map with an additional
2036 // property which can be shared as well, install this descriptor pointer 2039 // property which can be shared as well, install this descriptor pointer
2037 // along the entire chain of smaller maps. 2040 // along the entire chain of smaller maps.
2038 Map* map; 2041 Map* map;
2039 DescriptorArray* new_descriptors = new_map->instance_descriptors(); 2042 DescriptorArray* new_descriptors = new_map->instance_descriptors();
2040 DescriptorArray* old_descriptors = old_map->instance_descriptors(); 2043 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2041 for (Object* current = old_map; 2044 for (Object* current = old_map;
2042 !current->IsUndefined(); 2045 !current->IsUndefined();
2043 current = map->GetBackPointer()) { 2046 current = map->GetBackPointer()) {
2044 map = Map::cast(current); 2047 map = Map::cast(current);
2045 if (map->instance_descriptors() != old_descriptors) break; 2048 if (map->instance_descriptors() != old_descriptors) break;
2046 map->SetEnumLength(Map::kInvalidEnumCache); 2049 map->SetEnumLength(Map::kInvalidEnumCache);
2047 map->set_instance_descriptors(new_descriptors); 2050 map->set_instance_descriptors(new_descriptors);
2048 } 2051 }
2049 old_map->set_owns_descriptors(false); 2052 old_map->set_owns_descriptors(false);
2050 } 2053 }
2051 2054
2055 old_target->InvalidateTransitionTree();
2056
2052 old_map->SetTransition(transition_index, new_map); 2057 old_map->SetTransition(transition_index, new_map);
2053 new_map->SetBackPointer(old_map); 2058 new_map->SetBackPointer(old_map);
2054 return result; 2059 return result;
2055 } 2060 }
2056 2061
2057 2062
2058 MaybeObject* JSObject::ConvertDescriptorToField(Name* name, 2063 MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
2059 Object* new_value, 2064 Object* new_value,
2060 PropertyAttributes attributes) { 2065 PropertyAttributes attributes) {
2061 if (map()->unused_property_fields() == 0 && 2066 if (map()->unused_property_fields() == 0 &&
2062 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { 2067 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
2063 Object* obj; 2068 Object* obj;
2064 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 2069 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
2065 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2070 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2066 return ReplaceSlowProperty(name, new_value, attributes); 2071 return ReplaceSlowProperty(name, new_value, attributes);
2067 } 2072 }
2068 2073
2069 int index = map()->NextFreePropertyIndex(); 2074 int index = map()->NextFreePropertyIndex();
2070 FieldDescriptor new_field(name, index, attributes, 0); 2075 FieldDescriptor new_field(
2076 name, index, attributes, new_value->RequiredRepresentation(), 0);
2071 2077
2072 // Make a new map for the object. 2078 // Make a new map for the object.
2073 Map* new_map; 2079 Map* new_map;
2074 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, 2080 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field,
2075 OMIT_TRANSITION); 2081 OMIT_TRANSITION);
2076 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 2082 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2077 2083
2078 // Make new properties array if necessary. 2084 // Make new properties array if necessary.
2079 FixedArray* new_properties = NULL; 2085 FixedArray* new_properties = NULL;
2080 int new_unused_property_fields = map()->unused_property_fields() - 1; 2086 int new_unused_property_fields = map()->unused_property_fields() - 1;
2081 if (map()->unused_property_fields() == 0) { 2087 if (map()->unused_property_fields() == 0) {
2082 new_unused_property_fields = kFieldsAdded - 1; 2088 new_unused_property_fields = kFieldsAdded - 1;
2083 MaybeObject* maybe_new_properties = 2089 MaybeObject* maybe_new_properties =
2084 properties()->CopySize(properties()->length() + kFieldsAdded); 2090 properties()->CopySize(properties()->length() + kFieldsAdded);
2085 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; 2091 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties;
2086 } 2092 }
2087 2093
2088 // Update pointers to commit changes. 2094 // Update pointers to commit changes.
2089 // Object points to the new map. 2095 // Object points to the new map.
2090 new_map->set_unused_property_fields(new_unused_property_fields); 2096 new_map->set_unused_property_fields(new_unused_property_fields);
2091 set_map(new_map); 2097 set_map(new_map);
2092 if (new_properties != NULL) { 2098 if (new_properties != NULL) {
2093 set_properties(new_properties); 2099 set_properties(new_properties);
2094 } 2100 }
2095 return FastPropertyAtPut(index, new_value); 2101 return FastPropertyAtPut(index, new_value);
2096 } 2102 }
2097 2103
2098 2104
2105 const char* Representation::Mnemonic() const {
2106 switch (kind_) {
2107 case kNone: return "v";
2108 case kTagged: return "t";
2109 case kSmi: return "s";
2110 case kDouble: return "d";
2111 case kInteger32: return "i";
2112 case kExternal: return "x";
2113 default:
2114 UNREACHABLE();
2115 return NULL;
2116 }
2117 }
2118
2119
2120 enum RightTrimMode { FROM_GC, FROM_MUTATOR };
2121
2122
2123 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2124 // If we are doing a big trim in old space then we zap the space.
2125 Object** zap = reinterpret_cast<Object**>(new_end);
2126 zap++; // Header of filler must be at least one word so skip that.
2127 for (int i = 1; i < to_trim; i++) {
2128 *zap++ = Smi::FromInt(0);
2129 }
2130 }
2131
2132
2133 template<RightTrimMode trim_mode>
2134 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2135 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
2136 // For now this trick is only applied to fixed arrays in new and paged space.
2137 ASSERT(!HEAP->lo_space()->Contains(elms));
2138
2139 const int len = elms->length();
2140
2141 ASSERT(to_trim < len);
2142
2143 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2144
2145 if (trim_mode != FROM_GC || Heap::ShouldZapGarbage()) {
2146 ZapEndOfFixedArray(new_end, to_trim);
2147 }
2148
2149 int size_delta = to_trim * kPointerSize;
2150
2151 // Technically in new space this write might be omitted (except for
2152 // debug mode which iterates through the heap), but to play safer
2153 // we still do it.
2154 heap->CreateFillerObjectAt(new_end, size_delta);
2155
2156 elms->set_length(len - to_trim);
2157
2158 // Maintain marking consistency for IncrementalMarking.
2159 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
2160 if (trim_mode == FROM_GC) {
2161 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2162 } else {
2163 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2164 }
2165 }
2166 }
2167
2168
2169 bool Map::InstancesNeedRewriting(int target_number_of_fields,
2170 int target_inobject,
2171 int target_unused) {
2172 // If fields were added (or removed), rewrite the instance.
danno 2013/04/24 16:08:20 ASSERT(target_number_of_fileds >= NumberOfFields()
Toon Verwaest 2013/04/25 10:59:38 Done.
2173 if (target_number_of_fields != NumberOfFields()) return true;
2174 // If no fields were added, and no inobject properties were removed, setting
2175 // the map is sufficient.
2176 if (target_inobject == inobject_properties()) return false;
2177 // In-object slack tracking may have reduced the object size of the new map.
2178 // In that case, succeed if all existing fields were inobject, and they still
2179 // fit within the new inobject size.
2180 ASSERT(target_inobject < inobject_properties());
2181 if (target_number_of_fields <= target_inobject) {
2182 ASSERT(target_number_of_fields + target_unused == target_inobject);
2183 return false;
2184 }
2185 // Otherwise, properties will need to be moved to the backing store.
2186 return true;
2187 }
2188
2189
2190 // To migrate an instance to a map:
2191 // - First check whether the instance needs to be rewritten. If not, simply
2192 // change the map.
2193 // - Otherwise, allocate a fixed array large enough to hold all fields, in
2194 // addition to unused space.
2195 // - Copy all existing properties in, in the following order: backing store
2196 // properties, unused fields, inobject properties.
2197 // - If all allocation succeeded, commit the state atomically:
2198 // * Copy inobject properties from the backing store back into the object.
2199 // * Trim the difference in instance size of the object. This also cleanly
2200 // frees inobject properties that moved to the backing store.
2201 // * If there are properties left in the backing store, trim of the space used
2202 // to temporarily store the inobject properties.
2203 // * If there are properties left in the backing store, install the backing
2204 // store.
2205 MaybeObject* JSObject::MigrateToMap(Map* new_map) {
2206 Heap* heap = GetHeap();
2207 Map* old_map = map();
2208 int number_of_fields = new_map->NumberOfFields();
2209 int inobject = new_map->inobject_properties();
2210 int unused = new_map->unused_property_fields();
2211
2212 // Nothing to do if no functions were converted to fields.
2213 if (!old_map->InstancesNeedRewriting(number_of_fields, inobject, unused)) {
2214 set_map(new_map);
2215 return this;
2216 }
2217
2218 int total_size = number_of_fields + unused;
2219 int external = total_size - inobject;
2220 FixedArray* array;
2221 MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
2222 if (!maybe_array->To(&array)) return maybe_array;
2223
2224 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2225 DescriptorArray* new_descriptors = new_map->instance_descriptors();
2226 int descriptors = new_map->NumberOfOwnDescriptors();
2227
2228 for (int i = 0; i < descriptors; i++) {
2229 PropertyDetails details = new_descriptors->GetDetails(i);
2230 if (details.type() != FIELD) continue;
2231 PropertyDetails old_details = old_descriptors->GetDetails(i);
2232 ASSERT(old_details.type() == CONSTANT_FUNCTION ||
2233 old_details.type() == FIELD);
2234 Object* value = old_details.type() == CONSTANT_FUNCTION
2235 ? old_descriptors->GetValue(i)
2236 : FastPropertyAt(old_descriptors->GetFieldIndex(i));
2237 int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2238 if (target_index < 0) target_index += total_size;
2239 array->set(target_index, value);
2240 }
2241
2242 // From here on we cannot fail anymore.
2243
2244 // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2245 // avoid overwriting |one_pointer_filler_map|.
2246 int limit = Min(inobject, number_of_fields);
2247 for (int i = 0; i < limit; i++) {
2248 FastPropertyAtPut(i, array->get(external + i));
2249 }
2250
2251 // Create filler object past the new instance size.
2252 int new_instance_size = new_map->instance_size();
2253 int instance_size_delta = old_map->instance_size() - new_instance_size;
2254 ASSERT(instance_size_delta >= 0);
2255 Address address = this->address() + new_instance_size;
2256 heap->CreateFillerObjectAt(address, instance_size_delta);
2257
2258 // If there are properties in the new backing store, trim it to the correct
2259 // size and install the backing store into the object.
2260 if (external > 0) {
2261 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
2262 set_properties(array);
2263 }
2264
2265 set_map(new_map);
2266
2267 return this;
2268 }
2269
2270
2271 MaybeObject* JSObject::GeneralizeFieldRepresentation(
2272 int modify_index,
2273 Representation new_representation) {
2274 Map* new_map;
2275 MaybeObject* maybe_new_map =
2276 map()->GeneralizeRepresentation(modify_index, new_representation);
2277 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2278 ASSERT(map() != new_map || new_map->FindRootMap()->is_invalid_transition());
2279
2280 return MigrateToMap(new_map);
2281 }
2282
2283
2284 int Map::NumberOfFields() {
2285 DescriptorArray* descriptors = instance_descriptors();
2286 int result = 0;
2287 for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2288 if (descriptors->GetDetails(i).type() == FIELD) result++;
2289 }
2290 return result;
2291 }
2292
2293
2294 MaybeObject* Map::CopyGeneralizeRepresentation(
danno 2013/04/24 16:08:20 CopyGeneralizeAllRepresentations
Toon Verwaest 2013/04/25 10:59:38 Done.
2295 int modify_index,
2296 Representation new_representation) {
2297 Map* new_map;
2298 MaybeObject* maybe_map = this->Copy();
2299 if (!maybe_map->To(&new_map)) return maybe_map;
2300
2301 new_map->instance_descriptors()->InitializeRepresentations(
2302 Representation::Tagged());
2303 return new_map;
2304 }
2305
2306
2307 void Map::InvalidateTransitionTree() {
2308 if (is_invalid_transition()) return;
danno 2013/04/24 16:08:20 Stack overflow?
2309 if (HasTransitionArray()) {
2310 TransitionArray* transitions = this->transitions();
2311 for (int i = 0; i < transitions->number_of_transitions(); i++) {
2312 transitions->GetTarget(i)->InvalidateTransitionTree();
2313 }
2314 }
2315 invalidate_transition();
2316 dependent_code()->DeoptimizeDependentCodeGroup(
2317 GetIsolate(), DependentCode::kTransitionGroup);
2318 dependent_code()->DeoptimizeDependentCodeGroup(
2319 GetIsolate(), DependentCode::kPrototypeCheckGroup);
2320 }
2321
2322
2323 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2324 // the current instance_descriptors to ensure proper sharing of descriptor
2325 // arrays.
2326 void Map::InvalidateTarget(Name* key, DescriptorArray* new_descriptors) {
2327 if (HasTransitionArray()) {
2328 TransitionArray* transitions = this->transitions();
2329 int transition = transitions->Search(key);
2330 if (transition != TransitionArray::kNotFound) {
2331 transitions->GetTarget(transition)->InvalidateTransitionTree();
2332 }
2333 }
2334
2335 // Don't overwrite the empty descriptor array.
2336 if (NumberOfOwnDescriptors() == 0) return;
2337
2338 DescriptorArray* to_replace = instance_descriptors();
2339 Map* current = this;
2340 while (current->instance_descriptors() == to_replace) {
2341 current->SetEnumLength(Map::kInvalidEnumCache);
2342 current->set_instance_descriptors(new_descriptors);
2343 Object* next = current->GetBackPointer();
2344 if (next->IsUndefined()) break;
2345 current = Map::cast(next);
2346 }
2347
2348 set_owns_descriptors(false);
2349 }
2350
2351
2352 Map* Map::FindRootMap() {
2353 Map* result = this;
2354 while (true) {
2355 Object* back = result->GetBackPointer();
2356 if (back->IsUndefined()) return result;
2357 result = Map::cast(back);
2358 }
2359 }
2360
2361
2362 Map* Map::FindUpdatedMap(int verbatim,
2363 int length,
2364 DescriptorArray* descriptors) {
2365 // This can only be called on roots of transition trees.
2366 ASSERT(GetBackPointer()->IsUndefined());
2367
2368 Map* current = this;
2369
2370 for (int i = verbatim; i < length; i++) {
2371 if (!current->HasTransitionArray()) break;
2372 Name* name = descriptors->GetKey(i);
2373 TransitionArray* transitions = current->transitions();
2374 int transition = transitions->Search(name);
2375 if (transition == TransitionArray::kNotFound) break;
2376 current = transitions->GetTarget(transition);
2377 }
2378
2379 return current;
2380 }
2381
2382
2383 Map* Map::FindLastMatchMap(int verbatim,
2384 int length,
2385 DescriptorArray* descriptors) {
2386 // This can only be called on roots of transition trees.
2387 ASSERT(GetBackPointer()->IsUndefined());
2388
2389 Map* current = this;
2390
2391 for (int i = verbatim; i < length; i++) {
2392 if (!current->HasTransitionArray()) break;
2393 Name* name = descriptors->GetKey(i);
2394 TransitionArray* transitions = current->transitions();
2395 int transition = transitions->Search(name);
2396 if (transition == TransitionArray::kNotFound) break;
2397
2398 Map* next = transitions->GetTarget(transition);
2399 DescriptorArray* next_descriptors = next->instance_descriptors();
2400
2401 if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
2402
2403 PropertyDetails details = descriptors->GetDetails(i);
2404 PropertyDetails next_details = next_descriptors->GetDetails(i);
2405 if (details.type() != next_details.type()) break;
2406 if (details.attributes() != next_details.attributes()) break;
2407 if (!details.representation().Equals(next_details.representation())) break;
2408 ASSERT(!details.IsDeleted());
2409 ASSERT(!next_details.IsDeleted());
2410
2411 current = next;
2412 }
2413 return current;
2414 }
2415
2416
2417 // Generalize the representation of the descriptor at |modify_index|.
2418 // This method rewrites the transition tree to reflect the new change. To avoid
2419 // high degrees over polymorphism, and to stabilize quickly, on every rewrite
2420 // the new type is deduced by merging the current type with any potential new
2421 // (partial) version of the type in the transition tree.
2422 // To do this, on each rewrite:
2423 // - Search the root of the transition tree using FindRootMap.
2424 // - Find |updated|, the newest matching version of this map using
2425 // FindUpdatedMap. This uses the keys in the own map's descriptor array to
2426 // walk the transition tree.
2427 // - Merge/generalize the descriptor array of the current map and |updated|.
2428 // - Generalize the |modify_index| descriptor using |new_representation|.
2429 // - Walk the tree again starting from the root towards |updated|. Stop at
2430 // |split_map|, the first map who's descriptor array does not match the merged
2431 // descriptor array.
2432 // - If |updated| == |split_map|, |updated| is in the expected state. Return it.
2433 // - Otherwise, invalidate the outdated transition target from |updated|, and
2434 // replace its transition tree with a new branch for the updated descriptors.
2435 MaybeObject* Map::GeneralizeRepresentation(int modify_index,
2436 Representation new_representation) {
2437 Map* old_map = this;
2438 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2439 Representation old_reprepresentation =
2440 old_descriptors->GetDetails(modify_index).representation();
2441
2442 if (old_reprepresentation.IsNone()) {
2443 UNREACHABLE();
2444 old_descriptors->SetRepresentation(modify_index, new_representation);
2445 return this;
2446 }
2447
2448 int descriptors = old_map->NumberOfOwnDescriptors();
2449 Map* root_map = old_map->FindRootMap();
2450
2451 if (!old_map->EquivalentToForTransition(root_map)) {
2452 return CopyGeneralizeRepresentation(modify_index, new_representation);
2453 }
2454
2455 int verbatim = root_map->NumberOfOwnDescriptors();
2456
2457 Map* updated = root_map->FindUpdatedMap(
2458 verbatim, descriptors, old_descriptors);
2459 // Check the state of the root map.
2460 DescriptorArray* updated_descriptors = updated->instance_descriptors();
2461
2462 DescriptorArray* new_descriptors;
2463 MaybeObject* maybe_descriptors = updated_descriptors->Merge(
2464 verbatim,
2465 updated->NumberOfOwnDescriptors(),
2466 descriptors,
2467 old_descriptors);
2468 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
2469
2470 old_reprepresentation =
2471 new_descriptors->GetDetails(modify_index).representation();
2472 new_representation = new_representation.generalize(old_reprepresentation);
2473 new_descriptors->SetRepresentation(modify_index, new_representation);
2474
2475 Map* split_map = root_map->FindLastMatchMap(
2476 verbatim, descriptors, new_descriptors);
2477
2478 int descriptor = split_map->NumberOfOwnDescriptors();
danno 2013/04/24 16:08:20 split_descriptors
Toon Verwaest 2013/04/25 10:59:38 Done.
2479 // Check whether |split_map| matches what we were looking for. If so, return
2480 // it.
2481 if (descriptors == descriptor) return split_map;
2482
2483 split_map->InvalidateTarget(
2484 old_descriptors->GetKey(descriptor), new_descriptors);
2485
2486 Map* new_map = split_map;
2487 // Add missing transitions.
2488 for (; descriptor < descriptors; descriptor++) {
danno 2013/04/24 16:08:20 maybe a separate loop variable?
Toon Verwaest 2013/04/25 10:59:38 Done.
2489 MaybeObject* maybe_map = new_map->CopyInstallDescriptors(
2490 descriptor, new_descriptors);
2491 if (!maybe_map->To(&new_map)) {
2492 // Create a handle for the last created map to ensure it stays alive
2493 // during GC. Its descriptor array is too large, but it will be
2494 // overwritten during retry anyway.
2495 Handle<Map>(new_map);
danno 2013/04/24 16:08:20 Please try to test this with a crazy big object ex
2496 }
2497 }
2498
2499 new_map->set_owns_descriptors(true);
2500 return new_map;
2501 }
2502
2099 2503
2100 MaybeObject* JSObject::SetPropertyWithInterceptor( 2504 MaybeObject* JSObject::SetPropertyWithInterceptor(
2101 Name* name, 2505 Name* name,
2102 Object* value, 2506 Object* value,
2103 PropertyAttributes attributes, 2507 PropertyAttributes attributes,
2104 StrictModeFlag strict_mode) { 2508 StrictModeFlag strict_mode) {
2105 // TODO(rossberg): Support symbols in the API. 2509 // TODO(rossberg): Support symbols in the API.
2106 if (name->IsSymbol()) return value; 2510 if (name->IsSymbol()) return value;
2107 Isolate* isolate = GetIsolate(); 2511 Isolate* isolate = GetIsolate();
2108 HandleScope scope(isolate); 2512 HandleScope scope(isolate);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 if (strict_mode == kNonStrictMode) return value; 2788 if (strict_mode == kNonStrictMode) return value;
2385 Handle<Object> args[] = { Handle<Object>(name, isolate), 2789 Handle<Object> args[] = { Handle<Object>(name, isolate),
2386 Handle<Object>(this, isolate)}; 2790 Handle<Object>(this, isolate)};
2387 return isolate->Throw(*isolate->factory()->NewTypeError( 2791 return isolate->Throw(*isolate->factory()->NewTypeError(
2388 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); 2792 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2389 } 2793 }
2390 return heap->the_hole_value(); 2794 return heap->the_hole_value();
2391 } 2795 }
2392 2796
2393 2797
2394 enum RightTrimMode { FROM_GC, FROM_MUTATOR };
2395
2396
2397 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2398 // If we are doing a big trim in old space then we zap the space.
2399 Object** zap = reinterpret_cast<Object**>(new_end);
2400 zap++; // Header of filler must be at least one word so skip that.
2401 for (int i = 1; i < to_trim; i++) {
2402 *zap++ = Smi::FromInt(0);
2403 }
2404 }
2405
2406
2407 template<RightTrimMode trim_mode>
2408 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2409 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
2410 // For now this trick is only applied to fixed arrays in new and paged space.
2411 ASSERT(!HEAP->lo_space()->Contains(elms));
2412
2413 const int len = elms->length();
2414
2415 ASSERT(to_trim < len);
2416
2417 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2418
2419 if (trim_mode != FROM_GC || Heap::ShouldZapGarbage()) {
2420 ZapEndOfFixedArray(new_end, to_trim);
2421 }
2422
2423 int size_delta = to_trim * kPointerSize;
2424
2425 // Technically in new space this write might be omitted (except for
2426 // debug mode which iterates through the heap), but to play safer
2427 // we still do it.
2428 heap->CreateFillerObjectAt(new_end, size_delta);
2429
2430 elms->set_length(len - to_trim);
2431
2432 // Maintain marking consistency for IncrementalMarking.
2433 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
2434 if (trim_mode == FROM_GC) {
2435 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2436 } else {
2437 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2438 }
2439 }
2440 }
2441
2442
2443 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { 2798 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
2444 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 2799 Handle<DescriptorArray> descriptors(map->instance_descriptors());
2445 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 2800 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
2446 int number_of_descriptors = descriptors->number_of_descriptors(); 2801 int number_of_descriptors = descriptors->number_of_descriptors();
2447 Isolate* isolate = map->GetIsolate(); 2802 Isolate* isolate = map->GetIsolate();
2448 Handle<DescriptorArray> new_descriptors = 2803 Handle<DescriptorArray> new_descriptors =
2449 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); 2804 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
2450 DescriptorArray::WhitenessWitness witness(*new_descriptors); 2805 DescriptorArray::WhitenessWitness witness(*new_descriptors);
2451 2806
2452 for (int i = 0; i < number_of_descriptors; ++i) { 2807 for (int i = 0; i < number_of_descriptors; ++i) {
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
3096 return Handle<Object>(); 3451 return Handle<Object>();
3097 } 3452 }
3098 trap = Handle<Object>(derived); 3453 trap = Handle<Object>(derived);
3099 } 3454 }
3100 3455
3101 bool threw; 3456 bool threw;
3102 return Execution::Call(trap, handler, argc, argv, &threw); 3457 return Execution::Call(trap, handler, argc, argv, &threw);
3103 } 3458 }
3104 3459
3105 3460
3106 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
3107 Handle<Map> map) {
3108 CALL_HEAP_FUNCTION_VOID(
3109 object->GetIsolate(),
3110 object->AddFastPropertyUsingMap(*map));
3111 }
3112
3113
3114 void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) { 3461 void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) {
3115 CALL_HEAP_FUNCTION_VOID( 3462 CALL_HEAP_FUNCTION_VOID(
3116 object->GetIsolate(), 3463 object->GetIsolate(),
3117 object->TransitionToMap(*map)); 3464 object->TransitionToMap(*map));
3118 } 3465 }
3119 3466
3120 3467
3468 void JSObject::MigrateInstance(Handle<JSObject> object) {
3469 CALL_HEAP_FUNCTION_VOID(
3470 object->GetIsolate(),
3471 object->MigrateInstance());
3472 }
3473
3474
3475 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
3476 int modify_index,
3477 Representation new_representation) {
3478 CALL_HEAP_FUNCTION(
3479 map->GetIsolate(),
3480 map->GeneralizeRepresentation(modify_index, new_representation),
3481 Map);
3482 }
3483
3484
3121 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, 3485 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
3122 Name* name_raw, 3486 Name* name_raw,
3123 Object* value_raw, 3487 Object* value_raw,
3124 PropertyAttributes attributes, 3488 PropertyAttributes attributes,
3125 StrictModeFlag strict_mode, 3489 StrictModeFlag strict_mode,
3126 StoreFromKeyed store_mode) { 3490 StoreFromKeyed store_mode) {
3127 Heap* heap = GetHeap(); 3491 Heap* heap = GetHeap();
3128 Isolate* isolate = heap->isolate(); 3492 Isolate* isolate = heap->isolate();
3129 // Make sure that the top context does not change when doing callbacks or 3493 // Make sure that the top context does not change when doing callbacks or
3130 // interceptor calls. 3494 // interceptor calls.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3199 old_value = Object::GetProperty(self, name); 3563 old_value = Object::GetProperty(self, name);
3200 } 3564 }
3201 3565
3202 // This is a real property that is not read-only, or it is a 3566 // This is a real property that is not read-only, or it is a
3203 // transition or null descriptor and there are no setters in the prototypes. 3567 // transition or null descriptor and there are no setters in the prototypes.
3204 MaybeObject* result = *value; 3568 MaybeObject* result = *value;
3205 switch (lookup->type()) { 3569 switch (lookup->type()) {
3206 case NORMAL: 3570 case NORMAL:
3207 result = lookup->holder()->SetNormalizedProperty(lookup, *value); 3571 result = lookup->holder()->SetNormalizedProperty(lookup, *value);
3208 break; 3572 break;
3209 case FIELD: 3573 case FIELD: {
3574 Representation representation = lookup->representation();
3575 if (!value->FitsRepresentation(representation)) {
3576 MaybeObject* maybe_failure = GeneralizeFieldRepresentation(
3577 lookup->GetDescriptorIndex(), value->RequiredRepresentation());
3578 if (maybe_failure->IsFailure()) return maybe_failure;
3579 }
3210 result = lookup->holder()->FastPropertyAtPut( 3580 result = lookup->holder()->FastPropertyAtPut(
3211 lookup->GetFieldIndex().field_index(), *value); 3581 lookup->GetFieldIndex().field_index(), *value);
3212 break; 3582 break;
3583 }
3213 case CONSTANT_FUNCTION: 3584 case CONSTANT_FUNCTION:
3214 // Only replace the function if necessary. 3585 // Only replace the function if necessary.
3215 if (*value == lookup->GetConstantFunction()) return *value; 3586 if (*value == lookup->GetConstantFunction()) return *value;
3216 // Preserve the attributes of this existing property. 3587 // Preserve the attributes of this existing property.
3217 attributes = lookup->GetAttributes(); 3588 attributes = lookup->GetAttributes();
3218 result = 3589 result =
3219 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes); 3590 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes);
3220 break; 3591 break;
3221 case CALLBACKS: { 3592 case CALLBACKS: {
3222 Object* callback_object = lookup->GetCallbackObject(); 3593 Object* callback_object = lookup->GetCallbackObject();
3223 return self->SetPropertyWithCallback( 3594 return self->SetPropertyWithCallback(
3224 callback_object, *name, *value, lookup->holder(), strict_mode); 3595 callback_object, *name, *value, lookup->holder(), strict_mode);
3225 } 3596 }
3226 case INTERCEPTOR: 3597 case INTERCEPTOR:
3227 result = lookup->holder()->SetPropertyWithInterceptor( 3598 result = lookup->holder()->SetPropertyWithInterceptor(
3228 *name, *value, attributes, strict_mode); 3599 *name, *value, attributes, strict_mode);
3229 break; 3600 break;
3230 case TRANSITION: { 3601 case TRANSITION: {
3231 Map* transition_map = lookup->GetTransitionTarget(); 3602 Map* transition_map = lookup->GetTransitionTarget();
3232 int descriptor = transition_map->LastAdded(); 3603 int descriptor = transition_map->LastAdded();
3233 3604
3234 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3605 DescriptorArray* descriptors = transition_map->instance_descriptors();
3235 PropertyDetails details = descriptors->GetDetails(descriptor); 3606 PropertyDetails details = descriptors->GetDetails(descriptor);
3236 3607
3237 if (details.type() == FIELD) { 3608 if (details.type() == FIELD) {
3238 if (attributes == details.attributes()) { 3609 if (attributes == details.attributes()) {
3610 if (!value->FitsRepresentation(details.representation())) {
3611 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
3612 descriptor, value->RequiredRepresentation());
3613 if (!maybe_map->To(&transition_map)) return maybe_map;
3614 Object* back = transition_map->GetBackPointer();
3615 if (back->IsMap()) {
3616 MaybeObject* maybe_failure = MigrateToMap(Map::cast(back));
3617 if (maybe_failure->IsFailure()) return maybe_failure;
3618 }
3619 }
3239 int field_index = descriptors->GetFieldIndex(descriptor); 3620 int field_index = descriptors->GetFieldIndex(descriptor);
3240 result = lookup->holder()->AddFastPropertyUsingMap( 3621 result = lookup->holder()->AddFastPropertyUsingMap(
3241 transition_map, *name, *value, field_index); 3622 transition_map, *name, *value, field_index);
3242 } else { 3623 } else {
3243 result = lookup->holder()->ConvertDescriptorToField( 3624 result = lookup->holder()->ConvertDescriptorToField(
3244 *name, *value, attributes); 3625 *name, *value, attributes);
3245 } 3626 }
3246 } else if (details.type() == CALLBACKS) { 3627 } else if (details.type() == CALLBACKS) {
3247 result = lookup->holder()->ConvertDescriptorToField( 3628 result = lookup->holder()->ConvertDescriptorToField(
3248 *name, *value, attributes); 3629 *name, *value, attributes);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3359 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); 3740 bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
3360 if (is_observed) { 3741 if (is_observed) {
3361 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name); 3742 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name);
3362 old_attributes = lookup.GetAttributes(); 3743 old_attributes = lookup.GetAttributes();
3363 } 3744 }
3364 3745
3365 // Check of IsReadOnly removed from here in clone. 3746 // Check of IsReadOnly removed from here in clone.
3366 MaybeObject* result = *value; 3747 MaybeObject* result = *value;
3367 switch (lookup.type()) { 3748 switch (lookup.type()) {
3368 case NORMAL: { 3749 case NORMAL: {
3369 PropertyDetails details = PropertyDetails(attributes, NORMAL); 3750 PropertyDetails details = PropertyDetails(
3751 attributes, NORMAL, Representation::None());
3370 result = self->SetNormalizedProperty(*name, *value, details); 3752 result = self->SetNormalizedProperty(*name, *value, details);
3371 break; 3753 break;
3372 } 3754 }
3373 case FIELD: 3755 case FIELD: {
3756 Representation representation = lookup.representation();
3757 if (!value->FitsRepresentation(representation)) {
3758 MaybeObject* maybe_failure = GeneralizeFieldRepresentation(
3759 lookup.GetDescriptorIndex(), value->RequiredRepresentation());
3760 if (maybe_failure->IsFailure()) return maybe_failure;
3761 }
3374 result = self->FastPropertyAtPut( 3762 result = self->FastPropertyAtPut(
3375 lookup.GetFieldIndex().field_index(), *value); 3763 lookup.GetFieldIndex().field_index(), *value);
3376 break; 3764 break;
3765 }
3377 case CONSTANT_FUNCTION: 3766 case CONSTANT_FUNCTION:
3378 // Only replace the function if necessary. 3767 // Only replace the function if necessary.
3379 if (*value != lookup.GetConstantFunction()) { 3768 if (*value != lookup.GetConstantFunction()) {
3380 // Preserve the attributes of this existing property. 3769 // Preserve the attributes of this existing property.
3381 attributes = lookup.GetAttributes(); 3770 attributes = lookup.GetAttributes();
3382 result = self->ConvertDescriptorToField(*name, *value, attributes); 3771 result = self->ConvertDescriptorToField(*name, *value, attributes);
3383 } 3772 }
3384 break; 3773 break;
3385 case CALLBACKS: 3774 case CALLBACKS:
3386 case INTERCEPTOR: 3775 case INTERCEPTOR:
3387 // Override callback in clone 3776 // Override callback in clone
3388 result = self->ConvertDescriptorToField(*name, *value, attributes); 3777 result = self->ConvertDescriptorToField(*name, *value, attributes);
3389 break; 3778 break;
3390 case TRANSITION: { 3779 case TRANSITION: {
3391 Map* transition_map = lookup.GetTransitionTarget(); 3780 Map* transition_map = lookup.GetTransitionTarget();
3392 int descriptor = transition_map->LastAdded(); 3781 int descriptor = transition_map->LastAdded();
3393 3782
3394 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3783 DescriptorArray* descriptors = transition_map->instance_descriptors();
3395 PropertyDetails details = descriptors->GetDetails(descriptor); 3784 PropertyDetails details = descriptors->GetDetails(descriptor);
3396 3785
3397 if (details.type() == FIELD) { 3786 if (details.type() == FIELD) {
3398 if (attributes == details.attributes()) { 3787 if (attributes == details.attributes()) {
3788 if (!value->FitsRepresentation(details.representation())) {
3789 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
3790 descriptor, value->RequiredRepresentation());
3791 if (!maybe_map->To(&transition_map)) return maybe_map;
3792 Object* back = transition_map->GetBackPointer();
3793 if (back->IsMap()) {
3794 MaybeObject* maybe_failure = MigrateToMap(Map::cast(back));
3795 if (maybe_failure->IsFailure()) return maybe_failure;
3796 }
3797 }
3399 int field_index = descriptors->GetFieldIndex(descriptor); 3798 int field_index = descriptors->GetFieldIndex(descriptor);
3400 result = self->AddFastPropertyUsingMap( 3799 result = self->AddFastPropertyUsingMap(
3401 transition_map, *name, *value, field_index); 3800 transition_map, *name, *value, field_index);
3402 } else { 3801 } else {
3403 result = self->ConvertDescriptorToField(*name, *value, attributes); 3802 result = self->ConvertDescriptorToField(*name, *value, attributes);
3404 } 3803 }
3405 } else if (details.type() == CALLBACKS) { 3804 } else if (details.type() == CALLBACKS) {
3406 result = self->ConvertDescriptorToField(*name, *value, attributes); 3805 result = self->ConvertDescriptorToField(*name, *value, attributes);
3407 } else { 3806 } else {
3408 ASSERT(details.type() == CONSTANT_FUNCTION); 3807 ASSERT(details.type() == CONSTANT_FUNCTION);
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
3800 NameDictionary::Allocate(GetHeap(), property_count); 4199 NameDictionary::Allocate(GetHeap(), property_count);
3801 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4200 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3802 4201
3803 DescriptorArray* descs = map_of_this->instance_descriptors(); 4202 DescriptorArray* descs = map_of_this->instance_descriptors();
3804 for (int i = 0; i < real_size; i++) { 4203 for (int i = 0; i < real_size; i++) {
3805 PropertyDetails details = descs->GetDetails(i); 4204 PropertyDetails details = descs->GetDetails(i);
3806 switch (details.type()) { 4205 switch (details.type()) {
3807 case CONSTANT_FUNCTION: { 4206 case CONSTANT_FUNCTION: {
3808 PropertyDetails d = PropertyDetails(details.attributes(), 4207 PropertyDetails d = PropertyDetails(details.attributes(),
3809 NORMAL, 4208 NORMAL,
4209 Representation::None(),
3810 details.descriptor_index()); 4210 details.descriptor_index());
3811 Object* value = descs->GetConstantFunction(i); 4211 Object* value = descs->GetConstantFunction(i);
3812 MaybeObject* maybe_dictionary = 4212 MaybeObject* maybe_dictionary =
3813 dictionary->Add(descs->GetKey(i), value, d); 4213 dictionary->Add(descs->GetKey(i), value, d);
3814 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4214 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3815 break; 4215 break;
3816 } 4216 }
3817 case FIELD: { 4217 case FIELD: {
3818 PropertyDetails d = PropertyDetails(details.attributes(), 4218 PropertyDetails d = PropertyDetails(details.attributes(),
3819 NORMAL, 4219 NORMAL,
4220 Representation::None(),
3820 details.descriptor_index()); 4221 details.descriptor_index());
3821 Object* value = FastPropertyAt(descs->GetFieldIndex(i)); 4222 Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3822 MaybeObject* maybe_dictionary = 4223 MaybeObject* maybe_dictionary =
3823 dictionary->Add(descs->GetKey(i), value, d); 4224 dictionary->Add(descs->GetKey(i), value, d);
3824 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4225 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3825 break; 4226 break;
3826 } 4227 }
3827 case CALLBACKS: { 4228 case CALLBACKS: {
3828 Object* value = descs->GetCallbacksObject(i); 4229 Object* value = descs->GetCallbacksObject(i);
3829 details = details.set_pointer(0); 4230 PropertyDetails d = PropertyDetails(details.attributes(),
4231 CALLBACKS,
4232 Representation::None(),
4233 details.descriptor_index());
3830 MaybeObject* maybe_dictionary = 4234 MaybeObject* maybe_dictionary =
3831 dictionary->Add(descs->GetKey(i), value, details); 4235 dictionary->Add(descs->GetKey(i), value, d);
3832 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4236 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3833 break; 4237 break;
3834 } 4238 }
3835 case INTERCEPTOR: 4239 case INTERCEPTOR:
3836 break; 4240 break;
3837 case HANDLER: 4241 case HANDLER:
3838 case NORMAL: 4242 case NORMAL:
3839 case TRANSITION: 4243 case TRANSITION:
3840 case NONEXISTENT: 4244 case NONEXISTENT:
3841 UNREACHABLE(); 4245 UNREACHABLE();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3955 // exceed the capacity of new space, and we would fail repeatedly 4359 // exceed the capacity of new space, and we would fail repeatedly
3956 // trying to convert the FixedDoubleArray. 4360 // trying to convert the FixedDoubleArray.
3957 MaybeObject* maybe_value_object = 4361 MaybeObject* maybe_value_object =
3958 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); 4362 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3959 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 4363 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3960 } 4364 }
3961 } else { 4365 } else {
3962 ASSERT(old_map->has_fast_smi_or_object_elements()); 4366 ASSERT(old_map->has_fast_smi_or_object_elements());
3963 value = FixedArray::cast(array)->get(i); 4367 value = FixedArray::cast(array)->get(i);
3964 } 4368 }
3965 PropertyDetails details = PropertyDetails(NONE, NORMAL); 4369 PropertyDetails details = PropertyDetails(
4370 NONE, NORMAL, Representation::None());
3966 if (!value->IsTheHole()) { 4371 if (!value->IsTheHole()) {
3967 Object* result; 4372 Object* result;
3968 MaybeObject* maybe_result = 4373 MaybeObject* maybe_result =
3969 dictionary->AddNumberEntry(i, value, details); 4374 dictionary->AddNumberEntry(i, value, details);
3970 if (!maybe_result->ToObject(&result)) return maybe_result; 4375 if (!maybe_result->ToObject(&result)) return maybe_result;
3971 dictionary = SeededNumberDictionary::cast(result); 4376 dictionary = SeededNumberDictionary::cast(result);
3972 } 4377 }
3973 } 4378 }
3974 4379
3975 // Switch to using the dictionary as the backing storage for elements. 4380 // Switch to using the dictionary as the backing storage for elements.
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
4911 for (int i = 0; i < limit; i++) { 5316 for (int i = 0; i < limit; i++) {
4912 if ((descs->GetDetails(i).attributes() & filter) == 0 && 5317 if ((descs->GetDetails(i).attributes() & filter) == 0 &&
4913 ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) { 5318 ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
4914 result++; 5319 result++;
4915 } 5320 }
4916 } 5321 }
4917 return result; 5322 return result;
4918 } 5323 }
4919 5324
4920 5325
4921 int Map::PropertyIndexFor(Name* name) {
4922 DescriptorArray* descs = instance_descriptors();
4923 int limit = NumberOfOwnDescriptors();
4924 for (int i = 0; i < limit; i++) {
4925 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
4926 }
4927 return -1;
4928 }
4929
4930
4931 int Map::NextFreePropertyIndex() { 5326 int Map::NextFreePropertyIndex() {
4932 int max_index = -1; 5327 int max_index = -1;
4933 int number_of_own_descriptors = NumberOfOwnDescriptors(); 5328 int number_of_own_descriptors = NumberOfOwnDescriptors();
4934 DescriptorArray* descs = instance_descriptors(); 5329 DescriptorArray* descs = instance_descriptors();
4935 for (int i = 0; i < number_of_own_descriptors; i++) { 5330 for (int i = 0; i < number_of_own_descriptors; i++) {
4936 if (descs->GetType(i) == FIELD) { 5331 if (descs->GetType(i) == FIELD) {
4937 int current_index = descs->GetFieldIndex(i); 5332 int current_index = descs->GetFieldIndex(i);
4938 if (current_index > max_index) max_index = current_index; 5333 if (current_index > max_index) max_index = current_index;
4939 } 5334 }
4940 } 5335 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
5034 Object* getter, 5429 Object* getter,
5035 Object* setter, 5430 Object* setter,
5036 PropertyAttributes attributes) { 5431 PropertyAttributes attributes) {
5037 int entry = dictionary->FindEntry(index); 5432 int entry = dictionary->FindEntry(index);
5038 if (entry != SeededNumberDictionary::kNotFound) { 5433 if (entry != SeededNumberDictionary::kNotFound) {
5039 Object* result = dictionary->ValueAt(entry); 5434 Object* result = dictionary->ValueAt(entry);
5040 PropertyDetails details = dictionary->DetailsAt(entry); 5435 PropertyDetails details = dictionary->DetailsAt(entry);
5041 if (details.type() == CALLBACKS && result->IsAccessorPair()) { 5436 if (details.type() == CALLBACKS && result->IsAccessorPair()) {
5042 ASSERT(!details.IsDontDelete()); 5437 ASSERT(!details.IsDontDelete());
5043 if (details.attributes() != attributes) { 5438 if (details.attributes() != attributes) {
5044 dictionary->DetailsAtPut(entry, 5439 dictionary->DetailsAtPut(
5045 PropertyDetails(attributes, CALLBACKS, index)); 5440 entry,
5441 PropertyDetails(
5442 attributes, CALLBACKS, Representation::None(), index));
5046 } 5443 }
5047 AccessorPair::cast(result)->SetComponents(getter, setter); 5444 AccessorPair::cast(result)->SetComponents(getter, setter);
5048 return true; 5445 return true;
5049 } 5446 }
5050 } 5447 }
5051 return false; 5448 return false;
5052 } 5449 }
5053 5450
5054 5451
5055 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, 5452 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
5196 } 5593 }
5197 } 5594 }
5198 5595
5199 return true; 5596 return true;
5200 } 5597 }
5201 5598
5202 5599
5203 MaybeObject* JSObject::SetElementCallback(uint32_t index, 5600 MaybeObject* JSObject::SetElementCallback(uint32_t index,
5204 Object* structure, 5601 Object* structure,
5205 PropertyAttributes attributes) { 5602 PropertyAttributes attributes) {
5206 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 5603 PropertyDetails details = PropertyDetails(
5604 attributes, CALLBACKS, Representation::None());
5207 5605
5208 // Normalize elements to make this operation simple. 5606 // Normalize elements to make this operation simple.
5209 SeededNumberDictionary* dictionary; 5607 SeededNumberDictionary* dictionary;
5210 { MaybeObject* maybe_dictionary = NormalizeElements(); 5608 { MaybeObject* maybe_dictionary = NormalizeElements();
5211 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 5609 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
5212 } 5610 }
5213 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 5611 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
5214 5612
5215 // Update the dictionary with the new CALLBACKS property. 5613 // Update the dictionary with the new CALLBACKS property.
5216 { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details); 5614 { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
5254 ASSERT(new_map->is_dictionary_map()); 5652 ASSERT(new_map->is_dictionary_map());
5255 5653
5256 set_map(new_map); 5654 set_map(new_map);
5257 // When running crankshaft, changing the map is not enough. We 5655 // When running crankshaft, changing the map is not enough. We
5258 // need to deoptimize all functions that rely on this global 5656 // need to deoptimize all functions that rely on this global
5259 // object. 5657 // object.
5260 Deoptimizer::DeoptimizeGlobalObject(this); 5658 Deoptimizer::DeoptimizeGlobalObject(this);
5261 } 5659 }
5262 5660
5263 // Update the dictionary with the new CALLBACKS property. 5661 // Update the dictionary with the new CALLBACKS property.
5264 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 5662 PropertyDetails details = PropertyDetails(
5663 attributes, CALLBACKS, Representation::None());
5265 maybe_ok = SetNormalizedProperty(name, structure, details); 5664 maybe_ok = SetNormalizedProperty(name, structure, details);
5266 if (maybe_ok->IsFailure()) return maybe_ok; 5665 if (maybe_ok->IsFailure()) return maybe_ok;
5267 5666
5268 return GetHeap()->undefined_value(); 5667 return GetHeap()->undefined_value();
5269 } 5668 }
5270 5669
5271 5670
5272 void JSObject::DefineAccessor(Handle<JSObject> object, 5671 void JSObject::DefineAccessor(Handle<JSObject> object,
5273 Handle<Name> name, 5672 Handle<Name> name,
5274 Handle<Object> getter, 5673 Handle<Object> getter,
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
5771 if (!maybe_result->To(&result)) return maybe_result; 6170 if (!maybe_result->To(&result)) return maybe_result;
5772 6171
5773 result->InitializeDescriptors(descriptors); 6172 result->InitializeDescriptors(descriptors);
5774 6173
5775 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 6174 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
5776 TransitionArray* transitions; 6175 TransitionArray* transitions;
5777 SimpleTransitionFlag simple_flag = 6176 SimpleTransitionFlag simple_flag =
5778 (descriptor_index == descriptors->number_of_descriptors() - 1) 6177 (descriptor_index == descriptors->number_of_descriptors() - 1)
5779 ? SIMPLE_TRANSITION 6178 ? SIMPLE_TRANSITION
5780 : FULL_TRANSITION; 6179 : FULL_TRANSITION;
6180 ASSERT(name == descriptors->GetKey(descriptor_index));
5781 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); 6181 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
5782 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 6182 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5783 6183
5784 set_transitions(transitions); 6184 set_transitions(transitions);
5785 result->SetBackPointer(this); 6185 result->SetBackPointer(this);
5786 } 6186 }
5787 6187
5788 return result; 6188 return result;
5789 } 6189 }
5790 6190
5791 6191
6192 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor,
6193 DescriptorArray* descriptors) {
6194 ASSERT(descriptors->IsSortedNoDuplicates());
6195
6196 Map* result;
6197 MaybeObject* maybe_result = CopyDropDescriptors();
6198 if (!maybe_result->To(&result)) return maybe_result;
6199
6200 result->InitializeDescriptors(descriptors);
6201 result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6202
6203 int unused_property_fields = this->unused_property_fields();
6204 if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
6205 unused_property_fields = this->unused_property_fields() - 1;
6206 if (unused_property_fields < 0) {
6207 unused_property_fields += JSObject::kFieldsAdded;
6208 }
6209 }
6210
6211 result->set_unused_property_fields(unused_property_fields);
6212 result->set_owns_descriptors(false);
6213
6214 if (CanHaveMoreTransitions()) {
6215 Name* name = descriptors->GetKey(new_descriptor);
6216 TransitionArray* transitions;
6217 MaybeObject* maybe_transitions =
6218 AddTransition(name, result, SIMPLE_TRANSITION);
6219 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
6220
6221 set_transitions(transitions);
6222 result->SetBackPointer(this);
6223 }
6224
6225 return result;
6226 }
6227
6228
5792 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 6229 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
5793 if (flag == INSERT_TRANSITION) { 6230 if (flag == INSERT_TRANSITION) {
5794 ASSERT(!HasElementsTransition() || 6231 ASSERT(!HasElementsTransition() ||
5795 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 6232 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
5796 IsExternalArrayElementsKind( 6233 IsExternalArrayElementsKind(
5797 elements_transition_map()->elements_kind())) && 6234 elements_transition_map()->elements_kind())) &&
5798 (kind == DICTIONARY_ELEMENTS || 6235 (kind == DICTIONARY_ELEMENTS ||
5799 IsExternalArrayElementsKind(kind)))); 6236 IsExternalArrayElementsKind(kind))));
5800 ASSERT(!IsFastElementsKind(kind) || 6237 ASSERT(!IsFastElementsKind(kind) ||
5801 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); 6238 IsMoreGeneralElementsKindTransition(elements_kind(), kind));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5850 JSFunction* ctor = JSFunction::cast(constructor()); 6287 JSFunction* ctor = JSFunction::cast(constructor());
5851 Map* map = ctor->initial_map(); 6288 Map* map = ctor->initial_map();
5852 DescriptorArray* descriptors = map->instance_descriptors(); 6289 DescriptorArray* descriptors = map->instance_descriptors();
5853 6290
5854 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 6291 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
5855 DescriptorArray* new_descriptors; 6292 DescriptorArray* new_descriptors;
5856 MaybeObject* maybe_descriptors = 6293 MaybeObject* maybe_descriptors =
5857 descriptors->CopyUpTo(number_of_own_descriptors); 6294 descriptors->CopyUpTo(number_of_own_descriptors);
5858 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 6295 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5859 6296
6297 new_descriptors->InitializeRepresentations(Representation::Tagged());
6298
5860 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); 6299 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5861 } 6300 }
5862 6301
5863 6302
5864 MaybeObject* Map::Copy() { 6303 MaybeObject* Map::Copy() {
5865 DescriptorArray* descriptors = instance_descriptors(); 6304 DescriptorArray* descriptors = instance_descriptors();
5866 DescriptorArray* new_descriptors; 6305 DescriptorArray* new_descriptors;
5867 int number_of_own_descriptors = NumberOfOwnDescriptors(); 6306 int number_of_own_descriptors = NumberOfOwnDescriptors();
5868 MaybeObject* maybe_descriptors = 6307 MaybeObject* maybe_descriptors =
5869 descriptors->CopyUpTo(number_of_own_descriptors); 6308 descriptors->CopyUpTo(number_of_own_descriptors);
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
6805 DescriptorArray* src, 7244 DescriptorArray* src,
6806 int src_index, 7245 int src_index,
6807 const WhitenessWitness& witness) { 7246 const WhitenessWitness& witness) {
6808 Object* value = src->GetValue(src_index); 7247 Object* value = src->GetValue(src_index);
6809 PropertyDetails details = src->GetDetails(src_index); 7248 PropertyDetails details = src->GetDetails(src_index);
6810 Descriptor desc(src->GetKey(src_index), value, details); 7249 Descriptor desc(src->GetKey(src_index), value, details);
6811 Set(dst_index, &desc, witness); 7250 Set(dst_index, &desc, witness);
6812 } 7251 }
6813 7252
6814 7253
7254 // Generalize the |other| descriptor array by merging it with the (at least
7255 // partly) updated |this| descriptor array.
7256 // The method merges two descriptor array in three parts. Both descriptor arrays
7257 // are identical up to |verbatim|. They also overlap in keys up to |valid|.
7258 // Between |verbatim| and |valid|, the resulting descriptor type as well as the
7259 // representation are generalized from both |this| and |other|. Beyond |valid|,
7260 // the descriptors are copied verbatim from |other| up to |new_size|.
7261 // In case of incompatible types, the type and representation of |other| is
7262 // used.
7263 MaybeObject* DescriptorArray::Merge(int verbatim,
7264 int valid,
7265 int new_size,
7266 DescriptorArray* other) {
7267 ASSERT(verbatim <= valid);
7268 ASSERT(valid <= new_size);
7269
7270 DescriptorArray* result;
7271 // Allocate a new descriptor array large enough to hold the required
7272 // descriptors, with minimally the exact same size as this descriptor array.
7273 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
7274 new_size, Max(new_size, number_of_descriptors()) - new_size);
7275 if (!maybe_descriptors->To(&result)) return maybe_descriptors;
7276 ASSERT(result->length() > length() ||
7277 result->NumberOfSlackDescriptors() > 0 ||
7278 result->number_of_descriptors() == other->number_of_descriptors());
7279 ASSERT(result->number_of_descriptors() == new_size);
7280
7281 DescriptorArray::WhitenessWitness witness(result);
7282
7283 int descriptor;
7284
7285 int current_offset = 0;
7286 for (descriptor = 0; descriptor < verbatim; descriptor++) {
7287 if (GetDetails(descriptor).type() == FIELD) current_offset++;
7288 result->CopyFrom(descriptor, this, descriptor, witness);
7289 }
7290
7291 for (; descriptor < valid; descriptor++) {
7292 Name* key = GetKey(descriptor);
7293 PropertyDetails details = GetDetails(descriptor);
7294 PropertyDetails other_details = other->GetDetails(descriptor);
7295 ASSERT(details.attributes() == other_details.attributes());
7296
7297 if (details.type() == FIELD) {
7298 ASSERT(other_details.type() != CALLBACKS);
7299 Representation representation =
7300 details.representation().generalize(other_details.representation());
7301 FieldDescriptor d(key,
7302 current_offset++,
7303 details.attributes(),
7304 representation,
7305 descriptor + 1);
7306 result->Set(descriptor, &d, witness);
7307 } else if (other_details.type() == FIELD) {
7308 Representation representation =
7309 details.representation().generalize(other_details.representation());
7310 FieldDescriptor d(key,
7311 current_offset++,
7312 details.attributes(),
7313 representation,
7314 descriptor + 1);
7315 result->Set(descriptor, &d, witness);
7316 } else if (other_details.type() == CONSTANT_FUNCTION) {
7317 Object* value = GetValue(descriptor);
7318 Object* other_value = other->GetValue(descriptor);
7319 if (details.type() == CONSTANT_FUNCTION && value != other_value) {
7320 FieldDescriptor d(key,
7321 current_offset++,
7322 details.attributes(),
7323 Representation::Tagged(),
7324 descriptor + 1);
7325 result->Set(descriptor, &d, witness);
7326 } else {
7327 ConstantFunctionDescriptor d(key,
7328 JSFunction::cast(other_value),
7329 details.attributes(),
7330 descriptor + 1);
7331 result->Set(descriptor, &d, witness);
7332 }
7333 } else {
7334 ASSERT(other_details.type() != FIELD);
7335 result->CopyFrom(descriptor, other, descriptor, witness);
7336 }
7337 }
7338
7339 for (; descriptor < new_size; descriptor++) {
7340 PropertyDetails details = other->GetDetails(descriptor);
7341 if (details.type() == FIELD) {
7342 Name* key = other->GetKey(descriptor);
7343 FieldDescriptor d(key,
7344 current_offset++,
7345 details.attributes(),
7346 details.representation(),
7347 descriptor + 1);
7348 result->Set(descriptor, &d, witness);
7349 } else {
7350 result->CopyFrom(descriptor, other, descriptor, witness);
7351 }
7352 }
7353
7354 result->Sort();
7355 return result;
7356 }
7357
7358
6815 // We need the whiteness witness since sort will reshuffle the entries in the 7359 // We need the whiteness witness since sort will reshuffle the entries in the
6816 // descriptor array. If the descriptor array were to be black, the shuffling 7360 // descriptor array. If the descriptor array were to be black, the shuffling
6817 // would move a slot that was already recorded as pointing into an evacuation 7361 // would move a slot that was already recorded as pointing into an evacuation
6818 // candidate. This would result in missing updates upon evacuation. 7362 // candidate. This would result in missing updates upon evacuation.
6819 void DescriptorArray::Sort() { 7363 void DescriptorArray::Sort() {
6820 // In-place heap sort. 7364 // In-place heap sort.
6821 int len = number_of_descriptors(); 7365 int len = number_of_descriptors();
6822 // Reset sorting since the descriptor array might contain invalid pointers. 7366 // Reset sorting since the descriptor array might contain invalid pointers.
6823 for (int i = 0; i < len; ++i) SetSortedKey(i, i); 7367 for (int i = 0; i < len; ++i) SetSortedKey(i, i);
6824 // Bottom-up max-heap construction. 7368 // Bottom-up max-heap construction.
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after
8166 // XOR-ing the prototype and constructor directly yields too many zero bits 8710 // XOR-ing the prototype and constructor directly yields too many zero bits
8167 // when the two pointers are close (which is fairly common). 8711 // when the two pointers are close (which is fairly common).
8168 // To avoid this we shift the prototype 4 bits relatively to the constructor. 8712 // To avoid this we shift the prototype 4 bits relatively to the constructor.
8169 hash ^= (static_cast<uint32_t>( 8713 hash ^= (static_cast<uint32_t>(
8170 reinterpret_cast<uintptr_t>(prototype())) << 2); 8714 reinterpret_cast<uintptr_t>(prototype())) << 2);
8171 8715
8172 return hash ^ (hash >> 16) ^ bit_field2(); 8716 return hash ^ (hash >> 16) ^ bit_field2();
8173 } 8717 }
8174 8718
8175 8719
8720 static bool CheckEquivalent(Map* first, Map* second) {
8721 return
8722 first->constructor() == second->constructor() &&
8723 first->prototype() == second->prototype() &&
8724 first->instance_type() == second->instance_type() &&
8725 first->bit_field() == second->bit_field() &&
8726 first->bit_field2() == second->bit_field2() &&
8727 first->is_observed() == second->is_observed() &&
8728 first->function_with_prototype() == second->function_with_prototype();
8729 }
8730
8731
8732 bool Map::EquivalentToForTransition(Map* other) {
8733 return CheckEquivalent(this, other);
8734 }
8735
8736
8176 bool Map::EquivalentToForNormalization(Map* other, 8737 bool Map::EquivalentToForNormalization(Map* other,
8177 PropertyNormalizationMode mode) { 8738 PropertyNormalizationMode mode) {
8178 return 8739 int properties = mode == CLEAR_INOBJECT_PROPERTIES
8179 constructor() == other->constructor() && 8740 ? 0 : other->inobject_properties();
8180 prototype() == other->prototype() && 8741 return CheckEquivalent(this, other) && inobject_properties() == properties;
8181 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
8182 0 :
8183 other->inobject_properties()) &&
8184 instance_type() == other->instance_type() &&
8185 bit_field() == other->bit_field() &&
8186 bit_field2() == other->bit_field2() &&
8187 is_observed() == other->is_observed() &&
8188 function_with_prototype() == other->function_with_prototype();
8189 } 8742 }
8190 8743
8191 8744
8192 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { 8745 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
8193 // Iterate over all fields in the body but take care in dealing with 8746 // Iterate over all fields in the body but take care in dealing with
8194 // the code entry. 8747 // the code entry.
8195 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); 8748 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
8196 v->VisitCodeEntry(this->address() + kCodeEntryOffset); 8749 v->VisitCodeEntry(this->address() + kCodeEntryOffset);
8197 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); 8750 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
8198 } 8751 }
(...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after
10593 Object* element = dictionary->ValueAt(entry); 11146 Object* element = dictionary->ValueAt(entry);
10594 PropertyDetails details = dictionary->DetailsAt(entry); 11147 PropertyDetails details = dictionary->DetailsAt(entry);
10595 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { 11148 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
10596 return SetElementWithCallback(element, index, *value, this, strict_mode); 11149 return SetElementWithCallback(element, index, *value, this, strict_mode);
10597 } else { 11150 } else {
10598 dictionary->UpdateMaxNumberKey(index); 11151 dictionary->UpdateMaxNumberKey(index);
10599 // If a value has not been initialized we allow writing to it even if it 11152 // If a value has not been initialized we allow writing to it even if it
10600 // is read-only (a declared const that has not been initialized). If a 11153 // is read-only (a declared const that has not been initialized). If a
10601 // value is being defined we skip attribute checks completely. 11154 // value is being defined we skip attribute checks completely.
10602 if (set_mode == DEFINE_PROPERTY) { 11155 if (set_mode == DEFINE_PROPERTY) {
10603 details = PropertyDetails( 11156 details = PropertyDetails(attributes, NORMAL, Representation::None(),
10604 attributes, NORMAL, details.dictionary_index()); 11157 details.dictionary_index());
10605 dictionary->DetailsAtPut(entry, details); 11158 dictionary->DetailsAtPut(entry, details);
10606 } else if (details.IsReadOnly() && !element->IsTheHole()) { 11159 } else if (details.IsReadOnly() && !element->IsTheHole()) {
10607 if (strict_mode == kNonStrictMode) { 11160 if (strict_mode == kNonStrictMode) {
10608 return isolate->heap()->undefined_value(); 11161 return isolate->heap()->undefined_value();
10609 } else { 11162 } else {
10610 Handle<Object> holder(this, isolate); 11163 Handle<Object> holder(this, isolate);
10611 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); 11164 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
10612 Handle<Object> args[2] = { number, holder }; 11165 Handle<Object> args[2] = { number, holder };
10613 Handle<Object> error = 11166 Handle<Object> error =
10614 isolate->factory()->NewTypeError("strict_read_only_property", 11167 isolate->factory()->NewTypeError("strict_read_only_property",
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
10646 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); 11199 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
10647 Handle<String> name = isolate->factory()->NumberToString(number); 11200 Handle<String> name = isolate->factory()->NumberToString(number);
10648 Handle<Object> args[1] = { name }; 11201 Handle<Object> args[1] = { name };
10649 Handle<Object> error = 11202 Handle<Object> error =
10650 isolate->factory()->NewTypeError("object_not_extensible", 11203 isolate->factory()->NewTypeError("object_not_extensible",
10651 HandleVector(args, 1)); 11204 HandleVector(args, 1));
10652 return isolate->Throw(*error); 11205 return isolate->Throw(*error);
10653 } 11206 }
10654 } 11207 }
10655 FixedArrayBase* new_dictionary; 11208 FixedArrayBase* new_dictionary;
10656 PropertyDetails details = PropertyDetails(attributes, NORMAL); 11209 PropertyDetails details = PropertyDetails(
11210 attributes, NORMAL, Representation::None());
10657 MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details); 11211 MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details);
10658 if (!maybe->To(&new_dictionary)) return maybe; 11212 if (!maybe->To(&new_dictionary)) return maybe;
10659 if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) { 11213 if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) {
10660 if (is_arguments) { 11214 if (is_arguments) {
10661 elements->set(1, new_dictionary); 11215 elements->set(1, new_dictionary);
10662 } else { 11216 } else {
10663 self->set_elements(new_dictionary); 11217 self->set_elements(new_dictionary);
10664 } 11218 }
10665 dictionary = 11219 dictionary =
10666 handle(SeededNumberDictionary::cast(new_dictionary), isolate); 11220 handle(SeededNumberDictionary::cast(new_dictionary), isolate);
(...skipping 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after
12640 // Adding an entry with the key beyond smi-range requires 13194 // Adding an entry with the key beyond smi-range requires
12641 // allocation. Bailout. 13195 // allocation. Bailout.
12642 return Smi::FromInt(-1); 13196 return Smi::FromInt(-1);
12643 } 13197 }
12644 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); 13198 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
12645 } 13199 }
12646 } 13200 }
12647 } 13201 }
12648 13202
12649 uint32_t result = pos; 13203 uint32_t result = pos;
12650 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); 13204 PropertyDetails no_details = PropertyDetails(
13205 NONE, NORMAL, Representation::None());
12651 Heap* heap = GetHeap(); 13206 Heap* heap = GetHeap();
12652 while (undefs > 0) { 13207 while (undefs > 0) {
12653 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 13208 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
12654 // Adding an entry with the key beyond smi-range requires 13209 // Adding an entry with the key beyond smi-range requires
12655 // allocation. Bailout. 13210 // allocation. Bailout.
12656 return Smi::FromInt(-1); 13211 return Smi::FromInt(-1);
12657 } 13212 }
12658 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> 13213 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
12659 ToObjectUnchecked(); 13214 ToObjectUnchecked();
12660 pos++; 13215 pos++;
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
12998 MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) { 13553 MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) {
12999 ASSERT(!HasFastProperties()); 13554 ASSERT(!HasFastProperties());
13000 int entry = property_dictionary()->FindEntry(name); 13555 int entry = property_dictionary()->FindEntry(name);
13001 if (entry == NameDictionary::kNotFound) { 13556 if (entry == NameDictionary::kNotFound) {
13002 Heap* heap = GetHeap(); 13557 Heap* heap = GetHeap();
13003 Object* cell; 13558 Object* cell;
13004 { MaybeObject* maybe_cell = 13559 { MaybeObject* maybe_cell =
13005 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); 13560 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
13006 if (!maybe_cell->ToObject(&cell)) return maybe_cell; 13561 if (!maybe_cell->ToObject(&cell)) return maybe_cell;
13007 } 13562 }
13008 PropertyDetails details(NONE, NORMAL); 13563 PropertyDetails details(NONE, NORMAL, Representation::None());
13009 details = details.AsDeleted(); 13564 details = details.AsDeleted();
13010 Object* dictionary; 13565 Object* dictionary;
13011 { MaybeObject* maybe_dictionary = 13566 { MaybeObject* maybe_dictionary =
13012 property_dictionary()->Add(name, cell, details); 13567 property_dictionary()->Add(name, cell, details);
13013 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; 13568 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
13014 } 13569 }
13015 set_properties(NameDictionary::cast(dictionary)); 13570 set_properties(NameDictionary::cast(dictionary));
13016 return cell; 13571 return cell;
13017 } else { 13572 } else {
13018 Object* value = property_dictionary()->ValueAt(entry); 13573 Object* value = property_dictionary()->ValueAt(entry);
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
13440 enumeration_order->set(index, Smi::FromInt(enum_index)); 13995 enumeration_order->set(index, Smi::FromInt(enum_index));
13441 } 13996 }
13442 13997
13443 // Update the dictionary with new indices. 13998 // Update the dictionary with new indices.
13444 capacity = HashTable<Shape, Key>::Capacity(); 13999 capacity = HashTable<Shape, Key>::Capacity();
13445 pos = 0; 14000 pos = 0;
13446 for (int i = 0; i < capacity; i++) { 14001 for (int i = 0; i < capacity; i++) {
13447 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { 14002 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
13448 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); 14003 int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
13449 PropertyDetails details = DetailsAt(i); 14004 PropertyDetails details = DetailsAt(i);
13450 PropertyDetails new_details = 14005 PropertyDetails new_details = PropertyDetails(
13451 PropertyDetails(details.attributes(), details.type(), enum_index); 14006 details.attributes(), details.type(),
14007 Representation::None(), enum_index);
13452 DetailsAtPut(i, new_details); 14008 DetailsAtPut(i, new_details);
13453 } 14009 }
13454 } 14010 }
13455 14011
13456 // Set the next enumeration index. 14012 // Set the next enumeration index.
13457 SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); 14013 SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
13458 return this; 14014 return this;
13459 } 14015 }
13460 14016
13461 template<typename Shape, typename Key> 14017 template<typename Shape, typename Key>
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
13507 // Check whether the dictionary should be extended. 14063 // Check whether the dictionary should be extended.
13508 Object* obj; 14064 Object* obj;
13509 { MaybeObject* maybe_obj = EnsureCapacity(1, key); 14065 { MaybeObject* maybe_obj = EnsureCapacity(1, key);
13510 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 14066 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13511 } 14067 }
13512 14068
13513 Object* k; 14069 Object* k;
13514 { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key); 14070 { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key);
13515 if (!maybe_k->ToObject(&k)) return maybe_k; 14071 if (!maybe_k->ToObject(&k)) return maybe_k;
13516 } 14072 }
13517 PropertyDetails details = PropertyDetails(NONE, NORMAL); 14073 PropertyDetails details = PropertyDetails(
14074 NONE, NORMAL, Representation::None());
13518 14075
13519 return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details, 14076 return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
13520 Dictionary<Shape, Key>::Hash(key)); 14077 Dictionary<Shape, Key>::Hash(key));
13521 } 14078 }
13522 14079
13523 14080
13524 template<typename Shape, typename Key> 14081 template<typename Shape, typename Key>
13525 MaybeObject* Dictionary<Shape, Key>::Add(Key key, 14082 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
13526 Object* value, 14083 Object* value,
13527 PropertyDetails details) { 14084 PropertyDetails details) {
(...skipping 25 matching lines...) Expand all
13553 } 14110 }
13554 14111
13555 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); 14112 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
13556 // Insert element at empty or deleted entry 14113 // Insert element at empty or deleted entry
13557 if (!details.IsDeleted() && 14114 if (!details.IsDeleted() &&
13558 details.dictionary_index() == 0 && 14115 details.dictionary_index() == 0 &&
13559 Shape::kIsEnumerable) { 14116 Shape::kIsEnumerable) {
13560 // Assign an enumeration index to the property and update 14117 // Assign an enumeration index to the property and update
13561 // SetNextEnumerationIndex. 14118 // SetNextEnumerationIndex.
13562 int index = NextEnumerationIndex(); 14119 int index = NextEnumerationIndex();
13563 details = PropertyDetails(details.attributes(), details.type(), index); 14120 details = PropertyDetails(details.attributes(), details.type(),
14121 Representation::None(), index);
13564 SetNextEnumerationIndex(index + 1); 14122 SetNextEnumerationIndex(index + 1);
13565 } 14123 }
13566 SetEntry(entry, k, value, details); 14124 SetEntry(entry, k, value, details);
13567 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() || 14125 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() ||
13568 Dictionary<Shape, Key>::KeyAt(entry)->IsName())); 14126 Dictionary<Shape, Key>::KeyAt(entry)->IsName()));
13569 HashTable<Shape, Key>::ElementAdded(); 14127 HashTable<Shape, Key>::ElementAdded();
13570 return this; 14128 return this;
13571 } 14129 }
13572 14130
13573 14131
(...skipping 21 matching lines...) Expand all
13595 PropertyDetails details) { 14153 PropertyDetails details) {
13596 UpdateMaxNumberKey(key); 14154 UpdateMaxNumberKey(key);
13597 SLOW_ASSERT(this->FindEntry(key) == kNotFound); 14155 SLOW_ASSERT(this->FindEntry(key) == kNotFound);
13598 return Add(key, value, details); 14156 return Add(key, value, details);
13599 } 14157 }
13600 14158
13601 14159
13602 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key, 14160 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
13603 Object* value) { 14161 Object* value) {
13604 SLOW_ASSERT(this->FindEntry(key) == kNotFound); 14162 SLOW_ASSERT(this->FindEntry(key) == kNotFound);
13605 return Add(key, value, PropertyDetails(NONE, NORMAL)); 14163 return Add(key, value, PropertyDetails(NONE, NORMAL, Representation::None()));
13606 } 14164 }
13607 14165
13608 14166
13609 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) { 14167 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
13610 UpdateMaxNumberKey(key); 14168 UpdateMaxNumberKey(key);
13611 return AtPut(key, value); 14169 return AtPut(key, value);
13612 } 14170 }
13613 14171
13614 14172
13615 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key, 14173 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
(...skipping 24 matching lines...) Expand all
13640 14198
13641 14199
13642 MaybeObject* SeededNumberDictionary::Set(uint32_t key, 14200 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
13643 Object* value, 14201 Object* value,
13644 PropertyDetails details) { 14202 PropertyDetails details) {
13645 int entry = FindEntry(key); 14203 int entry = FindEntry(key);
13646 if (entry == kNotFound) return AddNumberEntry(key, value, details); 14204 if (entry == kNotFound) return AddNumberEntry(key, value, details);
13647 // Preserve enumeration index. 14205 // Preserve enumeration index.
13648 details = PropertyDetails(details.attributes(), 14206 details = PropertyDetails(details.attributes(),
13649 details.type(), 14207 details.type(),
14208 Representation::None(),
13650 DetailsAt(entry).dictionary_index()); 14209 DetailsAt(entry).dictionary_index());
13651 MaybeObject* maybe_object_key = 14210 MaybeObject* maybe_object_key =
13652 SeededNumberDictionaryShape::AsObject(GetHeap(), key); 14211 SeededNumberDictionaryShape::AsObject(GetHeap(), key);
13653 Object* object_key; 14212 Object* object_key;
13654 if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; 14213 if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
13655 SetEntry(entry, object_key, value, details); 14214 SetEntry(entry, object_key, value, details);
13656 return this; 14215 return this;
13657 } 14216 }
13658 14217
13659 14218
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
13914 obj->InObjectPropertyAtPut(current_offset, 14473 obj->InObjectPropertyAtPut(current_offset,
13915 value, 14474 value,
13916 UPDATE_WRITE_BARRIER); 14475 UPDATE_WRITE_BARRIER);
13917 } else { 14476 } else {
13918 int offset = current_offset - inobject_props; 14477 int offset = current_offset - inobject_props;
13919 fields->set(offset, value); 14478 fields->set(offset, value);
13920 } 14479 }
13921 FieldDescriptor d(key, 14480 FieldDescriptor d(key,
13922 current_offset++, 14481 current_offset++,
13923 details.attributes(), 14482 details.attributes(),
14483 // TODO(verwaest): value->RequiredRepresentation();
14484 Representation::Tagged(),
13924 enumeration_index); 14485 enumeration_index);
13925 descriptors->Set(enumeration_index - 1, &d, witness); 14486 descriptors->Set(enumeration_index - 1, &d, witness);
13926 } else if (type == CALLBACKS) { 14487 } else if (type == CALLBACKS) {
13927 CallbacksDescriptor d(key, 14488 CallbacksDescriptor d(key,
13928 value, 14489 value,
13929 details.attributes(), 14490 details.attributes(),
13930 enumeration_index); 14491 enumeration_index);
13931 descriptors->Set(enumeration_index - 1, &d, witness); 14492 descriptors->Set(enumeration_index - 1, &d, witness);
13932 } else { 14493 } else {
13933 UNREACHABLE(); 14494 UNREACHABLE();
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
14505 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 15066 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
14506 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 15067 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
14507 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 15068 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
14508 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 15069 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
14509 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 15070 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
14510 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 15071 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
14511 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 15072 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
14512 } 15073 }
14513 15074
14514 } } // namespace v8::internal 15075 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698