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

Side by Side Diff: src/objects.cc

Issue 10909007: Sharing of descriptor arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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(&copy)) return maybe_copy; 6171 if (!maybe_copy->To(&copy)) 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698