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 (TooManyFastProperties(properties()->length())) { | 1583 if (properties()->length() > MaxFastProperties()) { |
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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1826 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
1827 map()->SetBackPointer(old_map); | 1827 map()->SetBackPointer(old_map); |
1828 return result; | 1828 return result; |
1829 } | 1829 } |
1830 | 1830 |
1831 | 1831 |
1832 MaybeObject* JSObject::ConvertDescriptorToField(String* name, | 1832 MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
1833 Object* new_value, | 1833 Object* new_value, |
1834 PropertyAttributes attributes) { | 1834 PropertyAttributes attributes) { |
1835 if (map()->unused_property_fields() == 0 && | 1835 if (map()->unused_property_fields() == 0 && |
1836 TooManyFastProperties(properties()->length())) { | 1836 properties()->length() > MaxFastProperties()) { |
1837 Object* obj; | 1837 Object* obj; |
1838 { MaybeObject* maybe_obj = | 1838 { MaybeObject* maybe_obj = |
1839 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1839 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1840 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1840 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1841 } | 1841 } |
1842 return ReplaceSlowProperty(name, new_value, attributes); | 1842 return ReplaceSlowProperty(name, new_value, attributes); |
1843 } | 1843 } |
1844 | 1844 |
1845 int index = map()->NextFreePropertyIndex(); | 1845 int index = map()->NextFreePropertyIndex(); |
1846 FieldDescriptor new_field(name, index, attributes); | 1846 FieldDescriptor new_field(name, index, attributes); |
(...skipping 3185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5032 } | 5032 } |
5033 Object* descriptors; | 5033 Object* descriptors; |
5034 { MaybeObject* maybe_descriptors = | 5034 { MaybeObject* maybe_descriptors = |
5035 instance_descriptors()->RemoveTransitions(); | 5035 instance_descriptors()->RemoveTransitions(); |
5036 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; | 5036 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
5037 } | 5037 } |
5038 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 5038 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
5039 return new_map; | 5039 return new_map; |
5040 } | 5040 } |
5041 | 5041 |
5042 | |
5043 void Map::UpdateCodeCache(Handle<Map> map, | 5042 void Map::UpdateCodeCache(Handle<Map> map, |
5044 Handle<String> name, | 5043 Handle<String> name, |
5045 Handle<Code> code) { | 5044 Handle<Code> code) { |
5046 Isolate* isolate = map->GetIsolate(); | 5045 Isolate* isolate = map->GetIsolate(); |
5047 CALL_HEAP_FUNCTION_VOID(isolate, | 5046 CALL_HEAP_FUNCTION_VOID(isolate, |
5048 map->UpdateCodeCache(*name, *code)); | 5047 map->UpdateCodeCache(*name, *code)); |
5049 } | 5048 } |
5050 | 5049 |
5051 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 5050 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
5052 // Allocate the code cache if not present. | 5051 // Allocate the code cache if not present. |
(...skipping 2562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7615 if (!shared_info->script()->IsScript()) return false; | 7614 if (!shared_info->script()->IsScript()) return false; |
7616 if (shared_info->optimization_disabled()) return false; | 7615 if (shared_info->optimization_disabled()) return false; |
7617 Code* code = shared_info->code(); | 7616 Code* code = shared_info->code(); |
7618 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 7617 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
7619 // If we never ran this (unlikely) then lets try to optimize it. | 7618 // If we never ran this (unlikely) then lets try to optimize it. |
7620 if (code->kind() != Code::FUNCTION) return true; | 7619 if (code->kind() != Code::FUNCTION) return true; |
7621 return code->optimizable(); | 7620 return code->optimizable(); |
7622 } | 7621 } |
7623 | 7622 |
7624 | 7623 |
7625 MaybeObject* JSObject::OptimizeAsPrototype() { | |
7626 if (IsGlobalObject()) return this; | |
7627 | |
7628 // Make sure prototypes are fast objects and their maps have the bit set | |
7629 // so they remain fast. | |
7630 Map* proto_map = map(); | |
7631 if (!proto_map->used_for_prototype()) { | |
7632 if (!HasFastProperties()) { | |
7633 MaybeObject* new_proto = TransformToFastProperties(0); | |
7634 if (new_proto->IsFailure()) return new_proto; | |
7635 ASSERT(new_proto == this); | |
7636 proto_map = map(); | |
7637 if (!proto_map->is_shared()) { | |
7638 proto_map->set_used_for_prototype(true); | |
7639 } | |
7640 } else { | |
7641 Heap* heap = GetHeap(); | |
7642 // We use the hole value as a singleton key in the prototype transition | |
7643 // map so that we don't multiply the number of maps unnecessarily. | |
7644 Map* new_map = | |
7645 proto_map->GetPrototypeTransition(heap->the_hole_value()); | |
7646 if (new_map == NULL) { | |
7647 MaybeObject* maybe_new_map = proto_map->CopyDropTransitions(); | |
7648 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | |
7649 new_map->set_used_for_prototype(true); | |
7650 MaybeObject* ok = | |
7651 proto_map->PutPrototypeTransition(heap->the_hole_value(), | |
7652 new_map); | |
7653 if (ok->IsFailure()) return ok; | |
7654 } | |
7655 ASSERT(!proto_map->is_shared() && !new_map->is_shared()); | |
7656 set_map(new_map); | |
7657 } | |
7658 } | |
7659 return this; | |
7660 } | |
7661 | |
7662 | |
7663 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { | 7624 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
7664 ASSERT(value->IsJSReceiver()); | 7625 ASSERT(value->IsJSReceiver()); |
7665 Heap* heap = GetHeap(); | 7626 Heap* heap = GetHeap(); |
7666 | |
7667 // First some logic for the map of the prototype to make sure the | |
7668 // used_for_prototype flag is set. | |
7669 if (value->IsJSObject()) { | |
7670 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | |
7671 if (ok->IsFailure()) return ok; | |
7672 } | |
7673 | |
7674 // Now some logic for the maps of the objects that are created by using this | |
7675 // function as a constructor. | |
7676 if (has_initial_map()) { | 7627 if (has_initial_map()) { |
7677 // If the function has allocated the initial map | 7628 // If the function has allocated the initial map |
7678 // replace it with a copy containing the new prototype. | 7629 // replace it with a copy containing the new prototype. |
7679 Map* new_map; | 7630 Map* new_map; |
7680 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); | 7631 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); |
7681 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 7632 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
7682 new_map->set_prototype(value); | 7633 new_map->set_prototype(value); |
7683 MaybeObject* maybe_object = | 7634 MaybeObject* maybe_object = |
7684 set_initial_map_and_cache_transitions(new_map); | 7635 set_initial_map_and_cache_transitions(new_map); |
7685 if (maybe_object->IsFailure()) return maybe_object; | 7636 if (maybe_object->IsFailure()) return maybe_object; |
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8837 } | 8788 } |
8838 | 8789 |
8839 | 8790 |
8840 MaybeObject* JSArray::SetElementsLength(Object* len) { | 8791 MaybeObject* JSArray::SetElementsLength(Object* len) { |
8841 // We should never end in here with a pixel or external array. | 8792 // We should never end in here with a pixel or external array. |
8842 ASSERT(AllowsSetElementsLength()); | 8793 ASSERT(AllowsSetElementsLength()); |
8843 return GetElementsAccessor()->SetLength(this, len); | 8794 return GetElementsAccessor()->SetLength(this, len); |
8844 } | 8795 } |
8845 | 8796 |
8846 | 8797 |
8847 Map* Map::GetPrototypeTransition(Object* prototype) { | 8798 Object* Map::GetPrototypeTransition(Object* prototype) { |
8848 FixedArray* cache = prototype_transitions(); | 8799 FixedArray* cache = prototype_transitions(); |
8849 int number_of_transitions = NumberOfProtoTransitions(); | 8800 int number_of_transitions = NumberOfProtoTransitions(); |
8850 const int proto_offset = | 8801 const int proto_offset = |
8851 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 8802 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
8852 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 8803 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
8853 const int step = kProtoTransitionElementsPerEntry; | 8804 const int step = kProtoTransitionElementsPerEntry; |
8854 for (int i = 0; i < number_of_transitions; i++) { | 8805 for (int i = 0; i < number_of_transitions; i++) { |
8855 if (cache->get(proto_offset + i * step) == prototype) { | 8806 if (cache->get(proto_offset + i * step) == prototype) { |
8856 Object* map = cache->get(map_offset + i * step); | 8807 Object* map = cache->get(map_offset + i * step); |
8857 return Map::cast(map); | 8808 ASSERT(map->IsMap()); |
| 8809 return map; |
8858 } | 8810 } |
8859 } | 8811 } |
8860 return NULL; | 8812 return NULL; |
8861 } | 8813 } |
8862 | 8814 |
8863 | 8815 |
8864 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { | 8816 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { |
8865 ASSERT(map->IsMap()); | 8817 ASSERT(map->IsMap()); |
8866 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); | 8818 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); |
8867 // 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... |
8955 current_proto = current_proto->GetPrototype(); | 8907 current_proto = current_proto->GetPrototype(); |
8956 } | 8908 } |
8957 } | 8909 } |
8958 | 8910 |
8959 // Set the new prototype of the object. | 8911 // Set the new prototype of the object. |
8960 Map* map = real_receiver->map(); | 8912 Map* map = real_receiver->map(); |
8961 | 8913 |
8962 // Nothing to do if prototype is already set. | 8914 // Nothing to do if prototype is already set. |
8963 if (map->prototype() == value) return value; | 8915 if (map->prototype() == value) return value; |
8964 | 8916 |
8965 if (value->IsJSObject()) { | 8917 Object* new_map = map->GetPrototypeTransition(value); |
8966 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | |
8967 if (ok->IsFailure()) return ok; | |
8968 } | |
8969 | |
8970 Map* new_map = map->GetPrototypeTransition(value); | |
8971 if (new_map == NULL) { | 8918 if (new_map == NULL) { |
8972 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); | 8919 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); |
8973 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | 8920 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
8974 } | 8921 } |
8975 | 8922 |
8976 { MaybeObject* maybe_new_cache = | 8923 { MaybeObject* maybe_new_cache = |
8977 map->PutPrototypeTransition(value, new_map); | 8924 map->PutPrototypeTransition(value, Map::cast(new_map)); |
8978 if (maybe_new_cache->IsFailure()) return maybe_new_cache; | 8925 if (maybe_new_cache->IsFailure()) return maybe_new_cache; |
8979 } | 8926 } |
8980 | 8927 |
8981 new_map->set_prototype(value); | 8928 Map::cast(new_map)->set_prototype(value); |
8982 } | 8929 } |
8983 ASSERT(new_map->prototype() == value); | 8930 ASSERT(Map::cast(new_map)->prototype() == value); |
8984 real_receiver->set_map(new_map); | 8931 real_receiver->set_map(Map::cast(new_map)); |
8985 | 8932 |
8986 heap->ClearInstanceofCache(); | 8933 heap->ClearInstanceofCache(); |
8987 ASSERT(size == Size()); | 8934 ASSERT(size == Size()); |
8988 return value; | 8935 return value; |
8989 } | 8936 } |
8990 | 8937 |
8991 | 8938 |
8992 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 8939 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
8993 uint32_t first_arg, | 8940 uint32_t first_arg, |
8994 uint32_t arg_count, | 8941 uint32_t arg_count, |
(...skipping 4302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13297 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13244 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13298 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13245 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13299 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13246 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13300 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13247 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13301 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13248 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13302 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13249 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13303 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13250 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13304 } | 13251 } |
13305 | 13252 |
13306 } } // namespace v8::internal | 13253 } } // namespace v8::internal |
OLD | NEW |