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