OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |