OLD | NEW |
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 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 // If we have a global object set the cell to the hole. | 506 // If we have a global object set the cell to the hole. |
507 if (IsGlobalObject()) { | 507 if (IsGlobalObject()) { |
508 PropertyDetails details = dictionary->DetailsAt(entry); | 508 PropertyDetails details = dictionary->DetailsAt(entry); |
509 if (details.IsDontDelete()) { | 509 if (details.IsDontDelete()) { |
510 if (mode != FORCE_DELETION) return GetHeap()->false_value(); | 510 if (mode != FORCE_DELETION) return GetHeap()->false_value(); |
511 // When forced to delete global properties, we have to make a | 511 // When forced to delete global properties, we have to make a |
512 // map change to invalidate any ICs that think they can load | 512 // map change to invalidate any ICs that think they can load |
513 // from the DontDelete cell without checking if it contains | 513 // from the DontDelete cell without checking if it contains |
514 // the hole value. | 514 // the hole value. |
515 Map* new_map; | 515 Map* new_map; |
516 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 516 MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
517 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 517 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
518 } | 518 |
519 set_map(new_map); | 519 set_map(new_map); |
520 } | 520 } |
521 JSGlobalPropertyCell* cell = | 521 JSGlobalPropertyCell* cell = |
522 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); | 522 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); |
523 cell->set_value(cell->GetHeap()->the_hole_value()); | 523 cell->set_value(cell->GetHeap()->the_hole_value()); |
524 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 524 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
525 } else { | 525 } else { |
526 Object* deleted = dictionary->DeleteProperty(entry, mode); | 526 Object* deleted = dictionary->DeleteProperty(entry, mode); |
527 if (deleted == GetHeap()->true_value()) { | 527 if (deleted == GetHeap()->true_value()) { |
528 FixedArray* new_properties = NULL; | 528 FixedArray* new_properties = NULL; |
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1537 (map()->unused_property_fields() == 0 && | 1537 (map()->unused_property_fields() == 0 && |
1538 TooManyFastProperties(properties()->length(), store_mode))) { | 1538 TooManyFastProperties(properties()->length(), store_mode))) { |
1539 Object* obj; | 1539 Object* obj; |
1540 MaybeObject* maybe_obj = | 1540 MaybeObject* maybe_obj = |
1541 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1541 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1542 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1542 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1543 | 1543 |
1544 return AddSlowProperty(name, value, attributes); | 1544 return AddSlowProperty(name, value, attributes); |
1545 } | 1545 } |
1546 | 1546 |
1547 DescriptorArray* old_descriptors = map()->instance_descriptors(); | |
1548 // Compute the new index for new field. | 1547 // Compute the new index for new field. |
1549 int index = map()->NextFreePropertyIndex(); | 1548 int index = map()->NextFreePropertyIndex(); |
1550 | 1549 |
1551 // Allocate new instance descriptors with (name, index) added | 1550 // Allocate new instance descriptors with (name, index) added |
1552 FieldDescriptor new_field(name, index, attributes, 0); | 1551 FieldDescriptor new_field(name, index, attributes, 0); |
1553 | 1552 |
1554 DescriptorArray* new_descriptors; | |
1555 MaybeObject* maybe_new_descriptors = old_descriptors->CopyAdd(&new_field); | |
1556 if (!maybe_new_descriptors->To(&new_descriptors)) { | |
1557 return maybe_new_descriptors; | |
1558 } | |
1559 | |
1560 // Only allow map transition if the object isn't the global object. | |
1561 bool allow_map_transition = isolate->empty_object_map() != map(); | |
1562 | |
1563 ASSERT(index < map()->inobject_properties() || | 1553 ASSERT(index < map()->inobject_properties() || |
1564 (index - map()->inobject_properties()) < properties()->length() || | 1554 (index - map()->inobject_properties()) < properties()->length() || |
1565 map()->unused_property_fields() == 0); | 1555 map()->unused_property_fields() == 0); |
1566 | 1556 |
1567 // Allocate a new map for the object. | 1557 FixedArray* values = NULL; |
1568 Map* new_map; | |
1569 MaybeObject* maybe_r = map()->CopyReplaceDescriptors(new_descriptors); | |
1570 if (!maybe_r->To(&new_map)) return maybe_r; | |
1571 | |
1572 TransitionArray* new_transitions = NULL; | |
1573 if (allow_map_transition) { | |
1574 MaybeObject* maybe_transitions = map()->AddTransition(name, new_map); | |
1575 if (!maybe_transitions->To(&new_transitions)) return maybe_transitions; | |
1576 } | |
1577 | 1558 |
1578 if (map()->unused_property_fields() == 0) { | 1559 if (map()->unused_property_fields() == 0) { |
1579 // Make room for the new value | 1560 // Make room for the new value |
1580 FixedArray* values; | |
1581 MaybeObject* maybe_values = | 1561 MaybeObject* maybe_values = |
1582 properties()->CopySize(properties()->length() + kFieldsAdded); | 1562 properties()->CopySize(properties()->length() + kFieldsAdded); |
1583 if (!maybe_values->To(&values)) return maybe_values; | 1563 if (!maybe_values->To(&values)) return maybe_values; |
| 1564 } |
1584 | 1565 |
| 1566 // Only allow map transition if the object isn't the global object. |
| 1567 TransitionFlag flag = isolate->empty_object_map() != map() |
| 1568 ? INSERT_TRANSITION |
| 1569 : OMIT_TRANSITION; |
| 1570 |
| 1571 Map* new_map; |
| 1572 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); |
| 1573 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 1574 |
| 1575 if (map()->unused_property_fields() == 0) { |
| 1576 ASSERT(values != NULL); |
1585 set_properties(values); | 1577 set_properties(values); |
1586 new_map->set_unused_property_fields(kFieldsAdded - 1); | 1578 new_map->set_unused_property_fields(kFieldsAdded - 1); |
1587 } else { | 1579 } else { |
1588 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); | 1580 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); |
1589 } | 1581 } |
1590 | 1582 |
1591 // Apply all changes at once, so they are atomic. | |
1592 if (allow_map_transition) { | |
1593 MaybeObject* transition_added = map()->set_transitions(new_transitions); | |
1594 if (transition_added->IsFailure()) return transition_added; | |
1595 } | |
1596 | |
1597 new_map->SetBackPointer(map()); | |
1598 set_map(new_map); | 1583 set_map(new_map); |
1599 return FastPropertyAtPut(index, value); | 1584 return FastPropertyAtPut(index, value); |
1600 } | 1585 } |
1601 | 1586 |
1602 | 1587 |
1603 MaybeObject* JSObject::AddConstantFunctionProperty( | 1588 MaybeObject* JSObject::AddConstantFunctionProperty( |
1604 String* name, | 1589 String* name, |
1605 JSFunction* function, | 1590 JSFunction* function, |
1606 PropertyAttributes attributes) { | 1591 PropertyAttributes attributes) { |
1607 // Allocate new instance descriptors with (name, function) added | 1592 // Allocate new instance descriptors with (name, function) added |
1608 ConstantFunctionDescriptor d(name, function, attributes, 0); | 1593 ConstantFunctionDescriptor d(name, function, attributes, 0); |
1609 | 1594 |
1610 DescriptorArray* new_descriptors; | 1595 Heap* heap = GetHeap(); |
1611 MaybeObject* maybe_new_descriptors = | 1596 TransitionFlag flag = |
1612 map()->instance_descriptors()->CopyAdd(&d); | 1597 // Do not add transitions to the empty object map (map of "new Object()"), |
1613 if (!maybe_new_descriptors->To(&new_descriptors)) { | 1598 // nor to global objects. |
1614 return maybe_new_descriptors; | 1599 (map() == heap->isolate()->empty_object_map() || IsGlobalObject() || |
1615 } | 1600 // Don't add transitions to special properties with non-trivial |
| 1601 // attributes. |
| 1602 // TODO(verwaest): Once we support attribute changes, these transitions |
| 1603 // should be kept as well. |
| 1604 attributes != NONE) |
| 1605 ? OMIT_TRANSITION |
| 1606 : INSERT_TRANSITION; |
1616 | 1607 |
1617 // Allocate a new map for the object. | |
1618 Map* new_map; | 1608 Map* new_map; |
1619 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(new_descriptors); | 1609 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); |
1620 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 1610 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
1621 | 1611 |
1622 Map* old_map = map(); | |
1623 | |
1624 Heap* heap = GetHeap(); | |
1625 // Do not add transitions to the empty object map (map of "new Object()"), nor | |
1626 // to global objects. | |
1627 if (old_map == heap->isolate()->empty_object_map() || IsGlobalObject()) { | |
1628 set_map(new_map); | |
1629 return function; | |
1630 } | |
1631 | |
1632 // Don't add transitions to special properties with non-trivial attributes. | |
1633 // TODO(verwaest): Once we support attribute changes, these transitions should | |
1634 // be kept as well. | |
1635 if (attributes != NONE) { | |
1636 set_map(new_map); | |
1637 return function; | |
1638 } | |
1639 | |
1640 // Add a constant transition to the old map, so future assignments to this | |
1641 // property on other objects of the same type will create a normal field, not | |
1642 // a constant function. | |
1643 TransitionArray* transitions; | |
1644 MaybeObject* maybe_transitions = old_map->AddTransition(name, new_map); | |
1645 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
1646 | |
1647 MaybeObject* transition_added = old_map->set_transitions(transitions); | |
1648 if (transition_added->IsFailure()) return transition_added; | |
1649 | |
1650 set_map(new_map); | 1612 set_map(new_map); |
1651 new_map->SetBackPointer(old_map); | |
1652 return function; | 1613 return function; |
1653 } | 1614 } |
1654 | 1615 |
1655 | 1616 |
1656 // Add property in slow mode | 1617 // Add property in slow mode |
1657 MaybeObject* JSObject::AddSlowProperty(String* name, | 1618 MaybeObject* JSObject::AddSlowProperty(String* name, |
1658 Object* value, | 1619 Object* value, |
1659 PropertyAttributes attributes) { | 1620 PropertyAttributes attributes) { |
1660 ASSERT(!HasFastProperties()); | 1621 ASSERT(!HasFastProperties()); |
1661 StringDictionary* dict = property_dictionary(); | 1622 StringDictionary* dict = property_dictionary(); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | 1773 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { |
1813 Object* obj; | 1774 Object* obj; |
1814 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1775 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1815 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1776 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1816 return ReplaceSlowProperty(name, new_value, attributes); | 1777 return ReplaceSlowProperty(name, new_value, attributes); |
1817 } | 1778 } |
1818 | 1779 |
1819 int index = map()->NextFreePropertyIndex(); | 1780 int index = map()->NextFreePropertyIndex(); |
1820 FieldDescriptor new_field(name, index, attributes, 0); | 1781 FieldDescriptor new_field(name, index, attributes, 0); |
1821 | 1782 |
1822 // Make a new DescriptorArray replacing an entry with FieldDescriptor. | |
1823 DescriptorArray* new_descriptors; | |
1824 MaybeObject* maybe_descriptors = | |
1825 map()->instance_descriptors()->CopyInsert(&new_field); | |
1826 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
1827 | |
1828 // Make a new map for the object. | 1783 // Make a new map for the object. |
1829 Map* new_map; | 1784 Map* new_map; |
1830 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(new_descriptors); | 1785 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, |
| 1786 OMIT_TRANSITION); |
1831 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 1787 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
1832 | 1788 |
1833 // Make new properties array if necessary. | 1789 // Make new properties array if necessary. |
1834 FixedArray* new_properties = NULL; | 1790 FixedArray* new_properties = NULL; |
1835 int new_unused_property_fields = map()->unused_property_fields() - 1; | 1791 int new_unused_property_fields = map()->unused_property_fields() - 1; |
1836 if (map()->unused_property_fields() == 0) { | 1792 if (map()->unused_property_fields() == 0) { |
1837 new_unused_property_fields = kFieldsAdded - 1; | 1793 new_unused_property_fields = kFieldsAdded - 1; |
1838 MaybeObject* maybe_new_properties = | 1794 MaybeObject* maybe_new_properties = |
1839 properties()->CopySize(properties()->length() + kFieldsAdded); | 1795 properties()->CopySize(properties()->length() + kFieldsAdded); |
1840 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; | 1796 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2213 } | 2169 } |
2214 | 2170 |
2215 | 2171 |
2216 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 2172 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
2217 Map* to_map = FindClosestElementsTransition(this, to_kind); | 2173 Map* to_map = FindClosestElementsTransition(this, to_kind); |
2218 if (to_map->elements_kind() == to_kind) return to_map; | 2174 if (to_map->elements_kind() == to_kind) return to_map; |
2219 return NULL; | 2175 return NULL; |
2220 } | 2176 } |
2221 | 2177 |
2222 | 2178 |
2223 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) { | |
2224 ASSERT(!HasElementsTransition() || | |
2225 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || | |
2226 IsExternalArrayElementsKind( | |
2227 elements_transition_map()->elements_kind())) && | |
2228 (next_kind == DICTIONARY_ELEMENTS || | |
2229 IsExternalArrayElementsKind(next_kind)))); | |
2230 ASSERT(!IsFastElementsKind(next_kind) || | |
2231 IsMoreGeneralElementsKindTransition(elements_kind(), next_kind)); | |
2232 ASSERT(next_kind != elements_kind()); | |
2233 | |
2234 Map* next_map; | |
2235 { MaybeObject* maybe_next_map = | |
2236 this->CopyDropTransitions(DescriptorArray::CANNOT_BE_SHARED); | |
2237 if (!maybe_next_map->To(&next_map)) return maybe_next_map; | |
2238 } | |
2239 | |
2240 { MaybeObject* added_elements = this->set_elements_transition_map(next_map); | |
2241 if (added_elements->IsFailure()) return added_elements; | |
2242 } | |
2243 | |
2244 next_map->set_elements_kind(next_kind); | |
2245 next_map->SetBackPointer(this); | |
2246 return next_map; | |
2247 } | |
2248 | |
2249 | |
2250 static MaybeObject* AddMissingElementsTransitions(Map* map, | 2179 static MaybeObject* AddMissingElementsTransitions(Map* map, |
2251 ElementsKind to_kind) { | 2180 ElementsKind to_kind) { |
2252 ASSERT(IsFastElementsKind(map->elements_kind())); | 2181 ASSERT(IsFastElementsKind(map->elements_kind())); |
2253 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); | 2182 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
2254 int to_index = IsFastElementsKind(to_kind) | 2183 int to_index = IsFastElementsKind(to_kind) |
2255 ? GetSequenceIndexFromFastElementsKind(to_kind) | 2184 ? GetSequenceIndexFromFastElementsKind(to_kind) |
2256 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); | 2185 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
2257 | 2186 |
2258 ASSERT(index <= to_index); | 2187 ASSERT(index <= to_index); |
2259 | 2188 |
2260 Map* current_map = map; | 2189 Map* current_map = map; |
2261 | 2190 |
2262 for (; index < to_index; ++index) { | 2191 for (; index < to_index; ++index) { |
2263 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1); | 2192 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1); |
2264 MaybeObject* maybe_next_map = | 2193 MaybeObject* maybe_next_map = |
2265 current_map->CreateNextElementsTransition(next_kind); | 2194 current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION); |
2266 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | 2195 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
2267 } | 2196 } |
2268 | 2197 |
2269 // In case we are exiting the fast elements kind system, just add the map in | 2198 // In case we are exiting the fast elements kind system, just add the map in |
2270 // the end. | 2199 // the end. |
2271 if (!IsFastElementsKind(to_kind)) { | 2200 if (!IsFastElementsKind(to_kind)) { |
2272 MaybeObject* maybe_next_map = | 2201 MaybeObject* maybe_next_map = |
2273 current_map->CreateNextElementsTransition(to_kind); | 2202 current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION); |
2274 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | 2203 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
2275 } | 2204 } |
2276 | 2205 |
2277 ASSERT(current_map->elements_kind() == to_kind); | 2206 ASSERT(current_map->elements_kind() == to_kind); |
2278 return current_map; | 2207 return current_map; |
2279 } | 2208 } |
2280 | 2209 |
2281 | 2210 |
2282 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, | 2211 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
2283 ElementsKind to_kind) { | 2212 ElementsKind to_kind) { |
2284 Isolate* isolate = object->GetIsolate(); | 2213 Isolate* isolate = object->GetIsolate(); |
(...skipping 20 matching lines...) Expand all Loading... |
2305 IsFastElementsKind(from_kind); | 2234 IsFastElementsKind(from_kind); |
2306 | 2235 |
2307 // Only store fast element maps in ascending generality. | 2236 // Only store fast element maps in ascending generality. |
2308 if (IsFastElementsKind(to_kind)) { | 2237 if (IsFastElementsKind(to_kind)) { |
2309 allow_store_transition &= | 2238 allow_store_transition &= |
2310 IsTransitionableFastElementsKind(from_kind) && | 2239 IsTransitionableFastElementsKind(from_kind) && |
2311 IsMoreGeneralElementsKindTransition(from_kind, to_kind); | 2240 IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
2312 } | 2241 } |
2313 | 2242 |
2314 if (!allow_store_transition) { | 2243 if (!allow_store_transition) { |
2315 // Create a new free-floating map only if we are not allowed to store it. | 2244 return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION); |
2316 Map* new_map = NULL; | |
2317 MaybeObject* maybe_new_map = | |
2318 start_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); | |
2319 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
2320 new_map->set_elements_kind(to_kind); | |
2321 return new_map; | |
2322 } | 2245 } |
2323 | 2246 |
2324 Map* closest_map = FindClosestElementsTransition(start_map, to_kind); | 2247 Map* closest_map = FindClosestElementsTransition(start_map, to_kind); |
2325 | 2248 |
2326 if (closest_map->elements_kind() == to_kind) { | 2249 if (closest_map->elements_kind() == to_kind) { |
2327 return closest_map; | 2250 return closest_map; |
2328 } | 2251 } |
2329 | 2252 |
2330 return AddMissingElementsTransitions(closest_map, to_kind); | 2253 return AddMissingElementsTransitions(closest_map, to_kind); |
2331 } | 2254 } |
(...skipping 1723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4055 { MaybeObject* maybe = NormalizeElements(); | 3978 { MaybeObject* maybe = NormalizeElements(); |
4056 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; | 3979 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; |
4057 } | 3980 } |
4058 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 3981 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
4059 // Make sure that we never go back to fast case. | 3982 // Make sure that we never go back to fast case. |
4060 dictionary->set_requires_slow_elements(); | 3983 dictionary->set_requires_slow_elements(); |
4061 | 3984 |
4062 // Do a map transition, other objects with this map may still | 3985 // Do a map transition, other objects with this map may still |
4063 // be extensible. | 3986 // be extensible. |
4064 Map* new_map; | 3987 Map* new_map; |
4065 { MaybeObject* maybe = | 3988 MaybeObject* maybe = map()->Copy(DescriptorArray::MAY_BE_SHARED); |
4066 map()->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); | 3989 if (!maybe->To(&new_map)) return maybe; |
4067 if (!maybe->To<Map>(&new_map)) return maybe; | 3990 |
4068 } | |
4069 new_map->set_is_extensible(false); | 3991 new_map->set_is_extensible(false); |
4070 set_map(new_map); | 3992 set_map(new_map); |
4071 ASSERT(!map()->is_extensible()); | 3993 ASSERT(!map()->is_extensible()); |
4072 return new_map; | 3994 return new_map; |
4073 } | 3995 } |
4074 | 3996 |
4075 | 3997 |
4076 // Tests for the fast common case for property enumeration: | 3998 // Tests for the fast common case for property enumeration: |
4077 // - This object and all prototypes has an enum cache (which means that | 3999 // - This object and all prototypes has an enum cache (which means that |
4078 // it is no proxy, has no interceptors and needs no access checks). | 4000 // it is no proxy, has no interceptors and needs no access checks). |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4522 self->set_map(transitioned_map); | 4444 self->set_map(transitioned_map); |
4523 return self; | 4445 return self; |
4524 } | 4446 } |
4525 | 4447 |
4526 // If either not the same accessor, or not the same attributes, fall back to | 4448 // If either not the same accessor, or not the same attributes, fall back to |
4527 // the slow case. | 4449 // the slow case. |
4528 return self->GetHeap()->null_value(); | 4450 return self->GetHeap()->null_value(); |
4529 } | 4451 } |
4530 | 4452 |
4531 | 4453 |
4532 static MaybeObject* NewCallbackTransition(JSObject* obj, | |
4533 String* name, | |
4534 AccessorComponent component, | |
4535 Object* accessor, | |
4536 PropertyAttributes attributes, | |
4537 AccessorPair* new_accessors) { | |
4538 // step 1: create a copy of the descriptors, incl. the new getter/setter pair | |
4539 Map* old_map = obj->map(); | |
4540 CallbacksDescriptor new_accessors_desc(name, new_accessors, attributes); | |
4541 DescriptorArray* descriptors; | |
4542 MaybeObject* maybe_descriptors = | |
4543 old_map->instance_descriptors()->CopyInsert(&new_accessors_desc); | |
4544 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | |
4545 | |
4546 // step 2: create a new map with the new descriptors | |
4547 Map* new_map; | |
4548 MaybeObject* maybe_new_map = old_map->CopyReplaceDescriptors(descriptors); | |
4549 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
4550 | |
4551 // step 3: add a new transition to the new map | |
4552 TransitionArray* transitions; | |
4553 MaybeObject* maybe_transitions = old_map->AddTransition(name, new_map); | |
4554 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
4555 | |
4556 // step 4: everything went well so far, so we make our changes visible | |
4557 MaybeObject* transition_added = old_map->set_transitions(transitions); | |
4558 if (transition_added->IsFailure()) return transition_added; | |
4559 | |
4560 new_map->SetBackPointer(old_map); | |
4561 obj->set_map(new_map); | |
4562 return obj; | |
4563 } | |
4564 | |
4565 | |
4566 MaybeObject* JSObject::DefineFastAccessor(String* name, | 4454 MaybeObject* JSObject::DefineFastAccessor(String* name, |
4567 AccessorComponent component, | 4455 AccessorComponent component, |
4568 Object* accessor, | 4456 Object* accessor, |
4569 PropertyAttributes attributes) { | 4457 PropertyAttributes attributes) { |
4570 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); | 4458 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); |
4571 LookupResult result(GetIsolate()); | 4459 LookupResult result(GetIsolate()); |
4572 LocalLookup(name, &result); | 4460 LocalLookup(name, &result); |
4573 | 4461 |
4574 if (result.IsFound() | 4462 if (result.IsFound() |
4575 && !result.IsPropertyCallbacks() | 4463 && !result.IsPropertyCallbacks() |
(...skipping 30 matching lines...) Expand all Loading... |
4606 // Allocate a new pair if there were no source accessors. Otherwise, copy the | 4494 // Allocate a new pair if there were no source accessors. Otherwise, copy the |
4607 // pair and modify the accessor. | 4495 // pair and modify the accessor. |
4608 if (source_accessors != NULL) { | 4496 if (source_accessors != NULL) { |
4609 maybe_accessors = source_accessors->Copy(); | 4497 maybe_accessors = source_accessors->Copy(); |
4610 } else { | 4498 } else { |
4611 maybe_accessors = GetHeap()->AllocateAccessorPair(); | 4499 maybe_accessors = GetHeap()->AllocateAccessorPair(); |
4612 } | 4500 } |
4613 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | 4501 if (!maybe_accessors->To(&accessors)) return maybe_accessors; |
4614 accessors->set(component, accessor); | 4502 accessors->set(component, accessor); |
4615 | 4503 |
4616 return NewCallbackTransition(this, | 4504 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); |
4617 name, | 4505 |
4618 component, | 4506 Map* new_map; |
4619 accessor, | 4507 MaybeObject* maybe_new_map = |
4620 attributes, | 4508 map()->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION); |
4621 accessors); | 4509 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 4510 |
| 4511 set_map(new_map); |
| 4512 return this; |
4622 } | 4513 } |
4623 | 4514 |
4624 | 4515 |
4625 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 4516 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
4626 Isolate* isolate = GetIsolate(); | 4517 Isolate* isolate = GetIsolate(); |
4627 String* name = String::cast(info->name()); | 4518 String* name = String::cast(info->name()); |
4628 // Check access rights if needed. | 4519 // Check access rights if needed. |
4629 if (IsAccessCheckNeeded() && | 4520 if (IsAccessCheckNeeded() && |
4630 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 4521 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
4631 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 4522 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4819 result->SharedMapVerify(); | 4710 result->SharedMapVerify(); |
4820 } | 4711 } |
4821 #endif | 4712 #endif |
4822 | 4713 |
4823 return result; | 4714 return result; |
4824 } | 4715 } |
4825 | 4716 |
4826 | 4717 |
4827 MaybeObject* Map::CopyDropDescriptors() { | 4718 MaybeObject* Map::CopyDropDescriptors() { |
4828 Map* result; | 4719 Map* result; |
4829 { MaybeObject* maybe_result = RawCopy(instance_size()); | 4720 MaybeObject* maybe_result = RawCopy(instance_size()); |
4830 if (!maybe_result->To(&result)) return maybe_result; | 4721 if (!maybe_result->To(&result)) return maybe_result; |
4831 } | |
4832 | 4722 |
4833 // Please note instance_type and instance_size are set when allocated. | 4723 // Please note instance_type and instance_size are set when allocated. |
4834 result->set_inobject_properties(inobject_properties()); | 4724 result->set_inobject_properties(inobject_properties()); |
4835 result->set_unused_property_fields(unused_property_fields()); | 4725 result->set_unused_property_fields(unused_property_fields()); |
4836 | 4726 |
4837 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); | 4727 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
4838 result->set_is_shared(false); | 4728 result->set_is_shared(false); |
4839 result->ClearCodeCache(GetHeap()); | 4729 result->ClearCodeCache(GetHeap()); |
4840 return result; | 4730 return result; |
4841 } | 4731 } |
4842 | 4732 |
4843 | 4733 |
4844 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors) { | 4734 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
| 4735 String* name, |
| 4736 TransitionFlag flag) { |
4845 Map* result; | 4737 Map* result; |
4846 { MaybeObject* maybe_result = CopyDropDescriptors(); | 4738 MaybeObject* maybe_result = CopyDropDescriptors(); |
4847 if (!maybe_result->To(&result)) return maybe_result; | 4739 if (!maybe_result->To(&result)) return maybe_result; |
| 4740 |
| 4741 result->set_instance_descriptors(descriptors); |
| 4742 |
| 4743 if (flag == INSERT_TRANSITION) { |
| 4744 TransitionArray* transitions; |
| 4745 MaybeObject* maybe_transitions = AddTransition(name, result); |
| 4746 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 4747 |
| 4748 MaybeObject* maybe_set = set_transitions(transitions); |
| 4749 if (maybe_set->IsFailure()) return maybe_set; |
| 4750 |
| 4751 result->SetBackPointer(this); |
4848 } | 4752 } |
4849 result->set_instance_descriptors(descriptors); | 4753 |
4850 return result; | 4754 return result; |
4851 } | 4755 } |
4852 | 4756 |
4853 | 4757 |
| 4758 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { |
| 4759 // Create a new free-floating map only if we are not allowed to store it. |
| 4760 Map* new_map = NULL; |
| 4761 MaybeObject* maybe_new_map = Copy(DescriptorArray::MAY_BE_SHARED); |
| 4762 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 4763 new_map->set_elements_kind(kind); |
| 4764 |
| 4765 if (flag == INSERT_TRANSITION) { |
| 4766 ASSERT(!HasElementsTransition() || |
| 4767 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
| 4768 IsExternalArrayElementsKind( |
| 4769 elements_transition_map()->elements_kind())) && |
| 4770 (kind == DICTIONARY_ELEMENTS || |
| 4771 IsExternalArrayElementsKind(kind)))); |
| 4772 ASSERT(!IsFastElementsKind(kind) || |
| 4773 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); |
| 4774 ASSERT(kind != elements_kind()); |
| 4775 |
| 4776 MaybeObject* added_elements = set_elements_transition_map(new_map); |
| 4777 if (added_elements->IsFailure()) return added_elements; |
| 4778 |
| 4779 new_map->SetBackPointer(this); |
| 4780 } |
| 4781 |
| 4782 return new_map; |
| 4783 } |
| 4784 |
| 4785 |
4854 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { | 4786 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
4855 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); | 4787 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); |
4856 | 4788 |
4857 // If the map has pre-allocated properties always start out with a descriptor | 4789 // If the map has pre-allocated properties always start out with a descriptor |
4858 // array describing these properties. | 4790 // array describing these properties. |
4859 ASSERT(constructor()->IsJSFunction()); | 4791 ASSERT(constructor()->IsJSFunction()); |
4860 JSFunction* ctor = JSFunction::cast(constructor()); | 4792 JSFunction* ctor = JSFunction::cast(constructor()); |
4861 DescriptorArray* descriptors; | 4793 DescriptorArray* descriptors; |
4862 { MaybeObject* maybe_descriptors = | 4794 MaybeObject* maybe_descriptors = |
4863 ctor->initial_map()->instance_descriptors()->Copy( | 4795 ctor->initial_map()->instance_descriptors()->Copy( |
4864 DescriptorArray::MAY_BE_SHARED); | 4796 DescriptorArray::MAY_BE_SHARED); |
4865 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 4797 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
4866 } | 4798 |
4867 return CopyReplaceDescriptors(descriptors); | 4799 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); |
4868 } | 4800 } |
4869 | 4801 |
4870 | 4802 |
4871 MaybeObject* Map::CopyDropTransitions(DescriptorArray::SharedMode shared_mode) { | 4803 MaybeObject* Map::Copy(DescriptorArray::SharedMode shared_mode) { |
4872 DescriptorArray* descriptors; | 4804 DescriptorArray* descriptors; |
4873 { MaybeObject* maybe_descriptors = instance_descriptors()->Copy(shared_mode); | 4805 MaybeObject* maybe_descriptors = instance_descriptors()->Copy(shared_mode); |
4874 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 4806 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
4875 } | 4807 |
4876 return CopyReplaceDescriptors(descriptors); | 4808 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); |
4877 } | 4809 } |
4878 | 4810 |
4879 | 4811 |
| 4812 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
| 4813 TransitionFlag flag) { |
| 4814 DescriptorArray* descriptors; |
| 4815 MaybeObject* maybe_descriptors = instance_descriptors()->CopyAdd(descriptor); |
| 4816 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 4817 |
| 4818 return CopyReplaceDescriptors(descriptors, descriptor->GetKey(), flag); |
| 4819 } |
| 4820 |
| 4821 |
| 4822 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
| 4823 TransitionFlag flag) { |
| 4824 DescriptorArray* old_descriptors = instance_descriptors(); |
| 4825 |
| 4826 // Ensure the key is a symbol. |
| 4827 MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
| 4828 if (maybe_result->IsFailure()) return maybe_result; |
| 4829 |
| 4830 DescriptorArray* descriptors; |
| 4831 MaybeObject* maybe_descriptors; |
| 4832 |
| 4833 // We replace the key if it is already present. |
| 4834 int index = old_descriptors->SearchWithCache(descriptor->GetKey()); |
| 4835 if (index == DescriptorArray::kNotFound) { |
| 4836 maybe_descriptors = old_descriptors->CopyAdd(descriptor); |
| 4837 } else { |
| 4838 maybe_descriptors = old_descriptors->CopyReplace(descriptor, index); |
| 4839 } |
| 4840 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 4841 |
| 4842 return CopyReplaceDescriptors(descriptors, descriptor->GetKey(), flag); |
| 4843 } |
| 4844 |
| 4845 |
| 4846 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, |
| 4847 int index, |
| 4848 TransitionFlag flag) { |
| 4849 DescriptorArray* descriptors; |
| 4850 MaybeObject* maybe_descriptors = |
| 4851 instance_descriptors()->CopyReplace(descriptor, index); |
| 4852 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 4853 |
| 4854 return CopyReplaceDescriptors(descriptors, descriptor->GetKey(), flag); |
| 4855 } |
| 4856 |
| 4857 |
4880 void Map::UpdateCodeCache(Handle<Map> map, | 4858 void Map::UpdateCodeCache(Handle<Map> map, |
4881 Handle<String> name, | 4859 Handle<String> name, |
4882 Handle<Code> code) { | 4860 Handle<Code> code) { |
4883 Isolate* isolate = map->GetIsolate(); | 4861 Isolate* isolate = map->GetIsolate(); |
4884 CALL_HEAP_FUNCTION_VOID(isolate, | 4862 CALL_HEAP_FUNCTION_VOID(isolate, |
4885 map->UpdateCodeCache(*name, *code)); | 4863 map->UpdateCodeCache(*name, *code)); |
4886 } | 4864 } |
4887 | 4865 |
| 4866 |
4888 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 4867 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
4889 ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache()); | 4868 ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache()); |
4890 | 4869 |
4891 // Allocate the code cache if not present. | 4870 // Allocate the code cache if not present. |
4892 if (code_cache()->IsFixedArray()) { | 4871 if (code_cache()->IsFixedArray()) { |
4893 Object* result; | 4872 Object* result; |
4894 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); | 4873 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); |
4895 if (!maybe_result->ToObject(&result)) return maybe_result; | 4874 if (!maybe_result->ToObject(&result)) return maybe_result; |
4896 } | 4875 } |
4897 set_code_cache(result); | 4876 set_code_cache(result); |
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5731 descriptor->SetEnumerationIndex(GetDetails(insertion_index).index()); | 5710 descriptor->SetEnumerationIndex(GetDetails(insertion_index).index()); |
5732 new_descriptors->Set(insertion_index, descriptor, witness); | 5711 new_descriptors->Set(insertion_index, descriptor, witness); |
5733 new_descriptors->SetLastAdded(LastAdded()); | 5712 new_descriptors->SetLastAdded(LastAdded()); |
5734 | 5713 |
5735 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); | 5714 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
5736 | 5715 |
5737 return new_descriptors; | 5716 return new_descriptors; |
5738 } | 5717 } |
5739 | 5718 |
5740 | 5719 |
5741 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) { | |
5742 // Ensure the key is a symbol. | |
5743 MaybeObject* maybe_result = descriptor->KeyToSymbol(); | |
5744 if (maybe_result->IsFailure()) return maybe_result; | |
5745 | |
5746 // We replace the key if it is already present. | |
5747 int index = SearchWithCache(descriptor->GetKey()); | |
5748 if (index == kNotFound) return CopyAdd(descriptor); | |
5749 return CopyReplace(descriptor, index); | |
5750 } | |
5751 | |
5752 | |
5753 MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) { | 5720 MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) { |
5754 // Ensure the key is a symbol. | 5721 // Ensure the key is a symbol. |
5755 MaybeObject* maybe_result = descriptor->KeyToSymbol(); | 5722 MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
5756 if (maybe_result->IsFailure()) return maybe_result; | 5723 if (maybe_result->IsFailure()) return maybe_result; |
5757 | 5724 |
5758 String* key = descriptor->GetKey(); | 5725 String* key = descriptor->GetKey(); |
5759 ASSERT(Search(key) == kNotFound); | 5726 ASSERT(Search(key) == kNotFound); |
5760 | 5727 |
5761 int new_size = number_of_descriptors() + 1; | 5728 int new_size = number_of_descriptors() + 1; |
5762 | 5729 |
(...skipping 1696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7459 if (ok->IsFailure()) return ok; | 7426 if (ok->IsFailure()) return ok; |
7460 } | 7427 } |
7461 | 7428 |
7462 // Now some logic for the maps of the objects that are created by using this | 7429 // Now some logic for the maps of the objects that are created by using this |
7463 // function as a constructor. | 7430 // function as a constructor. |
7464 if (has_initial_map()) { | 7431 if (has_initial_map()) { |
7465 // If the function has allocated the initial map | 7432 // If the function has allocated the initial map |
7466 // replace it with a copy containing the new prototype. | 7433 // replace it with a copy containing the new prototype. |
7467 Map* new_map; | 7434 Map* new_map; |
7468 MaybeObject* maybe_new_map = | 7435 MaybeObject* maybe_new_map = |
7469 initial_map()->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); | 7436 initial_map()->Copy(DescriptorArray::MAY_BE_SHARED); |
7470 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 7437 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
7471 new_map->set_prototype(value); | 7438 new_map->set_prototype(value); |
7472 MaybeObject* maybe_object = | 7439 MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map); |
7473 set_initial_map_and_cache_transitions(new_map); | |
7474 if (maybe_object->IsFailure()) return maybe_object; | 7440 if (maybe_object->IsFailure()) return maybe_object; |
7475 } else { | 7441 } else { |
7476 // Put the value in the initial map field until an initial map is | 7442 // Put the value in the initial map field until an initial map is |
7477 // needed. At that point, a new initial map is created and the | 7443 // needed. At that point, a new initial map is created and the |
7478 // prototype is put into the initial map where it belongs. | 7444 // prototype is put into the initial map where it belongs. |
7479 set_prototype_or_initial_map(value); | 7445 set_prototype_or_initial_map(value); |
7480 } | 7446 } |
7481 heap->ClearInstanceofCache(); | 7447 heap->ClearInstanceofCache(); |
7482 return value; | 7448 return value; |
7483 } | 7449 } |
7484 | 7450 |
7485 | 7451 |
7486 MaybeObject* JSFunction::SetPrototype(Object* value) { | 7452 MaybeObject* JSFunction::SetPrototype(Object* value) { |
7487 ASSERT(should_have_prototype()); | 7453 ASSERT(should_have_prototype()); |
7488 Object* construct_prototype = value; | 7454 Object* construct_prototype = value; |
7489 | 7455 |
7490 // If the value is not a JSReceiver, store the value in the map's | 7456 // If the value is not a JSReceiver, store the value in the map's |
7491 // constructor field so it can be accessed. Also, set the prototype | 7457 // constructor field so it can be accessed. Also, set the prototype |
7492 // used for constructing objects to the original object prototype. | 7458 // used for constructing objects to the original object prototype. |
7493 // See ECMA-262 13.2.2. | 7459 // See ECMA-262 13.2.2. |
7494 if (!value->IsJSReceiver()) { | 7460 if (!value->IsJSReceiver()) { |
7495 // Copy the map so this does not affect unrelated functions. | 7461 // Copy the map so this does not affect unrelated functions. |
7496 // Remove map transitions because they point to maps with a | 7462 // Remove map transitions because they point to maps with a |
7497 // different prototype. | 7463 // different prototype. |
7498 Map* new_map; | 7464 Map* new_map; |
7499 { MaybeObject* maybe_new_map = | 7465 MaybeObject* maybe_new_map = map()->Copy(DescriptorArray::MAY_BE_SHARED); |
7500 map()->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); | 7466 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
7501 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 7467 |
7502 } | |
7503 Heap* heap = new_map->GetHeap(); | 7468 Heap* heap = new_map->GetHeap(); |
7504 set_map(new_map); | 7469 set_map(new_map); |
7505 new_map->set_constructor(value); | 7470 new_map->set_constructor(value); |
7506 new_map->set_non_instance_prototype(true); | 7471 new_map->set_non_instance_prototype(true); |
7507 construct_prototype = | 7472 construct_prototype = |
7508 heap->isolate()->context()->global_context()-> | 7473 heap->isolate()->context()->global_context()-> |
7509 initial_object_prototype(); | 7474 initial_object_prototype(); |
7510 } else { | 7475 } else { |
7511 map()->set_non_instance_prototype(false); | 7476 map()->set_non_instance_prototype(false); |
7512 } | 7477 } |
(...skipping 1271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8784 // Nothing to do if prototype is already set. | 8749 // Nothing to do if prototype is already set. |
8785 if (map->prototype() == value) return value; | 8750 if (map->prototype() == value) return value; |
8786 | 8751 |
8787 if (value->IsJSObject()) { | 8752 if (value->IsJSObject()) { |
8788 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | 8753 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); |
8789 if (ok->IsFailure()) return ok; | 8754 if (ok->IsFailure()) return ok; |
8790 } | 8755 } |
8791 | 8756 |
8792 Map* new_map = map->GetPrototypeTransition(value); | 8757 Map* new_map = map->GetPrototypeTransition(value); |
8793 if (new_map == NULL) { | 8758 if (new_map == NULL) { |
8794 { MaybeObject* maybe_new_map = | 8759 MaybeObject* maybe_new_map = map->Copy(DescriptorArray::MAY_BE_SHARED); |
8795 map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); | 8760 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
8796 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
8797 } | |
8798 | 8761 |
8799 { MaybeObject* maybe_new_cache = | 8762 MaybeObject* maybe_new_cache = |
8800 map->PutPrototypeTransition(value, new_map); | 8763 map->PutPrototypeTransition(value, new_map); |
8801 if (maybe_new_cache->IsFailure()) return maybe_new_cache; | 8764 if (maybe_new_cache->IsFailure()) return maybe_new_cache; |
8802 } | |
8803 | 8765 |
8804 new_map->set_prototype(value); | 8766 new_map->set_prototype(value); |
8805 } | 8767 } |
8806 ASSERT(new_map->prototype() == value); | 8768 ASSERT(new_map->prototype() == value); |
8807 real_receiver->set_map(new_map); | 8769 real_receiver->set_map(new_map); |
8808 | 8770 |
8809 heap->ClearInstanceofCache(); | 8771 heap->ClearInstanceofCache(); |
8810 ASSERT(size == Size()); | 8772 ASSERT(size == Size()); |
8811 return value; | 8773 return value; |
8812 } | 8774 } |
(...skipping 3756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12569 UNREACHABLE(); | 12531 UNREACHABLE(); |
12570 } | 12532 } |
12571 ++next_descriptor; | 12533 ++next_descriptor; |
12572 } | 12534 } |
12573 } | 12535 } |
12574 ASSERT(current_offset == number_of_fields); | 12536 ASSERT(current_offset == number_of_fields); |
12575 | 12537 |
12576 descriptors->Sort(witness); | 12538 descriptors->Sort(witness); |
12577 // Allocate new map. | 12539 // Allocate new map. |
12578 Map* new_map; | 12540 Map* new_map; |
12579 MaybeObject* maybe_new_map = obj->map()->CopyReplaceDescriptors(descriptors); | 12541 MaybeObject* maybe_new_map = |
| 12542 obj->map()->CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); |
12580 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 12543 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
12581 | 12544 |
12582 new_map->set_unused_property_fields(unused_property_fields); | 12545 new_map->set_unused_property_fields(unused_property_fields); |
12583 | 12546 |
12584 // Transform the object. | 12547 // Transform the object. |
12585 obj->set_map(new_map); | 12548 obj->set_map(new_map); |
12586 | 12549 |
12587 obj->set_properties(fields); | 12550 obj->set_properties(fields); |
12588 ASSERT(obj->IsJSObject()); | 12551 ASSERT(obj->IsJSObject()); |
12589 | 12552 |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13091 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13054 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13092 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13055 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13093 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13056 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13094 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13057 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13095 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13058 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13096 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13059 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13097 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13060 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13098 } | 13061 } |
13099 | 13062 |
13100 } } // namespace v8::internal | 13063 } } // namespace v8::internal |
OLD | NEW |