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