Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/objects.cc

Issue 10532021: Keep track of which maps are associated with prototype objects so we can tune the fast-case vs. has… (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698