OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |