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 return SetPropertyWithHandler( | 458 CALL_HEAP_FUNCTION(isolate, |
459 proxy, receiver, name, value, NONE, strict_mode); | 459 proxy->SetPropertyWithHandler( |
| 460 *receiver, *name, *value, NONE, strict_mode), |
| 461 Object); |
460 } | 462 } |
461 | 463 |
462 | 464 |
463 bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) { | 465 bool JSProxy::HasElementWithHandler(uint32_t index) { |
464 Isolate* isolate = proxy->GetIsolate(); | 466 String* name; |
465 Handle<String> name = isolate->factory()->Uint32ToString(index); | 467 MaybeObject* maybe = GetHeap()->Uint32ToString(index); |
466 return HasPropertyWithHandler(proxy, name); | 468 if (!maybe->To<String>(&name)) return maybe; |
| 469 return HasPropertyWithHandler(name); |
467 } | 470 } |
468 | 471 |
469 | 472 |
470 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, | 473 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, |
471 JSReceiver* getter) { | 474 JSReceiver* getter) { |
472 Isolate* isolate = getter->GetIsolate(); | 475 Isolate* isolate = getter->GetIsolate(); |
473 HandleScope scope(isolate); | 476 HandleScope scope(isolate); |
474 Handle<JSReceiver> fun(getter); | 477 Handle<JSReceiver> fun(getter); |
475 Handle<Object> self(receiver, isolate); | 478 Handle<Object> self(receiver, isolate); |
476 #ifdef ENABLE_DEBUGGER_SUPPORT | 479 #ifdef ENABLE_DEBUGGER_SUPPORT |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1861 // If the constructor is not present, return "Object". | 1864 // If the constructor is not present, return "Object". |
1862 return GetHeap()->Object_string(); | 1865 return GetHeap()->Object_string(); |
1863 } | 1866 } |
1864 | 1867 |
1865 | 1868 |
1866 String* JSReceiver::constructor_name() { | 1869 String* JSReceiver::constructor_name() { |
1867 return map()->constructor_name(); | 1870 return map()->constructor_name(); |
1868 } | 1871 } |
1869 | 1872 |
1870 | 1873 |
1871 Handle<Object> JSObject::AddFastPropertyUsingMap( | |
1872 Handle<JSObject> object, | |
1873 Handle<Map> new_map, | |
1874 Handle<Name> name, | |
1875 Handle<Object> value, | |
1876 int field_index, | |
1877 Representation representation) { | |
1878 CALL_HEAP_FUNCTION(object->GetIsolate(), | |
1879 object->AddFastPropertyUsingMap( | |
1880 *new_map, *name, *value, field_index, representation), | |
1881 Object); | |
1882 } | |
1883 | |
1884 | |
1885 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, | 1874 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
1886 Name* name, | 1875 Name* name, |
1887 Object* value, | 1876 Object* value, |
1888 int field_index, | 1877 int field_index, |
1889 Representation representation) { | 1878 Representation representation) { |
1890 // This method is used to transition to a field. If we are transitioning to a | 1879 // This method is used to transition to a field. If we are transitioning to a |
1891 // double field, allocate new storage. | 1880 // double field, allocate new storage. |
1892 Object* storage; | 1881 Object* storage; |
1893 MaybeObject* maybe_storage = | 1882 MaybeObject* maybe_storage = |
1894 value->AllocateNewStorageFor(GetHeap(), representation); | 1883 value->AllocateNewStorageFor(GetHeap(), representation); |
1895 if (!maybe_storage->To(&storage)) return maybe_storage; | 1884 if (!maybe_storage->To(&storage)) return maybe_storage; |
1896 | 1885 |
1897 if (map()->unused_property_fields() == 0) { | 1886 if (map()->unused_property_fields() == 0) { |
1898 int new_unused = new_map->unused_property_fields(); | 1887 int new_unused = new_map->unused_property_fields(); |
1899 FixedArray* values; | 1888 FixedArray* values; |
1900 MaybeObject* maybe_values = | 1889 MaybeObject* maybe_values = |
1901 properties()->CopySize(properties()->length() + new_unused + 1); | 1890 properties()->CopySize(properties()->length() + new_unused + 1); |
1902 if (!maybe_values->To(&values)) return maybe_values; | 1891 if (!maybe_values->To(&values)) return maybe_values; |
1903 | 1892 |
1904 set_properties(values); | 1893 set_properties(values); |
1905 } | 1894 } |
1906 | 1895 |
1907 set_map(new_map); | 1896 set_map(new_map); |
1908 | 1897 |
1909 FastPropertyAtPut(field_index, storage); | 1898 FastPropertyAtPut(field_index, storage); |
1910 return value; | 1899 return value; |
1911 } | 1900 } |
1912 | 1901 |
1913 | 1902 |
1914 static MaybeObject* CopyAddFieldDescriptor(Map* map, | 1903 MaybeObject* JSObject::AddFastProperty(Name* name, |
1915 Name* name, | 1904 Object* value, |
1916 int index, | 1905 PropertyAttributes attributes, |
1917 PropertyAttributes attributes, | 1906 StoreFromKeyed store_mode, |
1918 Representation representation, | 1907 ValueType value_type, |
1919 TransitionFlag flag) { | 1908 TransitionFlag flag) { |
1920 Map* new_map; | 1909 ASSERT(!IsJSGlobalProxy()); |
1921 FieldDescriptor new_field_desc(name, index, attributes, representation); | |
1922 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); | |
1923 if (!maybe_map->To(&new_map)) return maybe_map; | |
1924 int unused_property_fields = map->unused_property_fields() - 1; | |
1925 if (unused_property_fields < 0) { | |
1926 unused_property_fields += JSObject::kFieldsAdded; | |
1927 } | |
1928 new_map->set_unused_property_fields(unused_property_fields); | |
1929 return new_map; | |
1930 } | |
1931 | |
1932 | |
1933 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, | |
1934 Handle<Name> name, | |
1935 int index, | |
1936 PropertyAttributes attributes, | |
1937 Representation representation, | |
1938 TransitionFlag flag) { | |
1939 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
1940 CopyAddFieldDescriptor( | |
1941 *map, *name, index, attributes, representation, flag), | |
1942 Map); | |
1943 } | |
1944 | |
1945 | |
1946 void JSObject::AddFastProperty(Handle<JSObject> object, | |
1947 Handle<Name> name, | |
1948 Handle<Object> value, | |
1949 PropertyAttributes attributes, | |
1950 StoreFromKeyed store_mode, | |
1951 ValueType value_type, | |
1952 TransitionFlag flag) { | |
1953 ASSERT(!object->IsJSGlobalProxy()); | |
1954 ASSERT(DescriptorArray::kNotFound == | 1910 ASSERT(DescriptorArray::kNotFound == |
1955 object->map()->instance_descriptors()->Search( | 1911 map()->instance_descriptors()->Search( |
1956 *name, object->map()->NumberOfOwnDescriptors())); | 1912 name, map()->NumberOfOwnDescriptors())); |
1957 | 1913 |
1958 // Normalize the object if the name is an actual name (not the | 1914 // Normalize the object if the name is an actual name (not the |
1959 // hidden strings) and is not a real identifier. | 1915 // hidden strings) and is not a real identifier. |
1960 // Normalize the object if it will have too many fast properties. | 1916 // Normalize the object if it will have too many fast properties. |
1961 Isolate* isolate = object->GetIsolate(); | 1917 Isolate* isolate = GetHeap()->isolate(); |
1962 if (!name->IsCacheable(isolate) || | 1918 if (!name->IsCacheable(isolate) || TooManyFastProperties(store_mode)) { |
1963 object->TooManyFastProperties(store_mode)) { | 1919 MaybeObject* maybe_failure = |
1964 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 1920 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1965 AddSlowProperty(object, name, value, attributes); | 1921 if (maybe_failure->IsFailure()) return maybe_failure; |
1966 return; | 1922 return AddSlowProperty(name, value, attributes); |
1967 } | 1923 } |
1968 | 1924 |
1969 // Compute the new index for new field. | 1925 // Compute the new index for new field. |
1970 int index = object->map()->NextFreePropertyIndex(); | 1926 int index = map()->NextFreePropertyIndex(); |
1971 | 1927 |
1972 // Allocate new instance descriptors with (name, index) added | 1928 // Allocate new instance descriptors with (name, index) added |
1973 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 1929 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
1974 Representation representation = value->OptimalRepresentation(value_type); | 1930 Representation representation = value->OptimalRepresentation(value_type); |
1975 Handle<Map> new_map = CopyAddFieldDescriptor( | |
1976 handle(object->map()), name, index, attributes, representation, flag); | |
1977 | 1931 |
1978 AddFastPropertyUsingMap(object, new_map, name, value, index, representation); | 1932 FieldDescriptor new_field(name, index, attributes, representation); |
| 1933 |
| 1934 Map* new_map; |
| 1935 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); |
| 1936 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 1937 |
| 1938 int unused_property_fields = map()->unused_property_fields() - 1; |
| 1939 if (unused_property_fields < 0) { |
| 1940 unused_property_fields += kFieldsAdded; |
| 1941 } |
| 1942 new_map->set_unused_property_fields(unused_property_fields); |
| 1943 |
| 1944 return AddFastPropertyUsingMap(new_map, name, value, index, representation); |
1979 } | 1945 } |
1980 | 1946 |
1981 | 1947 |
1982 static MaybeObject* CopyAddConstantDescriptor(Map* map, | 1948 MaybeObject* JSObject::AddConstantProperty( |
1983 Name* name, | 1949 Name* name, |
1984 Object* value, | 1950 Object* constant, |
1985 PropertyAttributes attributes, | 1951 PropertyAttributes attributes, |
1986 TransitionFlag flag) { | 1952 TransitionFlag initial_flag) { |
1987 ConstantDescriptor new_constant_desc(name, value, attributes); | 1953 // Allocate new instance descriptors with (name, constant) added |
1988 return map->CopyAddDescriptor(&new_constant_desc, flag); | 1954 ConstantDescriptor d(name, constant, attributes); |
1989 } | |
1990 | 1955 |
1991 | |
1992 static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map, | |
1993 Handle<Name> name, | |
1994 Handle<Object> value, | |
1995 PropertyAttributes attributes, | |
1996 TransitionFlag flag) { | |
1997 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
1998 CopyAddConstantDescriptor( | |
1999 *map, *name, *value, attributes, flag), | |
2000 Map); | |
2001 } | |
2002 | |
2003 | |
2004 void JSObject::AddConstantProperty(Handle<JSObject> object, | |
2005 Handle<Name> name, | |
2006 Handle<Object> constant, | |
2007 PropertyAttributes attributes, | |
2008 TransitionFlag initial_flag) { | |
2009 TransitionFlag flag = | 1956 TransitionFlag flag = |
2010 // Do not add transitions to global objects. | 1957 // Do not add transitions to global objects. |
2011 (object->IsGlobalObject() || | 1958 (IsGlobalObject() || |
2012 // Don't add transitions to special properties with non-trivial | 1959 // Don't add transitions to special properties with non-trivial |
2013 // attributes. | 1960 // attributes. |
2014 attributes != NONE) | 1961 attributes != NONE) |
2015 ? OMIT_TRANSITION | 1962 ? OMIT_TRANSITION |
2016 : initial_flag; | 1963 : initial_flag; |
2017 | 1964 |
2018 // Allocate new instance descriptors with (name, constant) added. | 1965 Map* new_map; |
2019 Handle<Map> new_map = CopyAddConstantDescriptor( | 1966 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); |
2020 handle(object->map()), name, constant, attributes, flag); | 1967 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
2021 | 1968 |
2022 object->set_map(*new_map); | 1969 set_map(new_map); |
| 1970 return constant; |
2023 } | 1971 } |
2024 | 1972 |
2025 | 1973 |
2026 // TODO(mstarzinger): Temporary wrapper until handlified. | 1974 // Add property in slow mode |
2027 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, | 1975 MaybeObject* JSObject::AddSlowProperty(Name* name, |
2028 Handle<Name> name, | 1976 Object* value, |
2029 Handle<Object> value, | 1977 PropertyAttributes attributes) { |
2030 PropertyDetails details) { | 1978 ASSERT(!HasFastProperties()); |
2031 CALL_HEAP_FUNCTION(dict->GetIsolate(), | 1979 NameDictionary* dict = property_dictionary(); |
2032 dict->Add(*name, *value, details), | 1980 Object* store_value = value; |
2033 NameDictionary); | 1981 if (IsGlobalObject()) { |
2034 } | |
2035 | |
2036 | |
2037 void JSObject::AddSlowProperty(Handle<JSObject> object, | |
2038 Handle<Name> name, | |
2039 Handle<Object> value, | |
2040 PropertyAttributes attributes) { | |
2041 ASSERT(!object->HasFastProperties()); | |
2042 Isolate* isolate = object->GetIsolate(); | |
2043 Handle<NameDictionary> dict(object->property_dictionary()); | |
2044 if (object->IsGlobalObject()) { | |
2045 // In case name is an orphaned property reuse the cell. | 1982 // In case name is an orphaned property reuse the cell. |
2046 int entry = dict->FindEntry(*name); | 1983 int entry = dict->FindEntry(name); |
2047 if (entry != NameDictionary::kNotFound) { | 1984 if (entry != NameDictionary::kNotFound) { |
2048 Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); | 1985 store_value = dict->ValueAt(entry); |
2049 PropertyCell::SetValueInferType(cell, value); | 1986 MaybeObject* maybe_type = |
| 1987 PropertyCell::cast(store_value)->SetValueInferType(value); |
| 1988 if (maybe_type->IsFailure()) return maybe_type; |
2050 // Assign an enumeration index to the property and update | 1989 // Assign an enumeration index to the property and update |
2051 // SetNextEnumerationIndex. | 1990 // SetNextEnumerationIndex. |
2052 int index = dict->NextEnumerationIndex(); | 1991 int index = dict->NextEnumerationIndex(); |
2053 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); | 1992 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
2054 dict->SetNextEnumerationIndex(index + 1); | 1993 dict->SetNextEnumerationIndex(index + 1); |
2055 dict->SetEntry(entry, *name, *cell, details); | 1994 dict->SetEntry(entry, name, store_value, details); |
2056 return; | 1995 return value; |
2057 } | 1996 } |
2058 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value); | 1997 Heap* heap = GetHeap(); |
2059 PropertyCell::SetValueInferType(cell, value); | 1998 { MaybeObject* maybe_store_value = |
2060 value = cell; | 1999 heap->AllocatePropertyCell(value); |
| 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; |
2061 } | 2005 } |
2062 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 2006 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
2063 Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details); | 2007 Object* result; |
2064 if (*dict != *result) object->set_properties(*result); | 2008 { MaybeObject* maybe_result = dict->Add(name, store_value, details); |
| 2009 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2010 } |
| 2011 if (dict != result) set_properties(NameDictionary::cast(result)); |
| 2012 return value; |
2065 } | 2013 } |
2066 | 2014 |
2067 | 2015 |
2068 Handle<Object> JSObject::AddProperty(Handle<JSObject> object, | 2016 MaybeObject* JSObject::AddProperty(Name* name, |
2069 Handle<Name> name, | 2017 Object* value, |
2070 Handle<Object> value, | 2018 PropertyAttributes attributes, |
2071 PropertyAttributes attributes, | 2019 StrictModeFlag strict_mode, |
2072 StrictModeFlag strict_mode, | 2020 JSReceiver::StoreFromKeyed store_mode, |
2073 JSReceiver::StoreFromKeyed store_mode, | 2021 ExtensibilityCheck extensibility_check, |
2074 ExtensibilityCheck extensibility_check, | 2022 ValueType value_type, |
2075 ValueType value_type, | 2023 StoreMode mode, |
2076 StoreMode mode, | 2024 TransitionFlag transition_flag) { |
2077 TransitionFlag transition_flag) { | 2025 ASSERT(!IsJSGlobalProxy()); |
2078 ASSERT(!object->IsJSGlobalProxy()); | 2026 Map* map_of_this = map(); |
2079 Isolate* isolate = object->GetIsolate(); | 2027 Heap* heap = GetHeap(); |
| 2028 Isolate* isolate = heap->isolate(); |
| 2029 MaybeObject* result; |
2080 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2030 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
2081 !object->map()->is_extensible()) { | 2031 !map_of_this->is_extensible()) { |
2082 if (strict_mode == kNonStrictMode) { | 2032 if (strict_mode == kNonStrictMode) { |
2083 return value; | 2033 return value; |
2084 } else { | 2034 } else { |
2085 Handle<Object> args[1] = { name }; | 2035 Handle<Object> args[1] = {Handle<Name>(name)}; |
2086 Handle<Object> error = isolate->factory()->NewTypeError( | 2036 return isolate->Throw( |
2087 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); | 2037 *isolate->factory()->NewTypeError("object_not_extensible", |
2088 isolate->Throw(*error); | 2038 HandleVector(args, 1))); |
2089 return Handle<Object>(); | |
2090 } | 2039 } |
2091 } | 2040 } |
2092 | 2041 |
2093 if (object->HasFastProperties()) { | 2042 if (HasFastProperties()) { |
2094 // Ensure the descriptor array does not get too big. | 2043 // Ensure the descriptor array does not get too big. |
2095 if (object->map()->NumberOfOwnDescriptors() < | 2044 if (map_of_this->NumberOfOwnDescriptors() < |
2096 DescriptorArray::kMaxNumberOfDescriptors) { | 2045 DescriptorArray::kMaxNumberOfDescriptors) { |
2097 // TODO(verwaest): Support other constants. | 2046 // TODO(verwaest): Support other constants. |
2098 // if (mode == ALLOW_AS_CONSTANT && | 2047 // if (mode == ALLOW_AS_CONSTANT && |
2099 // !value->IsTheHole() && | 2048 // !value->IsTheHole() && |
2100 // !value->IsConsString()) { | 2049 // !value->IsConsString()) { |
2101 if (value->IsJSFunction()) { | 2050 if (value->IsJSFunction()) { |
2102 AddConstantProperty(object, name, value, attributes, transition_flag); | 2051 result = AddConstantProperty(name, value, attributes, transition_flag); |
2103 } else { | 2052 } else { |
2104 AddFastProperty(object, name, value, attributes, store_mode, | 2053 result = AddFastProperty( |
2105 value_type, transition_flag); | 2054 name, value, attributes, store_mode, value_type, transition_flag); |
2106 } | 2055 } |
2107 } else { | 2056 } else { |
2108 // Normalize the object to prevent very large instance descriptors. | 2057 // Normalize the object to prevent very large instance descriptors. |
2109 // This eliminates unwanted N^2 allocation and lookup behavior. | 2058 // This eliminates unwanted N^2 allocation and lookup behavior. |
2110 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 2059 Object* obj; |
2111 AddSlowProperty(object, name, value, attributes); | 2060 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2061 if (!maybe->To(&obj)) return maybe; |
| 2062 result = AddSlowProperty(name, value, attributes); |
2112 } | 2063 } |
2113 } else { | 2064 } else { |
2114 AddSlowProperty(object, name, value, attributes); | 2065 result = AddSlowProperty(name, value, attributes); |
2115 } | 2066 } |
2116 | 2067 |
2117 if (FLAG_harmony_observation && object->map()->is_observed()) { | 2068 Handle<Object> hresult; |
2118 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 2069 if (!result->ToHandle(&hresult, isolate)) return result; |
2119 EnqueueChangeRecord(object, "new", name, old_value); | 2070 |
| 2071 if (FLAG_harmony_observation && map()->is_observed()) { |
| 2072 EnqueueChangeRecord(handle(this, isolate), |
| 2073 "new", |
| 2074 handle(name, isolate), |
| 2075 handle(heap->the_hole_value(), isolate)); |
2120 } | 2076 } |
2121 | 2077 |
2122 return value; | 2078 return *hresult; |
2123 } | 2079 } |
2124 | 2080 |
2125 | 2081 |
2126 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2082 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
2127 const char* type_str, | 2083 const char* type_str, |
2128 Handle<Name> name, | 2084 Handle<Name> name, |
2129 Handle<Object> old_value) { | 2085 Handle<Object> old_value) { |
2130 Isolate* isolate = object->GetIsolate(); | 2086 Isolate* isolate = object->GetIsolate(); |
2131 HandleScope scope(isolate); | 2087 HandleScope scope(isolate); |
2132 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); | 2088 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); |
(...skipping 19 matching lines...) Expand all Loading... |
2152 isolate->observers_deliver_changes(), | 2108 isolate->observers_deliver_changes(), |
2153 isolate->factory()->undefined_value(), | 2109 isolate->factory()->undefined_value(), |
2154 0, | 2110 0, |
2155 NULL, | 2111 NULL, |
2156 &threw); | 2112 &threw); |
2157 ASSERT(!threw); | 2113 ASSERT(!threw); |
2158 isolate->set_observer_delivery_pending(false); | 2114 isolate->set_observer_delivery_pending(false); |
2159 } | 2115 } |
2160 | 2116 |
2161 | 2117 |
2162 Handle<Object> JSObject::SetPropertyPostInterceptor( | 2118 MaybeObject* JSObject::SetPropertyPostInterceptor( |
2163 Handle<JSObject> object, | 2119 Name* name, |
2164 Handle<Name> name, | 2120 Object* value, |
2165 Handle<Object> value, | |
2166 PropertyAttributes attributes, | 2121 PropertyAttributes attributes, |
2167 StrictModeFlag strict_mode) { | 2122 StrictModeFlag strict_mode, |
| 2123 StoreMode mode) { |
2168 // Check local property, ignore interceptor. | 2124 // Check local property, ignore interceptor. |
2169 LookupResult result(object->GetIsolate()); | 2125 LookupResult result(GetIsolate()); |
2170 object->LocalLookupRealNamedProperty(*name, &result); | 2126 LocalLookupRealNamedProperty(name, &result); |
2171 if (!result.IsFound()) { | 2127 if (!result.IsFound()) map()->LookupTransition(this, name, &result); |
2172 object->map()->LookupTransition(*object, *name, &result); | |
2173 } | |
2174 if (result.IsFound()) { | 2128 if (result.IsFound()) { |
2175 // An existing property or a map transition was found. Use set property to | 2129 // An existing property or a map transition was found. Use set property to |
2176 // handle all these cases. | 2130 // handle all these cases. |
2177 return SetPropertyForResult(object, &result, name, value, attributes, | 2131 return SetProperty(&result, name, value, attributes, strict_mode); |
2178 strict_mode, MAY_BE_STORE_FROM_KEYED); | |
2179 } | 2132 } |
2180 bool done = false; | 2133 bool done = false; |
2181 Handle<Object> result_object = SetPropertyViaPrototypes( | 2134 MaybeObject* result_object = |
2182 object, name, value, attributes, strict_mode, &done); | 2135 SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); |
2183 if (done) return result_object; | 2136 if (done) return result_object; |
2184 // Add a new real property. | 2137 // Add a new real property. |
2185 return AddProperty(object, name, value, attributes, strict_mode); | 2138 return AddProperty(name, value, attributes, strict_mode, |
| 2139 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, |
| 2140 OPTIMAL_REPRESENTATION, mode); |
2186 } | 2141 } |
2187 | 2142 |
2188 | 2143 |
2189 static Handle<Object> ReplaceSlowProperty(Handle<JSObject> object, | 2144 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, |
2190 Handle<Name> name, | 2145 Object* value, |
2191 Handle<Object> value, | 2146 PropertyAttributes attributes) { |
2192 PropertyAttributes attributes) { | 2147 NameDictionary* dictionary = property_dictionary(); |
2193 NameDictionary* dictionary = object->property_dictionary(); | 2148 int old_index = dictionary->FindEntry(name); |
2194 int old_index = dictionary->FindEntry(*name); | |
2195 int new_enumeration_index = 0; // 0 means "Use the next available index." | 2149 int new_enumeration_index = 0; // 0 means "Use the next available index." |
2196 if (old_index != -1) { | 2150 if (old_index != -1) { |
2197 // All calls to ReplaceSlowProperty have had all transitions removed. | 2151 // All calls to ReplaceSlowProperty have had all transitions removed. |
2198 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2152 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
2199 } | 2153 } |
2200 | 2154 |
2201 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2155 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
2202 return JSObject::SetNormalizedProperty(object, name, value, new_details); | 2156 return SetNormalizedProperty(name, value, new_details); |
2203 } | 2157 } |
2204 | 2158 |
2205 | 2159 |
2206 const char* Representation::Mnemonic() const { | 2160 const char* Representation::Mnemonic() const { |
2207 switch (kind_) { | 2161 switch (kind_) { |
2208 case kNone: return "v"; | 2162 case kNone: return "v"; |
2209 case kTagged: return "t"; | 2163 case kTagged: return "t"; |
2210 case kSmi: return "s"; | 2164 case kSmi: return "s"; |
2211 case kDouble: return "d"; | 2165 case kDouble: return "d"; |
2212 case kInteger32: return "i"; | 2166 case kInteger32: return "i"; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2299 ASSERT(target_inobject < inobject_properties()); | 2253 ASSERT(target_inobject < inobject_properties()); |
2300 if (target_number_of_fields <= target_inobject) { | 2254 if (target_number_of_fields <= target_inobject) { |
2301 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2255 ASSERT(target_number_of_fields + target_unused == target_inobject); |
2302 return false; | 2256 return false; |
2303 } | 2257 } |
2304 // Otherwise, properties will need to be moved to the backing store. | 2258 // Otherwise, properties will need to be moved to the backing store. |
2305 return true; | 2259 return true; |
2306 } | 2260 } |
2307 | 2261 |
2308 | 2262 |
2309 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { | |
2310 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map)); | |
2311 } | |
2312 | |
2313 | |
2314 // To migrate an instance to a map: | 2263 // To migrate an instance to a map: |
2315 // - First check whether the instance needs to be rewritten. If not, simply | 2264 // - First check whether the instance needs to be rewritten. If not, simply |
2316 // change the map. | 2265 // change the map. |
2317 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2266 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
2318 // addition to unused space. | 2267 // addition to unused space. |
2319 // - Copy all existing properties in, in the following order: backing store | 2268 // - Copy all existing properties in, in the following order: backing store |
2320 // properties, unused fields, inobject properties. | 2269 // properties, unused fields, inobject properties. |
2321 // - If all allocation succeeded, commit the state atomically: | 2270 // - If all allocation succeeded, commit the state atomically: |
2322 // * Copy inobject properties from the backing store back into the object. | 2271 // * Copy inobject properties from the backing store back into the object. |
2323 // * Trim the difference in instance size of the object. This also cleanly | 2272 // * 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... |
2405 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); | 2354 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); |
2406 set_properties(array); | 2355 set_properties(array); |
2407 } | 2356 } |
2408 | 2357 |
2409 set_map(new_map); | 2358 set_map(new_map); |
2410 | 2359 |
2411 return this; | 2360 return this; |
2412 } | 2361 } |
2413 | 2362 |
2414 | 2363 |
2415 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2364 MaybeObject* JSObject::GeneralizeFieldRepresentation( |
2416 int modify_index, | 2365 int modify_index, |
2417 Representation new_representation, | 2366 Representation new_representation, |
2418 StoreMode store_mode) { | 2367 StoreMode store_mode) { |
2419 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2368 Map* new_map; |
2420 handle(object->map()), modify_index, new_representation, store_mode); | 2369 MaybeObject* maybe_new_map = map()->GeneralizeRepresentation( |
2421 if (object->map() == *new_map) return; | 2370 modify_index, new_representation, store_mode); |
2422 return MigrateToMap(object, new_map); | 2371 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 2372 if (map() == new_map) return this; |
| 2373 |
| 2374 return MigrateToMap(new_map); |
2423 } | 2375 } |
2424 | 2376 |
2425 | 2377 |
2426 int Map::NumberOfFields() { | 2378 int Map::NumberOfFields() { |
2427 DescriptorArray* descriptors = instance_descriptors(); | 2379 DescriptorArray* descriptors = instance_descriptors(); |
2428 int result = 0; | 2380 int result = 0; |
2429 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2381 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
2430 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2382 if (descriptors->GetDetails(i).type() == FIELD) result++; |
2431 } | 2383 } |
2432 return result; | 2384 return result; |
2433 } | 2385 } |
2434 | 2386 |
2435 | 2387 |
2436 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, | 2388 MaybeObject* Map::CopyGeneralizeAllRepresentations( |
2437 int modify_index, | 2389 int modify_index, |
2438 StoreMode store_mode, | 2390 StoreMode store_mode, |
2439 PropertyAttributes attributes, | 2391 PropertyAttributes attributes, |
2440 const char* reason) { | 2392 const char* reason) { |
2441 Handle<Map> new_map = Copy(map); | 2393 Map* new_map; |
| 2394 MaybeObject* maybe_map = this->Copy(); |
| 2395 if (!maybe_map->To(&new_map)) return maybe_map; |
2442 | 2396 |
2443 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2397 DescriptorArray* descriptors = new_map->instance_descriptors(); |
2444 descriptors->InitializeRepresentations(Representation::Tagged()); | 2398 descriptors->InitializeRepresentations(Representation::Tagged()); |
2445 | 2399 |
2446 // Unless the instance is being migrated, ensure that modify_index is a field. | 2400 // Unless the instance is being migrated, ensure that modify_index is a field. |
2447 PropertyDetails details = descriptors->GetDetails(modify_index); | 2401 PropertyDetails details = descriptors->GetDetails(modify_index); |
2448 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2402 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
2449 FieldDescriptor d(descriptors->GetKey(modify_index), | 2403 FieldDescriptor d(descriptors->GetKey(modify_index), |
2450 new_map->NumberOfFields(), | 2404 new_map->NumberOfFields(), |
2451 attributes, | 2405 attributes, |
2452 Representation::Tagged()); | 2406 Representation::Tagged()); |
2453 d.SetSortedKeyIndex(details.pointer()); | 2407 d.SetSortedKeyIndex(details.pointer()); |
2454 descriptors->Set(modify_index, &d); | 2408 descriptors->Set(modify_index, &d); |
2455 int unused_property_fields = new_map->unused_property_fields() - 1; | 2409 int unused_property_fields = new_map->unused_property_fields() - 1; |
2456 if (unused_property_fields < 0) { | 2410 if (unused_property_fields < 0) { |
2457 unused_property_fields += JSObject::kFieldsAdded; | 2411 unused_property_fields += JSObject::kFieldsAdded; |
2458 } | 2412 } |
2459 new_map->set_unused_property_fields(unused_property_fields); | 2413 new_map->set_unused_property_fields(unused_property_fields); |
2460 } | 2414 } |
2461 | 2415 |
2462 if (FLAG_trace_generalization) { | 2416 if (FLAG_trace_generalization) { |
2463 map->PrintGeneralization(stdout, reason, modify_index, | 2417 PrintGeneralization(stdout, reason, modify_index, |
2464 new_map->NumberOfOwnDescriptors(), | 2418 new_map->NumberOfOwnDescriptors(), |
2465 new_map->NumberOfOwnDescriptors(), | 2419 new_map->NumberOfOwnDescriptors(), |
2466 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2420 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
2467 Representation::Tagged(), Representation::Tagged()); | 2421 Representation::Tagged(), Representation::Tagged()); |
2468 } | 2422 } |
2469 return new_map; | 2423 return new_map; |
2470 } | 2424 } |
2471 | 2425 |
2472 | 2426 |
2473 void Map::DeprecateTransitionTree() { | 2427 void Map::DeprecateTransitionTree() { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2601 // FindUpdatedMap. This uses the keys in the own map's descriptor array to | 2555 // FindUpdatedMap. This uses the keys in the own map's descriptor array to |
2602 // walk the transition tree. | 2556 // walk the transition tree. |
2603 // - Merge/generalize the descriptor array of the current map and |updated|. | 2557 // - Merge/generalize the descriptor array of the current map and |updated|. |
2604 // - Generalize the |modify_index| descriptor using |new_representation|. | 2558 // - Generalize the |modify_index| descriptor using |new_representation|. |
2605 // - Walk the tree again starting from the root towards |updated|. Stop at | 2559 // - Walk the tree again starting from the root towards |updated|. Stop at |
2606 // |split_map|, the first map who's descriptor array does not match the merged | 2560 // |split_map|, the first map who's descriptor array does not match the merged |
2607 // descriptor array. | 2561 // descriptor array. |
2608 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2562 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
2609 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2563 // - Otherwise, invalidate the outdated transition target from |updated|, and |
2610 // replace its transition tree with a new branch for the updated descriptors. | 2564 // replace its transition tree with a new branch for the updated descriptors. |
2611 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, | 2565 MaybeObject* Map::GeneralizeRepresentation(int modify_index, |
2612 int modify_index, | 2566 Representation new_representation, |
2613 Representation new_representation, | 2567 StoreMode store_mode) { |
2614 StoreMode store_mode) { | 2568 Map* old_map = this; |
2615 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2569 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2616 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2570 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2617 Representation old_representation = old_details.representation(); | 2571 Representation old_representation = old_details.representation(); |
2618 | 2572 |
2619 // It's fine to transition from None to anything but double without any | 2573 // It's fine to transition from None to anything but double without any |
2620 // modification to the object, because the default uninitialized value for | 2574 // modification to the object, because the default uninitialized value for |
2621 // representation None can be overwritten by both smi and tagged values. | 2575 // representation None can be overwritten by both smi and tagged values. |
2622 // Doubles, however, would require a box allocation. | 2576 // Doubles, however, would require a box allocation. |
2623 if (old_representation.IsNone() && | 2577 if (old_representation.IsNone() && |
2624 !new_representation.IsNone() && | 2578 !new_representation.IsNone() && |
2625 !new_representation.IsDouble()) { | 2579 !new_representation.IsDouble()) { |
2626 old_descriptors->SetRepresentation(modify_index, new_representation); | 2580 old_descriptors->SetRepresentation(modify_index, new_representation); |
2627 return old_map; | 2581 return old_map; |
2628 } | 2582 } |
2629 | 2583 |
2630 int descriptors = old_map->NumberOfOwnDescriptors(); | 2584 int descriptors = old_map->NumberOfOwnDescriptors(); |
2631 Handle<Map> root_map(old_map->FindRootMap()); | 2585 Map* root_map = old_map->FindRootMap(); |
2632 | 2586 |
2633 // Check the state of the root map. | 2587 // Check the state of the root map. |
2634 if (!old_map->EquivalentToForTransition(*root_map)) { | 2588 if (!old_map->EquivalentToForTransition(root_map)) { |
2635 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2589 return CopyGeneralizeAllRepresentations( |
2636 old_details.attributes(), "not equivalent"); | 2590 modify_index, store_mode, old_details.attributes(), "not equivalent"); |
2637 } | 2591 } |
2638 | 2592 |
2639 int verbatim = root_map->NumberOfOwnDescriptors(); | 2593 int verbatim = root_map->NumberOfOwnDescriptors(); |
2640 | 2594 |
2641 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2595 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
2642 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2596 return CopyGeneralizeAllRepresentations( |
| 2597 modify_index, store_mode, |
2643 old_details.attributes(), "root modification"); | 2598 old_details.attributes(), "root modification"); |
2644 } | 2599 } |
2645 | 2600 |
2646 Map* raw_updated = root_map->FindUpdatedMap( | 2601 Map* updated = root_map->FindUpdatedMap( |
2647 verbatim, descriptors, *old_descriptors); | 2602 verbatim, descriptors, old_descriptors); |
2648 if (raw_updated == NULL) { | 2603 if (updated == NULL) { |
2649 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2604 return CopyGeneralizeAllRepresentations( |
2650 old_details.attributes(), "incompatible"); | 2605 modify_index, store_mode, old_details.attributes(), "incompatible"); |
2651 } | 2606 } |
2652 | 2607 |
2653 Handle<Map> updated(raw_updated); | 2608 DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
2654 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); | |
2655 | 2609 |
2656 int valid = updated->NumberOfOwnDescriptors(); | 2610 int valid = updated->NumberOfOwnDescriptors(); |
2657 | 2611 |
2658 // Directly change the map if the target map is more general. Ensure that the | 2612 // Directly change the map if the target map is more general. Ensure that the |
2659 // target type of the modify_index is a FIELD, unless we are migrating. | 2613 // target type of the modify_index is a FIELD, unless we are migrating. |
2660 if (updated_descriptors->IsMoreGeneralThan( | 2614 if (updated_descriptors->IsMoreGeneralThan( |
2661 verbatim, valid, descriptors, *old_descriptors) && | 2615 verbatim, valid, descriptors, old_descriptors) && |
2662 (store_mode == ALLOW_AS_CONSTANT || | 2616 (store_mode == ALLOW_AS_CONSTANT || |
2663 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2617 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
2664 Representation updated_representation = | 2618 Representation updated_representation = |
2665 updated_descriptors->GetDetails(modify_index).representation(); | 2619 updated_descriptors->GetDetails(modify_index).representation(); |
2666 if (new_representation.fits_into(updated_representation)) return updated; | 2620 if (new_representation.fits_into(updated_representation)) return updated; |
2667 } | 2621 } |
2668 | 2622 |
2669 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( | 2623 DescriptorArray* new_descriptors; |
2670 updated_descriptors, verbatim, valid, descriptors, modify_index, | 2624 MaybeObject* maybe_descriptors = updated_descriptors->Merge( |
2671 store_mode, old_descriptors); | 2625 verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); |
| 2626 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
2672 ASSERT(store_mode == ALLOW_AS_CONSTANT || | 2627 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
2673 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2628 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2674 | 2629 |
2675 old_representation = | 2630 old_representation = |
2676 new_descriptors->GetDetails(modify_index).representation(); | 2631 new_descriptors->GetDetails(modify_index).representation(); |
2677 Representation updated_representation = | 2632 Representation updated_representation = |
2678 new_representation.generalize(old_representation); | 2633 new_representation.generalize(old_representation); |
2679 if (!updated_representation.Equals(old_representation)) { | 2634 if (!updated_representation.Equals(old_representation)) { |
2680 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2635 new_descriptors->SetRepresentation(modify_index, updated_representation); |
2681 } | 2636 } |
2682 | 2637 |
2683 Handle<Map> split_map(root_map->FindLastMatchMap( | 2638 Map* split_map = root_map->FindLastMatchMap( |
2684 verbatim, descriptors, *new_descriptors)); | 2639 verbatim, descriptors, new_descriptors); |
2685 | 2640 |
2686 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2641 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
2687 // This is shadowed by |updated_descriptors| being more general than | 2642 // This is shadowed by |updated_descriptors| being more general than |
2688 // |old_descriptors|. | 2643 // |old_descriptors|. |
2689 ASSERT(descriptors != split_descriptors); | 2644 ASSERT(descriptors != split_descriptors); |
2690 | 2645 |
2691 int descriptor = split_descriptors; | 2646 int descriptor = split_descriptors; |
2692 split_map->DeprecateTarget( | 2647 split_map->DeprecateTarget( |
2693 old_descriptors->GetKey(descriptor), *new_descriptors); | 2648 old_descriptors->GetKey(descriptor), new_descriptors); |
2694 | 2649 |
2695 if (FLAG_trace_generalization) { | 2650 if (FLAG_trace_generalization) { |
2696 old_map->PrintGeneralization( | 2651 PrintGeneralization( |
2697 stdout, "", modify_index, descriptor, descriptors, | 2652 stdout, "", modify_index, descriptor, descriptors, |
2698 old_descriptors->GetDetails(modify_index).type() == CONSTANT && | 2653 old_descriptors->GetDetails(modify_index).type() == CONSTANT && |
2699 store_mode == FORCE_FIELD, | 2654 store_mode == FORCE_FIELD, |
2700 old_representation, updated_representation); | 2655 old_representation, updated_representation); |
2701 } | 2656 } |
2702 | 2657 |
| 2658 Map* new_map = split_map; |
2703 // Add missing transitions. | 2659 // Add missing transitions. |
2704 Handle<Map> new_map = split_map; | |
2705 for (; descriptor < descriptors; descriptor++) { | 2660 for (; descriptor < descriptors; descriptor++) { |
2706 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); | 2661 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( |
| 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 } |
2707 new_map->set_migration_target(true); | 2670 new_map->set_migration_target(true); |
2708 } | 2671 } |
2709 | 2672 |
2710 new_map->set_owns_descriptors(true); | 2673 new_map->set_owns_descriptors(true); |
2711 return new_map; | 2674 return new_map; |
2712 } | 2675 } |
2713 | 2676 |
2714 | 2677 |
2715 Map* Map::CurrentMapForDeprecated() { | 2678 Map* Map::CurrentMapForDeprecated() { |
2716 DisallowHeapAllocation no_allocation; | 2679 DisallowHeapAllocation no_allocation; |
(...skipping 16 matching lines...) Expand all Loading... |
2733 int valid = updated->NumberOfOwnDescriptors(); | 2696 int valid = updated->NumberOfOwnDescriptors(); |
2734 if (!updated_descriptors->IsMoreGeneralThan( | 2697 if (!updated_descriptors->IsMoreGeneralThan( |
2735 verbatim, valid, descriptors, old_descriptors)) { | 2698 verbatim, valid, descriptors, old_descriptors)) { |
2736 return NULL; | 2699 return NULL; |
2737 } | 2700 } |
2738 | 2701 |
2739 return updated; | 2702 return updated; |
2740 } | 2703 } |
2741 | 2704 |
2742 | 2705 |
2743 Handle<Object> JSObject::SetPropertyWithInterceptor( | 2706 MaybeObject* JSObject::SetPropertyWithInterceptor( |
2744 Handle<JSObject> object, | 2707 Name* name, |
2745 Handle<Name> name, | 2708 Object* value, |
2746 Handle<Object> value, | |
2747 PropertyAttributes attributes, | 2709 PropertyAttributes attributes, |
2748 StrictModeFlag strict_mode) { | 2710 StrictModeFlag strict_mode) { |
2749 // TODO(rossberg): Support symbols in the API. | 2711 // TODO(rossberg): Support symbols in the API. |
2750 if (name->IsSymbol()) return value; | 2712 if (name->IsSymbol()) return value; |
2751 Isolate* isolate = object->GetIsolate(); | 2713 Isolate* isolate = GetIsolate(); |
2752 Handle<String> name_string = Handle<String>::cast(name); | 2714 HandleScope scope(isolate); |
2753 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); | 2715 Handle<JSObject> this_handle(this); |
| 2716 Handle<String> name_handle(String::cast(name)); |
| 2717 Handle<Object> value_handle(value, isolate); |
| 2718 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
2754 if (!interceptor->setter()->IsUndefined()) { | 2719 if (!interceptor->setter()->IsUndefined()) { |
2755 LOG(isolate, | 2720 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
2756 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); | 2721 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); |
2757 PropertyCallbackArguments args( | |
2758 isolate, interceptor->data(), *object, *object); | |
2759 v8::NamedPropertySetterCallback setter = | 2722 v8::NamedPropertySetterCallback setter = |
2760 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); | 2723 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |
2761 Handle<Object> value_unhole = value->IsTheHole() | 2724 Handle<Object> value_unhole(value->IsTheHole() ? |
2762 ? Handle<Object>(isolate->factory()->undefined_value()) : value; | 2725 isolate->heap()->undefined_value() : |
| 2726 value, |
| 2727 isolate); |
2763 v8::Handle<v8::Value> result = args.Call(setter, | 2728 v8::Handle<v8::Value> result = args.Call(setter, |
2764 v8::Utils::ToLocal(name_string), | 2729 v8::Utils::ToLocal(name_handle), |
2765 v8::Utils::ToLocal(value_unhole)); | 2730 v8::Utils::ToLocal(value_unhole)); |
2766 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 2731 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
2767 if (!result.IsEmpty()) return value; | 2732 if (!result.IsEmpty()) return *value_handle; |
2768 } | 2733 } |
2769 Handle<Object> result = | 2734 MaybeObject* raw_result = |
2770 SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); | 2735 this_handle->SetPropertyPostInterceptor(*name_handle, |
2771 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 2736 *value_handle, |
2772 return result; | 2737 attributes, |
| 2738 strict_mode); |
| 2739 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2740 return raw_result; |
2773 } | 2741 } |
2774 | 2742 |
2775 | 2743 |
2776 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 2744 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
2777 Handle<Name> name, | 2745 Handle<Name> key, |
2778 Handle<Object> value, | 2746 Handle<Object> value, |
2779 PropertyAttributes attributes, | 2747 PropertyAttributes attributes, |
2780 StrictModeFlag strict_mode, | 2748 StrictModeFlag strict_mode) { |
2781 StoreFromKeyed store_mode) { | 2749 CALL_HEAP_FUNCTION(object->GetIsolate(), |
2782 LookupResult result(object->GetIsolate()); | 2750 object->SetProperty(*key, *value, attributes, strict_mode), |
2783 object->LocalLookup(*name, &result, true); | 2751 Object); |
2784 if (!result.IsFound()) { | |
2785 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); | |
2786 } | |
2787 return SetProperty(object, &result, name, value, attributes, strict_mode, | |
2788 store_mode); | |
2789 } | 2752 } |
2790 | 2753 |
2791 | 2754 |
| 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 |
2792 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 2782 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
2793 Name* name, | 2783 Name* name, |
2794 Object* value, | 2784 Object* value, |
2795 JSObject* holder, | 2785 JSObject* holder, |
2796 StrictModeFlag strict_mode) { | 2786 StrictModeFlag strict_mode) { |
2797 Isolate* isolate = GetIsolate(); | 2787 Isolate* isolate = GetIsolate(); |
2798 HandleScope scope(isolate); | 2788 HandleScope scope(isolate); |
2799 | 2789 |
2800 // We should never get here to initialize a const with the hole | 2790 // We should never get here to initialize a const with the hole |
2801 // value since a const declaration would conflict with the setter. | 2791 // value since a const declaration would conflict with the setter. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2933 value, | 2923 value, |
2934 JSObject::cast(pt), | 2924 JSObject::cast(pt), |
2935 strict_mode); | 2925 strict_mode); |
2936 } | 2926 } |
2937 } | 2927 } |
2938 } | 2928 } |
2939 *found = false; | 2929 *found = false; |
2940 return heap->the_hole_value(); | 2930 return heap->the_hole_value(); |
2941 } | 2931 } |
2942 | 2932 |
2943 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, | 2933 MaybeObject* JSObject::SetPropertyViaPrototypes( |
2944 Handle<Name> name, | 2934 Name* name, |
2945 Handle<Object> value, | 2935 Object* value, |
2946 PropertyAttributes attributes, | 2936 PropertyAttributes attributes, |
2947 StrictModeFlag strict_mode, | 2937 StrictModeFlag strict_mode, |
2948 bool* done) { | 2938 bool* done) { |
2949 Isolate* isolate = object->GetIsolate(); | 2939 Heap* heap = GetHeap(); |
| 2940 Isolate* isolate = heap->isolate(); |
2950 | 2941 |
2951 *done = false; | 2942 *done = false; |
2952 // We could not find a local property so let's check whether there is an | 2943 // We could not find a local property so let's check whether there is an |
2953 // accessor that wants to handle the property, or whether the property is | 2944 // accessor that wants to handle the property, or whether the property is |
2954 // read-only on the prototype chain. | 2945 // read-only on the prototype chain. |
2955 LookupResult result(isolate); | 2946 LookupResult result(isolate); |
2956 object->LookupRealNamedPropertyInPrototypes(*name, &result); | 2947 LookupRealNamedPropertyInPrototypes(name, &result); |
2957 if (result.IsFound()) { | 2948 if (result.IsFound()) { |
2958 switch (result.type()) { | 2949 switch (result.type()) { |
2959 case NORMAL: | 2950 case NORMAL: |
2960 case FIELD: | 2951 case FIELD: |
2961 case CONSTANT: | 2952 case CONSTANT: |
2962 *done = result.IsReadOnly(); | 2953 *done = result.IsReadOnly(); |
2963 break; | 2954 break; |
2964 case INTERCEPTOR: { | 2955 case INTERCEPTOR: { |
2965 PropertyAttributes attr = | 2956 PropertyAttributes attr = |
2966 result.holder()->GetPropertyAttributeWithInterceptor( | 2957 result.holder()->GetPropertyAttributeWithInterceptor( |
2967 *object, *name, true); | 2958 this, name, true); |
2968 *done = !!(attr & READ_ONLY); | 2959 *done = !!(attr & READ_ONLY); |
2969 break; | 2960 break; |
2970 } | 2961 } |
2971 case CALLBACKS: { | 2962 case CALLBACKS: { |
2972 if (!FLAG_es5_readonly && result.IsReadOnly()) break; | 2963 if (!FLAG_es5_readonly && result.IsReadOnly()) break; |
2973 *done = true; | 2964 *done = true; |
2974 CALL_HEAP_FUNCTION(isolate, | 2965 return SetPropertyWithCallback(result.GetCallbackObject(), |
2975 object->SetPropertyWithCallback( | 2966 name, value, result.holder(), strict_mode); |
2976 result.GetCallbackObject(), | |
2977 *name, *value, result.holder(), strict_mode), | |
2978 Object); | |
2979 } | 2967 } |
2980 case HANDLER: { | 2968 case HANDLER: { |
2981 CALL_HEAP_FUNCTION(isolate, | 2969 return result.proxy()->SetPropertyViaPrototypesWithHandler( |
2982 result.proxy()->SetPropertyViaPrototypesWithHandler( | 2970 this, name, value, attributes, strict_mode, done); |
2983 *object, *name, *value, attributes, strict_mode, | |
2984 done), | |
2985 Object); | |
2986 } | 2971 } |
2987 case TRANSITION: | 2972 case TRANSITION: |
2988 case NONEXISTENT: | 2973 case NONEXISTENT: |
2989 UNREACHABLE(); | 2974 UNREACHABLE(); |
2990 break; | 2975 break; |
2991 } | 2976 } |
2992 } | 2977 } |
2993 | 2978 |
2994 // If we get here with *done true, we have encountered a read-only property. | 2979 // If we get here with *done true, we have encountered a read-only property. |
2995 if (!FLAG_es5_readonly) *done = false; | 2980 if (!FLAG_es5_readonly) *done = false; |
2996 if (*done) { | 2981 if (*done) { |
2997 if (strict_mode == kNonStrictMode) return value; | 2982 if (strict_mode == kNonStrictMode) return value; |
2998 Handle<Object> args[] = { name, object }; | 2983 Handle<Object> args[] = { Handle<Object>(name, isolate), |
2999 Handle<Object> error = isolate->factory()->NewTypeError( | 2984 Handle<Object>(this, isolate)}; |
3000 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 2985 return isolate->Throw(*isolate->factory()->NewTypeError( |
3001 isolate->Throw(*error); | 2986 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); |
3002 return Handle<Object>(); | |
3003 } | 2987 } |
3004 return isolate->factory()->the_hole_value(); | 2988 return heap->the_hole_value(); |
3005 } | 2989 } |
3006 | 2990 |
3007 | 2991 |
3008 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 2992 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
3009 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2993 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
3010 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 2994 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
3011 int number_of_descriptors = descriptors->number_of_descriptors(); | 2995 int number_of_descriptors = descriptors->number_of_descriptors(); |
3012 Isolate* isolate = map->GetIsolate(); | 2996 Isolate* isolate = map->GetIsolate(); |
3013 Handle<DescriptorArray> new_descriptors = | 2997 Handle<DescriptorArray> new_descriptors = |
3014 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); | 2998 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3415 | 3399 |
3416 Isolate* isolate = GetIsolate(); | 3400 Isolate* isolate = GetIsolate(); |
3417 HandleScope scope(isolate); | 3401 HandleScope scope(isolate); |
3418 Handle<Object> value_handle(value, isolate); | 3402 Handle<Object> value_handle(value, isolate); |
3419 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3403 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
3420 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 3404 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
3421 return *value_handle; | 3405 return *value_handle; |
3422 } | 3406 } |
3423 | 3407 |
3424 | 3408 |
3425 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 3409 MaybeObject* JSReceiver::SetProperty(LookupResult* result, |
3426 LookupResult* result, | 3410 Name* key, |
3427 Handle<Name> key, | 3411 Object* value, |
3428 Handle<Object> value, | 3412 PropertyAttributes attributes, |
3429 PropertyAttributes attributes, | 3413 StrictModeFlag strict_mode, |
3430 StrictModeFlag strict_mode, | 3414 JSReceiver::StoreFromKeyed store_mode) { |
3431 StoreFromKeyed store_mode) { | |
3432 if (result->IsHandler()) { | 3415 if (result->IsHandler()) { |
3433 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), | 3416 return result->proxy()->SetPropertyWithHandler( |
3434 object, key, value, attributes, strict_mode); | 3417 this, key, value, attributes, strict_mode); |
3435 } else { | 3418 } else { |
3436 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object), | 3419 return JSObject::cast(this)->SetPropertyForResult( |
3437 result, key, value, attributes, strict_mode, store_mode); | 3420 result, key, value, attributes, strict_mode, store_mode); |
3438 } | 3421 } |
3439 } | 3422 } |
3440 | 3423 |
3441 | 3424 |
3442 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { | 3425 bool JSProxy::HasPropertyWithHandler(Name* name_raw) { |
3443 Isolate* isolate = proxy->GetIsolate(); | 3426 Isolate* isolate = GetIsolate(); |
| 3427 HandleScope scope(isolate); |
| 3428 Handle<Object> receiver(this, isolate); |
| 3429 Handle<Object> name(name_raw, isolate); |
3444 | 3430 |
3445 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3431 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3446 if (name->IsSymbol()) return false; | 3432 if (name->IsSymbol()) return false; |
3447 | 3433 |
3448 Handle<Object> args[] = { name }; | 3434 Handle<Object> args[] = { name }; |
3449 Handle<Object> result = proxy->CallTrap( | 3435 Handle<Object> result = CallTrap( |
3450 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); | 3436 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); |
3451 if (isolate->has_pending_exception()) return false; | 3437 if (isolate->has_pending_exception()) return false; |
3452 | 3438 |
3453 return result->BooleanValue(); | 3439 return result->BooleanValue(); |
3454 } | 3440 } |
3455 | 3441 |
3456 | 3442 |
3457 Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, | 3443 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( |
3458 Handle<JSReceiver> receiver, | 3444 JSReceiver* receiver_raw, |
3459 Handle<Name> name, | 3445 Name* name_raw, |
3460 Handle<Object> value, | 3446 Object* value_raw, |
3461 PropertyAttributes attributes, | 3447 PropertyAttributes attributes, |
3462 StrictModeFlag strict_mode) { | 3448 StrictModeFlag strict_mode) { |
3463 Isolate* isolate = proxy->GetIsolate(); | 3449 Isolate* isolate = 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); |
3464 | 3454 |
3465 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3455 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3466 if (name->IsSymbol()) return value; | 3456 if (name->IsSymbol()) return *value; |
3467 | 3457 |
3468 Handle<Object> args[] = { receiver, name, value }; | 3458 Handle<Object> args[] = { receiver, name, value }; |
3469 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); | 3459 CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); |
3470 if (isolate->has_pending_exception()) return Handle<Object>(); | 3460 if (isolate->has_pending_exception()) return Failure::Exception(); |
3471 | 3461 |
3472 return value; | 3462 return *value; |
3473 } | 3463 } |
3474 | 3464 |
3475 | 3465 |
3476 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( | 3466 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( |
3477 JSReceiver* receiver_raw, | 3467 JSReceiver* receiver_raw, |
3478 Name* name_raw, | 3468 Name* name_raw, |
3479 Object* value_raw, | 3469 Object* value_raw, |
3480 PropertyAttributes attributes, | 3470 PropertyAttributes attributes, |
3481 StrictModeFlag strict_mode, | 3471 StrictModeFlag strict_mode, |
3482 bool* done) { | 3472 bool* done) { |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3737 | 3727 |
3738 | 3728 |
3739 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { | 3729 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
3740 CALL_HEAP_FUNCTION_VOID( | 3730 CALL_HEAP_FUNCTION_VOID( |
3741 object->GetIsolate(), | 3731 object->GetIsolate(), |
3742 object->AllocateStorageForMap(*map)); | 3732 object->AllocateStorageForMap(*map)); |
3743 } | 3733 } |
3744 | 3734 |
3745 | 3735 |
3746 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3736 void JSObject::MigrateInstance(Handle<JSObject> object) { |
3747 // Converting any field to the most specific type will cause the | 3737 CALL_HEAP_FUNCTION_VOID( |
3748 // GeneralizeFieldRepresentation algorithm to create the most general existing | 3738 object->GetIsolate(), |
3749 // transition that matches the object. This achieves what is needed. | 3739 object->MigrateInstance()); |
3750 Handle<Map> original_map(object->map()); | |
3751 GeneralizeFieldRepresentation( | |
3752 object, 0, Representation::None(), ALLOW_AS_CONSTANT); | |
3753 if (FLAG_trace_migration) { | |
3754 object->PrintInstanceMigration(stdout, *original_map, object->map()); | |
3755 } | |
3756 } | 3740 } |
3757 | 3741 |
3758 | 3742 |
3759 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3743 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
3760 MigrateInstance(object); | 3744 CALL_HEAP_FUNCTION( |
3761 return object; | 3745 object->GetIsolate(), |
| 3746 object->MigrateInstance(), |
| 3747 Object); |
3762 } | 3748 } |
3763 | 3749 |
3764 | 3750 |
3765 Handle<Object> JSObject::SetPropertyUsingTransition( | 3751 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, |
3766 Handle<JSObject> object, | 3752 int modify_index, |
3767 LookupResult* lookup, | 3753 Representation representation, |
3768 Handle<Name> name, | 3754 StoreMode store_mode) { |
3769 Handle<Object> value, | 3755 CALL_HEAP_FUNCTION( |
3770 PropertyAttributes attributes) { | 3756 map->GetIsolate(), |
3771 Handle<Map> transition_map(lookup->GetTransitionTarget()); | 3757 map->GeneralizeRepresentation(modify_index, representation, store_mode), |
| 3758 Map); |
| 3759 } |
| 3760 |
| 3761 |
| 3762 static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, |
| 3763 Handle<Name> name, |
| 3764 Handle<Object> value, |
| 3765 PropertyAttributes attributes) { |
| 3766 Map* transition_map = lookup->GetTransitionTarget(); |
3772 int descriptor = transition_map->LastAdded(); | 3767 int descriptor = transition_map->LastAdded(); |
3773 | 3768 |
3774 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3769 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
3775 PropertyDetails details = descriptors->GetDetails(descriptor); | 3770 PropertyDetails details = descriptors->GetDetails(descriptor); |
3776 | 3771 |
3777 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3772 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
3778 // AddProperty will either normalize the object, or create a new fast copy | 3773 // AddProperty will either normalize the object, or create a new fast copy |
3779 // of the map. If we get a fast copy of the map, all field representations | 3774 // of the map. If we get a fast copy of the map, all field representations |
3780 // will be tagged since the transition is omitted. | 3775 // will be tagged since the transition is omitted. |
3781 return JSObject::AddProperty( | 3776 return lookup->holder()->AddProperty( |
3782 object, name, value, attributes, kNonStrictMode, | 3777 *name, *value, attributes, kNonStrictMode, |
3783 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 3778 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
3784 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 3779 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
3785 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 3780 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
3786 } | 3781 } |
3787 | 3782 |
3788 // Keep the target CONSTANT if the same value is stored. | 3783 // Keep the target CONSTANT if the same value is stored. |
3789 // TODO(verwaest): Also support keeping the placeholder | 3784 // TODO(verwaest): Also support keeping the placeholder |
3790 // (value->IsUninitialized) as constant. | 3785 // (value->IsUninitialized) as constant. |
3791 if (details.type() == CONSTANT && | 3786 if (details.type() == CONSTANT && |
3792 descriptors->GetValue(descriptor) == *value) { | 3787 descriptors->GetValue(descriptor) == *value) { |
3793 object->set_map(*transition_map); | 3788 lookup->holder()->set_map(transition_map); |
3794 return value; | 3789 return *value; |
3795 } | 3790 } |
3796 | 3791 |
3797 Representation representation = details.representation(); | 3792 Representation representation = details.representation(); |
3798 | 3793 |
3799 if (!value->FitsRepresentation(representation) || | 3794 if (!value->FitsRepresentation(representation) || |
3800 details.type() == CONSTANT) { | 3795 details.type() == CONSTANT) { |
3801 transition_map = Map::GeneralizeRepresentation(transition_map, | 3796 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( |
3802 descriptor, value->OptimalRepresentation(), FORCE_FIELD); | 3797 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
| 3798 if (!maybe_map->To(&transition_map)) return maybe_map; |
3803 Object* back = transition_map->GetBackPointer(); | 3799 Object* back = transition_map->GetBackPointer(); |
3804 if (back->IsMap()) { | 3800 if (back->IsMap()) { |
3805 MigrateToMap(object, handle(Map::cast(back))); | 3801 MaybeObject* maybe_failure = |
| 3802 lookup->holder()->MigrateToMap(Map::cast(back)); |
| 3803 if (maybe_failure->IsFailure()) return maybe_failure; |
3806 } | 3804 } |
3807 descriptors = transition_map->instance_descriptors(); | 3805 descriptors = transition_map->instance_descriptors(); |
3808 representation = descriptors->GetDetails(descriptor).representation(); | 3806 representation = descriptors->GetDetails(descriptor).representation(); |
3809 } | 3807 } |
3810 | 3808 |
3811 int field_index = descriptors->GetFieldIndex(descriptor); | 3809 int field_index = descriptors->GetFieldIndex(descriptor); |
3812 return AddFastPropertyUsingMap( | 3810 return lookup->holder()->AddFastPropertyUsingMap( |
3813 object, transition_map, name, value, field_index, representation); | 3811 transition_map, *name, *value, field_index, representation); |
3814 } | 3812 } |
3815 | 3813 |
3816 | 3814 |
3817 static Handle<Object> SetPropertyToField(LookupResult* lookup, | 3815 static MaybeObject* SetPropertyToField(LookupResult* lookup, |
3818 Handle<Name> name, | 3816 Handle<Name> name, |
3819 Handle<Object> value) { | 3817 Handle<Object> value) { |
3820 Representation representation = lookup->representation(); | 3818 Representation representation = lookup->representation(); |
3821 if (!value->FitsRepresentation(representation) || | 3819 if (!value->FitsRepresentation(representation) || |
3822 lookup->type() == CONSTANT) { | 3820 lookup->type() == CONSTANT) { |
3823 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), | 3821 MaybeObject* maybe_failure = |
3824 lookup->GetDescriptorIndex(), | 3822 lookup->holder()->GeneralizeFieldRepresentation( |
3825 value->OptimalRepresentation(), | 3823 lookup->GetDescriptorIndex(), |
3826 FORCE_FIELD); | 3824 value->OptimalRepresentation(), |
| 3825 FORCE_FIELD); |
| 3826 if (maybe_failure->IsFailure()) return maybe_failure; |
3827 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 3827 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
3828 int descriptor = lookup->GetDescriptorIndex(); | 3828 int descriptor = lookup->GetDescriptorIndex(); |
3829 representation = desc->GetDetails(descriptor).representation(); | 3829 representation = desc->GetDetails(descriptor).representation(); |
3830 } | 3830 } |
3831 | 3831 |
3832 if (FLAG_track_double_fields && representation.IsDouble()) { | 3832 if (FLAG_track_double_fields && representation.IsDouble()) { |
3833 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 3833 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
3834 lookup->GetFieldIndex().field_index())); | 3834 lookup->GetFieldIndex().field_index())); |
3835 storage->set_value(value->Number()); | 3835 storage->set_value(value->Number()); |
3836 return value; | 3836 return *value; |
3837 } | 3837 } |
3838 | 3838 |
3839 lookup->holder()->FastPropertyAtPut( | 3839 lookup->holder()->FastPropertyAtPut( |
3840 lookup->GetFieldIndex().field_index(), *value); | 3840 lookup->GetFieldIndex().field_index(), *value); |
| 3841 return *value; |
| 3842 } |
| 3843 |
| 3844 |
| 3845 static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup, |
| 3846 Name* name, |
| 3847 Object* value, |
| 3848 PropertyAttributes attributes) { |
| 3849 JSObject* object = lookup->holder(); |
| 3850 if (object->TooManyFastProperties()) { |
| 3851 MaybeObject* maybe_failure = object->NormalizeProperties( |
| 3852 CLEAR_INOBJECT_PROPERTIES, 0); |
| 3853 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3854 } |
| 3855 |
| 3856 if (!object->HasFastProperties()) { |
| 3857 return object->ReplaceSlowProperty(name, value, attributes); |
| 3858 } |
| 3859 |
| 3860 int descriptor_index = lookup->GetDescriptorIndex(); |
| 3861 if (lookup->GetAttributes() == attributes) { |
| 3862 MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation( |
| 3863 descriptor_index, Representation::Tagged(), FORCE_FIELD); |
| 3864 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3865 } else { |
| 3866 Map* map; |
| 3867 MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations( |
| 3868 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
| 3869 if (!maybe_map->To(&map)) return maybe_map; |
| 3870 MaybeObject* maybe_failure = object->MigrateToMap(map); |
| 3871 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3872 } |
| 3873 |
| 3874 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 3875 int index = descriptors->GetDetails(descriptor_index).field_index(); |
| 3876 object->FastPropertyAtPut(index, value); |
3841 return value; | 3877 return value; |
3842 } | 3878 } |
3843 | 3879 |
3844 | 3880 |
3845 static Handle<Object> ConvertAndSetLocalProperty( | 3881 static MaybeObject* SetPropertyToFieldWithAttributes( |
3846 LookupResult* lookup, | |
3847 Handle<Name> name, | |
3848 Handle<Object> value, | |
3849 PropertyAttributes attributes) { | |
3850 Handle<JSObject> object(lookup->holder()); | |
3851 if (object->TooManyFastProperties()) { | |
3852 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | |
3853 } | |
3854 | |
3855 if (!object->HasFastProperties()) { | |
3856 return ReplaceSlowProperty(object, name, value, attributes); | |
3857 } | |
3858 | |
3859 int descriptor_index = lookup->GetDescriptorIndex(); | |
3860 if (lookup->GetAttributes() == attributes) { | |
3861 JSObject::GeneralizeFieldRepresentation( | |
3862 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); | |
3863 } else { | |
3864 Handle<Map> old_map(object->map()); | |
3865 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, | |
3866 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | |
3867 JSObject::MigrateToMap(object, new_map); | |
3868 } | |
3869 | |
3870 DescriptorArray* descriptors = object->map()->instance_descriptors(); | |
3871 int index = descriptors->GetDetails(descriptor_index).field_index(); | |
3872 object->FastPropertyAtPut(index, *value); | |
3873 return value; | |
3874 } | |
3875 | |
3876 | |
3877 static Handle<Object> SetPropertyToFieldWithAttributes( | |
3878 LookupResult* lookup, | 3882 LookupResult* lookup, |
3879 Handle<Name> name, | 3883 Handle<Name> name, |
3880 Handle<Object> value, | 3884 Handle<Object> value, |
3881 PropertyAttributes attributes) { | 3885 PropertyAttributes attributes) { |
3882 if (lookup->GetAttributes() == attributes) { | 3886 if (lookup->GetAttributes() == attributes) { |
3883 if (value->IsUninitialized()) return value; | 3887 if (value->IsUninitialized()) return *value; |
3884 return SetPropertyToField(lookup, name, value); | 3888 return SetPropertyToField(lookup, name, value); |
3885 } else { | 3889 } else { |
3886 return ConvertAndSetLocalProperty(lookup, name, value, attributes); | 3890 return ConvertAndSetLocalProperty(lookup, *name, *value, attributes); |
3887 } | 3891 } |
3888 } | 3892 } |
3889 | 3893 |
3890 | 3894 |
3891 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, | 3895 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, |
3892 LookupResult* lookup, | 3896 Name* name_raw, |
3893 Handle<Name> name, | 3897 Object* value_raw, |
3894 Handle<Object> value, | 3898 PropertyAttributes attributes, |
3895 PropertyAttributes attributes, | 3899 StrictModeFlag strict_mode, |
3896 StrictModeFlag strict_mode, | 3900 StoreFromKeyed store_mode) { |
3897 StoreFromKeyed store_mode) { | 3901 Heap* heap = GetHeap(); |
3898 Isolate* isolate = object->GetIsolate(); | 3902 Isolate* isolate = heap->isolate(); |
3899 | 3903 |
3900 // 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 |
3901 // interceptor calls. | 3905 // interceptor calls. |
3902 AssertNoContextChange ncc; | 3906 AssertNoContextChangeWithHandleScope ncc; |
3903 | 3907 |
3904 // 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 |
3905 // dictionary. We internalize these short keys to avoid constantly | 3909 // dictionary. We internalize these short keys to avoid constantly |
3906 // reallocating them. | 3910 // reallocating them. |
3907 if (name->IsString() && !name->IsInternalizedString() && | 3911 if (name_raw->IsString() && !name_raw->IsInternalizedString() && |
3908 Handle<String>::cast(name)->length() <= 2) { | 3912 String::cast(name_raw)->length() <= 2) { |
3909 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); | 3913 Object* internalized_version; |
| 3914 { MaybeObject* maybe_string_version = |
| 3915 heap->InternalizeString(String::cast(name_raw)); |
| 3916 if (maybe_string_version->ToObject(&internalized_version)) { |
| 3917 name_raw = String::cast(internalized_version); |
| 3918 } |
| 3919 } |
3910 } | 3920 } |
3911 | 3921 |
3912 // Check access rights if needed. | 3922 // Check access rights if needed. |
3913 if (object->IsAccessCheckNeeded()) { | 3923 if (IsAccessCheckNeeded()) { |
3914 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 3924 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { |
3915 CALL_HEAP_FUNCTION( | 3925 return SetPropertyWithFailedAccessCheck( |
3916 isolate, | 3926 lookup, name_raw, value_raw, true, strict_mode); |
3917 object->SetPropertyWithFailedAccessCheck( | |
3918 lookup, *name, *value, true, strict_mode), | |
3919 Object); | |
3920 } | 3927 } |
3921 } | 3928 } |
3922 | 3929 |
3923 if (object->IsJSGlobalProxy()) { | 3930 if (IsJSGlobalProxy()) { |
3924 Handle<Object> proto(object->GetPrototype(), isolate); | 3931 Object* proto = GetPrototype(); |
3925 if (proto->IsNull()) return value; | 3932 if (proto->IsNull()) return value_raw; |
3926 ASSERT(proto->IsJSGlobalObject()); | 3933 ASSERT(proto->IsJSGlobalObject()); |
3927 return SetPropertyForResult(Handle<JSObject>::cast(proto), | 3934 return JSObject::cast(proto)->SetPropertyForResult( |
3928 lookup, name, value, attributes, strict_mode, store_mode); | 3935 lookup, name_raw, value_raw, attributes, strict_mode, store_mode); |
3929 } | 3936 } |
3930 | 3937 |
3931 ASSERT(!lookup->IsFound() || lookup->holder() == *object || | 3938 ASSERT(!lookup->IsFound() || lookup->holder() == this || |
3932 lookup->holder()->map()->is_hidden_prototype()); | 3939 lookup->holder()->map()->is_hidden_prototype()); |
3933 | 3940 |
3934 if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) { | 3941 // From this point on everything needs to be handlified, because |
| 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()) { |
3935 bool done = false; | 3949 bool done = false; |
3936 Handle<Object> result_object = SetPropertyViaPrototypes( | 3950 MaybeObject* result_object = self->SetPropertyViaPrototypes( |
3937 object, name, value, attributes, strict_mode, &done); | 3951 *name, *value, attributes, strict_mode, &done); |
3938 if (done) return result_object; | 3952 if (done) return result_object; |
3939 } | 3953 } |
3940 | 3954 |
3941 if (!lookup->IsFound()) { | 3955 if (!lookup->IsFound()) { |
3942 // Neither properties nor transitions found. | 3956 // Neither properties nor transitions found. |
3943 return AddProperty( | 3957 return self->AddProperty( |
3944 object, name, value, attributes, strict_mode, store_mode); | 3958 *name, *value, attributes, strict_mode, store_mode); |
3945 } | 3959 } |
3946 | 3960 |
3947 if (lookup->IsProperty() && lookup->IsReadOnly()) { | 3961 if (lookup->IsProperty() && lookup->IsReadOnly()) { |
3948 if (strict_mode == kStrictMode) { | 3962 if (strict_mode == kStrictMode) { |
3949 Handle<Object> args[] = { name, object }; | 3963 Handle<Object> args[] = { name, self }; |
3950 Handle<Object> error = isolate->factory()->NewTypeError( | 3964 return isolate->Throw(*isolate->factory()->NewTypeError( |
3951 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 3965 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); |
3952 isolate->Throw(*error); | |
3953 return Handle<Object>(); | |
3954 } else { | 3966 } else { |
3955 return value; | 3967 return *value; |
3956 } | 3968 } |
3957 } | 3969 } |
3958 | 3970 |
3959 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 3971 Handle<Object> old_value(heap->the_hole_value(), isolate); |
3960 if (FLAG_harmony_observation && | 3972 if (FLAG_harmony_observation && |
3961 object->map()->is_observed() && lookup->IsDataProperty()) { | 3973 map()->is_observed() && lookup->IsDataProperty()) { |
3962 old_value = Object::GetProperty(object, name); | 3974 old_value = Object::GetProperty(self, name); |
3963 } | 3975 } |
3964 | 3976 |
3965 // This is a real property that is not read-only, or it is a | 3977 // This is a real property that is not read-only, or it is a |
3966 // transition or null descriptor and there are no setters in the prototypes. | 3978 // transition or null descriptor and there are no setters in the prototypes. |
3967 Handle<Object> result = value; | 3979 MaybeObject* result = *value; |
3968 switch (lookup->type()) { | 3980 switch (lookup->type()) { |
3969 case NORMAL: | 3981 case NORMAL: |
3970 result = SetNormalizedProperty(handle(lookup->holder()), lookup, value); | 3982 result = lookup->holder()->SetNormalizedProperty(lookup, *value); |
3971 break; | 3983 break; |
3972 case FIELD: | 3984 case FIELD: |
3973 result = SetPropertyToField(lookup, name, value); | 3985 result = SetPropertyToField(lookup, name, value); |
3974 break; | 3986 break; |
3975 case CONSTANT: | 3987 case CONSTANT: |
3976 // Only replace the constant if necessary. | 3988 // Only replace the constant if necessary. |
3977 if (*value == lookup->GetConstant()) return value; | 3989 if (*value == lookup->GetConstant()) return *value; |
3978 result = SetPropertyToField(lookup, name, value); | 3990 result = SetPropertyToField(lookup, name, value); |
3979 break; | 3991 break; |
3980 case CALLBACKS: { | 3992 case CALLBACKS: { |
3981 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); | 3993 Object* callback_object = lookup->GetCallbackObject(); |
3982 CALL_HEAP_FUNCTION( | 3994 return self->SetPropertyWithCallback( |
3983 isolate, | 3995 callback_object, *name, *value, lookup->holder(), strict_mode); |
3984 object->SetPropertyWithCallback(*callback_object, *name, *value, | |
3985 lookup->holder(), strict_mode), | |
3986 Object); | |
3987 } | 3996 } |
3988 case INTERCEPTOR: | 3997 case INTERCEPTOR: |
3989 result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value, | 3998 result = lookup->holder()->SetPropertyWithInterceptor( |
3990 attributes, strict_mode); | 3999 *name, *value, attributes, strict_mode); |
3991 break; | 4000 break; |
3992 case TRANSITION: | 4001 case TRANSITION: { |
3993 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, | 4002 result = SetPropertyUsingTransition(lookup, name, value, attributes); |
3994 name, value, attributes); | |
3995 break; | 4003 break; |
| 4004 } |
3996 case HANDLER: | 4005 case HANDLER: |
3997 case NONEXISTENT: | 4006 case NONEXISTENT: |
3998 UNREACHABLE(); | 4007 UNREACHABLE(); |
3999 } | 4008 } |
4000 | 4009 |
4001 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); | 4010 Handle<Object> hresult; |
| 4011 if (!result->ToHandle(&hresult, isolate)) return result; |
4002 | 4012 |
4003 if (FLAG_harmony_observation && object->map()->is_observed()) { | 4013 if (FLAG_harmony_observation && self->map()->is_observed()) { |
4004 if (lookup->IsTransition()) { | 4014 if (lookup->IsTransition()) { |
4005 EnqueueChangeRecord(object, "new", name, old_value); | 4015 EnqueueChangeRecord(self, "new", name, old_value); |
4006 } else { | 4016 } else { |
4007 LookupResult new_lookup(isolate); | 4017 LookupResult new_lookup(isolate); |
4008 object->LocalLookup(*name, &new_lookup, true); | 4018 self->LocalLookup(*name, &new_lookup, true); |
4009 if (new_lookup.IsDataProperty()) { | 4019 if (new_lookup.IsDataProperty()) { |
4010 Handle<Object> new_value = Object::GetProperty(object, name); | 4020 Handle<Object> new_value = Object::GetProperty(self, name); |
4011 if (!new_value->SameValue(*old_value)) { | 4021 if (!new_value->SameValue(*old_value)) { |
4012 EnqueueChangeRecord(object, "updated", name, old_value); | 4022 EnqueueChangeRecord(self, "updated", name, old_value); |
4013 } | 4023 } |
4014 } | 4024 } |
4015 } | 4025 } |
4016 } | 4026 } |
4017 | 4027 |
4018 return result; | 4028 return *hresult; |
4019 } | 4029 } |
4020 | 4030 |
4021 | 4031 |
4022 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( | 4032 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( |
4023 Name* key, | 4033 Name* key, |
4024 Object* value, | 4034 Object* value, |
4025 PropertyAttributes attributes, | 4035 PropertyAttributes attributes, |
4026 ValueType value_type, | 4036 ValueType value_type, |
4027 StoreMode mode, | 4037 StoreMode mode, |
4028 ExtensibilityCheck extensibility_check) { | 4038 ExtensibilityCheck extensibility_check) { |
(...skipping 17 matching lines...) Expand all Loading... |
4046 // present, add it with attributes NONE. This code is an exact clone of | 4056 // present, add it with attributes NONE. This code is an exact clone of |
4047 // SetProperty, with the check for IsReadOnly and the check for a | 4057 // SetProperty, with the check for IsReadOnly and the check for a |
4048 // callback setter removed. The two lines looking up the LookupResult | 4058 // callback setter removed. The two lines looking up the LookupResult |
4049 // result are also added. If one of the functions is changed, the other | 4059 // result are also added. If one of the functions is changed, the other |
4050 // should be. | 4060 // should be. |
4051 // Note that this method cannot be used to set the prototype of a function | 4061 // Note that this method cannot be used to set the prototype of a function |
4052 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" | 4062 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
4053 // doesn't handle function prototypes correctly. | 4063 // doesn't handle function prototypes correctly. |
4054 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( | 4064 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( |
4055 Handle<JSObject> object, | 4065 Handle<JSObject> object, |
4056 Handle<Name> name, | 4066 Handle<Name> key, |
4057 Handle<Object> value, | 4067 Handle<Object> value, |
4058 PropertyAttributes attributes, | 4068 PropertyAttributes attributes, |
4059 ValueType value_type, | 4069 ValueType value_type, |
4060 StoreMode mode, | 4070 StoreMode mode, |
4061 ExtensibilityCheck extensibility_check) { | 4071 ExtensibilityCheck extensibility_check) { |
4062 Isolate* isolate = object->GetIsolate(); | 4072 CALL_HEAP_FUNCTION( |
| 4073 object->GetIsolate(), |
| 4074 object->SetLocalPropertyIgnoreAttributes( |
| 4075 *key, *value, attributes, value_type, mode, extensibility_check), |
| 4076 Object); |
| 4077 } |
4063 | 4078 |
| 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) { |
4064 // Make sure that the top context does not change when doing callbacks or | 4087 // Make sure that the top context does not change when doing callbacks or |
4065 // interceptor calls. | 4088 // interceptor calls. |
4066 AssertNoContextChange ncc; | 4089 AssertNoContextChangeWithHandleScope ncc; |
4067 | 4090 Isolate* isolate = GetIsolate(); |
4068 LookupResult lookup(isolate); | 4091 LookupResult lookup(isolate); |
4069 object->LocalLookup(*name, &lookup, true); | 4092 LocalLookup(name_raw, &lookup, true); |
4070 if (!lookup.IsFound()) { | 4093 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup); |
4071 object->map()->LookupTransition(*object, *name, &lookup); | |
4072 } | |
4073 | |
4074 // Check access rights if needed. | 4094 // Check access rights if needed. |
4075 if (object->IsAccessCheckNeeded()) { | 4095 if (IsAccessCheckNeeded()) { |
4076 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 4096 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { |
4077 CALL_HEAP_FUNCTION( | 4097 return SetPropertyWithFailedAccessCheck(&lookup, |
4078 isolate, | 4098 name_raw, |
4079 object->SetPropertyWithFailedAccessCheck( | 4099 value_raw, |
4080 &lookup, *name, *value, false, kNonStrictMode), | 4100 false, |
4081 Object); | 4101 kNonStrictMode); |
4082 } | 4102 } |
4083 } | 4103 } |
4084 | 4104 |
4085 if (object->IsJSGlobalProxy()) { | 4105 if (IsJSGlobalProxy()) { |
4086 Handle<Object> proto(object->GetPrototype(), isolate); | 4106 Object* proto = GetPrototype(); |
4087 if (proto->IsNull()) return value; | 4107 if (proto->IsNull()) return value_raw; |
4088 ASSERT(proto->IsJSGlobalObject()); | 4108 ASSERT(proto->IsJSGlobalObject()); |
4089 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), | 4109 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( |
4090 name, value, attributes, value_type, mode, extensibility_check); | 4110 name_raw, |
| 4111 value_raw, |
| 4112 attributes, |
| 4113 value_type, |
| 4114 mode, |
| 4115 extensibility_check); |
4091 } | 4116 } |
4092 | 4117 |
4093 if (lookup.IsFound() && | 4118 if (lookup.IsFound() && |
4094 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { | 4119 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { |
4095 object->LocalLookupRealNamedProperty(*name, &lookup); | 4120 LocalLookupRealNamedProperty(name_raw, &lookup); |
4096 } | 4121 } |
4097 | 4122 |
4098 // Check for accessor in prototype chain removed here in clone. | 4123 // Check for accessor in prototype chain removed here in clone. |
4099 if (!lookup.IsFound()) { | 4124 if (!lookup.IsFound()) { |
4100 // Neither properties nor transitions found. | 4125 // Neither properties nor transitions found. |
4101 return AddProperty(object, name, value, attributes, kNonStrictMode, | 4126 return AddProperty( |
| 4127 name_raw, value_raw, attributes, kNonStrictMode, |
4102 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | 4128 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); |
4103 } | 4129 } |
4104 | 4130 |
4105 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4131 // From this point on everything needs to be handlified. |
| 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); |
4106 PropertyAttributes old_attributes = ABSENT; | 4138 PropertyAttributes old_attributes = ABSENT; |
4107 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 4139 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); |
4108 if (is_observed && lookup.IsProperty()) { | 4140 if (is_observed && lookup.IsProperty()) { |
4109 if (lookup.IsDataProperty()) old_value = | 4141 if (lookup.IsDataProperty()) old_value = |
4110 Object::GetProperty(object, name); | 4142 Object::GetProperty(self, name); |
4111 old_attributes = lookup.GetAttributes(); | 4143 old_attributes = lookup.GetAttributes(); |
4112 } | 4144 } |
4113 | 4145 |
4114 // Check of IsReadOnly removed from here in clone. | 4146 // Check of IsReadOnly removed from here in clone. |
4115 Handle<Object> result = value; | 4147 MaybeObject* result = *value; |
4116 switch (lookup.type()) { | 4148 switch (lookup.type()) { |
4117 case NORMAL: | 4149 case NORMAL: |
4118 result = ReplaceSlowProperty(object, name, value, attributes); | 4150 result = self->ReplaceSlowProperty(*name, *value, attributes); |
4119 break; | 4151 break; |
4120 case FIELD: | 4152 case FIELD: |
4121 result = SetPropertyToFieldWithAttributes( | 4153 result = SetPropertyToFieldWithAttributes( |
4122 &lookup, name, value, attributes); | 4154 &lookup, name, value, attributes); |
4123 break; | 4155 break; |
4124 case CONSTANT: | 4156 case CONSTANT: |
4125 // Only replace the constant if necessary. | 4157 // Only replace the constant if necessary. |
4126 if (lookup.GetAttributes() != attributes || | 4158 if (lookup.GetAttributes() != attributes || |
4127 *value != lookup.GetConstant()) { | 4159 *value != lookup.GetConstant()) { |
4128 result = SetPropertyToFieldWithAttributes( | 4160 result = SetPropertyToFieldWithAttributes( |
4129 &lookup, name, value, attributes); | 4161 &lookup, name, value, attributes); |
4130 } | 4162 } |
4131 break; | 4163 break; |
4132 case CALLBACKS: | 4164 case CALLBACKS: |
4133 result = ConvertAndSetLocalProperty(&lookup, name, value, attributes); | 4165 result = ConvertAndSetLocalProperty(&lookup, *name, *value, attributes); |
4134 break; | 4166 break; |
4135 case TRANSITION: | 4167 case TRANSITION: |
4136 result = SetPropertyUsingTransition(handle(lookup.holder()), &lookup, | 4168 result = SetPropertyUsingTransition(&lookup, name, value, attributes); |
4137 name, value, attributes); | |
4138 break; | 4169 break; |
4139 case NONEXISTENT: | 4170 case NONEXISTENT: |
4140 case HANDLER: | 4171 case HANDLER: |
4141 case INTERCEPTOR: | 4172 case INTERCEPTOR: |
4142 UNREACHABLE(); | 4173 UNREACHABLE(); |
4143 } | 4174 } |
4144 | 4175 |
4145 if (result.is_null()) return result; | 4176 Handle<Object> hresult; |
| 4177 if (!result->ToHandle(&hresult, isolate)) return result; |
4146 | 4178 |
4147 if (is_observed) { | 4179 if (is_observed) { |
4148 if (lookup.IsTransition()) { | 4180 if (lookup.IsTransition()) { |
4149 EnqueueChangeRecord(object, "new", name, old_value); | 4181 EnqueueChangeRecord(self, "new", name, old_value); |
4150 } else if (old_value->IsTheHole()) { | 4182 } else if (old_value->IsTheHole()) { |
4151 EnqueueChangeRecord(object, "reconfigured", name, old_value); | 4183 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
4152 } else { | 4184 } else { |
4153 LookupResult new_lookup(isolate); | 4185 LookupResult new_lookup(isolate); |
4154 object->LocalLookup(*name, &new_lookup, true); | 4186 self->LocalLookup(*name, &new_lookup, true); |
4155 bool value_changed = false; | 4187 bool value_changed = false; |
4156 if (new_lookup.IsDataProperty()) { | 4188 if (new_lookup.IsDataProperty()) { |
4157 Handle<Object> new_value = Object::GetProperty(object, name); | 4189 Handle<Object> new_value = Object::GetProperty(self, name); |
4158 value_changed = !old_value->SameValue(*new_value); | 4190 value_changed = !old_value->SameValue(*new_value); |
4159 } | 4191 } |
4160 if (new_lookup.GetAttributes() != old_attributes) { | 4192 if (new_lookup.GetAttributes() != old_attributes) { |
4161 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 4193 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
4162 EnqueueChangeRecord(object, "reconfigured", name, old_value); | 4194 EnqueueChangeRecord(self, "reconfigured", name, old_value); |
4163 } else if (value_changed) { | 4195 } else if (value_changed) { |
4164 EnqueueChangeRecord(object, "updated", name, old_value); | 4196 EnqueueChangeRecord(self, "updated", name, old_value); |
4165 } | 4197 } |
4166 } | 4198 } |
4167 } | 4199 } |
4168 | 4200 |
4169 return result; | 4201 return *hresult; |
4170 } | 4202 } |
4171 | 4203 |
4172 | 4204 |
4173 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 4205 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
4174 JSObject* receiver, | 4206 JSObject* receiver, |
4175 Name* name, | 4207 Name* name, |
4176 bool continue_search) { | 4208 bool continue_search) { |
4177 // Check local property, ignore interceptor. | 4209 // Check local property, ignore interceptor. |
4178 LookupResult result(GetIsolate()); | 4210 LookupResult result(GetIsolate()); |
4179 LocalLookupRealNamedProperty(name, &result); | 4211 LocalLookupRealNamedProperty(name, &result); |
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5113 if (object->IsJSGlobalProxy()) { | 5145 if (object->IsJSGlobalProxy()) { |
5114 Handle<Object> proto(object->GetPrototype(), isolate); | 5146 Handle<Object> proto(object->GetPrototype(), isolate); |
5115 if (proto->IsNull()) return factory->false_value(); | 5147 if (proto->IsNull()) return factory->false_value(); |
5116 ASSERT(proto->IsJSGlobalObject()); | 5148 ASSERT(proto->IsJSGlobalObject()); |
5117 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); | 5149 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); |
5118 } | 5150 } |
5119 | 5151 |
5120 Handle<Object> old_value; | 5152 Handle<Object> old_value; |
5121 bool should_enqueue_change_record = false; | 5153 bool should_enqueue_change_record = false; |
5122 if (FLAG_harmony_observation && object->map()->is_observed()) { | 5154 if (FLAG_harmony_observation && object->map()->is_observed()) { |
5123 should_enqueue_change_record = HasLocalElement(object, index); | 5155 should_enqueue_change_record = object->HasLocalElement(index); |
5124 if (should_enqueue_change_record) { | 5156 if (should_enqueue_change_record) { |
5125 old_value = object->GetLocalElementAccessorPair(index) != NULL | 5157 old_value = object->GetLocalElementAccessorPair(index) != NULL |
5126 ? Handle<Object>::cast(factory->the_hole_value()) | 5158 ? Handle<Object>::cast(factory->the_hole_value()) |
5127 : Object::GetElement(isolate, object, index); | 5159 : Object::GetElement(isolate, object, index); |
5128 } | 5160 } |
5129 } | 5161 } |
5130 | 5162 |
5131 // Skip interceptor if forcing deletion. | 5163 // Skip interceptor if forcing deletion. |
5132 Handle<Object> result; | 5164 Handle<Object> result; |
5133 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { | 5165 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { |
5134 result = DeleteElementWithInterceptor(object, index); | 5166 result = DeleteElementWithInterceptor(object, index); |
5135 } else { | 5167 } else { |
5136 result = AccessorDelete(object, index, mode); | 5168 result = AccessorDelete(object, index, mode); |
5137 } | 5169 } |
5138 | 5170 |
5139 if (should_enqueue_change_record && !HasLocalElement(object, index)) { | 5171 if (should_enqueue_change_record && !object->HasLocalElement(index)) { |
5140 Handle<String> name = factory->Uint32ToString(index); | 5172 Handle<String> name = factory->Uint32ToString(index); |
5141 EnqueueChangeRecord(object, "deleted", name, old_value); | 5173 EnqueueChangeRecord(object, "deleted", name, old_value); |
5142 } | 5174 } |
5143 | 5175 |
5144 return result; | 5176 return result; |
5145 } | 5177 } |
5146 | 5178 |
5147 | 5179 |
5148 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5180 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
5149 Handle<Name> name, | 5181 Handle<Name> name, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5204 } else { | 5236 } else { |
5205 result = DeletePropertyWithInterceptor(object, name); | 5237 result = DeletePropertyWithInterceptor(object, name); |
5206 } | 5238 } |
5207 } else { | 5239 } else { |
5208 // Normalize object if needed. | 5240 // Normalize object if needed. |
5209 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5241 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
5210 // Make sure the properties are normalized before removing the entry. | 5242 // Make sure the properties are normalized before removing the entry. |
5211 result = DeleteNormalizedProperty(object, name, mode); | 5243 result = DeleteNormalizedProperty(object, name, mode); |
5212 } | 5244 } |
5213 | 5245 |
5214 if (is_observed && !HasLocalProperty(object, name)) { | 5246 if (is_observed && !object->HasLocalProperty(*name)) { |
5215 EnqueueChangeRecord(object, "deleted", name, old_value); | 5247 EnqueueChangeRecord(object, "deleted", name, old_value); |
5216 } | 5248 } |
5217 | 5249 |
5218 return result; | 5250 return result; |
5219 } | 5251 } |
5220 | 5252 |
5221 | 5253 |
5222 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, | 5254 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
5223 uint32_t index, | 5255 uint32_t index, |
5224 DeleteMode mode) { | 5256 DeleteMode mode) { |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5596 MaybeObject* maybe_copy = map()->Copy(); | 5628 MaybeObject* maybe_copy = map()->Copy(); |
5597 if (!maybe_copy->To(&new_map)) return maybe_copy; | 5629 if (!maybe_copy->To(&new_map)) return maybe_copy; |
5598 new_map->set_is_observed(true); | 5630 new_map->set_is_observed(true); |
5599 } | 5631 } |
5600 set_map(new_map); | 5632 set_map(new_map); |
5601 | 5633 |
5602 return heap->undefined_value(); | 5634 return heap->undefined_value(); |
5603 } | 5635 } |
5604 | 5636 |
5605 | 5637 |
5606 // TODO(mstarzinger): Temporary wrapper until handlified. | 5638 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) { |
5607 static Handle<Object> NewStorageFor(Isolate* isolate, | 5639 StackLimitCheck check(isolate); |
5608 Handle<Object> object, | 5640 if (check.HasOverflowed()) return isolate->StackOverflow(); |
5609 Representation representation) { | |
5610 Heap* heap = isolate->heap(); | |
5611 CALL_HEAP_FUNCTION(isolate, | |
5612 object->AllocateNewStorageFor(heap, representation), | |
5613 Object); | |
5614 } | |
5615 | 5641 |
5616 | 5642 if (map()->is_deprecated()) { |
5617 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { | 5643 MaybeObject* maybe_failure = MigrateInstance(); |
5618 Isolate* isolate = object->GetIsolate(); | 5644 if (maybe_failure->IsFailure()) return maybe_failure; |
5619 CALL_HEAP_FUNCTION(isolate, | |
5620 isolate->heap()->CopyJSObject(*object), JSObject); | |
5621 } | |
5622 | |
5623 | |
5624 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { | |
5625 Isolate* isolate = object->GetIsolate(); | |
5626 StackLimitCheck check(isolate); | |
5627 if (check.HasOverflowed()) { | |
5628 isolate->StackOverflow(); | |
5629 return Handle<JSObject>::null(); | |
5630 } | 5645 } |
5631 | 5646 |
5632 if (object->map()->is_deprecated()) { | 5647 Heap* heap = isolate->heap(); |
5633 MigrateInstance(object); | 5648 Object* result; |
| 5649 { MaybeObject* maybe_result = heap->CopyJSObject(this); |
| 5650 if (!maybe_result->ToObject(&result)) return maybe_result; |
5634 } | 5651 } |
5635 | 5652 JSObject* copy = JSObject::cast(result); |
5636 Handle<JSObject> copy = Copy(object); | |
5637 | |
5638 HandleScope scope(isolate); | |
5639 | 5653 |
5640 // Deep copy local properties. | 5654 // Deep copy local properties. |
5641 if (copy->HasFastProperties()) { | 5655 if (copy->HasFastProperties()) { |
5642 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); | 5656 DescriptorArray* descriptors = copy->map()->instance_descriptors(); |
5643 int limit = copy->map()->NumberOfOwnDescriptors(); | 5657 int limit = copy->map()->NumberOfOwnDescriptors(); |
5644 for (int i = 0; i < limit; i++) { | 5658 for (int i = 0; i < limit; i++) { |
5645 PropertyDetails details = descriptors->GetDetails(i); | 5659 PropertyDetails details = descriptors->GetDetails(i); |
5646 if (details.type() != FIELD) continue; | 5660 if (details.type() != FIELD) continue; |
5647 int index = descriptors->GetFieldIndex(i); | 5661 int index = descriptors->GetFieldIndex(i); |
5648 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 5662 Object* value = RawFastPropertyAt(index); |
5649 if (value->IsJSObject()) { | 5663 if (value->IsJSObject()) { |
5650 value = DeepCopy(Handle<JSObject>::cast(value)); | 5664 JSObject* js_object = JSObject::cast(value); |
5651 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>()); | 5665 MaybeObject* maybe_copy = js_object->DeepCopy(isolate); |
| 5666 if (!maybe_copy->To(&value)) return maybe_copy; |
5652 } else { | 5667 } else { |
5653 Representation representation = details.representation(); | 5668 Representation representation = details.representation(); |
5654 value = NewStorageFor(isolate, value, representation); | 5669 MaybeObject* maybe_storage = |
| 5670 value->AllocateNewStorageFor(heap, representation); |
| 5671 if (!maybe_storage->To(&value)) return maybe_storage; |
5655 } | 5672 } |
5656 copy->FastPropertyAtPut(index, *value); | 5673 copy->FastPropertyAtPut(index, value); |
5657 } | 5674 } |
5658 } else { | 5675 } else { |
5659 Handle<FixedArray> names = | 5676 { MaybeObject* maybe_result = |
5660 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); | 5677 heap->AllocateFixedArray(copy->NumberOfLocalProperties()); |
5661 copy->GetLocalPropertyNames(*names, 0); | 5678 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5679 } |
| 5680 FixedArray* names = FixedArray::cast(result); |
| 5681 copy->GetLocalPropertyNames(names, 0); |
5662 for (int i = 0; i < names->length(); i++) { | 5682 for (int i = 0; i < names->length(); i++) { |
5663 ASSERT(names->get(i)->IsString()); | 5683 ASSERT(names->get(i)->IsString()); |
5664 Handle<String> key_string(String::cast(names->get(i))); | 5684 String* key_string = String::cast(names->get(i)); |
5665 PropertyAttributes attributes = | 5685 PropertyAttributes attributes = |
5666 copy->GetLocalPropertyAttribute(*key_string); | 5686 copy->GetLocalPropertyAttribute(key_string); |
5667 // Only deep copy fields from the object literal expression. | 5687 // Only deep copy fields from the object literal expression. |
5668 // In particular, don't try to copy the length attribute of | 5688 // In particular, don't try to copy the length attribute of |
5669 // an array. | 5689 // an array. |
5670 if (attributes != NONE) continue; | 5690 if (attributes != NONE) continue; |
5671 Handle<Object> value( | 5691 Object* value = |
5672 copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(), | 5692 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); |
5673 isolate); | |
5674 if (value->IsJSObject()) { | 5693 if (value->IsJSObject()) { |
5675 Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value)); | 5694 JSObject* js_object = JSObject::cast(value); |
5676 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5695 { MaybeObject* maybe_result = js_object->DeepCopy(isolate); |
5677 // Creating object copy for literals. No strict mode needed. | 5696 if (!maybe_result->ToObject(&result)) return maybe_result; |
5678 CHECK_NOT_EMPTY_HANDLE(isolate, SetProperty( | 5697 } |
5679 copy, key_string, result, NONE, kNonStrictMode)); | 5698 { MaybeObject* maybe_result = |
| 5699 // Creating object copy for literals. No strict mode needed. |
| 5700 copy->SetProperty(key_string, result, NONE, kNonStrictMode); |
| 5701 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5702 } |
5680 } | 5703 } |
5681 } | 5704 } |
5682 } | 5705 } |
5683 | 5706 |
5684 // Deep copy local elements. | 5707 // Deep copy local elements. |
5685 // Pixel elements cannot be created using an object literal. | 5708 // Pixel elements cannot be created using an object literal. |
5686 ASSERT(!copy->HasExternalArrayElements()); | 5709 ASSERT(!copy->HasExternalArrayElements()); |
5687 switch (copy->GetElementsKind()) { | 5710 switch (copy->GetElementsKind()) { |
5688 case FAST_SMI_ELEMENTS: | 5711 case FAST_SMI_ELEMENTS: |
5689 case FAST_ELEMENTS: | 5712 case FAST_ELEMENTS: |
5690 case FAST_HOLEY_SMI_ELEMENTS: | 5713 case FAST_HOLEY_SMI_ELEMENTS: |
5691 case FAST_HOLEY_ELEMENTS: { | 5714 case FAST_HOLEY_ELEMENTS: { |
5692 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); | 5715 FixedArray* elements = FixedArray::cast(copy->elements()); |
5693 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { | 5716 if (elements->map() == heap->fixed_cow_array_map()) { |
5694 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 5717 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
5695 #ifdef DEBUG | 5718 #ifdef DEBUG |
5696 for (int i = 0; i < elements->length(); i++) { | 5719 for (int i = 0; i < elements->length(); i++) { |
5697 ASSERT(!elements->get(i)->IsJSObject()); | 5720 ASSERT(!elements->get(i)->IsJSObject()); |
5698 } | 5721 } |
5699 #endif | 5722 #endif |
5700 } else { | 5723 } else { |
5701 for (int i = 0; i < elements->length(); i++) { | 5724 for (int i = 0; i < elements->length(); i++) { |
5702 Handle<Object> value(elements->get(i), isolate); | 5725 Object* value = elements->get(i); |
5703 ASSERT(value->IsSmi() || | 5726 ASSERT(value->IsSmi() || |
5704 value->IsTheHole() || | 5727 value->IsTheHole() || |
5705 (IsFastObjectElementsKind(copy->GetElementsKind()))); | 5728 (IsFastObjectElementsKind(copy->GetElementsKind()))); |
5706 if (value->IsJSObject()) { | 5729 if (value->IsJSObject()) { |
5707 Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value)); | 5730 JSObject* js_object = JSObject::cast(value); |
5708 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5731 { MaybeObject* maybe_result = js_object->DeepCopy(isolate); |
5709 elements->set(i, *result); | 5732 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5733 } |
| 5734 elements->set(i, result); |
5710 } | 5735 } |
5711 } | 5736 } |
5712 } | 5737 } |
5713 break; | 5738 break; |
5714 } | 5739 } |
5715 case DICTIONARY_ELEMENTS: { | 5740 case DICTIONARY_ELEMENTS: { |
5716 Handle<SeededNumberDictionary> element_dictionary( | 5741 SeededNumberDictionary* element_dictionary = copy->element_dictionary(); |
5717 copy->element_dictionary()); | |
5718 int capacity = element_dictionary->Capacity(); | 5742 int capacity = element_dictionary->Capacity(); |
5719 for (int i = 0; i < capacity; i++) { | 5743 for (int i = 0; i < capacity; i++) { |
5720 Object* k = element_dictionary->KeyAt(i); | 5744 Object* k = element_dictionary->KeyAt(i); |
5721 if (element_dictionary->IsKey(k)) { | 5745 if (element_dictionary->IsKey(k)) { |
5722 Handle<Object> value(element_dictionary->ValueAt(i), isolate); | 5746 Object* value = element_dictionary->ValueAt(i); |
5723 if (value->IsJSObject()) { | 5747 if (value->IsJSObject()) { |
5724 Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value)); | 5748 JSObject* js_object = JSObject::cast(value); |
5725 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5749 { MaybeObject* maybe_result = js_object->DeepCopy(isolate); |
5726 element_dictionary->ValueAtPut(i, *result); | 5750 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5751 } |
| 5752 element_dictionary->ValueAtPut(i, result); |
5727 } | 5753 } |
5728 } | 5754 } |
5729 } | 5755 } |
5730 break; | 5756 break; |
5731 } | 5757 } |
5732 case NON_STRICT_ARGUMENTS_ELEMENTS: | 5758 case NON_STRICT_ARGUMENTS_ELEMENTS: |
5733 UNIMPLEMENTED(); | 5759 UNIMPLEMENTED(); |
5734 break; | 5760 break; |
5735 case EXTERNAL_PIXEL_ELEMENTS: | 5761 case EXTERNAL_PIXEL_ELEMENTS: |
5736 case EXTERNAL_BYTE_ELEMENTS: | 5762 case EXTERNAL_BYTE_ELEMENTS: |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6157 if (!object->CanSetCallback(*name)) return; | 6183 if (!object->CanSetCallback(*name)) return; |
6158 | 6184 |
6159 uint32_t index = 0; | 6185 uint32_t index = 0; |
6160 bool is_element = name->AsArrayIndex(&index); | 6186 bool is_element = name->AsArrayIndex(&index); |
6161 | 6187 |
6162 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6188 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
6163 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 6189 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
6164 bool preexists = false; | 6190 bool preexists = false; |
6165 if (is_observed) { | 6191 if (is_observed) { |
6166 if (is_element) { | 6192 if (is_element) { |
6167 preexists = HasLocalElement(object, index); | 6193 preexists = object->HasLocalElement(index); |
6168 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { | 6194 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
6169 old_value = Object::GetElement(isolate, object, index); | 6195 old_value = Object::GetElement(isolate, object, index); |
6170 } | 6196 } |
6171 } else { | 6197 } else { |
6172 LookupResult lookup(isolate); | 6198 LookupResult lookup(isolate); |
6173 object->LocalLookup(*name, &lookup, true); | 6199 object->LocalLookup(*name, &lookup, true); |
6174 preexists = lookup.IsProperty(); | 6200 preexists = lookup.IsProperty(); |
6175 if (preexists && lookup.IsDataProperty()) { | 6201 if (preexists && lookup.IsDataProperty()) { |
6176 old_value = Object::GetProperty(object, name); | 6202 old_value = Object::GetProperty(object, name); |
6177 } | 6203 } |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6653 set_transitions(transitions); | 6679 set_transitions(transitions); |
6654 result->SetBackPointer(this); | 6680 result->SetBackPointer(this); |
6655 } else { | 6681 } else { |
6656 descriptors->InitializeRepresentations(Representation::Tagged()); | 6682 descriptors->InitializeRepresentations(Representation::Tagged()); |
6657 } | 6683 } |
6658 | 6684 |
6659 return result; | 6685 return result; |
6660 } | 6686 } |
6661 | 6687 |
6662 | 6688 |
6663 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | |
6664 int new_descriptor, | |
6665 Handle<DescriptorArray> descriptors) { | |
6666 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
6667 map->CopyInstallDescriptors(new_descriptor, *descriptors), | |
6668 Map); | |
6669 } | |
6670 | |
6671 | |
6672 // Since this method is used to rewrite an existing transition tree, it can | 6689 // Since this method is used to rewrite an existing transition tree, it can |
6673 // always insert transitions without checking. | 6690 // always insert transitions without checking. |
6674 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6691 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, |
6675 DescriptorArray* descriptors) { | 6692 DescriptorArray* descriptors) { |
6676 ASSERT(descriptors->IsSortedNoDuplicates()); | 6693 ASSERT(descriptors->IsSortedNoDuplicates()); |
6677 | 6694 |
6678 Map* result; | 6695 Map* result; |
6679 MaybeObject* maybe_result = CopyDropDescriptors(); | 6696 MaybeObject* maybe_result = CopyDropDescriptors(); |
6680 if (!maybe_result->To(&result)) return maybe_result; | 6697 if (!maybe_result->To(&result)) return maybe_result; |
6681 | 6698 |
(...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7774 DescriptorArray* src, | 7791 DescriptorArray* src, |
7775 int src_index, | 7792 int src_index, |
7776 const WhitenessWitness& witness) { | 7793 const WhitenessWitness& witness) { |
7777 Object* value = src->GetValue(src_index); | 7794 Object* value = src->GetValue(src_index); |
7778 PropertyDetails details = src->GetDetails(src_index); | 7795 PropertyDetails details = src->GetDetails(src_index); |
7779 Descriptor desc(src->GetKey(src_index), value, details); | 7796 Descriptor desc(src->GetKey(src_index), value, details); |
7780 Set(dst_index, &desc, witness); | 7797 Set(dst_index, &desc, witness); |
7781 } | 7798 } |
7782 | 7799 |
7783 | 7800 |
7784 Handle<DescriptorArray> DescriptorArray::Merge(Handle<DescriptorArray> desc, | |
7785 int verbatim, | |
7786 int valid, | |
7787 int new_size, | |
7788 int modify_index, | |
7789 StoreMode store_mode, | |
7790 Handle<DescriptorArray> other) { | |
7791 CALL_HEAP_FUNCTION(desc->GetIsolate(), | |
7792 desc->Merge(verbatim, valid, new_size, modify_index, | |
7793 store_mode, *other), | |
7794 DescriptorArray); | |
7795 } | |
7796 | |
7797 | |
7798 // Generalize the |other| descriptor array by merging it into the (at least | 7801 // Generalize the |other| descriptor array by merging it into the (at least |
7799 // partly) updated |this| descriptor array. | 7802 // partly) updated |this| descriptor array. |
7800 // The method merges two descriptor array in three parts. Both descriptor arrays | 7803 // The method merges two descriptor array in three parts. Both descriptor arrays |
7801 // are identical up to |verbatim|. They also overlap in keys up to |valid|. | 7804 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
7802 // Between |verbatim| and |valid|, the resulting descriptor type as well as the | 7805 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
7803 // representation are generalized from both |this| and |other|. Beyond |valid|, | 7806 // representation are generalized from both |this| and |other|. Beyond |valid|, |
7804 // the descriptors are copied verbatim from |other| up to |new_size|. | 7807 // the descriptors are copied verbatim from |other| up to |new_size|. |
7805 // In case of incompatible types, the type and representation of |other| is | 7808 // In case of incompatible types, the type and representation of |other| is |
7806 // used. | 7809 // used. |
7807 MaybeObject* DescriptorArray::Merge(int verbatim, | 7810 MaybeObject* DescriptorArray::Merge(int verbatim, |
(...skipping 2618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10426 } | 10429 } |
10427 | 10430 |
10428 | 10431 |
10429 bool Code::allowed_in_shared_map_code_cache() { | 10432 bool Code::allowed_in_shared_map_code_cache() { |
10430 return is_keyed_load_stub() || is_keyed_store_stub() || | 10433 return is_keyed_load_stub() || is_keyed_store_stub() || |
10431 (is_compare_ic_stub() && | 10434 (is_compare_ic_stub() && |
10432 ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT); | 10435 ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT); |
10433 } | 10436 } |
10434 | 10437 |
10435 | 10438 |
10436 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { | 10439 void Code::MakeCodeAgeSequenceYoung(byte* sequence) { |
10437 PatchPlatformCodeAge(isolate, sequence, kNoAge, NO_MARKING_PARITY); | 10440 PatchPlatformCodeAge(sequence, kNoAge, NO_MARKING_PARITY); |
10438 } | 10441 } |
10439 | 10442 |
10440 | 10443 |
10441 void Code::MakeOlder(MarkingParity current_parity) { | 10444 void Code::MakeOlder(MarkingParity current_parity) { |
10442 byte* sequence = FindCodeAgeSequence(); | 10445 byte* sequence = FindCodeAgeSequence(); |
10443 if (sequence != NULL) { | 10446 if (sequence != NULL) { |
10444 Age age; | 10447 Age age; |
10445 MarkingParity code_parity; | 10448 MarkingParity code_parity; |
10446 GetCodeAgeAndParity(sequence, &age, &code_parity); | 10449 GetCodeAgeAndParity(sequence, &age, &code_parity); |
10447 if (age != kLastCodeAge && code_parity != current_parity) { | 10450 if (age != kLastCodeAge && code_parity != current_parity) { |
10448 PatchPlatformCodeAge(GetIsolate(), | 10451 PatchPlatformCodeAge(sequence, static_cast<Age>(age + 1), |
10449 sequence, | |
10450 static_cast<Age>(age + 1), | |
10451 current_parity); | 10452 current_parity); |
10452 } | 10453 } |
10453 } | 10454 } |
10454 } | 10455 } |
10455 | 10456 |
10456 | 10457 |
10457 bool Code::IsOld() { | 10458 bool Code::IsOld() { |
10458 byte* sequence = FindCodeAgeSequence(); | 10459 byte* sequence = FindCodeAgeSequence(); |
10459 if (sequence == NULL) return false; | 10460 if (sequence == NULL) return false; |
10460 Age age; | 10461 Age age; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10503 *age = k##AGE##CodeAge; \ | 10504 *age = k##AGE##CodeAge; \ |
10504 *parity = ODD_MARKING_PARITY; \ | 10505 *parity = ODD_MARKING_PARITY; \ |
10505 return; \ | 10506 return; \ |
10506 } | 10507 } |
10507 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10508 CODE_AGE_LIST(HANDLE_CODE_AGE) |
10508 #undef HANDLE_CODE_AGE | 10509 #undef HANDLE_CODE_AGE |
10509 UNREACHABLE(); | 10510 UNREACHABLE(); |
10510 } | 10511 } |
10511 | 10512 |
10512 | 10513 |
10513 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { | 10514 Code* Code::GetCodeAgeStub(Age age, MarkingParity parity) { |
| 10515 Isolate* isolate = Isolate::Current(); |
10514 Builtins* builtins = isolate->builtins(); | 10516 Builtins* builtins = isolate->builtins(); |
10515 switch (age) { | 10517 switch (age) { |
10516 #define HANDLE_CODE_AGE(AGE) \ | 10518 #define HANDLE_CODE_AGE(AGE) \ |
10517 case k##AGE##CodeAge: { \ | 10519 case k##AGE##CodeAge: { \ |
10518 Code* stub = parity == EVEN_MARKING_PARITY \ | 10520 Code* stub = parity == EVEN_MARKING_PARITY \ |
10519 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ | 10521 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ |
10520 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 10522 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
10521 return stub; \ | 10523 return stub; \ |
10522 } | 10524 } |
10523 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10525 CODE_AGE_LIST(HANDLE_CODE_AGE) |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10774 } | 10776 } |
10775 | 10777 |
10776 | 10778 |
10777 const char* Code::StubType2String(StubType type) { | 10779 const char* Code::StubType2String(StubType type) { |
10778 switch (type) { | 10780 switch (type) { |
10779 case NORMAL: return "NORMAL"; | 10781 case NORMAL: return "NORMAL"; |
10780 case FIELD: return "FIELD"; | 10782 case FIELD: return "FIELD"; |
10781 case CONSTANT: return "CONSTANT"; | 10783 case CONSTANT: return "CONSTANT"; |
10782 case CALLBACKS: return "CALLBACKS"; | 10784 case CALLBACKS: return "CALLBACKS"; |
10783 case INTERCEPTOR: return "INTERCEPTOR"; | 10785 case INTERCEPTOR: return "INTERCEPTOR"; |
10784 case TRANSITION: return "TRANSITION"; | 10786 case MAP_TRANSITION: return "MAP_TRANSITION"; |
10785 case NONEXISTENT: return "NONEXISTENT"; | 10787 case NONEXISTENT: return "NONEXISTENT"; |
10786 } | 10788 } |
10787 UNREACHABLE(); // keep the compiler happy | 10789 UNREACHABLE(); // keep the compiler happy |
10788 return NULL; | 10790 return NULL; |
10789 } | 10791 } |
10790 | 10792 |
10791 | 10793 |
10792 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { | 10794 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
10793 PrintF(out, "extra_ic_state = "); | 10795 PrintF(out, "extra_ic_state = "); |
10794 const char* name = NULL; | 10796 const char* name = NULL; |
(...skipping 3715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14510 } | 14512 } |
14511 | 14513 |
14512 | 14514 |
14513 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 14515 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
14514 ASSERT(!HasFastProperties()); | 14516 ASSERT(!HasFastProperties()); |
14515 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 14517 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
14516 return PropertyCell::cast(value); | 14518 return PropertyCell::cast(value); |
14517 } | 14519 } |
14518 | 14520 |
14519 | 14521 |
| 14522 // TODO(mstarzinger): Temporary wrapper until handlified. |
| 14523 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, |
| 14524 Handle<Name> name, |
| 14525 Handle<Object> value, |
| 14526 PropertyDetails details) { |
| 14527 CALL_HEAP_FUNCTION(dict->GetIsolate(), |
| 14528 dict->Add(*name, *value, details), |
| 14529 NameDictionary); |
| 14530 } |
| 14531 |
| 14532 |
14520 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 14533 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( |
14521 Handle<GlobalObject> global, | 14534 Handle<GlobalObject> global, |
14522 Handle<Name> name) { | 14535 Handle<Name> name) { |
14523 ASSERT(!global->HasFastProperties()); | 14536 ASSERT(!global->HasFastProperties()); |
14524 int entry = global->property_dictionary()->FindEntry(*name); | 14537 int entry = global->property_dictionary()->FindEntry(*name); |
14525 if (entry == NameDictionary::kNotFound) { | 14538 if (entry == NameDictionary::kNotFound) { |
14526 Isolate* isolate = global->GetIsolate(); | 14539 Isolate* isolate = global->GetIsolate(); |
14527 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( | 14540 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( |
14528 isolate->factory()->the_hole_value()); | 14541 isolate->factory()->the_hole_value()); |
14529 PropertyDetails details(NONE, NORMAL, 0); | 14542 PropertyDetails details(NONE, NORMAL, 0); |
(...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16088 isolate, DependentCode::kPropertyCellChangedGroup); | 16101 isolate, DependentCode::kPropertyCellChangedGroup); |
16089 | 16102 |
16090 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { | 16103 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
16091 return *new_type; | 16104 return *new_type; |
16092 } | 16105 } |
16093 | 16106 |
16094 return Type::Any(); | 16107 return Type::Any(); |
16095 } | 16108 } |
16096 | 16109 |
16097 | 16110 |
16098 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, | |
16099 Handle<Object> value, | |
16100 WriteBarrierMode mode) { | |
16101 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), | |
16102 cell->SetValueInferType(*value, mode)); | |
16103 } | |
16104 | |
16105 | |
16106 MaybeObject* PropertyCell::SetValueInferType(Object* value, | 16111 MaybeObject* PropertyCell::SetValueInferType(Object* value, |
16107 WriteBarrierMode ignored) { | 16112 WriteBarrierMode ignored) { |
16108 set_value(value, ignored); | 16113 set_value(value, ignored); |
16109 if (!Type::Any()->Is(type())) { | 16114 if (!Type::Any()->Is(type())) { |
16110 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); | 16115 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); |
16111 MaybeObject* maybe_type = trampoline.CallWithReturnValue( | 16116 MaybeObject* maybe_type = trampoline.CallWithReturnValue( |
16112 &PropertyCell::UpdateType, | 16117 &PropertyCell::UpdateType, |
16113 Handle<PropertyCell>(this), | 16118 Handle<PropertyCell>(this), |
16114 Handle<Object>(value, GetIsolate())); | 16119 Handle<Object>(value, GetIsolate())); |
16115 Type* new_type = NULL; | 16120 Type* new_type = NULL; |
(...skipping 28 matching lines...) Expand all Loading... |
16144 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16149 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16145 static const char* error_messages_[] = { | 16150 static const char* error_messages_[] = { |
16146 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16151 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16147 }; | 16152 }; |
16148 #undef ERROR_MESSAGES_TEXTS | 16153 #undef ERROR_MESSAGES_TEXTS |
16149 return error_messages_[reason]; | 16154 return error_messages_[reason]; |
16150 } | 16155 } |
16151 | 16156 |
16152 | 16157 |
16153 } } // namespace v8::internal | 16158 } } // namespace v8::internal |
OLD | NEW |