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

Side by Side Diff: src/objects.cc

Issue 10448011: Keep track of which maps are associated with prototype objects (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 7 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
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 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698