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 1753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1764 Map* old_target = old_map->GetTransition(transition_index); | 1764 Map* old_target = old_map->GetTransition(transition_index); |
1765 Object* result; | 1765 Object* result; |
1766 | 1766 |
1767 // To sever a transition to a map with which the descriptors are shared, the | 1767 // To sever a transition to a map with which the descriptors are shared, the |
1768 // larger map (more descriptors) needs to store its own descriptors array. | 1768 // larger map (more descriptors) needs to store its own descriptors array. |
1769 // Both sides of the severed chain need to have their own descriptors pointer | 1769 // Both sides of the severed chain need to have their own descriptors pointer |
1770 // to store distinct descriptor arrays. | 1770 // to store distinct descriptor arrays. |
1771 | 1771 |
1772 // If the old_target did not yet store its own descriptors, the new | 1772 // If the old_target did not yet store its own descriptors, the new |
1773 // descriptors pointer is created for the old_target by temporarily clearing | 1773 // descriptors pointer is created for the old_target by temporarily clearing |
1774 // the back pointer and setting its descriptor array. The ownership of the | 1774 // the back pointer and setting its descriptor array. |
1775 // descriptor array is returned to the smaller maps by installing a reduced | |
1776 // copy of the descriptor array in the old_map. | |
1777 | 1775 |
1778 // This phase is executed before creating the new map since it requires | 1776 // This phase is executed before creating the new map since it requires |
1779 // allocation that may fail. | 1777 // allocation that may fail. |
1780 if (!old_target->StoresOwnDescriptors()) { | 1778 if (!old_target->StoresOwnDescriptors()) { |
1781 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 1779 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
1782 | 1780 |
1783 old_target->SetBackPointer(GetHeap()->undefined_value()); | 1781 old_target->SetBackPointer(GetHeap()->undefined_value()); |
1784 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); | 1782 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); |
1785 // Reset the backpointer before returning failure, otherwise the map ends up | 1783 // Reset the backpointer before returning failure, otherwise the map ends up |
1786 // with an undefined backpointer and no descriptors, losing its own | 1784 // with an undefined backpointer and no descriptors, losing its own |
1787 // descriptors. Setting the backpointer always succeeds. | 1785 // descriptors. Setting the backpointer always succeeds. |
1788 old_target->SetBackPointer(old_map); | 1786 old_target->SetBackPointer(old_map); |
1789 if (maybe_failure->IsFailure()) return maybe_failure; | 1787 if (maybe_failure->IsFailure()) return maybe_failure; |
1790 | |
1791 old_map->set_owns_descriptors(true); | |
1792 } | 1788 } |
1793 | 1789 |
1794 MaybeObject* maybe_result = | 1790 MaybeObject* maybe_result = |
1795 ConvertDescriptorToField(name, new_value, attributes); | 1791 ConvertDescriptorToField(name, new_value, attributes); |
1796 if (!maybe_result->To(&result)) return maybe_result; | 1792 if (!maybe_result->To(&result)) return maybe_result; |
1797 | 1793 |
1798 if (!HasFastProperties()) return result; | 1794 if (!HasFastProperties()) return result; |
1799 | 1795 |
1800 // This method should only be used to convert existing transitions. Objects | 1796 // This method should only be used to convert existing transitions. Objects |
1801 // with the map of "new Object()" cannot have transitions in the first place. | 1797 // with the map of "new Object()" cannot have transitions in the first place. |
1802 Map* new_map = map(); | 1798 Map* new_map = map(); |
1803 ASSERT(new_map != GetIsolate()->empty_object_map()); | 1799 ASSERT(new_map != GetIsolate()->empty_object_map()); |
1804 | 1800 |
1805 // TODO(verwaest): From here on we lose existing map transitions, causing | 1801 // TODO(verwaest): From here on we lose existing map transitions, causing |
1806 // invalid back pointers. This will change once we can store multiple | 1802 // invalid back pointers. This will change once we can store multiple |
1807 // transitions with the same key. | 1803 // transitions with the same key. |
1808 | 1804 |
1809 if (old_map->owns_descriptors()) { | 1805 if (old_map->owns_descriptors()) { |
1810 // If the old map owns its own descriptors, transfer ownership to the | 1806 // If the old map owns its own descriptors, transfer ownership to the |
1811 // new_map and install its descriptors in the old_map. Since the old_map | 1807 // new_map and install its descriptors in the old_map. Since the old_map |
1812 // stores the descriptors for the new_map, remove the transition array of | 1808 // stores the descriptors for the new_map, remove the transition array of |
1813 // the new_map that is only in place to store the descriptors. | 1809 // the new_map that is only in place to store the descriptors. |
1814 old_map->transitions()->descriptors_pointer()->set_value( | 1810 old_map->transitions()->descriptors_pointer()->set_value( |
1815 new_map->instance_descriptors()); | 1811 new_map->instance_descriptors()); |
1816 new_map->ClearTransitions(GetHeap()); | 1812 new_map->ClearTransitions(GetHeap()); |
1817 old_map->set_owns_descriptors(false); | 1813 old_map->set_owns_descriptors(false); |
1818 Map* map; | |
1819 JSGlobalPropertyCell* pointer = | |
1820 old_map->transitions()->descriptors_pointer(); | |
1821 for (Object* current = old_map; | |
1822 !current->IsUndefined(); | |
1823 current = map->GetBackPointer()) { | |
1824 map = Map::cast(current); | |
1825 if (!map->HasTransitionArray()) break; | |
1826 TransitionArray* transitions = map->transitions(); | |
1827 if (transitions->descriptors_pointer() != pointer) break; | |
1828 map->SetEnumLength(Map::kInvalidEnumCache); | |
1829 } | |
1830 } else if (old_target->instance_descriptors() == | 1814 } else if (old_target->instance_descriptors() == |
1831 old_map->instance_descriptors()) { | 1815 old_map->instance_descriptors()) { |
1832 // Since the conversion above generated a new fast map with an additional | 1816 // Since the conversion above generated a new fast map with an additional |
1833 // property which can be shared as well, install this descriptor pointer | 1817 // property which can be shared as well, install this descriptor pointer |
1834 // along the entire chain of smaller maps; and remove the transition array | 1818 // along the entire chain of smaller maps; and remove the transition array |
1835 // that is only in place to hold the descriptor array in the new map. | 1819 // that is only in place to hold the descriptor array in the new map. |
1836 Map* map; | 1820 Map* map; |
1837 JSGlobalPropertyCell* new_pointer = | 1821 JSGlobalPropertyCell* new_pointer = |
1838 new_map->transitions()->descriptors_pointer(); | 1822 new_map->transitions()->descriptors_pointer(); |
1839 JSGlobalPropertyCell* old_pointer = | 1823 JSGlobalPropertyCell* old_pointer = |
(...skipping 3148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4988 result->set_is_shared(false); | 4972 result->set_is_shared(false); |
4989 result->ClearCodeCache(GetHeap()); | 4973 result->ClearCodeCache(GetHeap()); |
4990 return result; | 4974 return result; |
4991 } | 4975 } |
4992 | 4976 |
4993 | 4977 |
4994 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { | 4978 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { |
4995 // Sanity check. This path is only to be taken if the map owns its descriptor | 4979 // Sanity check. This path is only to be taken if the map owns its descriptor |
4996 // array, implying that its NumberOfOwnDescriptors equals the number of | 4980 // array, implying that its NumberOfOwnDescriptors equals the number of |
4997 // descriptors in the descriptor array. | 4981 // descriptors in the descriptor array. |
4998 ASSERT(NumberOfOwnDescriptors() == | 4982 if (NumberOfOwnDescriptors() != |
4999 instance_descriptors()->number_of_descriptors()); | 4983 instance_descriptors()->number_of_descriptors()) { |
| 4984 Isolate::Current()->PushStackTraceAndDie( |
| 4985 0xDEAD0002, GetBackPointer(), this, 0xDEAD0003); |
| 4986 } |
5000 Map* result; | 4987 Map* result; |
5001 MaybeObject* maybe_result = CopyDropDescriptors(); | 4988 MaybeObject* maybe_result = CopyDropDescriptors(); |
5002 if (!maybe_result->To(&result)) return maybe_result; | 4989 if (!maybe_result->To(&result)) return maybe_result; |
5003 | 4990 |
5004 String* name = descriptor->GetKey(); | 4991 String* name = descriptor->GetKey(); |
5005 | 4992 |
5006 TransitionArray* transitions; | 4993 TransitionArray* transitions; |
5007 MaybeObject* maybe_transitions = | 4994 MaybeObject* maybe_transitions = |
5008 AddTransition(name, result, SIMPLE_TRANSITION); | 4995 AddTransition(name, result, SIMPLE_TRANSITION); |
5009 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 4996 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5079 ? SIMPLE_TRANSITION | 5066 ? SIMPLE_TRANSITION |
5080 : FULL_TRANSITION; | 5067 : FULL_TRANSITION; |
5081 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 5068 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
5082 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 5069 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
5083 | 5070 |
5084 if (descriptors->IsEmpty()) { | 5071 if (descriptors->IsEmpty()) { |
5085 if (owns_descriptors()) { | 5072 if (owns_descriptors()) { |
5086 // If the copied map has no added fields, and the parent map owns its | 5073 // If the copied map has no added fields, and the parent map owns its |
5087 // descriptors, those descriptors have to be empty. In that case, | 5074 // descriptors, those descriptors have to be empty. In that case, |
5088 // transfer ownership of the descriptors to the new child. | 5075 // transfer ownership of the descriptors to the new child. |
5089 ASSERT(instance_descriptors()->IsEmpty()); | 5076 CHECK(instance_descriptors()->IsEmpty()); |
5090 set_owns_descriptors(false); | 5077 set_owns_descriptors(false); |
5091 } else { | 5078 } else { |
5092 // If the parent did not own its own descriptors, it may share a larger | 5079 // If the parent did not own its own descriptors, it may share a larger |
5093 // descriptors array already. In that case, force a split by setting | 5080 // descriptors array already. In that case, force a split by setting |
5094 // the descriptor array of the new map to the empty descriptor array. | 5081 // the descriptor array of the new map to the empty descriptor array. |
5095 MaybeObject* maybe_failure = | 5082 MaybeObject* maybe_failure = |
5096 result->SetDescriptors(GetHeap()->empty_descriptor_array()); | 5083 result->SetDescriptors(GetHeap()->empty_descriptor_array()); |
5097 if (maybe_failure->IsFailure()) return maybe_failure; | 5084 if (maybe_failure->IsFailure()) return maybe_failure; |
5098 } | 5085 } |
5099 } | 5086 } |
(...skipping 8450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13550 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13537 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13551 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13538 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13552 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13539 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13553 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13540 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13554 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13541 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13555 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13542 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13556 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13543 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13557 } | 13544 } |
13558 | 13545 |
13559 } } // namespace v8::internal | 13546 } } // namespace v8::internal |
OLD | NEW |