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 1562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 // Allocate new instance descriptors for the old map with map transition. | 1573 // Allocate new instance descriptors for the old map with map transition. |
1574 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); | 1574 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); |
1575 Object* r; | 1575 Object* r; |
1576 { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); | 1576 { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); |
1577 if (!maybe_r->ToObject(&r)) return maybe_r; | 1577 if (!maybe_r->ToObject(&r)) return maybe_r; |
1578 } | 1578 } |
1579 old_descriptors = DescriptorArray::cast(r); | 1579 old_descriptors = DescriptorArray::cast(r); |
1580 } | 1580 } |
1581 | 1581 |
1582 if (map()->unused_property_fields() == 0) { | 1582 if (map()->unused_property_fields() == 0) { |
1583 if (properties()->length() > MaxFastProperties()) { | 1583 if (TooManyFastProperties(properties()->length())) { |
1584 Object* obj; | 1584 Object* obj; |
1585 { MaybeObject* maybe_obj = | 1585 { MaybeObject* maybe_obj = |
1586 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1586 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1587 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1587 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1588 } | 1588 } |
1589 return AddSlowProperty(name, value, attributes); | 1589 return AddSlowProperty(name, value, attributes); |
1590 } | 1590 } |
1591 // Make room for the new value | 1591 // Make room for the new value |
1592 Object* values; | 1592 Object* values; |
1593 { MaybeObject* maybe_values = | 1593 { MaybeObject* maybe_values = |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1823 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1823 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
1824 map()->SetBackPointer(old_map); | 1824 map()->SetBackPointer(old_map); |
1825 return result; | 1825 return result; |
1826 } | 1826 } |
1827 | 1827 |
1828 | 1828 |
1829 MaybeObject* JSObject::ConvertDescriptorToField(String* name, | 1829 MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
1830 Object* new_value, | 1830 Object* new_value, |
1831 PropertyAttributes attributes) { | 1831 PropertyAttributes attributes) { |
1832 if (map()->unused_property_fields() == 0 && | 1832 if (map()->unused_property_fields() == 0 && |
1833 properties()->length() > MaxFastProperties()) { | 1833 TooManyFastProperties(properties()->length())) { |
1834 Object* obj; | 1834 Object* obj; |
1835 { MaybeObject* maybe_obj = | 1835 { MaybeObject* maybe_obj = |
1836 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1836 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1837 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1837 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1838 } | 1838 } |
1839 return ReplaceSlowProperty(name, new_value, attributes); | 1839 return ReplaceSlowProperty(name, new_value, attributes); |
1840 } | 1840 } |
1841 | 1841 |
1842 int index = map()->NextFreePropertyIndex(); | 1842 int index = map()->NextFreePropertyIndex(); |
1843 FieldDescriptor new_field(name, index, attributes); | 1843 FieldDescriptor new_field(name, index, attributes); |
(...skipping 3191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5035 } | 5035 } |
5036 Object* descriptors; | 5036 Object* descriptors; |
5037 { MaybeObject* maybe_descriptors = | 5037 { MaybeObject* maybe_descriptors = |
5038 instance_descriptors()->RemoveTransitions(); | 5038 instance_descriptors()->RemoveTransitions(); |
5039 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; | 5039 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
5040 } | 5040 } |
5041 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 5041 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
5042 return new_map; | 5042 return new_map; |
5043 } | 5043 } |
5044 | 5044 |
| 5045 |
5045 void Map::UpdateCodeCache(Handle<Map> map, | 5046 void Map::UpdateCodeCache(Handle<Map> map, |
5046 Handle<String> name, | 5047 Handle<String> name, |
5047 Handle<Code> code) { | 5048 Handle<Code> code) { |
5048 Isolate* isolate = map->GetIsolate(); | 5049 Isolate* isolate = map->GetIsolate(); |
5049 CALL_HEAP_FUNCTION_VOID(isolate, | 5050 CALL_HEAP_FUNCTION_VOID(isolate, |
5050 map->UpdateCodeCache(*name, *code)); | 5051 map->UpdateCodeCache(*name, *code)); |
5051 } | 5052 } |
5052 | 5053 |
5053 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 5054 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
5054 // Allocate the code cache if not present. | 5055 // Allocate the code cache if not present. |
(...skipping 2550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7605 if (!shared_info->script()->IsScript()) return false; | 7606 if (!shared_info->script()->IsScript()) return false; |
7606 if (shared_info->optimization_disabled()) return false; | 7607 if (shared_info->optimization_disabled()) return false; |
7607 Code* code = shared_info->code(); | 7608 Code* code = shared_info->code(); |
7608 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 7609 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
7609 // If we never ran this (unlikely) then lets try to optimize it. | 7610 // If we never ran this (unlikely) then lets try to optimize it. |
7610 if (code->kind() != Code::FUNCTION) return true; | 7611 if (code->kind() != Code::FUNCTION) return true; |
7611 return code->optimizable(); | 7612 return code->optimizable(); |
7612 } | 7613 } |
7613 | 7614 |
7614 | 7615 |
| 7616 MaybeObject* JSObject::OptimizeAsPrototype() { |
| 7617 if (IsGlobalObject()) return this; |
| 7618 |
| 7619 // Make sure prototypes are fast objects and their maps have the bit set |
| 7620 // so they remain fast. |
| 7621 Map* proto_map = map(); |
| 7622 if (!proto_map->used_for_prototype()) { |
| 7623 if (!HasFastProperties()) { |
| 7624 MaybeObject* new_proto = TransformToFastProperties(0); |
| 7625 if (new_proto->IsFailure()) return new_proto; |
| 7626 ASSERT(new_proto == this); |
| 7627 proto_map = map(); |
| 7628 if (!proto_map->is_shared()) { |
| 7629 proto_map->set_used_for_prototype(true); |
| 7630 } |
| 7631 } else { |
| 7632 Heap* heap = GetHeap(); |
| 7633 // We use the hole value as a singleton key in the prototype transition |
| 7634 // map so that we don't multiply the number of maps unnecessarily. |
| 7635 Map* new_map = |
| 7636 proto_map->GetPrototypeTransition(heap->the_hole_value()); |
| 7637 if (new_map == NULL) { |
| 7638 MaybeObject* maybe_new_map = proto_map->CopyDropTransitions(); |
| 7639 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; |
| 7640 new_map->set_used_for_prototype(true); |
| 7641 MaybeObject* ok = |
| 7642 proto_map->PutPrototypeTransition(heap->the_hole_value(), |
| 7643 new_map); |
| 7644 if (ok->IsFailure()) return ok; |
| 7645 } |
| 7646 ASSERT(!proto_map->is_shared() && !new_map->is_shared()); |
| 7647 set_map(new_map); |
| 7648 } |
| 7649 } |
| 7650 return this; |
| 7651 } |
| 7652 |
| 7653 |
7615 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { | 7654 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
7616 ASSERT(value->IsJSReceiver()); | 7655 ASSERT(value->IsJSReceiver()); |
7617 Heap* heap = GetHeap(); | 7656 Heap* heap = GetHeap(); |
| 7657 |
| 7658 // First some logic for the map of the prototype to make sure the |
| 7659 // used_for_prototype flag is set. |
| 7660 if (value->IsJSObject()) { |
| 7661 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); |
| 7662 if (ok->IsFailure()) return ok; |
| 7663 } |
| 7664 |
| 7665 // Now some logic for the maps of the objects that are created by using this |
| 7666 // function as a constructor. |
7618 if (has_initial_map()) { | 7667 if (has_initial_map()) { |
7619 // If the function has allocated the initial map | 7668 // If the function has allocated the initial map |
7620 // replace it with a copy containing the new prototype. | 7669 // replace it with a copy containing the new prototype. |
7621 Map* new_map; | 7670 Map* new_map; |
7622 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); | 7671 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); |
7623 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 7672 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
7624 new_map->set_prototype(value); | 7673 new_map->set_prototype(value); |
7625 MaybeObject* maybe_object = | 7674 MaybeObject* maybe_object = |
7626 set_initial_map_and_cache_transitions(new_map); | 7675 set_initial_map_and_cache_transitions(new_map); |
7627 if (maybe_object->IsFailure()) return maybe_object; | 7676 if (maybe_object->IsFailure()) return maybe_object; |
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8779 } | 8828 } |
8780 | 8829 |
8781 | 8830 |
8782 MaybeObject* JSArray::SetElementsLength(Object* len) { | 8831 MaybeObject* JSArray::SetElementsLength(Object* len) { |
8783 // We should never end in here with a pixel or external array. | 8832 // We should never end in here with a pixel or external array. |
8784 ASSERT(AllowsSetElementsLength()); | 8833 ASSERT(AllowsSetElementsLength()); |
8785 return GetElementsAccessor()->SetLength(this, len); | 8834 return GetElementsAccessor()->SetLength(this, len); |
8786 } | 8835 } |
8787 | 8836 |
8788 | 8837 |
8789 Object* Map::GetPrototypeTransition(Object* prototype) { | 8838 Map* Map::GetPrototypeTransition(Object* prototype) { |
8790 FixedArray* cache = prototype_transitions(); | 8839 FixedArray* cache = prototype_transitions(); |
8791 int number_of_transitions = NumberOfProtoTransitions(); | 8840 int number_of_transitions = NumberOfProtoTransitions(); |
8792 const int proto_offset = | 8841 const int proto_offset = |
8793 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 8842 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
8794 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 8843 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
8795 const int step = kProtoTransitionElementsPerEntry; | 8844 const int step = kProtoTransitionElementsPerEntry; |
8796 for (int i = 0; i < number_of_transitions; i++) { | 8845 for (int i = 0; i < number_of_transitions; i++) { |
8797 if (cache->get(proto_offset + i * step) == prototype) { | 8846 if (cache->get(proto_offset + i * step) == prototype) { |
8798 Object* map = cache->get(map_offset + i * step); | 8847 Object* map = cache->get(map_offset + i * step); |
8799 ASSERT(map->IsMap()); | 8848 return Map::cast(map); |
8800 return map; | |
8801 } | 8849 } |
8802 } | 8850 } |
8803 return NULL; | 8851 return NULL; |
8804 } | 8852 } |
8805 | 8853 |
8806 | 8854 |
8807 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { | 8855 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { |
8808 ASSERT(map->IsMap()); | 8856 ASSERT(map->IsMap()); |
8809 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); | 8857 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); |
8810 // Don't cache prototype transition if this map is shared. | 8858 // Don't cache prototype transition if this map is shared. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8898 current_proto = current_proto->GetPrototype(); | 8946 current_proto = current_proto->GetPrototype(); |
8899 } | 8947 } |
8900 } | 8948 } |
8901 | 8949 |
8902 // Set the new prototype of the object. | 8950 // Set the new prototype of the object. |
8903 Map* map = real_receiver->map(); | 8951 Map* map = real_receiver->map(); |
8904 | 8952 |
8905 // Nothing to do if prototype is already set. | 8953 // Nothing to do if prototype is already set. |
8906 if (map->prototype() == value) return value; | 8954 if (map->prototype() == value) return value; |
8907 | 8955 |
8908 Object* new_map = map->GetPrototypeTransition(value); | 8956 if (value->IsJSObject()) { |
| 8957 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); |
| 8958 if (ok->IsFailure()) return ok; |
| 8959 } |
| 8960 |
| 8961 Map* new_map = map->GetPrototypeTransition(value); |
8909 if (new_map == NULL) { | 8962 if (new_map == NULL) { |
8910 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); | 8963 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); |
8911 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 8964 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; |
8912 } | 8965 } |
8913 | 8966 |
8914 { MaybeObject* maybe_new_cache = | 8967 { MaybeObject* maybe_new_cache = |
8915 map->PutPrototypeTransition(value, Map::cast(new_map)); | 8968 map->PutPrototypeTransition(value, new_map); |
8916 if (maybe_new_cache->IsFailure()) return maybe_new_cache; | 8969 if (maybe_new_cache->IsFailure()) return maybe_new_cache; |
8917 } | 8970 } |
8918 | 8971 |
8919 Map::cast(new_map)->set_prototype(value); | 8972 new_map->set_prototype(value); |
8920 } | 8973 } |
8921 ASSERT(Map::cast(new_map)->prototype() == value); | 8974 ASSERT(new_map->prototype() == value); |
8922 real_receiver->set_map(Map::cast(new_map)); | 8975 real_receiver->set_map(new_map); |
8923 | 8976 |
8924 heap->ClearInstanceofCache(); | 8977 heap->ClearInstanceofCache(); |
8925 ASSERT(size == Size()); | 8978 ASSERT(size == Size()); |
8926 return value; | 8979 return value; |
8927 } | 8980 } |
8928 | 8981 |
8929 | 8982 |
8930 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 8983 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
8931 uint32_t first_arg, | 8984 uint32_t first_arg, |
8932 uint32_t arg_count, | 8985 uint32_t arg_count, |
(...skipping 4302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13235 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13288 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13236 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13289 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13237 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13290 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13238 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13291 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13239 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13292 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13240 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13293 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13241 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13294 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13242 } | 13295 } |
13243 | 13296 |
13244 } } // namespace v8::internal | 13297 } } // namespace v8::internal |
OLD | NEW |