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 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 } | 448 } |
449 | 449 |
450 | 450 |
451 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, | 451 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, |
452 Handle<JSReceiver> receiver, | 452 Handle<JSReceiver> receiver, |
453 uint32_t index, | 453 uint32_t index, |
454 Handle<Object> value, | 454 Handle<Object> value, |
455 StrictModeFlag strict_mode) { | 455 StrictModeFlag strict_mode) { |
456 Isolate* isolate = proxy->GetIsolate(); | 456 Isolate* isolate = proxy->GetIsolate(); |
457 Handle<String> name = isolate->factory()->Uint32ToString(index); | 457 Handle<String> name = isolate->factory()->Uint32ToString(index); |
458 CALL_HEAP_FUNCTION(isolate, | 458 return SetPropertyWithHandler( |
459 proxy->SetPropertyWithHandler( | 459 proxy, receiver, name, value, NONE, strict_mode); |
460 *receiver, *name, *value, NONE, strict_mode), | |
461 Object); | |
462 } | 460 } |
463 | 461 |
464 | 462 |
465 bool JSProxy::HasElementWithHandler(uint32_t index) { | 463 bool JSProxy::HasElementWithHandler(uint32_t index) { |
466 String* name; | 464 String* name; |
467 MaybeObject* maybe = GetHeap()->Uint32ToString(index); | 465 MaybeObject* maybe = GetHeap()->Uint32ToString(index); |
468 if (!maybe->To<String>(&name)) return maybe; | 466 if (!maybe->To<String>(&name)) return maybe; |
469 return HasPropertyWithHandler(name); | 467 return HasPropertyWithHandler(name); |
470 } | 468 } |
471 | 469 |
(...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1864 // If the constructor is not present, return "Object". | 1862 // If the constructor is not present, return "Object". |
1865 return GetHeap()->Object_string(); | 1863 return GetHeap()->Object_string(); |
1866 } | 1864 } |
1867 | 1865 |
1868 | 1866 |
1869 String* JSReceiver::constructor_name() { | 1867 String* JSReceiver::constructor_name() { |
1870 return map()->constructor_name(); | 1868 return map()->constructor_name(); |
1871 } | 1869 } |
1872 | 1870 |
1873 | 1871 |
1872 Handle<Object> JSObject::AddFastPropertyUsingMap( | |
1873 Handle<JSObject> object, | |
1874 Handle<Map> new_map, | |
1875 Handle<Name> name, | |
1876 Handle<Object> value, | |
1877 int field_index, | |
1878 Representation representation) { | |
1879 CALL_HEAP_FUNCTION(object->GetIsolate(), | |
1880 object->AddFastPropertyUsingMap( | |
1881 *new_map, *name, *value, field_index, representation), | |
1882 Object); | |
1883 } | |
1884 | |
1885 | |
1874 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, | 1886 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
1875 Name* name, | 1887 Name* name, |
1876 Object* value, | 1888 Object* value, |
1877 int field_index, | 1889 int field_index, |
1878 Representation representation) { | 1890 Representation representation) { |
1879 // This method is used to transition to a field. If we are transitioning to a | 1891 // This method is used to transition to a field. If we are transitioning to a |
1880 // double field, allocate new storage. | 1892 // double field, allocate new storage. |
1881 Object* storage; | 1893 Object* storage; |
1882 MaybeObject* maybe_storage = | 1894 MaybeObject* maybe_storage = |
1883 value->AllocateNewStorageFor(GetHeap(), representation); | 1895 value->AllocateNewStorageFor(GetHeap(), representation); |
1884 if (!maybe_storage->To(&storage)) return maybe_storage; | 1896 if (!maybe_storage->To(&storage)) return maybe_storage; |
1885 | 1897 |
1886 if (map()->unused_property_fields() == 0) { | 1898 if (map()->unused_property_fields() == 0) { |
1887 int new_unused = new_map->unused_property_fields(); | 1899 int new_unused = new_map->unused_property_fields(); |
1888 FixedArray* values; | 1900 FixedArray* values; |
1889 MaybeObject* maybe_values = | 1901 MaybeObject* maybe_values = |
1890 properties()->CopySize(properties()->length() + new_unused + 1); | 1902 properties()->CopySize(properties()->length() + new_unused + 1); |
1891 if (!maybe_values->To(&values)) return maybe_values; | 1903 if (!maybe_values->To(&values)) return maybe_values; |
1892 | 1904 |
1893 set_properties(values); | 1905 set_properties(values); |
1894 } | 1906 } |
1895 | 1907 |
1896 set_map(new_map); | 1908 set_map(new_map); |
1897 | 1909 |
1898 FastPropertyAtPut(field_index, storage); | 1910 FastPropertyAtPut(field_index, storage); |
1899 return value; | 1911 return value; |
1900 } | 1912 } |
1901 | 1913 |
1902 | 1914 |
1903 MaybeObject* JSObject::AddFastProperty(Name* name, | 1915 static MaybeObject* CopyAddFieldDescriptor(Map* map, |
1904 Object* value, | 1916 Name* name, |
1905 PropertyAttributes attributes, | 1917 int index, |
1906 StoreFromKeyed store_mode, | 1918 PropertyAttributes attributes, |
1907 ValueType value_type, | 1919 Representation representation, |
1908 TransitionFlag flag) { | 1920 TransitionFlag flag) { |
1909 ASSERT(!IsJSGlobalProxy()); | 1921 FieldDescriptor new_field_desc(name, index, attributes, representation); |
1922 return map->CopyAddDescriptor(&new_field_desc, flag); | |
1923 } | |
1924 | |
1925 | |
1926 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, | |
1927 Handle<Name> name, | |
1928 int index, | |
1929 PropertyAttributes attributes, | |
1930 Representation representation, | |
1931 TransitionFlag flag) { | |
1932 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
1933 CopyAddFieldDescriptor( | |
1934 *map, *name, index, attributes, representation, flag), | |
1935 Map); | |
1936 } | |
1937 | |
1938 | |
1939 void JSObject::AddFastProperty(Handle<JSObject> object, | |
1940 Handle<Name> name, | |
1941 Handle<Object> value, | |
1942 PropertyAttributes attributes, | |
1943 StoreFromKeyed store_mode, | |
1944 ValueType value_type, | |
1945 TransitionFlag flag) { | |
1946 ASSERT(!object->IsJSGlobalProxy()); | |
1910 ASSERT(DescriptorArray::kNotFound == | 1947 ASSERT(DescriptorArray::kNotFound == |
1911 map()->instance_descriptors()->Search( | 1948 object->map()->instance_descriptors()->Search( |
1912 name, map()->NumberOfOwnDescriptors())); | 1949 *name, object->map()->NumberOfOwnDescriptors())); |
1913 | 1950 |
1914 // Normalize the object if the name is an actual name (not the | 1951 // Normalize the object if the name is an actual name (not the |
1915 // hidden strings) and is not a real identifier. | 1952 // hidden strings) and is not a real identifier. |
1916 // Normalize the object if it will have too many fast properties. | 1953 // Normalize the object if it will have too many fast properties. |
1917 Isolate* isolate = GetHeap()->isolate(); | 1954 Isolate* isolate = object->GetIsolate(); |
1918 if (!name->IsCacheable(isolate) || TooManyFastProperties(store_mode)) { | 1955 if (!name->IsCacheable(isolate) || |
1919 MaybeObject* maybe_failure = | 1956 object->TooManyFastProperties(store_mode)) { |
1920 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1957 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
1921 if (maybe_failure->IsFailure()) return maybe_failure; | 1958 AddSlowProperty(object, name, value, attributes); |
1922 return AddSlowProperty(name, value, attributes); | 1959 return; |
1923 } | 1960 } |
1924 | 1961 |
1925 // Compute the new index for new field. | 1962 // Compute the new index for new field. |
1926 int index = map()->NextFreePropertyIndex(); | 1963 int index = object->map()->NextFreePropertyIndex(); |
1927 | 1964 |
1928 // Allocate new instance descriptors with (name, index) added | 1965 // Allocate new instance descriptors with (name, index) added |
1929 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 1966 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
1930 Representation representation = value->OptimalRepresentation(value_type); | 1967 Representation representation = value->OptimalRepresentation(value_type); |
1931 | 1968 Handle<Map> new_map = CopyAddFieldDescriptor( |
1932 FieldDescriptor new_field(name, index, attributes, representation); | 1969 handle(object->map()), name, index, attributes, representation, flag); |
1933 | 1970 |
1934 Map* new_map; | 1971 int unused_property_fields = object->map()->unused_property_fields() - 1; |
1935 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); | |
1936 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
1937 | |
1938 int unused_property_fields = map()->unused_property_fields() - 1; | |
1939 if (unused_property_fields < 0) { | 1972 if (unused_property_fields < 0) { |
1940 unused_property_fields += kFieldsAdded; | 1973 unused_property_fields += kFieldsAdded; |
1941 } | 1974 } |
1942 new_map->set_unused_property_fields(unused_property_fields); | 1975 new_map->set_unused_property_fields(unused_property_fields); |
Toon Verwaest
2013/09/16 16:37:50
Can we move these lines changing the "unused prope
Michael Starzinger
2013/09/17 10:44:16
Done.
| |
1943 | 1976 |
1944 return AddFastPropertyUsingMap(new_map, name, value, index, representation); | 1977 AddFastPropertyUsingMap(object, new_map, name, value, index, representation); |
1945 } | 1978 } |
1946 | 1979 |
1947 | 1980 |
1948 MaybeObject* JSObject::AddConstantProperty( | 1981 static MaybeObject* CopyAddConstantDescriptor(Map* map, |
1949 Name* name, | 1982 Name* name, |
1950 Object* constant, | 1983 Object* value, |
1951 PropertyAttributes attributes, | 1984 PropertyAttributes attributes, |
1952 TransitionFlag initial_flag) { | 1985 TransitionFlag flag) { |
1953 // Allocate new instance descriptors with (name, constant) added | 1986 ConstantDescriptor new_constant_desc(name, value, attributes); |
1954 ConstantDescriptor d(name, constant, attributes); | 1987 return map->CopyAddDescriptor(&new_constant_desc, flag); |
1955 | 1988 } |
1989 | |
1990 | |
1991 static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map, | |
1992 Handle<Name> name, | |
1993 Handle<Object> value, | |
1994 PropertyAttributes attributes, | |
1995 TransitionFlag flag) { | |
1996 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
1997 CopyAddConstantDescriptor( | |
1998 *map, *name, *value, attributes, flag), | |
1999 Map); | |
2000 } | |
2001 | |
2002 | |
2003 void JSObject::AddConstantProperty(Handle<JSObject> object, | |
2004 Handle<Name> name, | |
2005 Handle<Object> constant, | |
2006 PropertyAttributes attributes, | |
2007 TransitionFlag initial_flag) { | |
1956 TransitionFlag flag = | 2008 TransitionFlag flag = |
1957 // Do not add transitions to global objects. | 2009 // Do not add transitions to global objects. |
1958 (IsGlobalObject() || | 2010 (object->IsGlobalObject() || |
1959 // Don't add transitions to special properties with non-trivial | 2011 // Don't add transitions to special properties with non-trivial |
1960 // attributes. | 2012 // attributes. |
1961 attributes != NONE) | 2013 attributes != NONE) |
1962 ? OMIT_TRANSITION | 2014 ? OMIT_TRANSITION |
1963 : initial_flag; | 2015 : initial_flag; |
1964 | 2016 |
1965 Map* new_map; | 2017 // Allocate new instance descriptors with (name, constant) added. |
1966 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); | 2018 Handle<Map> new_map = CopyAddConstantDescriptor( |
1967 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2019 handle(object->map()), name, constant, attributes, flag); |
1968 | 2020 |
1969 set_map(new_map); | 2021 object->set_map(*new_map); |
1970 return constant; | 2022 } |
1971 } | 2023 |
1972 | 2024 |
1973 | 2025 // TODO(mstarzinger): Temporary wrapper until handlified. |
1974 // Add property in slow mode | 2026 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, |
1975 MaybeObject* JSObject::AddSlowProperty(Name* name, | 2027 Handle<Name> name, |
1976 Object* value, | 2028 Handle<Object> value, |
1977 PropertyAttributes attributes) { | 2029 PropertyDetails details) { |
1978 ASSERT(!HasFastProperties()); | 2030 CALL_HEAP_FUNCTION(dict->GetIsolate(), |
1979 NameDictionary* dict = property_dictionary(); | 2031 dict->Add(*name, *value, details), |
1980 Object* store_value = value; | 2032 NameDictionary); |
1981 if (IsGlobalObject()) { | 2033 } |
2034 | |
2035 | |
2036 void JSObject::AddSlowProperty(Handle<JSObject> object, | |
2037 Handle<Name> name, | |
2038 Handle<Object> value, | |
2039 PropertyAttributes attributes) { | |
2040 ASSERT(!object->HasFastProperties()); | |
2041 Isolate* isolate = object->GetIsolate(); | |
2042 Handle<NameDictionary> dict(object->property_dictionary()); | |
2043 if (object->IsGlobalObject()) { | |
1982 // In case name is an orphaned property reuse the cell. | 2044 // In case name is an orphaned property reuse the cell. |
1983 int entry = dict->FindEntry(name); | 2045 int entry = dict->FindEntry(*name); |
1984 if (entry != NameDictionary::kNotFound) { | 2046 if (entry != NameDictionary::kNotFound) { |
1985 store_value = dict->ValueAt(entry); | 2047 Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); |
1986 MaybeObject* maybe_type = | 2048 PropertyCell::SetValueInferType(cell, value); |
1987 PropertyCell::cast(store_value)->SetValueInferType(value); | |
1988 if (maybe_type->IsFailure()) return maybe_type; | |
1989 // Assign an enumeration index to the property and update | 2049 // Assign an enumeration index to the property and update |
1990 // SetNextEnumerationIndex. | 2050 // SetNextEnumerationIndex. |
1991 int index = dict->NextEnumerationIndex(); | 2051 int index = dict->NextEnumerationIndex(); |
1992 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); | 2052 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
1993 dict->SetNextEnumerationIndex(index + 1); | 2053 dict->SetNextEnumerationIndex(index + 1); |
1994 dict->SetEntry(entry, name, store_value, details); | 2054 dict->SetEntry(entry, *name, *cell, details); |
1995 return value; | 2055 return; |
1996 } | 2056 } |
1997 Heap* heap = GetHeap(); | 2057 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value); |
1998 { MaybeObject* maybe_store_value = | 2058 PropertyCell::SetValueInferType(cell, value); |
1999 heap->AllocatePropertyCell(value); | 2059 value = cell; |
2000 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | |
2001 } | |
2002 MaybeObject* maybe_type = | |
2003 PropertyCell::cast(store_value)->SetValueInferType(value); | |
2004 if (maybe_type->IsFailure()) return maybe_type; | |
2005 } | 2060 } |
2006 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 2061 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
2007 Object* result; | 2062 Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details); |
2008 { MaybeObject* maybe_result = dict->Add(name, store_value, details); | 2063 if (*dict != *result) object->set_properties(*result); |
2009 if (!maybe_result->ToObject(&result)) return maybe_result; | 2064 } |
2010 } | 2065 |
2011 if (dict != result) set_properties(NameDictionary::cast(result)); | 2066 |
2012 return value; | 2067 Handle<Object> JSObject::AddProperty(Handle<JSObject> object, |
2013 } | 2068 Handle<Name> name, |
2014 | 2069 Handle<Object> value, |
2015 | 2070 PropertyAttributes attributes, |
2016 MaybeObject* JSObject::AddProperty(Name* name, | 2071 StrictModeFlag strict_mode, |
2017 Object* value, | 2072 JSReceiver::StoreFromKeyed store_mode, |
2018 PropertyAttributes attributes, | 2073 ExtensibilityCheck extensibility_check, |
2019 StrictModeFlag strict_mode, | 2074 ValueType value_type, |
2020 JSReceiver::StoreFromKeyed store_mode, | 2075 StoreMode mode, |
2021 ExtensibilityCheck extensibility_check, | 2076 TransitionFlag transition_flag) { |
2022 ValueType value_type, | 2077 ASSERT(!object->IsJSGlobalProxy()); |
2023 StoreMode mode, | 2078 Isolate* isolate = object->GetIsolate(); |
2024 TransitionFlag transition_flag) { | |
2025 ASSERT(!IsJSGlobalProxy()); | |
2026 Map* map_of_this = map(); | |
2027 Heap* heap = GetHeap(); | |
2028 Isolate* isolate = heap->isolate(); | |
2029 MaybeObject* result; | |
2030 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2079 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
2031 !map_of_this->is_extensible()) { | 2080 !object->map()->is_extensible()) { |
2032 if (strict_mode == kNonStrictMode) { | 2081 if (strict_mode == kNonStrictMode) { |
2033 return value; | 2082 return value; |
2034 } else { | 2083 } else { |
2035 Handle<Object> args[1] = {Handle<Name>(name)}; | 2084 Handle<Object> args[1] = { name }; |
2036 return isolate->Throw( | 2085 Handle<Object> error = isolate->factory()->NewTypeError( |
2037 *isolate->factory()->NewTypeError("object_not_extensible", | 2086 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
2038 HandleVector(args, 1))); | 2087 isolate->Throw(*error); |
2088 return Handle<Object>(); | |
2039 } | 2089 } |
2040 } | 2090 } |
2041 | 2091 |
2042 if (HasFastProperties()) { | 2092 if (object->HasFastProperties()) { |
2043 // Ensure the descriptor array does not get too big. | 2093 // Ensure the descriptor array does not get too big. |
2044 if (map_of_this->NumberOfOwnDescriptors() < | 2094 if (object->map()->NumberOfOwnDescriptors() < |
2045 DescriptorArray::kMaxNumberOfDescriptors) { | 2095 DescriptorArray::kMaxNumberOfDescriptors) { |
2046 // TODO(verwaest): Support other constants. | 2096 // TODO(verwaest): Support other constants. |
2047 // if (mode == ALLOW_AS_CONSTANT && | 2097 // if (mode == ALLOW_AS_CONSTANT && |
2048 // !value->IsTheHole() && | 2098 // !value->IsTheHole() && |
2049 // !value->IsConsString()) { | 2099 // !value->IsConsString()) { |
2050 if (value->IsJSFunction()) { | 2100 if (value->IsJSFunction()) { |
2051 result = AddConstantProperty(name, value, attributes, transition_flag); | 2101 AddConstantProperty(object, name, value, attributes, transition_flag); |
2052 } else { | 2102 } else { |
2053 result = AddFastProperty( | 2103 AddFastProperty(object, name, value, attributes, store_mode, |
2054 name, value, attributes, store_mode, value_type, transition_flag); | 2104 value_type, transition_flag); |
2055 } | 2105 } |
2056 } else { | 2106 } else { |
2057 // Normalize the object to prevent very large instance descriptors. | 2107 // Normalize the object to prevent very large instance descriptors. |
2058 // This eliminates unwanted N^2 allocation and lookup behavior. | 2108 // This eliminates unwanted N^2 allocation and lookup behavior. |
2059 Object* obj; | 2109 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
2060 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2110 AddSlowProperty(object, name, value, attributes); |
2061 if (!maybe->To(&obj)) return maybe; | |
2062 result = AddSlowProperty(name, value, attributes); | |
2063 } | 2111 } |
2064 } else { | 2112 } else { |
2065 result = AddSlowProperty(name, value, attributes); | 2113 AddSlowProperty(object, name, value, attributes); |
2066 } | 2114 } |
2067 | 2115 |
2068 Handle<Object> hresult; | 2116 if (FLAG_harmony_observation && object->map()->is_observed()) { |
2069 if (!result->ToHandle(&hresult, isolate)) return result; | 2117 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
2070 | 2118 EnqueueChangeRecord(object, "new", name, old_value); |
2071 if (FLAG_harmony_observation && map()->is_observed()) { | 2119 } |
2072 EnqueueChangeRecord(handle(this, isolate), | 2120 |
2073 "new", | 2121 return value; |
2074 handle(name, isolate), | 2122 } |
2075 handle(heap->the_hole_value(), isolate)); | 2123 |
2076 } | 2124 |
2077 | |
2078 return *hresult; | |
2079 } | |
2080 | |
2081 | |
2082 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2125 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
2083 const char* type_str, | 2126 const char* type_str, |
2084 Handle<Name> name, | 2127 Handle<Name> name, |
2085 Handle<Object> old_value) { | 2128 Handle<Object> old_value) { |
2086 Isolate* isolate = object->GetIsolate(); | 2129 Isolate* isolate = object->GetIsolate(); |
2087 HandleScope scope(isolate); | 2130 HandleScope scope(isolate); |
2088 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); | 2131 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); |
2089 if (object->IsJSGlobalObject()) { | 2132 if (object->IsJSGlobalObject()) { |
2090 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); | 2133 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); |
2091 } | 2134 } |
(...skipping 16 matching lines...) Expand all Loading... | |
2108 isolate->observers_deliver_changes(), | 2151 isolate->observers_deliver_changes(), |
2109 isolate->factory()->undefined_value(), | 2152 isolate->factory()->undefined_value(), |
2110 0, | 2153 0, |
2111 NULL, | 2154 NULL, |
2112 &threw); | 2155 &threw); |
2113 ASSERT(!threw); | 2156 ASSERT(!threw); |
2114 isolate->set_observer_delivery_pending(false); | 2157 isolate->set_observer_delivery_pending(false); |
2115 } | 2158 } |
2116 | 2159 |
2117 | 2160 |
2118 MaybeObject* JSObject::SetPropertyPostInterceptor( | 2161 Handle<Object> JSObject::SetPropertyPostInterceptor( |
2119 Name* name, | 2162 Handle<JSObject> object, |
2120 Object* value, | 2163 Handle<Name> name, |
2164 Handle<Object> value, | |
2121 PropertyAttributes attributes, | 2165 PropertyAttributes attributes, |
2122 StrictModeFlag strict_mode, | 2166 StrictModeFlag strict_mode) { |
2123 StoreMode mode) { | |
2124 // Check local property, ignore interceptor. | 2167 // Check local property, ignore interceptor. |
2125 LookupResult result(GetIsolate()); | 2168 LookupResult result(object->GetIsolate()); |
2126 LocalLookupRealNamedProperty(name, &result); | 2169 object->LocalLookupRealNamedProperty(*name, &result); |
2127 if (!result.IsFound()) map()->LookupTransition(this, name, &result); | 2170 if (!result.IsFound()) { |
2171 object->map()->LookupTransition(*object, *name, &result); | |
2172 } | |
2128 if (result.IsFound()) { | 2173 if (result.IsFound()) { |
2129 // An existing property or a map transition was found. Use set property to | 2174 // An existing property or a map transition was found. Use set property to |
2130 // handle all these cases. | 2175 // handle all these cases. |
2131 return SetProperty(&result, name, value, attributes, strict_mode); | 2176 return SetPropertyForResult(object, &result, name, value, attributes, |
2177 strict_mode, MAY_BE_STORE_FROM_KEYED); | |
2132 } | 2178 } |
2133 bool done = false; | 2179 bool done = false; |
2134 MaybeObject* result_object = | 2180 Handle<Object> result_object = SetPropertyViaPrototypes( |
2135 SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); | 2181 object, name, value, attributes, strict_mode, &done); |
2136 if (done) return result_object; | 2182 if (done) return result_object; |
2137 // Add a new real property. | 2183 // Add a new real property. |
2138 return AddProperty(name, value, attributes, strict_mode, | 2184 return AddProperty(object, name, value, attributes, strict_mode); |
2139 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, | |
2140 OPTIMAL_REPRESENTATION, mode); | |
2141 } | 2185 } |
2142 | 2186 |
2143 | 2187 |
2144 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, | 2188 static Handle<Object> ReplaceSlowProperty(Handle<JSObject> object, |
2145 Object* value, | 2189 Handle<Name> name, |
2146 PropertyAttributes attributes) { | 2190 Handle<Object> value, |
2147 NameDictionary* dictionary = property_dictionary(); | 2191 PropertyAttributes attributes) { |
2148 int old_index = dictionary->FindEntry(name); | 2192 NameDictionary* dictionary = object->property_dictionary(); |
2193 int old_index = dictionary->FindEntry(*name); | |
2149 int new_enumeration_index = 0; // 0 means "Use the next available index." | 2194 int new_enumeration_index = 0; // 0 means "Use the next available index." |
2150 if (old_index != -1) { | 2195 if (old_index != -1) { |
2151 // All calls to ReplaceSlowProperty have had all transitions removed. | 2196 // All calls to ReplaceSlowProperty have had all transitions removed. |
2152 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2197 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
2153 } | 2198 } |
2154 | 2199 |
2155 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2200 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
2156 return SetNormalizedProperty(name, value, new_details); | 2201 return JSObject::SetNormalizedProperty(object, name, value, new_details); |
2157 } | 2202 } |
2158 | 2203 |
2159 | 2204 |
2160 const char* Representation::Mnemonic() const { | 2205 const char* Representation::Mnemonic() const { |
2161 switch (kind_) { | 2206 switch (kind_) { |
2162 case kNone: return "v"; | 2207 case kNone: return "v"; |
2163 case kTagged: return "t"; | 2208 case kTagged: return "t"; |
2164 case kSmi: return "s"; | 2209 case kSmi: return "s"; |
2165 case kDouble: return "d"; | 2210 case kDouble: return "d"; |
2166 case kInteger32: return "i"; | 2211 case kInteger32: return "i"; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2253 ASSERT(target_inobject < inobject_properties()); | 2298 ASSERT(target_inobject < inobject_properties()); |
2254 if (target_number_of_fields <= target_inobject) { | 2299 if (target_number_of_fields <= target_inobject) { |
2255 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2300 ASSERT(target_number_of_fields + target_unused == target_inobject); |
2256 return false; | 2301 return false; |
2257 } | 2302 } |
2258 // Otherwise, properties will need to be moved to the backing store. | 2303 // Otherwise, properties will need to be moved to the backing store. |
2259 return true; | 2304 return true; |
2260 } | 2305 } |
2261 | 2306 |
2262 | 2307 |
2308 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { | |
2309 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map)); | |
2310 } | |
2311 | |
2312 | |
2263 // To migrate an instance to a map: | 2313 // To migrate an instance to a map: |
2264 // - First check whether the instance needs to be rewritten. If not, simply | 2314 // - First check whether the instance needs to be rewritten. If not, simply |
2265 // change the map. | 2315 // change the map. |
2266 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2316 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
2267 // addition to unused space. | 2317 // addition to unused space. |
2268 // - Copy all existing properties in, in the following order: backing store | 2318 // - Copy all existing properties in, in the following order: backing store |
2269 // properties, unused fields, inobject properties. | 2319 // properties, unused fields, inobject properties. |
2270 // - If all allocation succeeded, commit the state atomically: | 2320 // - If all allocation succeeded, commit the state atomically: |
2271 // * Copy inobject properties from the backing store back into the object. | 2321 // * Copy inobject properties from the backing store back into the object. |
2272 // * Trim the difference in instance size of the object. This also cleanly | 2322 // * Trim the difference in instance size of the object. This also cleanly |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2354 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); | 2404 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); |
2355 set_properties(array); | 2405 set_properties(array); |
2356 } | 2406 } |
2357 | 2407 |
2358 set_map(new_map); | 2408 set_map(new_map); |
2359 | 2409 |
2360 return this; | 2410 return this; |
2361 } | 2411 } |
2362 | 2412 |
2363 | 2413 |
2364 MaybeObject* JSObject::GeneralizeFieldRepresentation( | 2414 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
2365 int modify_index, | 2415 int modify_index, |
2366 Representation new_representation, | 2416 Representation new_representation, |
2367 StoreMode store_mode) { | 2417 StoreMode store_mode) { |
2368 Map* new_map; | 2418 Handle<Map> new_map = Map::GeneralizeRepresentation( |
2369 MaybeObject* maybe_new_map = map()->GeneralizeRepresentation( | 2419 handle(object->map()), modify_index, new_representation, store_mode); |
2370 modify_index, new_representation, store_mode); | 2420 if (object->map() == *new_map) return; |
2371 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2421 return MigrateToMap(object, new_map); |
2372 if (map() == new_map) return this; | |
2373 | |
2374 return MigrateToMap(new_map); | |
2375 } | 2422 } |
2376 | 2423 |
2377 | 2424 |
2378 int Map::NumberOfFields() { | 2425 int Map::NumberOfFields() { |
2379 DescriptorArray* descriptors = instance_descriptors(); | 2426 DescriptorArray* descriptors = instance_descriptors(); |
2380 int result = 0; | 2427 int result = 0; |
2381 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2428 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
2382 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2429 if (descriptors->GetDetails(i).type() == FIELD) result++; |
2383 } | 2430 } |
2384 return result; | 2431 return result; |
2385 } | 2432 } |
2386 | 2433 |
2387 | 2434 |
2388 MaybeObject* Map::CopyGeneralizeAllRepresentations( | 2435 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
2389 int modify_index, | 2436 int modify_index, |
2390 StoreMode store_mode, | 2437 StoreMode store_mode, |
2391 PropertyAttributes attributes, | 2438 PropertyAttributes attributes, |
2392 const char* reason) { | 2439 const char* reason) { |
2393 Map* new_map; | 2440 Handle<Map> new_map = Copy(map); |
2394 MaybeObject* maybe_map = this->Copy(); | |
2395 if (!maybe_map->To(&new_map)) return maybe_map; | |
2396 | 2441 |
2397 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2442 DescriptorArray* descriptors = new_map->instance_descriptors(); |
2398 descriptors->InitializeRepresentations(Representation::Tagged()); | 2443 descriptors->InitializeRepresentations(Representation::Tagged()); |
2399 | 2444 |
2400 // Unless the instance is being migrated, ensure that modify_index is a field. | 2445 // Unless the instance is being migrated, ensure that modify_index is a field. |
2401 PropertyDetails details = descriptors->GetDetails(modify_index); | 2446 PropertyDetails details = descriptors->GetDetails(modify_index); |
2402 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2447 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
2403 FieldDescriptor d(descriptors->GetKey(modify_index), | 2448 FieldDescriptor d(descriptors->GetKey(modify_index), |
2404 new_map->NumberOfFields(), | 2449 new_map->NumberOfFields(), |
2405 attributes, | 2450 attributes, |
2406 Representation::Tagged()); | 2451 Representation::Tagged()); |
2407 d.SetSortedKeyIndex(details.pointer()); | 2452 d.SetSortedKeyIndex(details.pointer()); |
2408 descriptors->Set(modify_index, &d); | 2453 descriptors->Set(modify_index, &d); |
2409 int unused_property_fields = new_map->unused_property_fields() - 1; | 2454 int unused_property_fields = new_map->unused_property_fields() - 1; |
2410 if (unused_property_fields < 0) { | 2455 if (unused_property_fields < 0) { |
2411 unused_property_fields += JSObject::kFieldsAdded; | 2456 unused_property_fields += JSObject::kFieldsAdded; |
2412 } | 2457 } |
2413 new_map->set_unused_property_fields(unused_property_fields); | 2458 new_map->set_unused_property_fields(unused_property_fields); |
2414 } | 2459 } |
2415 | 2460 |
2416 if (FLAG_trace_generalization) { | 2461 if (FLAG_trace_generalization) { |
2417 PrintGeneralization(stdout, reason, modify_index, | 2462 map->PrintGeneralization(stdout, reason, modify_index, |
2418 new_map->NumberOfOwnDescriptors(), | 2463 new_map->NumberOfOwnDescriptors(), |
2419 new_map->NumberOfOwnDescriptors(), | 2464 new_map->NumberOfOwnDescriptors(), |
2420 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2465 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
2421 Representation::Tagged(), Representation::Tagged()); | 2466 Representation::Tagged(), Representation::Tagged()); |
2422 } | 2467 } |
2423 return new_map; | 2468 return new_map; |
2424 } | 2469 } |
2425 | 2470 |
2426 | 2471 |
2427 void Map::DeprecateTransitionTree() { | 2472 void Map::DeprecateTransitionTree() { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2555 // FindUpdatedMap. This uses the keys in the own map's descriptor array to | 2600 // FindUpdatedMap. This uses the keys in the own map's descriptor array to |
2556 // walk the transition tree. | 2601 // walk the transition tree. |
2557 // - Merge/generalize the descriptor array of the current map and |updated|. | 2602 // - Merge/generalize the descriptor array of the current map and |updated|. |
2558 // - Generalize the |modify_index| descriptor using |new_representation|. | 2603 // - Generalize the |modify_index| descriptor using |new_representation|. |
2559 // - Walk the tree again starting from the root towards |updated|. Stop at | 2604 // - Walk the tree again starting from the root towards |updated|. Stop at |
2560 // |split_map|, the first map who's descriptor array does not match the merged | 2605 // |split_map|, the first map who's descriptor array does not match the merged |
2561 // descriptor array. | 2606 // descriptor array. |
2562 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2607 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
2563 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2608 // - Otherwise, invalidate the outdated transition target from |updated|, and |
2564 // replace its transition tree with a new branch for the updated descriptors. | 2609 // replace its transition tree with a new branch for the updated descriptors. |
2565 MaybeObject* Map::GeneralizeRepresentation(int modify_index, | 2610 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
2566 Representation new_representation, | 2611 int modify_index, |
2567 StoreMode store_mode) { | 2612 Representation new_representation, |
2568 Map* old_map = this; | 2613 StoreMode store_mode) { |
2569 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2614 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
2570 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2615 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2571 Representation old_representation = old_details.representation(); | 2616 Representation old_representation = old_details.representation(); |
2572 | 2617 |
2573 // It's fine to transition from None to anything but double without any | 2618 // It's fine to transition from None to anything but double without any |
2574 // modification to the object, because the default uninitialized value for | 2619 // modification to the object, because the default uninitialized value for |
2575 // representation None can be overwritten by both smi and tagged values. | 2620 // representation None can be overwritten by both smi and tagged values. |
2576 // Doubles, however, would require a box allocation. | 2621 // Doubles, however, would require a box allocation. |
2577 if (old_representation.IsNone() && | 2622 if (old_representation.IsNone() && |
2578 !new_representation.IsNone() && | 2623 !new_representation.IsNone() && |
2579 !new_representation.IsDouble()) { | 2624 !new_representation.IsDouble()) { |
2580 old_descriptors->SetRepresentation(modify_index, new_representation); | 2625 old_descriptors->SetRepresentation(modify_index, new_representation); |
2581 return old_map; | 2626 return old_map; |
2582 } | 2627 } |
2583 | 2628 |
2584 int descriptors = old_map->NumberOfOwnDescriptors(); | 2629 int descriptors = old_map->NumberOfOwnDescriptors(); |
2585 Map* root_map = old_map->FindRootMap(); | 2630 Handle<Map> root_map(old_map->FindRootMap()); |
2586 | 2631 |
2587 // Check the state of the root map. | 2632 // Check the state of the root map. |
2588 if (!old_map->EquivalentToForTransition(root_map)) { | 2633 if (!old_map->EquivalentToForTransition(*root_map)) { |
2589 return CopyGeneralizeAllRepresentations( | 2634 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2590 modify_index, store_mode, old_details.attributes(), "not equivalent"); | 2635 old_details.attributes(), "not equivalent"); |
2591 } | 2636 } |
2592 | 2637 |
2593 int verbatim = root_map->NumberOfOwnDescriptors(); | 2638 int verbatim = root_map->NumberOfOwnDescriptors(); |
2594 | 2639 |
2595 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2640 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
2596 return CopyGeneralizeAllRepresentations( | 2641 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2597 modify_index, store_mode, | |
2598 old_details.attributes(), "root modification"); | 2642 old_details.attributes(), "root modification"); |
2599 } | 2643 } |
2600 | 2644 |
2601 Map* updated = root_map->FindUpdatedMap( | 2645 Map* raw_updated = root_map->FindUpdatedMap( |
2602 verbatim, descriptors, old_descriptors); | 2646 verbatim, descriptors, *old_descriptors); |
2603 if (updated == NULL) { | 2647 if (raw_updated == NULL) { |
2604 return CopyGeneralizeAllRepresentations( | 2648 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2605 modify_index, store_mode, old_details.attributes(), "incompatible"); | 2649 old_details.attributes(), "incompatible"); |
2606 } | 2650 } |
2607 | 2651 |
2608 DescriptorArray* updated_descriptors = updated->instance_descriptors(); | 2652 Handle<Map> updated(raw_updated); |
2653 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); | |
2609 | 2654 |
2610 int valid = updated->NumberOfOwnDescriptors(); | 2655 int valid = updated->NumberOfOwnDescriptors(); |
2611 | 2656 |
2612 // Directly change the map if the target map is more general. Ensure that the | 2657 // Directly change the map if the target map is more general. Ensure that the |
2613 // target type of the modify_index is a FIELD, unless we are migrating. | 2658 // target type of the modify_index is a FIELD, unless we are migrating. |
2614 if (updated_descriptors->IsMoreGeneralThan( | 2659 if (updated_descriptors->IsMoreGeneralThan( |
2615 verbatim, valid, descriptors, old_descriptors) && | 2660 verbatim, valid, descriptors, *old_descriptors) && |
2616 (store_mode == ALLOW_AS_CONSTANT || | 2661 (store_mode == ALLOW_AS_CONSTANT || |
2617 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2662 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
2618 Representation updated_representation = | 2663 Representation updated_representation = |
2619 updated_descriptors->GetDetails(modify_index).representation(); | 2664 updated_descriptors->GetDetails(modify_index).representation(); |
2620 if (new_representation.fits_into(updated_representation)) return updated; | 2665 if (new_representation.fits_into(updated_representation)) return updated; |
2621 } | 2666 } |
2622 | 2667 |
2623 DescriptorArray* new_descriptors; | 2668 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( |
2624 MaybeObject* maybe_descriptors = updated_descriptors->Merge( | 2669 updated_descriptors, verbatim, valid, descriptors, modify_index, |
2625 verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); | 2670 store_mode, old_descriptors); |
2626 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
2627 ASSERT(store_mode == ALLOW_AS_CONSTANT || | 2671 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
2628 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2672 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2629 | 2673 |
2630 old_representation = | 2674 old_representation = |
2631 new_descriptors->GetDetails(modify_index).representation(); | 2675 new_descriptors->GetDetails(modify_index).representation(); |
2632 Representation updated_representation = | 2676 Representation updated_representation = |
2633 new_representation.generalize(old_representation); | 2677 new_representation.generalize(old_representation); |
2634 if (!updated_representation.Equals(old_representation)) { | 2678 if (!updated_representation.Equals(old_representation)) { |
2635 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2679 new_descriptors->SetRepresentation(modify_index, updated_representation); |
2636 } | 2680 } |
2637 | 2681 |
2638 Map* split_map = root_map->FindLastMatchMap( | 2682 Handle<Map> split_map(root_map->FindLastMatchMap( |
2639 verbatim, descriptors, new_descriptors); | 2683 verbatim, descriptors, *new_descriptors)); |
2640 | 2684 |
2641 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2685 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
2642 // This is shadowed by |updated_descriptors| being more general than | 2686 // This is shadowed by |updated_descriptors| being more general than |
2643 // |old_descriptors|. | 2687 // |old_descriptors|. |
2644 ASSERT(descriptors != split_descriptors); | 2688 ASSERT(descriptors != split_descriptors); |
2645 | 2689 |
2646 int descriptor = split_descriptors; | 2690 int descriptor = split_descriptors; |
2647 split_map->DeprecateTarget( | 2691 split_map->DeprecateTarget( |
2648 old_descriptors->GetKey(descriptor), new_descriptors); | 2692 old_descriptors->GetKey(descriptor), *new_descriptors); |
2649 | 2693 |
2650 if (FLAG_trace_generalization) { | 2694 if (FLAG_trace_generalization) { |
2651 PrintGeneralization( | 2695 old_map->PrintGeneralization( |
2652 stdout, "", modify_index, descriptor, descriptors, | 2696 stdout, "", modify_index, descriptor, descriptors, |
2653 old_descriptors->GetDetails(modify_index).type() == CONSTANT && | 2697 old_descriptors->GetDetails(modify_index).type() == CONSTANT && |
2654 store_mode == FORCE_FIELD, | 2698 store_mode == FORCE_FIELD, |
2655 old_representation, updated_representation); | 2699 old_representation, updated_representation); |
2656 } | 2700 } |
2657 | 2701 |
2658 Map* new_map = split_map; | |
2659 // Add missing transitions. | 2702 // Add missing transitions. |
2703 Handle<Map> new_map = split_map; | |
2660 for (; descriptor < descriptors; descriptor++) { | 2704 for (; descriptor < descriptors; descriptor++) { |
2661 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( | 2705 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
2662 descriptor, new_descriptors); | |
2663 if (!maybe_map->To(&new_map)) { | |
2664 // Create a handle for the last created map to ensure it stays alive | |
2665 // during GC. Its descriptor array is too large, but it will be | |
2666 // overwritten during retry anyway. | |
2667 Handle<Map>(new_map); | |
2668 return maybe_map; | |
2669 } | |
2670 new_map->set_migration_target(true); | 2706 new_map->set_migration_target(true); |
2671 } | 2707 } |
2672 | 2708 |
2673 new_map->set_owns_descriptors(true); | 2709 new_map->set_owns_descriptors(true); |
2674 return new_map; | 2710 return new_map; |
2675 } | 2711 } |
2676 | 2712 |
2677 | 2713 |
2678 Map* Map::CurrentMapForDeprecated() { | 2714 Map* Map::CurrentMapForDeprecated() { |
2679 DisallowHeapAllocation no_allocation; | 2715 DisallowHeapAllocation no_allocation; |
(...skipping 16 matching lines...) Expand all Loading... | |
2696 int valid = updated->NumberOfOwnDescriptors(); | 2732 int valid = updated->NumberOfOwnDescriptors(); |
2697 if (!updated_descriptors->IsMoreGeneralThan( | 2733 if (!updated_descriptors->IsMoreGeneralThan( |
2698 verbatim, valid, descriptors, old_descriptors)) { | 2734 verbatim, valid, descriptors, old_descriptors)) { |
2699 return NULL; | 2735 return NULL; |
2700 } | 2736 } |
2701 | 2737 |
2702 return updated; | 2738 return updated; |
2703 } | 2739 } |
2704 | 2740 |
2705 | 2741 |
2706 MaybeObject* JSObject::SetPropertyWithInterceptor( | 2742 Handle<Object> JSObject::SetPropertyWithInterceptor( |
2707 Name* name, | 2743 Handle<JSObject> object, |
2708 Object* value, | 2744 Handle<Name> name, |
2745 Handle<Object> value, | |
2709 PropertyAttributes attributes, | 2746 PropertyAttributes attributes, |
2710 StrictModeFlag strict_mode) { | 2747 StrictModeFlag strict_mode) { |
2711 // TODO(rossberg): Support symbols in the API. | 2748 // TODO(rossberg): Support symbols in the API. |
2712 if (name->IsSymbol()) return value; | 2749 if (name->IsSymbol()) return value; |
2713 Isolate* isolate = GetIsolate(); | 2750 Isolate* isolate = object->GetIsolate(); |
2714 HandleScope scope(isolate); | 2751 Handle<String> name_string = Handle<String>::cast(name); |
2715 Handle<JSObject> this_handle(this); | 2752 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
2716 Handle<String> name_handle(String::cast(name)); | |
2717 Handle<Object> value_handle(value, isolate); | |
2718 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | |
2719 if (!interceptor->setter()->IsUndefined()) { | 2753 if (!interceptor->setter()->IsUndefined()) { |
2720 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 2754 LOG(isolate, |
2721 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 2755 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); |
2756 PropertyCallbackArguments args( | |
2757 isolate, interceptor->data(), *object, *object); | |
2722 v8::NamedPropertySetterCallback setter = | 2758 v8::NamedPropertySetterCallback setter = |
2723 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); | 2759 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |
2724 Handle<Object> value_unhole(value->IsTheHole() ? | 2760 Handle<Object> value_unhole = value->IsTheHole() |
2725 isolate->heap()->undefined_value() : | 2761 ? Handle<Object>(isolate->factory()->undefined_value()) : value; |
2726 value, | |
2727 isolate); | |
2728 v8::Handle<v8::Value> result = args.Call(setter, | 2762 v8::Handle<v8::Value> result = args.Call(setter, |
2729 v8::Utils::ToLocal(name_handle), | 2763 v8::Utils::ToLocal(name_string), |
2730 v8::Utils::ToLocal(value_unhole)); | 2764 v8::Utils::ToLocal(value_unhole)); |
2731 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2765 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
2732 if (!result.IsEmpty()) return *value_handle; | 2766 if (!result.IsEmpty()) return value; |
2733 } | 2767 } |
2734 MaybeObject* raw_result = | 2768 Handle<Object> result = |
2735 this_handle->SetPropertyPostInterceptor(*name_handle, | 2769 SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); |
2736 *value_handle, | 2770 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
2737 attributes, | 2771 return result; |
2738 strict_mode); | |
2739 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
2740 return raw_result; | |
2741 } | 2772 } |
2742 | 2773 |
2743 | 2774 |
2744 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 2775 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
2745 Handle<Name> key, | 2776 Handle<Name> name, |
2746 Handle<Object> value, | 2777 Handle<Object> value, |
2747 PropertyAttributes attributes, | 2778 PropertyAttributes attributes, |
2748 StrictModeFlag strict_mode) { | 2779 StrictModeFlag strict_mode, |
2749 CALL_HEAP_FUNCTION(object->GetIsolate(), | 2780 StoreFromKeyed store_mode) { |
2750 object->SetProperty(*key, *value, attributes, strict_mode), | 2781 LookupResult result(object->GetIsolate()); |
2751 Object); | 2782 object->LocalLookup(*name, &result, true); |
2783 if (!result.IsFound()) { | |
2784 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); | |
2785 } | |
2786 return SetProperty(object, &result, name, value, attributes, strict_mode, | |
2787 store_mode); | |
2752 } | 2788 } |
2753 | 2789 |
2754 | 2790 |
2755 MaybeObject* JSReceiver::SetPropertyOrFail( | |
2756 Handle<JSReceiver> object, | |
2757 Handle<Name> key, | |
2758 Handle<Object> value, | |
2759 PropertyAttributes attributes, | |
2760 StrictModeFlag strict_mode, | |
2761 JSReceiver::StoreFromKeyed store_mode) { | |
2762 CALL_HEAP_FUNCTION_PASS_EXCEPTION( | |
2763 object->GetIsolate(), | |
2764 object->SetProperty(*key, *value, attributes, strict_mode, store_mode)); | |
2765 } | |
2766 | |
2767 | |
2768 MaybeObject* JSReceiver::SetProperty(Name* name, | |
2769 Object* value, | |
2770 PropertyAttributes attributes, | |
2771 StrictModeFlag strict_mode, | |
2772 JSReceiver::StoreFromKeyed store_mode) { | |
2773 LookupResult result(GetIsolate()); | |
2774 LocalLookup(name, &result, true); | |
2775 if (!result.IsFound()) { | |
2776 map()->LookupTransition(JSObject::cast(this), name, &result); | |
2777 } | |
2778 return SetProperty(&result, name, value, attributes, strict_mode, store_mode); | |
2779 } | |
2780 | |
2781 | |
2782 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 2791 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
2783 Name* name, | 2792 Name* name, |
2784 Object* value, | 2793 Object* value, |
2785 JSObject* holder, | 2794 JSObject* holder, |
2786 StrictModeFlag strict_mode) { | 2795 StrictModeFlag strict_mode) { |
2787 Isolate* isolate = GetIsolate(); | 2796 Isolate* isolate = GetIsolate(); |
2788 HandleScope scope(isolate); | 2797 HandleScope scope(isolate); |
2789 | 2798 |
2790 // We should never get here to initialize a const with the hole | 2799 // We should never get here to initialize a const with the hole |
2791 // value since a const declaration would conflict with the setter. | 2800 // value since a const declaration would conflict with the setter. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2923 value, | 2932 value, |
2924 JSObject::cast(pt), | 2933 JSObject::cast(pt), |
2925 strict_mode); | 2934 strict_mode); |
2926 } | 2935 } |
2927 } | 2936 } |
2928 } | 2937 } |
2929 *found = false; | 2938 *found = false; |
2930 return heap->the_hole_value(); | 2939 return heap->the_hole_value(); |
2931 } | 2940 } |
2932 | 2941 |
2933 MaybeObject* JSObject::SetPropertyViaPrototypes( | 2942 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
2934 Name* name, | 2943 Handle<Name> name, |
2935 Object* value, | 2944 Handle<Object> value, |
2936 PropertyAttributes attributes, | 2945 PropertyAttributes attributes, |
2937 StrictModeFlag strict_mode, | 2946 StrictModeFlag strict_mode, |
2938 bool* done) { | 2947 bool* done) { |
2939 Heap* heap = GetHeap(); | 2948 Isolate* isolate = object->GetIsolate(); |
2940 Isolate* isolate = heap->isolate(); | |
2941 | 2949 |
2942 *done = false; | 2950 *done = false; |
2943 // We could not find a local property so let's check whether there is an | 2951 // We could not find a local property so let's check whether there is an |
2944 // accessor that wants to handle the property, or whether the property is | 2952 // accessor that wants to handle the property, or whether the property is |
2945 // read-only on the prototype chain. | 2953 // read-only on the prototype chain. |
2946 LookupResult result(isolate); | 2954 LookupResult result(isolate); |
2947 LookupRealNamedPropertyInPrototypes(name, &result); | 2955 object->LookupRealNamedPropertyInPrototypes(*name, &result); |
2948 if (result.IsFound()) { | 2956 if (result.IsFound()) { |
2949 switch (result.type()) { | 2957 switch (result.type()) { |
2950 case NORMAL: | 2958 case NORMAL: |
2951 case FIELD: | 2959 case FIELD: |
2952 case CONSTANT: | 2960 case CONSTANT: |
2953 *done = result.IsReadOnly(); | 2961 *done = result.IsReadOnly(); |
2954 break; | 2962 break; |
2955 case INTERCEPTOR: { | 2963 case INTERCEPTOR: { |
2956 PropertyAttributes attr = | 2964 PropertyAttributes attr = |
2957 result.holder()->GetPropertyAttributeWithInterceptor( | 2965 result.holder()->GetPropertyAttributeWithInterceptor( |
2958 this, name, true); | 2966 *object, *name, true); |
2959 *done = !!(attr & READ_ONLY); | 2967 *done = !!(attr & READ_ONLY); |
2960 break; | 2968 break; |
2961 } | 2969 } |
2962 case CALLBACKS: { | 2970 case CALLBACKS: { |
2963 if (!FLAG_es5_readonly && result.IsReadOnly()) break; | 2971 if (!FLAG_es5_readonly && result.IsReadOnly()) break; |
2964 *done = true; | 2972 *done = true; |
2965 return SetPropertyWithCallback(result.GetCallbackObject(), | 2973 CALL_HEAP_FUNCTION(isolate, |
2966 name, value, result.holder(), strict_mode); | 2974 object->SetPropertyWithCallback( |
2975 result.GetCallbackObject(), | |
2976 *name, *value, result.holder(), strict_mode), | |
2977 Object); | |
2967 } | 2978 } |
2968 case HANDLER: { | 2979 case HANDLER: { |
2969 return result.proxy()->SetPropertyViaPrototypesWithHandler( | 2980 CALL_HEAP_FUNCTION(isolate, |
2970 this, name, value, attributes, strict_mode, done); | 2981 result.proxy()->SetPropertyViaPrototypesWithHandler( |
2982 *object, *name, *value, attributes, strict_mode, | |
2983 done), | |
2984 Object); | |
2971 } | 2985 } |
2972 case TRANSITION: | 2986 case TRANSITION: |
2973 case NONEXISTENT: | 2987 case NONEXISTENT: |
2974 UNREACHABLE(); | 2988 UNREACHABLE(); |
2975 break; | 2989 break; |
2976 } | 2990 } |
2977 } | 2991 } |
2978 | 2992 |
2979 // If we get here with *done true, we have encountered a read-only property. | 2993 // If we get here with *done true, we have encountered a read-only property. |
2980 if (!FLAG_es5_readonly) *done = false; | 2994 if (!FLAG_es5_readonly) *done = false; |
2981 if (*done) { | 2995 if (*done) { |
2982 if (strict_mode == kNonStrictMode) return value; | 2996 if (strict_mode == kNonStrictMode) return value; |
2983 Handle<Object> args[] = { Handle<Object>(name, isolate), | 2997 Handle<Object> args[] = { name, object }; |
2984 Handle<Object>(this, isolate)}; | 2998 Handle<Object> error = isolate->factory()->NewTypeError( |
2985 return isolate->Throw(*isolate->factory()->NewTypeError( | 2999 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
2986 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 3000 isolate->Throw(*error); |
3001 return Handle<Object>(); | |
2987 } | 3002 } |
2988 return heap->the_hole_value(); | 3003 return isolate->factory()->the_hole_value(); |
2989 } | 3004 } |
2990 | 3005 |
2991 | 3006 |
2992 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 3007 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
2993 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 3008 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
2994 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 3009 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
2995 int number_of_descriptors = descriptors->number_of_descriptors(); | 3010 int number_of_descriptors = descriptors->number_of_descriptors(); |
2996 Isolate* isolate = map->GetIsolate(); | 3011 Isolate* isolate = map->GetIsolate(); |
2997 Handle<DescriptorArray> new_descriptors = | 3012 Handle<DescriptorArray> new_descriptors = |
2998 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); | 3013 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3399 | 3414 |
3400 Isolate* isolate = GetIsolate(); | 3415 Isolate* isolate = GetIsolate(); |
3401 HandleScope scope(isolate); | 3416 HandleScope scope(isolate); |
3402 Handle<Object> value_handle(value, isolate); | 3417 Handle<Object> value_handle(value, isolate); |
3403 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3418 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
3404 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 3419 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
3405 return *value_handle; | 3420 return *value_handle; |
3406 } | 3421 } |
3407 | 3422 |
3408 | 3423 |
3409 MaybeObject* JSReceiver::SetProperty(LookupResult* result, | 3424 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
3410 Name* key, | 3425 LookupResult* result, |
3411 Object* value, | 3426 Handle<Name> key, |
3412 PropertyAttributes attributes, | 3427 Handle<Object> value, |
3413 StrictModeFlag strict_mode, | 3428 PropertyAttributes attributes, |
3414 JSReceiver::StoreFromKeyed store_mode) { | 3429 StrictModeFlag strict_mode, |
3430 StoreFromKeyed store_mode) { | |
3415 if (result->IsHandler()) { | 3431 if (result->IsHandler()) { |
3416 return result->proxy()->SetPropertyWithHandler( | 3432 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), |
3417 this, key, value, attributes, strict_mode); | 3433 object, key, value, attributes, strict_mode); |
3418 } else { | 3434 } else { |
3419 return JSObject::cast(this)->SetPropertyForResult( | 3435 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object), |
3420 result, key, value, attributes, strict_mode, store_mode); | 3436 result, key, value, attributes, strict_mode, store_mode); |
3421 } | 3437 } |
3422 } | 3438 } |
3423 | 3439 |
3424 | 3440 |
3425 bool JSProxy::HasPropertyWithHandler(Name* name_raw) { | 3441 bool JSProxy::HasPropertyWithHandler(Name* name_raw) { |
3426 Isolate* isolate = GetIsolate(); | 3442 Isolate* isolate = GetIsolate(); |
3427 HandleScope scope(isolate); | 3443 HandleScope scope(isolate); |
3428 Handle<Object> receiver(this, isolate); | 3444 Handle<Object> receiver(this, isolate); |
3429 Handle<Object> name(name_raw, isolate); | 3445 Handle<Object> name(name_raw, isolate); |
3430 | 3446 |
3431 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3447 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3432 if (name->IsSymbol()) return false; | 3448 if (name->IsSymbol()) return false; |
3433 | 3449 |
3434 Handle<Object> args[] = { name }; | 3450 Handle<Object> args[] = { name }; |
3435 Handle<Object> result = CallTrap( | 3451 Handle<Object> result = CallTrap( |
3436 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); | 3452 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); |
3437 if (isolate->has_pending_exception()) return false; | 3453 if (isolate->has_pending_exception()) return false; |
3438 | 3454 |
3439 return result->BooleanValue(); | 3455 return result->BooleanValue(); |
3440 } | 3456 } |
3441 | 3457 |
3442 | 3458 |
3443 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( | 3459 Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
3444 JSReceiver* receiver_raw, | 3460 Handle<JSReceiver> receiver, |
3445 Name* name_raw, | 3461 Handle<Name> name, |
3446 Object* value_raw, | 3462 Handle<Object> value, |
3447 PropertyAttributes attributes, | 3463 PropertyAttributes attributes, |
3448 StrictModeFlag strict_mode) { | 3464 StrictModeFlag strict_mode) { |
3449 Isolate* isolate = GetIsolate(); | 3465 Isolate* isolate = proxy->GetIsolate(); |
3450 HandleScope scope(isolate); | |
3451 Handle<JSReceiver> receiver(receiver_raw); | |
3452 Handle<Object> name(name_raw, isolate); | |
3453 Handle<Object> value(value_raw, isolate); | |
3454 | 3466 |
3455 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3467 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3456 if (name->IsSymbol()) return *value; | 3468 if (name->IsSymbol()) return value; |
3457 | 3469 |
3458 Handle<Object> args[] = { receiver, name, value }; | 3470 Handle<Object> args[] = { receiver, name, value }; |
3459 CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); | 3471 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); |
3460 if (isolate->has_pending_exception()) return Failure::Exception(); | 3472 if (isolate->has_pending_exception()) return Handle<Object>(); |
3461 | 3473 |
3462 return *value; | 3474 return value; |
3463 } | 3475 } |
3464 | 3476 |
3465 | 3477 |
3466 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( | 3478 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( |
3467 JSReceiver* receiver_raw, | 3479 JSReceiver* receiver_raw, |
3468 Name* name_raw, | 3480 Name* name_raw, |
3469 Object* value_raw, | 3481 Object* value_raw, |
3470 PropertyAttributes attributes, | 3482 PropertyAttributes attributes, |
3471 StrictModeFlag strict_mode, | 3483 StrictModeFlag strict_mode, |
3472 bool* done) { | 3484 bool* done) { |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3727 | 3739 |
3728 | 3740 |
3729 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { | 3741 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
3730 CALL_HEAP_FUNCTION_VOID( | 3742 CALL_HEAP_FUNCTION_VOID( |
3731 object->GetIsolate(), | 3743 object->GetIsolate(), |
3732 object->AllocateStorageForMap(*map)); | 3744 object->AllocateStorageForMap(*map)); |
3733 } | 3745 } |
3734 | 3746 |
3735 | 3747 |
3736 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3748 void JSObject::MigrateInstance(Handle<JSObject> object) { |
3737 CALL_HEAP_FUNCTION_VOID( | 3749 // Converting any field to the most specific type will cause the |
3738 object->GetIsolate(), | 3750 // GeneralizeFieldRepresentation algorithm to create the most general existing |
3739 object->MigrateInstance()); | 3751 // transition that matches the object. This achieves what is needed. |
3752 Handle<Map> original_map(object->map()); | |
3753 GeneralizeFieldRepresentation( | |
3754 object, 0, Representation::None(), ALLOW_AS_CONSTANT); | |
3755 if (FLAG_trace_migration) { | |
3756 object->PrintInstanceMigration(stdout, *original_map, object->map()); | |
3757 } | |
3740 } | 3758 } |
3741 | 3759 |
3742 | 3760 |
3743 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3761 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
3744 CALL_HEAP_FUNCTION( | 3762 MigrateInstance(object); |
3745 object->GetIsolate(), | 3763 return object; |
3746 object->MigrateInstance(), | |
3747 Object); | |
3748 } | 3764 } |
3749 | 3765 |
3750 | 3766 |
3751 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, | 3767 Handle<Object> JSObject::SetPropertyUsingTransition( |
3752 int modify_index, | 3768 LookupResult* lookup, |
3753 Representation representation, | 3769 Handle<Name> name, |
3754 StoreMode store_mode) { | 3770 Handle<Object> value, |
3755 CALL_HEAP_FUNCTION( | 3771 PropertyAttributes attributes) { |
3756 map->GetIsolate(), | 3772 Handle<Map> transition_map(lookup->GetTransitionTarget()); |
3757 map->GeneralizeRepresentation(modify_index, representation, store_mode), | |
3758 Map); | |
3759 } | |
3760 | |
3761 | |
3762 static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, | |
3763 Handle<Name> name, | |
3764 Handle<Object> value, | |
3765 PropertyAttributes attributes) { | |
3766 Map* transition_map = lookup->GetTransitionTarget(); | |
3767 int descriptor = transition_map->LastAdded(); | 3773 int descriptor = transition_map->LastAdded(); |
3768 | 3774 |
3769 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3775 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
3770 PropertyDetails details = descriptors->GetDetails(descriptor); | 3776 PropertyDetails details = descriptors->GetDetails(descriptor); |
3771 | 3777 |
3772 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3778 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
3773 // AddProperty will either normalize the object, or create a new fast copy | 3779 // AddProperty will either normalize the object, or create a new fast copy |
3774 // of the map. If we get a fast copy of the map, all field representations | 3780 // of the map. If we get a fast copy of the map, all field representations |
3775 // will be tagged since the transition is omitted. | 3781 // will be tagged since the transition is omitted. |
3776 return lookup->holder()->AddProperty( | 3782 return JSObject::AddProperty( |
3777 *name, *value, attributes, kNonStrictMode, | 3783 handle(lookup->holder()), name, value, attributes, kNonStrictMode, |
Toon Verwaest
2013/09/16 16:37:50
what about getting the receiver as input directly
Michael Starzinger
2013/09/17 10:44:16
Done.
| |
3778 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 3784 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
3779 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 3785 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
3780 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 3786 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
3781 } | 3787 } |
3782 | 3788 |
3783 // Keep the target CONSTANT if the same value is stored. | 3789 // Keep the target CONSTANT if the same value is stored. |
3784 // TODO(verwaest): Also support keeping the placeholder | 3790 // TODO(verwaest): Also support keeping the placeholder |
3785 // (value->IsUninitialized) as constant. | 3791 // (value->IsUninitialized) as constant. |
3786 if (details.type() == CONSTANT && | 3792 if (details.type() == CONSTANT && |
3787 descriptors->GetValue(descriptor) == *value) { | 3793 descriptors->GetValue(descriptor) == *value) { |
3788 lookup->holder()->set_map(transition_map); | 3794 lookup->holder()->set_map(*transition_map); |
3789 return *value; | 3795 return value; |
3790 } | 3796 } |
3791 | 3797 |
3792 Representation representation = details.representation(); | 3798 Representation representation = details.representation(); |
3793 | 3799 |
3794 if (!value->FitsRepresentation(representation) || | 3800 if (!value->FitsRepresentation(representation) || |
3795 details.type() == CONSTANT) { | 3801 details.type() == CONSTANT) { |
3796 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | 3802 transition_map = Map::GeneralizeRepresentation(transition_map, |
3797 descriptor, value->OptimalRepresentation(), FORCE_FIELD); | 3803 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
3798 if (!maybe_map->To(&transition_map)) return maybe_map; | |
3799 Object* back = transition_map->GetBackPointer(); | 3804 Object* back = transition_map->GetBackPointer(); |
3800 if (back->IsMap()) { | 3805 if (back->IsMap()) { |
3801 MaybeObject* maybe_failure = | 3806 MigrateToMap(handle(lookup->holder()), handle(Map::cast(back))); |
3802 lookup->holder()->MigrateToMap(Map::cast(back)); | |
3803 if (maybe_failure->IsFailure()) return maybe_failure; | |
3804 } | 3807 } |
3805 descriptors = transition_map->instance_descriptors(); | 3808 descriptors = transition_map->instance_descriptors(); |
3806 representation = descriptors->GetDetails(descriptor).representation(); | 3809 representation = descriptors->GetDetails(descriptor).representation(); |
3807 } | 3810 } |
3808 | 3811 |
3809 int field_index = descriptors->GetFieldIndex(descriptor); | 3812 int field_index = descriptors->GetFieldIndex(descriptor); |
3810 return lookup->holder()->AddFastPropertyUsingMap( | 3813 return AddFastPropertyUsingMap(handle(lookup->holder()), |
3811 transition_map, *name, *value, field_index, representation); | 3814 transition_map, name, value, field_index, representation); |
3812 } | 3815 } |
3813 | 3816 |
3814 | 3817 |
3815 static MaybeObject* SetPropertyToField(LookupResult* lookup, | 3818 static Handle<Object> SetPropertyToField(LookupResult* lookup, |
3816 Handle<Name> name, | 3819 Handle<Name> name, |
3817 Handle<Object> value) { | 3820 Handle<Object> value) { |
3818 Representation representation = lookup->representation(); | 3821 Representation representation = lookup->representation(); |
3819 if (!value->FitsRepresentation(representation) || | 3822 if (!value->FitsRepresentation(representation) || |
3820 lookup->type() == CONSTANT) { | 3823 lookup->type() == CONSTANT) { |
3821 MaybeObject* maybe_failure = | 3824 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), |
3822 lookup->holder()->GeneralizeFieldRepresentation( | 3825 lookup->GetDescriptorIndex(), |
3823 lookup->GetDescriptorIndex(), | 3826 value->OptimalRepresentation(), |
3824 value->OptimalRepresentation(), | 3827 FORCE_FIELD); |
3825 FORCE_FIELD); | |
3826 if (maybe_failure->IsFailure()) return maybe_failure; | |
3827 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 3828 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
3828 int descriptor = lookup->GetDescriptorIndex(); | 3829 int descriptor = lookup->GetDescriptorIndex(); |
3829 representation = desc->GetDetails(descriptor).representation(); | 3830 representation = desc->GetDetails(descriptor).representation(); |
3830 } | 3831 } |
3831 | 3832 |
3832 if (FLAG_track_double_fields && representation.IsDouble()) { | 3833 if (FLAG_track_double_fields && representation.IsDouble()) { |
3833 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 3834 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
3834 lookup->GetFieldIndex().field_index())); | 3835 lookup->GetFieldIndex().field_index())); |
3835 storage->set_value(value->Number()); | 3836 storage->set_value(value->Number()); |
3836 return *value; | 3837 return value; |
3837 } | 3838 } |
3838 | 3839 |
3839 lookup->holder()->FastPropertyAtPut( | 3840 lookup->holder()->FastPropertyAtPut( |
3840 lookup->GetFieldIndex().field_index(), *value); | 3841 lookup->GetFieldIndex().field_index(), *value); |
3841 return *value; | 3842 return value; |
3842 } | 3843 } |
3843 | 3844 |
3844 | 3845 |
3845 static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup, | 3846 static Handle<Object> ConvertAndSetLocalProperty( |
3846 Name* name, | 3847 LookupResult* lookup, |
3847 Object* value, | 3848 Handle<Name> name, |
3848 PropertyAttributes attributes) { | 3849 Handle<Object> value, |
3849 JSObject* object = lookup->holder(); | 3850 PropertyAttributes attributes) { |
3851 Handle<JSObject> object(lookup->holder()); | |
3850 if (object->TooManyFastProperties()) { | 3852 if (object->TooManyFastProperties()) { |
3851 MaybeObject* maybe_failure = object->NormalizeProperties( | 3853 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
3852 CLEAR_INOBJECT_PROPERTIES, 0); | |
3853 if (maybe_failure->IsFailure()) return maybe_failure; | |
3854 } | 3854 } |
3855 | 3855 |
3856 if (!object->HasFastProperties()) { | 3856 if (!object->HasFastProperties()) { |
3857 return object->ReplaceSlowProperty(name, value, attributes); | 3857 return ReplaceSlowProperty(object, name, value, attributes); |
3858 } | 3858 } |
3859 | 3859 |
3860 int descriptor_index = lookup->GetDescriptorIndex(); | 3860 int descriptor_index = lookup->GetDescriptorIndex(); |
3861 if (lookup->GetAttributes() == attributes) { | 3861 if (lookup->GetAttributes() == attributes) { |
3862 MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation( | 3862 JSObject::GeneralizeFieldRepresentation( |
3863 descriptor_index, Representation::Tagged(), FORCE_FIELD); | 3863 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); |
3864 if (maybe_failure->IsFailure()) return maybe_failure; | |
3865 } else { | 3864 } else { |
3866 Map* map; | 3865 Handle<Map> old_map(object->map()); |
3867 MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations( | 3866 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, |
3868 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | 3867 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
3869 if (!maybe_map->To(&map)) return maybe_map; | 3868 JSObject::MigrateToMap(object, new_map); |
3870 MaybeObject* maybe_failure = object->MigrateToMap(map); | |
3871 if (maybe_failure->IsFailure()) return maybe_failure; | |
3872 } | 3869 } |
3873 | 3870 |
3874 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 3871 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
3875 int index = descriptors->GetDetails(descriptor_index).field_index(); | 3872 int index = descriptors->GetDetails(descriptor_index).field_index(); |
3876 object->FastPropertyAtPut(index, value); | 3873 object->FastPropertyAtPut(index, *value); |
3877 return value; | 3874 return value; |
3878 } | 3875 } |
3879 | 3876 |
3880 | 3877 |
3881 static MaybeObject* SetPropertyToFieldWithAttributes( | 3878 static Handle<Object> SetPropertyToFieldWithAttributes( |
3882 LookupResult* lookup, | 3879 LookupResult* lookup, |
3883 Handle<Name> name, | 3880 Handle<Name> name, |
3884 Handle<Object> value, | 3881 Handle<Object> value, |
3885 PropertyAttributes attributes) { | 3882 PropertyAttributes attributes) { |
3886 if (lookup->GetAttributes() == attributes) { | 3883 if (lookup->GetAttributes() == attributes) { |
3887 if (value->IsUninitialized()) return *value; | 3884 if (value->IsUninitialized()) return value; |
3888 return SetPropertyToField(lookup, name, value); | 3885 return SetPropertyToField(lookup, name, value); |
3889 } else { | 3886 } else { |
3890 return ConvertAndSetLocalProperty(lookup, *name, *value, attributes); | 3887 return ConvertAndSetLocalProperty(lookup, name, value, attributes); |
3891 } | 3888 } |
3892 } | 3889 } |
3893 | 3890 |
3894 | 3891 |
3895 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, | 3892 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, |
3896 Name* name_raw, | 3893 LookupResult* lookup, |
3897 Object* value_raw, | 3894 Handle<Name> name, |
3898 PropertyAttributes attributes, | 3895 Handle<Object> value, |
3899 StrictModeFlag strict_mode, | 3896 PropertyAttributes attributes, |
3900 StoreFromKeyed store_mode) { | 3897 StrictModeFlag strict_mode, |
3901 Heap* heap = GetHeap(); | 3898 StoreFromKeyed store_mode) { |
3902 Isolate* isolate = heap->isolate(); | 3899 Isolate* isolate = object->GetIsolate(); |
3903 | 3900 |
3904 // Make sure that the top context does not change when doing callbacks or | 3901 // Make sure that the top context does not change when doing callbacks or |
3905 // interceptor calls. | 3902 // interceptor calls. |
3906 AssertNoContextChangeWithHandleScope ncc; | 3903 AssertNoContextChange ncc; |
3907 | 3904 |
3908 // Optimization for 2-byte strings often used as keys in a decompression | 3905 // Optimization for 2-byte strings often used as keys in a decompression |
3909 // dictionary. We internalize these short keys to avoid constantly | 3906 // dictionary. We internalize these short keys to avoid constantly |
3910 // reallocating them. | 3907 // reallocating them. |
3911 if (name_raw->IsString() && !name_raw->IsInternalizedString() && | 3908 if (name->IsString() && !name->IsInternalizedString() && |
3912 String::cast(name_raw)->length() <= 2) { | 3909 Handle<String>::cast(name)->length() <= 2) { |
3913 Object* internalized_version; | 3910 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); |
3914 { MaybeObject* maybe_string_version = | 3911 } |
3915 heap->InternalizeString(String::cast(name_raw)); | 3912 |
3916 if (maybe_string_version->ToObject(&internalized_version)) { | 3913 // Check access rights if needed. |
3917 name_raw = String::cast(internalized_version); | 3914 if (object->IsAccessCheckNeeded()) { |
3918 } | 3915 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
3916 CALL_HEAP_FUNCTION( | |
3917 isolate, | |
3918 object->SetPropertyWithFailedAccessCheck( | |
3919 lookup, *name, *value, true, strict_mode), | |
3920 Object); | |
3919 } | 3921 } |
3920 } | 3922 } |
3921 | 3923 |
3922 // Check access rights if needed. | 3924 if (object->IsJSGlobalProxy()) { |
3923 if (IsAccessCheckNeeded()) { | 3925 Handle<Object> proto(object->GetPrototype(), isolate); |
3924 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 3926 if (proto->IsNull()) return value; |
3925 return SetPropertyWithFailedAccessCheck( | 3927 ASSERT(proto->IsJSGlobalObject()); |
3926 lookup, name_raw, value_raw, true, strict_mode); | 3928 return SetPropertyForResult(Handle<JSObject>::cast(proto), |
3927 } | 3929 lookup, name, value, attributes, strict_mode, store_mode); |
3928 } | 3930 } |
3929 | 3931 |
3930 if (IsJSGlobalProxy()) { | 3932 ASSERT(!lookup->IsFound() || lookup->holder() == *object || |
3931 Object* proto = GetPrototype(); | |
3932 if (proto->IsNull()) return value_raw; | |
3933 ASSERT(proto->IsJSGlobalObject()); | |
3934 return JSObject::cast(proto)->SetPropertyForResult( | |
3935 lookup, name_raw, value_raw, attributes, strict_mode, store_mode); | |
3936 } | |
3937 | |
3938 ASSERT(!lookup->IsFound() || lookup->holder() == this || | |
3939 lookup->holder()->map()->is_hidden_prototype()); | 3933 lookup->holder()->map()->is_hidden_prototype()); |
3940 | 3934 |
3941 // From this point on everything needs to be handlified, because | 3935 if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) { |
3942 // SetPropertyViaPrototypes might call back into JavaScript. | |
3943 HandleScope scope(isolate); | |
3944 Handle<JSObject> self(this); | |
3945 Handle<Name> name(name_raw); | |
3946 Handle<Object> value(value_raw, isolate); | |
3947 | |
3948 if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { | |
3949 bool done = false; | 3936 bool done = false; |
3950 MaybeObject* result_object = self->SetPropertyViaPrototypes( | 3937 Handle<Object> result_object = SetPropertyViaPrototypes( |
3951 *name, *value, attributes, strict_mode, &done); | 3938 object, name, value, attributes, strict_mode, &done); |
3952 if (done) return result_object; | 3939 if (done) return result_object; |
3953 } | 3940 } |
3954 | 3941 |
3955 if (!lookup->IsFound()) { | 3942 if (!lookup->IsFound()) { |
3956 // Neither properties nor transitions found. | 3943 // Neither properties nor transitions found. |
3957 return self->AddProperty( | 3944 return AddProperty( |
3958 *name, *value, attributes, strict_mode, store_mode); | 3945 object, name, value, attributes, strict_mode, store_mode); |
3959 } | 3946 } |
3960 | 3947 |
3961 if (lookup->IsProperty() && lookup->IsReadOnly()) { | 3948 if (lookup->IsProperty() && lookup->IsReadOnly()) { |
3962 if (strict_mode == kStrictMode) { | 3949 if (strict_mode == kStrictMode) { |
3963 Handle<Object> args[] = { name, self }; | 3950 Handle<Object> args[] = { name, object }; |
3964 return isolate->Throw(*isolate->factory()->NewTypeError( | 3951 Handle<Object> error = isolate->factory()->NewTypeError( |
3965 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 3952 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
3953 isolate->Throw(*error); | |
3954 return Handle<Object>(); | |
3966 } else { | 3955 } else { |
3967 return *value; | 3956 return value; |
3968 } | 3957 } |
3969 } | 3958 } |
3970 | 3959 |
3971 Handle<Object> old_value(heap->the_hole_value(), isolate); | 3960 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
3972 if (FLAG_harmony_observation && | 3961 if (FLAG_harmony_observation && |
3973 map()->is_observed() && lookup->IsDataProperty()) { | 3962 object->map()->is_observed() && lookup->IsDataProperty()) { |
3974 old_value = Object::GetProperty(self, name); | 3963 old_value = Object::GetProperty(object, name); |
3975 } | 3964 } |
3976 | 3965 |
3977 // This is a real property that is not read-only, or it is a | 3966 // This is a real property that is not read-only, or it is a |
3978 // transition or null descriptor and there are no setters in the prototypes. | 3967 // transition or null descriptor and there are no setters in the prototypes. |
3979 MaybeObject* result = *value; | 3968 Handle<Object> result = value; |
3980 switch (lookup->type()) { | 3969 switch (lookup->type()) { |
3981 case NORMAL: | 3970 case NORMAL: |
3982 result = lookup->holder()->SetNormalizedProperty(lookup, *value); | 3971 result = SetNormalizedProperty(handle(lookup->holder()), lookup, value); |
3983 break; | 3972 break; |
3984 case FIELD: | 3973 case FIELD: |
3985 result = SetPropertyToField(lookup, name, value); | 3974 result = SetPropertyToField(lookup, name, value); |
3986 break; | 3975 break; |
3987 case CONSTANT: | 3976 case CONSTANT: |
3988 // Only replace the constant if necessary. | 3977 // Only replace the constant if necessary. |
3989 if (*value == lookup->GetConstant()) return *value; | 3978 if (*value == lookup->GetConstant()) return value; |
3990 result = SetPropertyToField(lookup, name, value); | 3979 result = SetPropertyToField(lookup, name, value); |
3991 break; | 3980 break; |
3992 case CALLBACKS: { | 3981 case CALLBACKS: { |
3993 Object* callback_object = lookup->GetCallbackObject(); | 3982 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); |
3994 return self->SetPropertyWithCallback( | 3983 CALL_HEAP_FUNCTION( |
3995 callback_object, *name, *value, lookup->holder(), strict_mode); | 3984 isolate, |
3985 object->SetPropertyWithCallback(*callback_object, *name, *value, | |
3986 lookup->holder(), strict_mode), | |
3987 Object); | |
3996 } | 3988 } |
3997 case INTERCEPTOR: | 3989 case INTERCEPTOR: |
3998 result = lookup->holder()->SetPropertyWithInterceptor( | 3990 result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value, |
3999 *name, *value, attributes, strict_mode); | 3991 attributes, strict_mode); |
4000 break; | 3992 break; |
4001 case TRANSITION: { | 3993 case TRANSITION: |
4002 result = SetPropertyUsingTransition(lookup, name, value, attributes); | 3994 result = SetPropertyUsingTransition(lookup, name, value, attributes); |
4003 break; | 3995 break; |
4004 } | |
4005 case HANDLER: | 3996 case HANDLER: |
4006 case NONEXISTENT: | 3997 case NONEXISTENT: |
4007 UNREACHABLE(); | 3998 UNREACHABLE(); |
4008 } | 3999 } |
4009 | 4000 |
4010 Handle<Object> hresult; | 4001 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
4011 if (!result->ToHandle(&hresult, isolate)) return result; | |
4012 | 4002 |
4013 if (FLAG_harmony_observation && self->map()->is_observed()) { | 4003 if (FLAG_harmony_observation && object->map()->is_observed()) { |
4014 if (lookup->IsTransition()) { | 4004 if (lookup->IsTransition()) { |
4015 EnqueueChangeRecord(self, "new", name, old_value); | 4005 EnqueueChangeRecord(object, "new", name, old_value); |
4016 } else { | 4006 } else { |
4017 LookupResult new_lookup(isolate); | 4007 LookupResult new_lookup(isolate); |
4018 self->LocalLookup(*name, &new_lookup, true); | 4008 object->LocalLookup(*name, &new_lookup, true); |
4019 if (new_lookup.IsDataProperty()) { | 4009 if (new_lookup.IsDataProperty()) { |
4020 Handle<Object> new_value = Object::GetProperty(self, name); | 4010 Handle<Object> new_value = Object::GetProperty(object, name); |
4021 if (!new_value->SameValue(*old_value)) { | 4011 if (!new_value->SameValue(*old_value)) { |
4022 EnqueueChangeRecord(self, "updated", name, old_value); | 4012 EnqueueChangeRecord(object, "updated", name, old_value); |
4023 } | 4013 } |
4024 } | 4014 } |
4025 } | 4015 } |
4026 } | 4016 } |
4027 | 4017 |
4028 return *hresult; | 4018 return result; |
4029 } | 4019 } |
4030 | 4020 |
4031 | 4021 |
4032 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( | 4022 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( |
4033 Name* key, | 4023 Name* key, |
4034 Object* value, | 4024 Object* value, |
4035 PropertyAttributes attributes, | 4025 PropertyAttributes attributes, |
4036 ValueType value_type, | 4026 ValueType value_type, |
4037 StoreMode mode, | 4027 StoreMode mode, |
4038 ExtensibilityCheck extensibility_check) { | 4028 ExtensibilityCheck extensibility_check) { |
(...skipping 17 matching lines...) Expand all Loading... | |
4056 // present, add it with attributes NONE. This code is an exact clone of | 4046 // present, add it with attributes NONE. This code is an exact clone of |
4057 // SetProperty, with the check for IsReadOnly and the check for a | 4047 // SetProperty, with the check for IsReadOnly and the check for a |
4058 // callback setter removed. The two lines looking up the LookupResult | 4048 // callback setter removed. The two lines looking up the LookupResult |
4059 // result are also added. If one of the functions is changed, the other | 4049 // result are also added. If one of the functions is changed, the other |
4060 // should be. | 4050 // should be. |
4061 // Note that this method cannot be used to set the prototype of a function | 4051 // Note that this method cannot be used to set the prototype of a function |
4062 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" | 4052 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
4063 // doesn't handle function prototypes correctly. | 4053 // doesn't handle function prototypes correctly. |
4064 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( | 4054 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( |
4065 Handle<JSObject> object, | 4055 Handle<JSObject> object, |
4066 Handle<Name> key, | 4056 Handle<Name> name, |
4067 Handle<Object> value, | 4057 Handle<Object> value, |
4068 PropertyAttributes attributes, | 4058 PropertyAttributes attributes, |
4069 ValueType value_type, | 4059 ValueType value_type, |
4070 StoreMode mode, | 4060 StoreMode mode, |
4071 ExtensibilityCheck extensibility_check) { | 4061 ExtensibilityCheck extensibility_check) { |
4072 CALL_HEAP_FUNCTION( | 4062 Isolate* isolate = object->GetIsolate(); |
4073 object->GetIsolate(), | |
4074 object->SetLocalPropertyIgnoreAttributes( | |
4075 *key, *value, attributes, value_type, mode, extensibility_check), | |
4076 Object); | |
4077 } | |
4078 | 4063 |
4079 | |
4080 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | |
4081 Name* name_raw, | |
4082 Object* value_raw, | |
4083 PropertyAttributes attributes, | |
4084 ValueType value_type, | |
4085 StoreMode mode, | |
4086 ExtensibilityCheck extensibility_check) { | |
4087 // Make sure that the top context does not change when doing callbacks or | 4064 // Make sure that the top context does not change when doing callbacks or |
4088 // interceptor calls. | 4065 // interceptor calls. |
4089 AssertNoContextChangeWithHandleScope ncc; | 4066 AssertNoContextChange ncc; |
4090 Isolate* isolate = GetIsolate(); | 4067 |
4091 LookupResult lookup(isolate); | 4068 LookupResult lookup(isolate); |
4092 LocalLookup(name_raw, &lookup, true); | 4069 object->LocalLookup(*name, &lookup, true); |
4093 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup); | 4070 if (!lookup.IsFound()) { |
4071 object->map()->LookupTransition(*object, *name, &lookup); | |
4072 } | |
4073 | |
4094 // Check access rights if needed. | 4074 // Check access rights if needed. |
4095 if (IsAccessCheckNeeded()) { | 4075 if (object->IsAccessCheckNeeded()) { |
4096 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 4076 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
4097 return SetPropertyWithFailedAccessCheck(&lookup, | 4077 CALL_HEAP_FUNCTION( |
4098 name_raw, | 4078 isolate, |
4099 value_raw, | 4079 object->SetPropertyWithFailedAccessCheck( |
4100 false, | 4080 &lookup, *name, *value, false, kNonStrictMode), |
4101 kNonStrictMode); | 4081 Object); |
4102 } | 4082 } |
4103 } | 4083 } |
4104 | 4084 |
4105 if (IsJSGlobalProxy()) { | 4085 if (object->IsJSGlobalProxy()) { |
4106 Object* proto = GetPrototype(); | 4086 Handle<Object> proto(object->GetPrototype(), isolate); |
4107 if (proto->IsNull()) return value_raw; | 4087 if (proto->IsNull()) return value; |
4108 ASSERT(proto->IsJSGlobalObject()); | 4088 ASSERT(proto->IsJSGlobalObject()); |
4109 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( | 4089 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), |
4110 name_raw, | 4090 name, value, attributes, value_type, mode, extensibility_check); |
4111 value_raw, | |
4112 attributes, | |
4113 value_type, | |
4114 mode, | |
4115 extensibility_check); | |
4116 } | 4091 } |
4117 | 4092 |
4118 if (lookup.IsFound() && | 4093 if (lookup.IsFound() && |
4119 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { | 4094 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { |
4120 LocalLookupRealNamedProperty(name_raw, &lookup); | 4095 object->LocalLookupRealNamedProperty(*name, &lookup); |
4121 } | 4096 } |
4122 | 4097 |
4123 // Check for accessor in prototype chain removed here in clone. | 4098 // Check for accessor in prototype chain removed here in clone. |
4124 if (!lookup.IsFound()) { | 4099 if (!lookup.IsFound()) { |
4125 // Neither properties nor transitions found. | 4100 // Neither properties nor transitions found. |
4126 return AddProperty( | 4101 return AddProperty(object, name, value, attributes, kNonStrictMode, |
4127 name_raw, value_raw, attributes, kNonStrictMode, | |
4128 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | 4102 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); |
4129 } | 4103 } |
4130 | 4104 |
4131 // From this point on everything needs to be handlified. | 4105 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
4132 HandleScope scope(isolate); | |
4133 Handle<JSObject> self(this); | |
4134 Handle<Name> name(name_raw); | |
4135 Handle<Object> value(value_raw, isolate); | |
4136 | |
4137 Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate); | |
4138 PropertyAttributes old_attributes = ABSENT; | 4106 PropertyAttributes old_attributes = ABSENT; |
4139 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 4107 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
4140 if (is_observed && lookup.IsProperty()) { | 4108 if (is_observed && lookup.IsProperty()) { |
4141 if (lookup.IsDataProperty()) old_value = | 4109 if (lookup.IsDataProperty()) old_value = |
4142 Object::GetProperty(self, name); | 4110 Object::GetProperty(object, name); |
4143 old_attributes = lookup.GetAttributes(); | 4111 old_attributes = lookup.GetAttributes(); |
4144 } | 4112 } |
4145 | 4113 |
4146 // Check of IsReadOnly removed from here in clone. | 4114 // Check of IsReadOnly removed from here in clone. |
4147 MaybeObject* result = *value; | 4115 Handle<Object> result = value; |
4148 switch (lookup.type()) { | 4116 switch (lookup.type()) { |
4149 case NORMAL: | 4117 case NORMAL: |
4150 result = self->ReplaceSlowProperty(*name, *value, attributes); | 4118 result = ReplaceSlowProperty(object, name, value, attributes); |
4151 break; | 4119 break; |
4152 case FIELD: | 4120 case FIELD: |
4153 result = SetPropertyToFieldWithAttributes( | 4121 result = SetPropertyToFieldWithAttributes( |
4154 &lookup, name, value, attributes); | 4122 &lookup, name, value, attributes); |
4155 break; | 4123 break; |
4156 case CONSTANT: | 4124 case CONSTANT: |
4157 // Only replace the constant if necessary. | 4125 // Only replace the constant if necessary. |
4158 if (lookup.GetAttributes() != attributes || | 4126 if (lookup.GetAttributes() != attributes || |
4159 *value != lookup.GetConstant()) { | 4127 *value != lookup.GetConstant()) { |
4160 result = SetPropertyToFieldWithAttributes( | 4128 result = SetPropertyToFieldWithAttributes( |
4161 &lookup, name, value, attributes); | 4129 &lookup, name, value, attributes); |
4162 } | 4130 } |
4163 break; | 4131 break; |
4164 case CALLBACKS: | 4132 case CALLBACKS: |
4165 result = ConvertAndSetLocalProperty(&lookup, *name, *value, attributes); | 4133 result = ConvertAndSetLocalProperty(&lookup, name, value, attributes); |
4166 break; | 4134 break; |
4167 case TRANSITION: | 4135 case TRANSITION: |
4168 result = SetPropertyUsingTransition(&lookup, name, value, attributes); | 4136 result = SetPropertyUsingTransition(&lookup, name, value, attributes); |
4169 break; | 4137 break; |
4170 case NONEXISTENT: | 4138 case NONEXISTENT: |
4171 case HANDLER: | 4139 case HANDLER: |
4172 case INTERCEPTOR: | 4140 case INTERCEPTOR: |
4173 UNREACHABLE(); | 4141 UNREACHABLE(); |
4174 } | 4142 } |
4175 | 4143 |
4176 Handle<Object> hresult; | 4144 if (result.is_null()) return result; |
4177 if (!result->ToHandle(&hresult, isolate)) return result; | |
4178 | 4145 |
4179 if (is_observed) { | 4146 if (is_observed) { |
4180 if (lookup.IsTransition()) { | 4147 if (lookup.IsTransition()) { |
4181 EnqueueChangeRecord(self, "new", name, old_value); | 4148 EnqueueChangeRecord(object, "new", name, old_value); |
4182 } else if (old_value->IsTheHole()) { | 4149 } else if (old_value->IsTheHole()) { |
4183 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 4150 EnqueueChangeRecord(object, "reconfigured", name, old_value); |
4184 } else { | 4151 } else { |
4185 LookupResult new_lookup(isolate); | 4152 LookupResult new_lookup(isolate); |
4186 self->LocalLookup(*name, &new_lookup, true); | 4153 object->LocalLookup(*name, &new_lookup, true); |
4187 bool value_changed = false; | 4154 bool value_changed = false; |
4188 if (new_lookup.IsDataProperty()) { | 4155 if (new_lookup.IsDataProperty()) { |
4189 Handle<Object> new_value = Object::GetProperty(self, name); | 4156 Handle<Object> new_value = Object::GetProperty(object, name); |
4190 value_changed = !old_value->SameValue(*new_value); | 4157 value_changed = !old_value->SameValue(*new_value); |
4191 } | 4158 } |
4192 if (new_lookup.GetAttributes() != old_attributes) { | 4159 if (new_lookup.GetAttributes() != old_attributes) { |
4193 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 4160 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
4194 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 4161 EnqueueChangeRecord(object, "reconfigured", name, old_value); |
4195 } else if (value_changed) { | 4162 } else if (value_changed) { |
4196 EnqueueChangeRecord(self, "updated", name, old_value); | 4163 EnqueueChangeRecord(object, "updated", name, old_value); |
4197 } | 4164 } |
4198 } | 4165 } |
4199 } | 4166 } |
4200 | 4167 |
4201 return *hresult; | 4168 return result; |
4202 } | 4169 } |
4203 | 4170 |
4204 | 4171 |
4205 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 4172 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
4206 JSObject* receiver, | 4173 JSObject* receiver, |
4207 Name* name, | 4174 Name* name, |
4208 bool continue_search) { | 4175 bool continue_search) { |
4209 // Check local property, ignore interceptor. | 4176 // Check local property, ignore interceptor. |
4210 LookupResult result(GetIsolate()); | 4177 LookupResult result(GetIsolate()); |
4211 LocalLookupRealNamedProperty(name, &result); | 4178 LocalLookupRealNamedProperty(name, &result); |
(...skipping 2471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6683 set_transitions(transitions); | 6650 set_transitions(transitions); |
6684 result->SetBackPointer(this); | 6651 result->SetBackPointer(this); |
6685 } else { | 6652 } else { |
6686 descriptors->InitializeRepresentations(Representation::Tagged()); | 6653 descriptors->InitializeRepresentations(Representation::Tagged()); |
6687 } | 6654 } |
6688 | 6655 |
6689 return result; | 6656 return result; |
6690 } | 6657 } |
6691 | 6658 |
6692 | 6659 |
6660 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | |
6661 int new_descriptor, | |
6662 Handle<DescriptorArray> descriptors) { | |
6663 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
6664 map->CopyInstallDescriptors(new_descriptor, *descriptors), | |
6665 Map); | |
6666 } | |
6667 | |
6668 | |
6693 // Since this method is used to rewrite an existing transition tree, it can | 6669 // Since this method is used to rewrite an existing transition tree, it can |
6694 // always insert transitions without checking. | 6670 // always insert transitions without checking. |
6695 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6671 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, |
6696 DescriptorArray* descriptors) { | 6672 DescriptorArray* descriptors) { |
6697 ASSERT(descriptors->IsSortedNoDuplicates()); | 6673 ASSERT(descriptors->IsSortedNoDuplicates()); |
6698 | 6674 |
6699 Map* result; | 6675 Map* result; |
6700 MaybeObject* maybe_result = CopyDropDescriptors(); | 6676 MaybeObject* maybe_result = CopyDropDescriptors(); |
6701 if (!maybe_result->To(&result)) return maybe_result; | 6677 if (!maybe_result->To(&result)) return maybe_result; |
6702 | 6678 |
(...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7795 DescriptorArray* src, | 7771 DescriptorArray* src, |
7796 int src_index, | 7772 int src_index, |
7797 const WhitenessWitness& witness) { | 7773 const WhitenessWitness& witness) { |
7798 Object* value = src->GetValue(src_index); | 7774 Object* value = src->GetValue(src_index); |
7799 PropertyDetails details = src->GetDetails(src_index); | 7775 PropertyDetails details = src->GetDetails(src_index); |
7800 Descriptor desc(src->GetKey(src_index), value, details); | 7776 Descriptor desc(src->GetKey(src_index), value, details); |
7801 Set(dst_index, &desc, witness); | 7777 Set(dst_index, &desc, witness); |
7802 } | 7778 } |
7803 | 7779 |
7804 | 7780 |
7781 Handle<DescriptorArray> DescriptorArray::Merge(Handle<DescriptorArray> desc, | |
7782 int verbatim, | |
7783 int valid, | |
7784 int new_size, | |
7785 int modify_index, | |
7786 StoreMode store_mode, | |
7787 Handle<DescriptorArray> other) { | |
7788 CALL_HEAP_FUNCTION(desc->GetIsolate(), | |
7789 desc->Merge(verbatim, valid, new_size, modify_index, | |
7790 store_mode, *other), | |
7791 DescriptorArray); | |
7792 } | |
7793 | |
7794 | |
7805 // Generalize the |other| descriptor array by merging it into the (at least | 7795 // Generalize the |other| descriptor array by merging it into the (at least |
7806 // partly) updated |this| descriptor array. | 7796 // partly) updated |this| descriptor array. |
7807 // The method merges two descriptor array in three parts. Both descriptor arrays | 7797 // The method merges two descriptor array in three parts. Both descriptor arrays |
7808 // are identical up to |verbatim|. They also overlap in keys up to |valid|. | 7798 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
7809 // Between |verbatim| and |valid|, the resulting descriptor type as well as the | 7799 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
7810 // representation are generalized from both |this| and |other|. Beyond |valid|, | 7800 // representation are generalized from both |this| and |other|. Beyond |valid|, |
7811 // the descriptors are copied verbatim from |other| up to |new_size|. | 7801 // the descriptors are copied verbatim from |other| up to |new_size|. |
7812 // In case of incompatible types, the type and representation of |other| is | 7802 // In case of incompatible types, the type and representation of |other| is |
7813 // used. | 7803 // used. |
7814 MaybeObject* DescriptorArray::Merge(int verbatim, | 7804 MaybeObject* DescriptorArray::Merge(int verbatim, |
(...skipping 6698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14513 } | 14503 } |
14514 | 14504 |
14515 | 14505 |
14516 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 14506 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
14517 ASSERT(!HasFastProperties()); | 14507 ASSERT(!HasFastProperties()); |
14518 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 14508 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
14519 return PropertyCell::cast(value); | 14509 return PropertyCell::cast(value); |
14520 } | 14510 } |
14521 | 14511 |
14522 | 14512 |
14523 // TODO(mstarzinger): Temporary wrapper until handlified. | |
14524 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, | |
14525 Handle<Name> name, | |
14526 Handle<Object> value, | |
14527 PropertyDetails details) { | |
14528 CALL_HEAP_FUNCTION(dict->GetIsolate(), | |
14529 dict->Add(*name, *value, details), | |
14530 NameDictionary); | |
14531 } | |
14532 | |
14533 | |
14534 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 14513 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( |
14535 Handle<GlobalObject> global, | 14514 Handle<GlobalObject> global, |
14536 Handle<Name> name) { | 14515 Handle<Name> name) { |
14537 ASSERT(!global->HasFastProperties()); | 14516 ASSERT(!global->HasFastProperties()); |
14538 int entry = global->property_dictionary()->FindEntry(*name); | 14517 int entry = global->property_dictionary()->FindEntry(*name); |
14539 if (entry == NameDictionary::kNotFound) { | 14518 if (entry == NameDictionary::kNotFound) { |
14540 Isolate* isolate = global->GetIsolate(); | 14519 Isolate* isolate = global->GetIsolate(); |
14541 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( | 14520 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( |
14542 isolate->factory()->the_hole_value()); | 14521 isolate->factory()->the_hole_value()); |
14543 PropertyDetails details(NONE, NORMAL, 0); | 14522 PropertyDetails details(NONE, NORMAL, 0); |
(...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16102 isolate, DependentCode::kPropertyCellChangedGroup); | 16081 isolate, DependentCode::kPropertyCellChangedGroup); |
16103 | 16082 |
16104 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { | 16083 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
16105 return *new_type; | 16084 return *new_type; |
16106 } | 16085 } |
16107 | 16086 |
16108 return Type::Any(); | 16087 return Type::Any(); |
16109 } | 16088 } |
16110 | 16089 |
16111 | 16090 |
16091 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, | |
16092 Handle<Object> value, | |
16093 WriteBarrierMode mode) { | |
16094 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), | |
16095 cell->SetValueInferType(*value, mode)); | |
16096 } | |
16097 | |
16098 | |
16112 MaybeObject* PropertyCell::SetValueInferType(Object* value, | 16099 MaybeObject* PropertyCell::SetValueInferType(Object* value, |
16113 WriteBarrierMode ignored) { | 16100 WriteBarrierMode ignored) { |
16114 set_value(value, ignored); | 16101 set_value(value, ignored); |
16115 if (!Type::Any()->Is(type())) { | 16102 if (!Type::Any()->Is(type())) { |
16116 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); | 16103 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); |
16117 MaybeObject* maybe_type = trampoline.CallWithReturnValue( | 16104 MaybeObject* maybe_type = trampoline.CallWithReturnValue( |
16118 &PropertyCell::UpdateType, | 16105 &PropertyCell::UpdateType, |
16119 Handle<PropertyCell>(this), | 16106 Handle<PropertyCell>(this), |
16120 Handle<Object>(value, GetIsolate())); | 16107 Handle<Object>(value, GetIsolate())); |
16121 Type* new_type = NULL; | 16108 Type* new_type = NULL; |
(...skipping 28 matching lines...) Expand all Loading... | |
16150 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16137 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16151 static const char* error_messages_[] = { | 16138 static const char* error_messages_[] = { |
16152 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16139 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16153 }; | 16140 }; |
16154 #undef ERROR_MESSAGES_TEXTS | 16141 #undef ERROR_MESSAGES_TEXTS |
16155 return error_messages_[reason]; | 16142 return error_messages_[reason]; |
16156 } | 16143 } |
16157 | 16144 |
16158 | 16145 |
16159 } } // namespace v8::internal | 16146 } } // namespace v8::internal |
OLD | NEW |