| 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 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 *attributes = ABSENT; | 808 *attributes = ABSENT; |
| 809 return heap->undefined_value(); | 809 return heap->undefined_value(); |
| 810 } | 810 } |
| 811 *attributes = result->GetAttributes(); | 811 *attributes = result->GetAttributes(); |
| 812 Object* value; | 812 Object* value; |
| 813 switch (result->type()) { | 813 switch (result->type()) { |
| 814 case NORMAL: | 814 case NORMAL: |
| 815 value = result->holder()->GetNormalizedProperty(result); | 815 value = result->holder()->GetNormalizedProperty(result); |
| 816 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 816 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 817 return value->IsTheHole() ? heap->undefined_value() : value; | 817 return value->IsTheHole() ? heap->undefined_value() : value; |
| 818 case FIELD: | 818 case FIELD: { |
| 819 value = result->holder()->FastPropertyAt( | 819 MaybeObject* maybe_result = result->holder()->FastPropertyAt( |
| 820 result->representation(), |
| 820 result->GetFieldIndex().field_index()); | 821 result->GetFieldIndex().field_index()); |
| 822 if (!maybe_result->To(&value)) return maybe_result; |
| 821 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 823 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 822 return value->IsTheHole() ? heap->undefined_value() : value; | 824 return value->IsTheHole() ? heap->undefined_value() : value; |
| 825 } |
| 823 case CONSTANT_FUNCTION: | 826 case CONSTANT_FUNCTION: |
| 824 return result->GetConstantFunction(); | 827 return result->GetConstantFunction(); |
| 825 case CALLBACKS: | 828 case CALLBACKS: |
| 826 return result->holder()->GetPropertyWithCallback( | 829 return result->holder()->GetPropertyWithCallback( |
| 827 receiver, result->GetCallbackObject(), name); | 830 receiver, result->GetCallbackObject(), name); |
| 828 case HANDLER: | 831 case HANDLER: |
| 829 return result->proxy()->GetPropertyWithHandler(receiver, name); | 832 return result->proxy()->GetPropertyWithHandler(receiver, name); |
| 830 case INTERCEPTOR: | 833 case INTERCEPTOR: |
| 831 return result->holder()->GetPropertyWithInterceptor( | 834 return result->holder()->GetPropertyWithInterceptor( |
| 832 receiver, name, attributes); | 835 receiver, name, attributes); |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 } | 1707 } |
| 1705 // TODO(rossberg): what about proxies? | 1708 // TODO(rossberg): what about proxies? |
| 1706 // If the constructor is not present, return "Object". | 1709 // If the constructor is not present, return "Object". |
| 1707 return GetHeap()->Object_string(); | 1710 return GetHeap()->Object_string(); |
| 1708 } | 1711 } |
| 1709 | 1712 |
| 1710 | 1713 |
| 1711 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, | 1714 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
| 1712 Name* name, | 1715 Name* name, |
| 1713 Object* value, | 1716 Object* value, |
| 1714 int field_index) { | 1717 int field_index, |
| 1718 Representation representation) { |
| 1719 // This method is used to transition to a field. If we are transitioning to a |
| 1720 // double field, allocate new storage. |
| 1721 Object* storage; |
| 1722 MaybeObject* maybe_storage = |
| 1723 value->AllocateNewStorageFor(GetHeap(), representation); |
| 1724 if (!maybe_storage->To(&storage)) return maybe_storage; |
| 1725 |
| 1715 if (map()->unused_property_fields() == 0) { | 1726 if (map()->unused_property_fields() == 0) { |
| 1716 int new_unused = new_map->unused_property_fields(); | 1727 int new_unused = new_map->unused_property_fields(); |
| 1717 FixedArray* values; | 1728 FixedArray* values; |
| 1718 MaybeObject* maybe_values = | 1729 MaybeObject* maybe_values = |
| 1719 properties()->CopySize(properties()->length() + new_unused + 1); | 1730 properties()->CopySize(properties()->length() + new_unused + 1); |
| 1720 if (!maybe_values->To(&values)) return maybe_values; | 1731 if (!maybe_values->To(&values)) return maybe_values; |
| 1721 | 1732 |
| 1722 set_properties(values); | 1733 set_properties(values); |
| 1723 } | 1734 } |
| 1735 |
| 1724 set_map(new_map); | 1736 set_map(new_map); |
| 1725 return FastPropertyAtPut(field_index, value); | 1737 |
| 1738 FastPropertyAtPut(field_index, storage); |
| 1739 return value; |
| 1726 } | 1740 } |
| 1727 | 1741 |
| 1728 | 1742 |
| 1729 static bool IsIdentifier(UnicodeCache* cache, Name* name) { | 1743 static bool IsIdentifier(UnicodeCache* cache, Name* name) { |
| 1730 // Checks whether the buffer contains an identifier (no escape). | 1744 // Checks whether the buffer contains an identifier (no escape). |
| 1731 if (!name->IsString()) return false; | 1745 if (!name->IsString()) return false; |
| 1732 String* string = String::cast(name); | 1746 String* string = String::cast(name); |
| 1733 if (string->length() == 0) return false; | 1747 if (string->length() == 0) return false; |
| 1734 ConsStringIteratorOp op; | 1748 ConsStringIteratorOp op; |
| 1735 StringCharacterStream stream(string, &op); | 1749 StringCharacterStream stream(string, &op); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1781 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1768 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1782 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1769 | 1783 |
| 1770 return AddSlowProperty(name, value, attributes); | 1784 return AddSlowProperty(name, value, attributes); |
| 1771 } | 1785 } |
| 1772 | 1786 |
| 1773 // Compute the new index for new field. | 1787 // Compute the new index for new field. |
| 1774 int index = map()->NextFreePropertyIndex(); | 1788 int index = map()->NextFreePropertyIndex(); |
| 1775 | 1789 |
| 1776 // Allocate new instance descriptors with (name, index) added | 1790 // Allocate new instance descriptors with (name, index) added |
| 1777 FieldDescriptor new_field( | 1791 Representation representation = value->OptimalRepresentation(); |
| 1778 name, index, attributes, value->OptimalRepresentation(), 0); | 1792 FieldDescriptor new_field(name, index, attributes, representation, 0); |
| 1779 | 1793 |
| 1780 ASSERT(index < map()->inobject_properties() || | 1794 ASSERT(index < map()->inobject_properties() || |
| 1781 (index - map()->inobject_properties()) < properties()->length() || | 1795 (index - map()->inobject_properties()) < properties()->length() || |
| 1782 map()->unused_property_fields() == 0); | 1796 map()->unused_property_fields() == 0); |
| 1783 | 1797 |
| 1784 FixedArray* values = NULL; | 1798 FixedArray* values = NULL; |
| 1785 | 1799 |
| 1800 // TODO(verwaest): Merge with AddFastPropertyUsingMap. |
| 1786 if (map()->unused_property_fields() == 0) { | 1801 if (map()->unused_property_fields() == 0) { |
| 1787 // Make room for the new value | 1802 // Make room for the new value |
| 1788 MaybeObject* maybe_values = | 1803 MaybeObject* maybe_values = |
| 1789 properties()->CopySize(properties()->length() + kFieldsAdded); | 1804 properties()->CopySize(properties()->length() + kFieldsAdded); |
| 1790 if (!maybe_values->To(&values)) return maybe_values; | 1805 if (!maybe_values->To(&values)) return maybe_values; |
| 1791 } | 1806 } |
| 1792 | 1807 |
| 1793 TransitionFlag flag = INSERT_TRANSITION; | 1808 TransitionFlag flag = INSERT_TRANSITION; |
| 1794 | 1809 |
| 1810 Heap* heap = isolate->heap(); |
| 1811 |
| 1795 Map* new_map; | 1812 Map* new_map; |
| 1796 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); | 1813 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); |
| 1797 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 1814 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 1798 | 1815 |
| 1816 Object* storage; |
| 1817 MaybeObject* maybe_storage = |
| 1818 value->AllocateNewStorageFor(heap, representation); |
| 1819 if (!maybe_storage->To(&storage)) return maybe_storage; |
| 1820 |
| 1799 if (map()->unused_property_fields() == 0) { | 1821 if (map()->unused_property_fields() == 0) { |
| 1800 ASSERT(values != NULL); | 1822 ASSERT(values != NULL); |
| 1801 set_properties(values); | 1823 set_properties(values); |
| 1802 new_map->set_unused_property_fields(kFieldsAdded - 1); | 1824 new_map->set_unused_property_fields(kFieldsAdded - 1); |
| 1803 } else { | 1825 } else { |
| 1804 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); | 1826 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); |
| 1805 } | 1827 } |
| 1806 | 1828 |
| 1807 set_map(new_map); | 1829 set_map(new_map); |
| 1808 return FastPropertyAtPut(index, value); | 1830 |
| 1831 FastPropertyAtPut(index, storage); |
| 1832 return value; |
| 1809 } | 1833 } |
| 1810 | 1834 |
| 1811 | 1835 |
| 1812 MaybeObject* JSObject::AddConstantFunctionProperty( | 1836 MaybeObject* JSObject::AddConstantFunctionProperty( |
| 1813 Name* name, | 1837 Name* name, |
| 1814 JSFunction* function, | 1838 JSFunction* function, |
| 1815 PropertyAttributes attributes) { | 1839 PropertyAttributes attributes) { |
| 1816 // Allocate new instance descriptors with (name, function) added | 1840 // Allocate new instance descriptors with (name, function) added |
| 1817 ConstantFunctionDescriptor d(name, function, attributes, 0); | 1841 ConstantFunctionDescriptor d(name, function, attributes, 0); |
| 1818 | 1842 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2064 Object* new_value, | 2088 Object* new_value, |
| 2065 PropertyAttributes attributes) { | 2089 PropertyAttributes attributes) { |
| 2066 if (map()->unused_property_fields() == 0 && | 2090 if (map()->unused_property_fields() == 0 && |
| 2067 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | 2091 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { |
| 2068 Object* obj; | 2092 Object* obj; |
| 2069 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2093 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2070 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2094 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2071 return ReplaceSlowProperty(name, new_value, attributes); | 2095 return ReplaceSlowProperty(name, new_value, attributes); |
| 2072 } | 2096 } |
| 2073 | 2097 |
| 2098 Representation representation = new_value->OptimalRepresentation(); |
| 2074 int index = map()->NextFreePropertyIndex(); | 2099 int index = map()->NextFreePropertyIndex(); |
| 2075 FieldDescriptor new_field( | 2100 FieldDescriptor new_field(name, index, attributes, representation, 0); |
| 2076 name, index, attributes, new_value->OptimalRepresentation(), 0); | |
| 2077 | 2101 |
| 2078 // Make a new map for the object. | 2102 // Make a new map for the object. |
| 2079 Map* new_map; | 2103 Map* new_map; |
| 2080 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, | 2104 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, |
| 2081 OMIT_TRANSITION); | 2105 OMIT_TRANSITION); |
| 2082 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2106 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 2083 | 2107 |
| 2084 // Make new properties array if necessary. | 2108 // Make new properties array if necessary. |
| 2085 FixedArray* new_properties = NULL; | 2109 FixedArray* new_properties = NULL; |
| 2086 int new_unused_property_fields = map()->unused_property_fields() - 1; | 2110 int new_unused_property_fields = map()->unused_property_fields() - 1; |
| 2087 if (map()->unused_property_fields() == 0) { | 2111 if (map()->unused_property_fields() == 0) { |
| 2088 new_unused_property_fields = kFieldsAdded - 1; | 2112 new_unused_property_fields = kFieldsAdded - 1; |
| 2089 MaybeObject* maybe_new_properties = | 2113 MaybeObject* maybe_new_properties = |
| 2090 properties()->CopySize(properties()->length() + kFieldsAdded); | 2114 properties()->CopySize(properties()->length() + kFieldsAdded); |
| 2091 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; | 2115 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; |
| 2092 } | 2116 } |
| 2093 | 2117 |
| 2118 Heap* heap = GetHeap(); |
| 2119 Object* storage; |
| 2120 MaybeObject* maybe_storage = |
| 2121 new_value->AllocateNewStorageFor(heap, representation); |
| 2122 if (!maybe_storage->To(&storage)) return maybe_storage; |
| 2123 |
| 2094 // Update pointers to commit changes. | 2124 // Update pointers to commit changes. |
| 2095 // Object points to the new map. | 2125 // Object points to the new map. |
| 2096 new_map->set_unused_property_fields(new_unused_property_fields); | 2126 new_map->set_unused_property_fields(new_unused_property_fields); |
| 2097 set_map(new_map); | 2127 set_map(new_map); |
| 2098 if (new_properties != NULL) { | 2128 if (new_properties != NULL) { |
| 2099 set_properties(new_properties); | 2129 set_properties(new_properties); |
| 2100 } | 2130 } |
| 2101 return FastPropertyAtPut(index, new_value); | 2131 FastPropertyAtPut(index, new_value); |
| 2132 return new_value; |
| 2102 } | 2133 } |
| 2103 | 2134 |
| 2104 | 2135 |
| 2105 const char* Representation::Mnemonic() const { | 2136 const char* Representation::Mnemonic() const { |
| 2106 switch (kind_) { | 2137 switch (kind_) { |
| 2107 case kNone: return "v"; | 2138 case kNone: return "v"; |
| 2108 case kTagged: return "t"; | 2139 case kTagged: return "t"; |
| 2109 case kSmi: return "s"; | 2140 case kSmi: return "s"; |
| 2110 case kDouble: return "d"; | 2141 case kDouble: return "d"; |
| 2111 case kInteger32: return "i"; | 2142 case kInteger32: return "i"; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { | 2190 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { |
| 2160 if (trim_mode == FROM_GC) { | 2191 if (trim_mode == FROM_GC) { |
| 2161 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); | 2192 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); |
| 2162 } else { | 2193 } else { |
| 2163 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); | 2194 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); |
| 2164 } | 2195 } |
| 2165 } | 2196 } |
| 2166 } | 2197 } |
| 2167 | 2198 |
| 2168 | 2199 |
| 2169 bool Map::InstancesNeedRewriting(int target_number_of_fields, | 2200 bool Map::InstancesNeedRewriting(Map* target, |
| 2201 int target_number_of_fields, |
| 2170 int target_inobject, | 2202 int target_inobject, |
| 2171 int target_unused) { | 2203 int target_unused) { |
| 2172 // If fields were added (or removed), rewrite the instance. | 2204 // If fields were added (or removed), rewrite the instance. |
| 2173 int number_of_fields = NumberOfFields(); | 2205 int number_of_fields = NumberOfFields(); |
| 2174 ASSERT(target_number_of_fields >= number_of_fields); | 2206 ASSERT(target_number_of_fields >= number_of_fields); |
| 2175 if (target_number_of_fields != number_of_fields) return true; | 2207 if (target_number_of_fields != number_of_fields) return true; |
| 2208 |
| 2209 if (FLAG_track_double_fields) { |
| 2210 // If smi descriptors were replaced by double descriptors, rewrite. |
| 2211 DescriptorArray* old_desc = instance_descriptors(); |
| 2212 DescriptorArray* new_desc = target->instance_descriptors(); |
| 2213 int limit = NumberOfOwnDescriptors(); |
| 2214 for (int i = 0; i < limit; i++) { |
| 2215 if (new_desc->GetDetails(i).representation().IsDouble() && |
| 2216 old_desc->GetDetails(i).representation().IsSmi()) { |
| 2217 return true; |
| 2218 } |
| 2219 } |
| 2220 } |
| 2221 |
| 2176 // If no fields were added, and no inobject properties were removed, setting | 2222 // If no fields were added, and no inobject properties were removed, setting |
| 2177 // the map is sufficient. | 2223 // the map is sufficient. |
| 2178 if (target_inobject == inobject_properties()) return false; | 2224 if (target_inobject == inobject_properties()) return false; |
| 2179 // In-object slack tracking may have reduced the object size of the new map. | 2225 // In-object slack tracking may have reduced the object size of the new map. |
| 2180 // In that case, succeed if all existing fields were inobject, and they still | 2226 // In that case, succeed if all existing fields were inobject, and they still |
| 2181 // fit within the new inobject size. | 2227 // fit within the new inobject size. |
| 2182 ASSERT(target_inobject < inobject_properties()); | 2228 ASSERT(target_inobject < inobject_properties()); |
| 2183 if (target_number_of_fields <= target_inobject) { | 2229 if (target_number_of_fields <= target_inobject) { |
| 2184 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2230 ASSERT(target_number_of_fields + target_unused == target_inobject); |
| 2185 return false; | 2231 return false; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2205 // * If there are properties left in the backing store, install the backing | 2251 // * If there are properties left in the backing store, install the backing |
| 2206 // store. | 2252 // store. |
| 2207 MaybeObject* JSObject::MigrateToMap(Map* new_map) { | 2253 MaybeObject* JSObject::MigrateToMap(Map* new_map) { |
| 2208 Heap* heap = GetHeap(); | 2254 Heap* heap = GetHeap(); |
| 2209 Map* old_map = map(); | 2255 Map* old_map = map(); |
| 2210 int number_of_fields = new_map->NumberOfFields(); | 2256 int number_of_fields = new_map->NumberOfFields(); |
| 2211 int inobject = new_map->inobject_properties(); | 2257 int inobject = new_map->inobject_properties(); |
| 2212 int unused = new_map->unused_property_fields(); | 2258 int unused = new_map->unused_property_fields(); |
| 2213 | 2259 |
| 2214 // Nothing to do if no functions were converted to fields. | 2260 // Nothing to do if no functions were converted to fields. |
| 2215 if (!old_map->InstancesNeedRewriting(number_of_fields, inobject, unused)) { | 2261 if (!old_map->InstancesNeedRewriting( |
| 2262 new_map, number_of_fields, inobject, unused)) { |
| 2216 set_map(new_map); | 2263 set_map(new_map); |
| 2217 return this; | 2264 return this; |
| 2218 } | 2265 } |
| 2219 | 2266 |
| 2220 int total_size = number_of_fields + unused; | 2267 int total_size = number_of_fields + unused; |
| 2221 int external = total_size - inobject; | 2268 int external = total_size - inobject; |
| 2222 FixedArray* array; | 2269 FixedArray* array; |
| 2223 MaybeObject* maybe_array = heap->AllocateFixedArray(total_size); | 2270 MaybeObject* maybe_array = heap->AllocateFixedArray(total_size); |
| 2224 if (!maybe_array->To(&array)) return maybe_array; | 2271 if (!maybe_array->To(&array)) return maybe_array; |
| 2225 | 2272 |
| 2226 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2273 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 2227 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2274 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
| 2228 int descriptors = new_map->NumberOfOwnDescriptors(); | 2275 int descriptors = new_map->NumberOfOwnDescriptors(); |
| 2229 | 2276 |
| 2230 for (int i = 0; i < descriptors; i++) { | 2277 for (int i = 0; i < descriptors; i++) { |
| 2231 PropertyDetails details = new_descriptors->GetDetails(i); | 2278 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2232 if (details.type() != FIELD) continue; | 2279 if (details.type() != FIELD) continue; |
| 2233 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2280 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2234 ASSERT(old_details.type() == CONSTANT_FUNCTION || | 2281 ASSERT(old_details.type() == CONSTANT_FUNCTION || |
| 2235 old_details.type() == FIELD); | 2282 old_details.type() == FIELD); |
| 2236 Object* value = old_details.type() == CONSTANT_FUNCTION | 2283 Object* value = old_details.type() == CONSTANT_FUNCTION |
| 2237 ? old_descriptors->GetValue(i) | 2284 ? old_descriptors->GetValue(i) |
| 2238 : FastPropertyAt(old_descriptors->GetFieldIndex(i)); | 2285 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
| 2286 if (FLAG_track_double_fields && |
| 2287 old_details.representation().IsSmi() && |
| 2288 details.representation().IsDouble()) { |
| 2289 // Objects must be allocated in the old object space, since the |
| 2290 // overall number of HeapNumbers needed for the conversion might |
| 2291 // exceed the capacity of new space, and we would fail repeatedly |
| 2292 // trying to migrate the instance. |
| 2293 MaybeObject* maybe_storage = |
| 2294 value->AllocateNewStorageFor(heap, details.representation(), TENURED); |
| 2295 if (!maybe_storage->To(&value)) return maybe_storage; |
| 2296 } |
| 2297 ASSERT(!(FLAG_track_double_fields && |
| 2298 details.representation().IsDouble() && |
| 2299 value->IsSmi())); |
| 2239 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2300 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
| 2240 if (target_index < 0) target_index += total_size; | 2301 if (target_index < 0) target_index += total_size; |
| 2241 array->set(target_index, value); | 2302 array->set(target_index, value); |
| 2242 } | 2303 } |
| 2243 | 2304 |
| 2244 // From here on we cannot fail anymore. | 2305 // From here on we cannot fail anymore. |
| 2245 | 2306 |
| 2246 // Copy (real) inobject properties. If necessary, stop at number_of_fields to | 2307 // Copy (real) inobject properties. If necessary, stop at number_of_fields to |
| 2247 // avoid overwriting |one_pointer_filler_map|. | 2308 // avoid overwriting |one_pointer_filler_map|. |
| 2248 int limit = Min(inobject, number_of_fields); | 2309 int limit = Min(inobject, number_of_fields); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2293 } | 2354 } |
| 2294 | 2355 |
| 2295 | 2356 |
| 2296 MaybeObject* Map::CopyGeneralizeAllRepresentations() { | 2357 MaybeObject* Map::CopyGeneralizeAllRepresentations() { |
| 2297 Map* new_map; | 2358 Map* new_map; |
| 2298 MaybeObject* maybe_map = this->Copy(); | 2359 MaybeObject* maybe_map = this->Copy(); |
| 2299 if (!maybe_map->To(&new_map)) return maybe_map; | 2360 if (!maybe_map->To(&new_map)) return maybe_map; |
| 2300 | 2361 |
| 2301 new_map->instance_descriptors()->InitializeRepresentations( | 2362 new_map->instance_descriptors()->InitializeRepresentations( |
| 2302 Representation::Tagged()); | 2363 Representation::Tagged()); |
| 2364 if (FLAG_trace_generalization) { |
| 2365 PrintF("failed generalization %p -> %p\n", |
| 2366 static_cast<void*>(this), static_cast<void*>(new_map)); |
| 2367 } |
| 2303 return new_map; | 2368 return new_map; |
| 2304 } | 2369 } |
| 2305 | 2370 |
| 2306 | 2371 |
| 2307 void Map::DeprecateTransitionTree() { | 2372 void Map::DeprecateTransitionTree() { |
| 2308 if (!FLAG_track_fields) return; | 2373 if (!FLAG_track_fields) return; |
| 2309 if (is_deprecated()) return; | 2374 if (is_deprecated()) return; |
| 2310 if (HasTransitionArray()) { | 2375 if (HasTransitionArray()) { |
| 2311 TransitionArray* transitions = this->transitions(); | 2376 TransitionArray* transitions = this->transitions(); |
| 2312 for (int i = 0; i < transitions->number_of_transitions(); i++) { | 2377 for (int i = 0; i < transitions->number_of_transitions(); i++) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2458 Map* updated = root_map->FindUpdatedMap( | 2523 Map* updated = root_map->FindUpdatedMap( |
| 2459 verbatim, descriptors, old_descriptors); | 2524 verbatim, descriptors, old_descriptors); |
| 2460 // Check the state of the root map. | 2525 // Check the state of the root map. |
| 2461 DescriptorArray* updated_descriptors = updated->instance_descriptors(); | 2526 DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
| 2462 | 2527 |
| 2463 int valid = updated->NumberOfOwnDescriptors(); | 2528 int valid = updated->NumberOfOwnDescriptors(); |
| 2464 if (updated_descriptors->IsMoreGeneralThan( | 2529 if (updated_descriptors->IsMoreGeneralThan( |
| 2465 verbatim, valid, descriptors, old_descriptors)) { | 2530 verbatim, valid, descriptors, old_descriptors)) { |
| 2466 Representation updated_representation = | 2531 Representation updated_representation = |
| 2467 updated_descriptors->GetDetails(modify_index).representation(); | 2532 updated_descriptors->GetDetails(modify_index).representation(); |
| 2468 if (new_representation.fits_into(updated_representation)) return updated; | 2533 if (new_representation.fits_into(updated_representation)) { |
| 2534 if (FLAG_trace_generalization) { |
| 2535 PrintF("migrating to existing map %p -> %p\n", |
| 2536 static_cast<void*>(this), static_cast<void*>(updated)); |
| 2537 } |
| 2538 return updated; |
| 2539 } |
| 2469 } | 2540 } |
| 2470 | 2541 |
| 2471 DescriptorArray* new_descriptors; | 2542 DescriptorArray* new_descriptors; |
| 2472 MaybeObject* maybe_descriptors = updated_descriptors->Merge( | 2543 MaybeObject* maybe_descriptors = updated_descriptors->Merge( |
| 2473 verbatim, valid, descriptors, old_descriptors); | 2544 verbatim, valid, descriptors, old_descriptors); |
| 2474 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 2545 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 2475 | 2546 |
| 2476 old_reprepresentation = | 2547 old_reprepresentation = |
| 2477 new_descriptors->GetDetails(modify_index).representation(); | 2548 new_descriptors->GetDetails(modify_index).representation(); |
| 2478 new_representation = new_representation.generalize(old_reprepresentation); | 2549 new_representation = new_representation.generalize(old_reprepresentation); |
| 2479 new_descriptors->SetRepresentation(modify_index, new_representation); | 2550 new_descriptors->SetRepresentation(modify_index, new_representation); |
| 2480 | 2551 |
| 2481 Map* split_map = root_map->FindLastMatchMap( | 2552 Map* split_map = root_map->FindLastMatchMap( |
| 2482 verbatim, descriptors, new_descriptors); | 2553 verbatim, descriptors, new_descriptors); |
| 2483 | 2554 |
| 2484 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2555 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
| 2485 // This is shadowed by |updated_descriptors| being more general than | 2556 // This is shadowed by |updated_descriptors| being more general than |
| 2486 // |old_descriptors|. | 2557 // |old_descriptors|. |
| 2487 ASSERT(descriptors != split_descriptors); | 2558 ASSERT(descriptors != split_descriptors); |
| 2488 | 2559 |
| 2489 int descriptor = split_descriptors; | 2560 int descriptor = split_descriptors; |
| 2490 split_map->DeprecateTarget( | 2561 split_map->DeprecateTarget( |
| 2491 old_descriptors->GetKey(descriptor), new_descriptors); | 2562 old_descriptors->GetKey(descriptor), new_descriptors); |
| 2492 | 2563 |
| 2564 if (FLAG_trace_generalization) { |
| 2565 PrintF("migrating to new map %p -> %p (%i steps)\n", |
| 2566 static_cast<void*>(this), |
| 2567 static_cast<void*>(new_descriptors), |
| 2568 descriptors - descriptor); |
| 2569 } |
| 2570 |
| 2493 Map* new_map = split_map; | 2571 Map* new_map = split_map; |
| 2494 // Add missing transitions. | 2572 // Add missing transitions. |
| 2495 for (; descriptor < descriptors; descriptor++) { | 2573 for (; descriptor < descriptors; descriptor++) { |
| 2496 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( | 2574 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( |
| 2497 descriptor, new_descriptors); | 2575 descriptor, new_descriptors); |
| 2498 if (!maybe_map->To(&new_map)) { | 2576 if (!maybe_map->To(&new_map)) { |
| 2499 // Create a handle for the last created map to ensure it stays alive | 2577 // Create a handle for the last created map to ensure it stays alive |
| 2500 // during GC. Its descriptor array is too large, but it will be | 2578 // during GC. Its descriptor array is too large, but it will be |
| 2501 // overwritten during retry anyway. | 2579 // overwritten during retry anyway. |
| 2502 Handle<Map>(new_map); | 2580 Handle<Map>(new_map); |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3025 map()->LookupDescriptor(this, name, result); | 3103 map()->LookupDescriptor(this, name, result); |
| 3026 // A property or a map transition was found. We return all of these result | 3104 // A property or a map transition was found. We return all of these result |
| 3027 // types because LocalLookupRealNamedProperty is used when setting | 3105 // types because LocalLookupRealNamedProperty is used when setting |
| 3028 // properties where map transitions are handled. | 3106 // properties where map transitions are handled. |
| 3029 ASSERT(!result->IsFound() || | 3107 ASSERT(!result->IsFound() || |
| 3030 (result->holder() == this && result->IsFastPropertyType())); | 3108 (result->holder() == this && result->IsFastPropertyType())); |
| 3031 // Disallow caching for uninitialized constants. These can only | 3109 // Disallow caching for uninitialized constants. These can only |
| 3032 // occur as fields. | 3110 // occur as fields. |
| 3033 if (result->IsField() && | 3111 if (result->IsField() && |
| 3034 result->IsReadOnly() && | 3112 result->IsReadOnly() && |
| 3035 FastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) { | 3113 RawFastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) { |
| 3036 result->DisallowCaching(); | 3114 result->DisallowCaching(); |
| 3037 } | 3115 } |
| 3038 return; | 3116 return; |
| 3039 } | 3117 } |
| 3040 | 3118 |
| 3041 int entry = property_dictionary()->FindEntry(name); | 3119 int entry = property_dictionary()->FindEntry(name); |
| 3042 if (entry != NameDictionary::kNotFound) { | 3120 if (entry != NameDictionary::kNotFound) { |
| 3043 Object* value = property_dictionary()->ValueAt(entry); | 3121 Object* value = property_dictionary()->ValueAt(entry); |
| 3044 if (IsGlobalObject()) { | 3122 if (IsGlobalObject()) { |
| 3045 PropertyDetails d = property_dictionary()->DetailsAt(entry); | 3123 PropertyDetails d = property_dictionary()->DetailsAt(entry); |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3458 return Handle<Object>(); | 3536 return Handle<Object>(); |
| 3459 } | 3537 } |
| 3460 trap = Handle<Object>(derived); | 3538 trap = Handle<Object>(derived); |
| 3461 } | 3539 } |
| 3462 | 3540 |
| 3463 bool threw; | 3541 bool threw; |
| 3464 return Execution::Call(trap, handler, argc, argv, &threw); | 3542 return Execution::Call(trap, handler, argc, argv, &threw); |
| 3465 } | 3543 } |
| 3466 | 3544 |
| 3467 | 3545 |
| 3468 void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) { | 3546 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
| 3469 CALL_HEAP_FUNCTION_VOID( | 3547 CALL_HEAP_FUNCTION_VOID( |
| 3470 object->GetIsolate(), | 3548 object->GetIsolate(), |
| 3471 object->TransitionToMap(*map)); | 3549 object->AllocateStorageForMap(*map)); |
| 3472 } | 3550 } |
| 3473 | 3551 |
| 3474 | 3552 |
| 3475 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3553 void JSObject::MigrateInstance(Handle<JSObject> object) { |
| 3554 if (FLAG_trace_migration) { |
| 3555 PrintF("migrating instance %p (%p)\n", |
| 3556 static_cast<void*>(*object), |
| 3557 static_cast<void*>(object->map())); |
| 3558 } |
| 3476 CALL_HEAP_FUNCTION_VOID( | 3559 CALL_HEAP_FUNCTION_VOID( |
| 3477 object->GetIsolate(), | 3560 object->GetIsolate(), |
| 3478 object->MigrateInstance()); | 3561 object->MigrateInstance()); |
| 3479 } | 3562 } |
| 3480 | 3563 |
| 3481 | 3564 |
| 3482 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, | 3565 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, |
| 3483 int modify_index, | 3566 int modify_index, |
| 3484 Representation new_representation) { | 3567 Representation representation) { |
| 3485 CALL_HEAP_FUNCTION( | 3568 CALL_HEAP_FUNCTION( |
| 3486 map->GetIsolate(), | 3569 map->GetIsolate(), |
| 3487 map->GeneralizeRepresentation(modify_index, new_representation), | 3570 map->GeneralizeRepresentation(modify_index, representation), |
| 3488 Map); | 3571 Map); |
| 3489 } | 3572 } |
| 3490 | 3573 |
| 3491 | 3574 |
| 3492 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, | 3575 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, |
| 3493 Name* name_raw, | 3576 Name* name_raw, |
| 3494 Object* value_raw, | 3577 Object* value_raw, |
| 3495 PropertyAttributes attributes, | 3578 PropertyAttributes attributes, |
| 3496 StrictModeFlag strict_mode, | 3579 StrictModeFlag strict_mode, |
| 3497 StoreFromKeyed store_mode) { | 3580 StoreFromKeyed store_mode) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3577 case NORMAL: | 3660 case NORMAL: |
| 3578 result = lookup->holder()->SetNormalizedProperty(lookup, *value); | 3661 result = lookup->holder()->SetNormalizedProperty(lookup, *value); |
| 3579 break; | 3662 break; |
| 3580 case FIELD: { | 3663 case FIELD: { |
| 3581 Representation representation = lookup->representation(); | 3664 Representation representation = lookup->representation(); |
| 3582 if (!value->FitsRepresentation(representation)) { | 3665 if (!value->FitsRepresentation(representation)) { |
| 3583 MaybeObject* maybe_failure = | 3666 MaybeObject* maybe_failure = |
| 3584 lookup->holder()->GeneralizeFieldRepresentation( | 3667 lookup->holder()->GeneralizeFieldRepresentation( |
| 3585 lookup->GetDescriptorIndex(), value->OptimalRepresentation()); | 3668 lookup->GetDescriptorIndex(), value->OptimalRepresentation()); |
| 3586 if (maybe_failure->IsFailure()) return maybe_failure; | 3669 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3670 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3671 int descriptor = lookup->GetDescriptorIndex(); |
| 3672 representation = desc->GetDetails(descriptor).representation(); |
| 3587 } | 3673 } |
| 3588 result = lookup->holder()->FastPropertyAtPut( | 3674 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 3675 HeapNumber* storage = |
| 3676 HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3677 lookup->GetFieldIndex().field_index())); |
| 3678 storage->set_value(value->Number()); |
| 3679 result = *value; |
| 3680 break; |
| 3681 } |
| 3682 lookup->holder()->FastPropertyAtPut( |
| 3589 lookup->GetFieldIndex().field_index(), *value); | 3683 lookup->GetFieldIndex().field_index(), *value); |
| 3684 result = *value; |
| 3590 break; | 3685 break; |
| 3591 } | 3686 } |
| 3592 case CONSTANT_FUNCTION: | 3687 case CONSTANT_FUNCTION: |
| 3593 // Only replace the function if necessary. | 3688 // Only replace the function if necessary. |
| 3594 if (*value == lookup->GetConstantFunction()) return *value; | 3689 if (*value == lookup->GetConstantFunction()) return *value; |
| 3595 // Preserve the attributes of this existing property. | 3690 // Preserve the attributes of this existing property. |
| 3596 attributes = lookup->GetAttributes(); | 3691 attributes = lookup->GetAttributes(); |
| 3597 result = | 3692 result = |
| 3598 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes); | 3693 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes); |
| 3599 break; | 3694 break; |
| 3600 case CALLBACKS: { | 3695 case CALLBACKS: { |
| 3601 Object* callback_object = lookup->GetCallbackObject(); | 3696 Object* callback_object = lookup->GetCallbackObject(); |
| 3602 return self->SetPropertyWithCallback( | 3697 return self->SetPropertyWithCallback( |
| 3603 callback_object, *name, *value, lookup->holder(), strict_mode); | 3698 callback_object, *name, *value, lookup->holder(), strict_mode); |
| 3604 } | 3699 } |
| 3605 case INTERCEPTOR: | 3700 case INTERCEPTOR: |
| 3606 result = lookup->holder()->SetPropertyWithInterceptor( | 3701 result = lookup->holder()->SetPropertyWithInterceptor( |
| 3607 *name, *value, attributes, strict_mode); | 3702 *name, *value, attributes, strict_mode); |
| 3608 break; | 3703 break; |
| 3609 case TRANSITION: { | 3704 case TRANSITION: { |
| 3610 Map* transition_map = lookup->GetTransitionTarget(); | 3705 Map* transition_map = lookup->GetTransitionTarget(); |
| 3611 int descriptor = transition_map->LastAdded(); | 3706 int descriptor = transition_map->LastAdded(); |
| 3612 | 3707 |
| 3613 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3708 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3614 PropertyDetails details = descriptors->GetDetails(descriptor); | 3709 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3615 | 3710 |
| 3616 if (details.type() == FIELD) { | 3711 if (details.type() == FIELD) { |
| 3617 if (attributes == details.attributes()) { | 3712 if (attributes == details.attributes()) { |
| 3618 if (!value->FitsRepresentation(details.representation())) { | 3713 Representation representation = details.representation(); |
| 3714 if (!value->FitsRepresentation(representation)) { |
| 3619 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | 3715 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( |
| 3620 descriptor, value->OptimalRepresentation()); | 3716 descriptor, value->OptimalRepresentation()); |
| 3621 if (!maybe_map->To(&transition_map)) return maybe_map; | 3717 if (!maybe_map->To(&transition_map)) return maybe_map; |
| 3622 Object* back = transition_map->GetBackPointer(); | 3718 Object* back = transition_map->GetBackPointer(); |
| 3623 if (back->IsMap()) { | 3719 if (back->IsMap()) { |
| 3624 MaybeObject* maybe_failure = | 3720 MaybeObject* maybe_failure = |
| 3625 lookup->holder()->MigrateToMap(Map::cast(back)); | 3721 lookup->holder()->MigrateToMap(Map::cast(back)); |
| 3626 if (maybe_failure->IsFailure()) return maybe_failure; | 3722 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3627 } | 3723 } |
| 3724 DescriptorArray* desc = transition_map->instance_descriptors(); |
| 3725 int descriptor = transition_map->LastAdded(); |
| 3726 representation = desc->GetDetails(descriptor).representation(); |
| 3628 } | 3727 } |
| 3629 int field_index = descriptors->GetFieldIndex(descriptor); | 3728 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3630 result = lookup->holder()->AddFastPropertyUsingMap( | 3729 result = lookup->holder()->AddFastPropertyUsingMap( |
| 3631 transition_map, *name, *value, field_index); | 3730 transition_map, *name, *value, field_index, representation); |
| 3632 } else { | 3731 } else { |
| 3633 result = lookup->holder()->ConvertDescriptorToField( | 3732 result = lookup->holder()->ConvertDescriptorToField( |
| 3634 *name, *value, attributes); | 3733 *name, *value, attributes); |
| 3635 } | 3734 } |
| 3636 } else if (details.type() == CALLBACKS) { | 3735 } else if (details.type() == CALLBACKS) { |
| 3637 result = lookup->holder()->ConvertDescriptorToField( | 3736 result = lookup->holder()->ConvertDescriptorToField( |
| 3638 *name, *value, attributes); | 3737 *name, *value, attributes); |
| 3639 } else { | 3738 } else { |
| 3640 ASSERT(details.type() == CONSTANT_FUNCTION); | 3739 ASSERT(details.type() == CONSTANT_FUNCTION); |
| 3641 | 3740 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3762 attributes, NORMAL, Representation::None()); | 3861 attributes, NORMAL, Representation::None()); |
| 3763 result = self->SetNormalizedProperty(*name, *value, details); | 3862 result = self->SetNormalizedProperty(*name, *value, details); |
| 3764 break; | 3863 break; |
| 3765 } | 3864 } |
| 3766 case FIELD: { | 3865 case FIELD: { |
| 3767 Representation representation = lookup.representation(); | 3866 Representation representation = lookup.representation(); |
| 3768 if (!value->FitsRepresentation(representation)) { | 3867 if (!value->FitsRepresentation(representation)) { |
| 3769 MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation( | 3868 MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation( |
| 3770 lookup.GetDescriptorIndex(), value->OptimalRepresentation()); | 3869 lookup.GetDescriptorIndex(), value->OptimalRepresentation()); |
| 3771 if (maybe_failure->IsFailure()) return maybe_failure; | 3870 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3871 DescriptorArray* desc = self->map()->instance_descriptors(); |
| 3872 int descriptor = lookup.GetDescriptorIndex(); |
| 3873 representation = desc->GetDetails(descriptor).representation(); |
| 3772 } | 3874 } |
| 3773 result = self->FastPropertyAtPut( | 3875 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 3774 lookup.GetFieldIndex().field_index(), *value); | 3876 HeapNumber* storage = |
| 3877 HeapNumber::cast(self->RawFastPropertyAt( |
| 3878 lookup.GetFieldIndex().field_index())); |
| 3879 storage->set_value(value->Number()); |
| 3880 result = *value; |
| 3881 break; |
| 3882 } |
| 3883 self->FastPropertyAtPut(lookup.GetFieldIndex().field_index(), *value); |
| 3884 result = *value; |
| 3775 break; | 3885 break; |
| 3776 } | 3886 } |
| 3777 case CONSTANT_FUNCTION: | 3887 case CONSTANT_FUNCTION: |
| 3778 // Only replace the function if necessary. | 3888 // Only replace the function if necessary. |
| 3779 if (*value != lookup.GetConstantFunction()) { | 3889 if (*value != lookup.GetConstantFunction()) { |
| 3780 // Preserve the attributes of this existing property. | 3890 // Preserve the attributes of this existing property. |
| 3781 attributes = lookup.GetAttributes(); | 3891 attributes = lookup.GetAttributes(); |
| 3782 result = self->ConvertDescriptorToField(*name, *value, attributes); | 3892 result = self->ConvertDescriptorToField(*name, *value, attributes); |
| 3783 } | 3893 } |
| 3784 break; | 3894 break; |
| 3785 case CALLBACKS: | 3895 case CALLBACKS: |
| 3786 case INTERCEPTOR: | 3896 case INTERCEPTOR: |
| 3787 // Override callback in clone | 3897 // Override callback in clone |
| 3788 result = self->ConvertDescriptorToField(*name, *value, attributes); | 3898 result = self->ConvertDescriptorToField(*name, *value, attributes); |
| 3789 break; | 3899 break; |
| 3790 case TRANSITION: { | 3900 case TRANSITION: { |
| 3791 Map* transition_map = lookup.GetTransitionTarget(); | 3901 Map* transition_map = lookup.GetTransitionTarget(); |
| 3792 int descriptor = transition_map->LastAdded(); | 3902 int descriptor = transition_map->LastAdded(); |
| 3793 | 3903 |
| 3794 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3904 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3795 PropertyDetails details = descriptors->GetDetails(descriptor); | 3905 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3796 | 3906 |
| 3797 if (details.type() == FIELD) { | 3907 if (details.type() == FIELD) { |
| 3798 if (attributes == details.attributes()) { | 3908 if (attributes == details.attributes()) { |
| 3799 if (!value->FitsRepresentation(details.representation())) { | 3909 Representation representation = details.representation(); |
| 3910 if (!value->FitsRepresentation(representation)) { |
| 3800 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | 3911 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( |
| 3801 descriptor, value->OptimalRepresentation()); | 3912 descriptor, value->OptimalRepresentation()); |
| 3802 if (!maybe_map->To(&transition_map)) return maybe_map; | 3913 if (!maybe_map->To(&transition_map)) return maybe_map; |
| 3803 Object* back = transition_map->GetBackPointer(); | 3914 Object* back = transition_map->GetBackPointer(); |
| 3804 if (back->IsMap()) { | 3915 if (back->IsMap()) { |
| 3805 MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back)); | 3916 MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back)); |
| 3806 if (maybe_failure->IsFailure()) return maybe_failure; | 3917 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3807 } | 3918 } |
| 3919 DescriptorArray* desc = transition_map->instance_descriptors(); |
| 3920 int descriptor = transition_map->LastAdded(); |
| 3921 representation = desc->GetDetails(descriptor).representation(); |
| 3808 } | 3922 } |
| 3809 int field_index = descriptors->GetFieldIndex(descriptor); | 3923 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3810 result = self->AddFastPropertyUsingMap( | 3924 result = self->AddFastPropertyUsingMap( |
| 3811 transition_map, *name, *value, field_index); | 3925 transition_map, *name, *value, field_index, representation); |
| 3812 } else { | 3926 } else { |
| 3813 result = self->ConvertDescriptorToField(*name, *value, attributes); | 3927 result = self->ConvertDescriptorToField(*name, *value, attributes); |
| 3814 } | 3928 } |
| 3815 } else if (details.type() == CALLBACKS) { | 3929 } else if (details.type() == CALLBACKS) { |
| 3816 result = self->ConvertDescriptorToField(*name, *value, attributes); | 3930 result = self->ConvertDescriptorToField(*name, *value, attributes); |
| 3817 } else { | 3931 } else { |
| 3818 ASSERT(details.type() == CONSTANT_FUNCTION); | 3932 ASSERT(details.type() == CONSTANT_FUNCTION); |
| 3819 | 3933 |
| 3820 // Replace transition to CONSTANT FUNCTION with a map transition to a | 3934 // Replace transition to CONSTANT FUNCTION with a map transition to a |
| 3821 // new map with a FIELD, even if the value is a function. | 3935 // new map with a FIELD, even if the value is a function. |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4226 MaybeObject* maybe_dictionary = | 4340 MaybeObject* maybe_dictionary = |
| 4227 dictionary->Add(descs->GetKey(i), value, d); | 4341 dictionary->Add(descs->GetKey(i), value, d); |
| 4228 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 4342 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
| 4229 break; | 4343 break; |
| 4230 } | 4344 } |
| 4231 case FIELD: { | 4345 case FIELD: { |
| 4232 PropertyDetails d = PropertyDetails(details.attributes(), | 4346 PropertyDetails d = PropertyDetails(details.attributes(), |
| 4233 NORMAL, | 4347 NORMAL, |
| 4234 Representation::None(), | 4348 Representation::None(), |
| 4235 details.descriptor_index()); | 4349 details.descriptor_index()); |
| 4236 Object* value = FastPropertyAt(descs->GetFieldIndex(i)); | 4350 Object* value = RawFastPropertyAt(descs->GetFieldIndex(i)); |
| 4237 MaybeObject* maybe_dictionary = | 4351 MaybeObject* maybe_dictionary = |
| 4238 dictionary->Add(descs->GetKey(i), value, d); | 4352 dictionary->Add(descs->GetKey(i), value, d); |
| 4239 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 4353 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
| 4240 break; | 4354 break; |
| 4241 } | 4355 } |
| 4242 case CALLBACKS: { | 4356 case CALLBACKS: { |
| 4243 Object* value = descs->GetCallbacksObject(i); | 4357 Object* value = descs->GetCallbacksObject(i); |
| 4244 PropertyDetails d = PropertyDetails(details.attributes(), | 4358 PropertyDetails d = PropertyDetails(details.attributes(), |
| 4245 CALLBACKS, | 4359 CALLBACKS, |
| 4246 Representation::None(), | 4360 Representation::None(), |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4607 // If the object has fast properties, check whether the first slot | 4721 // If the object has fast properties, check whether the first slot |
| 4608 // in the descriptor array matches the hidden string. Since the | 4722 // in the descriptor array matches the hidden string. Since the |
| 4609 // hidden strings hash code is zero (and no other name has hash | 4723 // hidden strings hash code is zero (and no other name has hash |
| 4610 // code zero) it will always occupy the first entry if present. | 4724 // code zero) it will always occupy the first entry if present. |
| 4611 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 4725 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 4612 if (descriptors->number_of_descriptors() > 0) { | 4726 if (descriptors->number_of_descriptors() > 0) { |
| 4613 int sorted_index = descriptors->GetSortedKeyIndex(0); | 4727 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 4614 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 4728 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && |
| 4615 sorted_index < map()->NumberOfOwnDescriptors()) { | 4729 sorted_index < map()->NumberOfOwnDescriptors()) { |
| 4616 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 4730 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 4617 inline_value = | 4731 MaybeObject* maybe_value = this->FastPropertyAt( |
| 4618 this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index)); | 4732 descriptors->GetDetails(sorted_index).representation(), |
| 4733 descriptors->GetFieldIndex(sorted_index)); |
| 4734 if (!maybe_value->To(&inline_value)) return maybe_value; |
| 4619 } else { | 4735 } else { |
| 4620 inline_value = GetHeap()->undefined_value(); | 4736 inline_value = GetHeap()->undefined_value(); |
| 4621 } | 4737 } |
| 4622 } else { | 4738 } else { |
| 4623 inline_value = GetHeap()->undefined_value(); | 4739 inline_value = GetHeap()->undefined_value(); |
| 4624 } | 4740 } |
| 4625 } else { | 4741 } else { |
| 4626 PropertyAttributes attributes; | 4742 PropertyAttributes attributes; |
| 4627 // You can't install a getter on a property indexed by the hidden string, | 4743 // You can't install a getter on a property indexed by the hidden string, |
| 4628 // so we can be sure that GetLocalPropertyPostInterceptor returns a real | 4744 // so we can be sure that GetLocalPropertyPostInterceptor returns a real |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4677 // If the object has fast properties, check whether the first slot | 4793 // If the object has fast properties, check whether the first slot |
| 4678 // in the descriptor array matches the hidden string. Since the | 4794 // in the descriptor array matches the hidden string. Since the |
| 4679 // hidden strings hash code is zero (and no other name has hash | 4795 // hidden strings hash code is zero (and no other name has hash |
| 4680 // code zero) it will always occupy the first entry if present. | 4796 // code zero) it will always occupy the first entry if present. |
| 4681 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 4797 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 4682 if (descriptors->number_of_descriptors() > 0) { | 4798 if (descriptors->number_of_descriptors() > 0) { |
| 4683 int sorted_index = descriptors->GetSortedKeyIndex(0); | 4799 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 4684 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 4800 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && |
| 4685 sorted_index < map()->NumberOfOwnDescriptors()) { | 4801 sorted_index < map()->NumberOfOwnDescriptors()) { |
| 4686 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 4802 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 4687 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), | 4803 FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value); |
| 4688 value); | |
| 4689 return this; | 4804 return this; |
| 4690 } | 4805 } |
| 4691 } | 4806 } |
| 4692 } | 4807 } |
| 4693 MaybeObject* store_result = | 4808 MaybeObject* store_result = |
| 4694 SetPropertyPostInterceptor(GetHeap()->hidden_string(), | 4809 SetPropertyPostInterceptor(GetHeap()->hidden_string(), |
| 4695 value, | 4810 value, |
| 4696 DONT_ENUM, | 4811 DONT_ENUM, |
| 4697 kNonStrictMode, | 4812 kNonStrictMode, |
| 4698 OMIT_EXTENSIBILITY_CHECK); | 4813 OMIT_EXTENSIBILITY_CHECK); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5154 set_map(new_map); | 5269 set_map(new_map); |
| 5155 ASSERT(!map()->is_extensible()); | 5270 ASSERT(!map()->is_extensible()); |
| 5156 return new_map; | 5271 return new_map; |
| 5157 } | 5272 } |
| 5158 | 5273 |
| 5159 | 5274 |
| 5160 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { | 5275 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { |
| 5161 StackLimitCheck check(isolate); | 5276 StackLimitCheck check(isolate); |
| 5162 if (check.HasOverflowed()) return isolate->StackOverflow(); | 5277 if (check.HasOverflowed()) return isolate->StackOverflow(); |
| 5163 | 5278 |
| 5279 if (map()->is_deprecated()) { |
| 5280 MaybeObject* maybe_failure = MigrateInstance(); |
| 5281 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5282 } |
| 5283 |
| 5164 Heap* heap = isolate->heap(); | 5284 Heap* heap = isolate->heap(); |
| 5165 Object* result; | 5285 Object* result; |
| 5166 { MaybeObject* maybe_result = heap->CopyJSObject(this); | 5286 { MaybeObject* maybe_result = heap->CopyJSObject(this); |
| 5167 if (!maybe_result->ToObject(&result)) return maybe_result; | 5287 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5168 } | 5288 } |
| 5169 JSObject* copy = JSObject::cast(result); | 5289 JSObject* copy = JSObject::cast(result); |
| 5170 | 5290 |
| 5171 // Deep copy local properties. | 5291 // Deep copy local properties. |
| 5172 if (copy->HasFastProperties()) { | 5292 if (copy->HasFastProperties()) { |
| 5173 FixedArray* properties = copy->properties(); | 5293 DescriptorArray* descriptors = copy->map()->instance_descriptors(); |
| 5174 for (int i = 0; i < properties->length(); i++) { | 5294 int limit = copy->map()->NumberOfOwnDescriptors(); |
| 5175 Object* value = properties->get(i); | 5295 for (int i = 0; i < limit; i++) { |
| 5296 PropertyDetails details = descriptors->GetDetails(i); |
| 5297 if (details.type() != FIELD) continue; |
| 5298 int index = descriptors->GetFieldIndex(i); |
| 5299 Object* value = RawFastPropertyAt(index); |
| 5176 if (value->IsJSObject()) { | 5300 if (value->IsJSObject()) { |
| 5177 JSObject* js_object = JSObject::cast(value); | 5301 JSObject* js_object = JSObject::cast(value); |
| 5178 { MaybeObject* maybe_result = js_object->DeepCopy(isolate); | 5302 MaybeObject* maybe_copy = js_object->DeepCopy(isolate); |
| 5179 if (!maybe_result->ToObject(&result)) return maybe_result; | 5303 if (!maybe_copy->To(&value)) return maybe_copy; |
| 5180 } | 5304 } else { |
| 5181 properties->set(i, result); | 5305 Representation representation = details.representation(); |
| 5306 MaybeObject* maybe_storage = |
| 5307 value->AllocateNewStorageFor(heap, representation); |
| 5308 if (!maybe_storage->To(&value)) return maybe_storage; |
| 5182 } | 5309 } |
| 5183 } | 5310 copy->FastPropertyAtPut(index, value); |
| 5184 int nof = copy->map()->inobject_properties(); | |
| 5185 for (int i = 0; i < nof; i++) { | |
| 5186 Object* value = copy->InObjectPropertyAt(i); | |
| 5187 if (value->IsJSObject()) { | |
| 5188 JSObject* js_object = JSObject::cast(value); | |
| 5189 { MaybeObject* maybe_result = js_object->DeepCopy(isolate); | |
| 5190 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 5191 } | |
| 5192 copy->InObjectPropertyAtPut(i, result); | |
| 5193 } | |
| 5194 } | 5311 } |
| 5195 } else { | 5312 } else { |
| 5196 { MaybeObject* maybe_result = | 5313 { MaybeObject* maybe_result = |
| 5197 heap->AllocateFixedArray(copy->NumberOfLocalProperties()); | 5314 heap->AllocateFixedArray(copy->NumberOfLocalProperties()); |
| 5198 if (!maybe_result->ToObject(&result)) return maybe_result; | 5315 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5199 } | 5316 } |
| 5200 FixedArray* names = FixedArray::cast(result); | 5317 FixedArray* names = FixedArray::cast(result); |
| 5201 copy->GetLocalPropertyNames(names, 0); | 5318 copy->GetLocalPropertyNames(names, 0); |
| 5202 for (int i = 0; i < names->length(); i++) { | 5319 for (int i = 0; i < names->length(); i++) { |
| 5203 ASSERT(names->get(i)->IsString()); | 5320 ASSERT(names->get(i)->IsString()); |
| (...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6011 return heap->undefined_value(); | 6128 return heap->undefined_value(); |
| 6012 } | 6129 } |
| 6013 | 6130 |
| 6014 | 6131 |
| 6015 Object* JSObject::SlowReverseLookup(Object* value) { | 6132 Object* JSObject::SlowReverseLookup(Object* value) { |
| 6016 if (HasFastProperties()) { | 6133 if (HasFastProperties()) { |
| 6017 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); | 6134 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); |
| 6018 DescriptorArray* descs = map()->instance_descriptors(); | 6135 DescriptorArray* descs = map()->instance_descriptors(); |
| 6019 for (int i = 0; i < number_of_own_descriptors; i++) { | 6136 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 6020 if (descs->GetType(i) == FIELD) { | 6137 if (descs->GetType(i) == FIELD) { |
| 6021 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { | 6138 Object* property = RawFastPropertyAt(descs->GetFieldIndex(i)); |
| 6139 if (FLAG_track_double_fields && |
| 6140 descs->GetDetails(i).representation().IsDouble()) { |
| 6141 ASSERT(property->IsHeapNumber()); |
| 6142 if (value->IsNumber() && property->Number() == value->Number()) { |
| 6143 return descs->GetKey(i); |
| 6144 } |
| 6145 } else if (property == value) { |
| 6022 return descs->GetKey(i); | 6146 return descs->GetKey(i); |
| 6023 } | 6147 } |
| 6024 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { | 6148 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { |
| 6025 if (descs->GetConstantFunction(i) == value) { | 6149 if (descs->GetConstantFunction(i) == value) { |
| 6026 return descs->GetKey(i); | 6150 return descs->GetKey(i); |
| 6027 } | 6151 } |
| 6028 } | 6152 } |
| 6029 } | 6153 } |
| 6030 return GetHeap()->undefined_value(); | 6154 return GetHeap()->undefined_value(); |
| 6031 } else { | 6155 } else { |
| 6032 return property_dictionary()->SlowReverseLookup(value); | 6156 return property_dictionary()->SlowReverseLookup(value); |
| 6033 } | 6157 } |
| 6034 } | 6158 } |
| 6035 | 6159 |
| 6036 | 6160 |
| 6037 MaybeObject* Map::RawCopy(int instance_size) { | 6161 MaybeObject* Map::RawCopy(int instance_size) { |
| 6038 Map* result; | 6162 Map* result; |
| 6039 MaybeObject* maybe_result = | 6163 MaybeObject* maybe_result = |
| 6040 GetHeap()->AllocateMap(instance_type(), instance_size); | 6164 GetHeap()->AllocateMap(instance_type(), instance_size); |
| 6041 if (!maybe_result->To(&result)) return maybe_result; | 6165 if (!maybe_result->To(&result)) return maybe_result; |
| 6042 | 6166 |
| 6043 result->set_prototype(prototype()); | 6167 result->set_prototype(prototype()); |
| 6044 result->set_constructor(constructor()); | 6168 result->set_constructor(constructor()); |
| 6045 result->set_bit_field(bit_field()); | 6169 result->set_bit_field(bit_field()); |
| 6046 result->set_bit_field2(bit_field2()); | 6170 result->set_bit_field2(bit_field2()); |
| 6047 int new_bit_field3 = bit_field3(); | 6171 int new_bit_field3 = bit_field3(); |
| 6048 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); | 6172 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); |
| 6049 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); | 6173 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); |
| 6050 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); | 6174 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); |
| 6175 new_bit_field3 = Deprecated::update(new_bit_field3, false); |
| 6051 result->set_bit_field3(new_bit_field3); | 6176 result->set_bit_field3(new_bit_field3); |
| 6052 return result; | 6177 return result; |
| 6053 } | 6178 } |
| 6054 | 6179 |
| 6055 | 6180 |
| 6056 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, | 6181 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
| 6057 NormalizedMapSharingMode sharing) { | 6182 NormalizedMapSharingMode sharing) { |
| 6058 int new_instance_size = instance_size(); | 6183 int new_instance_size = instance_size(); |
| 6059 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 6184 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 6060 new_instance_size -= inobject_properties() * kPointerSize; | 6185 new_instance_size -= inobject_properties() * kPointerSize; |
| (...skipping 9078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15139 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 15264 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 15140 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 15265 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 15141 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 15266 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 15142 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 15267 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 15143 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 15268 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 15144 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 15269 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 15145 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 15270 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 15146 } | 15271 } |
| 15147 | 15272 |
| 15148 } } // namespace v8::internal | 15273 } } // namespace v8::internal |
| OLD | NEW |