Chromium Code Reviews

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: MUST_USE_RESULT Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | 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...)
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 Handle<Map>();
Igor Sheludko 2014/04/15 15:02:39 MaybeHandle<>
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();
Igor Sheludko 2014/04/15 15:02:39 Shouldn't we update type here as well?
1853 }
1854
1855 FieldDescriptor new_field_desc(name, index, type, attributes, representation);
1856 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1857 int unused_property_fields = new_map->unused_property_fields() - 1;
1858 if (unused_property_fields < 0) {
1859 unused_property_fields += JSObject::kFieldsAdded;
1860 }
1861 new_map->set_unused_property_fields(unused_property_fields);
1862 return new_map;
1863 }
1864
1865
1866 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1867 Handle<Name> name,
1868 Handle<Object> constant,
1869 PropertyAttributes attributes,
1870 TransitionFlag flag) {
1871 // Ensure the descriptor array does not get too big.
1872 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1873 return MaybeHandle<Map>();
1874 }
1875
1876 // Allocate new instance descriptors with (name, constant) added.
1877 ConstantDescriptor new_constant_desc(name, constant, attributes);
1878 return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1879 }
1880
1881
1827 void JSObject::AddFastProperty(Handle<JSObject> object, 1882 void JSObject::AddFastProperty(Handle<JSObject> object,
1828 Handle<Name> name, 1883 Handle<Name> name,
1829 Handle<Object> value, 1884 Handle<Object> value,
1830 PropertyAttributes attributes, 1885 PropertyAttributes attributes,
1831 StoreFromKeyed store_mode, 1886 StoreFromKeyed store_mode,
1832 ValueType value_type, 1887 ValueType value_type,
1833 TransitionFlag flag) { 1888 TransitionFlag flag) {
1834 ASSERT(!object->IsJSGlobalProxy()); 1889 ASSERT(!object->IsJSGlobalProxy());
1835 ASSERT(DescriptorArray::kNotFound ==
1836 object->map()->instance_descriptors()->Search(
1837 *name, object->map()->NumberOfOwnDescriptors()));
1838 1890
1839 // Normalize the object if the name is an actual name (not the 1891 MaybeHandle<Map> maybe_map;
1840 // hidden strings) and is not a real identifier. 1892 if (value->IsJSFunction()) {
1841 // Normalize the object if it will have too many fast properties. 1893 maybe_map = Map::CopyWithConstant(
1842 Isolate* isolate = object->GetIsolate(); 1894 handle(object->map()), name, value, attributes, flag);
1843 if (!name->IsCacheable(isolate) || 1895 } else if (object->TooManyFastProperties(store_mode)) {
1844 object->TooManyFastProperties(store_mode)) {
1845 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 1896 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1846 AddSlowProperty(object, name, value, attributes); 1897 return;
1898 } else {
Igor Sheludko 2014/04/15 15:02:39 I think you can now write here: } else if (!obje
1899 Isolate* isolate = object->GetIsolate();
1900 Representation representation = value->OptimalRepresentation(value_type);
1901 maybe_map = Map::CopyWithField(
1902 handle(object->map(), isolate), name,
1903 value->OptimalType(isolate, representation),
1904 attributes, representation, flag);
1905 }
1906
1907 Handle<Map> new_map;
1908 if (!maybe_map.ToHandle(&new_map)) {
1909 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1847 return; 1910 return;
1848 } 1911 }
1849 1912
1850 // Allocate new instance descriptors with (name, index) added 1913 JSObject::MigrateToMap(object, new_map);
1851 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
1852 Representation representation = value->OptimalRepresentation(value_type);
1853 1914
1854 // Compute the new index for new field. 1915 PropertyDetails details = new_map->GetLastDescriptorDetails();
1855 int index = object->map()->NextFreePropertyIndex(); 1916 if (details.type() != FIELD) return;
1856 1917
1857 Handle<HeapType> type = value->OptimalType(isolate, representation); 1918 Representation representation = details.representation();
1858 FieldDescriptor new_field_desc(name, index, type, attributes, representation); 1919 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 1920
1869 if (representation.IsDouble()) { 1921 if (representation.IsDouble()) {
1870 // Nothing more to be done. 1922 // Nothing more to be done.
1871 if (value->IsUninitialized()) return; 1923 if (value->IsUninitialized()) return;
1872 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); 1924 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
1873 box->set_value(value->Number()); 1925 box->set_value(value->Number());
1874 } else { 1926 } else {
1875 object->FastPropertyAtPut(index, *value); 1927 object->FastPropertyAtPut(index, *value);
1876 } 1928 }
1877 } 1929 }
1878 1930
1879 1931
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;
Igor Sheludko 2014/04/15 15:02:39 This code is lost.
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, 1932 void JSObject::AddSlowProperty(Handle<JSObject> object,
1899 Handle<Name> name, 1933 Handle<Name> name,
1900 Handle<Object> value, 1934 Handle<Object> value,
1901 PropertyAttributes attributes) { 1935 PropertyAttributes attributes) {
1902 ASSERT(!object->HasFastProperties()); 1936 ASSERT(!object->HasFastProperties());
1903 Isolate* isolate = object->GetIsolate(); 1937 Isolate* isolate = object->GetIsolate();
1904 Handle<NameDictionary> dict(object->property_dictionary()); 1938 Handle<NameDictionary> dict(object->property_dictionary());
1905 if (object->IsGlobalObject()) { 1939 if (object->IsGlobalObject()) {
1906 // In case name is an orphaned property reuse the cell. 1940 // In case name is an orphaned property reuse the cell.
1907 int entry = dict->FindEntry(*name); 1941 int entry = dict->FindEntry(*name);
(...skipping 44 matching lines...)
1952 return value; 1986 return value;
1953 } else { 1987 } else {
1954 Handle<Object> args[1] = { name }; 1988 Handle<Object> args[1] = { name };
1955 Handle<Object> error = isolate->factory()->NewTypeError( 1989 Handle<Object> error = isolate->factory()->NewTypeError(
1956 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); 1990 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
1957 return isolate->Throw<Object>(error); 1991 return isolate->Throw<Object>(error);
1958 } 1992 }
1959 } 1993 }
1960 1994
1961 if (object->HasFastProperties()) { 1995 if (object->HasFastProperties()) {
1962 // Ensure the descriptor array does not get too big. 1996 AddFastProperty(object, name, value, attributes, store_mode,
1963 if (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors) { 1997 value_type, transition_flag);
1964 // TODO(verwaest): Support other constants. 1998 }
1965 // if (mode == ALLOW_AS_CONSTANT && 1999
1966 // !value->IsTheHole() && 2000 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); 2001 AddSlowProperty(object, name, value, attributes);
1982 } 2002 }
1983 2003
1984 if (object->map()->is_observed() && 2004 if (object->map()->is_observed() &&
1985 *name != isolate->heap()->hidden_string()) { 2005 *name != isolate->heap()->hidden_string()) {
1986 Handle<Object> old_value = isolate->factory()->the_hole_value(); 2006 Handle<Object> old_value = isolate->factory()->the_hole_value();
1987 EnqueueChangeRecord(object, "add", name, old_value); 2007 EnqueueChangeRecord(object, "add", name, old_value);
1988 } 2008 }
1989 2009
1990 return value; 2010 return value;
(...skipping 4615 matching lines...)
6606 JSObject::MigrateToMap(self, transitioned_map); 6626 JSObject::MigrateToMap(self, transitioned_map);
6607 return true; 6627 return true;
6608 } 6628 }
6609 6629
6610 // If either not the same accessor, or not the same attributes, fall back to 6630 // If either not the same accessor, or not the same attributes, fall back to
6611 // the slow case. 6631 // the slow case.
6612 return false; 6632 return false;
6613 } 6633 }
6614 6634
6615 6635
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, 6636 bool JSObject::DefineFastAccessor(Handle<JSObject> object,
6626 Handle<Name> name, 6637 Handle<Name> name,
6627 AccessorComponent component, 6638 AccessorComponent component,
6628 Handle<Object> accessor, 6639 Handle<Object> accessor,
6629 PropertyAttributes attributes) { 6640 PropertyAttributes attributes) {
6630 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); 6641 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
6631 Isolate* isolate = object->GetIsolate(); 6642 Isolate* isolate = object->GetIsolate();
6632 LookupResult result(isolate); 6643 LookupResult result(isolate);
6633 object->LocalLookup(*name, &result); 6644 object->LocalLookup(*name, &result);
6634 6645
(...skipping 44 matching lines...)
6679 } 6690 }
6680 } 6691 }
6681 6692
6682 // If there is no transition yet, add a transition to the a new accessor pair 6693 // 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 6694 // containing the accessor. Allocate a new pair if there were no source
6684 // accessors. Otherwise, copy the pair and modify the accessor. 6695 // accessors. Otherwise, copy the pair and modify the accessor.
6685 Handle<AccessorPair> accessors = source_accessors != NULL 6696 Handle<AccessorPair> accessors = source_accessors != NULL
6686 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) 6697 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
6687 : isolate->factory()->NewAccessorPair(); 6698 : isolate->factory()->NewAccessorPair();
6688 accessors->set(component, *accessor); 6699 accessors->set(component, *accessor);
6689 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), 6700
6690 name, accessors, attributes); 6701 CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
6702 Handle<Map> new_map = Map::CopyInsertDescriptor(
6703 handle(object->map()), &new_accessors_desc, INSERT_TRANSITION);
6704
6691 JSObject::MigrateToMap(object, new_map); 6705 JSObject::MigrateToMap(object, new_map);
6692 return true; 6706 return true;
6693 } 6707 }
6694 6708
6695 6709
6696 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object, 6710 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6697 Handle<AccessorInfo> info) { 6711 Handle<AccessorInfo> info) {
6698 Isolate* isolate = object->GetIsolate(); 6712 Isolate* isolate = object->GetIsolate();
6699 Factory* factory = isolate->factory(); 6713 Factory* factory = isolate->factory();
6700 Handle<Name> name(Name::cast(info->name())); 6714 Handle<Name> name(Name::cast(info->name()));
(...skipping 9893 matching lines...)
16594 #define ERROR_MESSAGES_TEXTS(C, T) T, 16608 #define ERROR_MESSAGES_TEXTS(C, T) T,
16595 static const char* error_messages_[] = { 16609 static const char* error_messages_[] = {
16596 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16610 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16597 }; 16611 };
16598 #undef ERROR_MESSAGES_TEXTS 16612 #undef ERROR_MESSAGES_TEXTS
16599 return error_messages_[reason]; 16613 return error_messages_[reason];
16600 } 16614 }
16601 16615
16602 16616
16603 } } // namespace v8::internal 16617 } } // 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