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

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: fix handling of empty property name 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
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(
Mads Ager (chromium) 2011/03/22 18:57:25 Move fist disjunct of the assert to the first line
danno 2011/03/23 09:56:52 Done.
1294 descriptor_index == DescriptorArray::kNotFound ||
1295 old_descriptors->GetType(descriptor_index) != EXTERNAL_ARRAY_TRANSITION);
1296 bool can_insert_transition =
1297 (descriptor_index == DescriptorArray::kNotFound ||
1298 old_descriptors->GetType(descriptor_index) == EXTERNAL_ARRAY_TRANSITION);
1287 bool allow_map_transition = 1299 bool allow_map_transition =
1288 !old_descriptors->Contains(name) && 1300 can_insert_transition &&
1289 (isolate->context()->global_context()->object_function()-> 1301 (isolate->context()->global_context()->object_function()->map() != map());
1290 map() != map());
1291 1302
1292 ASSERT(index < map()->inobject_properties() || 1303 ASSERT(index < map()->inobject_properties() ||
1293 (index - map()->inobject_properties()) < properties()->length() || 1304 (index - map()->inobject_properties()) < properties()->length() ||
1294 map()->unused_property_fields() == 0); 1305 map()->unused_property_fields() == 0);
1295 // Allocate a new map for the object. 1306 // Allocate a new map for the object.
1296 Object* r; 1307 Object* r;
1297 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); 1308 { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1298 if (!maybe_r->ToObject(&r)) return maybe_r; 1309 if (!maybe_r->ToObject(&r)) return maybe_r;
1299 } 1310 }
1300 Map* new_map = Map::cast(r); 1311 Map* new_map = Map::cast(r);
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 cache->Update(descriptors, name, number); 1823 cache->Update(descriptors, name, number);
1813 } 1824 }
1814 if (number != DescriptorArray::kNotFound) { 1825 if (number != DescriptorArray::kNotFound) {
1815 result->DescriptorResult(holder, descriptors->GetDetails(number), number); 1826 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
1816 } else { 1827 } else {
1817 result->NotFound(); 1828 result->NotFound();
1818 } 1829 }
1819 } 1830 }
1820 1831
1821 1832
1833 MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
1834 bool safe_to_add_transition) {
1835 DescriptorArray* descriptors = instance_descriptors();
1836 String* external_array_sentinel_name = HEAP->empty_symbol();
Mads Ager (chromium) 2011/03/22 18:57:25 Let's replace HEAP with GetIsolate()->heap() here
danno 2011/03/23 09:56:52 Done.
1837
1838 if (safe_to_add_transition) {
1839 // It's only safe to manipulate the descriptor array if it would be
1840 // safe to add a transition.
1841
1842 ASSERT(!is_shared()); // no transitions can be added to shared maps.
1843 // Check if the external array transition already exists.
1844 DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache();
1845 int index = cache->Lookup(descriptors, external_array_sentinel_name);
1846 if (index == DescriptorLookupCache::kAbsent) {
1847 index = descriptors->Search(external_array_sentinel_name);
1848 cache->Update(descriptors,
1849 external_array_sentinel_name,
1850 index);
1851 }
1852
1853 // If the transition already exists, check the type. If there is a match,
1854 // return it.
1855 if (index != DescriptorArray::kNotFound) {
1856 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index)));
1857 if (details.type() == EXTERNAL_ARRAY_TRANSITION &&
1858 details.array_type() == array_type) {
1859 return descriptors->GetValue(index);
1860 } else {
1861 safe_to_add_transition = false;
1862 }
1863 }
1864 }
1865
1866 // No transition to an existing external array map. Make a new one.
1867 Object* obj;
1868 { MaybeObject* maybe_map = CopyDropTransitions();
1869 if (!maybe_map->ToObject(&obj)) return maybe_map;
1870 }
1871 Map* new_map = Map::cast(obj);
1872
1873 new_map->set_has_fast_elements(false);
1874 new_map->set_has_external_array_elements(true);
1875 COUNTERS->map_to_external_array_elements()->Increment();
Mads Ager (chromium) 2011/03/22 18:57:25 GetIsolate()->counters() instead of COUNTERS.
danno 2011/03/23 09:56:52 Done.
1876
1877 // Only remember the map transition if the object's map is NOT equal to the
1878 // global object_function's map and there is not an already existing
1879 // non-matching external array transition.
1880 Heap* heap = GetHeap();
1881 bool allow_map_transition =
1882 safe_to_add_transition &&
1883 (heap->isolate()->context()->global_context()->object_function()->map() !=
Mads Ager (chromium) 2011/03/22 18:57:25 Instead of getting the heap and using heap->isolat
danno 2011/03/23 09:56:52 Done.
1884 map());
1885 if (allow_map_transition) {
1886 // Allocate new instance descriptors for the old map with map transition.
1887 ExternalArrayTransitionDescriptor desc(external_array_sentinel_name,
1888 Map::cast(new_map),
1889 array_type);
1890 Object* new_descriptors;
1891 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert(
1892 &desc,
1893 KEEP_TRANSITIONS);
1894 if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1895 return maybe_new_descriptors;
1896 }
1897 descriptors = DescriptorArray::cast(new_descriptors);
1898 set_instance_descriptors(descriptors);
1899 }
1900
1901 return new_map;
1902 }
1903
1904
1822 void JSObject::LocalLookupRealNamedProperty(String* name, 1905 void JSObject::LocalLookupRealNamedProperty(String* name,
1823 LookupResult* result) { 1906 LookupResult* result) {
1824 if (IsJSGlobalProxy()) { 1907 if (IsJSGlobalProxy()) {
1825 Object* proto = GetPrototype(); 1908 Object* proto = GetPrototype();
1826 if (proto->IsNull()) return result->NotFound(); 1909 if (proto->IsNull()) return result->NotFound();
1827 ASSERT(proto->IsJSGlobalObject()); 1910 ASSERT(proto->IsJSGlobalObject());
1828 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); 1911 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
1829 } 1912 }
1830 1913
1831 if (HasFastProperties()) { 1914 if (HasFastProperties()) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 ASSERT(!HEAP->InNewSpace(function)); 2127 ASSERT(!HEAP->InNewSpace(function));
2045 if (value == function) { 2128 if (value == function) {
2046 set_map(target_map); 2129 set_map(target_map);
2047 return value; 2130 return value;
2048 } 2131 }
2049 // Otherwise, replace with a MAP_TRANSITION to a new map with a 2132 // Otherwise, replace with a MAP_TRANSITION to a new map with a
2050 // FIELD, even if the value is a constant function. 2133 // FIELD, even if the value is a constant function.
2051 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2134 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2052 } 2135 }
2053 case NULL_DESCRIPTOR: 2136 case NULL_DESCRIPTOR:
2137 case EXTERNAL_ARRAY_TRANSITION:
2054 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2138 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2055 default: 2139 default:
2056 UNREACHABLE(); 2140 UNREACHABLE();
2057 } 2141 }
2058 UNREACHABLE(); 2142 UNREACHABLE();
2059 return value; 2143 return value;
2060 } 2144 }
2061 2145
2062 2146
2063 // Set a real local property, even if it is READ_ONLY. If the property is not 2147 // 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); 2207 return ConvertDescriptorToField(name, value, attributes);
2124 case CALLBACKS: 2208 case CALLBACKS:
2125 case INTERCEPTOR: 2209 case INTERCEPTOR:
2126 // Override callback in clone 2210 // Override callback in clone
2127 return ConvertDescriptorToField(name, value, attributes); 2211 return ConvertDescriptorToField(name, value, attributes);
2128 case CONSTANT_TRANSITION: 2212 case CONSTANT_TRANSITION:
2129 // Replace with a MAP_TRANSITION to a new map with a FIELD, even 2213 // Replace with a MAP_TRANSITION to a new map with a FIELD, even
2130 // if the value is a function. 2214 // if the value is a function.
2131 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2215 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2132 case NULL_DESCRIPTOR: 2216 case NULL_DESCRIPTOR:
2217 case EXTERNAL_ARRAY_TRANSITION:
2133 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2218 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2134 default: 2219 default:
2135 UNREACHABLE(); 2220 UNREACHABLE();
2136 } 2221 }
2137 UNREACHABLE(); 2222 UNREACHABLE();
2138 return value; 2223 return value;
2139 } 2224 }
2140 2225
2141 2226
2142 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 2227 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
(...skipping 3336 matching lines...) Expand 10 before | Expand all | Expand 10 after
5479 for (int i = 0; i < length; i++) { 5564 for (int i = 0; i < length; i++) {
5480 fprintf(file, "%c", Get(i)); 5565 fprintf(file, "%c", Get(i));
5481 } 5566 }
5482 } 5567 }
5483 5568
5484 5569
5485 void Map::CreateBackPointers() { 5570 void Map::CreateBackPointers() {
5486 DescriptorArray* descriptors = instance_descriptors(); 5571 DescriptorArray* descriptors = instance_descriptors();
5487 for (int i = 0; i < descriptors->number_of_descriptors(); i++) { 5572 for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
5488 if (descriptors->GetType(i) == MAP_TRANSITION || 5573 if (descriptors->GetType(i) == MAP_TRANSITION ||
5574 descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION ||
5489 descriptors->GetType(i) == CONSTANT_TRANSITION) { 5575 descriptors->GetType(i) == CONSTANT_TRANSITION) {
5490 // Get target. 5576 // Get target.
5491 Map* target = Map::cast(descriptors->GetValue(i)); 5577 Map* target = Map::cast(descriptors->GetValue(i));
5492 #ifdef DEBUG 5578 #ifdef DEBUG
5493 // Verify target. 5579 // Verify target.
5494 Object* source_prototype = prototype(); 5580 Object* source_prototype = prototype();
5495 Object* target_prototype = target->prototype(); 5581 Object* target_prototype = target->prototype();
5496 ASSERT(source_prototype->IsJSObject() || 5582 ASSERT(source_prototype->IsJSObject() ||
5497 source_prototype->IsMap() || 5583 source_prototype->IsMap() ||
5498 source_prototype->IsNull()); 5584 source_prototype->IsNull());
(...skipping 22 matching lines...) Expand all
5521 d->get(DescriptorArray::kContentArrayIndex)); 5607 d->get(DescriptorArray::kContentArrayIndex));
5522 ASSERT(contents->length() >= 2); 5608 ASSERT(contents->length() >= 2);
5523 for (int i = 0; i < contents->length(); i += 2) { 5609 for (int i = 0; i < contents->length(); i += 2) {
5524 // If the pair (value, details) is a map transition, 5610 // If the pair (value, details) is a map transition,
5525 // check if the target is live. If not, null the descriptor. 5611 // check if the target is live. If not, null the descriptor.
5526 // Also drop the back pointer for that map transition, so that this 5612 // Also drop the back pointer for that map transition, so that this
5527 // map is not reached again by following a back pointer from a 5613 // map is not reached again by following a back pointer from a
5528 // non-live object. 5614 // non-live object.
5529 PropertyDetails details(Smi::cast(contents->get(i + 1))); 5615 PropertyDetails details(Smi::cast(contents->get(i + 1)));
5530 if (details.type() == MAP_TRANSITION || 5616 if (details.type() == MAP_TRANSITION ||
5617 details.type() == EXTERNAL_ARRAY_TRANSITION ||
5531 details.type() == CONSTANT_TRANSITION) { 5618 details.type() == CONSTANT_TRANSITION) {
5532 Map* target = reinterpret_cast<Map*>(contents->get(i)); 5619 Map* target = reinterpret_cast<Map*>(contents->get(i));
5533 ASSERT(target->IsHeapObject()); 5620 ASSERT(target->IsHeapObject());
5534 if (!target->IsMarked()) { 5621 if (!target->IsMarked()) {
5535 ASSERT(target->IsMap()); 5622 ASSERT(target->IsMap());
5536 contents->set_unchecked(i + 1, NullDescriptorDetails); 5623 contents->set_unchecked(i + 1, NullDescriptorDetails);
5537 contents->set_null_unchecked(heap, i); 5624 contents->set_null_unchecked(heap, i);
5538 ASSERT(target->prototype() == this || 5625 ASSERT(target->prototype() == this ||
5539 target->prototype() == real_prototype); 5626 target->prototype() == real_prototype);
5540 // Getter prototype() is read-only, set_prototype() has side effects. 5627 // Getter prototype() is read-only, set_prototype() has side effects.
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
6394 6481
6395 6482
6396 const char* Code::PropertyType2String(PropertyType type) { 6483 const char* Code::PropertyType2String(PropertyType type) {
6397 switch (type) { 6484 switch (type) {
6398 case NORMAL: return "NORMAL"; 6485 case NORMAL: return "NORMAL";
6399 case FIELD: return "FIELD"; 6486 case FIELD: return "FIELD";
6400 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; 6487 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
6401 case CALLBACKS: return "CALLBACKS"; 6488 case CALLBACKS: return "CALLBACKS";
6402 case INTERCEPTOR: return "INTERCEPTOR"; 6489 case INTERCEPTOR: return "INTERCEPTOR";
6403 case MAP_TRANSITION: return "MAP_TRANSITION"; 6490 case MAP_TRANSITION: return "MAP_TRANSITION";
6491 case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION";
6404 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; 6492 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
6405 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; 6493 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
6406 } 6494 }
6407 UNREACHABLE(); 6495 UNREACHABLE();
6408 return NULL; 6496 return NULL;
6409 } 6497 }
6410 6498
6411 6499
6412 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { 6500 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
6413 const char* name = NULL; 6501 const char* name = NULL;
(...skipping 3748 matching lines...) Expand 10 before | Expand all | Expand 10 after
10162 if (break_point_objects()->IsUndefined()) return 0; 10250 if (break_point_objects()->IsUndefined()) return 0;
10163 // Single beak point. 10251 // Single beak point.
10164 if (!break_point_objects()->IsFixedArray()) return 1; 10252 if (!break_point_objects()->IsFixedArray()) return 1;
10165 // Multiple break points. 10253 // Multiple break points.
10166 return FixedArray::cast(break_point_objects())->length(); 10254 return FixedArray::cast(break_point_objects())->length();
10167 } 10255 }
10168 #endif 10256 #endif
10169 10257
10170 10258
10171 } } // namespace v8::internal 10259 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698