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