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

Side by Side Diff: src/objects.cc

Issue 238543005: Move property addition code from JSObject to Map (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed last comments Created 6 years, 8 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') | test/cctest/test-heap.cc » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 1806 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 // If the constructor is not present, return "Object". 1817 // If the constructor is not present, return "Object".
1818 return GetHeap()->Object_string(); 1818 return GetHeap()->Object_string();
1819 } 1819 }
1820 1820
1821 1821
1822 String* JSReceiver::constructor_name() { 1822 String* JSReceiver::constructor_name() {
1823 return map()->constructor_name(); 1823 return map()->constructor_name();
1824 } 1824 }
1825 1825
1826 1826
1827 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1828 Handle<Name> name,
1829 Handle<HeapType> type,
1830 PropertyAttributes attributes,
1831 Representation representation,
1832 TransitionFlag flag) {
1833 ASSERT(DescriptorArray::kNotFound ==
1834 map->instance_descriptors()->Search(
1835 *name, map->NumberOfOwnDescriptors()));
1836
1837 // Ensure the descriptor array does not get too big.
1838 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1839 return MaybeHandle<Map>();
1840 }
1841
1842 // Normalize the object if the name is an actual name (not the
1843 // hidden strings) and is not a real identifier.
1844 // Normalize the object if it will have too many fast properties.
1845 Isolate* isolate = map->GetIsolate();
1846 if (!name->IsCacheable(isolate)) return MaybeHandle<Map>();
1847
1848 // Compute the new index for new field.
1849 int index = map->NextFreePropertyIndex();
1850
1851 if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1852 representation = Representation::Tagged();
1853 type = HeapType::Any(isolate);
1854 }
1855
1856 FieldDescriptor new_field_desc(name, index, type, attributes, representation);
1857 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1858 int unused_property_fields = new_map->unused_property_fields() - 1;
1859 if (unused_property_fields < 0) {
1860 unused_property_fields += JSObject::kFieldsAdded;
1861 }
1862 new_map->set_unused_property_fields(unused_property_fields);
1863 return new_map;
1864 }
1865
1866
1867 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1868 Handle<Name> name,
1869 Handle<Object> constant,
1870 PropertyAttributes attributes,
1871 TransitionFlag flag) {
1872 // Ensure the descriptor array does not get too big.
1873 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1874 return MaybeHandle<Map>();
1875 }
1876
1877 // Allocate new instance descriptors with (name, constant) added.
1878 ConstantDescriptor new_constant_desc(name, constant, attributes);
1879 return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1880 }
1881
1882
1827 void JSObject::AddFastProperty(Handle<JSObject> object, 1883 void JSObject::AddFastProperty(Handle<JSObject> object,
1828 Handle<Name> name, 1884 Handle<Name> name,
1829 Handle<Object> value, 1885 Handle<Object> value,
1830 PropertyAttributes attributes, 1886 PropertyAttributes attributes,
1831 StoreFromKeyed store_mode, 1887 StoreFromKeyed store_mode,
1832 ValueType value_type, 1888 ValueType value_type,
1833 TransitionFlag flag) { 1889 TransitionFlag flag) {
1834 ASSERT(!object->IsJSGlobalProxy()); 1890 ASSERT(!object->IsJSGlobalProxy());
1835 ASSERT(DescriptorArray::kNotFound ==
1836 object->map()->instance_descriptors()->Search(
1837 *name, object->map()->NumberOfOwnDescriptors()));
1838 1891
1839 // Normalize the object if the name is an actual name (not the 1892 MaybeHandle<Map> maybe_map;
1840 // hidden strings) and is not a real identifier. 1893 if (value->IsJSFunction()) {
1841 // Normalize the object if it will have too many fast properties. 1894 maybe_map = Map::CopyWithConstant(
1842 Isolate* isolate = object->GetIsolate(); 1895 handle(object->map()), name, value, attributes, flag);
1843 if (!name->IsCacheable(isolate) || 1896 } else if (!object->TooManyFastProperties(store_mode)) {
1844 object->TooManyFastProperties(store_mode)) { 1897 Isolate* isolate = object->GetIsolate();
1898 Representation representation = value->OptimalRepresentation(value_type);
1899 maybe_map = Map::CopyWithField(
1900 handle(object->map(), isolate), name,
1901 value->OptimalType(isolate, representation),
1902 attributes, representation, flag);
1903 }
1904
1905 Handle<Map> new_map;
1906 if (!maybe_map.ToHandle(&new_map)) {
1845 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 1907 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1846 AddSlowProperty(object, name, value, attributes);
1847 return; 1908 return;
1848 } 1909 }
1849 1910
1850 // Allocate new instance descriptors with (name, index) added 1911 JSObject::MigrateToMap(object, new_map);
1851 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
1852 Representation representation = value->OptimalRepresentation(value_type);
1853 1912
1854 // Compute the new index for new field. 1913 PropertyDetails details = new_map->GetLastDescriptorDetails();
1855 int index = object->map()->NextFreePropertyIndex(); 1914 if (details.type() != FIELD) return;
1856 1915
1857 Handle<HeapType> type = value->OptimalType(isolate, representation); 1916 Representation representation = details.representation();
1858 FieldDescriptor new_field_desc(name, index, type, attributes, representation); 1917 int index = details.field_index();
1859 Handle<Map> new_map = Map::CopyAddDescriptor(
1860 handle(object->map()), &new_field_desc, flag);
1861 int unused_property_fields = new_map->unused_property_fields() - 1;
1862 if (unused_property_fields < 0) {
1863 unused_property_fields += JSObject::kFieldsAdded;
1864 }
1865 new_map->set_unused_property_fields(unused_property_fields);
1866
1867 JSObject::MigrateToMap(object, new_map);
1868 1918
1869 if (representation.IsDouble()) { 1919 if (representation.IsDouble()) {
1870 // Nothing more to be done. 1920 // Nothing more to be done.
1871 if (value->IsUninitialized()) return; 1921 if (value->IsUninitialized()) return;
1872 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); 1922 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
1873 box->set_value(value->Number()); 1923 box->set_value(value->Number());
1874 } else { 1924 } else {
1875 object->FastPropertyAtPut(index, *value); 1925 object->FastPropertyAtPut(index, *value);
1876 } 1926 }
1877 } 1927 }
1878 1928
1879 1929
1880 void JSObject::AddConstantProperty(Handle<JSObject> object,
1881 Handle<Name> name,
1882 Handle<Object> constant,
1883 PropertyAttributes attributes,
1884 TransitionFlag initial_flag) {
1885 ASSERT(!object->IsGlobalObject());
1886 // Don't add transitions to special properties with non-trivial attributes.
1887 TransitionFlag flag = attributes != NONE ? OMIT_TRANSITION : initial_flag;
1888
1889 // Allocate new instance descriptors with (name, constant) added.
1890 ConstantDescriptor new_constant_desc(name, constant, attributes);
1891 Handle<Map> new_map = Map::CopyAddDescriptor(
1892 handle(object->map()), &new_constant_desc, flag);
1893
1894 JSObject::MigrateToMap(object, new_map);
1895 }
1896
1897
1898 void JSObject::AddSlowProperty(Handle<JSObject> object, 1930 void JSObject::AddSlowProperty(Handle<JSObject> object,
1899 Handle<Name> name, 1931 Handle<Name> name,
1900 Handle<Object> value, 1932 Handle<Object> value,
1901 PropertyAttributes attributes) { 1933 PropertyAttributes attributes) {
1902 ASSERT(!object->HasFastProperties()); 1934 ASSERT(!object->HasFastProperties());
1903 Isolate* isolate = object->GetIsolate(); 1935 Isolate* isolate = object->GetIsolate();
1904 Handle<NameDictionary> dict(object->property_dictionary()); 1936 Handle<NameDictionary> dict(object->property_dictionary());
1905 if (object->IsGlobalObject()) { 1937 if (object->IsGlobalObject()) {
1906 // In case name is an orphaned property reuse the cell. 1938 // In case name is an orphaned property reuse the cell.
1907 int entry = dict->FindEntry(*name); 1939 int entry = dict->FindEntry(*name);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1952 return value; 1984 return value;
1953 } else { 1985 } else {
1954 Handle<Object> args[1] = { name }; 1986 Handle<Object> args[1] = { name };
1955 Handle<Object> error = isolate->factory()->NewTypeError( 1987 Handle<Object> error = isolate->factory()->NewTypeError(
1956 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); 1988 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
1957 return isolate->Throw<Object>(error); 1989 return isolate->Throw<Object>(error);
1958 } 1990 }
1959 } 1991 }
1960 1992
1961 if (object->HasFastProperties()) { 1993 if (object->HasFastProperties()) {
1962 // Ensure the descriptor array does not get too big. 1994 AddFastProperty(object, name, value, attributes, store_mode,
1963 if (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors) { 1995 value_type, transition_flag);
1964 // TODO(verwaest): Support other constants. 1996 }
1965 // if (mode == ALLOW_AS_CONSTANT && 1997
1966 // !value->IsTheHole() && 1998 if (!object->HasFastProperties()) {
1967 // !value->IsConsString()) {
1968 if (value->IsJSFunction()) {
1969 AddConstantProperty(object, name, value, attributes, transition_flag);
1970 } else {
1971 AddFastProperty(object, name, value, attributes, store_mode,
1972 value_type, transition_flag);
1973 }
1974 } else {
1975 // Normalize the object to prevent very large instance descriptors.
1976 // This eliminates unwanted N^2 allocation and lookup behavior.
1977 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1978 AddSlowProperty(object, name, value, attributes);
1979 }
1980 } else {
1981 AddSlowProperty(object, name, value, attributes); 1999 AddSlowProperty(object, name, value, attributes);
1982 } 2000 }
1983 2001
1984 if (object->map()->is_observed() && 2002 if (object->map()->is_observed() &&
1985 *name != isolate->heap()->hidden_string()) { 2003 *name != isolate->heap()->hidden_string()) {
1986 Handle<Object> old_value = isolate->factory()->the_hole_value(); 2004 Handle<Object> old_value = isolate->factory()->the_hole_value();
1987 EnqueueChangeRecord(object, "add", name, old_value); 2005 EnqueueChangeRecord(object, "add", name, old_value);
1988 } 2006 }
1989 2007
1990 return value; 2008 return value;
(...skipping 4615 matching lines...) Expand 10 before | Expand all | Expand 10 after
6606 JSObject::MigrateToMap(self, transitioned_map); 6624 JSObject::MigrateToMap(self, transitioned_map);
6607 return true; 6625 return true;
6608 } 6626 }
6609 6627
6610 // If either not the same accessor, or not the same attributes, fall back to 6628 // If either not the same accessor, or not the same attributes, fall back to
6611 // the slow case. 6629 // the slow case.
6612 return false; 6630 return false;
6613 } 6631 }
6614 6632
6615 6633
6616 static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
6617 Handle<Name> name,
6618 Handle<AccessorPair> accessors,
6619 PropertyAttributes attributes) {
6620 CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
6621 return Map::CopyInsertDescriptor(map, &new_accessors_desc, INSERT_TRANSITION);
6622 }
6623
6624
6625 bool JSObject::DefineFastAccessor(Handle<JSObject> object, 6634 bool JSObject::DefineFastAccessor(Handle<JSObject> object,
6626 Handle<Name> name, 6635 Handle<Name> name,
6627 AccessorComponent component, 6636 AccessorComponent component,
6628 Handle<Object> accessor, 6637 Handle<Object> accessor,
6629 PropertyAttributes attributes) { 6638 PropertyAttributes attributes) {
6630 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); 6639 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
6631 Isolate* isolate = object->GetIsolate(); 6640 Isolate* isolate = object->GetIsolate();
6632 LookupResult result(isolate); 6641 LookupResult result(isolate);
6633 object->LocalLookup(*name, &result); 6642 object->LocalLookup(*name, &result);
6634 6643
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
6679 } 6688 }
6680 } 6689 }
6681 6690
6682 // If there is no transition yet, add a transition to the a new accessor pair 6691 // If there is no transition yet, add a transition to the a new accessor pair
6683 // containing the accessor. Allocate a new pair if there were no source 6692 // containing the accessor. Allocate a new pair if there were no source
6684 // accessors. Otherwise, copy the pair and modify the accessor. 6693 // accessors. Otherwise, copy the pair and modify the accessor.
6685 Handle<AccessorPair> accessors = source_accessors != NULL 6694 Handle<AccessorPair> accessors = source_accessors != NULL
6686 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) 6695 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
6687 : isolate->factory()->NewAccessorPair(); 6696 : isolate->factory()->NewAccessorPair();
6688 accessors->set(component, *accessor); 6697 accessors->set(component, *accessor);
6689 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), 6698
6690 name, accessors, attributes); 6699 CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
6700 Handle<Map> new_map = Map::CopyInsertDescriptor(
6701 handle(object->map()), &new_accessors_desc, INSERT_TRANSITION);
6702
6691 JSObject::MigrateToMap(object, new_map); 6703 JSObject::MigrateToMap(object, new_map);
6692 return true; 6704 return true;
6693 } 6705 }
6694 6706
6695 6707
6696 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object, 6708 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6697 Handle<AccessorInfo> info) { 6709 Handle<AccessorInfo> info) {
6698 Isolate* isolate = object->GetIsolate(); 6710 Isolate* isolate = object->GetIsolate();
6699 Factory* factory = isolate->factory(); 6711 Factory* factory = isolate->factory();
6700 Handle<Name> name(Name::cast(info->name())); 6712 Handle<Name> name(Name::cast(info->name()));
(...skipping 9893 matching lines...) Expand 10 before | Expand all | Expand 10 after
16594 #define ERROR_MESSAGES_TEXTS(C, T) T, 16606 #define ERROR_MESSAGES_TEXTS(C, T) T,
16595 static const char* error_messages_[] = { 16607 static const char* error_messages_[] = {
16596 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16608 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16597 }; 16609 };
16598 #undef ERROR_MESSAGES_TEXTS 16610 #undef ERROR_MESSAGES_TEXTS
16599 return error_messages_[reason]; 16611 return error_messages_[reason];
16600 } 16612 }
16601 16613
16602 16614
16603 } } // namespace v8::internal 16615 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698