Chromium Code Reviews| 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 1882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1893 set_properties(values); | 1893 set_properties(values); |
| 1894 } | 1894 } |
| 1895 | 1895 |
| 1896 set_map(new_map); | 1896 set_map(new_map); |
| 1897 | 1897 |
| 1898 FastPropertyAtPut(field_index, storage); | 1898 FastPropertyAtPut(field_index, storage); |
| 1899 return value; | 1899 return value; |
| 1900 } | 1900 } |
| 1901 | 1901 |
| 1902 | 1902 |
| 1903 void JSObject::AddFastProperty(Handle<JSObject> object, | |
| 1904 Handle<Name> name, | |
| 1905 Handle<Object> value, | |
| 1906 PropertyAttributes attributes, | |
| 1907 StoreFromKeyed store_mode, | |
| 1908 ValueType value_type, | |
| 1909 TransitionFlag flag) { | |
| 1910 CALL_HEAP_FUNCTION_VOID( | |
| 1911 object->GetIsolate(), | |
| 1912 object->AddFastProperty( | |
| 1913 *name, *value, attributes, store_mode, value_type, flag)); | |
| 1914 } | |
| 1915 | |
| 1916 | |
| 1903 MaybeObject* JSObject::AddFastProperty(Name* name, | 1917 MaybeObject* JSObject::AddFastProperty(Name* name, |
| 1904 Object* value, | 1918 Object* value, |
| 1905 PropertyAttributes attributes, | 1919 PropertyAttributes attributes, |
| 1906 StoreFromKeyed store_mode, | 1920 StoreFromKeyed store_mode, |
| 1907 ValueType value_type, | 1921 ValueType value_type, |
| 1908 TransitionFlag flag) { | 1922 TransitionFlag flag) { |
| 1909 ASSERT(!IsJSGlobalProxy()); | 1923 ASSERT(!IsJSGlobalProxy()); |
| 1910 ASSERT(DescriptorArray::kNotFound == | 1924 ASSERT(DescriptorArray::kNotFound == |
| 1911 map()->instance_descriptors()->Search( | 1925 map()->instance_descriptors()->Search( |
| 1912 name, map()->NumberOfOwnDescriptors())); | 1926 name, map()->NumberOfOwnDescriptors())); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1938 int unused_property_fields = map()->unused_property_fields() - 1; | 1952 int unused_property_fields = map()->unused_property_fields() - 1; |
| 1939 if (unused_property_fields < 0) { | 1953 if (unused_property_fields < 0) { |
| 1940 unused_property_fields += kFieldsAdded; | 1954 unused_property_fields += kFieldsAdded; |
| 1941 } | 1955 } |
| 1942 new_map->set_unused_property_fields(unused_property_fields); | 1956 new_map->set_unused_property_fields(unused_property_fields); |
| 1943 | 1957 |
| 1944 return AddFastPropertyUsingMap(new_map, name, value, index, representation); | 1958 return AddFastPropertyUsingMap(new_map, name, value, index, representation); |
| 1945 } | 1959 } |
| 1946 | 1960 |
| 1947 | 1961 |
| 1962 void JSObject::AddConstantProperty(Handle<JSObject> object, | |
| 1963 Handle<Name> name, | |
| 1964 Handle<Object> constant, | |
| 1965 PropertyAttributes attributes, | |
| 1966 TransitionFlag flag) { | |
| 1967 CALL_HEAP_FUNCTION_VOID( | |
| 1968 object->GetIsolate(), | |
| 1969 object->AddConstantProperty(*name, *constant, attributes, flag)); | |
| 1970 } | |
| 1971 | |
| 1972 | |
| 1948 MaybeObject* JSObject::AddConstantProperty( | 1973 MaybeObject* JSObject::AddConstantProperty( |
| 1949 Name* name, | 1974 Name* name, |
| 1950 Object* constant, | 1975 Object* constant, |
| 1951 PropertyAttributes attributes, | 1976 PropertyAttributes attributes, |
| 1952 TransitionFlag initial_flag) { | 1977 TransitionFlag initial_flag) { |
| 1953 // Allocate new instance descriptors with (name, constant) added | 1978 // Allocate new instance descriptors with (name, constant) added |
| 1954 ConstantDescriptor d(name, constant, attributes); | 1979 ConstantDescriptor d(name, constant, attributes); |
| 1955 | 1980 |
| 1956 TransitionFlag flag = | 1981 TransitionFlag flag = |
| 1957 // Do not add transitions to global objects. | 1982 // Do not add transitions to global objects. |
| 1958 (IsGlobalObject() || | 1983 (IsGlobalObject() || |
| 1959 // Don't add transitions to special properties with non-trivial | 1984 // Don't add transitions to special properties with non-trivial |
| 1960 // attributes. | 1985 // attributes. |
| 1961 attributes != NONE) | 1986 attributes != NONE) |
| 1962 ? OMIT_TRANSITION | 1987 ? OMIT_TRANSITION |
| 1963 : initial_flag; | 1988 : initial_flag; |
| 1964 | 1989 |
| 1965 Map* new_map; | 1990 Map* new_map; |
| 1966 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); | 1991 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); |
| 1967 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 1992 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 1968 | 1993 |
| 1969 set_map(new_map); | 1994 set_map(new_map); |
| 1970 return constant; | 1995 return constant; |
| 1971 } | 1996 } |
| 1972 | 1997 |
| 1973 | 1998 |
| 1974 // Add property in slow mode | 1999 void JSObject::AddSlowProperty(Handle<JSObject> object, |
| 2000 Handle<Name> name, | |
| 2001 Handle<Object> value, | |
| 2002 PropertyAttributes attributes) { | |
| 2003 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | |
| 2004 object->AddSlowProperty(*name, *value, attributes)); | |
| 2005 } | |
| 2006 | |
| 2007 | |
| 1975 MaybeObject* JSObject::AddSlowProperty(Name* name, | 2008 MaybeObject* JSObject::AddSlowProperty(Name* name, |
| 1976 Object* value, | 2009 Object* value, |
| 1977 PropertyAttributes attributes) { | 2010 PropertyAttributes attributes) { |
| 1978 ASSERT(!HasFastProperties()); | 2011 ASSERT(!HasFastProperties()); |
| 1979 NameDictionary* dict = property_dictionary(); | 2012 NameDictionary* dict = property_dictionary(); |
| 1980 Object* store_value = value; | 2013 Object* store_value = value; |
| 1981 if (IsGlobalObject()) { | 2014 if (IsGlobalObject()) { |
| 1982 // In case name is an orphaned property reuse the cell. | 2015 // In case name is an orphaned property reuse the cell. |
| 1983 int entry = dict->FindEntry(name); | 2016 int entry = dict->FindEntry(name); |
| 1984 if (entry != NameDictionary::kNotFound) { | 2017 if (entry != NameDictionary::kNotFound) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2006 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 2039 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
| 2007 Object* result; | 2040 Object* result; |
| 2008 { MaybeObject* maybe_result = dict->Add(name, store_value, details); | 2041 { MaybeObject* maybe_result = dict->Add(name, store_value, details); |
| 2009 if (!maybe_result->ToObject(&result)) return maybe_result; | 2042 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2010 } | 2043 } |
| 2011 if (dict != result) set_properties(NameDictionary::cast(result)); | 2044 if (dict != result) set_properties(NameDictionary::cast(result)); |
| 2012 return value; | 2045 return value; |
| 2013 } | 2046 } |
| 2014 | 2047 |
| 2015 | 2048 |
| 2016 MaybeObject* JSObject::AddProperty(Name* name, | 2049 Handle<Object> JSObject::AddProperty(Handle<JSObject> object, |
| 2017 Object* value, | 2050 Handle<Name> name, |
| 2018 PropertyAttributes attributes, | 2051 Handle<Object> value, |
| 2019 StrictModeFlag strict_mode, | 2052 PropertyAttributes attributes, |
| 2020 JSReceiver::StoreFromKeyed store_mode, | 2053 StrictModeFlag strict_mode, |
| 2021 ExtensibilityCheck extensibility_check, | 2054 JSReceiver::StoreFromKeyed store_mode, |
| 2022 ValueType value_type, | 2055 ExtensibilityCheck extensibility_check, |
| 2023 StoreMode mode, | 2056 ValueType value_type, |
| 2024 TransitionFlag transition_flag) { | 2057 StoreMode mode, |
| 2025 ASSERT(!IsJSGlobalProxy()); | 2058 TransitionFlag transition_flag) { |
| 2026 Map* map_of_this = map(); | 2059 ASSERT(!object->IsJSGlobalProxy()); |
| 2027 Heap* heap = GetHeap(); | 2060 Isolate* isolate = object->GetIsolate(); |
| 2028 Isolate* isolate = heap->isolate(); | |
| 2029 MaybeObject* result; | |
| 2030 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2061 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
| 2031 !map_of_this->is_extensible()) { | 2062 !object->map()->is_extensible()) { |
| 2032 if (strict_mode == kNonStrictMode) { | 2063 if (strict_mode == kNonStrictMode) { |
| 2033 return value; | 2064 return value; |
| 2034 } else { | 2065 } else { |
| 2035 Handle<Object> args[1] = {Handle<Name>(name)}; | 2066 Handle<Object> args[1] = { name }; |
| 2036 return isolate->Throw( | 2067 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2037 *isolate->factory()->NewTypeError("object_not_extensible", | 2068 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
| 2038 HandleVector(args, 1))); | 2069 isolate->Throw(*error); |
| 2070 return Handle<Object>(); | |
| 2039 } | 2071 } |
| 2040 } | 2072 } |
| 2041 | 2073 |
| 2042 if (HasFastProperties()) { | 2074 if (object->HasFastProperties()) { |
| 2043 // Ensure the descriptor array does not get too big. | 2075 // Ensure the descriptor array does not get too big. |
| 2044 if (map_of_this->NumberOfOwnDescriptors() < | 2076 if (object->map()->NumberOfOwnDescriptors() < |
| 2045 DescriptorArray::kMaxNumberOfDescriptors) { | 2077 DescriptorArray::kMaxNumberOfDescriptors) { |
| 2046 // TODO(verwaest): Support other constants. | 2078 // TODO(verwaest): Support other constants. |
| 2047 // if (mode == ALLOW_AS_CONSTANT && | 2079 // if (mode == ALLOW_AS_CONSTANT && |
| 2048 // !value->IsTheHole() && | 2080 // !value->IsTheHole() && |
| 2049 // !value->IsConsString()) { | 2081 // !value->IsConsString()) { |
| 2050 if (value->IsJSFunction()) { | 2082 if (value->IsJSFunction()) { |
| 2051 result = AddConstantProperty(name, value, attributes, transition_flag); | 2083 AddConstantProperty(object, name, value, attributes, transition_flag); |
| 2052 } else { | 2084 } else { |
| 2053 result = AddFastProperty( | 2085 AddFastProperty(object, name, value, attributes, store_mode, |
| 2054 name, value, attributes, store_mode, value_type, transition_flag); | 2086 value_type, transition_flag); |
| 2055 } | 2087 } |
| 2056 } else { | 2088 } else { |
| 2057 // Normalize the object to prevent very large instance descriptors. | 2089 // Normalize the object to prevent very large instance descriptors. |
| 2058 // This eliminates unwanted N^2 allocation and lookup behavior. | 2090 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2059 Object* obj; | 2091 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 2060 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2092 AddSlowProperty(object, name, value, attributes); |
| 2061 if (!maybe->To(&obj)) return maybe; | |
| 2062 result = AddSlowProperty(name, value, attributes); | |
| 2063 } | 2093 } |
| 2064 } else { | 2094 } else { |
| 2065 result = AddSlowProperty(name, value, attributes); | 2095 AddSlowProperty(object, name, value, attributes); |
| 2066 } | 2096 } |
| 2067 | 2097 |
| 2068 Handle<Object> hresult; | 2098 if (FLAG_harmony_observation && object->map()->is_observed()) { |
| 2069 if (!result->ToHandle(&hresult, isolate)) return result; | 2099 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 2070 | 2100 EnqueueChangeRecord(object, "new", name, old_value); |
| 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)); | |
| 2076 } | 2101 } |
| 2077 | 2102 |
| 2078 return *hresult; | 2103 return value; |
| 2079 } | 2104 } |
| 2080 | 2105 |
| 2081 | 2106 |
| 2082 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2107 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| 2083 const char* type_str, | 2108 const char* type_str, |
| 2084 Handle<Name> name, | 2109 Handle<Name> name, |
| 2085 Handle<Object> old_value) { | 2110 Handle<Object> old_value) { |
| 2086 Isolate* isolate = object->GetIsolate(); | 2111 Isolate* isolate = object->GetIsolate(); |
| 2087 HandleScope scope(isolate); | 2112 HandleScope scope(isolate); |
| 2088 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); | 2113 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2108 isolate->observers_deliver_changes(), | 2133 isolate->observers_deliver_changes(), |
| 2109 isolate->factory()->undefined_value(), | 2134 isolate->factory()->undefined_value(), |
| 2110 0, | 2135 0, |
| 2111 NULL, | 2136 NULL, |
| 2112 &threw); | 2137 &threw); |
| 2113 ASSERT(!threw); | 2138 ASSERT(!threw); |
| 2114 isolate->set_observer_delivery_pending(false); | 2139 isolate->set_observer_delivery_pending(false); |
| 2115 } | 2140 } |
| 2116 | 2141 |
| 2117 | 2142 |
| 2118 MaybeObject* JSObject::SetPropertyPostInterceptor( | 2143 Handle<Object> JSObject::SetPropertyPostInterceptor( |
| 2119 Name* name, | 2144 Handle<JSObject> object, |
| 2120 Object* value, | 2145 Handle<Name> name, |
| 2146 Handle<Object> value, | |
| 2121 PropertyAttributes attributes, | 2147 PropertyAttributes attributes, |
| 2122 StrictModeFlag strict_mode, | 2148 StrictModeFlag strict_mode) { |
| 2123 StoreMode mode) { | |
| 2124 // Check local property, ignore interceptor. | 2149 // Check local property, ignore interceptor. |
| 2125 LookupResult result(GetIsolate()); | 2150 LookupResult result(object->GetIsolate()); |
| 2126 LocalLookupRealNamedProperty(name, &result); | 2151 object->LocalLookupRealNamedProperty(*name, &result); |
| 2127 if (!result.IsFound()) map()->LookupTransition(this, name, &result); | 2152 if (!result.IsFound()) { |
| 2153 object->map()->LookupTransition(*object, *name, &result); | |
| 2154 } | |
| 2128 if (result.IsFound()) { | 2155 if (result.IsFound()) { |
| 2129 // An existing property or a map transition was found. Use set property to | 2156 // An existing property or a map transition was found. Use set property to |
| 2130 // handle all these cases. | 2157 // handle all these cases. |
| 2131 return SetProperty(&result, name, value, attributes, strict_mode); | 2158 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 2159 object->SetProperty( | |
| 2160 &result, *name, *value, attributes, strict_mode), | |
| 2161 Object); | |
| 2132 } | 2162 } |
| 2133 bool done = false; | 2163 bool done = false; |
| 2134 MaybeObject* result_object = | 2164 Handle<Object> result_object = SetPropertyViaPrototypes( |
| 2135 SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); | 2165 object, name, value, attributes, strict_mode, &done); |
| 2136 if (done) return result_object; | 2166 if (done) return result_object; |
| 2137 // Add a new real property. | 2167 // Add a new real property. |
| 2138 return AddProperty(name, value, attributes, strict_mode, | 2168 return AddProperty(object, name, value, attributes, strict_mode, |
| 2139 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, | 2169 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, |
|
Toon Verwaest
2013/09/11 09:31:29
Those 4 uppercase arguments are the default argume
Michael Starzinger
2013/09/11 10:52:32
Done.
| |
| 2140 OPTIMAL_REPRESENTATION, mode); | 2170 OPTIMAL_REPRESENTATION, ALLOW_AS_CONSTANT); |
| 2141 } | 2171 } |
| 2142 | 2172 |
| 2143 | 2173 |
| 2144 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, | 2174 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, |
| 2145 Object* value, | 2175 Object* value, |
| 2146 PropertyAttributes attributes) { | 2176 PropertyAttributes attributes) { |
| 2147 NameDictionary* dictionary = property_dictionary(); | 2177 NameDictionary* dictionary = property_dictionary(); |
| 2148 int old_index = dictionary->FindEntry(name); | 2178 int old_index = dictionary->FindEntry(name); |
| 2149 int new_enumeration_index = 0; // 0 means "Use the next available index." | 2179 int new_enumeration_index = 0; // 0 means "Use the next available index." |
| 2150 if (old_index != -1) { | 2180 if (old_index != -1) { |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2696 int valid = updated->NumberOfOwnDescriptors(); | 2726 int valid = updated->NumberOfOwnDescriptors(); |
| 2697 if (!updated_descriptors->IsMoreGeneralThan( | 2727 if (!updated_descriptors->IsMoreGeneralThan( |
| 2698 verbatim, valid, descriptors, old_descriptors)) { | 2728 verbatim, valid, descriptors, old_descriptors)) { |
| 2699 return NULL; | 2729 return NULL; |
| 2700 } | 2730 } |
| 2701 | 2731 |
| 2702 return updated; | 2732 return updated; |
| 2703 } | 2733 } |
| 2704 | 2734 |
| 2705 | 2735 |
| 2706 MaybeObject* JSObject::SetPropertyWithInterceptor( | 2736 Handle<Object> JSObject::SetPropertyWithInterceptor( |
| 2707 Name* name, | 2737 Handle<JSObject> object, |
| 2708 Object* value, | 2738 Handle<Name> name, |
| 2739 Handle<Object> value, | |
| 2709 PropertyAttributes attributes, | 2740 PropertyAttributes attributes, |
| 2710 StrictModeFlag strict_mode) { | 2741 StrictModeFlag strict_mode) { |
| 2711 // TODO(rossberg): Support symbols in the API. | 2742 // TODO(rossberg): Support symbols in the API. |
| 2712 if (name->IsSymbol()) return value; | 2743 if (name->IsSymbol()) return value; |
| 2713 Isolate* isolate = GetIsolate(); | 2744 Isolate* isolate = object->GetIsolate(); |
| 2714 HandleScope scope(isolate); | 2745 Handle<String> name_string = Handle<String>::cast(name); |
| 2715 Handle<JSObject> this_handle(this); | 2746 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
| 2716 Handle<String> name_handle(String::cast(name)); | |
| 2717 Handle<Object> value_handle(value, isolate); | |
| 2718 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | |
| 2719 if (!interceptor->setter()->IsUndefined()) { | 2747 if (!interceptor->setter()->IsUndefined()) { |
| 2720 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 2748 LOG(isolate, |
| 2721 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 2749 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); |
| 2750 PropertyCallbackArguments args( | |
| 2751 isolate, interceptor->data(), *object, *object); | |
| 2722 v8::NamedPropertySetterCallback setter = | 2752 v8::NamedPropertySetterCallback setter = |
| 2723 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); | 2753 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |
| 2724 Handle<Object> value_unhole(value->IsTheHole() ? | 2754 Handle<Object> value_unhole = value->IsTheHole() |
| 2725 isolate->heap()->undefined_value() : | 2755 ? Handle<Object>(isolate->factory()->undefined_value()) : value; |
| 2726 value, | |
| 2727 isolate); | |
| 2728 v8::Handle<v8::Value> result = args.Call(setter, | 2756 v8::Handle<v8::Value> result = args.Call(setter, |
| 2729 v8::Utils::ToLocal(name_handle), | 2757 v8::Utils::ToLocal(name_string), |
| 2730 v8::Utils::ToLocal(value_unhole)); | 2758 v8::Utils::ToLocal(value_unhole)); |
| 2731 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2759 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2732 if (!result.IsEmpty()) return *value_handle; | 2760 if (!result.IsEmpty()) return value; |
| 2733 } | 2761 } |
| 2734 MaybeObject* raw_result = | 2762 Handle<Object> result = |
| 2735 this_handle->SetPropertyPostInterceptor(*name_handle, | 2763 SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); |
| 2736 *value_handle, | 2764 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2737 attributes, | 2765 return result; |
| 2738 strict_mode); | |
| 2739 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 2740 return raw_result; | |
| 2741 } | 2766 } |
| 2742 | 2767 |
| 2743 | 2768 |
| 2744 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 2769 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 2745 Handle<Name> key, | 2770 Handle<Name> key, |
| 2746 Handle<Object> value, | 2771 Handle<Object> value, |
| 2747 PropertyAttributes attributes, | 2772 PropertyAttributes attributes, |
| 2748 StrictModeFlag strict_mode) { | 2773 StrictModeFlag strict_mode) { |
| 2749 CALL_HEAP_FUNCTION(object->GetIsolate(), | 2774 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 2750 object->SetProperty(*key, *value, attributes, strict_mode), | 2775 object->SetProperty(*key, *value, attributes, strict_mode), |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2923 value, | 2948 value, |
| 2924 JSObject::cast(pt), | 2949 JSObject::cast(pt), |
| 2925 strict_mode); | 2950 strict_mode); |
| 2926 } | 2951 } |
| 2927 } | 2952 } |
| 2928 } | 2953 } |
| 2929 *found = false; | 2954 *found = false; |
| 2930 return heap->the_hole_value(); | 2955 return heap->the_hole_value(); |
| 2931 } | 2956 } |
| 2932 | 2957 |
| 2933 MaybeObject* JSObject::SetPropertyViaPrototypes( | 2958 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
| 2934 Name* name, | 2959 Handle<Name> name, |
| 2935 Object* value, | 2960 Handle<Object> value, |
| 2936 PropertyAttributes attributes, | 2961 PropertyAttributes attributes, |
| 2937 StrictModeFlag strict_mode, | 2962 StrictModeFlag strict_mode, |
| 2938 bool* done) { | 2963 bool* done) { |
| 2939 Heap* heap = GetHeap(); | 2964 Isolate* isolate = object->GetIsolate(); |
| 2940 Isolate* isolate = heap->isolate(); | |
| 2941 | 2965 |
| 2942 *done = false; | 2966 *done = false; |
| 2943 // We could not find a local property so let's check whether there is an | 2967 // We could not find a local property so let's check whether there is an |
| 2944 // accessor that wants to handle the property, or whether the property is | 2968 // accessor that wants to handle the property, or whether the property is |
| 2945 // read-only on the prototype chain. | 2969 // read-only on the prototype chain. |
| 2946 LookupResult result(isolate); | 2970 LookupResult result(isolate); |
| 2947 LookupRealNamedPropertyInPrototypes(name, &result); | 2971 object->LookupRealNamedPropertyInPrototypes(*name, &result); |
| 2948 if (result.IsFound()) { | 2972 if (result.IsFound()) { |
| 2949 switch (result.type()) { | 2973 switch (result.type()) { |
| 2950 case NORMAL: | 2974 case NORMAL: |
| 2951 case FIELD: | 2975 case FIELD: |
| 2952 case CONSTANT: | 2976 case CONSTANT: |
| 2953 *done = result.IsReadOnly(); | 2977 *done = result.IsReadOnly(); |
| 2954 break; | 2978 break; |
| 2955 case INTERCEPTOR: { | 2979 case INTERCEPTOR: { |
| 2956 PropertyAttributes attr = | 2980 PropertyAttributes attr = |
| 2957 result.holder()->GetPropertyAttributeWithInterceptor( | 2981 result.holder()->GetPropertyAttributeWithInterceptor( |
| 2958 this, name, true); | 2982 *object, *name, true); |
| 2959 *done = !!(attr & READ_ONLY); | 2983 *done = !!(attr & READ_ONLY); |
| 2960 break; | 2984 break; |
| 2961 } | 2985 } |
| 2962 case CALLBACKS: { | 2986 case CALLBACKS: { |
| 2963 if (!FLAG_es5_readonly && result.IsReadOnly()) break; | 2987 if (!FLAG_es5_readonly && result.IsReadOnly()) break; |
| 2964 *done = true; | 2988 *done = true; |
| 2965 return SetPropertyWithCallback(result.GetCallbackObject(), | 2989 CALL_HEAP_FUNCTION(isolate, |
| 2966 name, value, result.holder(), strict_mode); | 2990 object->SetPropertyWithCallback( |
| 2991 result.GetCallbackObject(), | |
| 2992 *name, *value, result.holder(), strict_mode), | |
| 2993 Object); | |
| 2967 } | 2994 } |
| 2968 case HANDLER: { | 2995 case HANDLER: { |
| 2969 return result.proxy()->SetPropertyViaPrototypesWithHandler( | 2996 CALL_HEAP_FUNCTION(isolate, |
| 2970 this, name, value, attributes, strict_mode, done); | 2997 result.proxy()->SetPropertyViaPrototypesWithHandler( |
| 2998 *object, *name, *value, attributes, strict_mode, | |
| 2999 done), | |
| 3000 Object); | |
| 2971 } | 3001 } |
| 2972 case TRANSITION: | 3002 case TRANSITION: |
| 2973 case NONEXISTENT: | 3003 case NONEXISTENT: |
| 2974 UNREACHABLE(); | 3004 UNREACHABLE(); |
| 2975 break; | 3005 break; |
| 2976 } | 3006 } |
| 2977 } | 3007 } |
| 2978 | 3008 |
| 2979 // If we get here with *done true, we have encountered a read-only property. | 3009 // If we get here with *done true, we have encountered a read-only property. |
| 2980 if (!FLAG_es5_readonly) *done = false; | 3010 if (!FLAG_es5_readonly) *done = false; |
| 2981 if (*done) { | 3011 if (*done) { |
| 2982 if (strict_mode == kNonStrictMode) return value; | 3012 if (strict_mode == kNonStrictMode) return value; |
| 2983 Handle<Object> args[] = { Handle<Object>(name, isolate), | 3013 Handle<Object> args[] = { name, object }; |
| 2984 Handle<Object>(this, isolate)}; | 3014 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2985 return isolate->Throw(*isolate->factory()->NewTypeError( | 3015 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 2986 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 3016 isolate->Throw(*error); |
| 3017 return Handle<Object>(); | |
| 2987 } | 3018 } |
| 2988 return heap->the_hole_value(); | 3019 return isolate->factory()->the_hole_value(); |
| 2989 } | 3020 } |
| 2990 | 3021 |
| 2991 | 3022 |
| 2992 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 3023 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
| 2993 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 3024 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 2994 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 3025 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
| 2995 int number_of_descriptors = descriptors->number_of_descriptors(); | 3026 int number_of_descriptors = descriptors->number_of_descriptors(); |
| 2996 Isolate* isolate = map->GetIsolate(); | 3027 Isolate* isolate = map->GetIsolate(); |
| 2997 Handle<DescriptorArray> new_descriptors = | 3028 Handle<DescriptorArray> new_descriptors = |
| 2998 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); | 3029 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); |
| (...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3766 Map* transition_map = lookup->GetTransitionTarget(); | 3797 Map* transition_map = lookup->GetTransitionTarget(); |
| 3767 int descriptor = transition_map->LastAdded(); | 3798 int descriptor = transition_map->LastAdded(); |
| 3768 | 3799 |
| 3769 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3800 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3770 PropertyDetails details = descriptors->GetDetails(descriptor); | 3801 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3771 | 3802 |
| 3772 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3803 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3773 // AddProperty will either normalize the object, or create a new fast copy | 3804 // AddProperty will either normalize the object, or create a new fast copy |
| 3774 // of the map. If we get a fast copy of the map, all field representations | 3805 // of the map. If we get a fast copy of the map, all field representations |
| 3775 // will be tagged since the transition is omitted. | 3806 // will be tagged since the transition is omitted. |
| 3776 return lookup->holder()->AddProperty( | 3807 Handle<JSObject> holder(lookup->holder()); |
| 3777 *name, *value, attributes, kNonStrictMode, | 3808 Handle<Object> result = JSObject::AddProperty( |
| 3809 holder, name, value, attributes, kNonStrictMode, | |
| 3778 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 3810 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
| 3779 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 3811 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
| 3780 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 3812 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
| 3813 RETURN_IF_EMPTY_HANDLE(holder->GetIsolate(), result); | |
| 3814 return *result; | |
| 3781 } | 3815 } |
| 3782 | 3816 |
| 3783 // Keep the target CONSTANT if the same value is stored. | 3817 // Keep the target CONSTANT if the same value is stored. |
| 3784 // TODO(verwaest): Also support keeping the placeholder | 3818 // TODO(verwaest): Also support keeping the placeholder |
| 3785 // (value->IsUninitialized) as constant. | 3819 // (value->IsUninitialized) as constant. |
| 3786 if (details.type() == CONSTANT && | 3820 if (details.type() == CONSTANT && |
| 3787 descriptors->GetValue(descriptor) == *value) { | 3821 descriptors->GetValue(descriptor) == *value) { |
| 3788 lookup->holder()->set_map(transition_map); | 3822 lookup->holder()->set_map(transition_map); |
| 3789 return *value; | 3823 return *value; |
| 3790 } | 3824 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3940 | 3974 |
| 3941 // From this point on everything needs to be handlified, because | 3975 // From this point on everything needs to be handlified, because |
| 3942 // SetPropertyViaPrototypes might call back into JavaScript. | 3976 // SetPropertyViaPrototypes might call back into JavaScript. |
| 3943 HandleScope scope(isolate); | 3977 HandleScope scope(isolate); |
| 3944 Handle<JSObject> self(this); | 3978 Handle<JSObject> self(this); |
| 3945 Handle<Name> name(name_raw); | 3979 Handle<Name> name(name_raw); |
| 3946 Handle<Object> value(value_raw, isolate); | 3980 Handle<Object> value(value_raw, isolate); |
| 3947 | 3981 |
| 3948 if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { | 3982 if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { |
| 3949 bool done = false; | 3983 bool done = false; |
| 3950 MaybeObject* result_object = self->SetPropertyViaPrototypes( | 3984 Handle<Object> result_object = SetPropertyViaPrototypes( |
| 3951 *name, *value, attributes, strict_mode, &done); | 3985 self, name, value, attributes, strict_mode, &done); |
| 3952 if (done) return result_object; | 3986 RETURN_IF_EMPTY_HANDLE(isolate, result_object); |
| 3987 if (done) return *result_object; | |
| 3953 } | 3988 } |
| 3954 | 3989 |
| 3955 if (!lookup->IsFound()) { | 3990 if (!lookup->IsFound()) { |
| 3956 // Neither properties nor transitions found. | 3991 // Neither properties nor transitions found. |
| 3957 return self->AddProperty( | 3992 Handle<Object> result_object = AddProperty( |
| 3958 *name, *value, attributes, strict_mode, store_mode); | 3993 self, name, value, attributes, strict_mode, store_mode); |
| 3994 RETURN_IF_EMPTY_HANDLE(isolate, result_object); | |
| 3995 return *result_object; | |
| 3959 } | 3996 } |
| 3960 | 3997 |
| 3961 if (lookup->IsProperty() && lookup->IsReadOnly()) { | 3998 if (lookup->IsProperty() && lookup->IsReadOnly()) { |
| 3962 if (strict_mode == kStrictMode) { | 3999 if (strict_mode == kStrictMode) { |
| 3963 Handle<Object> args[] = { name, self }; | 4000 Handle<Object> args[] = { name, self }; |
| 3964 return isolate->Throw(*isolate->factory()->NewTypeError( | 4001 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 3965 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 4002 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); |
| 3966 } else { | 4003 } else { |
| 3967 return *value; | 4004 return *value; |
| 3968 } | 4005 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 3987 case CONSTANT: | 4024 case CONSTANT: |
| 3988 // Only replace the constant if necessary. | 4025 // Only replace the constant if necessary. |
| 3989 if (*value == lookup->GetConstant()) return *value; | 4026 if (*value == lookup->GetConstant()) return *value; |
| 3990 result = SetPropertyToField(lookup, name, value); | 4027 result = SetPropertyToField(lookup, name, value); |
| 3991 break; | 4028 break; |
| 3992 case CALLBACKS: { | 4029 case CALLBACKS: { |
| 3993 Object* callback_object = lookup->GetCallbackObject(); | 4030 Object* callback_object = lookup->GetCallbackObject(); |
| 3994 return self->SetPropertyWithCallback( | 4031 return self->SetPropertyWithCallback( |
| 3995 callback_object, *name, *value, lookup->holder(), strict_mode); | 4032 callback_object, *name, *value, lookup->holder(), strict_mode); |
| 3996 } | 4033 } |
| 3997 case INTERCEPTOR: | 4034 case INTERCEPTOR: { |
| 3998 result = lookup->holder()->SetPropertyWithInterceptor( | 4035 Handle<JSObject> holder(lookup->holder()); |
| 3999 *name, *value, attributes, strict_mode); | 4036 Handle<Object> hresult = SetPropertyWithInterceptor( |
| 4037 holder, name, value, attributes, strict_mode); | |
| 4038 RETURN_IF_EMPTY_HANDLE(isolate, hresult); | |
| 4039 result = *hresult; | |
| 4000 break; | 4040 break; |
| 4041 } | |
| 4001 case TRANSITION: { | 4042 case TRANSITION: { |
| 4002 result = SetPropertyUsingTransition(lookup, name, value, attributes); | 4043 result = SetPropertyUsingTransition(lookup, name, value, attributes); |
| 4003 break; | 4044 break; |
| 4004 } | 4045 } |
| 4005 case HANDLER: | 4046 case HANDLER: |
| 4006 case NONEXISTENT: | 4047 case NONEXISTENT: |
| 4007 UNREACHABLE(); | 4048 UNREACHABLE(); |
| 4008 } | 4049 } |
| 4009 | 4050 |
| 4010 Handle<Object> hresult; | 4051 Handle<Object> hresult; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4113 value_type, | 4154 value_type, |
| 4114 mode, | 4155 mode, |
| 4115 extensibility_check); | 4156 extensibility_check); |
| 4116 } | 4157 } |
| 4117 | 4158 |
| 4118 if (lookup.IsFound() && | 4159 if (lookup.IsFound() && |
| 4119 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { | 4160 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { |
| 4120 LocalLookupRealNamedProperty(name_raw, &lookup); | 4161 LocalLookupRealNamedProperty(name_raw, &lookup); |
| 4121 } | 4162 } |
| 4122 | 4163 |
| 4123 // Check for accessor in prototype chain removed here in clone. | |
| 4124 if (!lookup.IsFound()) { | |
| 4125 // Neither properties nor transitions found. | |
| 4126 return AddProperty( | |
| 4127 name_raw, value_raw, attributes, kNonStrictMode, | |
| 4128 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | |
| 4129 } | |
| 4130 | |
| 4131 // From this point on everything needs to be handlified. | 4164 // From this point on everything needs to be handlified. |
| 4132 HandleScope scope(isolate); | 4165 HandleScope scope(isolate); |
| 4133 Handle<JSObject> self(this); | 4166 Handle<JSObject> self(this); |
| 4134 Handle<Name> name(name_raw); | 4167 Handle<Name> name(name_raw); |
| 4135 Handle<Object> value(value_raw, isolate); | 4168 Handle<Object> value(value_raw, isolate); |
| 4136 | 4169 |
| 4137 Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate); | 4170 // Check for accessor in prototype chain removed here in clone. |
| 4171 if (!lookup.IsFound()) { | |
| 4172 // Neither properties nor transitions found. | |
| 4173 Handle<Object> result = AddProperty( | |
| 4174 self, name, value, attributes, kNonStrictMode, | |
| 4175 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | |
| 4176 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 4177 return *result; | |
| 4178 } | |
| 4179 | |
| 4180 Handle<Object> old_value = isolate->factory()->the_hole_value(); | |
| 4138 PropertyAttributes old_attributes = ABSENT; | 4181 PropertyAttributes old_attributes = ABSENT; |
| 4139 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 4182 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); |
| 4140 if (is_observed && lookup.IsProperty()) { | 4183 if (is_observed && lookup.IsProperty()) { |
| 4141 if (lookup.IsDataProperty()) old_value = | 4184 if (lookup.IsDataProperty()) old_value = |
| 4142 Object::GetProperty(self, name); | 4185 Object::GetProperty(self, name); |
| 4143 old_attributes = lookup.GetAttributes(); | 4186 old_attributes = lookup.GetAttributes(); |
| 4144 } | 4187 } |
| 4145 | 4188 |
| 4146 // Check of IsReadOnly removed from here in clone. | 4189 // Check of IsReadOnly removed from here in clone. |
| 4147 MaybeObject* result = *value; | 4190 MaybeObject* result = *value; |
| (...skipping 11929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16077 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16120 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16078 static const char* error_messages_[] = { | 16121 static const char* error_messages_[] = { |
| 16079 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16122 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16080 }; | 16123 }; |
| 16081 #undef ERROR_MESSAGES_TEXTS | 16124 #undef ERROR_MESSAGES_TEXTS |
| 16082 return error_messages_[reason]; | 16125 return error_messages_[reason]; |
| 16083 } | 16126 } |
| 16084 | 16127 |
| 16085 | 16128 |
| 16086 } } // namespace v8::internal | 16129 } } // namespace v8::internal |
| OLD | NEW |