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 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1572 // Allocate new instance descriptors for the old map with map transition. | 1572 // Allocate new instance descriptors for the old map with map transition. |
1573 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); | 1573 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); |
1574 Object* r; | 1574 Object* r; |
1575 { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); | 1575 { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); |
1576 if (!maybe_r->ToObject(&r)) return maybe_r; | 1576 if (!maybe_r->ToObject(&r)) return maybe_r; |
1577 } | 1577 } |
1578 old_descriptors = DescriptorArray::cast(r); | 1578 old_descriptors = DescriptorArray::cast(r); |
1579 } | 1579 } |
1580 | 1580 |
1581 if (map()->unused_property_fields() == 0) { | 1581 if (map()->unused_property_fields() == 0) { |
1582 if (properties()->length() > MaxFastProperties()) { | 1582 if (TooManyFastProperties(properties()->length())) { |
1583 Object* obj; | 1583 Object* obj; |
1584 { MaybeObject* maybe_obj = | 1584 { MaybeObject* maybe_obj = |
1585 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1585 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1586 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1586 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1587 } | 1587 } |
1588 return AddSlowProperty(name, value, attributes); | 1588 return AddSlowProperty(name, value, attributes); |
1589 } | 1589 } |
1590 // Make room for the new value | 1590 // Make room for the new value |
1591 Object* values; | 1591 Object* values; |
1592 { MaybeObject* maybe_values = | 1592 { MaybeObject* maybe_values = |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1630 | 1630 |
1631 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); | 1631 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); |
1632 Map::cast(new_map)->set_instance_descriptors(descriptors); | 1632 Map::cast(new_map)->set_instance_descriptors(descriptors); |
1633 Map* old_map = map(); | 1633 Map* old_map = map(); |
1634 set_map(Map::cast(new_map)); | 1634 set_map(Map::cast(new_map)); |
1635 | 1635 |
1636 // If the old map is the global object map (from new Object()), | 1636 // If the old map is the global object map (from new Object()), |
1637 // then transitions are not added to it, so we are done. | 1637 // then transitions are not added to it, so we are done. |
1638 Heap* heap = GetHeap(); | 1638 Heap* heap = GetHeap(); |
1639 if (old_map == heap->isolate()->context()->global_context()-> | 1639 if (old_map == heap->isolate()->context()->global_context()-> |
1640 object_function()->map()) { | 1640 object_function()->map()) { |
Michael Starzinger
2012/05/30 14:08:03
Indentation seems off.
Erik Corry
2012/05/30 15:24:13
Done.
| |
1641 return function; | 1641 return function; |
1642 } | 1642 } |
1643 | 1643 |
1644 // Do not add CONSTANT_TRANSITIONS to global objects | 1644 // Do not add CONSTANT_TRANSITIONS to global objects |
1645 if (IsGlobalObject()) { | 1645 if (IsGlobalObject()) { |
1646 return function; | 1646 return function; |
1647 } | 1647 } |
1648 | 1648 |
1649 // Add a CONSTANT_TRANSITION descriptor to the old map, | 1649 // Add a CONSTANT_TRANSITION descriptor to the old map, |
1650 // so future assignments to this property on other objects | 1650 // so future assignments to this property on other objects |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1825 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1825 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
1826 map()->SetBackPointer(old_map); | 1826 map()->SetBackPointer(old_map); |
1827 return result; | 1827 return result; |
1828 } | 1828 } |
1829 | 1829 |
1830 | 1830 |
1831 MaybeObject* JSObject::ConvertDescriptorToField(String* name, | 1831 MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
1832 Object* new_value, | 1832 Object* new_value, |
1833 PropertyAttributes attributes) { | 1833 PropertyAttributes attributes) { |
1834 if (map()->unused_property_fields() == 0 && | 1834 if (map()->unused_property_fields() == 0 && |
1835 properties()->length() > MaxFastProperties()) { | 1835 TooManyFastProperties(properties()->length())) { |
1836 Object* obj; | 1836 Object* obj; |
1837 { MaybeObject* maybe_obj = | 1837 { MaybeObject* maybe_obj = |
1838 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1838 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1839 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1839 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1840 } | 1840 } |
1841 return ReplaceSlowProperty(name, new_value, attributes); | 1841 return ReplaceSlowProperty(name, new_value, attributes); |
1842 } | 1842 } |
1843 | 1843 |
1844 int index = map()->NextFreePropertyIndex(); | 1844 int index = map()->NextFreePropertyIndex(); |
1845 FieldDescriptor new_field(name, index, attributes); | 1845 FieldDescriptor new_field(name, index, attributes); |
(...skipping 3177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5023 } | 5023 } |
5024 Object* descriptors; | 5024 Object* descriptors; |
5025 { MaybeObject* maybe_descriptors = | 5025 { MaybeObject* maybe_descriptors = |
5026 instance_descriptors()->RemoveTransitions(); | 5026 instance_descriptors()->RemoveTransitions(); |
5027 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; | 5027 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
5028 } | 5028 } |
5029 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 5029 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
5030 return new_map; | 5030 return new_map; |
5031 } | 5031 } |
5032 | 5032 |
5033 | |
5033 void Map::UpdateCodeCache(Handle<Map> map, | 5034 void Map::UpdateCodeCache(Handle<Map> map, |
5034 Handle<String> name, | 5035 Handle<String> name, |
5035 Handle<Code> code) { | 5036 Handle<Code> code) { |
5036 Isolate* isolate = map->GetIsolate(); | 5037 Isolate* isolate = map->GetIsolate(); |
5037 CALL_HEAP_FUNCTION_VOID(isolate, | 5038 CALL_HEAP_FUNCTION_VOID(isolate, |
5038 map->UpdateCodeCache(*name, *code)); | 5039 map->UpdateCodeCache(*name, *code)); |
5039 } | 5040 } |
5040 | 5041 |
5041 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 5042 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
5042 // Allocate the code cache if not present. | 5043 // Allocate the code cache if not present. |
(...skipping 2523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7566 if (!shared_info->script()->IsScript()) return false; | 7567 if (!shared_info->script()->IsScript()) return false; |
7567 if (shared_info->optimization_disabled()) return false; | 7568 if (shared_info->optimization_disabled()) return false; |
7568 Code* code = shared_info->code(); | 7569 Code* code = shared_info->code(); |
7569 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 7570 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
7570 // If we never ran this (unlikely) then lets try to optimize it. | 7571 // If we never ran this (unlikely) then lets try to optimize it. |
7571 if (code->kind() != Code::FUNCTION) return true; | 7572 if (code->kind() != Code::FUNCTION) return true; |
7572 return code->optimizable(); | 7573 return code->optimizable(); |
7573 } | 7574 } |
7574 | 7575 |
7575 | 7576 |
7577 MaybeObject* JSObject::OptimizeAsPrototype() { | |
7578 if (IsGlobalObject()) return this; | |
7579 | |
7580 // Make sure prototypes are fast objects and their maps have the bit set | |
7581 // so they remain fast. | |
7582 Map* proto_map = map(); | |
7583 if (!proto_map->used_for_prototype()) { | |
7584 if (!HasFastProperties()) { | |
7585 MaybeObject* new_proto = TransformToFastProperties(0); | |
7586 if (new_proto->IsFailure()) return new_proto; | |
7587 ASSERT(new_proto == this); | |
7588 proto_map = map(); | |
7589 if (!proto_map->is_shared()) { | |
7590 proto_map->set_used_for_prototype(true); | |
7591 } | |
7592 } else { | |
7593 Heap* heap = GetHeap(); | |
7594 // We use the hole value as a singleton key in the prototype transition | |
7595 // map so that we don't multiply the number of maps unnecessarily. | |
7596 Map* new_map = | |
7597 proto_map->GetPrototypeTransition(heap->the_hole_value()); | |
7598 if (new_map == NULL) { | |
7599 MaybeObject* maybe_new_map = proto_map->CopyDropTransitions(); | |
7600 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | |
7601 new_map->set_used_for_prototype(true); | |
7602 MaybeObject* ok = | |
7603 proto_map->PutPrototypeTransition(heap->the_hole_value(), | |
7604 new_map); | |
7605 if (ok->IsFailure()) return ok; | |
7606 } | |
7607 ASSERT(!proto_map->is_shared() && !new_map->is_shared()); | |
7608 set_map(new_map); | |
7609 } | |
7610 } | |
7611 return this; | |
7612 } | |
7613 | |
7614 | |
7576 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { | 7615 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
7577 ASSERT(value->IsJSReceiver()); | 7616 ASSERT(value->IsJSReceiver()); |
7578 Heap* heap = GetHeap(); | 7617 Heap* heap = GetHeap(); |
7618 | |
7619 // First some logic for the map of the prototype to make sure the | |
7620 // used_for_prototype flag is set. | |
7621 if (value->IsJSObject()) { | |
7622 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | |
7623 if (ok->IsFailure()) return ok; | |
7624 } | |
7625 | |
7626 // Now some logic for the maps of the objects that are created by using this | |
7627 // function as a constructor. | |
7579 if (has_initial_map()) { | 7628 if (has_initial_map()) { |
7580 // If the function has allocated the initial map | 7629 // If the function has allocated the initial map |
7581 // replace it with a copy containing the new prototype. | 7630 // replace it with a copy containing the new prototype. |
7582 Map* new_map; | 7631 Map* new_map; |
7583 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); | 7632 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); |
7584 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 7633 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
7585 new_map->set_prototype(value); | 7634 new_map->set_prototype(value); |
7586 MaybeObject* maybe_object = | 7635 MaybeObject* maybe_object = |
7587 set_initial_map_and_cache_transitions(new_map); | 7636 set_initial_map_and_cache_transitions(new_map); |
7588 if (maybe_object->IsFailure()) return maybe_object; | 7637 if (maybe_object->IsFailure()) return maybe_object; |
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8740 } | 8789 } |
8741 | 8790 |
8742 | 8791 |
8743 MaybeObject* JSArray::SetElementsLength(Object* len) { | 8792 MaybeObject* JSArray::SetElementsLength(Object* len) { |
8744 // We should never end in here with a pixel or external array. | 8793 // We should never end in here with a pixel or external array. |
8745 ASSERT(AllowsSetElementsLength()); | 8794 ASSERT(AllowsSetElementsLength()); |
8746 return GetElementsAccessor()->SetLength(this, len); | 8795 return GetElementsAccessor()->SetLength(this, len); |
8747 } | 8796 } |
8748 | 8797 |
8749 | 8798 |
8750 Object* Map::GetPrototypeTransition(Object* prototype) { | 8799 Map* Map::GetPrototypeTransition(Object* prototype) { |
8751 FixedArray* cache = prototype_transitions(); | 8800 FixedArray* cache = prototype_transitions(); |
8752 int number_of_transitions = NumberOfProtoTransitions(); | 8801 int number_of_transitions = NumberOfProtoTransitions(); |
8753 const int proto_offset = | 8802 const int proto_offset = |
8754 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 8803 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
8755 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 8804 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
8756 const int step = kProtoTransitionElementsPerEntry; | 8805 const int step = kProtoTransitionElementsPerEntry; |
8757 for (int i = 0; i < number_of_transitions; i++) { | 8806 for (int i = 0; i < number_of_transitions; i++) { |
8758 if (cache->get(proto_offset + i * step) == prototype) { | 8807 if (cache->get(proto_offset + i * step) == prototype) { |
8759 Object* map = cache->get(map_offset + i * step); | 8808 Object* map = cache->get(map_offset + i * step); |
8760 ASSERT(map->IsMap()); | 8809 return Map::cast(map); |
8761 return map; | |
8762 } | 8810 } |
8763 } | 8811 } |
8764 return NULL; | 8812 return NULL; |
8765 } | 8813 } |
8766 | 8814 |
8767 | 8815 |
8768 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { | 8816 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { |
8769 ASSERT(map->IsMap()); | 8817 ASSERT(map->IsMap()); |
8770 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); | 8818 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); |
8771 // Don't cache prototype transition if this map is shared. | 8819 // Don't cache prototype transition if this map is shared. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8859 current_proto = current_proto->GetPrototype(); | 8907 current_proto = current_proto->GetPrototype(); |
8860 } | 8908 } |
8861 } | 8909 } |
8862 | 8910 |
8863 // Set the new prototype of the object. | 8911 // Set the new prototype of the object. |
8864 Map* map = real_receiver->map(); | 8912 Map* map = real_receiver->map(); |
8865 | 8913 |
8866 // Nothing to do if prototype is already set. | 8914 // Nothing to do if prototype is already set. |
8867 if (map->prototype() == value) return value; | 8915 if (map->prototype() == value) return value; |
8868 | 8916 |
8869 Object* new_map = map->GetPrototypeTransition(value); | 8917 if (value->IsJSObject()) { |
8918 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | |
8919 if (ok->IsFailure()) return ok; | |
8920 } | |
8921 | |
8922 Map* new_map = map->GetPrototypeTransition(value); | |
8870 if (new_map == NULL) { | 8923 if (new_map == NULL) { |
8871 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); | 8924 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); |
8872 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 8925 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; |
8873 } | 8926 } |
8874 | 8927 |
8875 { MaybeObject* maybe_new_cache = | 8928 { MaybeObject* maybe_new_cache = |
8876 map->PutPrototypeTransition(value, Map::cast(new_map)); | 8929 map->PutPrototypeTransition(value, new_map); |
8877 if (maybe_new_cache->IsFailure()) return maybe_new_cache; | 8930 if (maybe_new_cache->IsFailure()) return maybe_new_cache; |
8878 } | 8931 } |
8879 | 8932 |
8880 Map::cast(new_map)->set_prototype(value); | 8933 new_map->set_prototype(value); |
8881 } | 8934 } |
8882 ASSERT(Map::cast(new_map)->prototype() == value); | 8935 ASSERT(new_map->prototype() == value); |
8883 real_receiver->set_map(Map::cast(new_map)); | 8936 real_receiver->set_map(new_map); |
8884 | 8937 |
8885 heap->ClearInstanceofCache(); | 8938 heap->ClearInstanceofCache(); |
8886 ASSERT(size == Size()); | 8939 ASSERT(size == Size()); |
8887 return value; | 8940 return value; |
8888 } | 8941 } |
8889 | 8942 |
8890 | 8943 |
8891 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 8944 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
8892 uint32_t first_arg, | 8945 uint32_t first_arg, |
8893 uint32_t arg_count, | 8946 uint32_t arg_count, |
(...skipping 4302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13196 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13249 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13197 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13250 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13198 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13251 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13199 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13252 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13200 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13253 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13201 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13254 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13202 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13255 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13203 } | 13256 } |
13204 | 13257 |
13205 } } // namespace v8::internal | 13258 } } // namespace v8::internal |
OLD | NEW |