| 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 |