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

Side by Side Diff: src/objects.cc

Issue 11028027: Revert trunk to bleeding_edge at r12484 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 value = result->holder()->FastPropertyAt(result->GetFieldIndex()); 635 value = result->holder()->FastPropertyAt(result->GetFieldIndex());
645 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 636 ASSERT(!value->IsTheHole() || result->IsReadOnly());
646 return value->IsTheHole() ? heap->undefined_value() : value; 637 return value->IsTheHole() ? heap->undefined_value() : value;
647 case CONSTANT_FUNCTION: 638 case CONSTANT_FUNCTION:
648 return result->GetConstantFunction(); 639 return result->GetConstantFunction();
649 case CALLBACKS: 640 case CALLBACKS:
650 return result->holder()->GetPropertyWithCallback( 641 return result->holder()->GetPropertyWithCallback(
651 receiver, result->GetCallbackObject(), name); 642 receiver, result->GetCallbackObject(), name);
652 case HANDLER: 643 case HANDLER:
653 return result->proxy()->GetPropertyWithHandler(receiver, name); 644 return result->proxy()->GetPropertyWithHandler(receiver, name);
654 case INTERCEPTOR: 645 case INTERCEPTOR: {
646 JSObject* recvr = JSObject::cast(receiver);
655 return result->holder()->GetPropertyWithInterceptor( 647 return result->holder()->GetPropertyWithInterceptor(
656 receiver, name, attributes); 648 recvr, name, attributes);
649 }
657 case TRANSITION: 650 case TRANSITION:
658 case NONEXISTENT: 651 case NONEXISTENT:
659 UNREACHABLE(); 652 UNREACHABLE();
660 break; 653 break;
661 } 654 }
662 UNREACHABLE(); 655 UNREACHABLE();
663 return NULL; 656 return NULL;
664 } 657 }
665 658
666 659
(...skipping 865 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 } 1525 }
1533 return true; 1526 return true;
1534 } 1527 }
1535 1528
1536 1529
1537 MaybeObject* JSObject::AddFastProperty(String* name, 1530 MaybeObject* JSObject::AddFastProperty(String* name,
1538 Object* value, 1531 Object* value,
1539 PropertyAttributes attributes, 1532 PropertyAttributes attributes,
1540 StoreFromKeyed store_mode) { 1533 StoreFromKeyed store_mode) {
1541 ASSERT(!IsJSGlobalProxy()); 1534 ASSERT(!IsJSGlobalProxy());
1542 ASSERT(DescriptorArray::kNotFound == 1535 ASSERT(map()->instance_descriptors()->Search(name) ==
1543 map()->instance_descriptors()->Search( 1536 DescriptorArray::kNotFound);
1544 name, map()->NumberOfOwnDescriptors()));
1545 1537
1546 // 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
1547 // hidden symbols) and is not a real identifier. 1539 // hidden symbols) and is not a real identifier.
1548 // Normalize the object if it will have too many fast properties. 1540 // Normalize the object if it will have too many fast properties.
1549 Isolate* isolate = GetHeap()->isolate(); 1541 Isolate* isolate = GetHeap()->isolate();
1550 StringInputBuffer buffer(name); 1542 StringInputBuffer buffer(name);
1551 if ((!IsIdentifier(isolate->unicode_cache(), &buffer) 1543 if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
1552 && name != isolate->heap()->hidden_symbol()) || 1544 && name != isolate->heap()->hidden_symbol()) ||
1553 (map()->unused_property_fields() == 0 && 1545 (map()->unused_property_fields() == 0 &&
1554 TooManyFastProperties(properties()->length(), store_mode))) { 1546 TooManyFastProperties(properties()->length(), store_mode))) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1683 return value; 1675 return value;
1684 } else { 1676 } else {
1685 Handle<Object> args[1] = {Handle<String>(name)}; 1677 Handle<Object> args[1] = {Handle<String>(name)};
1686 return heap->isolate()->Throw( 1678 return heap->isolate()->Throw(
1687 *FACTORY->NewTypeError("object_not_extensible", 1679 *FACTORY->NewTypeError("object_not_extensible",
1688 HandleVector(args, 1))); 1680 HandleVector(args, 1)));
1689 } 1681 }
1690 } 1682 }
1691 if (HasFastProperties()) { 1683 if (HasFastProperties()) {
1692 // Ensure the descriptor array does not get too big. 1684 // Ensure the descriptor array does not get too big.
1693 if (map_of_this->NumberOfOwnDescriptors() < 1685 if (map_of_this->instance_descriptors()->number_of_descriptors() <
1694 DescriptorArray::kMaxNumberOfDescriptors) { 1686 DescriptorArray::kMaxNumberOfDescriptors) {
1695 if (value->IsJSFunction()) { 1687 if (value->IsJSFunction()) {
1696 return AddConstantFunctionProperty(name, 1688 return AddConstantFunctionProperty(name,
1697 JSFunction::cast(value), 1689 JSFunction::cast(value),
1698 attributes); 1690 attributes);
1699 } else { 1691 } else {
1700 return AddFastProperty(name, value, attributes, store_mode); 1692 return AddFastProperty(name, value, attributes, store_mode);
1701 } 1693 }
1702 } else { 1694 } else {
1703 // Normalize the object to prevent very large instance descriptors. 1695 // Normalize the object to prevent very large instance descriptors.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1754 return SetNormalizedProperty(name, value, new_details); 1746 return SetNormalizedProperty(name, value, new_details);
1755 } 1747 }
1756 1748
1757 1749
1758 MaybeObject* JSObject::ConvertTransitionToMapTransition( 1750 MaybeObject* JSObject::ConvertTransitionToMapTransition(
1759 int transition_index, 1751 int transition_index,
1760 String* name, 1752 String* name,
1761 Object* new_value, 1753 Object* new_value,
1762 PropertyAttributes attributes) { 1754 PropertyAttributes attributes) {
1763 Map* old_map = map(); 1755 Map* old_map = map();
1764 Map* old_target = old_map->GetTransition(transition_index);
1765 Object* result; 1756 Object* result;
1766 1757
1767 // To sever a transition to a map with which the descriptors are shared, the
1768 // larger map (more descriptors) needs to store its own descriptors array.
1769 // Both sides of the severed chain need to have their own descriptors pointer
1770 // to store distinct descriptor arrays.
1771
1772 // If the old_target did not yet store its own descriptors, the new
1773 // descriptors pointer is created for the old_target by temporarily clearing
1774 // the back pointer and setting its descriptor array. The ownership of the
1775 // descriptor array is returned to the smaller maps by installing a reduced
1776 // copy of the descriptor array in the old_map.
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 old_map->set_owns_descriptors(true);
1792 }
1793
1794 MaybeObject* maybe_result = 1758 MaybeObject* maybe_result =
1795 ConvertDescriptorToField(name, new_value, attributes); 1759 ConvertDescriptorToField(name, new_value, attributes);
1796 if (!maybe_result->To(&result)) return maybe_result; 1760 if (!maybe_result->To(&result)) return maybe_result;
1797 1761
1798 if (!HasFastProperties()) return result; 1762 if (!HasFastProperties()) return result;
1799 1763
1800 // This method should only be used to convert existing transitions. Objects 1764 // This method should only be used to convert existing transitions. Objects
1801 // 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.
1802 Map* new_map = map(); 1766 ASSERT(map() != GetIsolate()->empty_object_map());
1803 ASSERT(new_map != GetIsolate()->empty_object_map());
1804 1767
1805 // TODO(verwaest): From here on we lose existing map transitions, causing 1768 // TODO(verwaest): From here on we lose existing map transitions, causing
1806 // invalid back pointers. This will change once we can store multiple 1769 // invalid back pointers. This will change once we can store multiple
1807 // transitions with the same key. 1770 // transitions with the same key.
1808 1771 old_map->SetTransition(transition_index, map());
1809 if (old_map->owns_descriptors()) { 1772 map()->SetBackPointer(old_map);
1810 // If the old map owns its own descriptors, transfer ownership to the
1811 // new_map and install its descriptors in the old_map. Since the old_map
1812 // stores the descriptors for the new_map, remove the transition array of
1813 // the new_map that is only in place to store the descriptors.
1814 old_map->transitions()->descriptors_pointer()->set_value(
1815 new_map->instance_descriptors());
1816 new_map->ClearTransitions(GetHeap());
1817 old_map->set_owns_descriptors(false);
1818 Map* map;
1819 JSGlobalPropertyCell* pointer =
1820 old_map->transitions()->descriptors_pointer();
1821 for (Object* current = old_map;
1822 !current->IsUndefined();
1823 current = map->GetBackPointer()) {
1824 map = Map::cast(current);
1825 if (!map->HasTransitionArray()) break;
1826 TransitionArray* transitions = map->transitions();
1827 if (transitions->descriptors_pointer() != pointer) break;
1828 map->SetEnumLength(Map::kInvalidEnumCache);
1829 }
1830 } else if (old_target->instance_descriptors() ==
1831 old_map->instance_descriptors()) {
1832 // Since the conversion above generated a new fast map with an additional
1833 // property which can be shared as well, install this descriptor pointer
1834 // along the entire chain of smaller maps; and remove the transition array
1835 // that is only in place to hold the descriptor array in the new map.
1836 Map* map;
1837 JSGlobalPropertyCell* new_pointer =
1838 new_map->transitions()->descriptors_pointer();
1839 JSGlobalPropertyCell* old_pointer =
1840 old_map->transitions()->descriptors_pointer();
1841 for (Object* current = old_map;
1842 !current->IsUndefined();
1843 current = map->GetBackPointer()) {
1844 map = Map::cast(current);
1845 if (!map->HasTransitionArray()) break;
1846 TransitionArray* transitions = map->transitions();
1847 if (transitions->descriptors_pointer() != old_pointer) break;
1848 map->SetEnumLength(Map::kInvalidEnumCache);
1849 transitions->set_descriptors_pointer(new_pointer);
1850 }
1851 new_map->ClearTransitions(GetHeap());
1852 }
1853
1854 old_map->SetTransition(transition_index, new_map);
1855 new_map->SetBackPointer(old_map);
1856 return result; 1773 return result;
1857 } 1774 }
1858 1775
1859 1776
1860 MaybeObject* JSObject::ConvertDescriptorToField(String* name, 1777 MaybeObject* JSObject::ConvertDescriptorToField(String* name,
1861 Object* new_value, 1778 Object* new_value,
1862 PropertyAttributes attributes) { 1779 PropertyAttributes attributes) {
1863 if (map()->unused_property_fields() == 0 && 1780 if (map()->unused_property_fields() == 0 &&
1864 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { 1781 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
1865 Object* obj; 1782 Object* obj;
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 return heap->the_hole_value(); 2086 return heap->the_hole_value();
2170 } 2087 }
2171 2088
2172 2089
2173 enum RightTrimMode { FROM_GC, FROM_MUTATOR }; 2090 enum RightTrimMode { FROM_GC, FROM_MUTATOR };
2174 2091
2175 2092
2176 static void ZapEndOfFixedArray(Address new_end, int to_trim) { 2093 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2177 // If we are doing a big trim in old space then we zap the space. 2094 // If we are doing a big trim in old space then we zap the space.
2178 Object** zap = reinterpret_cast<Object**>(new_end); 2095 Object** zap = reinterpret_cast<Object**>(new_end);
2179 zap++; // Header of filler must be at least one word so skip that.
2180 for (int i = 1; i < to_trim; i++) { 2096 for (int i = 1; i < to_trim; i++) {
2181 *zap++ = Smi::FromInt(0); 2097 *zap++ = Smi::FromInt(0);
2182 } 2098 }
2183 } 2099 }
2184 2100
2185
2186 template<RightTrimMode trim_mode> 2101 template<RightTrimMode trim_mode>
2187 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { 2102 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2188 ASSERT(elms->map() != HEAP->fixed_cow_array_map()); 2103 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
2189 // For now this trick is only applied to fixed arrays in new and paged space. 2104 // For now this trick is only applied to fixed arrays in new and paged space.
2190 ASSERT(!HEAP->lo_space()->Contains(elms)); 2105 ASSERT(!HEAP->lo_space()->Contains(elms));
2191 2106
2192 const int len = elms->length(); 2107 const int len = elms->length();
2193 2108
2194 ASSERT(to_trim < len); 2109 ASSERT(to_trim < len);
2195 2110
(...skipping 20 matching lines...) Expand all
2216 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { 2131 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
2217 if (trim_mode == FROM_GC) { 2132 if (trim_mode == FROM_GC) {
2218 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); 2133 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2219 } else { 2134 } else {
2220 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); 2135 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2221 } 2136 }
2222 } 2137 }
2223 } 2138 }
2224 2139
2225 2140
2226 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { 2141 void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
2227 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 2142 Handle<Object> descriptors) {
2228 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
2229 int number_of_descriptors = descriptors->number_of_descriptors();
2230 Isolate* isolate = map->GetIsolate();
2231 Handle<DescriptorArray> new_descriptors =
2232 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
2233 DescriptorArray::WhitenessWitness witness(*new_descriptors);
2234
2235 for (int i = 0; i < number_of_descriptors; ++i) {
2236 new_descriptors->CopyFrom(i, *descriptors, i, witness);
2237 }
2238
2239 Map::SetDescriptors(map, new_descriptors);
2240 }
2241
2242
2243 void Map::AppendCallbackDescriptors(Handle<Map> map,
2244 Handle<Object> descriptors) {
2245 Isolate* isolate = map->GetIsolate(); 2143 Isolate* isolate = map->GetIsolate();
2246 Handle<DescriptorArray> array(map->instance_descriptors()); 2144 Handle<DescriptorArray> array(map->instance_descriptors());
2247 NeanderArray callbacks(descriptors); 2145 v8::NeanderArray callbacks(descriptors);
2248 int nof_callbacks = callbacks.length(); 2146 int nof_callbacks = callbacks.length();
2249 2147 int descriptor_count = array->number_of_descriptors();
2250 ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
2251 2148
2252 // Ensure the keys are symbols before writing them into the instance 2149 // Ensure the keys are symbols before writing them into the instance
2253 // 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
2254 // temporarily put the heap in an invalid state while appending descriptors. 2151 // temporarily put the heap in an invalid state while appending descriptors.
2255 for (int i = 0; i < nof_callbacks; ++i) { 2152 for (int i = 0; i < nof_callbacks; ++i) {
2256 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); 2153 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
2257 Handle<String> key = 2154 Handle<String> key =
2258 isolate->factory()->SymbolFromString( 2155 isolate->factory()->SymbolFromString(
2259 Handle<String>(String::cast(entry->name()))); 2156 Handle<String>(String::cast(entry->name())));
2260 entry->set_name(*key); 2157 entry->set_name(*key);
2261 } 2158 }
2262 2159
2263 int nof = map->NumberOfOwnDescriptors(); 2160 Handle<DescriptorArray> result =
2161 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks);
2162
2163 // Ensure that marking will not progress and change color of objects.
2164 DescriptorArray::WhitenessWitness witness(*result);
2165
2166 // Copy the descriptors from the array.
2167 if (0 < descriptor_count) {
2168 for (int i = 0; i < descriptor_count; i++) {
2169 result->CopyFrom(i, *array, i, witness);
2170 }
2171 }
2172
2173 // 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
2175 // descriptor array is trimmed to the right size.
2176 Map::SetDescriptors(map, result);
2264 2177
2265 // Fill in new callback descriptors. Process the callbacks from 2178 // Fill in new callback descriptors. Process the callbacks from
2266 // 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
2267 // precedence over previously added callbacks with that name. 2180 // precedence over previously added callbacks with that name.
2268 for (int i = nof_callbacks - 1; i >= 0; i--) { 2181 for (int i = nof_callbacks - 1; i >= 0; i--) {
2269 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); 2182 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
2270 String* key = String::cast(entry->name()); 2183 String* key = String::cast(entry->name());
2271 // Check if a descriptor with this name already exists before writing. 2184 // Check if a descriptor with this name already exists before writing.
2272 if (array->Search(key, nof) == DescriptorArray::kNotFound) { 2185 if (LinearSearch(*result, key, map->NumberOfOwnDescriptors()) ==
2186 DescriptorArray::kNotFound) {
2273 CallbacksDescriptor desc(key, entry, entry->property_attributes()); 2187 CallbacksDescriptor desc(key, entry, entry->property_attributes());
2274 array->Append(&desc); 2188 map->AppendDescriptor(&desc, witness);
2275 nof += 1;
2276 } 2189 }
2277 } 2190 }
2278 2191
2279 map->SetNumberOfOwnDescriptors(nof); 2192 int new_number_of_descriptors = map->NumberOfOwnDescriptors();
2193 // Reinstall the original descriptor array if no new elements were added.
2194 if (new_number_of_descriptors == descriptor_count) {
2195 Map::SetDescriptors(map, array);
2196 return;
2197 }
2198
2199 // If duplicates were detected, trim the descriptor array to the right size.
2200 int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors);
2201 if (new_array_size < result->length()) {
2202 RightTrimFixedArray<FROM_MUTATOR>(
2203 isolate->heap(), *result, result->length() - new_array_size);
2204 }
2280 } 2205 }
2281 2206
2282 2207
2283 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { 2208 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2284 ASSERT(!map.is_null()); 2209 ASSERT(!map.is_null());
2285 for (int i = 0; i < maps->length(); ++i) { 2210 for (int i = 0; i < maps->length(); ++i) {
2286 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; 2211 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2287 } 2212 }
2288 return false; 2213 return false;
2289 } 2214 }
(...skipping 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after
3332 if (!HasFastProperties()) return this; 3257 if (!HasFastProperties()) return this;
3333 3258
3334 // The global object is always normalized. 3259 // The global object is always normalized.
3335 ASSERT(!IsGlobalObject()); 3260 ASSERT(!IsGlobalObject());
3336 // JSGlobalProxy must never be normalized 3261 // JSGlobalProxy must never be normalized
3337 ASSERT(!IsJSGlobalProxy()); 3262 ASSERT(!IsJSGlobalProxy());
3338 3263
3339 Map* map_of_this = map(); 3264 Map* map_of_this = map();
3340 3265
3341 // Allocate new content. 3266 // Allocate new content.
3342 int real_size = map_of_this->NumberOfOwnDescriptors(); 3267 int property_count = map_of_this->NumberOfDescribedProperties();
3343 int property_count = real_size;
3344 if (expected_additional_properties > 0) { 3268 if (expected_additional_properties > 0) {
3345 property_count += expected_additional_properties; 3269 property_count += expected_additional_properties;
3346 } else { 3270 } else {
3347 property_count += 2; // Make space for two more properties. 3271 property_count += 2; // Make space for two more properties.
3348 } 3272 }
3349 StringDictionary* dictionary; 3273 StringDictionary* dictionary;
3350 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); 3274 { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3351 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3275 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3276 }
3352 3277
3353 DescriptorArray* descs = map_of_this->instance_descriptors(); 3278 DescriptorArray* descs = map_of_this->instance_descriptors();
3354 for (int i = 0; i < real_size; i++) { 3279 for (int i = 0; i < descs->number_of_descriptors(); i++) {
3355 PropertyDetails details = descs->GetDetails(i); 3280 PropertyDetails details = descs->GetDetails(i);
3356 switch (details.type()) { 3281 switch (details.type()) {
3357 case CONSTANT_FUNCTION: { 3282 case CONSTANT_FUNCTION: {
3358 PropertyDetails d = PropertyDetails(details.attributes(), 3283 PropertyDetails d = PropertyDetails(details.attributes(),
3359 NORMAL, 3284 NORMAL,
3360 details.descriptor_index()); 3285 details.descriptor_index());
3361 Object* value = descs->GetConstantFunction(i); 3286 Object* value = descs->GetConstantFunction(i);
3362 MaybeObject* maybe_dictionary = 3287 MaybeObject* maybe_dictionary =
3363 dictionary->Add(descs->GetKey(i), value, d); 3288 dictionary->Add(descs->GetKey(i), value, d);
3364 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3289 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
(...skipping 24 matching lines...) Expand all
3389 case TRANSITION: 3314 case TRANSITION:
3390 case NONEXISTENT: 3315 case NONEXISTENT:
3391 UNREACHABLE(); 3316 UNREACHABLE();
3392 break; 3317 break;
3393 } 3318 }
3394 } 3319 }
3395 3320
3396 Heap* current_heap = GetHeap(); 3321 Heap* current_heap = GetHeap();
3397 3322
3398 // Copy the next enumeration index from instance descriptor. 3323 // Copy the next enumeration index from instance descriptor.
3399 dictionary->SetNextEnumerationIndex(real_size + 1); 3324 int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
3325 dictionary->SetNextEnumerationIndex(index);
3400 3326
3401 Map* new_map; 3327 Map* new_map;
3402 MaybeObject* maybe_map = 3328 MaybeObject* maybe_map =
3403 current_heap->isolate()->context()->native_context()-> 3329 current_heap->isolate()->context()->native_context()->
3404 normalized_map_cache()->Get(this, mode); 3330 normalized_map_cache()->Get(this, mode);
3405 if (!maybe_map->To(&new_map)) return maybe_map; 3331 if (!maybe_map->To(&new_map)) return maybe_map;
3406 ASSERT(new_map->is_dictionary_map()); 3332 ASSERT(new_map->is_dictionary_map());
3407 3333
3408 // We have now successfully allocated all the necessary objects. 3334 // We have now successfully allocated all the necessary objects.
3409 // 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
3735 ASSERT(!IsJSGlobalProxy()); 3661 ASSERT(!IsJSGlobalProxy());
3736 Object* inline_value; 3662 Object* inline_value;
3737 if (HasFastProperties()) { 3663 if (HasFastProperties()) {
3738 // If the object has fast properties, check whether the first slot 3664 // If the object has fast properties, check whether the first slot
3739 // in the descriptor array matches the hidden symbol. Since the 3665 // in the descriptor array matches the hidden symbol. Since the
3740 // 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
3741 // code zero) it will always occupy the first entry if present. 3667 // code zero) it will always occupy the first entry if present.
3742 DescriptorArray* descriptors = this->map()->instance_descriptors(); 3668 DescriptorArray* descriptors = this->map()->instance_descriptors();
3743 if (descriptors->number_of_descriptors() > 0) { 3669 if (descriptors->number_of_descriptors() > 0) {
3744 int sorted_index = descriptors->GetSortedKeyIndex(0); 3670 int sorted_index = descriptors->GetSortedKeyIndex(0);
3745 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() && 3671 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
3746 sorted_index < map()->NumberOfOwnDescriptors()) {
3747 ASSERT(descriptors->GetType(sorted_index) == FIELD); 3672 ASSERT(descriptors->GetType(sorted_index) == FIELD);
3748 inline_value = 3673 inline_value = this->FastPropertyAt(
3749 this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index)); 3674 descriptors->GetFieldIndex(sorted_index));
3750 } else { 3675 } else {
3751 inline_value = GetHeap()->undefined_value(); 3676 inline_value = GetHeap()->undefined_value();
3752 } 3677 }
3753 } else { 3678 } else {
3754 inline_value = GetHeap()->undefined_value(); 3679 inline_value = GetHeap()->undefined_value();
3755 } 3680 }
3756 } else { 3681 } else {
3757 PropertyAttributes attributes; 3682 PropertyAttributes attributes;
3758 // 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,
3759 // 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
3804 // for hidden properties yet. 3729 // for hidden properties yet.
3805 ASSERT(HasHiddenProperties() != value->IsSmi()); 3730 ASSERT(HasHiddenProperties() != value->IsSmi());
3806 if (HasFastProperties()) { 3731 if (HasFastProperties()) {
3807 // If the object has fast properties, check whether the first slot 3732 // If the object has fast properties, check whether the first slot
3808 // in the descriptor array matches the hidden symbol. Since the 3733 // in the descriptor array matches the hidden symbol. Since the
3809 // 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
3810 // code zero) it will always occupy the first entry if present. 3735 // code zero) it will always occupy the first entry if present.
3811 DescriptorArray* descriptors = this->map()->instance_descriptors(); 3736 DescriptorArray* descriptors = this->map()->instance_descriptors();
3812 if (descriptors->number_of_descriptors() > 0) { 3737 if (descriptors->number_of_descriptors() > 0) {
3813 int sorted_index = descriptors->GetSortedKeyIndex(0); 3738 int sorted_index = descriptors->GetSortedKeyIndex(0);
3814 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() && 3739 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
3815 sorted_index < map()->NumberOfOwnDescriptors()) {
3816 ASSERT(descriptors->GetType(sorted_index) == FIELD); 3740 ASSERT(descriptors->GetType(sorted_index) == FIELD);
3817 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), 3741 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
3818 value); 3742 value);
3819 return this; 3743 return this;
3820 } 3744 }
3821 } 3745 }
3822 } 3746 }
3823 MaybeObject* store_result = 3747 MaybeObject* store_result =
3824 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), 3748 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3825 value, 3749 value,
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
4247 } 4171 }
4248 4172
4249 4173
4250 void Map::SetDescriptors(Handle<Map> map, 4174 void Map::SetDescriptors(Handle<Map> map,
4251 Handle<DescriptorArray> descriptors) { 4175 Handle<DescriptorArray> descriptors) {
4252 Isolate* isolate = map->GetIsolate(); 4176 Isolate* isolate = map->GetIsolate();
4253 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); 4177 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors));
4254 } 4178 }
4255 4179
4256 4180
4257 int Map::NumberOfDescribedProperties(DescriptorFlag which, 4181 int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
4258 PropertyAttributes filter) {
4259 int result = 0; 4182 int result = 0;
4260 DescriptorArray* descs = instance_descriptors(); 4183 DescriptorArray* descs = instance_descriptors();
4261 int limit = which == ALL_DESCRIPTORS 4184 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4262 ? descs->number_of_descriptors() 4185 PropertyDetails details = descs->GetDetails(i);
4263 : NumberOfOwnDescriptors(); 4186 if ((details.attributes() & filter) == 0) {
4264 for (int i = 0; i < limit; i++) { 4187 result++;
4265 if ((descs->GetDetails(i).attributes() & filter) == 0) result++; 4188 }
4266 } 4189 }
4267 return result; 4190 return result;
4268 } 4191 }
4269 4192
4270 4193
4271 int Map::PropertyIndexFor(String* name) { 4194 int Map::PropertyIndexFor(String* name) {
4272 DescriptorArray* descs = instance_descriptors(); 4195 DescriptorArray* descs = instance_descriptors();
4273 int limit = NumberOfOwnDescriptors(); 4196 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4274 for (int i = 0; i < limit; i++) {
4275 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i); 4197 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
4276 } 4198 }
4277 return -1; 4199 return -1;
4278 } 4200 }
4279 4201
4280 4202
4281 int Map::NextFreePropertyIndex() { 4203 int Map::NextFreePropertyIndex() {
4282 int max_index = -1; 4204 int max_index = -1;
4283 int number_of_own_descriptors = NumberOfOwnDescriptors();
4284 DescriptorArray* descs = instance_descriptors(); 4205 DescriptorArray* descs = instance_descriptors();
4285 for (int i = 0; i < number_of_own_descriptors; i++) { 4206 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4286 if (descs->GetType(i) == FIELD) { 4207 if (descs->GetType(i) == FIELD) {
4287 int current_index = descs->GetFieldIndex(i); 4208 int current_index = descs->GetFieldIndex(i);
4288 if (current_index > max_index) max_index = current_index; 4209 if (current_index > max_index) max_index = current_index;
4289 } 4210 }
4290 } 4211 }
4291 return max_index + 1; 4212 return max_index + 1;
4292 } 4213 }
4293 4214
4294 4215
4295 AccessorDescriptor* Map::FindAccessor(String* name) { 4216 AccessorDescriptor* Map::FindAccessor(String* name) {
4296 DescriptorArray* descs = instance_descriptors(); 4217 DescriptorArray* descs = instance_descriptors();
4297 int number_of_own_descriptors = NumberOfOwnDescriptors(); 4218 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4298 for (int i = 0; i < number_of_own_descriptors; i++) { 4219 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
4299 if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
4300 return descs->GetCallbacks(i); 4220 return descs->GetCallbacks(i);
4301 } 4221 }
4302 } 4222 }
4303 return NULL; 4223 return NULL;
4304 } 4224 }
4305 4225
4306 4226
4307 void JSReceiver::LocalLookup(String* name, LookupResult* result) { 4227 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
4308 ASSERT(name->IsString()); 4228 ASSERT(name->IsString());
4309 4229
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
4713 } else { 4633 } else {
4714 return GetHeap()->null_value(); 4634 return GetHeap()->null_value();
4715 } 4635 }
4716 4636
4717 int descriptor_number = result.GetDescriptorIndex(); 4637 int descriptor_number = result.GetDescriptorIndex();
4718 4638
4719 map()->LookupTransition(this, name, &result); 4639 map()->LookupTransition(this, name, &result);
4720 4640
4721 if (result.IsFound()) { 4641 if (result.IsFound()) {
4722 Map* target = result.GetTransitionTarget(); 4642 Map* target = result.GetTransitionTarget();
4723 ASSERT(target->NumberOfOwnDescriptors() == 4643 ASSERT(target->instance_descriptors()->number_of_descriptors() ==
4724 map()->NumberOfOwnDescriptors()); 4644 map()->instance_descriptors()->number_of_descriptors());
4725 // This works since descriptors are sorted in order of addition. 4645 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) == name);
4726 ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name);
4727 return TryAccessorTransition( 4646 return TryAccessorTransition(
4728 this, target, descriptor_number, component, accessor, attributes); 4647 this, target, descriptor_number, component, accessor, attributes);
4729 } 4648 }
4730 } else { 4649 } else {
4731 // If not, lookup a transition. 4650 // If not, lookup a transition.
4732 map()->LookupTransition(this, name, &result); 4651 map()->LookupTransition(this, name, &result);
4733 4652
4734 // If there is a transition, try to follow it. 4653 // If there is a transition, try to follow it.
4735 if (result.IsFound()) { 4654 if (result.IsFound()) {
4736 Map* target = result.GetTransitionTarget(); 4655 Map* target = result.GetTransitionTarget();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
4899 } 4818 }
4900 } 4819 }
4901 } 4820 }
4902 } 4821 }
4903 return heap->undefined_value(); 4822 return heap->undefined_value();
4904 } 4823 }
4905 4824
4906 4825
4907 Object* JSObject::SlowReverseLookup(Object* value) { 4826 Object* JSObject::SlowReverseLookup(Object* value) {
4908 if (HasFastProperties()) { 4827 if (HasFastProperties()) {
4909 int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
4910 DescriptorArray* descs = map()->instance_descriptors(); 4828 DescriptorArray* descs = map()->instance_descriptors();
4911 for (int i = 0; i < number_of_own_descriptors; i++) { 4829 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4912 if (descs->GetType(i) == FIELD) { 4830 if (descs->GetType(i) == FIELD) {
4913 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { 4831 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4914 return descs->GetKey(i); 4832 return descs->GetKey(i);
4915 } 4833 }
4916 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { 4834 } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4917 if (descs->GetConstantFunction(i) == value) { 4835 if (descs->GetConstantFunction(i) == value) {
4918 return descs->GetKey(i); 4836 return descs->GetKey(i);
4919 } 4837 }
4920 } 4838 }
4921 } 4839 }
4922 return GetHeap()->undefined_value(); 4840 return GetHeap()->undefined_value();
4923 } else { 4841 } else {
4924 return property_dictionary()->SlowReverseLookup(value); 4842 return property_dictionary()->SlowReverseLookup(value);
4925 } 4843 }
4926 } 4844 }
4927 4845
4928 4846
4929 MaybeObject* Map::RawCopy(int instance_size) { 4847 MaybeObject* Map::RawCopy(int instance_size) {
4930 Map* result; 4848 Map* result;
4931 MaybeObject* maybe_result = 4849 MaybeObject* maybe_result =
4932 GetHeap()->AllocateMap(instance_type(), instance_size); 4850 GetHeap()->AllocateMap(instance_type(), instance_size);
4933 if (!maybe_result->To(&result)) return maybe_result; 4851 if (!maybe_result->To(&result)) return maybe_result;
4934 4852
4935 result->set_prototype(prototype()); 4853 result->set_prototype(prototype());
4936 result->set_constructor(constructor()); 4854 result->set_constructor(constructor());
4937 result->set_bit_field(bit_field()); 4855 result->set_bit_field(bit_field());
4938 result->set_bit_field2(bit_field2()); 4856 result->set_bit_field2(bit_field2());
4939 result->set_bit_field3(bit_field3()); 4857 result->set_bit_field3(bit_field3());
4940 int new_bit_field3 = bit_field3(); 4858 result->SetNumberOfOwnDescriptors(0);
4941 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); 4859 result->SetEnumLength(kInvalidEnumCache);
4942 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
4943 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
4944 result->set_bit_field3(new_bit_field3);
4945 return result; 4860 return result;
4946 } 4861 }
4947 4862
4948 4863
4949 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, 4864 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
4950 NormalizedMapSharingMode sharing) { 4865 NormalizedMapSharingMode sharing) {
4951 int new_instance_size = instance_size(); 4866 int new_instance_size = instance_size();
4952 if (mode == CLEAR_INOBJECT_PROPERTIES) { 4867 if (mode == CLEAR_INOBJECT_PROPERTIES) {
4953 new_instance_size -= inobject_properties() * kPointerSize; 4868 new_instance_size -= inobject_properties() * kPointerSize;
4954 } 4869 }
(...skipping 29 matching lines...) Expand all
4984 result->set_inobject_properties(inobject_properties()); 4899 result->set_inobject_properties(inobject_properties());
4985 result->set_unused_property_fields(unused_property_fields()); 4900 result->set_unused_property_fields(unused_property_fields());
4986 4901
4987 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); 4902 result->set_pre_allocated_property_fields(pre_allocated_property_fields());
4988 result->set_is_shared(false); 4903 result->set_is_shared(false);
4989 result->ClearCodeCache(GetHeap()); 4904 result->ClearCodeCache(GetHeap());
4990 return result; 4905 return result;
4991 } 4906 }
4992 4907
4993 4908
4994 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
4995 // Sanity check. This path is only to be taken if the map owns its descriptor
4996 // array, implying that its NumberOfOwnDescriptors equals the number of
4997 // descriptors in the descriptor array.
4998 ASSERT(NumberOfOwnDescriptors() ==
4999 instance_descriptors()->number_of_descriptors());
5000 Map* result;
5001 MaybeObject* maybe_result = CopyDropDescriptors();
5002 if (!maybe_result->To(&result)) return maybe_result;
5003
5004 String* name = descriptor->GetKey();
5005
5006 TransitionArray* transitions;
5007 MaybeObject* maybe_transitions =
5008 AddTransition(name, result, SIMPLE_TRANSITION);
5009 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5010
5011 DescriptorArray* descriptors = instance_descriptors();
5012 int old_size = descriptors->number_of_descriptors();
5013
5014 DescriptorArray* new_descriptors;
5015
5016 if (descriptors->NumberOfSlackDescriptors() > 0) {
5017 new_descriptors = descriptors;
5018 new_descriptors->Append(descriptor);
5019 } else {
5020 // Descriptor arrays grow by 50%.
5021 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
5022 old_size, old_size < 4 ? 1 : old_size / 2);
5023 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5024
5025 DescriptorArray::WhitenessWitness witness(new_descriptors);
5026
5027 // Copy the descriptors, inserting a descriptor.
5028 for (int i = 0; i < old_size; ++i) {
5029 new_descriptors->CopyFrom(i, descriptors, i, witness);
5030 }
5031
5032 new_descriptors->Append(descriptor, witness);
5033
5034 // If the source descriptors had an enum cache we copy it. This ensures that
5035 // the maps to which we push the new descriptor array back can rely on a
5036 // cache always being available once it is set. If the map has more
5037 // enumerated descriptors than available in the original cache, the cache
5038 // will be lazily replaced by the extended cache when needed.
5039 if (descriptors->HasEnumCache()) {
5040 new_descriptors->CopyEnumCacheFrom(descriptors);
5041 }
5042 }
5043
5044 transitions->set_descriptors(new_descriptors);
5045
5046 set_transitions(transitions);
5047 result->SetBackPointer(this);
5048 set_owns_descriptors(false);
5049
5050 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors());
5051 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
5052
5053 return result;
5054 }
5055
5056
5057 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, 4909 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
5058 String* name, 4910 String* name,
5059 TransitionFlag flag, 4911 TransitionFlag flag) {
5060 int descriptor_index) {
5061 ASSERT(descriptors->IsSortedNoDuplicates());
5062
5063 Map* result; 4912 Map* result;
5064 MaybeObject* maybe_result = CopyDropDescriptors(); 4913 MaybeObject* maybe_result = CopyDropDescriptors();
5065 if (!maybe_result->To(&result)) return maybe_result; 4914 if (!maybe_result->To(&result)) return maybe_result;
5066 4915
5067 // Unless we are creating a map with no descriptors and no back pointer, we 4916 if (descriptors->number_of_descriptors() != 0) {
5068 // insert the descriptor array locally.
5069 if (!descriptors->IsEmpty()) {
5070 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); 4917 MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
5071 if (maybe_failure->IsFailure()) return maybe_failure; 4918 if (maybe_failure->IsFailure()) return maybe_failure;
5072 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); 4919 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
5073 } 4920 }
5074 4921
5075 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 4922 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
5076 TransitionArray* transitions; 4923 TransitionArray* transitions;
5077 SimpleTransitionFlag simple_flag = 4924 MaybeObject* maybe_transitions = AddTransition(name, result);
5078 (descriptor_index == descriptors->number_of_descriptors() - 1)
5079 ? SIMPLE_TRANSITION
5080 : FULL_TRANSITION;
5081 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
5082 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 4925 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5083 4926
5084 if (descriptors->IsEmpty()) {
5085 if (owns_descriptors()) {
5086 // If the copied map has no added fields, and the parent map owns its
5087 // descriptors, those descriptors have to be empty. In that case,
5088 // transfer ownership of the descriptors to the new child.
5089 ASSERT(instance_descriptors()->IsEmpty());
5090 set_owns_descriptors(false);
5091 } else {
5092 // If the parent did not own its own descriptors, it may share a larger
5093 // descriptors array already. In that case, force a split by setting
5094 // the descriptor array of the new map to the empty descriptor array.
5095 MaybeObject* maybe_failure =
5096 result->SetDescriptors(GetHeap()->empty_descriptor_array());
5097 if (maybe_failure->IsFailure()) return maybe_failure;
5098 }
5099 }
5100
5101 set_transitions(transitions); 4927 set_transitions(transitions);
5102 result->SetBackPointer(this); 4928 result->SetBackPointer(this);
5103 } 4929 }
5104 4930
5105 return result; 4931 return result;
5106 } 4932 }
5107 4933
5108 4934
5109 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
5110 if (flag == INSERT_TRANSITION) { 4942 if (flag == INSERT_TRANSITION) {
5111 ASSERT(!HasElementsTransition() || 4943 ASSERT(!HasElementsTransition() ||
5112 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 4944 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
5113 IsExternalArrayElementsKind( 4945 IsExternalArrayElementsKind(
5114 elements_transition_map()->elements_kind())) && 4946 elements_transition_map()->elements_kind())) &&
5115 (kind == DICTIONARY_ELEMENTS || 4947 (kind == DICTIONARY_ELEMENTS ||
5116 IsExternalArrayElementsKind(kind)))); 4948 IsExternalArrayElementsKind(kind))));
5117 ASSERT(!IsFastElementsKind(kind) || 4949 ASSERT(!IsFastElementsKind(kind) ||
5118 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); 4950 IsMoreGeneralElementsKindTransition(elements_kind(), kind));
5119 ASSERT(kind != elements_kind()); 4951 ASSERT(kind != elements_kind());
5120 }
5121 4952
5122 if (flag == INSERT_TRANSITION && owns_descriptors()) {
5123 // In case the map owned its own descriptors, share the descriptors and
5124 // transfer ownership to the new map.
5125 Map* new_map;
5126 MaybeObject* maybe_new_map = CopyDropDescriptors();
5127 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5128
5129 MaybeObject* added_elements = set_elements_transition_map(new_map);
5130 if (added_elements->IsFailure()) return added_elements;
5131
5132 new_map->set_elements_kind(kind);
5133 new_map->SetBackPointer(this);
5134 new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors());
5135 set_owns_descriptors(false);
5136 return new_map;
5137 }
5138
5139 // In case the map did not own its own descriptors, a split is forced by
5140 // copying the map; creating a new descriptor array cell.
5141 // Create a new free-floating map only if we are not allowed to store it.
5142 Map* new_map;
5143 MaybeObject* maybe_new_map = Copy();
5144 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5145 ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors());
5146 new_map->set_elements_kind(kind);
5147
5148 if (flag == INSERT_TRANSITION) {
5149 // Map::Copy does not store the descriptor array in case it is empty, since
5150 // it does not insert a back pointer; implicitly indicating that its
5151 // descriptor array is empty. Since in this case we do want to insert a back
5152 // pointer, we have to manually set the empty descriptor array to force a
5153 // split.
5154 if (!new_map->StoresOwnDescriptors()) {
5155 ASSERT(new_map->NumberOfOwnDescriptors() == 0);
5156 MaybeObject* maybe_failure =
5157 new_map->SetDescriptors(GetHeap()->empty_descriptor_array());
5158 if (maybe_failure->IsFailure()) return maybe_failure;
5159 }
5160 MaybeObject* added_elements = set_elements_transition_map(new_map); 4953 MaybeObject* added_elements = set_elements_transition_map(new_map);
5161 if (added_elements->IsFailure()) return added_elements; 4954 if (added_elements->IsFailure()) return added_elements;
5162 4955
5163 new_map->SetBackPointer(this); 4956 new_map->SetBackPointer(this);
5164 } 4957 }
5165 4958
5166 return new_map; 4959 return new_map;
5167 } 4960 }
5168 4961
5169 4962
5170 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { 4963 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
5171 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); 4964 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
5172 4965
5173 // 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
5174 // array describing these properties. 4967 // array describing these properties.
5175 ASSERT(constructor()->IsJSFunction()); 4968 ASSERT(constructor()->IsJSFunction());
5176 JSFunction* ctor = JSFunction::cast(constructor()); 4969 JSFunction* ctor = JSFunction::cast(constructor());
5177 Map* map = ctor->initial_map(); 4970 Map* map = ctor->initial_map();
5178 DescriptorArray* descriptors = map->instance_descriptors(); 4971 DescriptorArray* descriptors = map->instance_descriptors();
5179 4972
5180 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 4973 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
5181 DescriptorArray* new_descriptors;
5182 MaybeObject* maybe_descriptors =
5183 descriptors->CopyUpTo(number_of_own_descriptors);
5184 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5185
5186 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5187 } 4974 }
5188 4975
5189 4976
5190 MaybeObject* Map::Copy() { 4977 MaybeObject* Map::Copy() {
5191 DescriptorArray* descriptors = instance_descriptors(); 4978 DescriptorArray* descriptors = instance_descriptors();
5192 DescriptorArray* new_descriptors; 4979 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
5193 int number_of_own_descriptors = NumberOfOwnDescriptors();
5194 MaybeObject* maybe_descriptors =
5195 descriptors->CopyUpTo(number_of_own_descriptors);
5196 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5197
5198 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5199 } 4980 }
5200 4981
5201 4982
5202 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 4983 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
5203 TransitionFlag flag) { 4984 TransitionFlag flag) {
5204 DescriptorArray* descriptors = instance_descriptors(); 4985 DescriptorArray* descriptors = instance_descriptors();
5205 4986
5206 // Ensure the key is a symbol. 4987 // Ensure the key is a symbol.
5207 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 4988 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5208 if (maybe_failure->IsFailure()) return maybe_failure; 4989 if (maybe_failure->IsFailure()) return maybe_failure;
5209 4990
5210 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();
5211 int new_size = old_size + 1; 4995 int new_size = old_size + 1;
5212 descriptor->SetEnumerationIndex(new_size);
5213
5214 if (flag == INSERT_TRANSITION &&
5215 owns_descriptors() &&
5216 CanHaveMoreTransitions()) {
5217 return ShareDescriptor(descriptor);
5218 }
5219 4996
5220 DescriptorArray* new_descriptors; 4997 DescriptorArray* new_descriptors;
5221 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1); 4998 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
5222 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 4999 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5223 5000
5224 DescriptorArray::WhitenessWitness witness(new_descriptors); 5001 FixedArray::WhitenessWitness witness(new_descriptors);
5225 5002
5226 // Copy the descriptors, inserting a descriptor. 5003 // Copy the descriptors, inserting a descriptor.
5227 for (int i = 0; i < old_size; ++i) { 5004 for (int i = 0; i < old_size; ++i) {
5228 new_descriptors->CopyFrom(i, descriptors, i, witness); 5005 new_descriptors->CopyFrom(i, descriptors, i, witness);
5229 } 5006 }
5230 5007
5231 if (old_size != descriptors->number_of_descriptors()) { 5008 new_descriptors->Append(descriptor, witness, old_size);
5232 new_descriptors->SetNumberOfDescriptors(new_size);
5233 new_descriptors->Set(old_size, descriptor, witness);
5234 new_descriptors->Sort();
5235 } else {
5236 new_descriptors->Append(descriptor, witness);
5237 }
5238 5009
5239 String* key = descriptor->GetKey(); 5010 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5240 int insertion_index = new_descriptors->number_of_descriptors() - 1;
5241 5011
5242 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); 5012 return CopyReplaceDescriptors(new_descriptors, key, flag);
5243 } 5013 }
5244 5014
5245 5015
5246 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, 5016 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
5247 TransitionFlag flag) { 5017 TransitionFlag flag) {
5248 DescriptorArray* old_descriptors = instance_descriptors(); 5018 DescriptorArray* old_descriptors = instance_descriptors();
5249 5019
5250 // Ensure the key is a symbol. 5020 // Ensure the key is a symbol.
5251 MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5021 MaybeObject* maybe_result = descriptor->KeyToSymbol();
5252 if (maybe_result->IsFailure()) return maybe_result; 5022 if (maybe_result->IsFailure()) return maybe_result;
5253 5023
5254 // We replace the key if it is already present. 5024 // We replace the key if it is already present.
5255 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); 5025 int index = old_descriptors->SearchWithCache(descriptor->GetKey());
5256 if (index != DescriptorArray::kNotFound) { 5026 if (index != DescriptorArray::kNotFound) {
5257 return CopyReplaceDescriptor(descriptor, index, flag); 5027 return CopyReplaceDescriptor(descriptor, index, flag);
5258 } 5028 }
5259 return CopyAddDescriptor(descriptor, flag); 5029 return CopyAddDescriptor(descriptor, flag);
5260 } 5030 }
5261 5031
5262 5032
5263 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
5264 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
5265
5266 int size = enumeration_index;
5267
5268 DescriptorArray* descriptors;
5269 MaybeObject* maybe_descriptors = Allocate(size);
5270 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
5271 DescriptorArray::WhitenessWitness witness(descriptors);
5272
5273 for (int i = 0; i < size; ++i) {
5274 descriptors->CopyFrom(i, this, i, witness);
5275 }
5276
5277 if (number_of_descriptors() != enumeration_index) descriptors->Sort();
5278
5279 return descriptors;
5280 }
5281
5282
5283 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, 5033 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
5284 int insertion_index, 5034 int insertion_index,
5285 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
5286 // Ensure the key is a symbol. 5040 // Ensure the key is a symbol.
5287 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 5041 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5288 if (maybe_failure->IsFailure()) return maybe_failure; 5042 if (maybe_failure->IsFailure()) return maybe_failure;
5289 5043
5290 DescriptorArray* descriptors = instance_descriptors();
5291
5292 String* key = descriptor->GetKey(); 5044 String* key = descriptor->GetKey();
5293 ASSERT(key == descriptors->GetKey(insertion_index)); 5045 ASSERT(key == descriptors->GetKey(insertion_index));
5294 5046
5295 int new_size = NumberOfOwnDescriptors(); 5047 DescriptorArray* new_descriptors;
5296 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;
5297 5050
5298 PropertyDetails details = descriptors->GetDetails(insertion_index); 5051 FixedArray::WhitenessWitness witness(new_descriptors);
5299 ASSERT_LE(details.descriptor_index(), new_size);
5300 descriptor->SetEnumerationIndex(details.descriptor_index());
5301 5052
5302 DescriptorArray* new_descriptors; 5053 // Copy the descriptors, replacing a descriptor.
5303 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size); 5054 for (int index = 0; index < size; ++index) {
5304 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5055 if (index == insertion_index) continue;
5305 DescriptorArray::WhitenessWitness witness(new_descriptors); 5056 new_descriptors->CopyFrom(index, descriptors, index, witness);
5306
5307 for (int i = 0; i < new_size; ++i) {
5308 if (i == insertion_index) {
5309 new_descriptors->Set(i, descriptor, witness);
5310 } else {
5311 new_descriptors->CopyFrom(i, descriptors, i, witness);
5312 }
5313 } 5057 }
5314 5058
5315 // Re-sort if descriptors were removed. 5059 PropertyDetails original_details = descriptors->GetDetails(insertion_index);
5316 if (new_size != descriptors->length()) new_descriptors->Sort(); 5060 descriptor->SetEnumerationIndex(original_details.descriptor_index());
5061 descriptor->SetSortedKey(original_details.pointer());
5317 5062
5318 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); 5063 new_descriptors->Set(insertion_index, descriptor, witness);
5064
5065 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5066
5067 return CopyReplaceDescriptors(new_descriptors, key, flag);
5319 } 5068 }
5320 5069
5321 5070
5322 void Map::UpdateCodeCache(Handle<Map> map, 5071 void Map::UpdateCodeCache(Handle<Map> map,
5323 Handle<String> name, 5072 Handle<String> name,
5324 Handle<Code> code) { 5073 Handle<Code> code) {
5325 Isolate* isolate = map->GetIsolate(); 5074 Isolate* isolate = map->GetIsolate();
5326 CALL_HEAP_FUNCTION_VOID(isolate, 5075 CALL_HEAP_FUNCTION_VOID(isolate,
5327 map->UpdateCodeCache(*name, *code)); 5076 map->UpdateCodeCache(*name, *code));
5328 } 5077 }
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after
6083 bool FixedArray::IsEqualTo(FixedArray* other) { 5832 bool FixedArray::IsEqualTo(FixedArray* other) {
6084 if (length() != other->length()) return false; 5833 if (length() != other->length()) return false;
6085 for (int i = 0 ; i < length(); ++i) { 5834 for (int i = 0 ; i < length(); ++i) {
6086 if (get(i) != other->get(i)) return false; 5835 if (get(i) != other->get(i)) return false;
6087 } 5836 }
6088 return true; 5837 return true;
6089 } 5838 }
6090 #endif 5839 #endif
6091 5840
6092 5841
6093 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) { 5842 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
6094 Heap* heap = Isolate::Current()->heap(); 5843 Heap* heap = Isolate::Current()->heap();
6095 // Do not use DescriptorArray::cast on incomplete object. 5844 // Do not use DescriptorArray::cast on incomplete object.
6096 int size = number_of_descriptors + slack;
6097 if (size == 0) return heap->empty_descriptor_array();
6098 FixedArray* result; 5845 FixedArray* result;
5846 if (number_of_descriptors == 0) return heap->empty_descriptor_array();
6099 // Allocate the array of keys. 5847 // Allocate the array of keys.
6100 MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size)); 5848 MaybeObject* maybe_array =
5849 heap->AllocateFixedArray(LengthFor(number_of_descriptors));
6101 if (!maybe_array->To(&result)) return maybe_array; 5850 if (!maybe_array->To(&result)) return maybe_array;
6102 5851
6103 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
6104 result->set(kEnumCacheIndex, Smi::FromInt(0)); 5852 result->set(kEnumCacheIndex, Smi::FromInt(0));
6105 return result; 5853 return result;
6106 } 5854 }
6107 5855
6108 5856
6109 void DescriptorArray::ClearEnumCache() {
6110 set(kEnumCacheIndex, Smi::FromInt(0));
6111 }
6112
6113
6114 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 5857 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
6115 FixedArray* new_cache, 5858 FixedArray* new_cache,
6116 Object* new_index_cache) { 5859 Object* new_index_cache) {
6117 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 5860 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
6118 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 5861 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
6119 if (HasEnumCache()) { 5862 if (HasEnumCache()) {
6120 ASSERT(new_cache->length() > GetEnumCache()->length());
6121 FixedArray::cast(get(kEnumCacheIndex))-> 5863 FixedArray::cast(get(kEnumCacheIndex))->
6122 set(kEnumCacheBridgeCacheIndex, new_cache); 5864 set(kEnumCacheBridgeCacheIndex, new_cache);
6123 FixedArray::cast(get(kEnumCacheIndex))-> 5865 FixedArray::cast(get(kEnumCacheIndex))->
6124 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 5866 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
6125 } else { 5867 } else {
6126 ASSERT(!IsEmpty()); 5868 if (IsEmpty()) return; // Do nothing for empty descriptor array.
6127 FixedArray::cast(bridge_storage)-> 5869 FixedArray::cast(bridge_storage)->
6128 set(kEnumCacheBridgeCacheIndex, new_cache); 5870 set(kEnumCacheBridgeCacheIndex, new_cache);
6129 FixedArray::cast(bridge_storage)-> 5871 FixedArray::cast(bridge_storage)->
6130 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 5872 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
6131 set(kEnumCacheIndex, bridge_storage); 5873 set(kEnumCacheIndex, bridge_storage);
6132 } 5874 }
6133 } 5875 }
6134 5876
6135 5877
6136 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
6192 if (right_child_hash > child_hash) { 5934 if (right_child_hash > child_hash) {
6193 child_index++; 5935 child_index++;
6194 child_hash = right_child_hash; 5936 child_hash = right_child_hash;
6195 } 5937 }
6196 } 5938 }
6197 if (child_hash <= parent_hash) break; 5939 if (child_hash <= parent_hash) break;
6198 SwapSortedKeys(parent_index, child_index); 5940 SwapSortedKeys(parent_index, child_index);
6199 parent_index = child_index; 5941 parent_index = child_index;
6200 } 5942 }
6201 } 5943 }
6202 ASSERT(IsSortedNoDuplicates());
6203 } 5944 }
6204 5945
6205 5946
6206 MaybeObject* AccessorPair::Copy() { 5947 MaybeObject* AccessorPair::Copy() {
6207 Heap* heap = GetHeap(); 5948 Heap* heap = GetHeap();
6208 AccessorPair* copy; 5949 AccessorPair* copy;
6209 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); 5950 MaybeObject* maybe_copy = heap->AllocateAccessorPair();
6210 if (!maybe_copy->To(&copy)) return maybe_copy; 5951 if (!maybe_copy->To(&copy)) return maybe_copy;
6211 5952
6212 copy->set_getter(getter()); 5953 copy->set_getter(getter());
(...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after
7383 7124
7384 void StringHasher::AddSurrogatePairNoIndex(uc32 c) { 7125 void StringHasher::AddSurrogatePairNoIndex(uc32 c) {
7385 uint16_t lead = unibrow::Utf16::LeadSurrogate(c); 7126 uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7386 AddCharacterNoIndex(lead); 7127 AddCharacterNoIndex(lead);
7387 uint16_t trail = unibrow::Utf16::TrailSurrogate(c); 7128 uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7388 AddCharacterNoIndex(trail); 7129 AddCharacterNoIndex(trail);
7389 } 7130 }
7390 7131
7391 7132
7392 uint32_t StringHasher::GetHashField() { 7133 uint32_t StringHasher::GetHashField() {
7134 ASSERT(is_valid());
7393 if (length_ <= String::kMaxHashCalcLength) { 7135 if (length_ <= String::kMaxHashCalcLength) {
7394 if (is_array_index()) { 7136 if (is_array_index()) {
7395 return MakeArrayIndexHash(array_index(), length_); 7137 return MakeArrayIndexHash(array_index(), length_);
7396 } 7138 }
7397 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask; 7139 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
7398 } else { 7140 } else {
7399 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; 7141 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7400 } 7142 }
7401 } 7143 }
7402 7144
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
7439 void String::PrintOn(FILE* file) { 7181 void String::PrintOn(FILE* file) {
7440 int length = this->length(); 7182 int length = this->length();
7441 for (int i = 0; i < length; i++) { 7183 for (int i = 0; i < length; i++) {
7442 fprintf(file, "%c", Get(i)); 7184 fprintf(file, "%c", Get(i));
7443 } 7185 }
7444 } 7186 }
7445 7187
7446 7188
7447 // 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.
7448 // 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.
7449 static bool ClearBackPointer(Heap* heap, Map* target) { 7191 static bool ClearBackPointer(Heap* heap, Object* target) {
7450 if (Marking::MarkBitFrom(target).Get()) return false; 7192 ASSERT(target->IsMap());
7451 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);
7452 return true; 7196 return true;
7453 } 7197 }
7454 7198
7455 7199
7456 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
7457 int live_enum = map->EnumLength();
7458 if (live_enum == Map::kInvalidEnumCache) {
7459 live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
7460 }
7461 if (live_enum == 0) return descriptors->ClearEnumCache();
7462
7463 FixedArray* enum_cache = descriptors->GetEnumCache();
7464
7465 int to_trim = enum_cache->length() - live_enum;
7466 if (to_trim <= 0) return;
7467 RightTrimFixedArray<FROM_GC>(heap, descriptors->GetEnumCache(), to_trim);
7468
7469 if (!descriptors->HasEnumIndicesCache()) return;
7470 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
7471 RightTrimFixedArray<FROM_GC>(heap, enum_indices_cache, to_trim);
7472 }
7473
7474
7475 static void TrimDescriptorArray(Heap* heap,
7476 Map* map,
7477 DescriptorArray* descriptors,
7478 int number_of_own_descriptors) {
7479 int number_of_descriptors = descriptors->number_of_descriptors();
7480 int to_trim = number_of_descriptors - number_of_own_descriptors;
7481 if (to_trim <= 0) return;
7482
7483 // Maximally keep 50% of unused descriptors.
7484 int keep = Min(to_trim, number_of_own_descriptors / 2);
7485 for (int i = number_of_own_descriptors;
7486 i < number_of_own_descriptors + keep;
7487 ++i) {
7488 descriptors->EraseDescriptor(heap, i);
7489 }
7490
7491 if (to_trim > keep) {
7492 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep);
7493 }
7494 descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
7495
7496 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
7497 descriptors->Sort();
7498 }
7499
7500
7501 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, 7200 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
7502 // 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
7503 // depending on the transitions layout in the GC anyways. 7202 // depending on the transitions layout in the GC anyways.
7504 void Map::ClearNonLiveTransitions(Heap* heap) { 7203 void Map::ClearNonLiveTransitions(Heap* heap) {
7505 // If there are no transitions to be cleared, return. 7204 // If there are no transitions to be cleared, return.
7506 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7205 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7507 // properly cleared. 7206 // properly cleared.
7508 if (!HasTransitionArray()) return; 7207 if (!HasTransitionArray()) return;
7509 7208
7510 TransitionArray* t = transitions(); 7209 TransitionArray* t = transitions();
7511 MarkCompactCollector* collector = heap->mark_compact_collector(); 7210 MarkCompactCollector* collector = heap->mark_compact_collector();
7512 7211
7513 int transition_index = 0; 7212 int transition_index = 0;
7514 7213
7515 DescriptorArray* descriptors = t->descriptors();
7516 bool descriptors_owner_died = false;
7517
7518 // Compact all live descriptors to the left. 7214 // Compact all live descriptors to the left.
7519 for (int i = 0; i < t->number_of_transitions(); ++i) { 7215 for (int i = 0; i < t->number_of_transitions(); ++i) {
7520 Map* target = t->GetTarget(i); 7216 if (!ClearBackPointer(heap, t->GetTarget(i))) {
7521 if (ClearBackPointer(heap, target)) {
7522 ASSERT(!Marking::IsGrey(Marking::MarkBitFrom(target)));
7523 DescriptorArray* target_descriptors = target->instance_descriptors();
7524 if ((target_descriptors->number_of_descriptors() == 0 &&
7525 target->NumberOfOwnDescriptors() > 0) ||
7526 target_descriptors == descriptors) {
7527 descriptors_owner_died = true;
7528 }
7529 } else {
7530 if (i != transition_index) { 7217 if (i != transition_index) {
7531 String* key = t->GetKey(i); 7218 String* key = t->GetKey(i);
7532 t->SetKey(transition_index, key); 7219 t->SetKey(transition_index, key);
7533 Object** key_slot = t->GetKeySlot(transition_index); 7220 Object** key_slot = t->GetKeySlot(transition_index);
7534 collector->RecordSlot(key_slot, key_slot, key); 7221 collector->RecordSlot(key_slot, key_slot, key);
7535 // 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.
7536 t->SetTarget(transition_index, t->GetTarget(i)); 7223 t->SetTarget(transition_index, t->GetTarget(i));
7537 } 7224 }
7538 transition_index++; 7225 transition_index++;
7539 } 7226 }
7540 } 7227 }
7541 7228
7542 if (t->HasElementsTransition() && 7229 if (t->HasElementsTransition() &&
7543 ClearBackPointer(heap, t->elements_transition())) { 7230 ClearBackPointer(heap, t->elements_transition())) {
7544 if (t->elements_transition()->instance_descriptors() == descriptors) {
7545 descriptors_owner_died = true;
7546 }
7547 t->ClearElementsTransition(); 7231 t->ClearElementsTransition();
7548 } else { 7232 } else {
7549 // If there are no transitions to be cleared, return. 7233 // If there are no transitions to be cleared, return.
7550 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7234 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7551 // properly cleared. 7235 // properly cleared.
7552 if (transition_index == t->number_of_transitions()) return; 7236 if (transition_index == t->number_of_transitions()) return;
7553 } 7237 }
7554 7238
7555 int number_of_own_descriptors = NumberOfOwnDescriptors();
7556
7557 if (descriptors_owner_died) {
7558 if (number_of_own_descriptors > 0) {
7559 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
7560 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
7561 } else {
7562 t->set_descriptors(heap->empty_descriptor_array());
7563 }
7564 set_owns_descriptors(true);
7565 }
7566
7567 // 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
7568 // the transition array from the map. 7240 // the transition array from the map.
7569 if (transition_index == 0 && 7241 if (transition_index == 0 &&
7570 !t->HasElementsTransition() && 7242 !t->HasElementsTransition() &&
7571 !t->HasPrototypeTransitions() && 7243 !t->HasPrototypeTransitions() &&
7572 number_of_own_descriptors == 0) { 7244 t->descriptors()->IsEmpty()) {
7573 ASSERT(owns_descriptors());
7574 return ClearTransitions(heap); 7245 return ClearTransitions(heap);
7575 } 7246 }
7576 7247
7577 int trim = t->number_of_transitions() - transition_index; 7248 int trim = t->number_of_transitions() - transition_index;
7578 if (trim > 0) { 7249 if (trim > 0) {
7579 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() 7250 RightTrimFixedArray<FROM_GC>(
7580 ? trim : trim * TransitionArray::kTransitionSize); 7251 heap, t, trim * TransitionArray::kTransitionSize);
7581 } 7252 }
7582 } 7253 }
7583 7254
7584 7255
7585 int Map::Hash() { 7256 int Map::Hash() {
7586 // For performance reasons we only hash the 3 most variable fields of a map: 7257 // For performance reasons we only hash the 3 most variable fields of a map:
7587 // constructor, prototype and bit_field2. 7258 // constructor, prototype and bit_field2.
7588 7259
7589 // Shift away the tag. 7260 // Shift away the tag.
7590 int hash = (static_cast<uint32_t>( 7261 int hash = (static_cast<uint32_t>(
(...skipping 2926 matching lines...) Expand 10 before | Expand all | Expand 10 after
10517 ASSERT(map()->has_indexed_interceptor()); 10188 ASSERT(map()->has_indexed_interceptor());
10518 JSFunction* constructor = JSFunction::cast(map()->constructor()); 10189 JSFunction* constructor = JSFunction::cast(map()->constructor());
10519 ASSERT(constructor->shared()->IsApiFunction()); 10190 ASSERT(constructor->shared()->IsApiFunction());
10520 Object* result = 10191 Object* result =
10521 constructor->shared()->get_api_func_data()->indexed_property_handler(); 10192 constructor->shared()->get_api_func_data()->indexed_property_handler();
10522 return InterceptorInfo::cast(result); 10193 return InterceptorInfo::cast(result);
10523 } 10194 }
10524 10195
10525 10196
10526 MaybeObject* JSObject::GetPropertyPostInterceptor( 10197 MaybeObject* JSObject::GetPropertyPostInterceptor(
10527 Object* receiver, 10198 JSReceiver* receiver,
10528 String* name, 10199 String* name,
10529 PropertyAttributes* attributes) { 10200 PropertyAttributes* attributes) {
10530 // Check local property in holder, ignore interceptor. 10201 // Check local property in holder, ignore interceptor.
10531 LookupResult result(GetIsolate()); 10202 LookupResult result(GetIsolate());
10532 LocalLookupRealNamedProperty(name, &result); 10203 LocalLookupRealNamedProperty(name, &result);
10533 if (result.IsFound()) { 10204 if (result.IsFound()) {
10534 return GetProperty(receiver, &result, name, attributes); 10205 return GetProperty(receiver, &result, name, attributes);
10535 } 10206 }
10536 // Continue searching via the prototype chain. 10207 // Continue searching via the prototype chain.
10537 Object* pt = GetPrototype(); 10208 Object* pt = GetPrototype();
10538 *attributes = ABSENT; 10209 *attributes = ABSENT;
10539 if (pt->IsNull()) return GetHeap()->undefined_value(); 10210 if (pt->IsNull()) return GetHeap()->undefined_value();
10540 return pt->GetPropertyWithReceiver(receiver, name, attributes); 10211 return pt->GetPropertyWithReceiver(receiver, name, attributes);
10541 } 10212 }
10542 10213
10543 10214
10544 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( 10215 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
10545 Object* receiver, 10216 JSReceiver* receiver,
10546 String* name, 10217 String* name,
10547 PropertyAttributes* attributes) { 10218 PropertyAttributes* attributes) {
10548 // Check local property in holder, ignore interceptor. 10219 // Check local property in holder, ignore interceptor.
10549 LookupResult result(GetIsolate()); 10220 LookupResult result(GetIsolate());
10550 LocalLookupRealNamedProperty(name, &result); 10221 LocalLookupRealNamedProperty(name, &result);
10551 if (result.IsFound()) { 10222 if (result.IsFound()) {
10552 return GetProperty(receiver, &result, name, attributes); 10223 return GetProperty(receiver, &result, name, attributes);
10553 } 10224 }
10554 return GetHeap()->undefined_value(); 10225 return GetHeap()->undefined_value();
10555 } 10226 }
10556 10227
10557 10228
10558 MaybeObject* JSObject::GetPropertyWithInterceptor( 10229 MaybeObject* JSObject::GetPropertyWithInterceptor(
10559 Object* receiver, 10230 JSReceiver* receiver,
10560 String* name, 10231 String* name,
10561 PropertyAttributes* attributes) { 10232 PropertyAttributes* attributes) {
10562 Isolate* isolate = GetIsolate(); 10233 Isolate* isolate = GetIsolate();
10563 InterceptorInfo* interceptor = GetNamedInterceptor(); 10234 InterceptorInfo* interceptor = GetNamedInterceptor();
10564 HandleScope scope(isolate); 10235 HandleScope scope(isolate);
10565 Handle<Object> receiver_handle(receiver); 10236 Handle<JSReceiver> receiver_handle(receiver);
10566 Handle<JSObject> holder_handle(this); 10237 Handle<JSObject> holder_handle(this);
10567 Handle<String> name_handle(name); 10238 Handle<String> name_handle(name);
10568 10239
10569 if (!interceptor->getter()->IsUndefined()) { 10240 if (!interceptor->getter()->IsUndefined()) {
10570 v8::NamedPropertyGetter getter = 10241 v8::NamedPropertyGetter getter =
10571 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); 10242 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
10572 LOG(isolate, 10243 LOG(isolate,
10573 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); 10244 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
10574 CustomArguments args(isolate, interceptor->data(), receiver, this); 10245 CustomArguments args(isolate, interceptor->data(), receiver, this);
10575 v8::AccessorInfo info(args.end()); 10246 v8::AccessorInfo info(args.end());
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
10687 } 10358 }
10688 } 10359 }
10689 10360
10690 LookupResult result(isolate); 10361 LookupResult result(isolate);
10691 LocalLookupRealNamedProperty(key, &result); 10362 LocalLookupRealNamedProperty(key, &result);
10692 return result.IsPropertyCallbacks(); 10363 return result.IsPropertyCallbacks();
10693 } 10364 }
10694 10365
10695 10366
10696 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { 10367 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10697 if (HasFastProperties()) { 10368 return HasFastProperties() ?
10698 Map* map = this->map(); 10369 map()->NumberOfDescribedProperties(filter) :
10699 if (filter == NONE) return map->NumberOfOwnDescriptors(); 10370 property_dictionary()->NumberOfElementsFilterAttributes(filter);
10700 if (filter == DONT_ENUM) {
10701 int result = map->EnumLength();
10702 if (result != Map::kInvalidEnumCache) return result;
10703 }
10704 return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
10705 }
10706 return property_dictionary()->NumberOfElementsFilterAttributes(filter);
10707 } 10371 }
10708 10372
10709 10373
10710 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { 10374 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10711 Object* temp = get(i); 10375 Object* temp = get(i);
10712 set(i, get(j)); 10376 set(i, get(j));
10713 set(j, temp); 10377 set(j, temp);
10714 if (this != numbers) { 10378 if (this != numbers) {
10715 temp = numbers->get(i); 10379 temp = numbers->get(i);
10716 numbers->set(i, Smi::cast(numbers->get(j))); 10380 numbers->set(i, Smi::cast(numbers->get(j)));
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
10819 } 10483 }
10820 } 10484 }
10821 10485
10822 10486
10823 // 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
10824 // 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
10825 // mirrors. 10489 // mirrors.
10826 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { 10490 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10827 ASSERT(storage->length() >= (NumberOfLocalProperties() - index)); 10491 ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10828 if (HasFastProperties()) { 10492 if (HasFastProperties()) {
10829 int real_size = map()->NumberOfOwnDescriptors();
10830 DescriptorArray* descs = map()->instance_descriptors(); 10493 DescriptorArray* descs = map()->instance_descriptors();
10831 ASSERT(storage->length() >= index + real_size); 10494 ASSERT(storage->length() >= index + descs->number_of_descriptors());
10832 for (int i = 0; i < real_size; i++) { 10495 for (int i = 0; i < descs->number_of_descriptors(); i++) {
10833 storage->set(index + i, descs->GetKey(i)); 10496 storage->set(index + i, descs->GetKey(i));
10834 } 10497 }
10835 } else { 10498 } else {
10836 property_dictionary()->CopyKeysTo(storage, 10499 property_dictionary()->CopyKeysTo(storage,
10837 index, 10500 index,
10838 StringDictionary::UNSORTED); 10501 StringDictionary::UNSORTED);
10839 } 10502 }
10840 } 10503 }
10841 10504
10842 10505
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after
12525 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); 12188 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12526 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 12189 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12527 } 12190 }
12528 FixedArray* enumeration_order = FixedArray::cast(obj); 12191 FixedArray* enumeration_order = FixedArray::cast(obj);
12529 12192
12530 // Fill the enumeration order array with property details. 12193 // Fill the enumeration order array with property details.
12531 int capacity = HashTable<Shape, Key>::Capacity(); 12194 int capacity = HashTable<Shape, Key>::Capacity();
12532 int pos = 0; 12195 int pos = 0;
12533 for (int i = 0; i < capacity; i++) { 12196 for (int i = 0; i < capacity; i++) {
12534 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { 12197 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12535 int index = DetailsAt(i).dictionary_index(); 12198 enumeration_order->set(
12536 enumeration_order->set(pos++, Smi::FromInt(index)); 12199 pos++, Smi::FromInt(DetailsAt(i).dictionary_index()));
12537 } 12200 }
12538 } 12201 }
12539 12202
12540 // Sort the arrays wrt. enumeration order. 12203 // Sort the arrays wrt. enumeration order.
12541 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); 12204 iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12542 12205
12543 // Overwrite the enumeration_order with the enumeration indices. 12206 // Overwrite the enumeration_order with the enumeration indices.
12544 for (int i = 0; i < length; i++) { 12207 for (int i = 0; i < length; i++) {
12545 int index = Smi::cast(iteration_order->get(i))->value(); 12208 int index = Smi::cast(iteration_order->get(i))->value();
12546 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
12655 uint32_t hash) { 12318 uint32_t hash) {
12656 // Compute the key object. 12319 // Compute the key object.
12657 Object* k; 12320 Object* k;
12658 { MaybeObject* maybe_k = Shape::AsObject(key); 12321 { MaybeObject* maybe_k = Shape::AsObject(key);
12659 if (!maybe_k->ToObject(&k)) return maybe_k; 12322 if (!maybe_k->ToObject(&k)) return maybe_k;
12660 } 12323 }
12661 12324
12662 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); 12325 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12663 // Insert element at empty or deleted entry 12326 // Insert element at empty or deleted entry
12664 if (!details.IsDeleted() && 12327 if (!details.IsDeleted() &&
12665 details.dictionary_index() == 0 && 12328 details.dictionary_index() == 0 && Shape::kIsEnumerable) {
12666 Shape::kIsEnumerable) {
12667 // Assign an enumeration index to the property and update 12329 // Assign an enumeration index to the property and update
12668 // SetNextEnumerationIndex. 12330 // SetNextEnumerationIndex.
12669 int index = NextEnumerationIndex(); 12331 int index = NextEnumerationIndex();
12670 details = PropertyDetails(details.attributes(), details.type(), index); 12332 details = PropertyDetails(details.attributes(), details.type(), index);
12671 SetNextEnumerationIndex(index + 1); 12333 SetNextEnumerationIndex(index + 1);
12672 } 12334 }
12673 SetEntry(entry, k, value, details); 12335 SetEntry(entry, k, value, details);
12674 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() 12336 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12675 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); 12337 || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12676 HashTable<Shape, Key>::ElementAdded(); 12338 HashTable<Shape, Key>::ElementAdded();
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
12962 } 12624 }
12963 12625
12964 // Allocate the instance descriptor. 12626 // Allocate the instance descriptor.
12965 DescriptorArray* descriptors; 12627 DescriptorArray* descriptors;
12966 MaybeObject* maybe_descriptors = 12628 MaybeObject* maybe_descriptors =
12967 DescriptorArray::Allocate(instance_descriptor_length); 12629 DescriptorArray::Allocate(instance_descriptor_length);
12968 if (!maybe_descriptors->To(&descriptors)) { 12630 if (!maybe_descriptors->To(&descriptors)) {
12969 return maybe_descriptors; 12631 return maybe_descriptors;
12970 } 12632 }
12971 12633
12972 DescriptorArray::WhitenessWitness witness(descriptors); 12634 FixedArray::WhitenessWitness witness(descriptors);
12973 12635
12974 int number_of_allocated_fields = 12636 int number_of_allocated_fields =
12975 number_of_fields + unused_property_fields - inobject_props; 12637 number_of_fields + unused_property_fields - inobject_props;
12976 if (number_of_allocated_fields < 0) { 12638 if (number_of_allocated_fields < 0) {
12977 // There is enough inobject space for all fields (including unused). 12639 // There is enough inobject space for all fields (including unused).
12978 number_of_allocated_fields = 0; 12640 number_of_allocated_fields = 0;
12979 unused_property_fields = inobject_props - number_of_fields; 12641 unused_property_fields = inobject_props - number_of_fields;
12980 } 12642 }
12981 12643
12982 // Allocate the fixed array for the fields. 12644 // Allocate the fixed array for the fields.
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
13550 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13212 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13551 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13213 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13552 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13214 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13553 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13215 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13554 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13216 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13555 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13217 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13556 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13218 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13557 } 13219 }
13558 13220
13559 } } // 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