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

Side by Side Diff: src/objects.cc

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