OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 } | 1536 } |
1537 return true; | 1537 return true; |
1538 } | 1538 } |
1539 | 1539 |
1540 | 1540 |
1541 MaybeObject* JSObject::AddFastProperty(String* name, | 1541 MaybeObject* JSObject::AddFastProperty(String* name, |
1542 Object* value, | 1542 Object* value, |
1543 PropertyAttributes attributes, | 1543 PropertyAttributes attributes, |
1544 StoreFromKeyed store_mode) { | 1544 StoreFromKeyed store_mode) { |
1545 ASSERT(!IsJSGlobalProxy()); | 1545 ASSERT(!IsJSGlobalProxy()); |
1546 ASSERT(map()->instance_descriptors()->Search(name) == | 1546 ASSERT(DescriptorArray::kNotFound == |
1547 DescriptorArray::kNotFound); | 1547 map()->instance_descriptors()->Search( |
| 1548 name, map()->NumberOfOwnDescriptors())); |
1548 | 1549 |
1549 // Normalize the object if the name is an actual string (not the | 1550 // Normalize the object if the name is an actual string (not the |
1550 // hidden symbols) and is not a real identifier. | 1551 // hidden symbols) and is not a real identifier. |
1551 // Normalize the object if it will have too many fast properties. | 1552 // Normalize the object if it will have too many fast properties. |
1552 Isolate* isolate = GetHeap()->isolate(); | 1553 Isolate* isolate = GetHeap()->isolate(); |
1553 StringInputBuffer buffer(name); | 1554 StringInputBuffer buffer(name); |
1554 if ((!IsIdentifier(isolate->unicode_cache(), &buffer) | 1555 if ((!IsIdentifier(isolate->unicode_cache(), &buffer) |
1555 && name != isolate->heap()->hidden_symbol()) || | 1556 && name != isolate->heap()->hidden_symbol()) || |
1556 (map()->unused_property_fields() == 0 && | 1557 (map()->unused_property_fields() == 0 && |
1557 TooManyFastProperties(properties()->length(), store_mode))) { | 1558 TooManyFastProperties(properties()->length(), store_mode))) { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1757 return SetNormalizedProperty(name, value, new_details); | 1758 return SetNormalizedProperty(name, value, new_details); |
1758 } | 1759 } |
1759 | 1760 |
1760 | 1761 |
1761 MaybeObject* JSObject::ConvertTransitionToMapTransition( | 1762 MaybeObject* JSObject::ConvertTransitionToMapTransition( |
1762 int transition_index, | 1763 int transition_index, |
1763 String* name, | 1764 String* name, |
1764 Object* new_value, | 1765 Object* new_value, |
1765 PropertyAttributes attributes) { | 1766 PropertyAttributes attributes) { |
1766 Map* old_map = map(); | 1767 Map* old_map = map(); |
| 1768 Map* old_target = old_map->GetTransition(transition_index); |
1767 Object* result; | 1769 Object* result; |
1768 | 1770 |
| 1771 // To sever a transition to a map with which the descriptors are shared, the |
| 1772 // larger map (more descriptors) needs to store its own descriptors array. |
| 1773 // Both sides of the severed chain need to have their own descriptors pointer |
| 1774 // to store distinct descriptor arrays. |
| 1775 |
| 1776 // If the old_target did not yet store its own descriptors, the new |
| 1777 // descriptors pointer is created for the old_target by temporarily clearing |
| 1778 // the back pointer and setting its descriptor array. The ownership of the |
| 1779 // descriptor array is returned to the smaller maps by installing a reduced |
| 1780 // copy of the descriptor array in the old_map. |
| 1781 |
| 1782 // This phase is executed before creating the new map since it requires |
| 1783 // allocation that may fail. |
| 1784 if (!old_target->StoresOwnDescriptors()) { |
| 1785 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 1786 |
| 1787 old_target->SetBackPointer(GetHeap()->undefined_value()); |
| 1788 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); |
| 1789 if (maybe_failure->IsFailure()) return maybe_failure; |
| 1790 old_target->SetBackPointer(old_map); |
| 1791 |
| 1792 old_map->set_owns_descriptors(true); |
| 1793 } |
| 1794 |
1769 MaybeObject* maybe_result = | 1795 MaybeObject* maybe_result = |
1770 ConvertDescriptorToField(name, new_value, attributes); | 1796 ConvertDescriptorToField(name, new_value, attributes); |
1771 if (!maybe_result->To(&result)) return maybe_result; | 1797 if (!maybe_result->To(&result)) return maybe_result; |
1772 | 1798 |
1773 if (!HasFastProperties()) return result; | 1799 if (!HasFastProperties()) return result; |
1774 | 1800 |
1775 // This method should only be used to convert existing transitions. Objects | 1801 // This method should only be used to convert existing transitions. Objects |
1776 // with the map of "new Object()" cannot have transitions in the first place. | 1802 // with the map of "new Object()" cannot have transitions in the first place. |
1777 ASSERT(map() != GetIsolate()->empty_object_map()); | 1803 Map* new_map = map(); |
| 1804 ASSERT(new_map != GetIsolate()->empty_object_map()); |
1778 | 1805 |
1779 // TODO(verwaest): From here on we lose existing map transitions, causing | 1806 // TODO(verwaest): From here on we lose existing map transitions, causing |
1780 // invalid back pointers. This will change once we can store multiple | 1807 // invalid back pointers. This will change once we can store multiple |
1781 // transitions with the same key. | 1808 // transitions with the same key. |
1782 old_map->SetTransition(transition_index, map()); | 1809 |
1783 map()->SetBackPointer(old_map); | 1810 if (old_map->owns_descriptors()) { |
| 1811 // If the old map owns its own descriptors, transfer ownership to the |
| 1812 // new_map and install its descriptors in the old_map. Since the old_map |
| 1813 // stores the descriptors for the new_map, remove the transition array of |
| 1814 // the new_map that is only in place to store the descriptors. |
| 1815 old_map->transitions()->set_descriptors(new_map->instance_descriptors()); |
| 1816 new_map->ClearTransitions(GetHeap()); |
| 1817 old_map->set_owns_descriptors(false); |
| 1818 } else if (old_target->instance_descriptors() == |
| 1819 old_map->instance_descriptors()) { |
| 1820 // Since the conversion above generated a new fast map with an additional |
| 1821 // property which can be shared as well, install this descriptor pointer |
| 1822 // along the entire chain of smaller maps; and remove the transition array |
| 1823 // that is only in place to hold the descriptor array in the new map. |
| 1824 Map* map; |
| 1825 JSGlobalPropertyCell* new_pointer = |
| 1826 new_map->transitions()->descriptors_pointer(); |
| 1827 JSGlobalPropertyCell* old_pointer = |
| 1828 old_map->transitions()->descriptors_pointer(); |
| 1829 for (Object* current = old_map; |
| 1830 !current->IsUndefined(); |
| 1831 current = map->GetBackPointer()) { |
| 1832 map = Map::cast(current); |
| 1833 if (!map->HasTransitionArray()) break; |
| 1834 TransitionArray* transitions = map->transitions(); |
| 1835 if (transitions->descriptors_pointer() != old_pointer) break; |
| 1836 transitions->set_descriptors_pointer(new_pointer); |
| 1837 } |
| 1838 new_map->ClearTransitions(GetHeap()); |
| 1839 } |
| 1840 |
| 1841 old_map->SetTransition(transition_index, new_map); |
| 1842 new_map->SetBackPointer(old_map); |
1784 return result; | 1843 return result; |
1785 } | 1844 } |
1786 | 1845 |
1787 | 1846 |
1788 MaybeObject* JSObject::ConvertDescriptorToField(String* name, | 1847 MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
1789 Object* new_value, | 1848 Object* new_value, |
1790 PropertyAttributes attributes) { | 1849 PropertyAttributes attributes) { |
1791 if (map()->unused_property_fields() == 0 && | 1850 if (map()->unused_property_fields() == 0 && |
1792 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | 1851 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { |
1793 Object* obj; | 1852 Object* obj; |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2149 } | 2208 } |
2150 | 2209 |
2151 | 2210 |
2152 void Map::CopyAppendCallbackDescriptors(Handle<Map> map, | 2211 void Map::CopyAppendCallbackDescriptors(Handle<Map> map, |
2153 Handle<Object> descriptors) { | 2212 Handle<Object> descriptors) { |
2154 Isolate* isolate = map->GetIsolate(); | 2213 Isolate* isolate = map->GetIsolate(); |
2155 Handle<DescriptorArray> array(map->instance_descriptors()); | 2214 Handle<DescriptorArray> array(map->instance_descriptors()); |
2156 v8::NeanderArray callbacks(descriptors); | 2215 v8::NeanderArray callbacks(descriptors); |
2157 int nof_callbacks = callbacks.length(); | 2216 int nof_callbacks = callbacks.length(); |
2158 int descriptor_count = array->number_of_descriptors(); | 2217 int descriptor_count = array->number_of_descriptors(); |
| 2218 ASSERT(descriptor_count == map->NumberOfOwnDescriptors()); |
2159 | 2219 |
2160 // Ensure the keys are symbols before writing them into the instance | 2220 // Ensure the keys are symbols before writing them into the instance |
2161 // descriptor. Since it may cause a GC, it has to be done before we | 2221 // descriptor. Since it may cause a GC, it has to be done before we |
2162 // temporarily put the heap in an invalid state while appending descriptors. | 2222 // temporarily put the heap in an invalid state while appending descriptors. |
2163 for (int i = 0; i < nof_callbacks; ++i) { | 2223 for (int i = 0; i < nof_callbacks; ++i) { |
2164 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); | 2224 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); |
2165 Handle<String> key = | 2225 Handle<String> key = |
2166 isolate->factory()->SymbolFromString( | 2226 isolate->factory()->SymbolFromString( |
2167 Handle<String>(String::cast(entry->name()))); | 2227 Handle<String>(String::cast(entry->name()))); |
2168 entry->set_name(*key); | 2228 entry->set_name(*key); |
2169 } | 2229 } |
2170 | 2230 |
2171 Handle<DescriptorArray> result = | 2231 Handle<DescriptorArray> result = |
2172 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks); | 2232 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks); |
2173 | 2233 |
2174 // Ensure that marking will not progress and change color of objects. | 2234 // Ensure that marking will not progress and change color of objects. |
2175 DescriptorArray::WhitenessWitness witness(*result); | 2235 DescriptorArray::WhitenessWitness witness(*result); |
2176 | 2236 |
2177 // Copy the descriptors from the array. | 2237 // Copy the descriptors from the array. |
2178 if (0 < descriptor_count) { | 2238 for (int i = 0; i < descriptor_count; i++) { |
2179 for (int i = 0; i < descriptor_count; i++) { | 2239 result->CopyFrom(i, *array, i, witness); |
2180 result->CopyFrom(i, *array, i, witness); | |
2181 } | |
2182 } | 2240 } |
2183 | 2241 |
2184 // After this point the GC is not allowed to run anymore until the map is in a | 2242 // After this point the GC is not allowed to run anymore until the map is in a |
2185 // consistent state again, i.e., all the descriptors are appended and the | 2243 // consistent state again, i.e., all the descriptors are appended and the |
2186 // descriptor array is trimmed to the right size. | 2244 // descriptor array is trimmed to the right size. |
2187 Map::SetDescriptors(map, result); | 2245 Map::SetDescriptors(map, result); |
2188 | 2246 |
2189 // Fill in new callback descriptors. Process the callbacks from | 2247 // Fill in new callback descriptors. Process the callbacks from |
2190 // back to front so that the last callback with a given name takes | 2248 // back to front so that the last callback with a given name takes |
2191 // precedence over previously added callbacks with that name. | 2249 // precedence over previously added callbacks with that name. |
| 2250 int nof = descriptor_count; |
2192 for (int i = nof_callbacks - 1; i >= 0; i--) { | 2251 for (int i = nof_callbacks - 1; i >= 0; i--) { |
2193 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); | 2252 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); |
2194 String* key = String::cast(entry->name()); | 2253 String* key = String::cast(entry->name()); |
2195 // Check if a descriptor with this name already exists before writing. | 2254 // Check if a descriptor with this name already exists before writing. |
2196 if (LinearSearch(*result, key, map->NumberOfOwnDescriptors()) == | 2255 if (result->Search(key, nof) == DescriptorArray::kNotFound) { |
2197 DescriptorArray::kNotFound) { | |
2198 CallbacksDescriptor desc(key, entry, entry->property_attributes()); | 2256 CallbacksDescriptor desc(key, entry, entry->property_attributes()); |
2199 map->AppendDescriptor(&desc, witness); | 2257 map->AppendDescriptor(&desc, witness); |
| 2258 nof += 1; |
2200 } | 2259 } |
2201 } | 2260 } |
2202 | 2261 |
2203 int new_number_of_descriptors = map->NumberOfOwnDescriptors(); | 2262 ASSERT(nof == map->NumberOfOwnDescriptors()); |
| 2263 |
2204 // Reinstall the original descriptor array if no new elements were added. | 2264 // Reinstall the original descriptor array if no new elements were added. |
2205 if (new_number_of_descriptors == descriptor_count) { | 2265 if (nof == descriptor_count) { |
2206 Map::SetDescriptors(map, array); | 2266 Map::SetDescriptors(map, array); |
2207 return; | 2267 return; |
2208 } | 2268 } |
2209 | 2269 |
2210 // If duplicates were detected, trim the descriptor array to the right size. | 2270 // If duplicates were detected, trim the descriptor array to the right size. |
2211 int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors); | 2271 int new_array_size = DescriptorArray::LengthFor(nof); |
2212 if (new_array_size < result->length()) { | 2272 if (new_array_size < result->length()) { |
2213 RightTrimFixedArray<FROM_MUTATOR>( | 2273 RightTrimFixedArray<FROM_MUTATOR>( |
2214 isolate->heap(), *result, result->length() - new_array_size); | 2274 isolate->heap(), *result, result->length() - new_array_size); |
2215 } | 2275 } |
2216 } | 2276 } |
2217 | 2277 |
2218 | 2278 |
2219 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { | 2279 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { |
2220 ASSERT(!map.is_null()); | 2280 ASSERT(!map.is_null()); |
2221 for (int i = 0; i < maps->length(); ++i) { | 2281 for (int i = 0; i < maps->length(); ++i) { |
(...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3268 if (!HasFastProperties()) return this; | 3328 if (!HasFastProperties()) return this; |
3269 | 3329 |
3270 // The global object is always normalized. | 3330 // The global object is always normalized. |
3271 ASSERT(!IsGlobalObject()); | 3331 ASSERT(!IsGlobalObject()); |
3272 // JSGlobalProxy must never be normalized | 3332 // JSGlobalProxy must never be normalized |
3273 ASSERT(!IsJSGlobalProxy()); | 3333 ASSERT(!IsJSGlobalProxy()); |
3274 | 3334 |
3275 Map* map_of_this = map(); | 3335 Map* map_of_this = map(); |
3276 | 3336 |
3277 // Allocate new content. | 3337 // Allocate new content. |
3278 int property_count = map_of_this->NumberOfDescribedProperties(); | 3338 int real_size = map_of_this->NumberOfOwnDescriptors(); |
| 3339 int property_count = |
| 3340 map_of_this->NumberOfDescribedProperties(OWN_DESCRIPTORS); |
3279 if (expected_additional_properties > 0) { | 3341 if (expected_additional_properties > 0) { |
3280 property_count += expected_additional_properties; | 3342 property_count += expected_additional_properties; |
3281 } else { | 3343 } else { |
3282 property_count += 2; // Make space for two more properties. | 3344 property_count += 2; // Make space for two more properties. |
3283 } | 3345 } |
3284 StringDictionary* dictionary; | 3346 StringDictionary* dictionary; |
3285 { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); | 3347 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); |
3286 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 3348 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
3287 } | |
3288 | 3349 |
3289 DescriptorArray* descs = map_of_this->instance_descriptors(); | 3350 DescriptorArray* descs = map_of_this->instance_descriptors(); |
3290 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 3351 for (int i = 0; i < real_size; i++) { |
3291 PropertyDetails details = descs->GetDetails(i); | 3352 PropertyDetails details = descs->GetDetails(i); |
3292 switch (details.type()) { | 3353 switch (details.type()) { |
3293 case CONSTANT_FUNCTION: { | 3354 case CONSTANT_FUNCTION: { |
3294 PropertyDetails d = PropertyDetails(details.attributes(), | 3355 PropertyDetails d = PropertyDetails(details.attributes(), |
3295 NORMAL, | 3356 NORMAL, |
3296 details.descriptor_index()); | 3357 details.descriptor_index()); |
3297 Object* value = descs->GetConstantFunction(i); | 3358 Object* value = descs->GetConstantFunction(i); |
3298 MaybeObject* maybe_dictionary = | 3359 MaybeObject* maybe_dictionary = |
3299 dictionary->Add(descs->GetKey(i), value, d); | 3360 dictionary->Add(descs->GetKey(i), value, d); |
3300 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 3361 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
(...skipping 24 matching lines...) Expand all Loading... |
3325 case TRANSITION: | 3386 case TRANSITION: |
3326 case NONEXISTENT: | 3387 case NONEXISTENT: |
3327 UNREACHABLE(); | 3388 UNREACHABLE(); |
3328 break; | 3389 break; |
3329 } | 3390 } |
3330 } | 3391 } |
3331 | 3392 |
3332 Heap* current_heap = GetHeap(); | 3393 Heap* current_heap = GetHeap(); |
3333 | 3394 |
3334 // Copy the next enumeration index from instance descriptor. | 3395 // Copy the next enumeration index from instance descriptor. |
3335 int index = map_of_this->instance_descriptors()->NextEnumerationIndex(); | 3396 dictionary->SetNextEnumerationIndex(real_size + 1); |
3336 dictionary->SetNextEnumerationIndex(index); | |
3337 | 3397 |
3338 Map* new_map; | 3398 Map* new_map; |
3339 MaybeObject* maybe_map = | 3399 MaybeObject* maybe_map = |
3340 current_heap->isolate()->context()->native_context()-> | 3400 current_heap->isolate()->context()->native_context()-> |
3341 normalized_map_cache()->Get(this, mode); | 3401 normalized_map_cache()->Get(this, mode); |
3342 if (!maybe_map->To(&new_map)) return maybe_map; | 3402 if (!maybe_map->To(&new_map)) return maybe_map; |
3343 ASSERT(new_map->is_dictionary_map()); | 3403 ASSERT(new_map->is_dictionary_map()); |
3344 | 3404 |
3345 // We have now successfully allocated all the necessary objects. | 3405 // We have now successfully allocated all the necessary objects. |
3346 // Changes can now be made with the guarantee that all of them take effect. | 3406 // Changes can now be made with the guarantee that all of them take effect. |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3672 ASSERT(!IsJSGlobalProxy()); | 3732 ASSERT(!IsJSGlobalProxy()); |
3673 Object* inline_value; | 3733 Object* inline_value; |
3674 if (HasFastProperties()) { | 3734 if (HasFastProperties()) { |
3675 // If the object has fast properties, check whether the first slot | 3735 // If the object has fast properties, check whether the first slot |
3676 // in the descriptor array matches the hidden symbol. Since the | 3736 // in the descriptor array matches the hidden symbol. Since the |
3677 // hidden symbols hash code is zero (and no other string has hash | 3737 // hidden symbols hash code is zero (and no other string has hash |
3678 // code zero) it will always occupy the first entry if present. | 3738 // code zero) it will always occupy the first entry if present. |
3679 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 3739 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
3680 if (descriptors->number_of_descriptors() > 0) { | 3740 if (descriptors->number_of_descriptors() > 0) { |
3681 int sorted_index = descriptors->GetSortedKeyIndex(0); | 3741 int sorted_index = descriptors->GetSortedKeyIndex(0); |
3682 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) { | 3742 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() && |
| 3743 sorted_index < map()->NumberOfOwnDescriptors()) { |
3683 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 3744 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
3684 inline_value = this->FastPropertyAt( | 3745 inline_value = |
3685 descriptors->GetFieldIndex(sorted_index)); | 3746 this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index)); |
3686 } else { | 3747 } else { |
3687 inline_value = GetHeap()->undefined_value(); | 3748 inline_value = GetHeap()->undefined_value(); |
3688 } | 3749 } |
3689 } else { | 3750 } else { |
3690 inline_value = GetHeap()->undefined_value(); | 3751 inline_value = GetHeap()->undefined_value(); |
3691 } | 3752 } |
3692 } else { | 3753 } else { |
3693 PropertyAttributes attributes; | 3754 PropertyAttributes attributes; |
3694 // You can't install a getter on a property indexed by the hidden symbol, | 3755 // You can't install a getter on a property indexed by the hidden symbol, |
3695 // so we can be sure that GetLocalPropertyPostInterceptor returns a real | 3756 // so we can be sure that GetLocalPropertyPostInterceptor returns a real |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3740 // for hidden properties yet. | 3801 // for hidden properties yet. |
3741 ASSERT(HasHiddenProperties() != value->IsSmi()); | 3802 ASSERT(HasHiddenProperties() != value->IsSmi()); |
3742 if (HasFastProperties()) { | 3803 if (HasFastProperties()) { |
3743 // If the object has fast properties, check whether the first slot | 3804 // If the object has fast properties, check whether the first slot |
3744 // in the descriptor array matches the hidden symbol. Since the | 3805 // in the descriptor array matches the hidden symbol. Since the |
3745 // hidden symbols hash code is zero (and no other string has hash | 3806 // hidden symbols hash code is zero (and no other string has hash |
3746 // code zero) it will always occupy the first entry if present. | 3807 // code zero) it will always occupy the first entry if present. |
3747 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 3808 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
3748 if (descriptors->number_of_descriptors() > 0) { | 3809 if (descriptors->number_of_descriptors() > 0) { |
3749 int sorted_index = descriptors->GetSortedKeyIndex(0); | 3810 int sorted_index = descriptors->GetSortedKeyIndex(0); |
3750 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) { | 3811 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() && |
| 3812 sorted_index < map()->NumberOfOwnDescriptors()) { |
3751 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 3813 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
3752 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), | 3814 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), |
3753 value); | 3815 value); |
3754 return this; | 3816 return this; |
3755 } | 3817 } |
3756 } | 3818 } |
3757 } | 3819 } |
3758 MaybeObject* store_result = | 3820 MaybeObject* store_result = |
3759 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), | 3821 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), |
3760 value, | 3822 value, |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4178 } | 4240 } |
4179 | 4241 |
4180 | 4242 |
4181 void Map::SetDescriptors(Handle<Map> map, | 4243 void Map::SetDescriptors(Handle<Map> map, |
4182 Handle<DescriptorArray> descriptors) { | 4244 Handle<DescriptorArray> descriptors) { |
4183 Isolate* isolate = map->GetIsolate(); | 4245 Isolate* isolate = map->GetIsolate(); |
4184 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); | 4246 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); |
4185 } | 4247 } |
4186 | 4248 |
4187 | 4249 |
4188 int Map::NumberOfDescribedProperties(PropertyAttributes filter) { | 4250 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
| 4251 PropertyAttributes filter) { |
4189 int result = 0; | 4252 int result = 0; |
4190 DescriptorArray* descs = instance_descriptors(); | 4253 DescriptorArray* descs = instance_descriptors(); |
4191 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4254 int limit = which == ALL_DESCRIPTORS |
4192 PropertyDetails details = descs->GetDetails(i); | 4255 ? descs->number_of_descriptors() |
4193 if ((details.attributes() & filter) == 0) { | 4256 : NumberOfOwnDescriptors(); |
4194 result++; | 4257 for (int i = 0; i < limit; i++) { |
4195 } | 4258 if ((descs->GetDetails(i).attributes() & filter) == 0) result++; |
4196 } | 4259 } |
4197 return result; | 4260 return result; |
4198 } | 4261 } |
4199 | 4262 |
4200 | 4263 |
4201 int Map::PropertyIndexFor(String* name) { | 4264 int Map::PropertyIndexFor(String* name) { |
4202 DescriptorArray* descs = instance_descriptors(); | 4265 DescriptorArray* descs = instance_descriptors(); |
4203 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4266 int limit = NumberOfOwnDescriptors(); |
| 4267 for (int i = 0; i < limit; i++) { |
4204 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i); | 4268 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i); |
4205 } | 4269 } |
4206 return -1; | 4270 return -1; |
4207 } | 4271 } |
4208 | 4272 |
4209 | 4273 |
4210 int Map::NextFreePropertyIndex() { | 4274 int Map::NextFreePropertyIndex() { |
4211 int max_index = -1; | 4275 int max_index = -1; |
| 4276 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
4212 DescriptorArray* descs = instance_descriptors(); | 4277 DescriptorArray* descs = instance_descriptors(); |
4213 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4278 for (int i = 0; i < number_of_own_descriptors; i++) { |
4214 if (descs->GetType(i) == FIELD) { | 4279 if (descs->GetType(i) == FIELD) { |
4215 int current_index = descs->GetFieldIndex(i); | 4280 int current_index = descs->GetFieldIndex(i); |
4216 if (current_index > max_index) max_index = current_index; | 4281 if (current_index > max_index) max_index = current_index; |
4217 } | 4282 } |
4218 } | 4283 } |
4219 return max_index + 1; | 4284 return max_index + 1; |
4220 } | 4285 } |
4221 | 4286 |
4222 | 4287 |
4223 AccessorDescriptor* Map::FindAccessor(String* name) { | 4288 AccessorDescriptor* Map::FindAccessor(String* name) { |
4224 DescriptorArray* descs = instance_descriptors(); | 4289 DescriptorArray* descs = instance_descriptors(); |
4225 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4290 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
4226 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) { | 4291 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 4292 if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) { |
4227 return descs->GetCallbacks(i); | 4293 return descs->GetCallbacks(i); |
4228 } | 4294 } |
4229 } | 4295 } |
4230 return NULL; | 4296 return NULL; |
4231 } | 4297 } |
4232 | 4298 |
4233 | 4299 |
4234 void JSReceiver::LocalLookup(String* name, LookupResult* result) { | 4300 void JSReceiver::LocalLookup(String* name, LookupResult* result) { |
4235 ASSERT(name->IsString()); | 4301 ASSERT(name->IsString()); |
4236 | 4302 |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4640 } else { | 4706 } else { |
4641 return GetHeap()->null_value(); | 4707 return GetHeap()->null_value(); |
4642 } | 4708 } |
4643 | 4709 |
4644 int descriptor_number = result.GetDescriptorIndex(); | 4710 int descriptor_number = result.GetDescriptorIndex(); |
4645 | 4711 |
4646 map()->LookupTransition(this, name, &result); | 4712 map()->LookupTransition(this, name, &result); |
4647 | 4713 |
4648 if (result.IsFound()) { | 4714 if (result.IsFound()) { |
4649 Map* target = result.GetTransitionTarget(); | 4715 Map* target = result.GetTransitionTarget(); |
4650 ASSERT(target->instance_descriptors()->number_of_descriptors() == | 4716 ASSERT(target->NumberOfOwnDescriptors() == |
4651 map()->instance_descriptors()->number_of_descriptors()); | 4717 map()->NumberOfOwnDescriptors()); |
4652 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) == name); | 4718 // This works since descriptors are sorted in order of addition. |
| 4719 ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name); |
4653 return TryAccessorTransition( | 4720 return TryAccessorTransition( |
4654 this, target, descriptor_number, component, accessor, attributes); | 4721 this, target, descriptor_number, component, accessor, attributes); |
4655 } | 4722 } |
4656 } else { | 4723 } else { |
4657 // If not, lookup a transition. | 4724 // If not, lookup a transition. |
4658 map()->LookupTransition(this, name, &result); | 4725 map()->LookupTransition(this, name, &result); |
4659 | 4726 |
4660 // If there is a transition, try to follow it. | 4727 // If there is a transition, try to follow it. |
4661 if (result.IsFound()) { | 4728 if (result.IsFound()) { |
4662 Map* target = result.GetTransitionTarget(); | 4729 Map* target = result.GetTransitionTarget(); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4825 } | 4892 } |
4826 } | 4893 } |
4827 } | 4894 } |
4828 } | 4895 } |
4829 return heap->undefined_value(); | 4896 return heap->undefined_value(); |
4830 } | 4897 } |
4831 | 4898 |
4832 | 4899 |
4833 Object* JSObject::SlowReverseLookup(Object* value) { | 4900 Object* JSObject::SlowReverseLookup(Object* value) { |
4834 if (HasFastProperties()) { | 4901 if (HasFastProperties()) { |
| 4902 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); |
4835 DescriptorArray* descs = map()->instance_descriptors(); | 4903 DescriptorArray* descs = map()->instance_descriptors(); |
4836 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 4904 for (int i = 0; i < number_of_own_descriptors; i++) { |
4837 if (descs->GetType(i) == FIELD) { | 4905 if (descs->GetType(i) == FIELD) { |
4838 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { | 4906 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { |
4839 return descs->GetKey(i); | 4907 return descs->GetKey(i); |
4840 } | 4908 } |
4841 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { | 4909 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { |
4842 if (descs->GetConstantFunction(i) == value) { | 4910 if (descs->GetConstantFunction(i) == value) { |
4843 return descs->GetKey(i); | 4911 return descs->GetKey(i); |
4844 } | 4912 } |
4845 } | 4913 } |
4846 } | 4914 } |
4847 return GetHeap()->undefined_value(); | 4915 return GetHeap()->undefined_value(); |
4848 } else { | 4916 } else { |
4849 return property_dictionary()->SlowReverseLookup(value); | 4917 return property_dictionary()->SlowReverseLookup(value); |
4850 } | 4918 } |
4851 } | 4919 } |
4852 | 4920 |
4853 | 4921 |
4854 MaybeObject* Map::RawCopy(int instance_size) { | 4922 MaybeObject* Map::RawCopy(int instance_size) { |
4855 Map* result; | 4923 Map* result; |
4856 MaybeObject* maybe_result = | 4924 MaybeObject* maybe_result = |
4857 GetHeap()->AllocateMap(instance_type(), instance_size); | 4925 GetHeap()->AllocateMap(instance_type(), instance_size); |
4858 if (!maybe_result->To(&result)) return maybe_result; | 4926 if (!maybe_result->To(&result)) return maybe_result; |
4859 | 4927 |
4860 result->set_prototype(prototype()); | 4928 result->set_prototype(prototype()); |
4861 result->set_constructor(constructor()); | 4929 result->set_constructor(constructor()); |
4862 result->set_bit_field(bit_field()); | 4930 result->set_bit_field(bit_field()); |
4863 result->set_bit_field2(bit_field2()); | 4931 result->set_bit_field2(bit_field2()); |
4864 result->set_bit_field3(bit_field3()); | 4932 result->set_bit_field3(bit_field3()); |
4865 result->SetNumberOfOwnDescriptors(0); | 4933 int new_bit_field3 = bit_field3(); |
4866 result->SetEnumLength(kInvalidEnumCache); | 4934 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); |
| 4935 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); |
| 4936 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); |
| 4937 result->set_bit_field3(new_bit_field3); |
4867 return result; | 4938 return result; |
4868 } | 4939 } |
4869 | 4940 |
4870 | 4941 |
4871 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, | 4942 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
4872 NormalizedMapSharingMode sharing) { | 4943 NormalizedMapSharingMode sharing) { |
4873 int new_instance_size = instance_size(); | 4944 int new_instance_size = instance_size(); |
4874 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 4945 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
4875 new_instance_size -= inobject_properties() * kPointerSize; | 4946 new_instance_size -= inobject_properties() * kPointerSize; |
4876 } | 4947 } |
(...skipping 29 matching lines...) Expand all Loading... |
4906 result->set_inobject_properties(inobject_properties()); | 4977 result->set_inobject_properties(inobject_properties()); |
4907 result->set_unused_property_fields(unused_property_fields()); | 4978 result->set_unused_property_fields(unused_property_fields()); |
4908 | 4979 |
4909 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); | 4980 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
4910 result->set_is_shared(false); | 4981 result->set_is_shared(false); |
4911 result->ClearCodeCache(GetHeap()); | 4982 result->ClearCodeCache(GetHeap()); |
4912 return result; | 4983 return result; |
4913 } | 4984 } |
4914 | 4985 |
4915 | 4986 |
| 4987 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { |
| 4988 // Sanity check. This path is only to be taken if the map owns its descriptor |
| 4989 // array, implying that its NumberOfOwnDescriptors equals the number of |
| 4990 // descriptors in the descriptor array. |
| 4991 ASSERT(NumberOfOwnDescriptors() == |
| 4992 instance_descriptors()->number_of_descriptors()); |
| 4993 Map* result; |
| 4994 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 4995 if (!maybe_result->To(&result)) return maybe_result; |
| 4996 |
| 4997 String* name = descriptor->GetKey(); |
| 4998 |
| 4999 TransitionArray* transitions; |
| 5000 MaybeObject* maybe_transitions = AddTransition(name, result); |
| 5001 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 5002 |
| 5003 DescriptorArray* descriptors = instance_descriptors(); |
| 5004 int old_size = descriptors->number_of_descriptors(); |
| 5005 |
| 5006 DescriptorArray* new_descriptors; |
| 5007 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); |
| 5008 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5009 FixedArray::WhitenessWitness witness(new_descriptors); |
| 5010 |
| 5011 for (int i = 0; i < old_size; ++i) { |
| 5012 new_descriptors->CopyFrom(i, descriptors, i, witness); |
| 5013 } |
| 5014 new_descriptors->Append(descriptor, witness, old_size); |
| 5015 |
| 5016 // If the source descriptors had an enum cache we copy it. This ensures that |
| 5017 // the maps to which we push the new descriptor array back can rely on a |
| 5018 // cache always being available once it is set. If the map has more |
| 5019 // enumerated descriptors than available in the original cache, the cache |
| 5020 // will be lazily replaced by the extended cache when needed. |
| 5021 if (descriptors->HasEnumCache()) { |
| 5022 new_descriptors->CopyEnumCacheFrom(descriptors); |
| 5023 } |
| 5024 |
| 5025 transitions->set_descriptors(new_descriptors); |
| 5026 set_transitions(transitions); |
| 5027 result->SetBackPointer(this); |
| 5028 set_owns_descriptors(false); |
| 5029 |
| 5030 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); |
| 5031 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
| 5032 |
| 5033 return result; |
| 5034 } |
| 5035 |
| 5036 |
4916 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 5037 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
4917 String* name, | 5038 String* name, |
4918 TransitionFlag flag) { | 5039 TransitionFlag flag) { |
| 5040 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 5041 |
4919 Map* result; | 5042 Map* result; |
4920 MaybeObject* maybe_result = CopyDropDescriptors(); | 5043 MaybeObject* maybe_result = CopyDropDescriptors(); |
4921 if (!maybe_result->To(&result)) return maybe_result; | 5044 if (!maybe_result->To(&result)) return maybe_result; |
4922 | 5045 |
4923 if (descriptors->number_of_descriptors() != 0) { | 5046 // Unless we are creating a map with no descriptors and no back pointer, we |
| 5047 // insert the descriptor array locally. |
| 5048 if (!descriptors->IsEmpty()) { |
4924 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); | 5049 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); |
4925 if (maybe_failure->IsFailure()) return maybe_failure; | 5050 if (maybe_failure->IsFailure()) return maybe_failure; |
4926 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); | 5051 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); |
4927 } | 5052 } |
4928 | 5053 |
4929 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 5054 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
4930 TransitionArray* transitions; | 5055 TransitionArray* transitions; |
4931 MaybeObject* maybe_transitions = AddTransition(name, result); | 5056 MaybeObject* maybe_transitions = AddTransition(name, result); |
4932 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 5057 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
4933 | 5058 |
| 5059 if (descriptors->IsEmpty()) { |
| 5060 if (owns_descriptors()) { |
| 5061 // If the copied map has no added fields, and the parent map owns its |
| 5062 // descriptors, those descriptors have to be empty. In that case, |
| 5063 // transfer ownership of the descriptors to the new child. |
| 5064 ASSERT(instance_descriptors()->IsEmpty()); |
| 5065 set_owns_descriptors(false); |
| 5066 } else { |
| 5067 // If the parent did not own its own descriptors, it may share a larger |
| 5068 // descriptors array already. In that case, force a split by setting |
| 5069 // the descriptor array of the new map to the empty descriptor array. |
| 5070 MaybeObject* maybe_failure = |
| 5071 result->SetDescriptors(GetHeap()->empty_descriptor_array()); |
| 5072 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5073 } |
| 5074 } |
| 5075 |
4934 set_transitions(transitions); | 5076 set_transitions(transitions); |
4935 result->SetBackPointer(this); | 5077 result->SetBackPointer(this); |
4936 } | 5078 } |
4937 | 5079 |
4938 return result; | 5080 return result; |
4939 } | 5081 } |
4940 | 5082 |
4941 | 5083 |
4942 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { | 5084 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { |
4943 // Create a new free-floating map only if we are not allowed to store it. | |
4944 Map* new_map = NULL; | |
4945 MaybeObject* maybe_new_map = Copy(); | |
4946 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
4947 new_map->set_elements_kind(kind); | |
4948 | |
4949 if (flag == INSERT_TRANSITION) { | 5085 if (flag == INSERT_TRANSITION) { |
4950 ASSERT(!HasElementsTransition() || | 5086 ASSERT(!HasElementsTransition() || |
4951 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || | 5087 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
4952 IsExternalArrayElementsKind( | 5088 IsExternalArrayElementsKind( |
4953 elements_transition_map()->elements_kind())) && | 5089 elements_transition_map()->elements_kind())) && |
4954 (kind == DICTIONARY_ELEMENTS || | 5090 (kind == DICTIONARY_ELEMENTS || |
4955 IsExternalArrayElementsKind(kind)))); | 5091 IsExternalArrayElementsKind(kind)))); |
4956 ASSERT(!IsFastElementsKind(kind) || | 5092 ASSERT(!IsFastElementsKind(kind) || |
4957 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); | 5093 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); |
4958 ASSERT(kind != elements_kind()); | 5094 ASSERT(kind != elements_kind()); |
| 5095 } |
| 5096 |
| 5097 if (flag == INSERT_TRANSITION && owns_descriptors()) { |
| 5098 // In case the map owned its own descriptors, share the descriptors and |
| 5099 // transfer ownership to the new map. |
| 5100 Map* new_map; |
| 5101 MaybeObject* maybe_new_map = CopyDropDescriptors(); |
| 5102 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
4959 | 5103 |
4960 MaybeObject* added_elements = set_elements_transition_map(new_map); | 5104 MaybeObject* added_elements = set_elements_transition_map(new_map); |
4961 if (added_elements->IsFailure()) return added_elements; | 5105 if (added_elements->IsFailure()) return added_elements; |
4962 | 5106 |
| 5107 new_map->set_elements_kind(kind); |
| 5108 new_map->SetBackPointer(this); |
| 5109 new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors()); |
| 5110 set_owns_descriptors(false); |
| 5111 return new_map; |
| 5112 } |
| 5113 |
| 5114 // In case the map did not own its own descriptors, a split is forced by |
| 5115 // copying the map; creating a new descriptor array cell. |
| 5116 // Create a new free-floating map only if we are not allowed to store it. |
| 5117 Map* new_map; |
| 5118 MaybeObject* maybe_new_map = Copy(); |
| 5119 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 5120 ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors()); |
| 5121 new_map->set_elements_kind(kind); |
| 5122 |
| 5123 if (flag == INSERT_TRANSITION) { |
| 5124 // Map::Copy does not store the descriptor array in case it is empty, since |
| 5125 // it does not insert a back pointer; implicitly indicating that its |
| 5126 // descriptor array is empty. Since in this case we do want to insert a back |
| 5127 // pointer, we have to manually set the empty descriptor array to force a |
| 5128 // split. |
| 5129 if (!new_map->StoresOwnDescriptors()) { |
| 5130 ASSERT(new_map->NumberOfOwnDescriptors() == 0); |
| 5131 MaybeObject* maybe_failure = |
| 5132 new_map->SetDescriptors(GetHeap()->empty_descriptor_array()); |
| 5133 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5134 } |
| 5135 MaybeObject* added_elements = set_elements_transition_map(new_map); |
| 5136 if (added_elements->IsFailure()) return added_elements; |
| 5137 |
4963 new_map->SetBackPointer(this); | 5138 new_map->SetBackPointer(this); |
4964 } | 5139 } |
4965 | 5140 |
4966 return new_map; | 5141 return new_map; |
4967 } | 5142 } |
4968 | 5143 |
4969 | 5144 |
4970 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { | 5145 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
4971 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); | 5146 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); |
4972 | 5147 |
4973 // If the map has pre-allocated properties always start out with a descriptor | 5148 // If the map has pre-allocated properties always start out with a descriptor |
4974 // array describing these properties. | 5149 // array describing these properties. |
4975 ASSERT(constructor()->IsJSFunction()); | 5150 ASSERT(constructor()->IsJSFunction()); |
4976 JSFunction* ctor = JSFunction::cast(constructor()); | 5151 JSFunction* ctor = JSFunction::cast(constructor()); |
4977 Map* map = ctor->initial_map(); | 5152 Map* map = ctor->initial_map(); |
4978 DescriptorArray* descriptors = map->instance_descriptors(); | 5153 DescriptorArray* descriptors = map->instance_descriptors(); |
4979 | 5154 |
4980 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); | 5155 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 5156 DescriptorArray* new_descriptors; |
| 5157 MaybeObject* maybe_descriptors = |
| 5158 descriptors->CopyUpTo(number_of_own_descriptors); |
| 5159 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5160 |
| 5161 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION); |
4981 } | 5162 } |
4982 | 5163 |
4983 | 5164 |
4984 MaybeObject* Map::Copy() { | 5165 MaybeObject* Map::Copy() { |
4985 DescriptorArray* descriptors = instance_descriptors(); | 5166 DescriptorArray* descriptors = instance_descriptors(); |
4986 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); | 5167 DescriptorArray* new_descriptors; |
| 5168 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 5169 MaybeObject* maybe_descriptors = |
| 5170 descriptors->CopyUpTo(number_of_own_descriptors); |
| 5171 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5172 |
| 5173 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION); |
4987 } | 5174 } |
4988 | 5175 |
4989 | 5176 |
4990 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, | 5177 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
4991 TransitionFlag flag) { | 5178 TransitionFlag flag) { |
4992 DescriptorArray* descriptors = instance_descriptors(); | 5179 DescriptorArray* descriptors = instance_descriptors(); |
4993 | 5180 |
4994 // Ensure the key is a symbol. | 5181 // Ensure the key is a symbol. |
4995 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); | 5182 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
4996 if (maybe_failure->IsFailure()) return maybe_failure; | 5183 if (maybe_failure->IsFailure()) return maybe_failure; |
4997 | 5184 |
4998 String* key = descriptor->GetKey(); | 5185 int old_size = NumberOfOwnDescriptors(); |
4999 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound); | 5186 int new_size = old_size + 1; |
| 5187 descriptor->SetEnumerationIndex(new_size); |
5000 | 5188 |
5001 int old_size = descriptors->number_of_descriptors(); | 5189 if (flag == INSERT_TRANSITION && |
5002 int new_size = old_size + 1; | 5190 owns_descriptors() && |
| 5191 CanHaveMoreTransitions()) { |
| 5192 return ShareDescriptor(descriptor); |
| 5193 } |
5003 | 5194 |
5004 DescriptorArray* new_descriptors; | 5195 DescriptorArray* new_descriptors; |
5005 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size); | 5196 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); |
5006 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5197 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
5007 | 5198 |
5008 FixedArray::WhitenessWitness witness(new_descriptors); | 5199 FixedArray::WhitenessWitness witness(new_descriptors); |
5009 | 5200 |
5010 // Copy the descriptors, inserting a descriptor. | 5201 // Copy the descriptors, inserting a descriptor. |
5011 for (int i = 0; i < old_size; ++i) { | 5202 for (int i = 0; i < old_size; ++i) { |
5012 new_descriptors->CopyFrom(i, descriptors, i, witness); | 5203 new_descriptors->CopyFrom(i, descriptors, i, witness); |
5013 } | 5204 } |
5014 | 5205 |
5015 new_descriptors->Append(descriptor, witness, old_size); | 5206 new_descriptors->Set(old_size, descriptor, witness); |
| 5207 new_descriptors->Sort(); |
5016 | 5208 |
5017 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); | 5209 return CopyReplaceDescriptors(new_descriptors, descriptor->GetKey(), flag); |
5018 | |
5019 return CopyReplaceDescriptors(new_descriptors, key, flag); | |
5020 } | 5210 } |
5021 | 5211 |
5022 | 5212 |
5023 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, | 5213 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
5024 TransitionFlag flag) { | 5214 TransitionFlag flag) { |
5025 DescriptorArray* old_descriptors = instance_descriptors(); | 5215 DescriptorArray* old_descriptors = instance_descriptors(); |
5026 | 5216 |
5027 // Ensure the key is a symbol. | 5217 // Ensure the key is a symbol. |
5028 MaybeObject* maybe_result = descriptor->KeyToSymbol(); | 5218 MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
5029 if (maybe_result->IsFailure()) return maybe_result; | 5219 if (maybe_result->IsFailure()) return maybe_result; |
5030 | 5220 |
5031 // We replace the key if it is already present. | 5221 // We replace the key if it is already present. |
5032 int index = old_descriptors->SearchWithCache(descriptor->GetKey()); | 5222 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
5033 if (index != DescriptorArray::kNotFound) { | 5223 if (index != DescriptorArray::kNotFound) { |
5034 return CopyReplaceDescriptor(descriptor, index, flag); | 5224 return CopyReplaceDescriptor(descriptor, index, flag); |
5035 } | 5225 } |
5036 return CopyAddDescriptor(descriptor, flag); | 5226 return CopyAddDescriptor(descriptor, flag); |
5037 } | 5227 } |
5038 | 5228 |
5039 | 5229 |
| 5230 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { |
| 5231 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
| 5232 |
| 5233 int size = enumeration_index; |
| 5234 |
| 5235 DescriptorArray* descriptors; |
| 5236 MaybeObject* maybe_descriptors = Allocate(size); |
| 5237 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 5238 DescriptorArray::WhitenessWitness witness(descriptors); |
| 5239 |
| 5240 for (int i = 0; i < size; ++i) { |
| 5241 descriptors->CopyFrom(i, this, i, witness); |
| 5242 } |
| 5243 |
| 5244 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); |
| 5245 |
| 5246 return descriptors; |
| 5247 } |
| 5248 |
| 5249 |
5040 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, | 5250 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, |
5041 int insertion_index, | 5251 int insertion_index, |
5042 TransitionFlag flag) { | 5252 TransitionFlag flag) { |
5043 DescriptorArray* descriptors = instance_descriptors(); | |
5044 int size = descriptors->number_of_descriptors(); | |
5045 ASSERT(0 <= insertion_index && insertion_index < size); | |
5046 | |
5047 // Ensure the key is a symbol. | 5253 // Ensure the key is a symbol. |
5048 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); | 5254 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
5049 if (maybe_failure->IsFailure()) return maybe_failure; | 5255 if (maybe_failure->IsFailure()) return maybe_failure; |
5050 | 5256 |
| 5257 DescriptorArray* descriptors = instance_descriptors(); |
| 5258 |
5051 String* key = descriptor->GetKey(); | 5259 String* key = descriptor->GetKey(); |
5052 ASSERT(key == descriptors->GetKey(insertion_index)); | 5260 ASSERT(key == descriptors->GetKey(insertion_index)); |
5053 | 5261 |
| 5262 int new_size = NumberOfOwnDescriptors(); |
| 5263 ASSERT(0 <= insertion_index && insertion_index < new_size); |
| 5264 |
| 5265 PropertyDetails details = descriptors->GetDetails(insertion_index); |
| 5266 ASSERT_LE(details.descriptor_index(), new_size); |
| 5267 descriptor->SetEnumerationIndex(details.descriptor_index()); |
| 5268 |
5054 DescriptorArray* new_descriptors; | 5269 DescriptorArray* new_descriptors; |
5055 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size); | 5270 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size); |
5056 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5271 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5272 DescriptorArray::WhitenessWitness witness(new_descriptors); |
5057 | 5273 |
5058 FixedArray::WhitenessWitness witness(new_descriptors); | 5274 for (int i = 0; i < new_size; ++i) { |
5059 | 5275 if (i == insertion_index) { |
5060 // Copy the descriptors, replacing a descriptor. | 5276 new_descriptors->Set(i, descriptor, witness); |
5061 for (int index = 0; index < size; ++index) { | 5277 } else { |
5062 if (index == insertion_index) continue; | 5278 new_descriptors->CopyFrom(i, descriptors, i, witness); |
5063 new_descriptors->CopyFrom(index, descriptors, index, witness); | 5279 } |
5064 } | 5280 } |
5065 | 5281 |
5066 PropertyDetails original_details = descriptors->GetDetails(insertion_index); | 5282 // Re-sort if descriptors were removed. |
5067 descriptor->SetEnumerationIndex(original_details.descriptor_index()); | 5283 if (new_size != descriptors->length()) new_descriptors->Sort(); |
5068 descriptor->SetSortedKey(original_details.pointer()); | |
5069 | |
5070 new_descriptors->Set(insertion_index, descriptor, witness); | |
5071 | |
5072 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); | |
5073 | 5284 |
5074 return CopyReplaceDescriptors(new_descriptors, key, flag); | 5285 return CopyReplaceDescriptors(new_descriptors, key, flag); |
5075 } | 5286 } |
5076 | 5287 |
5077 | 5288 |
5078 void Map::UpdateCodeCache(Handle<Map> map, | 5289 void Map::UpdateCodeCache(Handle<Map> map, |
5079 Handle<String> name, | 5290 Handle<String> name, |
5080 Handle<Code> code) { | 5291 Handle<Code> code) { |
5081 Isolate* isolate = map->GetIsolate(); | 5292 Isolate* isolate = map->GetIsolate(); |
5082 CALL_HEAP_FUNCTION_VOID(isolate, | 5293 CALL_HEAP_FUNCTION_VOID(isolate, |
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5860 return result; | 6071 return result; |
5861 } | 6072 } |
5862 | 6073 |
5863 | 6074 |
5864 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 6075 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
5865 FixedArray* new_cache, | 6076 FixedArray* new_cache, |
5866 Object* new_index_cache) { | 6077 Object* new_index_cache) { |
5867 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 6078 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
5868 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); | 6079 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); |
5869 if (HasEnumCache()) { | 6080 if (HasEnumCache()) { |
| 6081 ASSERT(new_cache->length() > FixedArray::cast(GetEnumCache())->length()); |
5870 FixedArray::cast(get(kEnumCacheIndex))-> | 6082 FixedArray::cast(get(kEnumCacheIndex))-> |
5871 set(kEnumCacheBridgeCacheIndex, new_cache); | 6083 set(kEnumCacheBridgeCacheIndex, new_cache); |
5872 FixedArray::cast(get(kEnumCacheIndex))-> | 6084 FixedArray::cast(get(kEnumCacheIndex))-> |
5873 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 6085 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
5874 } else { | 6086 } else { |
5875 if (IsEmpty()) return; // Do nothing for empty descriptor array. | 6087 ASSERT(!IsEmpty()); |
5876 FixedArray::cast(bridge_storage)-> | 6088 FixedArray::cast(bridge_storage)-> |
5877 set(kEnumCacheBridgeCacheIndex, new_cache); | 6089 set(kEnumCacheBridgeCacheIndex, new_cache); |
5878 FixedArray::cast(bridge_storage)-> | 6090 FixedArray::cast(bridge_storage)-> |
5879 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 6091 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
5880 set(kEnumCacheIndex, bridge_storage); | 6092 set(kEnumCacheIndex, bridge_storage); |
5881 } | 6093 } |
5882 } | 6094 } |
5883 | 6095 |
5884 | 6096 |
5885 void DescriptorArray::CopyFrom(int dst_index, | 6097 void DescriptorArray::CopyFrom(int dst_index, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5941 if (right_child_hash > child_hash) { | 6153 if (right_child_hash > child_hash) { |
5942 child_index++; | 6154 child_index++; |
5943 child_hash = right_child_hash; | 6155 child_hash = right_child_hash; |
5944 } | 6156 } |
5945 } | 6157 } |
5946 if (child_hash <= parent_hash) break; | 6158 if (child_hash <= parent_hash) break; |
5947 SwapSortedKeys(parent_index, child_index); | 6159 SwapSortedKeys(parent_index, child_index); |
5948 parent_index = child_index; | 6160 parent_index = child_index; |
5949 } | 6161 } |
5950 } | 6162 } |
| 6163 ASSERT(IsSortedNoDuplicates()); |
5951 } | 6164 } |
5952 | 6165 |
5953 | 6166 |
5954 MaybeObject* AccessorPair::Copy() { | 6167 MaybeObject* AccessorPair::Copy() { |
5955 Heap* heap = GetHeap(); | 6168 Heap* heap = GetHeap(); |
5956 AccessorPair* copy; | 6169 AccessorPair* copy; |
5957 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); | 6170 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); |
5958 if (!maybe_copy->To(©)) return maybe_copy; | 6171 if (!maybe_copy->To(©)) return maybe_copy; |
5959 | 6172 |
5960 copy->set_getter(getter()); | 6173 copy->set_getter(getter()); |
(...skipping 1227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7188 void String::PrintOn(FILE* file) { | 7401 void String::PrintOn(FILE* file) { |
7189 int length = this->length(); | 7402 int length = this->length(); |
7190 for (int i = 0; i < length; i++) { | 7403 for (int i = 0; i < length; i++) { |
7191 fprintf(file, "%c", Get(i)); | 7404 fprintf(file, "%c", Get(i)); |
7192 } | 7405 } |
7193 } | 7406 } |
7194 | 7407 |
7195 | 7408 |
7196 // Clear a possible back pointer in case the transition leads to a dead map. | 7409 // Clear a possible back pointer in case the transition leads to a dead map. |
7197 // Return true in case a back pointer has been cleared and false otherwise. | 7410 // Return true in case a back pointer has been cleared and false otherwise. |
7198 static bool ClearBackPointer(Heap* heap, Object* target) { | 7411 static bool ClearBackPointer(Heap* heap, Map* target) { |
7199 ASSERT(target->IsMap()); | 7412 if (Marking::MarkBitFrom(target).Get()) return false; |
7200 Map* map = Map::cast(target); | 7413 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); |
7201 if (Marking::MarkBitFrom(map).Get()) return false; | |
7202 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); | |
7203 return true; | 7414 return true; |
7204 } | 7415 } |
7205 | 7416 |
7206 | 7417 |
7207 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, | 7418 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, |
7208 // because it cannot be called from outside the GC and we already have methods | 7419 // because it cannot be called from outside the GC and we already have methods |
7209 // depending on the transitions layout in the GC anyways. | 7420 // depending on the transitions layout in the GC anyways. |
7210 void Map::ClearNonLiveTransitions(Heap* heap) { | 7421 void Map::ClearNonLiveTransitions(Heap* heap) { |
7211 // If there are no transitions to be cleared, return. | 7422 // If there are no transitions to be cleared, return. |
7212 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7423 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7213 // properly cleared. | 7424 // properly cleared. |
7214 if (!HasTransitionArray()) return; | 7425 if (!HasTransitionArray()) return; |
7215 | 7426 |
7216 TransitionArray* t = transitions(); | 7427 TransitionArray* t = transitions(); |
7217 MarkCompactCollector* collector = heap->mark_compact_collector(); | 7428 MarkCompactCollector* collector = heap->mark_compact_collector(); |
7218 | 7429 |
7219 int transition_index = 0; | 7430 int transition_index = 0; |
7220 | 7431 |
| 7432 DescriptorArray* descriptors = t->descriptors(); |
| 7433 bool descriptors_owner_died = false; |
| 7434 |
7221 // Compact all live descriptors to the left. | 7435 // Compact all live descriptors to the left. |
7222 for (int i = 0; i < t->number_of_transitions(); ++i) { | 7436 for (int i = 0; i < t->number_of_transitions(); ++i) { |
7223 if (!ClearBackPointer(heap, t->GetTarget(i))) { | 7437 Map* target = t->GetTarget(i); |
| 7438 if (ClearBackPointer(heap, target)) { |
| 7439 ASSERT(!Marking::IsGrey(Marking::MarkBitFrom(target))); |
| 7440 DescriptorArray* target_descriptors = target->instance_descriptors(); |
| 7441 if ((target_descriptors->number_of_descriptors() == 0 && |
| 7442 target->NumberOfOwnDescriptors() > 0) || |
| 7443 target_descriptors == descriptors) { |
| 7444 descriptors_owner_died = true; |
| 7445 } |
| 7446 } else { |
7224 if (i != transition_index) { | 7447 if (i != transition_index) { |
7225 String* key = t->GetKey(i); | 7448 String* key = t->GetKey(i); |
7226 t->SetKey(transition_index, key); | 7449 t->SetKey(transition_index, key); |
7227 Object** key_slot = t->GetKeySlot(transition_index); | 7450 Object** key_slot = t->GetKeySlot(transition_index); |
7228 collector->RecordSlot(key_slot, key_slot, key); | 7451 collector->RecordSlot(key_slot, key_slot, key); |
7229 // Target slots do not need to be recorded since maps are not compacted. | 7452 // Target slots do not need to be recorded since maps are not compacted. |
7230 t->SetTarget(transition_index, t->GetTarget(i)); | 7453 t->SetTarget(transition_index, t->GetTarget(i)); |
7231 } | 7454 } |
7232 transition_index++; | 7455 transition_index++; |
7233 } | 7456 } |
7234 } | 7457 } |
7235 | 7458 |
7236 if (t->HasElementsTransition() && | 7459 if (t->HasElementsTransition() && |
7237 ClearBackPointer(heap, t->elements_transition())) { | 7460 ClearBackPointer(heap, t->elements_transition())) { |
| 7461 if (t->elements_transition()->instance_descriptors() == descriptors) { |
| 7462 descriptors_owner_died = true; |
| 7463 } |
7238 t->ClearElementsTransition(); | 7464 t->ClearElementsTransition(); |
7239 } else { | 7465 } else { |
7240 // If there are no transitions to be cleared, return. | 7466 // If there are no transitions to be cleared, return. |
7241 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7467 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7242 // properly cleared. | 7468 // properly cleared. |
7243 if (transition_index == t->number_of_transitions()) return; | 7469 if (transition_index == t->number_of_transitions()) return; |
7244 } | 7470 } |
7245 | 7471 |
| 7472 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 7473 |
| 7474 if (descriptors_owner_died) { |
| 7475 if (number_of_own_descriptors > 0) { |
| 7476 int live_enum = NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); |
| 7477 int number_of_descriptors = descriptors->number_of_descriptors(); |
| 7478 int to_trim = number_of_descriptors - number_of_own_descriptors; |
| 7479 if (to_trim > 0) { |
| 7480 RightTrimFixedArray<FROM_GC>( |
| 7481 heap, descriptors, to_trim * DescriptorArray::kDescriptorSize); |
| 7482 if (descriptors->HasEnumCache()) { |
| 7483 FixedArray* enum_cache = |
| 7484 FixedArray::cast(descriptors->GetEnumCache()); |
| 7485 to_trim = enum_cache->length() - live_enum; |
| 7486 if (to_trim > 0) { |
| 7487 RightTrimFixedArray<FROM_GC>( |
| 7488 heap, FixedArray::cast(descriptors->GetEnumCache()), to_trim); |
| 7489 } |
| 7490 } |
| 7491 descriptors->Sort(); |
| 7492 } |
| 7493 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 7494 } else { |
| 7495 t->set_descriptors(heap->empty_descriptor_array()); |
| 7496 } |
| 7497 set_owns_descriptors(true); |
| 7498 } |
| 7499 |
7246 // If the final transition array does not contain any live transitions, remove | 7500 // If the final transition array does not contain any live transitions, remove |
7247 // the transition array from the map. | 7501 // the transition array from the map. |
7248 if (transition_index == 0 && | 7502 if (transition_index == 0 && |
7249 !t->HasElementsTransition() && | 7503 !t->HasElementsTransition() && |
7250 !t->HasPrototypeTransitions() && | 7504 !t->HasPrototypeTransitions() && |
7251 t->descriptors()->IsEmpty()) { | 7505 number_of_own_descriptors == 0) { |
| 7506 ASSERT(owns_descriptors()); |
7252 return ClearTransitions(heap); | 7507 return ClearTransitions(heap); |
7253 } | 7508 } |
7254 | 7509 |
7255 int trim = t->number_of_transitions() - transition_index; | 7510 int trim = t->number_of_transitions() - transition_index; |
7256 if (trim > 0) { | 7511 if (trim > 0) { |
7257 RightTrimFixedArray<FROM_GC>( | 7512 RightTrimFixedArray<FROM_GC>( |
7258 heap, t, trim * TransitionArray::kTransitionSize); | 7513 heap, t, trim * TransitionArray::kTransitionSize); |
7259 } | 7514 } |
7260 } | 7515 } |
7261 | 7516 |
(...skipping 3100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10362 } | 10617 } |
10363 | 10618 |
10364 LookupResult result(isolate); | 10619 LookupResult result(isolate); |
10365 LocalLookupRealNamedProperty(key, &result); | 10620 LocalLookupRealNamedProperty(key, &result); |
10366 return result.IsPropertyCallbacks(); | 10621 return result.IsPropertyCallbacks(); |
10367 } | 10622 } |
10368 | 10623 |
10369 | 10624 |
10370 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 10625 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
10371 return HasFastProperties() ? | 10626 return HasFastProperties() ? |
10372 map()->NumberOfDescribedProperties(filter) : | 10627 map()->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter) : |
10373 property_dictionary()->NumberOfElementsFilterAttributes(filter); | 10628 property_dictionary()->NumberOfElementsFilterAttributes(filter); |
10374 } | 10629 } |
10375 | 10630 |
10376 | 10631 |
10377 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { | 10632 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { |
10378 Object* temp = get(i); | 10633 Object* temp = get(i); |
10379 set(i, get(j)); | 10634 set(i, get(j)); |
10380 set(j, temp); | 10635 set(j, temp); |
10381 if (this != numbers) { | 10636 if (this != numbers) { |
10382 temp = numbers->get(i); | 10637 temp = numbers->get(i); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10486 } | 10741 } |
10487 } | 10742 } |
10488 | 10743 |
10489 | 10744 |
10490 // Fill in the names of local properties into the supplied storage. The main | 10745 // Fill in the names of local properties into the supplied storage. The main |
10491 // purpose of this function is to provide reflection information for the object | 10746 // purpose of this function is to provide reflection information for the object |
10492 // mirrors. | 10747 // mirrors. |
10493 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { | 10748 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { |
10494 ASSERT(storage->length() >= (NumberOfLocalProperties() - index)); | 10749 ASSERT(storage->length() >= (NumberOfLocalProperties() - index)); |
10495 if (HasFastProperties()) { | 10750 if (HasFastProperties()) { |
| 10751 int real_size = map()->NumberOfOwnDescriptors(); |
10496 DescriptorArray* descs = map()->instance_descriptors(); | 10752 DescriptorArray* descs = map()->instance_descriptors(); |
10497 ASSERT(storage->length() >= index + descs->number_of_descriptors()); | 10753 ASSERT(storage->length() >= index + real_size); |
10498 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 10754 for (int i = 0; i < real_size; i++) { |
10499 storage->set(index + i, descs->GetKey(i)); | 10755 storage->set(index + i, descs->GetKey(i)); |
10500 } | 10756 } |
10501 } else { | 10757 } else { |
10502 property_dictionary()->CopyKeysTo(storage, | 10758 property_dictionary()->CopyKeysTo(storage, |
10503 index, | 10759 index, |
10504 StringDictionary::UNSORTED); | 10760 StringDictionary::UNSORTED); |
10505 } | 10761 } |
10506 } | 10762 } |
10507 | 10763 |
10508 | 10764 |
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12191 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); | 12447 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); |
12192 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 12448 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
12193 } | 12449 } |
12194 FixedArray* enumeration_order = FixedArray::cast(obj); | 12450 FixedArray* enumeration_order = FixedArray::cast(obj); |
12195 | 12451 |
12196 // Fill the enumeration order array with property details. | 12452 // Fill the enumeration order array with property details. |
12197 int capacity = HashTable<Shape, Key>::Capacity(); | 12453 int capacity = HashTable<Shape, Key>::Capacity(); |
12198 int pos = 0; | 12454 int pos = 0; |
12199 for (int i = 0; i < capacity; i++) { | 12455 for (int i = 0; i < capacity; i++) { |
12200 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 12456 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
12201 enumeration_order->set( | 12457 int index = DetailsAt(i).dictionary_index(); |
12202 pos++, Smi::FromInt(DetailsAt(i).dictionary_index())); | 12458 enumeration_order->set(pos++, Smi::FromInt(index)); |
12203 } | 12459 } |
12204 } | 12460 } |
12205 | 12461 |
12206 // Sort the arrays wrt. enumeration order. | 12462 // Sort the arrays wrt. enumeration order. |
12207 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); | 12463 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); |
12208 | 12464 |
12209 // Overwrite the enumeration_order with the enumeration indices. | 12465 // Overwrite the enumeration_order with the enumeration indices. |
12210 for (int i = 0; i < length; i++) { | 12466 for (int i = 0; i < length; i++) { |
12211 int index = Smi::cast(iteration_order->get(i))->value(); | 12467 int index = Smi::cast(iteration_order->get(i))->value(); |
12212 int enum_index = PropertyDetails::kInitialIndex + i; | 12468 int enum_index = PropertyDetails::kInitialIndex + i; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12321 uint32_t hash) { | 12577 uint32_t hash) { |
12322 // Compute the key object. | 12578 // Compute the key object. |
12323 Object* k; | 12579 Object* k; |
12324 { MaybeObject* maybe_k = Shape::AsObject(key); | 12580 { MaybeObject* maybe_k = Shape::AsObject(key); |
12325 if (!maybe_k->ToObject(&k)) return maybe_k; | 12581 if (!maybe_k->ToObject(&k)) return maybe_k; |
12326 } | 12582 } |
12327 | 12583 |
12328 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); | 12584 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); |
12329 // Insert element at empty or deleted entry | 12585 // Insert element at empty or deleted entry |
12330 if (!details.IsDeleted() && | 12586 if (!details.IsDeleted() && |
12331 details.dictionary_index() == 0 && Shape::kIsEnumerable) { | 12587 details.dictionary_index() == 0 && |
| 12588 Shape::kIsEnumerable) { |
12332 // Assign an enumeration index to the property and update | 12589 // Assign an enumeration index to the property and update |
12333 // SetNextEnumerationIndex. | 12590 // SetNextEnumerationIndex. |
12334 int index = NextEnumerationIndex(); | 12591 int index = NextEnumerationIndex(); |
12335 details = PropertyDetails(details.attributes(), details.type(), index); | 12592 details = PropertyDetails(details.attributes(), details.type(), index); |
12336 SetNextEnumerationIndex(index + 1); | 12593 SetNextEnumerationIndex(index + 1); |
12337 } | 12594 } |
12338 SetEntry(entry, k, value, details); | 12595 SetEntry(entry, k, value, details); |
12339 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() | 12596 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() |
12340 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); | 12597 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); |
12341 HashTable<Shape, Key>::ElementAdded(); | 12598 HashTable<Shape, Key>::ElementAdded(); |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13215 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13472 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13216 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13473 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13217 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13474 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13218 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13475 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13219 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13476 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13220 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13477 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13221 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13478 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13222 } | 13479 } |
13223 | 13480 |
13224 } } // namespace v8::internal | 13481 } } // namespace v8::internal |
OLD | NEW |