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

Side by Side Diff: src/objects.cc

Issue 6685073: Remember and reuse derived map for external arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback Created 9 years, 9 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-inl.h » ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 // Allocate new instance descriptors with (name, index) added 1275 // Allocate new instance descriptors with (name, index) added
1276 FieldDescriptor new_field(name, index, attributes); 1276 FieldDescriptor new_field(name, index, attributes);
1277 Object* new_descriptors; 1277 Object* new_descriptors;
1278 { MaybeObject* maybe_new_descriptors = 1278 { MaybeObject* maybe_new_descriptors =
1279 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); 1279 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
1280 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { 1280 if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1281 return maybe_new_descriptors; 1281 return maybe_new_descriptors;
1282 } 1282 }
1283 } 1283 }
1284 1284
1285 // Only allow map transition if the object's map is NOT equal to the 1285 // Only allow map transition if the object isn't the global object and there
1286 // global object_function's map and there is not a transition for name. 1286 // is not a transition for the name, or there's a transition for the name but
1287 // it's unrelated to properties.
1288 int descriptor_index = old_descriptors->Search(name);
1289
1290 // External array transitions are stored in the descriptor for property "",
1291 // which is not a identifier and should have forced a switch to slow
1292 // properties above.
1293 ASSERT(descriptor_index == DescriptorArray::kNotFound ||
1294 old_descriptors->GetType(descriptor_index) != EXTERNAL_ARRAY_TRANSITION);
1295 bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
1296 old_descriptors->GetType(descriptor_index) == EXTERNAL_ARRAY_TRANSITION;
1287 bool allow_map_transition = 1297 bool allow_map_transition =
1288 !old_descriptors->Contains(name) && 1298 can_insert_transition &&
1289 (isolate->context()->global_context()->object_function()-> 1299 (isolate->context()->global_context()->object_function()->map() != map());
1290 map() != map());
1291 1300
1292 ASSERT(index < map()->inobject_properties() || 1301 ASSERT(index < map()->inobject_properties() ||
1293 (index - map()->inobject_properties()) < properties()->length() || 1302 (index - map()->inobject_properties()) < properties()->length() ||
1294 map()->unused_property_fields() == 0); 1303 map()->unused_property_fields() == 0);
1295 // Allocate a new map for the object. 1304 // Allocate a new map for the object.
1296 Object* r; 1305 Object* r;
1297 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); 1306 { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1298 if (!maybe_r->ToObject(&r)) return maybe_r; 1307 if (!maybe_r->ToObject(&r)) return maybe_r;
1299 } 1308 }
1300 Map* new_map = Map::cast(r); 1309 Map* new_map = Map::cast(r);
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 cache->Update(descriptors, name, number); 1821 cache->Update(descriptors, name, number);
1813 } 1822 }
1814 if (number != DescriptorArray::kNotFound) { 1823 if (number != DescriptorArray::kNotFound) {
1815 result->DescriptorResult(holder, descriptors->GetDetails(number), number); 1824 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
1816 } else { 1825 } else {
1817 result->NotFound(); 1826 result->NotFound();
1818 } 1827 }
1819 } 1828 }
1820 1829
1821 1830
1831 MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
1832 bool safe_to_add_transition) {
1833 DescriptorArray* descriptors = instance_descriptors();
1834 String* external_array_sentinel_name = GetIsolate()->heap()->empty_symbol();
1835
1836 if (safe_to_add_transition) {
1837 // It's only safe to manipulate the descriptor array if it would be
1838 // safe to add a transition.
1839
1840 ASSERT(!is_shared()); // no transitions can be added to shared maps.
1841 // Check if the external array transition already exists.
1842 DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache();
1843 int index = cache->Lookup(descriptors, external_array_sentinel_name);
1844 if (index == DescriptorLookupCache::kAbsent) {
1845 index = descriptors->Search(external_array_sentinel_name);
1846 cache->Update(descriptors,
1847 external_array_sentinel_name,
1848 index);
1849 }
1850
1851 // If the transition already exists, check the type. If there is a match,
1852 // return it.
1853 if (index != DescriptorArray::kNotFound) {
1854 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index)));
1855 if (details.type() == EXTERNAL_ARRAY_TRANSITION &&
1856 details.array_type() == array_type) {
1857 return descriptors->GetValue(index);
1858 } else {
1859 safe_to_add_transition = false;
1860 }
1861 }
1862 }
1863
1864 // No transition to an existing external array map. Make a new one.
1865 Object* obj;
1866 { MaybeObject* maybe_map = CopyDropTransitions();
1867 if (!maybe_map->ToObject(&obj)) return maybe_map;
1868 }
1869 Map* new_map = Map::cast(obj);
1870
1871 new_map->set_has_fast_elements(false);
1872 new_map->set_has_external_array_elements(true);
1873 GetIsolate()->counters()->map_to_external_array_elements()->Increment();
1874
1875 // Only remember the map transition if the object's map is NOT equal to the
1876 // global object_function's map and there is not an already existing
1877 // non-matching external array transition.
1878 bool allow_map_transition =
1879 safe_to_add_transition &&
1880 (GetIsolate()->context()->global_context()->object_function()->map() !=
1881 map());
1882 if (allow_map_transition) {
1883 // Allocate new instance descriptors for the old map with map transition.
1884 ExternalArrayTransitionDescriptor desc(external_array_sentinel_name,
1885 Map::cast(new_map),
1886 array_type);
1887 Object* new_descriptors;
1888 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert(
1889 &desc,
1890 KEEP_TRANSITIONS);
1891 if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1892 return maybe_new_descriptors;
1893 }
1894 descriptors = DescriptorArray::cast(new_descriptors);
1895 set_instance_descriptors(descriptors);
1896 }
1897
1898 return new_map;
1899 }
1900
1901
1822 void JSObject::LocalLookupRealNamedProperty(String* name, 1902 void JSObject::LocalLookupRealNamedProperty(String* name,
1823 LookupResult* result) { 1903 LookupResult* result) {
1824 if (IsJSGlobalProxy()) { 1904 if (IsJSGlobalProxy()) {
1825 Object* proto = GetPrototype(); 1905 Object* proto = GetPrototype();
1826 if (proto->IsNull()) return result->NotFound(); 1906 if (proto->IsNull()) return result->NotFound();
1827 ASSERT(proto->IsJSGlobalObject()); 1907 ASSERT(proto->IsJSGlobalObject());
1828 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); 1908 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
1829 } 1909 }
1830 1910
1831 if (HasFastProperties()) { 1911 if (HasFastProperties()) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 ASSERT(!HEAP->InNewSpace(function)); 2124 ASSERT(!HEAP->InNewSpace(function));
2045 if (value == function) { 2125 if (value == function) {
2046 set_map(target_map); 2126 set_map(target_map);
2047 return value; 2127 return value;
2048 } 2128 }
2049 // Otherwise, replace with a MAP_TRANSITION to a new map with a 2129 // Otherwise, replace with a MAP_TRANSITION to a new map with a
2050 // FIELD, even if the value is a constant function. 2130 // FIELD, even if the value is a constant function.
2051 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2131 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2052 } 2132 }
2053 case NULL_DESCRIPTOR: 2133 case NULL_DESCRIPTOR:
2134 case EXTERNAL_ARRAY_TRANSITION:
2054 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2135 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2055 default: 2136 default:
2056 UNREACHABLE(); 2137 UNREACHABLE();
2057 } 2138 }
2058 UNREACHABLE(); 2139 UNREACHABLE();
2059 return value; 2140 return value;
2060 } 2141 }
2061 2142
2062 2143
2063 // Set a real local property, even if it is READ_ONLY. If the property is not 2144 // Set a real local property, even if it is READ_ONLY. If the property is not
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2123 return ConvertDescriptorToField(name, value, attributes); 2204 return ConvertDescriptorToField(name, value, attributes);
2124 case CALLBACKS: 2205 case CALLBACKS:
2125 case INTERCEPTOR: 2206 case INTERCEPTOR:
2126 // Override callback in clone 2207 // Override callback in clone
2127 return ConvertDescriptorToField(name, value, attributes); 2208 return ConvertDescriptorToField(name, value, attributes);
2128 case CONSTANT_TRANSITION: 2209 case CONSTANT_TRANSITION:
2129 // Replace with a MAP_TRANSITION to a new map with a FIELD, even 2210 // Replace with a MAP_TRANSITION to a new map with a FIELD, even
2130 // if the value is a function. 2211 // if the value is a function.
2131 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2212 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2132 case NULL_DESCRIPTOR: 2213 case NULL_DESCRIPTOR:
2214 case EXTERNAL_ARRAY_TRANSITION:
2133 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2215 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2134 default: 2216 default:
2135 UNREACHABLE(); 2217 UNREACHABLE();
2136 } 2218 }
2137 UNREACHABLE(); 2219 UNREACHABLE();
2138 return value; 2220 return value;
2139 } 2221 }
2140 2222
2141 2223
2142 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 2224 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
(...skipping 3334 matching lines...) Expand 10 before | Expand all | Expand 10 after
5477 for (int i = 0; i < length; i++) { 5559 for (int i = 0; i < length; i++) {
5478 fprintf(file, "%c", Get(i)); 5560 fprintf(file, "%c", Get(i));
5479 } 5561 }
5480 } 5562 }
5481 5563
5482 5564
5483 void Map::CreateBackPointers() { 5565 void Map::CreateBackPointers() {
5484 DescriptorArray* descriptors = instance_descriptors(); 5566 DescriptorArray* descriptors = instance_descriptors();
5485 for (int i = 0; i < descriptors->number_of_descriptors(); i++) { 5567 for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
5486 if (descriptors->GetType(i) == MAP_TRANSITION || 5568 if (descriptors->GetType(i) == MAP_TRANSITION ||
5569 descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION ||
5487 descriptors->GetType(i) == CONSTANT_TRANSITION) { 5570 descriptors->GetType(i) == CONSTANT_TRANSITION) {
5488 // Get target. 5571 // Get target.
5489 Map* target = Map::cast(descriptors->GetValue(i)); 5572 Map* target = Map::cast(descriptors->GetValue(i));
5490 #ifdef DEBUG 5573 #ifdef DEBUG
5491 // Verify target. 5574 // Verify target.
5492 Object* source_prototype = prototype(); 5575 Object* source_prototype = prototype();
5493 Object* target_prototype = target->prototype(); 5576 Object* target_prototype = target->prototype();
5494 ASSERT(source_prototype->IsJSObject() || 5577 ASSERT(source_prototype->IsJSObject() ||
5495 source_prototype->IsMap() || 5578 source_prototype->IsMap() ||
5496 source_prototype->IsNull()); 5579 source_prototype->IsNull());
(...skipping 22 matching lines...) Expand all
5519 d->get(DescriptorArray::kContentArrayIndex)); 5602 d->get(DescriptorArray::kContentArrayIndex));
5520 ASSERT(contents->length() >= 2); 5603 ASSERT(contents->length() >= 2);
5521 for (int i = 0; i < contents->length(); i += 2) { 5604 for (int i = 0; i < contents->length(); i += 2) {
5522 // If the pair (value, details) is a map transition, 5605 // If the pair (value, details) is a map transition,
5523 // check if the target is live. If not, null the descriptor. 5606 // check if the target is live. If not, null the descriptor.
5524 // Also drop the back pointer for that map transition, so that this 5607 // Also drop the back pointer for that map transition, so that this
5525 // map is not reached again by following a back pointer from a 5608 // map is not reached again by following a back pointer from a
5526 // non-live object. 5609 // non-live object.
5527 PropertyDetails details(Smi::cast(contents->get(i + 1))); 5610 PropertyDetails details(Smi::cast(contents->get(i + 1)));
5528 if (details.type() == MAP_TRANSITION || 5611 if (details.type() == MAP_TRANSITION ||
5612 details.type() == EXTERNAL_ARRAY_TRANSITION ||
5529 details.type() == CONSTANT_TRANSITION) { 5613 details.type() == CONSTANT_TRANSITION) {
5530 Map* target = reinterpret_cast<Map*>(contents->get(i)); 5614 Map* target = reinterpret_cast<Map*>(contents->get(i));
5531 ASSERT(target->IsHeapObject()); 5615 ASSERT(target->IsHeapObject());
5532 if (!target->IsMarked()) { 5616 if (!target->IsMarked()) {
5533 ASSERT(target->IsMap()); 5617 ASSERT(target->IsMap());
5534 contents->set_unchecked(i + 1, NullDescriptorDetails); 5618 contents->set_unchecked(i + 1, NullDescriptorDetails);
5535 contents->set_null_unchecked(heap, i); 5619 contents->set_null_unchecked(heap, i);
5536 ASSERT(target->prototype() == this || 5620 ASSERT(target->prototype() == this ||
5537 target->prototype() == real_prototype); 5621 target->prototype() == real_prototype);
5538 // Getter prototype() is read-only, set_prototype() has side effects. 5622 // Getter prototype() is read-only, set_prototype() has side effects.
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
6392 6476
6393 6477
6394 const char* Code::PropertyType2String(PropertyType type) { 6478 const char* Code::PropertyType2String(PropertyType type) {
6395 switch (type) { 6479 switch (type) {
6396 case NORMAL: return "NORMAL"; 6480 case NORMAL: return "NORMAL";
6397 case FIELD: return "FIELD"; 6481 case FIELD: return "FIELD";
6398 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; 6482 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
6399 case CALLBACKS: return "CALLBACKS"; 6483 case CALLBACKS: return "CALLBACKS";
6400 case INTERCEPTOR: return "INTERCEPTOR"; 6484 case INTERCEPTOR: return "INTERCEPTOR";
6401 case MAP_TRANSITION: return "MAP_TRANSITION"; 6485 case MAP_TRANSITION: return "MAP_TRANSITION";
6486 case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION";
6402 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; 6487 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
6403 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; 6488 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
6404 } 6489 }
6405 UNREACHABLE(); 6490 UNREACHABLE();
6406 return NULL; 6491 return NULL;
6407 } 6492 }
6408 6493
6409 6494
6410 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { 6495 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
6411 const char* name = NULL; 6496 const char* name = NULL;
(...skipping 3748 matching lines...) Expand 10 before | Expand all | Expand 10 after
10160 if (break_point_objects()->IsUndefined()) return 0; 10245 if (break_point_objects()->IsUndefined()) return 0;
10161 // Single beak point. 10246 // Single beak point.
10162 if (!break_point_objects()->IsFixedArray()) return 1; 10247 if (!break_point_objects()->IsFixedArray()) return 1;
10163 // Multiple break points. 10248 // Multiple break points.
10164 return FixedArray::cast(break_point_objects())->length(); 10249 return FixedArray::cast(break_point_objects())->length();
10165 } 10250 }
10166 #endif 10251 #endif
10167 10252
10168 10253
10169 } } // namespace v8::internal 10254 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698