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

Side by Side Diff: src/objects.cc

Issue 11072014: Reverting sharing of descriptor arrays: (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Bump version Created 8 years, 2 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 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; 480 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
481 } 481 }
482 Object* dict; 482 Object* dict;
483 { MaybeObject* maybe_dict = 483 { MaybeObject* maybe_dict =
484 property_dictionary()->Add(name, store_value, details); 484 property_dictionary()->Add(name, store_value, details);
485 if (!maybe_dict->ToObject(&dict)) return maybe_dict; 485 if (!maybe_dict->ToObject(&dict)) return maybe_dict;
486 } 486 }
487 set_properties(StringDictionary::cast(dict)); 487 set_properties(StringDictionary::cast(dict));
488 return value; 488 return value;
489 } 489 }
490 490 // Preserve enumeration index.
491 PropertyDetails original_details = property_dictionary()->DetailsAt(entry);
492 int enumeration_index;
493 // Preserve the enumeration index unless the property was deleted.
494 if (original_details.IsDeleted()) {
495 enumeration_index = property_dictionary()->NextEnumerationIndex();
496 property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
497 } else {
498 enumeration_index = original_details.dictionary_index();
499 ASSERT(enumeration_index > 0);
500 }
501
502 details = PropertyDetails( 491 details = PropertyDetails(
503 details.attributes(), details.type(), enumeration_index); 492 details.attributes(),
493 details.type(),
494 property_dictionary()->DetailsAt(entry).dictionary_index());
504 495
505 if (IsGlobalObject()) { 496 if (IsGlobalObject()) {
506 JSGlobalPropertyCell* cell = 497 JSGlobalPropertyCell* cell =
507 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); 498 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
508 cell->set_value(value); 499 cell->set_value(value);
509 // Please note we have to update the property details. 500 // Please note we have to update the property details.
510 property_dictionary()->DetailsAtPut(entry, details); 501 property_dictionary()->DetailsAtPut(entry, details);
511 } else { 502 } else {
512 property_dictionary()->SetEntry(entry, name, value, details); 503 property_dictionary()->SetEntry(entry, name, value, details);
513 } 504 }
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 } 1525 }
1535 return true; 1526 return true;
1536 } 1527 }
1537 1528
1538 1529
1539 MaybeObject* JSObject::AddFastProperty(String* name, 1530 MaybeObject* JSObject::AddFastProperty(String* name,
1540 Object* value, 1531 Object* value,
1541 PropertyAttributes attributes, 1532 PropertyAttributes attributes,
1542 StoreFromKeyed store_mode) { 1533 StoreFromKeyed store_mode) {
1543 ASSERT(!IsJSGlobalProxy()); 1534 ASSERT(!IsJSGlobalProxy());
1544 ASSERT(DescriptorArray::kNotFound == 1535 ASSERT(map()->instance_descriptors()->Search(name) ==
1545 map()->instance_descriptors()->Search( 1536 DescriptorArray::kNotFound);
1546 name, map()->NumberOfOwnDescriptors()));
1547 1537
1548 // Normalize the object if the name is an actual string (not the 1538 // Normalize the object if the name is an actual string (not the
1549 // hidden symbols) and is not a real identifier. 1539 // hidden symbols) and is not a real identifier.
1550 // Normalize the object if it will have too many fast properties. 1540 // Normalize the object if it will have too many fast properties.
1551 Isolate* isolate = GetHeap()->isolate(); 1541 Isolate* isolate = GetHeap()->isolate();
1552 StringInputBuffer buffer(name); 1542 StringInputBuffer buffer(name);
1553 if ((!IsIdentifier(isolate->unicode_cache(), &buffer) 1543 if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
1554 && name != isolate->heap()->hidden_symbol()) || 1544 && name != isolate->heap()->hidden_symbol()) ||
1555 (map()->unused_property_fields() == 0 && 1545 (map()->unused_property_fields() == 0 &&
1556 TooManyFastProperties(properties()->length(), store_mode))) { 1546 TooManyFastProperties(properties()->length(), store_mode))) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1756 return SetNormalizedProperty(name, value, new_details); 1746 return SetNormalizedProperty(name, value, new_details);
1757 } 1747 }
1758 1748
1759 1749
1760 MaybeObject* JSObject::ConvertTransitionToMapTransition( 1750 MaybeObject* JSObject::ConvertTransitionToMapTransition(
1761 int transition_index, 1751 int transition_index,
1762 String* name, 1752 String* name,
1763 Object* new_value, 1753 Object* new_value,
1764 PropertyAttributes attributes) { 1754 PropertyAttributes attributes) {
1765 Map* old_map = map(); 1755 Map* old_map = map();
1766 Map* old_target = old_map->GetTransition(transition_index);
1767 Object* result; 1756 Object* result;
1768 1757
1769 // To sever a transition to a map with which the descriptors are shared, the
1770 // larger map (more descriptors) needs to store its own descriptors array.
1771 // Both sides of the severed chain need to have their own descriptors pointer
1772 // to store distinct descriptor arrays.
1773
1774 // If the old_target did not yet store its own descriptors, the new
1775 // descriptors pointer is created for the old_target by temporarily clearing
1776 // the back pointer and setting its descriptor array. The ownership of the
1777 // descriptor array is returned to the smaller maps by installing a reduced
1778 // copy of the descriptor array in the old_map.
1779
1780 // This phase is executed before creating the new map since it requires
1781 // allocation that may fail.
1782 if (!old_target->StoresOwnDescriptors()) {
1783 DescriptorArray* old_descriptors = old_map->instance_descriptors();
1784
1785 old_target->SetBackPointer(GetHeap()->undefined_value());
1786 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors);
1787 // Reset the backpointer before returning failure, otherwise the map ends up
1788 // with an undefined backpointer and no descriptors, losing its own
1789 // descriptors. Setting the backpointer always succeeds.
1790 old_target->SetBackPointer(old_map);
1791 if (maybe_failure->IsFailure()) return maybe_failure;
1792
1793 old_map->set_owns_descriptors(true);
1794 }
1795
1796 MaybeObject* maybe_result = 1758 MaybeObject* maybe_result =
1797 ConvertDescriptorToField(name, new_value, attributes); 1759 ConvertDescriptorToField(name, new_value, attributes);
1798 if (!maybe_result->To(&result)) return maybe_result; 1760 if (!maybe_result->To(&result)) return maybe_result;
1799 1761
1800 if (!HasFastProperties()) return result; 1762 if (!HasFastProperties()) return result;
1801 1763
1802 // This method should only be used to convert existing transitions. Objects 1764 // This method should only be used to convert existing transitions. Objects
1803 // with the map of "new Object()" cannot have transitions in the first place. 1765 // with the map of "new Object()" cannot have transitions in the first place.
1804 Map* new_map = map(); 1766 ASSERT(map() != GetIsolate()->empty_object_map());
1805 ASSERT(new_map != GetIsolate()->empty_object_map());
1806 1767
1807 // TODO(verwaest): From here on we lose existing map transitions, causing 1768 // TODO(verwaest): From here on we lose existing map transitions, causing
1808 // invalid back pointers. This will change once we can store multiple 1769 // invalid back pointers. This will change once we can store multiple
1809 // transitions with the same key. 1770 // transitions with the same key.
1810 1771 old_map->SetTransition(transition_index, map());
1811 if (old_map->owns_descriptors()) { 1772 map()->SetBackPointer(old_map);
1812 // If the old map owns its own descriptors, transfer ownership to the
1813 // new_map and install its descriptors in the old_map. Since the old_map
1814 // stores the descriptors for the new_map, remove the transition array of
1815 // the new_map that is only in place to store the descriptors.
1816 old_map->transitions()->descriptors_pointer()->set_value(
1817 new_map->instance_descriptors());
1818 new_map->ClearTransitions(GetHeap());
1819 old_map->set_owns_descriptors(false);
1820 Map* map;
1821 JSGlobalPropertyCell* pointer =
1822 old_map->transitions()->descriptors_pointer();
1823 for (Object* current = old_map;
1824 !current->IsUndefined();
1825 current = map->GetBackPointer()) {
1826 map = Map::cast(current);
1827 if (!map->HasTransitionArray()) break;
1828 TransitionArray* transitions = map->transitions();
1829 if (transitions->descriptors_pointer() != pointer) break;
1830 map->SetEnumLength(Map::kInvalidEnumCache);
1831 }
1832 } else if (old_target->instance_descriptors() ==
1833 old_map->instance_descriptors()) {
1834 // Since the conversion above generated a new fast map with an additional
1835 // property which can be shared as well, install this descriptor pointer
1836 // along the entire chain of smaller maps; and remove the transition array
1837 // that is only in place to hold the descriptor array in the new map.
1838 Map* map;
1839 JSGlobalPropertyCell* new_pointer =
1840 new_map->transitions()->descriptors_pointer();
1841 JSGlobalPropertyCell* old_pointer =
1842 old_map->transitions()->descriptors_pointer();
1843 for (Object* current = old_map;
1844 !current->IsUndefined();
1845 current = map->GetBackPointer()) {
1846 map = Map::cast(current);
1847 if (!map->HasTransitionArray()) break;
1848 TransitionArray* transitions = map->transitions();
1849 if (transitions->descriptors_pointer() != old_pointer) break;
1850 map->SetEnumLength(Map::kInvalidEnumCache);
1851 transitions->set_descriptors_pointer(new_pointer);
1852 }
1853 new_map->ClearTransitions(GetHeap());
1854 }
1855
1856 old_map->SetTransition(transition_index, new_map);
1857 new_map->SetBackPointer(old_map);
1858 return result; 1773 return result;
1859 } 1774 }
1860 1775
1861 1776
1862 MaybeObject* JSObject::ConvertDescriptorToField(String* name, 1777 MaybeObject* JSObject::ConvertDescriptorToField(String* name,
1863 Object* new_value, 1778 Object* new_value,
1864 PropertyAttributes attributes) { 1779 PropertyAttributes attributes) {
1865 if (map()->unused_property_fields() == 0 && 1780 if (map()->unused_property_fields() == 0 &&
1866 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { 1781 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
1867 Object* obj; 1782 Object* obj;
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
2223 } 2138 }
2224 2139
2225 2140
2226 void Map::CopyAppendCallbackDescriptors(Handle<Map> map, 2141 void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
2227 Handle<Object> descriptors) { 2142 Handle<Object> descriptors) {
2228 Isolate* isolate = map->GetIsolate(); 2143 Isolate* isolate = map->GetIsolate();
2229 Handle<DescriptorArray> array(map->instance_descriptors()); 2144 Handle<DescriptorArray> array(map->instance_descriptors());
2230 v8::NeanderArray callbacks(descriptors); 2145 v8::NeanderArray callbacks(descriptors);
2231 int nof_callbacks = callbacks.length(); 2146 int nof_callbacks = callbacks.length();
2232 int descriptor_count = array->number_of_descriptors(); 2147 int descriptor_count = array->number_of_descriptors();
2233 ASSERT(descriptor_count == map->NumberOfOwnDescriptors());
2234 2148
2235 // Ensure the keys are symbols before writing them into the instance 2149 // Ensure the keys are symbols before writing them into the instance
2236 // descriptor. Since it may cause a GC, it has to be done before we 2150 // descriptor. Since it may cause a GC, it has to be done before we
2237 // temporarily put the heap in an invalid state while appending descriptors. 2151 // temporarily put the heap in an invalid state while appending descriptors.
2238 for (int i = 0; i < nof_callbacks; ++i) { 2152 for (int i = 0; i < nof_callbacks; ++i) {
2239 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); 2153 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
2240 Handle<String> key = 2154 Handle<String> key =
2241 isolate->factory()->SymbolFromString( 2155 isolate->factory()->SymbolFromString(
2242 Handle<String>(String::cast(entry->name()))); 2156 Handle<String>(String::cast(entry->name())));
2243 entry->set_name(*key); 2157 entry->set_name(*key);
2244 } 2158 }
2245 2159
2246 Handle<DescriptorArray> result = 2160 Handle<DescriptorArray> result =
2247 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks); 2161 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks);
2248 2162
2249 // Ensure that marking will not progress and change color of objects. 2163 // Ensure that marking will not progress and change color of objects.
2250 DescriptorArray::WhitenessWitness witness(*result); 2164 DescriptorArray::WhitenessWitness witness(*result);
2251 2165
2252 // Copy the descriptors from the array. 2166 // Copy the descriptors from the array.
2253 for (int i = 0; i < descriptor_count; i++) { 2167 if (0 < descriptor_count) {
2254 result->CopyFrom(i, *array, i, witness); 2168 for (int i = 0; i < descriptor_count; i++) {
2169 result->CopyFrom(i, *array, i, witness);
2170 }
2255 } 2171 }
2256 2172
2257 // After this point the GC is not allowed to run anymore until the map is in a 2173 // After this point the GC is not allowed to run anymore until the map is in a
2258 // consistent state again, i.e., all the descriptors are appended and the 2174 // consistent state again, i.e., all the descriptors are appended and the
2259 // descriptor array is trimmed to the right size. 2175 // descriptor array is trimmed to the right size.
2260 Map::SetDescriptors(map, result); 2176 Map::SetDescriptors(map, result);
2261 2177
2262 // Fill in new callback descriptors. Process the callbacks from 2178 // Fill in new callback descriptors. Process the callbacks from
2263 // back to front so that the last callback with a given name takes 2179 // back to front so that the last callback with a given name takes
2264 // precedence over previously added callbacks with that name. 2180 // precedence over previously added callbacks with that name.
2265 int nof = descriptor_count;
2266 for (int i = nof_callbacks - 1; i >= 0; i--) { 2181 for (int i = nof_callbacks - 1; i >= 0; i--) {
2267 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); 2182 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
2268 String* key = String::cast(entry->name()); 2183 String* key = String::cast(entry->name());
2269 // Check if a descriptor with this name already exists before writing. 2184 // Check if a descriptor with this name already exists before writing.
2270 if (result->Search(key, nof) == DescriptorArray::kNotFound) { 2185 if (LinearSearch(*result, key, map->NumberOfOwnDescriptors()) ==
2186 DescriptorArray::kNotFound) {
2271 CallbacksDescriptor desc(key, entry, entry->property_attributes()); 2187 CallbacksDescriptor desc(key, entry, entry->property_attributes());
2272 map->AppendDescriptor(&desc, witness); 2188 map->AppendDescriptor(&desc, witness);
2273 nof += 1;
2274 } 2189 }
2275 } 2190 }
2276 2191
2277 ASSERT(nof == map->NumberOfOwnDescriptors()); 2192 int new_number_of_descriptors = map->NumberOfOwnDescriptors();
2278
2279 // Reinstall the original descriptor array if no new elements were added. 2193 // Reinstall the original descriptor array if no new elements were added.
2280 if (nof == descriptor_count) { 2194 if (new_number_of_descriptors == descriptor_count) {
2281 Map::SetDescriptors(map, array); 2195 Map::SetDescriptors(map, array);
2282 return; 2196 return;
2283 } 2197 }
2284 2198
2285 // If duplicates were detected, trim the descriptor array to the right size. 2199 // If duplicates were detected, trim the descriptor array to the right size.
2286 int new_array_size = DescriptorArray::LengthFor(nof); 2200 int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors);
2287 if (new_array_size < result->length()) { 2201 if (new_array_size < result->length()) {
2288 RightTrimFixedArray<FROM_MUTATOR>( 2202 RightTrimFixedArray<FROM_MUTATOR>(
2289 isolate->heap(), *result, result->length() - new_array_size); 2203 isolate->heap(), *result, result->length() - new_array_size);
2290 } 2204 }
2291 } 2205 }
2292 2206
2293 2207
2294 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { 2208 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2295 ASSERT(!map.is_null()); 2209 ASSERT(!map.is_null());
2296 for (int i = 0; i < maps->length(); ++i) { 2210 for (int i = 0; i < maps->length(); ++i) {
(...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after
3343 if (!HasFastProperties()) return this; 3257 if (!HasFastProperties()) return this;
3344 3258
3345 // The global object is always normalized. 3259 // The global object is always normalized.
3346 ASSERT(!IsGlobalObject()); 3260 ASSERT(!IsGlobalObject());
3347 // JSGlobalProxy must never be normalized 3261 // JSGlobalProxy must never be normalized
3348 ASSERT(!IsJSGlobalProxy()); 3262 ASSERT(!IsJSGlobalProxy());
3349 3263
3350 Map* map_of_this = map(); 3264 Map* map_of_this = map();
3351 3265
3352 // Allocate new content. 3266 // Allocate new content.
3353 int real_size = map_of_this->NumberOfOwnDescriptors(); 3267 int property_count = map_of_this->NumberOfDescribedProperties();
3354 int property_count =
3355 map_of_this->NumberOfDescribedProperties(OWN_DESCRIPTORS);
3356 if (expected_additional_properties > 0) { 3268 if (expected_additional_properties > 0) {
3357 property_count += expected_additional_properties; 3269 property_count += expected_additional_properties;
3358 } else { 3270 } else {
3359 property_count += 2; // Make space for two more properties. 3271 property_count += 2; // Make space for two more properties.
3360 } 3272 }
3361 StringDictionary* dictionary; 3273 StringDictionary* dictionary;
3362 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); 3274 { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3363 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3275 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3276 }
3364 3277
3365 DescriptorArray* descs = map_of_this->instance_descriptors(); 3278 DescriptorArray* descs = map_of_this->instance_descriptors();
3366 for (int i = 0; i < real_size; i++) { 3279 for (int i = 0; i < descs->number_of_descriptors(); i++) {
3367 PropertyDetails details = descs->GetDetails(i); 3280 PropertyDetails details = descs->GetDetails(i);
3368 switch (details.type()) { 3281 switch (details.type()) {
3369 case CONSTANT_FUNCTION: { 3282 case CONSTANT_FUNCTION: {
3370 PropertyDetails d = PropertyDetails(details.attributes(), 3283 PropertyDetails d = PropertyDetails(details.attributes(),
3371 NORMAL, 3284 NORMAL,
3372 details.descriptor_index()); 3285 details.descriptor_index());
3373 Object* value = descs->GetConstantFunction(i); 3286 Object* value = descs->GetConstantFunction(i);
3374 MaybeObject* maybe_dictionary = 3287 MaybeObject* maybe_dictionary =
3375 dictionary->Add(descs->GetKey(i), value, d); 3288 dictionary->Add(descs->GetKey(i), value, d);
3376 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3289 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
(...skipping 24 matching lines...) Expand all
3401 case TRANSITION: 3314 case TRANSITION:
3402 case NONEXISTENT: 3315 case NONEXISTENT:
3403 UNREACHABLE(); 3316 UNREACHABLE();
3404 break; 3317 break;
3405 } 3318 }
3406 } 3319 }
3407 3320
3408 Heap* current_heap = GetHeap(); 3321 Heap* current_heap = GetHeap();
3409 3322
3410 // Copy the next enumeration index from instance descriptor. 3323 // Copy the next enumeration index from instance descriptor.
3411 dictionary->SetNextEnumerationIndex(real_size + 1); 3324 int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
3325 dictionary->SetNextEnumerationIndex(index);
3412 3326
3413 Map* new_map; 3327 Map* new_map;
3414 MaybeObject* maybe_map = 3328 MaybeObject* maybe_map =
3415 current_heap->isolate()->context()->native_context()-> 3329 current_heap->isolate()->context()->native_context()->
3416 normalized_map_cache()->Get(this, mode); 3330 normalized_map_cache()->Get(this, mode);
3417 if (!maybe_map->To(&new_map)) return maybe_map; 3331 if (!maybe_map->To(&new_map)) return maybe_map;
3418 ASSERT(new_map->is_dictionary_map()); 3332 ASSERT(new_map->is_dictionary_map());
3419 3333
3420 // We have now successfully allocated all the necessary objects. 3334 // We have now successfully allocated all the necessary objects.
3421 // Changes can now be made with the guarantee that all of them take effect. 3335 // 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
3747 ASSERT(!IsJSGlobalProxy()); 3661 ASSERT(!IsJSGlobalProxy());
3748 Object* inline_value; 3662 Object* inline_value;
3749 if (HasFastProperties()) { 3663 if (HasFastProperties()) {
3750 // If the object has fast properties, check whether the first slot 3664 // If the object has fast properties, check whether the first slot
3751 // in the descriptor array matches the hidden symbol. Since the 3665 // in the descriptor array matches the hidden symbol. Since the
3752 // hidden symbols hash code is zero (and no other string has hash 3666 // hidden symbols hash code is zero (and no other string has hash
3753 // code zero) it will always occupy the first entry if present. 3667 // code zero) it will always occupy the first entry if present.
3754 DescriptorArray* descriptors = this->map()->instance_descriptors(); 3668 DescriptorArray* descriptors = this->map()->instance_descriptors();
3755 if (descriptors->number_of_descriptors() > 0) { 3669 if (descriptors->number_of_descriptors() > 0) {
3756 int sorted_index = descriptors->GetSortedKeyIndex(0); 3670 int sorted_index = descriptors->GetSortedKeyIndex(0);
3757 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() && 3671 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
3758 sorted_index < map()->NumberOfOwnDescriptors()) {
3759 ASSERT(descriptors->GetType(sorted_index) == FIELD); 3672 ASSERT(descriptors->GetType(sorted_index) == FIELD);
3760 inline_value = 3673 inline_value = this->FastPropertyAt(
3761 this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index)); 3674 descriptors->GetFieldIndex(sorted_index));
3762 } else { 3675 } else {
3763 inline_value = GetHeap()->undefined_value(); 3676 inline_value = GetHeap()->undefined_value();
3764 } 3677 }
3765 } else { 3678 } else {
3766 inline_value = GetHeap()->undefined_value(); 3679 inline_value = GetHeap()->undefined_value();
3767 } 3680 }
3768 } else { 3681 } else {
3769 PropertyAttributes attributes; 3682 PropertyAttributes attributes;
3770 // You can't install a getter on a property indexed by the hidden symbol, 3683 // You can't install a getter on a property indexed by the hidden symbol,
3771 // so we can be sure that GetLocalPropertyPostInterceptor returns a real 3684 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3816 // for hidden properties yet. 3729 // for hidden properties yet.
3817 ASSERT(HasHiddenProperties() != value->IsSmi()); 3730 ASSERT(HasHiddenProperties() != value->IsSmi());
3818 if (HasFastProperties()) { 3731 if (HasFastProperties()) {
3819 // If the object has fast properties, check whether the first slot 3732 // If the object has fast properties, check whether the first slot
3820 // in the descriptor array matches the hidden symbol. Since the 3733 // in the descriptor array matches the hidden symbol. Since the
3821 // hidden symbols hash code is zero (and no other string has hash 3734 // hidden symbols hash code is zero (and no other string has hash
3822 // code zero) it will always occupy the first entry if present. 3735 // code zero) it will always occupy the first entry if present.
3823 DescriptorArray* descriptors = this->map()->instance_descriptors(); 3736 DescriptorArray* descriptors = this->map()->instance_descriptors();
3824 if (descriptors->number_of_descriptors() > 0) { 3737 if (descriptors->number_of_descriptors() > 0) {
3825 int sorted_index = descriptors->GetSortedKeyIndex(0); 3738 int sorted_index = descriptors->GetSortedKeyIndex(0);
3826 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() && 3739 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
3827 sorted_index < map()->NumberOfOwnDescriptors()) {
3828 ASSERT(descriptors->GetType(sorted_index) == FIELD); 3740 ASSERT(descriptors->GetType(sorted_index) == FIELD);
3829 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), 3741 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
3830 value); 3742 value);
3831 return this; 3743 return this;
3832 } 3744 }
3833 } 3745 }
3834 } 3746 }
3835 MaybeObject* store_result = 3747 MaybeObject* store_result =
3836 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), 3748 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3837 value, 3749 value,
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
4259 } 4171 }
4260 4172
4261 4173
4262 void Map::SetDescriptors(Handle<Map> map, 4174 void Map::SetDescriptors(Handle<Map> map,
4263 Handle<DescriptorArray> descriptors) { 4175 Handle<DescriptorArray> descriptors) {
4264 Isolate* isolate = map->GetIsolate(); 4176 Isolate* isolate = map->GetIsolate();
4265 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); 4177 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors));
4266 } 4178 }
4267 4179
4268 4180
4269 int Map::NumberOfDescribedProperties(DescriptorFlag which, 4181 int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
4270 PropertyAttributes filter) {
4271 int result = 0; 4182 int result = 0;
4272 DescriptorArray* descs = instance_descriptors(); 4183 DescriptorArray* descs = instance_descriptors();
4273 int limit = which == ALL_DESCRIPTORS 4184 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4274 ? descs->number_of_descriptors() 4185 PropertyDetails details = descs->GetDetails(i);
4275 : NumberOfOwnDescriptors(); 4186 if ((details.attributes() & filter) == 0) {
4276 for (int i = 0; i < limit; i++) { 4187 result++;
4277 if ((descs->GetDetails(i).attributes() & filter) == 0) result++; 4188 }
4278 } 4189 }
4279 return result; 4190 return result;
4280 } 4191 }
4281 4192
4282 4193
4283 int Map::PropertyIndexFor(String* name) { 4194 int Map::PropertyIndexFor(String* name) {
4284 DescriptorArray* descs = instance_descriptors(); 4195 DescriptorArray* descs = instance_descriptors();
4285 int limit = NumberOfOwnDescriptors(); 4196 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4286 for (int i = 0; i < limit; i++) {
4287 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i); 4197 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
4288 } 4198 }
4289 return -1; 4199 return -1;
4290 } 4200 }
4291 4201
4292 4202
4293 int Map::NextFreePropertyIndex() { 4203 int Map::NextFreePropertyIndex() {
4294 int max_index = -1; 4204 int max_index = -1;
4295 int number_of_own_descriptors = NumberOfOwnDescriptors();
4296 DescriptorArray* descs = instance_descriptors(); 4205 DescriptorArray* descs = instance_descriptors();
4297 for (int i = 0; i < number_of_own_descriptors; i++) { 4206 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4298 if (descs->GetType(i) == FIELD) { 4207 if (descs->GetType(i) == FIELD) {
4299 int current_index = descs->GetFieldIndex(i); 4208 int current_index = descs->GetFieldIndex(i);
4300 if (current_index > max_index) max_index = current_index; 4209 if (current_index > max_index) max_index = current_index;
4301 } 4210 }
4302 } 4211 }
4303 return max_index + 1; 4212 return max_index + 1;
4304 } 4213 }
4305 4214
4306 4215
4307 AccessorDescriptor* Map::FindAccessor(String* name) { 4216 AccessorDescriptor* Map::FindAccessor(String* name) {
4308 DescriptorArray* descs = instance_descriptors(); 4217 DescriptorArray* descs = instance_descriptors();
4309 int number_of_own_descriptors = NumberOfOwnDescriptors(); 4218 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4310 for (int i = 0; i < number_of_own_descriptors; i++) { 4219 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
4311 if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
4312 return descs->GetCallbacks(i); 4220 return descs->GetCallbacks(i);
4313 } 4221 }
4314 } 4222 }
4315 return NULL; 4223 return NULL;
4316 } 4224 }
4317 4225
4318 4226
4319 void JSReceiver::LocalLookup(String* name, LookupResult* result) { 4227 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
4320 ASSERT(name->IsString()); 4228 ASSERT(name->IsString());
4321 4229
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
4725 } else { 4633 } else {
4726 return GetHeap()->null_value(); 4634 return GetHeap()->null_value();
4727 } 4635 }
4728 4636
4729 int descriptor_number = result.GetDescriptorIndex(); 4637 int descriptor_number = result.GetDescriptorIndex();
4730 4638
4731 map()->LookupTransition(this, name, &result); 4639 map()->LookupTransition(this, name, &result);
4732 4640
4733 if (result.IsFound()) { 4641 if (result.IsFound()) {
4734 Map* target = result.GetTransitionTarget(); 4642 Map* target = result.GetTransitionTarget();
4735 ASSERT(target->NumberOfOwnDescriptors() == 4643 ASSERT(target->instance_descriptors()->number_of_descriptors() ==
4736 map()->NumberOfOwnDescriptors()); 4644 map()->instance_descriptors()->number_of_descriptors());
4737 // This works since descriptors are sorted in order of addition. 4645 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) == name);
4738 ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name);
4739 return TryAccessorTransition( 4646 return TryAccessorTransition(
4740 this, target, descriptor_number, component, accessor, attributes); 4647 this, target, descriptor_number, component, accessor, attributes);
4741 } 4648 }
4742 } else { 4649 } else {
4743 // If not, lookup a transition. 4650 // If not, lookup a transition.
4744 map()->LookupTransition(this, name, &result); 4651 map()->LookupTransition(this, name, &result);
4745 4652
4746 // If there is a transition, try to follow it. 4653 // If there is a transition, try to follow it.
4747 if (result.IsFound()) { 4654 if (result.IsFound()) {
4748 Map* target = result.GetTransitionTarget(); 4655 Map* target = result.GetTransitionTarget();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
4911 } 4818 }
4912 } 4819 }
4913 } 4820 }
4914 } 4821 }
4915 return heap->undefined_value(); 4822 return heap->undefined_value();
4916 } 4823 }
4917 4824
4918 4825
4919 Object* JSObject::SlowReverseLookup(Object* value) { 4826 Object* JSObject::SlowReverseLookup(Object* value) {
4920 if (HasFastProperties()) { 4827 if (HasFastProperties()) {
4921 int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
4922 DescriptorArray* descs = map()->instance_descriptors(); 4828 DescriptorArray* descs = map()->instance_descriptors();
4923 for (int i = 0; i < number_of_own_descriptors; i++) { 4829 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4924 if (descs->GetType(i) == FIELD) { 4830 if (descs->GetType(i) == FIELD) {
4925 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { 4831 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4926 return descs->GetKey(i); 4832 return descs->GetKey(i);
4927 } 4833 }
4928 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { 4834 } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4929 if (descs->GetConstantFunction(i) == value) { 4835 if (descs->GetConstantFunction(i) == value) {
4930 return descs->GetKey(i); 4836 return descs->GetKey(i);
4931 } 4837 }
4932 } 4838 }
4933 } 4839 }
4934 return GetHeap()->undefined_value(); 4840 return GetHeap()->undefined_value();
4935 } else { 4841 } else {
4936 return property_dictionary()->SlowReverseLookup(value); 4842 return property_dictionary()->SlowReverseLookup(value);
4937 } 4843 }
4938 } 4844 }
4939 4845
4940 4846
4941 MaybeObject* Map::RawCopy(int instance_size) { 4847 MaybeObject* Map::RawCopy(int instance_size) {
4942 Map* result; 4848 Map* result;
4943 MaybeObject* maybe_result = 4849 MaybeObject* maybe_result =
4944 GetHeap()->AllocateMap(instance_type(), instance_size); 4850 GetHeap()->AllocateMap(instance_type(), instance_size);
4945 if (!maybe_result->To(&result)) return maybe_result; 4851 if (!maybe_result->To(&result)) return maybe_result;
4946 4852
4947 result->set_prototype(prototype()); 4853 result->set_prototype(prototype());
4948 result->set_constructor(constructor()); 4854 result->set_constructor(constructor());
4949 result->set_bit_field(bit_field()); 4855 result->set_bit_field(bit_field());
4950 result->set_bit_field2(bit_field2()); 4856 result->set_bit_field2(bit_field2());
4951 result->set_bit_field3(bit_field3()); 4857 result->set_bit_field3(bit_field3());
4952 int new_bit_field3 = bit_field3(); 4858 result->SetNumberOfOwnDescriptors(0);
4953 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); 4859 result->SetEnumLength(kInvalidEnumCache);
4954 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
4955 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
4956 result->set_bit_field3(new_bit_field3);
4957 return result; 4860 return result;
4958 } 4861 }
4959 4862
4960 4863
4961 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, 4864 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
4962 NormalizedMapSharingMode sharing) { 4865 NormalizedMapSharingMode sharing) {
4963 int new_instance_size = instance_size(); 4866 int new_instance_size = instance_size();
4964 if (mode == CLEAR_INOBJECT_PROPERTIES) { 4867 if (mode == CLEAR_INOBJECT_PROPERTIES) {
4965 new_instance_size -= inobject_properties() * kPointerSize; 4868 new_instance_size -= inobject_properties() * kPointerSize;
4966 } 4869 }
(...skipping 29 matching lines...) Expand all
4996 result->set_inobject_properties(inobject_properties()); 4899 result->set_inobject_properties(inobject_properties());
4997 result->set_unused_property_fields(unused_property_fields()); 4900 result->set_unused_property_fields(unused_property_fields());
4998 4901
4999 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); 4902 result->set_pre_allocated_property_fields(pre_allocated_property_fields());
5000 result->set_is_shared(false); 4903 result->set_is_shared(false);
5001 result->ClearCodeCache(GetHeap()); 4904 result->ClearCodeCache(GetHeap());
5002 return result; 4905 return result;
5003 } 4906 }
5004 4907
5005 4908
5006 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
5007 // Sanity check. This path is only to be taken if the map owns its descriptor
5008 // array, implying that its NumberOfOwnDescriptors equals the number of
5009 // descriptors in the descriptor array.
5010 ASSERT(NumberOfOwnDescriptors() ==
5011 instance_descriptors()->number_of_descriptors());
5012 Map* result;
5013 MaybeObject* maybe_result = CopyDropDescriptors();
5014 if (!maybe_result->To(&result)) return maybe_result;
5015
5016 String* name = descriptor->GetKey();
5017
5018 TransitionArray* transitions;
5019 MaybeObject* maybe_transitions = AddTransition(name, result);
5020 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5021
5022 DescriptorArray* descriptors = instance_descriptors();
5023 int old_size = descriptors->number_of_descriptors();
5024
5025 DescriptorArray* new_descriptors;
5026 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1);
5027 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5028 DescriptorArray::WhitenessWitness witness(new_descriptors);
5029
5030 for (int i = 0; i < old_size; ++i) {
5031 new_descriptors->CopyFrom(i, descriptors, i, witness);
5032 }
5033 new_descriptors->Append(descriptor, witness, old_size);
5034
5035 // If the source descriptors had an enum cache we copy it. This ensures that
5036 // the maps to which we push the new descriptor array back can rely on a
5037 // cache always being available once it is set. If the map has more
5038 // enumerated descriptors than available in the original cache, the cache
5039 // will be lazily replaced by the extended cache when needed.
5040 if (descriptors->HasEnumCache()) {
5041 new_descriptors->CopyEnumCacheFrom(descriptors);
5042 }
5043
5044 transitions->set_descriptors(new_descriptors);
5045 set_transitions(transitions);
5046 result->SetBackPointer(this);
5047 set_owns_descriptors(false);
5048
5049 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors());
5050 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
5051
5052 return result;
5053 }
5054
5055
5056 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, 4909 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
5057 String* name, 4910 String* name,
5058 TransitionFlag flag) { 4911 TransitionFlag flag) {
5059 ASSERT(descriptors->IsSortedNoDuplicates());
5060
5061 Map* result; 4912 Map* result;
5062 MaybeObject* maybe_result = CopyDropDescriptors(); 4913 MaybeObject* maybe_result = CopyDropDescriptors();
5063 if (!maybe_result->To(&result)) return maybe_result; 4914 if (!maybe_result->To(&result)) return maybe_result;
5064 4915
5065 // Unless we are creating a map with no descriptors and no back pointer, we 4916 if (descriptors->number_of_descriptors() != 0) {
5066 // insert the descriptor array locally.
5067 if (!descriptors->IsEmpty()) {
5068 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); 4917 MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
5069 if (maybe_failure->IsFailure()) return maybe_failure; 4918 if (maybe_failure->IsFailure()) return maybe_failure;
5070 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); 4919 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
5071 } 4920 }
5072 4921
5073 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 4922 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
5074 TransitionArray* transitions; 4923 TransitionArray* transitions;
5075 MaybeObject* maybe_transitions = AddTransition(name, result); 4924 MaybeObject* maybe_transitions = AddTransition(name, result);
5076 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 4925 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5077 4926
5078 if (descriptors->IsEmpty()) {
5079 if (owns_descriptors()) {
5080 // If the copied map has no added fields, and the parent map owns its
5081 // descriptors, those descriptors have to be empty. In that case,
5082 // transfer ownership of the descriptors to the new child.
5083 ASSERT(instance_descriptors()->IsEmpty());
5084 set_owns_descriptors(false);
5085 } else {
5086 // If the parent did not own its own descriptors, it may share a larger
5087 // descriptors array already. In that case, force a split by setting
5088 // the descriptor array of the new map to the empty descriptor array.
5089 MaybeObject* maybe_failure =
5090 result->SetDescriptors(GetHeap()->empty_descriptor_array());
5091 if (maybe_failure->IsFailure()) return maybe_failure;
5092 }
5093 }
5094
5095 set_transitions(transitions); 4927 set_transitions(transitions);
5096 result->SetBackPointer(this); 4928 result->SetBackPointer(this);
5097 } 4929 }
5098 4930
5099 return result; 4931 return result;
5100 } 4932 }
5101 4933
5102 4934
5103 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 4935 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
4936 // Create a new free-floating map only if we are not allowed to store it.
4937 Map* new_map = NULL;
4938 MaybeObject* maybe_new_map = Copy();
4939 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4940 new_map->set_elements_kind(kind);
4941
5104 if (flag == INSERT_TRANSITION) { 4942 if (flag == INSERT_TRANSITION) {
5105 ASSERT(!HasElementsTransition() || 4943 ASSERT(!HasElementsTransition() ||
5106 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 4944 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
5107 IsExternalArrayElementsKind( 4945 IsExternalArrayElementsKind(
5108 elements_transition_map()->elements_kind())) && 4946 elements_transition_map()->elements_kind())) &&
5109 (kind == DICTIONARY_ELEMENTS || 4947 (kind == DICTIONARY_ELEMENTS ||
5110 IsExternalArrayElementsKind(kind)))); 4948 IsExternalArrayElementsKind(kind))));
5111 ASSERT(!IsFastElementsKind(kind) || 4949 ASSERT(!IsFastElementsKind(kind) ||
5112 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); 4950 IsMoreGeneralElementsKindTransition(elements_kind(), kind));
5113 ASSERT(kind != elements_kind()); 4951 ASSERT(kind != elements_kind());
5114 }
5115 4952
5116 if (flag == INSERT_TRANSITION && owns_descriptors()) {
5117 // In case the map owned its own descriptors, share the descriptors and
5118 // transfer ownership to the new map.
5119 Map* new_map;
5120 MaybeObject* maybe_new_map = CopyDropDescriptors();
5121 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5122
5123 MaybeObject* added_elements = set_elements_transition_map(new_map);
5124 if (added_elements->IsFailure()) return added_elements;
5125
5126 new_map->set_elements_kind(kind);
5127 new_map->SetBackPointer(this);
5128 new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors());
5129 set_owns_descriptors(false);
5130 return new_map;
5131 }
5132
5133 // In case the map did not own its own descriptors, a split is forced by
5134 // copying the map; creating a new descriptor array cell.
5135 // Create a new free-floating map only if we are not allowed to store it.
5136 Map* new_map;
5137 MaybeObject* maybe_new_map = Copy();
5138 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5139 ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors());
5140 new_map->set_elements_kind(kind);
5141
5142 if (flag == INSERT_TRANSITION) {
5143 // Map::Copy does not store the descriptor array in case it is empty, since
5144 // it does not insert a back pointer; implicitly indicating that its
5145 // descriptor array is empty. Since in this case we do want to insert a back
5146 // pointer, we have to manually set the empty descriptor array to force a
5147 // split.
5148 if (!new_map->StoresOwnDescriptors()) {
5149 ASSERT(new_map->NumberOfOwnDescriptors() == 0);
5150 MaybeObject* maybe_failure =
5151 new_map->SetDescriptors(GetHeap()->empty_descriptor_array());
5152 if (maybe_failure->IsFailure()) return maybe_failure;
5153 }
5154 MaybeObject* added_elements = set_elements_transition_map(new_map); 4953 MaybeObject* added_elements = set_elements_transition_map(new_map);
5155 if (added_elements->IsFailure()) return added_elements; 4954 if (added_elements->IsFailure()) return added_elements;
5156 4955
5157 new_map->SetBackPointer(this); 4956 new_map->SetBackPointer(this);
5158 } 4957 }
5159 4958
5160 return new_map; 4959 return new_map;
5161 } 4960 }
5162 4961
5163 4962
5164 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { 4963 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
5165 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); 4964 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
5166 4965
5167 // If the map has pre-allocated properties always start out with a descriptor 4966 // If the map has pre-allocated properties always start out with a descriptor
5168 // array describing these properties. 4967 // array describing these properties.
5169 ASSERT(constructor()->IsJSFunction()); 4968 ASSERT(constructor()->IsJSFunction());
5170 JSFunction* ctor = JSFunction::cast(constructor()); 4969 JSFunction* ctor = JSFunction::cast(constructor());
5171 Map* map = ctor->initial_map(); 4970 Map* map = ctor->initial_map();
5172 DescriptorArray* descriptors = map->instance_descriptors(); 4971 DescriptorArray* descriptors = map->instance_descriptors();
5173 4972
5174 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 4973 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
5175 DescriptorArray* new_descriptors;
5176 MaybeObject* maybe_descriptors =
5177 descriptors->CopyUpTo(number_of_own_descriptors);
5178 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5179
5180 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION);
5181 } 4974 }
5182 4975
5183 4976
5184 MaybeObject* Map::Copy() { 4977 MaybeObject* Map::Copy() {
5185 DescriptorArray* descriptors = instance_descriptors(); 4978 DescriptorArray* descriptors = instance_descriptors();
5186 DescriptorArray* new_descriptors; 4979 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
5187 int number_of_own_descriptors = NumberOfOwnDescriptors();
5188 MaybeObject* maybe_descriptors =
5189 descriptors->CopyUpTo(number_of_own_descriptors);
5190 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5191
5192 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION);
5193 } 4980 }
5194 4981
5195 4982
5196 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 4983 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
5197 TransitionFlag flag) { 4984 TransitionFlag flag) {
5198 DescriptorArray* descriptors = instance_descriptors(); 4985 DescriptorArray* descriptors = instance_descriptors();
5199 4986
5200 // Ensure the key is a symbol. 4987 // Ensure the key is a symbol.
5201 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 4988 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5202 if (maybe_failure->IsFailure()) return maybe_failure; 4989 if (maybe_failure->IsFailure()) return maybe_failure;
5203 4990
5204 int old_size = NumberOfOwnDescriptors(); 4991 String* key = descriptor->GetKey();
4992 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound);
4993
4994 int old_size = descriptors->number_of_descriptors();
5205 int new_size = old_size + 1; 4995 int new_size = old_size + 1;
5206 descriptor->SetEnumerationIndex(new_size);
5207
5208 if (flag == INSERT_TRANSITION &&
5209 owns_descriptors() &&
5210 CanHaveMoreTransitions()) {
5211 return ShareDescriptor(descriptor);
5212 }
5213 4996
5214 DescriptorArray* new_descriptors; 4997 DescriptorArray* new_descriptors;
5215 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); 4998 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
5216 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 4999 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5217 5000
5218 DescriptorArray::WhitenessWitness witness(new_descriptors); 5001 DescriptorArray::WhitenessWitness witness(new_descriptors);
5219 5002
5220 // Copy the descriptors, inserting a descriptor. 5003 // Copy the descriptors, inserting a descriptor.
5221 for (int i = 0; i < old_size; ++i) { 5004 for (int i = 0; i < old_size; ++i) {
5222 new_descriptors->CopyFrom(i, descriptors, i, witness); 5005 new_descriptors->CopyFrom(i, descriptors, i, witness);
5223 } 5006 }
5224 5007
5225 new_descriptors->Set(old_size, descriptor, witness); 5008 new_descriptors->Append(descriptor, witness, old_size);
5226 new_descriptors->Sort();
5227 5009
5228 return CopyReplaceDescriptors(new_descriptors, descriptor->GetKey(), flag); 5010 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5011
5012 return CopyReplaceDescriptors(new_descriptors, key, flag);
5229 } 5013 }
5230 5014
5231 5015
5232 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, 5016 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
5233 TransitionFlag flag) { 5017 TransitionFlag flag) {
5234 DescriptorArray* old_descriptors = instance_descriptors(); 5018 DescriptorArray* old_descriptors = instance_descriptors();
5235 5019
5236 // Ensure the key is a symbol. 5020 // Ensure the key is a symbol.
5237 MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5021 MaybeObject* maybe_result = descriptor->KeyToSymbol();
5238 if (maybe_result->IsFailure()) return maybe_result; 5022 if (maybe_result->IsFailure()) return maybe_result;
5239 5023
5240 // We replace the key if it is already present. 5024 // We replace the key if it is already present.
5241 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); 5025 int index = old_descriptors->SearchWithCache(descriptor->GetKey());
5242 if (index != DescriptorArray::kNotFound) { 5026 if (index != DescriptorArray::kNotFound) {
5243 return CopyReplaceDescriptor(descriptor, index, flag); 5027 return CopyReplaceDescriptor(descriptor, index, flag);
5244 } 5028 }
5245 return CopyAddDescriptor(descriptor, flag); 5029 return CopyAddDescriptor(descriptor, flag);
5246 } 5030 }
5247 5031
5248 5032
5249 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
5250 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
5251
5252 int size = enumeration_index;
5253
5254 DescriptorArray* descriptors;
5255 MaybeObject* maybe_descriptors = Allocate(size);
5256 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
5257 DescriptorArray::WhitenessWitness witness(descriptors);
5258
5259 for (int i = 0; i < size; ++i) {
5260 descriptors->CopyFrom(i, this, i, witness);
5261 }
5262
5263 if (number_of_descriptors() != enumeration_index) descriptors->Sort();
5264
5265 return descriptors;
5266 }
5267
5268
5269 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, 5033 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
5270 int insertion_index, 5034 int insertion_index,
5271 TransitionFlag flag) { 5035 TransitionFlag flag) {
5036 DescriptorArray* descriptors = instance_descriptors();
5037 int size = descriptors->number_of_descriptors();
5038 ASSERT(0 <= insertion_index && insertion_index < size);
5039
5272 // Ensure the key is a symbol. 5040 // Ensure the key is a symbol.
5273 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 5041 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5274 if (maybe_failure->IsFailure()) return maybe_failure; 5042 if (maybe_failure->IsFailure()) return maybe_failure;
5275 5043
5276 DescriptorArray* descriptors = instance_descriptors();
5277
5278 String* key = descriptor->GetKey(); 5044 String* key = descriptor->GetKey();
5279 ASSERT(key == descriptors->GetKey(insertion_index)); 5045 ASSERT(key == descriptors->GetKey(insertion_index));
5280 5046
5281 int new_size = NumberOfOwnDescriptors(); 5047 DescriptorArray* new_descriptors;
5282 ASSERT(0 <= insertion_index && insertion_index < new_size); 5048 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size);
5049 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5283 5050
5284 PropertyDetails details = descriptors->GetDetails(insertion_index);
5285 ASSERT_LE(details.descriptor_index(), new_size);
5286 descriptor->SetEnumerationIndex(details.descriptor_index());
5287
5288 DescriptorArray* new_descriptors;
5289 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
5290 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5291 DescriptorArray::WhitenessWitness witness(new_descriptors); 5051 DescriptorArray::WhitenessWitness witness(new_descriptors);
5292 5052
5293 for (int i = 0; i < new_size; ++i) { 5053 // Copy the descriptors, replacing a descriptor.
5294 if (i == insertion_index) { 5054 for (int index = 0; index < size; ++index) {
5295 new_descriptors->Set(i, descriptor, witness); 5055 if (index == insertion_index) continue;
5296 } else { 5056 new_descriptors->CopyFrom(index, descriptors, index, witness);
5297 new_descriptors->CopyFrom(i, descriptors, i, witness);
5298 }
5299 } 5057 }
5300 5058
5301 // Re-sort if descriptors were removed. 5059 PropertyDetails original_details = descriptors->GetDetails(insertion_index);
5302 if (new_size != descriptors->length()) new_descriptors->Sort(); 5060 descriptor->SetEnumerationIndex(original_details.descriptor_index());
5061 descriptor->SetSortedKey(original_details.pointer());
5062
5063 new_descriptors->Set(insertion_index, descriptor, witness);
5064
5065 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5303 5066
5304 return CopyReplaceDescriptors(new_descriptors, key, flag); 5067 return CopyReplaceDescriptors(new_descriptors, key, flag);
5305 } 5068 }
5306 5069
5307 5070
5308 void Map::UpdateCodeCache(Handle<Map> map, 5071 void Map::UpdateCodeCache(Handle<Map> map,
5309 Handle<String> name, 5072 Handle<String> name,
5310 Handle<Code> code) { 5073 Handle<Code> code) {
5311 Isolate* isolate = map->GetIsolate(); 5074 Isolate* isolate = map->GetIsolate();
5312 CALL_HEAP_FUNCTION_VOID(isolate, 5075 CALL_HEAP_FUNCTION_VOID(isolate,
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after
6084 // Allocate the array of keys. 5847 // Allocate the array of keys.
6085 MaybeObject* maybe_array = 5848 MaybeObject* maybe_array =
6086 heap->AllocateFixedArray(LengthFor(number_of_descriptors)); 5849 heap->AllocateFixedArray(LengthFor(number_of_descriptors));
6087 if (!maybe_array->To(&result)) return maybe_array; 5850 if (!maybe_array->To(&result)) return maybe_array;
6088 5851
6089 result->set(kEnumCacheIndex, Smi::FromInt(0)); 5852 result->set(kEnumCacheIndex, Smi::FromInt(0));
6090 return result; 5853 return result;
6091 } 5854 }
6092 5855
6093 5856
6094 void DescriptorArray::ClearEnumCache() {
6095 set(kEnumCacheIndex, Smi::FromInt(0));
6096 }
6097
6098
6099 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 5857 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
6100 FixedArray* new_cache, 5858 FixedArray* new_cache,
6101 Object* new_index_cache) { 5859 Object* new_index_cache) {
6102 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 5860 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
6103 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 5861 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
6104 if (HasEnumCache()) { 5862 if (HasEnumCache()) {
6105 ASSERT(new_cache->length() > FixedArray::cast(GetEnumCache())->length());
6106 FixedArray::cast(get(kEnumCacheIndex))-> 5863 FixedArray::cast(get(kEnumCacheIndex))->
6107 set(kEnumCacheBridgeCacheIndex, new_cache); 5864 set(kEnumCacheBridgeCacheIndex, new_cache);
6108 FixedArray::cast(get(kEnumCacheIndex))-> 5865 FixedArray::cast(get(kEnumCacheIndex))->
6109 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 5866 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
6110 } else { 5867 } else {
6111 ASSERT(!IsEmpty()); 5868 if (IsEmpty()) return; // Do nothing for empty descriptor array.
6112 FixedArray::cast(bridge_storage)-> 5869 FixedArray::cast(bridge_storage)->
6113 set(kEnumCacheBridgeCacheIndex, new_cache); 5870 set(kEnumCacheBridgeCacheIndex, new_cache);
6114 FixedArray::cast(bridge_storage)-> 5871 FixedArray::cast(bridge_storage)->
6115 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 5872 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
6116 set(kEnumCacheIndex, bridge_storage); 5873 set(kEnumCacheIndex, bridge_storage);
6117 } 5874 }
6118 } 5875 }
6119 5876
6120 5877
6121 void DescriptorArray::CopyFrom(int dst_index, 5878 void DescriptorArray::CopyFrom(int dst_index,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
6177 if (right_child_hash > child_hash) { 5934 if (right_child_hash > child_hash) {
6178 child_index++; 5935 child_index++;
6179 child_hash = right_child_hash; 5936 child_hash = right_child_hash;
6180 } 5937 }
6181 } 5938 }
6182 if (child_hash <= parent_hash) break; 5939 if (child_hash <= parent_hash) break;
6183 SwapSortedKeys(parent_index, child_index); 5940 SwapSortedKeys(parent_index, child_index);
6184 parent_index = child_index; 5941 parent_index = child_index;
6185 } 5942 }
6186 } 5943 }
6187 ASSERT(IsSortedNoDuplicates());
6188 } 5944 }
6189 5945
6190 5946
6191 MaybeObject* AccessorPair::Copy() { 5947 MaybeObject* AccessorPair::Copy() {
6192 Heap* heap = GetHeap(); 5948 Heap* heap = GetHeap();
6193 AccessorPair* copy; 5949 AccessorPair* copy;
6194 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); 5950 MaybeObject* maybe_copy = heap->AllocateAccessorPair();
6195 if (!maybe_copy->To(&copy)) return maybe_copy; 5951 if (!maybe_copy->To(&copy)) return maybe_copy;
6196 5952
6197 copy->set_getter(getter()); 5953 copy->set_getter(getter());
(...skipping 1227 matching lines...) Expand 10 before | Expand all | Expand 10 after
7425 void String::PrintOn(FILE* file) { 7181 void String::PrintOn(FILE* file) {
7426 int length = this->length(); 7182 int length = this->length();
7427 for (int i = 0; i < length; i++) { 7183 for (int i = 0; i < length; i++) {
7428 fprintf(file, "%c", Get(i)); 7184 fprintf(file, "%c", Get(i));
7429 } 7185 }
7430 } 7186 }
7431 7187
7432 7188
7433 // Clear a possible back pointer in case the transition leads to a dead map. 7189 // Clear a possible back pointer in case the transition leads to a dead map.
7434 // Return true in case a back pointer has been cleared and false otherwise. 7190 // Return true in case a back pointer has been cleared and false otherwise.
7435 static bool ClearBackPointer(Heap* heap, Map* target) { 7191 static bool ClearBackPointer(Heap* heap, Object* target) {
7436 if (Marking::MarkBitFrom(target).Get()) return false; 7192 ASSERT(target->IsMap());
7437 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); 7193 Map* map = Map::cast(target);
7194 if (Marking::MarkBitFrom(map).Get()) return false;
7195 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7438 return true; 7196 return true;
7439 } 7197 }
7440 7198
7441 7199
7442 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, 7200 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
7443 // because it cannot be called from outside the GC and we already have methods 7201 // because it cannot be called from outside the GC and we already have methods
7444 // depending on the transitions layout in the GC anyways. 7202 // depending on the transitions layout in the GC anyways.
7445 void Map::ClearNonLiveTransitions(Heap* heap) { 7203 void Map::ClearNonLiveTransitions(Heap* heap) {
7446 // If there are no transitions to be cleared, return. 7204 // If there are no transitions to be cleared, return.
7447 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7205 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7448 // properly cleared. 7206 // properly cleared.
7449 if (!HasTransitionArray()) return; 7207 if (!HasTransitionArray()) return;
7450 7208
7451 TransitionArray* t = transitions(); 7209 TransitionArray* t = transitions();
7452 MarkCompactCollector* collector = heap->mark_compact_collector(); 7210 MarkCompactCollector* collector = heap->mark_compact_collector();
7453 7211
7454 int transition_index = 0; 7212 int transition_index = 0;
7455 7213
7456 DescriptorArray* descriptors = t->descriptors();
7457 bool descriptors_owner_died = false;
7458
7459 // Compact all live descriptors to the left. 7214 // Compact all live descriptors to the left.
7460 for (int i = 0; i < t->number_of_transitions(); ++i) { 7215 for (int i = 0; i < t->number_of_transitions(); ++i) {
7461 Map* target = t->GetTarget(i); 7216 if (!ClearBackPointer(heap, t->GetTarget(i))) {
7462 if (ClearBackPointer(heap, target)) {
7463 ASSERT(!Marking::IsGrey(Marking::MarkBitFrom(target)));
7464 DescriptorArray* target_descriptors = target->instance_descriptors();
7465 if ((target_descriptors->number_of_descriptors() == 0 &&
7466 target->NumberOfOwnDescriptors() > 0) ||
7467 target_descriptors == descriptors) {
7468 descriptors_owner_died = true;
7469 }
7470 } else {
7471 if (i != transition_index) { 7217 if (i != transition_index) {
7472 String* key = t->GetKey(i); 7218 String* key = t->GetKey(i);
7473 t->SetKey(transition_index, key); 7219 t->SetKey(transition_index, key);
7474 Object** key_slot = t->GetKeySlot(transition_index); 7220 Object** key_slot = t->GetKeySlot(transition_index);
7475 collector->RecordSlot(key_slot, key_slot, key); 7221 collector->RecordSlot(key_slot, key_slot, key);
7476 // Target slots do not need to be recorded since maps are not compacted. 7222 // Target slots do not need to be recorded since maps are not compacted.
7477 t->SetTarget(transition_index, t->GetTarget(i)); 7223 t->SetTarget(transition_index, t->GetTarget(i));
7478 } 7224 }
7479 transition_index++; 7225 transition_index++;
7480 } 7226 }
7481 } 7227 }
7482 7228
7483 if (t->HasElementsTransition() && 7229 if (t->HasElementsTransition() &&
7484 ClearBackPointer(heap, t->elements_transition())) { 7230 ClearBackPointer(heap, t->elements_transition())) {
7485 if (t->elements_transition()->instance_descriptors() == descriptors) {
7486 descriptors_owner_died = true;
7487 }
7488 t->ClearElementsTransition(); 7231 t->ClearElementsTransition();
7489 } else { 7232 } else {
7490 // If there are no transitions to be cleared, return. 7233 // If there are no transitions to be cleared, return.
7491 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7234 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7492 // properly cleared. 7235 // properly cleared.
7493 if (transition_index == t->number_of_transitions()) return; 7236 if (transition_index == t->number_of_transitions()) return;
7494 } 7237 }
7495 7238
7496 int number_of_own_descriptors = NumberOfOwnDescriptors();
7497
7498 if (descriptors_owner_died) {
7499 if (number_of_own_descriptors > 0) {
7500 int number_of_descriptors = descriptors->number_of_descriptors();
7501 int to_trim = number_of_descriptors - number_of_own_descriptors;
7502 if (to_trim > 0) {
7503 RightTrimFixedArray<FROM_GC>(
7504 heap, descriptors, to_trim * DescriptorArray::kDescriptorSize);
7505 if (descriptors->HasEnumCache()) {
7506 int live_enum =
7507 NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
7508 if (live_enum == 0) {
7509 descriptors->ClearEnumCache();
7510 } else {
7511 FixedArray* enum_cache =
7512 FixedArray::cast(descriptors->GetEnumCache());
7513 to_trim = enum_cache->length() - live_enum;
7514 if (to_trim > 0) {
7515 RightTrimFixedArray<FROM_GC>(
7516 heap, FixedArray::cast(descriptors->GetEnumCache()), to_trim);
7517 }
7518 }
7519 }
7520 descriptors->Sort();
7521 }
7522 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
7523 } else {
7524 t->set_descriptors(heap->empty_descriptor_array());
7525 }
7526 set_owns_descriptors(true);
7527 }
7528
7529 // If the final transition array does not contain any live transitions, remove 7239 // If the final transition array does not contain any live transitions, remove
7530 // the transition array from the map. 7240 // the transition array from the map.
7531 if (transition_index == 0 && 7241 if (transition_index == 0 &&
7532 !t->HasElementsTransition() && 7242 !t->HasElementsTransition() &&
7533 !t->HasPrototypeTransitions() && 7243 !t->HasPrototypeTransitions() &&
7534 number_of_own_descriptors == 0) { 7244 t->descriptors()->IsEmpty()) {
7535 ASSERT(owns_descriptors());
7536 return ClearTransitions(heap); 7245 return ClearTransitions(heap);
7537 } 7246 }
7538 7247
7539 int trim = t->number_of_transitions() - transition_index; 7248 int trim = t->number_of_transitions() - transition_index;
7540 if (trim > 0) { 7249 if (trim > 0) {
7541 RightTrimFixedArray<FROM_GC>( 7250 RightTrimFixedArray<FROM_GC>(
7542 heap, t, trim * TransitionArray::kTransitionSize); 7251 heap, t, trim * TransitionArray::kTransitionSize);
7543 } 7252 }
7544 } 7253 }
7545 7254
(...skipping 3104 matching lines...) Expand 10 before | Expand all | Expand 10 after
10650 } 10359 }
10651 10360
10652 LookupResult result(isolate); 10361 LookupResult result(isolate);
10653 LocalLookupRealNamedProperty(key, &result); 10362 LocalLookupRealNamedProperty(key, &result);
10654 return result.IsPropertyCallbacks(); 10363 return result.IsPropertyCallbacks();
10655 } 10364 }
10656 10365
10657 10366
10658 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { 10367 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10659 return HasFastProperties() ? 10368 return HasFastProperties() ?
10660 map()->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter) : 10369 map()->NumberOfDescribedProperties(filter) :
10661 property_dictionary()->NumberOfElementsFilterAttributes(filter); 10370 property_dictionary()->NumberOfElementsFilterAttributes(filter);
10662 } 10371 }
10663 10372
10664 10373
10665 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { 10374 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10666 Object* temp = get(i); 10375 Object* temp = get(i);
10667 set(i, get(j)); 10376 set(i, get(j));
10668 set(j, temp); 10377 set(j, temp);
10669 if (this != numbers) { 10378 if (this != numbers) {
10670 temp = numbers->get(i); 10379 temp = numbers->get(i);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
10774 } 10483 }
10775 } 10484 }
10776 10485
10777 10486
10778 // Fill in the names of local properties into the supplied storage. The main 10487 // Fill in the names of local properties into the supplied storage. The main
10779 // purpose of this function is to provide reflection information for the object 10488 // purpose of this function is to provide reflection information for the object
10780 // mirrors. 10489 // mirrors.
10781 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { 10490 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10782 ASSERT(storage->length() >= (NumberOfLocalProperties() - index)); 10491 ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10783 if (HasFastProperties()) { 10492 if (HasFastProperties()) {
10784 int real_size = map()->NumberOfOwnDescriptors();
10785 DescriptorArray* descs = map()->instance_descriptors(); 10493 DescriptorArray* descs = map()->instance_descriptors();
10786 ASSERT(storage->length() >= index + real_size); 10494 ASSERT(storage->length() >= index + descs->number_of_descriptors());
10787 for (int i = 0; i < real_size; i++) { 10495 for (int i = 0; i < descs->number_of_descriptors(); i++) {
10788 storage->set(index + i, descs->GetKey(i)); 10496 storage->set(index + i, descs->GetKey(i));
10789 } 10497 }
10790 } else { 10498 } else {
10791 property_dictionary()->CopyKeysTo(storage, 10499 property_dictionary()->CopyKeysTo(storage,
10792 index, 10500 index,
10793 StringDictionary::UNSORTED); 10501 StringDictionary::UNSORTED);
10794 } 10502 }
10795 } 10503 }
10796 10504
10797 10505
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after
12480 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); 12188 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12481 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 12189 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12482 } 12190 }
12483 FixedArray* enumeration_order = FixedArray::cast(obj); 12191 FixedArray* enumeration_order = FixedArray::cast(obj);
12484 12192
12485 // Fill the enumeration order array with property details. 12193 // Fill the enumeration order array with property details.
12486 int capacity = HashTable<Shape, Key>::Capacity(); 12194 int capacity = HashTable<Shape, Key>::Capacity();
12487 int pos = 0; 12195 int pos = 0;
12488 for (int i = 0; i < capacity; i++) { 12196 for (int i = 0; i < capacity; i++) {
12489 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { 12197 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12490 int index = DetailsAt(i).dictionary_index(); 12198 enumeration_order->set(
12491 enumeration_order->set(pos++, Smi::FromInt(index)); 12199 pos++, Smi::FromInt(DetailsAt(i).dictionary_index()));
12492 } 12200 }
12493 } 12201 }
12494 12202
12495 // Sort the arrays wrt. enumeration order. 12203 // Sort the arrays wrt. enumeration order.
12496 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); 12204 iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12497 12205
12498 // Overwrite the enumeration_order with the enumeration indices. 12206 // Overwrite the enumeration_order with the enumeration indices.
12499 for (int i = 0; i < length; i++) { 12207 for (int i = 0; i < length; i++) {
12500 int index = Smi::cast(iteration_order->get(i))->value(); 12208 int index = Smi::cast(iteration_order->get(i))->value();
12501 int enum_index = PropertyDetails::kInitialIndex + i; 12209 int enum_index = PropertyDetails::kInitialIndex + i;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
12610 uint32_t hash) { 12318 uint32_t hash) {
12611 // Compute the key object. 12319 // Compute the key object.
12612 Object* k; 12320 Object* k;
12613 { MaybeObject* maybe_k = Shape::AsObject(key); 12321 { MaybeObject* maybe_k = Shape::AsObject(key);
12614 if (!maybe_k->ToObject(&k)) return maybe_k; 12322 if (!maybe_k->ToObject(&k)) return maybe_k;
12615 } 12323 }
12616 12324
12617 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); 12325 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12618 // Insert element at empty or deleted entry 12326 // Insert element at empty or deleted entry
12619 if (!details.IsDeleted() && 12327 if (!details.IsDeleted() &&
12620 details.dictionary_index() == 0 && 12328 details.dictionary_index() == 0 && Shape::kIsEnumerable) {
12621 Shape::kIsEnumerable) {
12622 // Assign an enumeration index to the property and update 12329 // Assign an enumeration index to the property and update
12623 // SetNextEnumerationIndex. 12330 // SetNextEnumerationIndex.
12624 int index = NextEnumerationIndex(); 12331 int index = NextEnumerationIndex();
12625 details = PropertyDetails(details.attributes(), details.type(), index); 12332 details = PropertyDetails(details.attributes(), details.type(), index);
12626 SetNextEnumerationIndex(index + 1); 12333 SetNextEnumerationIndex(index + 1);
12627 } 12334 }
12628 SetEntry(entry, k, value, details); 12335 SetEntry(entry, k, value, details);
12629 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() 12336 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12630 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); 12337 || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12631 HashTable<Shape, Key>::ElementAdded(); 12338 HashTable<Shape, Key>::ElementAdded();
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after
13505 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13212 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13506 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13213 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13507 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13214 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13508 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13215 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13509 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13216 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13510 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13217 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13511 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13218 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13512 } 13219 }
13513 13220
13514 } } // namespace v8::internal 13221 } } // 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