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

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: Add test for tracking fields 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
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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->OptimalRepresentation(), 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->DeprecateTransitionTree();
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->OptimalRepresentation(), 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.
2173 int number_of_fields = NumberOfFields();
2174 ASSERT(target_number_of_fields >= number_of_fields);
2175 if (target_number_of_fields != number_of_fields) return true;
2176 // If no fields were added, and no inobject properties were removed, setting
2177 // the map is sufficient.
2178 if (target_inobject == inobject_properties()) return false;
2179 // In-object slack tracking may have reduced the object size of the new map.
2180 // In that case, succeed if all existing fields were inobject, and they still
2181 // fit within the new inobject size.
2182 ASSERT(target_inobject < inobject_properties());
2183 if (target_number_of_fields <= target_inobject) {
2184 ASSERT(target_number_of_fields + target_unused == target_inobject);
2185 return false;
2186 }
2187 // Otherwise, properties will need to be moved to the backing store.
2188 return true;
2189 }
2190
2191
2192 // To migrate an instance to a map:
2193 // - First check whether the instance needs to be rewritten. If not, simply
2194 // change the map.
2195 // - Otherwise, allocate a fixed array large enough to hold all fields, in
2196 // addition to unused space.
2197 // - Copy all existing properties in, in the following order: backing store
2198 // properties, unused fields, inobject properties.
2199 // - If all allocation succeeded, commit the state atomically:
2200 // * Copy inobject properties from the backing store back into the object.
2201 // * Trim the difference in instance size of the object. This also cleanly
2202 // frees inobject properties that moved to the backing store.
2203 // * If there are properties left in the backing store, trim of the space used
2204 // to temporarily store the inobject properties.
2205 // * If there are properties left in the backing store, install the backing
2206 // store.
2207 MaybeObject* JSObject::MigrateToMap(Map* new_map) {
2208 Heap* heap = GetHeap();
2209 Map* old_map = map();
2210 int number_of_fields = new_map->NumberOfFields();
2211 int inobject = new_map->inobject_properties();
2212 int unused = new_map->unused_property_fields();
2213
2214 // Nothing to do if no functions were converted to fields.
2215 if (!old_map->InstancesNeedRewriting(number_of_fields, inobject, unused)) {
2216 set_map(new_map);
2217 return this;
2218 }
2219
2220 int total_size = number_of_fields + unused;
2221 int external = total_size - inobject;
2222 FixedArray* array;
2223 MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
2224 if (!maybe_array->To(&array)) return maybe_array;
2225
2226 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2227 DescriptorArray* new_descriptors = new_map->instance_descriptors();
2228 int descriptors = new_map->NumberOfOwnDescriptors();
2229
2230 for (int i = 0; i < descriptors; i++) {
2231 PropertyDetails details = new_descriptors->GetDetails(i);
2232 if (details.type() != FIELD) continue;
2233 PropertyDetails old_details = old_descriptors->GetDetails(i);
2234 ASSERT(old_details.type() == CONSTANT_FUNCTION ||
2235 old_details.type() == FIELD);
2236 Object* value = old_details.type() == CONSTANT_FUNCTION
2237 ? old_descriptors->GetValue(i)
2238 : FastPropertyAt(old_descriptors->GetFieldIndex(i));
2239 int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2240 if (target_index < 0) target_index += total_size;
2241 array->set(target_index, value);
2242 }
2243
2244 // From here on we cannot fail anymore.
2245
2246 // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2247 // avoid overwriting |one_pointer_filler_map|.
2248 int limit = Min(inobject, number_of_fields);
2249 for (int i = 0; i < limit; i++) {
2250 FastPropertyAtPut(i, array->get(external + i));
2251 }
2252
2253 // Create filler object past the new instance size.
2254 int new_instance_size = new_map->instance_size();
2255 int instance_size_delta = old_map->instance_size() - new_instance_size;
2256 ASSERT(instance_size_delta >= 0);
2257 Address address = this->address() + new_instance_size;
2258 heap->CreateFillerObjectAt(address, instance_size_delta);
2259
2260 // If there are properties in the new backing store, trim it to the correct
2261 // size and install the backing store into the object.
2262 if (external > 0) {
2263 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
2264 set_properties(array);
2265 }
2266
2267 set_map(new_map);
2268
2269 return this;
2270 }
2271
2272
2273 MaybeObject* JSObject::GeneralizeFieldRepresentation(
2274 int modify_index,
2275 Representation new_representation) {
2276 Map* new_map;
2277 MaybeObject* maybe_new_map =
2278 map()->GeneralizeRepresentation(modify_index, new_representation);
2279 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2280 ASSERT(map() != new_map || new_map->FindRootMap()->is_deprecated());
2281
2282 return MigrateToMap(new_map);
2283 }
2284
2285
2286 int Map::NumberOfFields() {
2287 DescriptorArray* descriptors = instance_descriptors();
2288 int result = 0;
2289 for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2290 if (descriptors->GetDetails(i).type() == FIELD) result++;
2291 }
2292 return result;
2293 }
2294
2295
2296 MaybeObject* Map::CopyGeneralizeAllRepresentations() {
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::DeprecateTransitionTree() {
2308 if (!FLAG_track_fields) return;
2309 if (is_deprecated()) return;
2310 if (HasTransitionArray()) {
2311 TransitionArray* transitions = this->transitions();
2312 for (int i = 0; i < transitions->number_of_transitions(); i++) {
2313 transitions->GetTarget(i)->DeprecateTransitionTree();
2314 }
2315 }
2316 deprecate();
2317 dependent_code()->DeoptimizeDependentCodeGroup(
2318 GetIsolate(), DependentCode::kTransitionGroup);
2319 dependent_code()->DeoptimizeDependentCodeGroup(
2320 GetIsolate(), DependentCode::kPrototypeCheckGroup);
2321 }
2322
2323
2324 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2325 // the current instance_descriptors to ensure proper sharing of descriptor
2326 // arrays.
2327 void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
2328 if (HasTransitionArray()) {
2329 TransitionArray* transitions = this->transitions();
2330 int transition = transitions->Search(key);
2331 if (transition != TransitionArray::kNotFound) {
2332 transitions->GetTarget(transition)->DeprecateTransitionTree();
2333 }
2334 }
2335
2336 // Don't overwrite the empty descriptor array.
2337 if (NumberOfOwnDescriptors() == 0) return;
2338
2339 DescriptorArray* to_replace = instance_descriptors();
2340 Map* current = this;
2341 while (current->instance_descriptors() == to_replace) {
2342 current->SetEnumLength(Map::kInvalidEnumCache);
2343 current->set_instance_descriptors(new_descriptors);
2344 Object* next = current->GetBackPointer();
2345 if (next->IsUndefined()) break;
2346 current = Map::cast(next);
2347 }
2348
2349 set_owns_descriptors(false);
2350 }
2351
2352
2353 Map* Map::FindRootMap() {
2354 Map* result = this;
2355 while (true) {
2356 Object* back = result->GetBackPointer();
2357 if (back->IsUndefined()) return result;
2358 result = Map::cast(back);
2359 }
2360 }
2361
2362
2363 Map* Map::FindUpdatedMap(int verbatim,
2364 int length,
2365 DescriptorArray* descriptors) {
2366 // This can only be called on roots of transition trees.
2367 ASSERT(GetBackPointer()->IsUndefined());
2368
2369 Map* current = this;
2370
2371 for (int i = verbatim; i < length; i++) {
2372 if (!current->HasTransitionArray()) break;
2373 Name* name = descriptors->GetKey(i);
2374 TransitionArray* transitions = current->transitions();
2375 int transition = transitions->Search(name);
2376 if (transition == TransitionArray::kNotFound) break;
2377 current = transitions->GetTarget(transition);
2378 }
2379
2380 return current;
2381 }
2382
2383
2384 Map* Map::FindLastMatchMap(int verbatim,
2385 int length,
2386 DescriptorArray* descriptors) {
2387 // This can only be called on roots of transition trees.
2388 ASSERT(GetBackPointer()->IsUndefined());
2389
2390 Map* current = this;
2391
2392 for (int i = verbatim; i < length; i++) {
2393 if (!current->HasTransitionArray()) break;
2394 Name* name = descriptors->GetKey(i);
2395 TransitionArray* transitions = current->transitions();
2396 int transition = transitions->Search(name);
2397 if (transition == TransitionArray::kNotFound) break;
2398
2399 Map* next = transitions->GetTarget(transition);
2400 DescriptorArray* next_descriptors = next->instance_descriptors();
2401
2402 if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
2403
2404 PropertyDetails details = descriptors->GetDetails(i);
2405 PropertyDetails next_details = next_descriptors->GetDetails(i);
2406 if (details.type() != next_details.type()) break;
2407 if (details.attributes() != next_details.attributes()) break;
2408 if (!details.representation().Equals(next_details.representation())) break;
2409 ASSERT(!details.IsDeleted());
2410 ASSERT(!next_details.IsDeleted());
2411
2412 current = next;
2413 }
2414 return current;
2415 }
2416
2417
2418 // Generalize the representation of the descriptor at |modify_index|.
2419 // This method rewrites the transition tree to reflect the new change. To avoid
2420 // high degrees over polymorphism, and to stabilize quickly, on every rewrite
2421 // the new type is deduced by merging the current type with any potential new
2422 // (partial) version of the type in the transition tree.
2423 // To do this, on each rewrite:
2424 // - Search the root of the transition tree using FindRootMap.
2425 // - Find |updated|, the newest matching version of this map using
2426 // FindUpdatedMap. This uses the keys in the own map's descriptor array to
2427 // walk the transition tree.
2428 // - Merge/generalize the descriptor array of the current map and |updated|.
2429 // - Generalize the |modify_index| descriptor using |new_representation|.
2430 // - Walk the tree again starting from the root towards |updated|. Stop at
2431 // |split_map|, the first map who's descriptor array does not match the merged
2432 // descriptor array.
2433 // - If |updated| == |split_map|, |updated| is in the expected state. Return it.
2434 // - Otherwise, invalidate the outdated transition target from |updated|, and
2435 // replace its transition tree with a new branch for the updated descriptors.
2436 MaybeObject* Map::GeneralizeRepresentation(int modify_index,
2437 Representation new_representation) {
2438 Map* old_map = this;
2439 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2440 Representation old_reprepresentation =
2441 old_descriptors->GetDetails(modify_index).representation();
2442
2443 if (old_reprepresentation.IsNone()) {
2444 UNREACHABLE();
2445 old_descriptors->SetRepresentation(modify_index, new_representation);
2446 return this;
2447 }
2448
2449 int descriptors = old_map->NumberOfOwnDescriptors();
2450 Map* root_map = old_map->FindRootMap();
2451
2452 if (!old_map->EquivalentToForTransition(root_map)) {
2453 return CopyGeneralizeAllRepresentations();
2454 }
2455
2456 int verbatim = root_map->NumberOfOwnDescriptors();
2457
2458 Map* updated = root_map->FindUpdatedMap(
2459 verbatim, descriptors, old_descriptors);
2460 // Check the state of the root map.
2461 DescriptorArray* updated_descriptors = updated->instance_descriptors();
2462
2463 DescriptorArray* new_descriptors;
2464 MaybeObject* maybe_descriptors = updated_descriptors->Merge(
2465 verbatim,
2466 updated->NumberOfOwnDescriptors(),
2467 descriptors,
2468 old_descriptors);
2469 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
2470
2471 old_reprepresentation =
2472 new_descriptors->GetDetails(modify_index).representation();
2473 new_representation = new_representation.generalize(old_reprepresentation);
2474 new_descriptors->SetRepresentation(modify_index, new_representation);
2475
2476 Map* split_map = root_map->FindLastMatchMap(
2477 verbatim, descriptors, new_descriptors);
2478
2479 int split_descriptors = split_map->NumberOfOwnDescriptors();
2480 // Check whether |split_map| matches what we were looking for. If so, return
2481 // it.
2482 if (descriptors == split_descriptors) return split_map;
2483
2484 int descriptor = split_descriptors;
2485 split_map->DeprecateTarget(
2486 old_descriptors->GetKey(descriptor), new_descriptors);
2487
2488 Map* new_map = split_map;
2489 // Add missing transitions.
2490 for (; descriptor < descriptors; descriptor++) {
2491 MaybeObject* maybe_map = new_map->CopyInstallDescriptors(
2492 descriptor, new_descriptors);
2493 if (!maybe_map->To(&new_map)) {
2494 // Create a handle for the last created map to ensure it stays alive
2495 // during GC. Its descriptor array is too large, but it will be
2496 // overwritten during retry anyway.
2497 Handle<Map>(new_map);
2498 }
2499 }
2500
2501 new_map->set_owns_descriptors(true);
2502 return new_map;
2503 }
2504
2099 2505
2100 MaybeObject* JSObject::SetPropertyWithInterceptor( 2506 MaybeObject* JSObject::SetPropertyWithInterceptor(
2101 Name* name, 2507 Name* name,
2102 Object* value, 2508 Object* value,
2103 PropertyAttributes attributes, 2509 PropertyAttributes attributes,
2104 StrictModeFlag strict_mode) { 2510 StrictModeFlag strict_mode) {
2105 // TODO(rossberg): Support symbols in the API. 2511 // TODO(rossberg): Support symbols in the API.
2106 if (name->IsSymbol()) return value; 2512 if (name->IsSymbol()) return value;
2107 Isolate* isolate = GetIsolate(); 2513 Isolate* isolate = GetIsolate();
2108 HandleScope scope(isolate); 2514 HandleScope scope(isolate);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 if (strict_mode == kNonStrictMode) return value; 2790 if (strict_mode == kNonStrictMode) return value;
2385 Handle<Object> args[] = { Handle<Object>(name, isolate), 2791 Handle<Object> args[] = { Handle<Object>(name, isolate),
2386 Handle<Object>(this, isolate)}; 2792 Handle<Object>(this, isolate)};
2387 return isolate->Throw(*isolate->factory()->NewTypeError( 2793 return isolate->Throw(*isolate->factory()->NewTypeError(
2388 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); 2794 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2389 } 2795 }
2390 return heap->the_hole_value(); 2796 return heap->the_hole_value();
2391 } 2797 }
2392 2798
2393 2799
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) { 2800 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
2444 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 2801 Handle<DescriptorArray> descriptors(map->instance_descriptors());
2445 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 2802 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
2446 int number_of_descriptors = descriptors->number_of_descriptors(); 2803 int number_of_descriptors = descriptors->number_of_descriptors();
2447 Isolate* isolate = map->GetIsolate(); 2804 Isolate* isolate = map->GetIsolate();
2448 Handle<DescriptorArray> new_descriptors = 2805 Handle<DescriptorArray> new_descriptors =
2449 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); 2806 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
2450 DescriptorArray::WhitenessWitness witness(*new_descriptors); 2807 DescriptorArray::WhitenessWitness witness(*new_descriptors);
2451 2808
2452 for (int i = 0; i < number_of_descriptors; ++i) { 2809 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>(); 3453 return Handle<Object>();
3097 } 3454 }
3098 trap = Handle<Object>(derived); 3455 trap = Handle<Object>(derived);
3099 } 3456 }
3100 3457
3101 bool threw; 3458 bool threw;
3102 return Execution::Call(trap, handler, argc, argv, &threw); 3459 return Execution::Call(trap, handler, argc, argv, &threw);
3103 } 3460 }
3104 3461
3105 3462
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) { 3463 void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) {
3115 CALL_HEAP_FUNCTION_VOID( 3464 CALL_HEAP_FUNCTION_VOID(
3116 object->GetIsolate(), 3465 object->GetIsolate(),
3117 object->TransitionToMap(*map)); 3466 object->TransitionToMap(*map));
3118 } 3467 }
3119 3468
3120 3469
3470 void JSObject::MigrateInstance(Handle<JSObject> object) {
3471 CALL_HEAP_FUNCTION_VOID(
3472 object->GetIsolate(),
3473 object->MigrateInstance());
3474 }
3475
3476
3477 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
3478 int modify_index,
3479 Representation new_representation) {
3480 CALL_HEAP_FUNCTION(
3481 map->GetIsolate(),
3482 map->GeneralizeRepresentation(modify_index, new_representation),
3483 Map);
3484 }
3485
3486
3121 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, 3487 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
3122 Name* name_raw, 3488 Name* name_raw,
3123 Object* value_raw, 3489 Object* value_raw,
3124 PropertyAttributes attributes, 3490 PropertyAttributes attributes,
3125 StrictModeFlag strict_mode, 3491 StrictModeFlag strict_mode,
3126 StoreFromKeyed store_mode) { 3492 StoreFromKeyed store_mode) {
3127 Heap* heap = GetHeap(); 3493 Heap* heap = GetHeap();
3128 Isolate* isolate = heap->isolate(); 3494 Isolate* isolate = heap->isolate();
3129 // Make sure that the top context does not change when doing callbacks or 3495 // Make sure that the top context does not change when doing callbacks or
3130 // interceptor calls. 3496 // interceptor calls.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3199 old_value = Object::GetProperty(self, name); 3565 old_value = Object::GetProperty(self, name);
3200 } 3566 }
3201 3567
3202 // This is a real property that is not read-only, or it is a 3568 // 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. 3569 // transition or null descriptor and there are no setters in the prototypes.
3204 MaybeObject* result = *value; 3570 MaybeObject* result = *value;
3205 switch (lookup->type()) { 3571 switch (lookup->type()) {
3206 case NORMAL: 3572 case NORMAL:
3207 result = lookup->holder()->SetNormalizedProperty(lookup, *value); 3573 result = lookup->holder()->SetNormalizedProperty(lookup, *value);
3208 break; 3574 break;
3209 case FIELD: 3575 case FIELD: {
3576 Representation representation = lookup->representation();
3577 if (!value->FitsRepresentation(representation)) {
3578 MaybeObject* maybe_failure =
3579 lookup->holder()->GeneralizeFieldRepresentation(
3580 lookup->GetDescriptorIndex(), value->OptimalRepresentation());
3581 if (maybe_failure->IsFailure()) return maybe_failure;
3582 }
3210 result = lookup->holder()->FastPropertyAtPut( 3583 result = lookup->holder()->FastPropertyAtPut(
3211 lookup->GetFieldIndex().field_index(), *value); 3584 lookup->GetFieldIndex().field_index(), *value);
3212 break; 3585 break;
3586 }
3213 case CONSTANT_FUNCTION: 3587 case CONSTANT_FUNCTION:
3214 // Only replace the function if necessary. 3588 // Only replace the function if necessary.
3215 if (*value == lookup->GetConstantFunction()) return *value; 3589 if (*value == lookup->GetConstantFunction()) return *value;
3216 // Preserve the attributes of this existing property. 3590 // Preserve the attributes of this existing property.
3217 attributes = lookup->GetAttributes(); 3591 attributes = lookup->GetAttributes();
3218 result = 3592 result =
3219 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes); 3593 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes);
3220 break; 3594 break;
3221 case CALLBACKS: { 3595 case CALLBACKS: {
3222 Object* callback_object = lookup->GetCallbackObject(); 3596 Object* callback_object = lookup->GetCallbackObject();
3223 return self->SetPropertyWithCallback( 3597 return self->SetPropertyWithCallback(
3224 callback_object, *name, *value, lookup->holder(), strict_mode); 3598 callback_object, *name, *value, lookup->holder(), strict_mode);
3225 } 3599 }
3226 case INTERCEPTOR: 3600 case INTERCEPTOR:
3227 result = lookup->holder()->SetPropertyWithInterceptor( 3601 result = lookup->holder()->SetPropertyWithInterceptor(
3228 *name, *value, attributes, strict_mode); 3602 *name, *value, attributes, strict_mode);
3229 break; 3603 break;
3230 case TRANSITION: { 3604 case TRANSITION: {
3231 Map* transition_map = lookup->GetTransitionTarget(); 3605 Map* transition_map = lookup->GetTransitionTarget();
3232 int descriptor = transition_map->LastAdded(); 3606 int descriptor = transition_map->LastAdded();
3233 3607
3234 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3608 DescriptorArray* descriptors = transition_map->instance_descriptors();
3235 PropertyDetails details = descriptors->GetDetails(descriptor); 3609 PropertyDetails details = descriptors->GetDetails(descriptor);
3236 3610
3237 if (details.type() == FIELD) { 3611 if (details.type() == FIELD) {
3238 if (attributes == details.attributes()) { 3612 if (attributes == details.attributes()) {
3613 if (!value->FitsRepresentation(details.representation())) {
3614 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
3615 descriptor, value->OptimalRepresentation());
3616 if (!maybe_map->To(&transition_map)) return maybe_map;
3617 Object* back = transition_map->GetBackPointer();
3618 if (back->IsMap()) {
3619 MaybeObject* maybe_failure =
3620 lookup->holder()->MigrateToMap(Map::cast(back));
3621 if (maybe_failure->IsFailure()) return maybe_failure;
3622 }
3623 }
3239 int field_index = descriptors->GetFieldIndex(descriptor); 3624 int field_index = descriptors->GetFieldIndex(descriptor);
3240 result = lookup->holder()->AddFastPropertyUsingMap( 3625 result = lookup->holder()->AddFastPropertyUsingMap(
3241 transition_map, *name, *value, field_index); 3626 transition_map, *name, *value, field_index);
3242 } else { 3627 } else {
3243 result = lookup->holder()->ConvertDescriptorToField( 3628 result = lookup->holder()->ConvertDescriptorToField(
3244 *name, *value, attributes); 3629 *name, *value, attributes);
3245 } 3630 }
3246 } else if (details.type() == CALLBACKS) { 3631 } else if (details.type() == CALLBACKS) {
3247 result = lookup->holder()->ConvertDescriptorToField( 3632 result = lookup->holder()->ConvertDescriptorToField(
3248 *name, *value, attributes); 3633 *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(); 3744 bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
3360 if (is_observed) { 3745 if (is_observed) {
3361 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name); 3746 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name);
3362 old_attributes = lookup.GetAttributes(); 3747 old_attributes = lookup.GetAttributes();
3363 } 3748 }
3364 3749
3365 // Check of IsReadOnly removed from here in clone. 3750 // Check of IsReadOnly removed from here in clone.
3366 MaybeObject* result = *value; 3751 MaybeObject* result = *value;
3367 switch (lookup.type()) { 3752 switch (lookup.type()) {
3368 case NORMAL: { 3753 case NORMAL: {
3369 PropertyDetails details = PropertyDetails(attributes, NORMAL); 3754 PropertyDetails details = PropertyDetails(
3755 attributes, NORMAL, Representation::None());
3370 result = self->SetNormalizedProperty(*name, *value, details); 3756 result = self->SetNormalizedProperty(*name, *value, details);
3371 break; 3757 break;
3372 } 3758 }
3373 case FIELD: 3759 case FIELD: {
3760 Representation representation = lookup.representation();
3761 if (!value->FitsRepresentation(representation)) {
3762 MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation(
3763 lookup.GetDescriptorIndex(), value->OptimalRepresentation());
3764 if (maybe_failure->IsFailure()) return maybe_failure;
3765 }
3374 result = self->FastPropertyAtPut( 3766 result = self->FastPropertyAtPut(
3375 lookup.GetFieldIndex().field_index(), *value); 3767 lookup.GetFieldIndex().field_index(), *value);
3376 break; 3768 break;
3769 }
3377 case CONSTANT_FUNCTION: 3770 case CONSTANT_FUNCTION:
3378 // Only replace the function if necessary. 3771 // Only replace the function if necessary.
3379 if (*value != lookup.GetConstantFunction()) { 3772 if (*value != lookup.GetConstantFunction()) {
3380 // Preserve the attributes of this existing property. 3773 // Preserve the attributes of this existing property.
3381 attributes = lookup.GetAttributes(); 3774 attributes = lookup.GetAttributes();
3382 result = self->ConvertDescriptorToField(*name, *value, attributes); 3775 result = self->ConvertDescriptorToField(*name, *value, attributes);
3383 } 3776 }
3384 break; 3777 break;
3385 case CALLBACKS: 3778 case CALLBACKS:
3386 case INTERCEPTOR: 3779 case INTERCEPTOR:
3387 // Override callback in clone 3780 // Override callback in clone
3388 result = self->ConvertDescriptorToField(*name, *value, attributes); 3781 result = self->ConvertDescriptorToField(*name, *value, attributes);
3389 break; 3782 break;
3390 case TRANSITION: { 3783 case TRANSITION: {
3391 Map* transition_map = lookup.GetTransitionTarget(); 3784 Map* transition_map = lookup.GetTransitionTarget();
3392 int descriptor = transition_map->LastAdded(); 3785 int descriptor = transition_map->LastAdded();
3393 3786
3394 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3787 DescriptorArray* descriptors = transition_map->instance_descriptors();
3395 PropertyDetails details = descriptors->GetDetails(descriptor); 3788 PropertyDetails details = descriptors->GetDetails(descriptor);
3396 3789
3397 if (details.type() == FIELD) { 3790 if (details.type() == FIELD) {
3398 if (attributes == details.attributes()) { 3791 if (attributes == details.attributes()) {
3792 if (!value->FitsRepresentation(details.representation())) {
3793 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
3794 descriptor, value->OptimalRepresentation());
3795 if (!maybe_map->To(&transition_map)) return maybe_map;
3796 Object* back = transition_map->GetBackPointer();
3797 if (back->IsMap()) {
3798 MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back));
3799 if (maybe_failure->IsFailure()) return maybe_failure;
3800 }
3801 }
3399 int field_index = descriptors->GetFieldIndex(descriptor); 3802 int field_index = descriptors->GetFieldIndex(descriptor);
3400 result = self->AddFastPropertyUsingMap( 3803 result = self->AddFastPropertyUsingMap(
3401 transition_map, *name, *value, field_index); 3804 transition_map, *name, *value, field_index);
3402 } else { 3805 } else {
3403 result = self->ConvertDescriptorToField(*name, *value, attributes); 3806 result = self->ConvertDescriptorToField(*name, *value, attributes);
3404 } 3807 }
3405 } else if (details.type() == CALLBACKS) { 3808 } else if (details.type() == CALLBACKS) {
3406 result = self->ConvertDescriptorToField(*name, *value, attributes); 3809 result = self->ConvertDescriptorToField(*name, *value, attributes);
3407 } else { 3810 } else {
3408 ASSERT(details.type() == CONSTANT_FUNCTION); 3811 ASSERT(details.type() == CONSTANT_FUNCTION);
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
3800 NameDictionary::Allocate(GetHeap(), property_count); 4203 NameDictionary::Allocate(GetHeap(), property_count);
3801 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4204 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3802 4205
3803 DescriptorArray* descs = map_of_this->instance_descriptors(); 4206 DescriptorArray* descs = map_of_this->instance_descriptors();
3804 for (int i = 0; i < real_size; i++) { 4207 for (int i = 0; i < real_size; i++) {
3805 PropertyDetails details = descs->GetDetails(i); 4208 PropertyDetails details = descs->GetDetails(i);
3806 switch (details.type()) { 4209 switch (details.type()) {
3807 case CONSTANT_FUNCTION: { 4210 case CONSTANT_FUNCTION: {
3808 PropertyDetails d = PropertyDetails(details.attributes(), 4211 PropertyDetails d = PropertyDetails(details.attributes(),
3809 NORMAL, 4212 NORMAL,
4213 Representation::None(),
3810 details.descriptor_index()); 4214 details.descriptor_index());
3811 Object* value = descs->GetConstantFunction(i); 4215 Object* value = descs->GetConstantFunction(i);
3812 MaybeObject* maybe_dictionary = 4216 MaybeObject* maybe_dictionary =
3813 dictionary->Add(descs->GetKey(i), value, d); 4217 dictionary->Add(descs->GetKey(i), value, d);
3814 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4218 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3815 break; 4219 break;
3816 } 4220 }
3817 case FIELD: { 4221 case FIELD: {
3818 PropertyDetails d = PropertyDetails(details.attributes(), 4222 PropertyDetails d = PropertyDetails(details.attributes(),
3819 NORMAL, 4223 NORMAL,
4224 Representation::None(),
3820 details.descriptor_index()); 4225 details.descriptor_index());
3821 Object* value = FastPropertyAt(descs->GetFieldIndex(i)); 4226 Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3822 MaybeObject* maybe_dictionary = 4227 MaybeObject* maybe_dictionary =
3823 dictionary->Add(descs->GetKey(i), value, d); 4228 dictionary->Add(descs->GetKey(i), value, d);
3824 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4229 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3825 break; 4230 break;
3826 } 4231 }
3827 case CALLBACKS: { 4232 case CALLBACKS: {
3828 Object* value = descs->GetCallbacksObject(i); 4233 Object* value = descs->GetCallbacksObject(i);
3829 details = details.set_pointer(0); 4234 PropertyDetails d = PropertyDetails(details.attributes(),
4235 CALLBACKS,
4236 Representation::None(),
4237 details.descriptor_index());
3830 MaybeObject* maybe_dictionary = 4238 MaybeObject* maybe_dictionary =
3831 dictionary->Add(descs->GetKey(i), value, details); 4239 dictionary->Add(descs->GetKey(i), value, d);
3832 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4240 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3833 break; 4241 break;
3834 } 4242 }
3835 case INTERCEPTOR: 4243 case INTERCEPTOR:
3836 break; 4244 break;
3837 case HANDLER: 4245 case HANDLER:
3838 case NORMAL: 4246 case NORMAL:
3839 case TRANSITION: 4247 case TRANSITION:
3840 case NONEXISTENT: 4248 case NONEXISTENT:
3841 UNREACHABLE(); 4249 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 4363 // exceed the capacity of new space, and we would fail repeatedly
3956 // trying to convert the FixedDoubleArray. 4364 // trying to convert the FixedDoubleArray.
3957 MaybeObject* maybe_value_object = 4365 MaybeObject* maybe_value_object =
3958 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); 4366 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3959 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 4367 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3960 } 4368 }
3961 } else { 4369 } else {
3962 ASSERT(old_map->has_fast_smi_or_object_elements()); 4370 ASSERT(old_map->has_fast_smi_or_object_elements());
3963 value = FixedArray::cast(array)->get(i); 4371 value = FixedArray::cast(array)->get(i);
3964 } 4372 }
3965 PropertyDetails details = PropertyDetails(NONE, NORMAL); 4373 PropertyDetails details = PropertyDetails(
4374 NONE, NORMAL, Representation::None());
3966 if (!value->IsTheHole()) { 4375 if (!value->IsTheHole()) {
3967 Object* result; 4376 Object* result;
3968 MaybeObject* maybe_result = 4377 MaybeObject* maybe_result =
3969 dictionary->AddNumberEntry(i, value, details); 4378 dictionary->AddNumberEntry(i, value, details);
3970 if (!maybe_result->ToObject(&result)) return maybe_result; 4379 if (!maybe_result->ToObject(&result)) return maybe_result;
3971 dictionary = SeededNumberDictionary::cast(result); 4380 dictionary = SeededNumberDictionary::cast(result);
3972 } 4381 }
3973 } 4382 }
3974 4383
3975 // Switch to using the dictionary as the backing storage for elements. 4384 // 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++) { 5320 for (int i = 0; i < limit; i++) {
4912 if ((descs->GetDetails(i).attributes() & filter) == 0 && 5321 if ((descs->GetDetails(i).attributes() & filter) == 0 &&
4913 ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) { 5322 ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
4914 result++; 5323 result++;
4915 } 5324 }
4916 } 5325 }
4917 return result; 5326 return result;
4918 } 5327 }
4919 5328
4920 5329
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() { 5330 int Map::NextFreePropertyIndex() {
4932 int max_index = -1; 5331 int max_index = -1;
4933 int number_of_own_descriptors = NumberOfOwnDescriptors(); 5332 int number_of_own_descriptors = NumberOfOwnDescriptors();
4934 DescriptorArray* descs = instance_descriptors(); 5333 DescriptorArray* descs = instance_descriptors();
4935 for (int i = 0; i < number_of_own_descriptors; i++) { 5334 for (int i = 0; i < number_of_own_descriptors; i++) {
4936 if (descs->GetType(i) == FIELD) { 5335 if (descs->GetType(i) == FIELD) {
4937 int current_index = descs->GetFieldIndex(i); 5336 int current_index = descs->GetFieldIndex(i);
4938 if (current_index > max_index) max_index = current_index; 5337 if (current_index > max_index) max_index = current_index;
4939 } 5338 }
4940 } 5339 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
5034 Object* getter, 5433 Object* getter,
5035 Object* setter, 5434 Object* setter,
5036 PropertyAttributes attributes) { 5435 PropertyAttributes attributes) {
5037 int entry = dictionary->FindEntry(index); 5436 int entry = dictionary->FindEntry(index);
5038 if (entry != SeededNumberDictionary::kNotFound) { 5437 if (entry != SeededNumberDictionary::kNotFound) {
5039 Object* result = dictionary->ValueAt(entry); 5438 Object* result = dictionary->ValueAt(entry);
5040 PropertyDetails details = dictionary->DetailsAt(entry); 5439 PropertyDetails details = dictionary->DetailsAt(entry);
5041 if (details.type() == CALLBACKS && result->IsAccessorPair()) { 5440 if (details.type() == CALLBACKS && result->IsAccessorPair()) {
5042 ASSERT(!details.IsDontDelete()); 5441 ASSERT(!details.IsDontDelete());
5043 if (details.attributes() != attributes) { 5442 if (details.attributes() != attributes) {
5044 dictionary->DetailsAtPut(entry, 5443 dictionary->DetailsAtPut(
5045 PropertyDetails(attributes, CALLBACKS, index)); 5444 entry,
5445 PropertyDetails(
5446 attributes, CALLBACKS, Representation::None(), index));
5046 } 5447 }
5047 AccessorPair::cast(result)->SetComponents(getter, setter); 5448 AccessorPair::cast(result)->SetComponents(getter, setter);
5048 return true; 5449 return true;
5049 } 5450 }
5050 } 5451 }
5051 return false; 5452 return false;
5052 } 5453 }
5053 5454
5054 5455
5055 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, 5456 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
5196 } 5597 }
5197 } 5598 }
5198 5599
5199 return true; 5600 return true;
5200 } 5601 }
5201 5602
5202 5603
5203 MaybeObject* JSObject::SetElementCallback(uint32_t index, 5604 MaybeObject* JSObject::SetElementCallback(uint32_t index,
5204 Object* structure, 5605 Object* structure,
5205 PropertyAttributes attributes) { 5606 PropertyAttributes attributes) {
5206 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 5607 PropertyDetails details = PropertyDetails(
5608 attributes, CALLBACKS, Representation::None());
5207 5609
5208 // Normalize elements to make this operation simple. 5610 // Normalize elements to make this operation simple.
5209 SeededNumberDictionary* dictionary; 5611 SeededNumberDictionary* dictionary;
5210 { MaybeObject* maybe_dictionary = NormalizeElements(); 5612 { MaybeObject* maybe_dictionary = NormalizeElements();
5211 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 5613 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
5212 } 5614 }
5213 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 5615 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
5214 5616
5215 // Update the dictionary with the new CALLBACKS property. 5617 // Update the dictionary with the new CALLBACKS property.
5216 { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details); 5618 { 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()); 5656 ASSERT(new_map->is_dictionary_map());
5255 5657
5256 set_map(new_map); 5658 set_map(new_map);
5257 // When running crankshaft, changing the map is not enough. We 5659 // When running crankshaft, changing the map is not enough. We
5258 // need to deoptimize all functions that rely on this global 5660 // need to deoptimize all functions that rely on this global
5259 // object. 5661 // object.
5260 Deoptimizer::DeoptimizeGlobalObject(this); 5662 Deoptimizer::DeoptimizeGlobalObject(this);
5261 } 5663 }
5262 5664
5263 // Update the dictionary with the new CALLBACKS property. 5665 // Update the dictionary with the new CALLBACKS property.
5264 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 5666 PropertyDetails details = PropertyDetails(
5667 attributes, CALLBACKS, Representation::None());
5265 maybe_ok = SetNormalizedProperty(name, structure, details); 5668 maybe_ok = SetNormalizedProperty(name, structure, details);
5266 if (maybe_ok->IsFailure()) return maybe_ok; 5669 if (maybe_ok->IsFailure()) return maybe_ok;
5267 5670
5268 return GetHeap()->undefined_value(); 5671 return GetHeap()->undefined_value();
5269 } 5672 }
5270 5673
5271 5674
5272 void JSObject::DefineAccessor(Handle<JSObject> object, 5675 void JSObject::DefineAccessor(Handle<JSObject> object,
5273 Handle<Name> name, 5676 Handle<Name> name,
5274 Handle<Object> getter, 5677 Handle<Object> getter,
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
5771 if (!maybe_result->To(&result)) return maybe_result; 6174 if (!maybe_result->To(&result)) return maybe_result;
5772 6175
5773 result->InitializeDescriptors(descriptors); 6176 result->InitializeDescriptors(descriptors);
5774 6177
5775 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 6178 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
5776 TransitionArray* transitions; 6179 TransitionArray* transitions;
5777 SimpleTransitionFlag simple_flag = 6180 SimpleTransitionFlag simple_flag =
5778 (descriptor_index == descriptors->number_of_descriptors() - 1) 6181 (descriptor_index == descriptors->number_of_descriptors() - 1)
5779 ? SIMPLE_TRANSITION 6182 ? SIMPLE_TRANSITION
5780 : FULL_TRANSITION; 6183 : FULL_TRANSITION;
6184 ASSERT(name == descriptors->GetKey(descriptor_index));
5781 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); 6185 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
5782 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 6186 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5783 6187
5784 set_transitions(transitions); 6188 set_transitions(transitions);
5785 result->SetBackPointer(this); 6189 result->SetBackPointer(this);
5786 } 6190 }
5787 6191
5788 return result; 6192 return result;
5789 } 6193 }
5790 6194
5791 6195
6196 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor,
6197 DescriptorArray* descriptors) {
6198 ASSERT(descriptors->IsSortedNoDuplicates());
6199
6200 Map* result;
6201 MaybeObject* maybe_result = CopyDropDescriptors();
6202 if (!maybe_result->To(&result)) return maybe_result;
6203
6204 result->InitializeDescriptors(descriptors);
6205 result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6206
6207 int unused_property_fields = this->unused_property_fields();
6208 if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
6209 unused_property_fields = this->unused_property_fields() - 1;
6210 if (unused_property_fields < 0) {
6211 unused_property_fields += JSObject::kFieldsAdded;
6212 }
6213 }
6214
6215 result->set_unused_property_fields(unused_property_fields);
6216 result->set_owns_descriptors(false);
6217
6218 if (CanHaveMoreTransitions()) {
6219 Name* name = descriptors->GetKey(new_descriptor);
6220 TransitionArray* transitions;
6221 MaybeObject* maybe_transitions =
6222 AddTransition(name, result, SIMPLE_TRANSITION);
6223 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
6224
6225 set_transitions(transitions);
6226 result->SetBackPointer(this);
6227 }
6228
6229 return result;
6230 }
6231
6232
5792 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 6233 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
5793 if (flag == INSERT_TRANSITION) { 6234 if (flag == INSERT_TRANSITION) {
5794 ASSERT(!HasElementsTransition() || 6235 ASSERT(!HasElementsTransition() ||
5795 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 6236 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
5796 IsExternalArrayElementsKind( 6237 IsExternalArrayElementsKind(
5797 elements_transition_map()->elements_kind())) && 6238 elements_transition_map()->elements_kind())) &&
5798 (kind == DICTIONARY_ELEMENTS || 6239 (kind == DICTIONARY_ELEMENTS ||
5799 IsExternalArrayElementsKind(kind)))); 6240 IsExternalArrayElementsKind(kind))));
5800 ASSERT(!IsFastElementsKind(kind) || 6241 ASSERT(!IsFastElementsKind(kind) ||
5801 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); 6242 IsMoreGeneralElementsKindTransition(elements_kind(), kind));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5850 JSFunction* ctor = JSFunction::cast(constructor()); 6291 JSFunction* ctor = JSFunction::cast(constructor());
5851 Map* map = ctor->initial_map(); 6292 Map* map = ctor->initial_map();
5852 DescriptorArray* descriptors = map->instance_descriptors(); 6293 DescriptorArray* descriptors = map->instance_descriptors();
5853 6294
5854 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 6295 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
5855 DescriptorArray* new_descriptors; 6296 DescriptorArray* new_descriptors;
5856 MaybeObject* maybe_descriptors = 6297 MaybeObject* maybe_descriptors =
5857 descriptors->CopyUpTo(number_of_own_descriptors); 6298 descriptors->CopyUpTo(number_of_own_descriptors);
5858 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 6299 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5859 6300
6301 new_descriptors->InitializeRepresentations(Representation::Tagged());
6302
5860 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); 6303 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5861 } 6304 }
5862 6305
5863 6306
5864 MaybeObject* Map::Copy() { 6307 MaybeObject* Map::Copy() {
5865 DescriptorArray* descriptors = instance_descriptors(); 6308 DescriptorArray* descriptors = instance_descriptors();
5866 DescriptorArray* new_descriptors; 6309 DescriptorArray* new_descriptors;
5867 int number_of_own_descriptors = NumberOfOwnDescriptors(); 6310 int number_of_own_descriptors = NumberOfOwnDescriptors();
5868 MaybeObject* maybe_descriptors = 6311 MaybeObject* maybe_descriptors =
5869 descriptors->CopyUpTo(number_of_own_descriptors); 6312 descriptors->CopyUpTo(number_of_own_descriptors);
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
6805 DescriptorArray* src, 7248 DescriptorArray* src,
6806 int src_index, 7249 int src_index,
6807 const WhitenessWitness& witness) { 7250 const WhitenessWitness& witness) {
6808 Object* value = src->GetValue(src_index); 7251 Object* value = src->GetValue(src_index);
6809 PropertyDetails details = src->GetDetails(src_index); 7252 PropertyDetails details = src->GetDetails(src_index);
6810 Descriptor desc(src->GetKey(src_index), value, details); 7253 Descriptor desc(src->GetKey(src_index), value, details);
6811 Set(dst_index, &desc, witness); 7254 Set(dst_index, &desc, witness);
6812 } 7255 }
6813 7256
6814 7257
7258 // Generalize the |other| descriptor array by merging it with the (at least
7259 // partly) updated |this| descriptor array.
7260 // The method merges two descriptor array in three parts. Both descriptor arrays
7261 // are identical up to |verbatim|. They also overlap in keys up to |valid|.
7262 // Between |verbatim| and |valid|, the resulting descriptor type as well as the
7263 // representation are generalized from both |this| and |other|. Beyond |valid|,
7264 // the descriptors are copied verbatim from |other| up to |new_size|.
7265 // In case of incompatible types, the type and representation of |other| is
7266 // used.
7267 MaybeObject* DescriptorArray::Merge(int verbatim,
7268 int valid,
7269 int new_size,
7270 DescriptorArray* other) {
7271 ASSERT(verbatim <= valid);
7272 ASSERT(valid <= new_size);
7273
7274 DescriptorArray* result;
7275 // Allocate a new descriptor array large enough to hold the required
7276 // descriptors, with minimally the exact same size as this descriptor array.
7277 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
7278 new_size, Max(new_size, number_of_descriptors()) - new_size);
7279 if (!maybe_descriptors->To(&result)) return maybe_descriptors;
7280 ASSERT(result->length() > length() ||
7281 result->NumberOfSlackDescriptors() > 0 ||
7282 result->number_of_descriptors() == other->number_of_descriptors());
7283 ASSERT(result->number_of_descriptors() == new_size);
7284
7285 DescriptorArray::WhitenessWitness witness(result);
7286
7287 int descriptor;
7288
7289 // 0 -> |verbatim|
7290 int current_offset = 0;
7291 for (descriptor = 0; descriptor < verbatim; descriptor++) {
7292 if (GetDetails(descriptor).type() == FIELD) current_offset++;
7293 result->CopyFrom(descriptor, this, descriptor, witness);
7294 }
7295
7296 // |verbatim| -> |valid|
7297 for (; descriptor < valid; descriptor++) {
7298 Name* key = GetKey(descriptor);
7299 PropertyDetails details = GetDetails(descriptor);
7300 PropertyDetails other_details = other->GetDetails(descriptor);
7301 ASSERT(details.attributes() == other_details.attributes());
7302
7303 if (details.type() == FIELD || other_details.type() == FIELD ||
7304 (details.type() == CONSTANT_FUNCTION &&
7305 other_details.type() == CONSTANT_FUNCTION &&
7306 GetValue(descriptor) != other->GetValue(descriptor))) {
7307 Representation representation =
7308 details.representation().generalize(other_details.representation());
7309 FieldDescriptor d(key,
7310 current_offset++,
7311 details.attributes(),
7312 representation,
7313 descriptor + 1);
7314 result->Set(descriptor, &d, witness);
7315 } else {
7316 result->CopyFrom(descriptor, other, descriptor, witness);
7317 }
7318 }
7319
7320 // |valid| -> |new_size|
7321 for (; descriptor < new_size; descriptor++) {
7322 PropertyDetails details = other->GetDetails(descriptor);
7323 if (details.type() == FIELD) {
7324 Name* key = other->GetKey(descriptor);
7325 FieldDescriptor d(key,
7326 current_offset++,
7327 details.attributes(),
7328 details.representation(),
7329 descriptor + 1);
7330 result->Set(descriptor, &d, witness);
7331 } else {
7332 result->CopyFrom(descriptor, other, descriptor, witness);
7333 }
7334 }
7335
7336 result->Sort();
7337 return result;
7338 }
7339
7340
6815 // We need the whiteness witness since sort will reshuffle the entries in the 7341 // 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 7342 // 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 7343 // would move a slot that was already recorded as pointing into an evacuation
6818 // candidate. This would result in missing updates upon evacuation. 7344 // candidate. This would result in missing updates upon evacuation.
6819 void DescriptorArray::Sort() { 7345 void DescriptorArray::Sort() {
6820 // In-place heap sort. 7346 // In-place heap sort.
6821 int len = number_of_descriptors(); 7347 int len = number_of_descriptors();
6822 // Reset sorting since the descriptor array might contain invalid pointers. 7348 // Reset sorting since the descriptor array might contain invalid pointers.
6823 for (int i = 0; i < len; ++i) SetSortedKey(i, i); 7349 for (int i = 0; i < len; ++i) SetSortedKey(i, i);
6824 // Bottom-up max-heap construction. 7350 // 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 8692 // XOR-ing the prototype and constructor directly yields too many zero bits
8167 // when the two pointers are close (which is fairly common). 8693 // when the two pointers are close (which is fairly common).
8168 // To avoid this we shift the prototype 4 bits relatively to the constructor. 8694 // To avoid this we shift the prototype 4 bits relatively to the constructor.
8169 hash ^= (static_cast<uint32_t>( 8695 hash ^= (static_cast<uint32_t>(
8170 reinterpret_cast<uintptr_t>(prototype())) << 2); 8696 reinterpret_cast<uintptr_t>(prototype())) << 2);
8171 8697
8172 return hash ^ (hash >> 16) ^ bit_field2(); 8698 return hash ^ (hash >> 16) ^ bit_field2();
8173 } 8699 }
8174 8700
8175 8701
8702 static bool CheckEquivalent(Map* first, Map* second) {
8703 return
8704 first->constructor() == second->constructor() &&
8705 first->prototype() == second->prototype() &&
8706 first->instance_type() == second->instance_type() &&
8707 first->bit_field() == second->bit_field() &&
8708 first->bit_field2() == second->bit_field2() &&
8709 first->is_observed() == second->is_observed() &&
8710 first->function_with_prototype() == second->function_with_prototype();
8711 }
8712
8713
8714 bool Map::EquivalentToForTransition(Map* other) {
8715 return CheckEquivalent(this, other);
8716 }
8717
8718
8176 bool Map::EquivalentToForNormalization(Map* other, 8719 bool Map::EquivalentToForNormalization(Map* other,
8177 PropertyNormalizationMode mode) { 8720 PropertyNormalizationMode mode) {
8178 return 8721 int properties = mode == CLEAR_INOBJECT_PROPERTIES
8179 constructor() == other->constructor() && 8722 ? 0 : other->inobject_properties();
8180 prototype() == other->prototype() && 8723 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 } 8724 }
8190 8725
8191 8726
8192 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { 8727 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
8193 // Iterate over all fields in the body but take care in dealing with 8728 // Iterate over all fields in the body but take care in dealing with
8194 // the code entry. 8729 // the code entry.
8195 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); 8730 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
8196 v->VisitCodeEntry(this->address() + kCodeEntryOffset); 8731 v->VisitCodeEntry(this->address() + kCodeEntryOffset);
8197 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); 8732 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
8198 } 8733 }
(...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after
10593 Object* element = dictionary->ValueAt(entry); 11128 Object* element = dictionary->ValueAt(entry);
10594 PropertyDetails details = dictionary->DetailsAt(entry); 11129 PropertyDetails details = dictionary->DetailsAt(entry);
10595 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { 11130 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
10596 return SetElementWithCallback(element, index, *value, this, strict_mode); 11131 return SetElementWithCallback(element, index, *value, this, strict_mode);
10597 } else { 11132 } else {
10598 dictionary->UpdateMaxNumberKey(index); 11133 dictionary->UpdateMaxNumberKey(index);
10599 // If a value has not been initialized we allow writing to it even if it 11134 // 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 11135 // is read-only (a declared const that has not been initialized). If a
10601 // value is being defined we skip attribute checks completely. 11136 // value is being defined we skip attribute checks completely.
10602 if (set_mode == DEFINE_PROPERTY) { 11137 if (set_mode == DEFINE_PROPERTY) {
10603 details = PropertyDetails( 11138 details = PropertyDetails(attributes, NORMAL, Representation::None(),
10604 attributes, NORMAL, details.dictionary_index()); 11139 details.dictionary_index());
10605 dictionary->DetailsAtPut(entry, details); 11140 dictionary->DetailsAtPut(entry, details);
10606 } else if (details.IsReadOnly() && !element->IsTheHole()) { 11141 } else if (details.IsReadOnly() && !element->IsTheHole()) {
10607 if (strict_mode == kNonStrictMode) { 11142 if (strict_mode == kNonStrictMode) {
10608 return isolate->heap()->undefined_value(); 11143 return isolate->heap()->undefined_value();
10609 } else { 11144 } else {
10610 Handle<Object> holder(this, isolate); 11145 Handle<Object> holder(this, isolate);
10611 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); 11146 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
10612 Handle<Object> args[2] = { number, holder }; 11147 Handle<Object> args[2] = { number, holder };
10613 Handle<Object> error = 11148 Handle<Object> error =
10614 isolate->factory()->NewTypeError("strict_read_only_property", 11149 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); 11181 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
10647 Handle<String> name = isolate->factory()->NumberToString(number); 11182 Handle<String> name = isolate->factory()->NumberToString(number);
10648 Handle<Object> args[1] = { name }; 11183 Handle<Object> args[1] = { name };
10649 Handle<Object> error = 11184 Handle<Object> error =
10650 isolate->factory()->NewTypeError("object_not_extensible", 11185 isolate->factory()->NewTypeError("object_not_extensible",
10651 HandleVector(args, 1)); 11186 HandleVector(args, 1));
10652 return isolate->Throw(*error); 11187 return isolate->Throw(*error);
10653 } 11188 }
10654 } 11189 }
10655 FixedArrayBase* new_dictionary; 11190 FixedArrayBase* new_dictionary;
10656 PropertyDetails details = PropertyDetails(attributes, NORMAL); 11191 PropertyDetails details = PropertyDetails(
11192 attributes, NORMAL, Representation::None());
10657 MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details); 11193 MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details);
10658 if (!maybe->To(&new_dictionary)) return maybe; 11194 if (!maybe->To(&new_dictionary)) return maybe;
10659 if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) { 11195 if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) {
10660 if (is_arguments) { 11196 if (is_arguments) {
10661 elements->set(1, new_dictionary); 11197 elements->set(1, new_dictionary);
10662 } else { 11198 } else {
10663 self->set_elements(new_dictionary); 11199 self->set_elements(new_dictionary);
10664 } 11200 }
10665 dictionary = 11201 dictionary =
10666 handle(SeededNumberDictionary::cast(new_dictionary), isolate); 11202 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 13176 // Adding an entry with the key beyond smi-range requires
12641 // allocation. Bailout. 13177 // allocation. Bailout.
12642 return Smi::FromInt(-1); 13178 return Smi::FromInt(-1);
12643 } 13179 }
12644 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); 13180 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
12645 } 13181 }
12646 } 13182 }
12647 } 13183 }
12648 13184
12649 uint32_t result = pos; 13185 uint32_t result = pos;
12650 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); 13186 PropertyDetails no_details = PropertyDetails(
13187 NONE, NORMAL, Representation::None());
12651 Heap* heap = GetHeap(); 13188 Heap* heap = GetHeap();
12652 while (undefs > 0) { 13189 while (undefs > 0) {
12653 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 13190 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
12654 // Adding an entry with the key beyond smi-range requires 13191 // Adding an entry with the key beyond smi-range requires
12655 // allocation. Bailout. 13192 // allocation. Bailout.
12656 return Smi::FromInt(-1); 13193 return Smi::FromInt(-1);
12657 } 13194 }
12658 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> 13195 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
12659 ToObjectUnchecked(); 13196 ToObjectUnchecked();
12660 pos++; 13197 pos++;
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
12998 MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) { 13535 MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) {
12999 ASSERT(!HasFastProperties()); 13536 ASSERT(!HasFastProperties());
13000 int entry = property_dictionary()->FindEntry(name); 13537 int entry = property_dictionary()->FindEntry(name);
13001 if (entry == NameDictionary::kNotFound) { 13538 if (entry == NameDictionary::kNotFound) {
13002 Heap* heap = GetHeap(); 13539 Heap* heap = GetHeap();
13003 Object* cell; 13540 Object* cell;
13004 { MaybeObject* maybe_cell = 13541 { MaybeObject* maybe_cell =
13005 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); 13542 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
13006 if (!maybe_cell->ToObject(&cell)) return maybe_cell; 13543 if (!maybe_cell->ToObject(&cell)) return maybe_cell;
13007 } 13544 }
13008 PropertyDetails details(NONE, NORMAL); 13545 PropertyDetails details(NONE, NORMAL, Representation::None());
13009 details = details.AsDeleted(); 13546 details = details.AsDeleted();
13010 Object* dictionary; 13547 Object* dictionary;
13011 { MaybeObject* maybe_dictionary = 13548 { MaybeObject* maybe_dictionary =
13012 property_dictionary()->Add(name, cell, details); 13549 property_dictionary()->Add(name, cell, details);
13013 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; 13550 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
13014 } 13551 }
13015 set_properties(NameDictionary::cast(dictionary)); 13552 set_properties(NameDictionary::cast(dictionary));
13016 return cell; 13553 return cell;
13017 } else { 13554 } else {
13018 Object* value = property_dictionary()->ValueAt(entry); 13555 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)); 13977 enumeration_order->set(index, Smi::FromInt(enum_index));
13441 } 13978 }
13442 13979
13443 // Update the dictionary with new indices. 13980 // Update the dictionary with new indices.
13444 capacity = HashTable<Shape, Key>::Capacity(); 13981 capacity = HashTable<Shape, Key>::Capacity();
13445 pos = 0; 13982 pos = 0;
13446 for (int i = 0; i < capacity; i++) { 13983 for (int i = 0; i < capacity; i++) {
13447 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { 13984 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
13448 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); 13985 int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
13449 PropertyDetails details = DetailsAt(i); 13986 PropertyDetails details = DetailsAt(i);
13450 PropertyDetails new_details = 13987 PropertyDetails new_details = PropertyDetails(
13451 PropertyDetails(details.attributes(), details.type(), enum_index); 13988 details.attributes(), details.type(),
13989 Representation::None(), enum_index);
13452 DetailsAtPut(i, new_details); 13990 DetailsAtPut(i, new_details);
13453 } 13991 }
13454 } 13992 }
13455 13993
13456 // Set the next enumeration index. 13994 // Set the next enumeration index.
13457 SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); 13995 SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
13458 return this; 13996 return this;
13459 } 13997 }
13460 13998
13461 template<typename Shape, typename Key> 13999 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. 14045 // Check whether the dictionary should be extended.
13508 Object* obj; 14046 Object* obj;
13509 { MaybeObject* maybe_obj = EnsureCapacity(1, key); 14047 { MaybeObject* maybe_obj = EnsureCapacity(1, key);
13510 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 14048 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13511 } 14049 }
13512 14050
13513 Object* k; 14051 Object* k;
13514 { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key); 14052 { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key);
13515 if (!maybe_k->ToObject(&k)) return maybe_k; 14053 if (!maybe_k->ToObject(&k)) return maybe_k;
13516 } 14054 }
13517 PropertyDetails details = PropertyDetails(NONE, NORMAL); 14055 PropertyDetails details = PropertyDetails(
14056 NONE, NORMAL, Representation::None());
13518 14057
13519 return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details, 14058 return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
13520 Dictionary<Shape, Key>::Hash(key)); 14059 Dictionary<Shape, Key>::Hash(key));
13521 } 14060 }
13522 14061
13523 14062
13524 template<typename Shape, typename Key> 14063 template<typename Shape, typename Key>
13525 MaybeObject* Dictionary<Shape, Key>::Add(Key key, 14064 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
13526 Object* value, 14065 Object* value,
13527 PropertyDetails details) { 14066 PropertyDetails details) {
(...skipping 25 matching lines...) Expand all
13553 } 14092 }
13554 14093
13555 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); 14094 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
13556 // Insert element at empty or deleted entry 14095 // Insert element at empty or deleted entry
13557 if (!details.IsDeleted() && 14096 if (!details.IsDeleted() &&
13558 details.dictionary_index() == 0 && 14097 details.dictionary_index() == 0 &&
13559 Shape::kIsEnumerable) { 14098 Shape::kIsEnumerable) {
13560 // Assign an enumeration index to the property and update 14099 // Assign an enumeration index to the property and update
13561 // SetNextEnumerationIndex. 14100 // SetNextEnumerationIndex.
13562 int index = NextEnumerationIndex(); 14101 int index = NextEnumerationIndex();
13563 details = PropertyDetails(details.attributes(), details.type(), index); 14102 details = PropertyDetails(details.attributes(), details.type(),
14103 Representation::None(), index);
13564 SetNextEnumerationIndex(index + 1); 14104 SetNextEnumerationIndex(index + 1);
13565 } 14105 }
13566 SetEntry(entry, k, value, details); 14106 SetEntry(entry, k, value, details);
13567 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() || 14107 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() ||
13568 Dictionary<Shape, Key>::KeyAt(entry)->IsName())); 14108 Dictionary<Shape, Key>::KeyAt(entry)->IsName()));
13569 HashTable<Shape, Key>::ElementAdded(); 14109 HashTable<Shape, Key>::ElementAdded();
13570 return this; 14110 return this;
13571 } 14111 }
13572 14112
13573 14113
(...skipping 21 matching lines...) Expand all
13595 PropertyDetails details) { 14135 PropertyDetails details) {
13596 UpdateMaxNumberKey(key); 14136 UpdateMaxNumberKey(key);
13597 SLOW_ASSERT(this->FindEntry(key) == kNotFound); 14137 SLOW_ASSERT(this->FindEntry(key) == kNotFound);
13598 return Add(key, value, details); 14138 return Add(key, value, details);
13599 } 14139 }
13600 14140
13601 14141
13602 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key, 14142 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
13603 Object* value) { 14143 Object* value) {
13604 SLOW_ASSERT(this->FindEntry(key) == kNotFound); 14144 SLOW_ASSERT(this->FindEntry(key) == kNotFound);
13605 return Add(key, value, PropertyDetails(NONE, NORMAL)); 14145 return Add(key, value, PropertyDetails(NONE, NORMAL, Representation::None()));
13606 } 14146 }
13607 14147
13608 14148
13609 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) { 14149 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
13610 UpdateMaxNumberKey(key); 14150 UpdateMaxNumberKey(key);
13611 return AtPut(key, value); 14151 return AtPut(key, value);
13612 } 14152 }
13613 14153
13614 14154
13615 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key, 14155 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
(...skipping 24 matching lines...) Expand all
13640 14180
13641 14181
13642 MaybeObject* SeededNumberDictionary::Set(uint32_t key, 14182 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
13643 Object* value, 14183 Object* value,
13644 PropertyDetails details) { 14184 PropertyDetails details) {
13645 int entry = FindEntry(key); 14185 int entry = FindEntry(key);
13646 if (entry == kNotFound) return AddNumberEntry(key, value, details); 14186 if (entry == kNotFound) return AddNumberEntry(key, value, details);
13647 // Preserve enumeration index. 14187 // Preserve enumeration index.
13648 details = PropertyDetails(details.attributes(), 14188 details = PropertyDetails(details.attributes(),
13649 details.type(), 14189 details.type(),
14190 Representation::None(),
13650 DetailsAt(entry).dictionary_index()); 14191 DetailsAt(entry).dictionary_index());
13651 MaybeObject* maybe_object_key = 14192 MaybeObject* maybe_object_key =
13652 SeededNumberDictionaryShape::AsObject(GetHeap(), key); 14193 SeededNumberDictionaryShape::AsObject(GetHeap(), key);
13653 Object* object_key; 14194 Object* object_key;
13654 if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; 14195 if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
13655 SetEntry(entry, object_key, value, details); 14196 SetEntry(entry, object_key, value, details);
13656 return this; 14197 return this;
13657 } 14198 }
13658 14199
13659 14200
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
13914 obj->InObjectPropertyAtPut(current_offset, 14455 obj->InObjectPropertyAtPut(current_offset,
13915 value, 14456 value,
13916 UPDATE_WRITE_BARRIER); 14457 UPDATE_WRITE_BARRIER);
13917 } else { 14458 } else {
13918 int offset = current_offset - inobject_props; 14459 int offset = current_offset - inobject_props;
13919 fields->set(offset, value); 14460 fields->set(offset, value);
13920 } 14461 }
13921 FieldDescriptor d(key, 14462 FieldDescriptor d(key,
13922 current_offset++, 14463 current_offset++,
13923 details.attributes(), 14464 details.attributes(),
14465 // TODO(verwaest): value->OptimalRepresentation();
14466 Representation::Tagged(),
13924 enumeration_index); 14467 enumeration_index);
13925 descriptors->Set(enumeration_index - 1, &d, witness); 14468 descriptors->Set(enumeration_index - 1, &d, witness);
13926 } else if (type == CALLBACKS) { 14469 } else if (type == CALLBACKS) {
13927 CallbacksDescriptor d(key, 14470 CallbacksDescriptor d(key,
13928 value, 14471 value,
13929 details.attributes(), 14472 details.attributes(),
13930 enumeration_index); 14473 enumeration_index);
13931 descriptors->Set(enumeration_index - 1, &d, witness); 14474 descriptors->Set(enumeration_index - 1, &d, witness);
13932 } else { 14475 } else {
13933 UNREACHABLE(); 14476 UNREACHABLE();
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
14505 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 15048 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
14506 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 15049 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
14507 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 15050 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
14508 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 15051 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
14509 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 15052 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
14510 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 15053 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
14511 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 15054 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
14512 } 15055 }
14513 15056
14514 } } // namespace v8::internal 15057 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698