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 1909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1920 } | 1920 } |
| 1921 } | 1921 } |
| 1922 return true; | 1922 return true; |
| 1923 } | 1923 } |
| 1924 | 1924 |
| 1925 | 1925 |
| 1926 MaybeObject* JSObject::AddFastProperty(Name* name, | 1926 MaybeObject* JSObject::AddFastProperty(Name* name, |
| 1927 Object* value, | 1927 Object* value, |
| 1928 PropertyAttributes attributes, | 1928 PropertyAttributes attributes, |
| 1929 StoreFromKeyed store_mode, | 1929 StoreFromKeyed store_mode, |
| 1930 ValueType value_type) { | 1930 ValueType value_type, |
| 1931 TransitionFlag flag) { | |
| 1931 ASSERT(!IsJSGlobalProxy()); | 1932 ASSERT(!IsJSGlobalProxy()); |
| 1932 ASSERT(DescriptorArray::kNotFound == | 1933 ASSERT(DescriptorArray::kNotFound == |
| 1933 map()->instance_descriptors()->Search( | 1934 map()->instance_descriptors()->Search( |
| 1934 name, map()->NumberOfOwnDescriptors())); | 1935 name, map()->NumberOfOwnDescriptors())); |
| 1935 | 1936 |
| 1936 // Normalize the object if the name is an actual name (not the | 1937 // Normalize the object if the name is an actual name (not the |
| 1937 // hidden strings) and is not a real identifier. | 1938 // hidden strings) and is not a real identifier. |
| 1938 // Normalize the object if it will have too many fast properties. | 1939 // Normalize the object if it will have too many fast properties. |
| 1939 Isolate* isolate = GetHeap()->isolate(); | 1940 Isolate* isolate = GetHeap()->isolate(); |
| 1940 if ((!name->IsSymbol() && !IsIdentifier(isolate->unicode_cache(), name) | 1941 if ((!name->IsSymbol() && |
| 1941 && name != isolate->heap()->hidden_string()) || | 1942 !IsIdentifier(isolate->unicode_cache(), name) && |
| 1942 (map()->unused_property_fields() == 0 && | 1943 name != isolate->heap()->hidden_string()) || |
| 1943 TooManyFastProperties(properties()->length(), store_mode))) { | 1944 TooManyFastProperties(store_mode)) { |
| 1944 Object* obj; | 1945 MaybeObject* maybe_failure = |
| 1945 MaybeObject* maybe_obj = | |
| 1946 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1946 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1947 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1947 if (maybe_failure->IsFailure()) return maybe_failure; |
| 1948 | |
| 1949 return AddSlowProperty(name, value, attributes); | 1948 return AddSlowProperty(name, value, attributes); |
| 1950 } | 1949 } |
| 1951 | 1950 |
| 1952 // Compute the new index for new field. | 1951 // Compute the new index for new field. |
| 1953 int index = map()->NextFreePropertyIndex(); | 1952 int index = map()->NextFreePropertyIndex(); |
| 1954 | 1953 |
| 1955 // Allocate new instance descriptors with (name, index) added | 1954 // Allocate new instance descriptors with (name, index) added |
| 1956 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 1955 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
| 1957 Representation representation = value->OptimalRepresentation(value_type); | 1956 Representation representation = value->OptimalRepresentation(value_type); |
| 1958 | 1957 |
| 1959 FieldDescriptor new_field(name, index, attributes, representation); | 1958 FieldDescriptor new_field(name, index, attributes, representation); |
| 1960 | 1959 |
| 1961 ASSERT(index < map()->inobject_properties() || | 1960 ASSERT(index < map()->inobject_properties() || |
| 1962 (index - map()->inobject_properties()) < properties()->length() || | 1961 (index - map()->inobject_properties()) < properties()->length() || |
| 1963 map()->unused_property_fields() == 0); | 1962 map()->unused_property_fields() == 0); |
| 1964 | 1963 |
| 1965 FixedArray* values = NULL; | 1964 FixedArray* values = NULL; |
| 1966 | 1965 |
| 1967 // TODO(verwaest): Merge with AddFastPropertyUsingMap. | 1966 // TODO(verwaest): Merge with AddFastPropertyUsingMap. |
| 1968 if (map()->unused_property_fields() == 0) { | 1967 if (map()->unused_property_fields() == 0) { |
| 1969 // Make room for the new value | 1968 // Make room for the new value |
| 1970 MaybeObject* maybe_values = | 1969 MaybeObject* maybe_values = |
| 1971 properties()->CopySize(properties()->length() + kFieldsAdded); | 1970 properties()->CopySize(properties()->length() + kFieldsAdded); |
| 1972 if (!maybe_values->To(&values)) return maybe_values; | 1971 if (!maybe_values->To(&values)) return maybe_values; |
| 1973 } | 1972 } |
| 1974 | 1973 |
| 1975 TransitionFlag flag = INSERT_TRANSITION; | |
| 1976 | |
| 1977 Heap* heap = isolate->heap(); | 1974 Heap* heap = isolate->heap(); |
| 1978 | 1975 |
| 1979 Object* storage; | 1976 Object* storage; |
| 1980 MaybeObject* maybe_storage = | 1977 MaybeObject* maybe_storage = |
| 1981 value->AllocateNewStorageFor(heap, representation); | 1978 value->AllocateNewStorageFor(heap, representation); |
| 1982 if (!maybe_storage->To(&storage)) return maybe_storage; | 1979 if (!maybe_storage->To(&storage)) return maybe_storage; |
| 1983 | 1980 |
| 1984 // Note that Map::CopyAddDescriptor has side-effects, the new map is already | 1981 // Note that Map::CopyAddDescriptor has side-effects, the new map is already |
| 1985 // inserted in the transition tree. No more allocations that might fail are | 1982 // inserted in the transition tree. No more allocations that might fail are |
| 1986 // allowed after this point. | 1983 // allowed after this point. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1999 set_map(new_map); | 1996 set_map(new_map); |
| 2000 | 1997 |
| 2001 FastPropertyAtPut(index, storage); | 1998 FastPropertyAtPut(index, storage); |
| 2002 return value; | 1999 return value; |
| 2003 } | 2000 } |
| 2004 | 2001 |
| 2005 | 2002 |
| 2006 MaybeObject* JSObject::AddConstantProperty( | 2003 MaybeObject* JSObject::AddConstantProperty( |
| 2007 Name* name, | 2004 Name* name, |
| 2008 Object* constant, | 2005 Object* constant, |
| 2009 PropertyAttributes attributes) { | 2006 PropertyAttributes attributes, |
| 2007 TransitionFlag initial_flag) { | |
| 2010 // Allocate new instance descriptors with (name, constant) added | 2008 // Allocate new instance descriptors with (name, constant) added |
| 2011 ConstantDescriptor d(name, constant, attributes); | 2009 ConstantDescriptor d(name, constant, attributes); |
| 2012 | 2010 |
| 2013 TransitionFlag flag = | 2011 TransitionFlag flag = |
| 2014 // Do not add transitions to global objects. | 2012 // Do not add transitions to global objects. |
| 2015 (IsGlobalObject() || | 2013 (IsGlobalObject() || |
| 2016 // Don't add transitions to special properties with non-trivial | 2014 // Don't add transitions to special properties with non-trivial |
| 2017 // attributes. | 2015 // attributes. |
| 2018 attributes != NONE) | 2016 attributes != NONE) |
| 2019 ? OMIT_TRANSITION | 2017 ? OMIT_TRANSITION |
| 2020 : INSERT_TRANSITION; | 2018 : initial_flag; |
| 2021 | 2019 |
| 2022 Map* new_map; | 2020 Map* new_map; |
| 2023 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); | 2021 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); |
| 2024 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2022 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 2025 | 2023 |
| 2026 set_map(new_map); | 2024 set_map(new_map); |
| 2027 return constant; | 2025 return constant; |
| 2028 } | 2026 } |
| 2029 | 2027 |
| 2030 | 2028 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2070 } | 2068 } |
| 2071 | 2069 |
| 2072 | 2070 |
| 2073 MaybeObject* JSObject::AddProperty(Name* name, | 2071 MaybeObject* JSObject::AddProperty(Name* name, |
| 2074 Object* value, | 2072 Object* value, |
| 2075 PropertyAttributes attributes, | 2073 PropertyAttributes attributes, |
| 2076 StrictModeFlag strict_mode, | 2074 StrictModeFlag strict_mode, |
| 2077 JSReceiver::StoreFromKeyed store_mode, | 2075 JSReceiver::StoreFromKeyed store_mode, |
| 2078 ExtensibilityCheck extensibility_check, | 2076 ExtensibilityCheck extensibility_check, |
| 2079 ValueType value_type, | 2077 ValueType value_type, |
| 2080 StoreMode mode) { | 2078 StoreMode mode, |
| 2079 TransitionFlag transition_flag) { | |
| 2081 ASSERT(!IsJSGlobalProxy()); | 2080 ASSERT(!IsJSGlobalProxy()); |
| 2082 Map* map_of_this = map(); | 2081 Map* map_of_this = map(); |
| 2083 Heap* heap = GetHeap(); | 2082 Heap* heap = GetHeap(); |
| 2084 Isolate* isolate = heap->isolate(); | 2083 Isolate* isolate = heap->isolate(); |
| 2085 MaybeObject* result; | 2084 MaybeObject* result; |
| 2086 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2085 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
| 2087 !map_of_this->is_extensible()) { | 2086 !map_of_this->is_extensible()) { |
| 2088 if (strict_mode == kNonStrictMode) { | 2087 if (strict_mode == kNonStrictMode) { |
| 2089 return value; | 2088 return value; |
| 2090 } else { | 2089 } else { |
| 2091 Handle<Object> args[1] = {Handle<Name>(name)}; | 2090 Handle<Object> args[1] = {Handle<Name>(name)}; |
| 2092 return isolate->Throw( | 2091 return isolate->Throw( |
| 2093 *isolate->factory()->NewTypeError("object_not_extensible", | 2092 *isolate->factory()->NewTypeError("object_not_extensible", |
| 2094 HandleVector(args, 1))); | 2093 HandleVector(args, 1))); |
| 2095 } | 2094 } |
| 2096 } | 2095 } |
| 2097 | 2096 |
| 2098 if (HasFastProperties()) { | 2097 if (HasFastProperties()) { |
| 2099 // Ensure the descriptor array does not get too big. | 2098 // Ensure the descriptor array does not get too big. |
| 2100 if (map_of_this->NumberOfOwnDescriptors() < | 2099 if (map_of_this->NumberOfOwnDescriptors() < |
| 2101 DescriptorArray::kMaxNumberOfDescriptors) { | 2100 DescriptorArray::kMaxNumberOfDescriptors) { |
| 2102 // TODO(verwaest): Support other constants. | 2101 // TODO(verwaest): Support other constants. |
| 2103 // if (mode == ALLOW_AS_CONSTANT && | 2102 // if (mode == ALLOW_AS_CONSTANT && |
| 2104 // !value->IsTheHole() && | 2103 // !value->IsTheHole() && |
| 2105 // !value->IsConsString()) { | 2104 // !value->IsConsString()) { |
| 2106 if (value->IsJSFunction()) { | 2105 if (value->IsJSFunction()) { |
| 2107 result = AddConstantProperty(name, value, attributes); | 2106 result = AddConstantProperty(name, value, attributes, transition_flag); |
| 2108 } else { | 2107 } else { |
| 2109 result = AddFastProperty( | 2108 result = AddFastProperty( |
| 2110 name, value, attributes, store_mode, value_type); | 2109 name, value, attributes, store_mode, value_type, transition_flag); |
| 2111 } | 2110 } |
| 2112 } else { | 2111 } else { |
| 2113 // Normalize the object to prevent very large instance descriptors. | 2112 // Normalize the object to prevent very large instance descriptors. |
| 2114 // This eliminates unwanted N^2 allocation and lookup behavior. | 2113 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2115 Object* obj; | 2114 Object* obj; |
| 2116 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2115 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2117 if (!maybe->To(&obj)) return maybe; | 2116 if (!maybe->To(&obj)) return maybe; |
| 2118 result = AddSlowProperty(name, value, attributes); | 2117 result = AddSlowProperty(name, value, attributes); |
| 2119 } | 2118 } |
| 2120 } else { | 2119 } else { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2204 if (old_index != -1) { | 2203 if (old_index != -1) { |
| 2205 // All calls to ReplaceSlowProperty have had all transitions removed. | 2204 // All calls to ReplaceSlowProperty have had all transitions removed. |
| 2206 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2205 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
| 2207 } | 2206 } |
| 2208 | 2207 |
| 2209 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2208 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
| 2210 return SetNormalizedProperty(name, value, new_details); | 2209 return SetNormalizedProperty(name, value, new_details); |
| 2211 } | 2210 } |
| 2212 | 2211 |
| 2213 | 2212 |
| 2214 MaybeObject* JSObject::ConvertDescriptorToField(Name* name, | |
| 2215 Object* new_value, | |
| 2216 PropertyAttributes attributes, | |
| 2217 TransitionFlag flag) { | |
| 2218 if (map()->unused_property_fields() == 0 && | |
| 2219 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | |
| 2220 Object* obj; | |
| 2221 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | |
| 2222 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 2223 return ReplaceSlowProperty(name, new_value, attributes); | |
| 2224 } | |
| 2225 | |
| 2226 Representation representation = IsJSContextExtensionObject() | |
| 2227 ? Representation::Tagged() : new_value->OptimalRepresentation(); | |
| 2228 int index = map()->NextFreePropertyIndex(); | |
| 2229 FieldDescriptor new_field(name, index, attributes, representation); | |
| 2230 | |
| 2231 // Make a new map for the object. | |
| 2232 Map* new_map; | |
| 2233 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, flag); | |
| 2234 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 2235 | |
| 2236 // Make new properties array if necessary. | |
| 2237 FixedArray* new_properties = NULL; | |
| 2238 int new_unused_property_fields = map()->unused_property_fields() - 1; | |
| 2239 if (map()->unused_property_fields() == 0) { | |
| 2240 new_unused_property_fields = kFieldsAdded - 1; | |
| 2241 MaybeObject* maybe_new_properties = | |
| 2242 properties()->CopySize(properties()->length() + kFieldsAdded); | |
| 2243 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; | |
| 2244 } | |
| 2245 | |
| 2246 Heap* heap = GetHeap(); | |
| 2247 Object* storage; | |
| 2248 MaybeObject* maybe_storage = | |
| 2249 new_value->AllocateNewStorageFor(heap, representation); | |
| 2250 if (!maybe_storage->To(&storage)) return maybe_storage; | |
| 2251 | |
| 2252 // Update pointers to commit changes. | |
| 2253 // Object points to the new map. | |
| 2254 new_map->set_unused_property_fields(new_unused_property_fields); | |
| 2255 set_map(new_map); | |
| 2256 if (new_properties != NULL) { | |
| 2257 set_properties(new_properties); | |
| 2258 } | |
| 2259 FastPropertyAtPut(index, storage); | |
| 2260 return new_value; | |
| 2261 } | |
| 2262 | |
| 2263 | |
| 2264 const char* Representation::Mnemonic() const { | 2213 const char* Representation::Mnemonic() const { |
| 2265 switch (kind_) { | 2214 switch (kind_) { |
| 2266 case kNone: return "v"; | 2215 case kNone: return "v"; |
| 2267 case kTagged: return "t"; | 2216 case kTagged: return "t"; |
| 2268 case kSmi: return "s"; | 2217 case kSmi: return "s"; |
| 2269 case kDouble: return "d"; | 2218 case kDouble: return "d"; |
| 2270 case kInteger32: return "i"; | 2219 case kInteger32: return "i"; |
| 2271 case kHeapObject: return "h"; | 2220 case kHeapObject: return "h"; |
| 2272 case kExternal: return "x"; | 2221 case kExternal: return "x"; |
| 2273 default: | 2222 default: |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2400 if (!maybe_array->To(&array)) return maybe_array; | 2349 if (!maybe_array->To(&array)) return maybe_array; |
| 2401 | 2350 |
| 2402 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2351 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 2403 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2352 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
| 2404 int descriptors = new_map->NumberOfOwnDescriptors(); | 2353 int descriptors = new_map->NumberOfOwnDescriptors(); |
| 2405 | 2354 |
| 2406 for (int i = 0; i < descriptors; i++) { | 2355 for (int i = 0; i < descriptors; i++) { |
| 2407 PropertyDetails details = new_descriptors->GetDetails(i); | 2356 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2408 if (details.type() != FIELD) continue; | 2357 if (details.type() != FIELD) continue; |
| 2409 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2358 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2359 if (old_details.type() == CALLBACKS) { | |
| 2360 ASSERT(details.representation().IsTagged()); | |
| 2361 continue; | |
| 2362 } | |
| 2410 ASSERT(old_details.type() == CONSTANT || | 2363 ASSERT(old_details.type() == CONSTANT || |
| 2411 old_details.type() == FIELD); | 2364 old_details.type() == FIELD); |
| 2412 Object* value = old_details.type() == CONSTANT | 2365 Object* value = old_details.type() == CONSTANT |
| 2413 ? old_descriptors->GetValue(i) | 2366 ? old_descriptors->GetValue(i) |
| 2414 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); | 2367 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
| 2415 if (FLAG_track_double_fields && | 2368 if (FLAG_track_double_fields && |
| 2416 !old_details.representation().IsDouble() && | 2369 !old_details.representation().IsDouble() && |
| 2417 details.representation().IsDouble()) { | 2370 details.representation().IsDouble()) { |
| 2418 if (old_details.representation().IsNone()) value = Smi::FromInt(0); | 2371 if (old_details.representation().IsNone()) value = Smi::FromInt(0); |
| 2419 // Objects must be allocated in the old object space, since the | 2372 // Objects must be allocated in the old object space, since the |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2481 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2434 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
| 2482 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2435 if (descriptors->GetDetails(i).type() == FIELD) result++; |
| 2483 } | 2436 } |
| 2484 return result; | 2437 return result; |
| 2485 } | 2438 } |
| 2486 | 2439 |
| 2487 | 2440 |
| 2488 MaybeObject* Map::CopyGeneralizeAllRepresentations( | 2441 MaybeObject* Map::CopyGeneralizeAllRepresentations( |
| 2489 int modify_index, | 2442 int modify_index, |
| 2490 StoreMode store_mode, | 2443 StoreMode store_mode, |
| 2444 PropertyAttributes attributes, | |
| 2491 const char* reason) { | 2445 const char* reason) { |
| 2492 Map* new_map; | 2446 Map* new_map; |
| 2493 MaybeObject* maybe_map = this->Copy(); | 2447 MaybeObject* maybe_map = this->Copy(); |
| 2494 if (!maybe_map->To(&new_map)) return maybe_map; | 2448 if (!maybe_map->To(&new_map)) return maybe_map; |
| 2495 | 2449 |
| 2496 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2450 DescriptorArray* descriptors = new_map->instance_descriptors(); |
| 2497 descriptors->InitializeRepresentations(Representation::Tagged()); | 2451 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 2498 | 2452 |
| 2499 // Unless the instance is being migrated, ensure that modify_index is a field. | 2453 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2500 PropertyDetails details = descriptors->GetDetails(modify_index); | 2454 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2501 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2455 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
| 2502 FieldDescriptor d(descriptors->GetKey(modify_index), | 2456 FieldDescriptor d(descriptors->GetKey(modify_index), |
| 2503 new_map->NumberOfFields(), | 2457 new_map->NumberOfFields(), |
| 2504 details.attributes(), | 2458 attributes, |
| 2505 Representation::Tagged()); | 2459 Representation::Tagged()); |
| 2506 d.SetSortedKeyIndex(details.pointer()); | 2460 d.SetSortedKeyIndex(details.pointer()); |
| 2507 descriptors->Set(modify_index, &d); | 2461 descriptors->Set(modify_index, &d); |
| 2508 int unused_property_fields = new_map->unused_property_fields() - 1; | 2462 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2509 if (unused_property_fields < 0) { | 2463 if (unused_property_fields < 0) { |
| 2510 unused_property_fields += JSObject::kFieldsAdded; | 2464 unused_property_fields += JSObject::kFieldsAdded; |
| 2511 } | 2465 } |
| 2512 new_map->set_unused_property_fields(unused_property_fields); | 2466 new_map->set_unused_property_fields(unused_property_fields); |
| 2513 } | 2467 } |
| 2514 | 2468 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2659 // |split_map|, the first map who's descriptor array does not match the merged | 2613 // |split_map|, the first map who's descriptor array does not match the merged |
| 2660 // descriptor array. | 2614 // descriptor array. |
| 2661 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2615 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
| 2662 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2616 // - Otherwise, invalidate the outdated transition target from |updated|, and |
| 2663 // replace its transition tree with a new branch for the updated descriptors. | 2617 // replace its transition tree with a new branch for the updated descriptors. |
| 2664 MaybeObject* Map::GeneralizeRepresentation(int modify_index, | 2618 MaybeObject* Map::GeneralizeRepresentation(int modify_index, |
| 2665 Representation new_representation, | 2619 Representation new_representation, |
| 2666 StoreMode store_mode) { | 2620 StoreMode store_mode) { |
| 2667 Map* old_map = this; | 2621 Map* old_map = this; |
| 2668 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2622 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 2669 Representation old_representation = | 2623 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2670 old_descriptors->GetDetails(modify_index).representation(); | 2624 Representation old_representation = old_details.representation(); |
| 2671 | 2625 |
| 2672 // It's fine to transition from None to anything but double without any | 2626 // It's fine to transition from None to anything but double without any |
| 2673 // modification to the object, because the default uninitialized value for | 2627 // modification to the object, because the default uninitialized value for |
| 2674 // representation None can be overwritten by both smi and tagged values. | 2628 // representation None can be overwritten by both smi and tagged values. |
| 2675 // Doubles, however, would require a box allocation. | 2629 // Doubles, however, would require a box allocation. |
| 2676 if (old_representation.IsNone() && | 2630 if (old_representation.IsNone() && |
| 2677 !new_representation.IsNone() && | 2631 !new_representation.IsNone() && |
| 2678 !new_representation.IsDouble()) { | 2632 !new_representation.IsDouble()) { |
| 2679 old_descriptors->SetRepresentation(modify_index, new_representation); | 2633 old_descriptors->SetRepresentation(modify_index, new_representation); |
| 2680 return old_map; | 2634 return old_map; |
| 2681 } | 2635 } |
| 2682 | 2636 |
| 2683 int descriptors = old_map->NumberOfOwnDescriptors(); | 2637 int descriptors = old_map->NumberOfOwnDescriptors(); |
| 2684 Map* root_map = old_map->FindRootMap(); | 2638 Map* root_map = old_map->FindRootMap(); |
| 2685 | 2639 |
| 2686 // Check the state of the root map. | 2640 // Check the state of the root map. |
| 2687 if (!old_map->EquivalentToForTransition(root_map)) { | 2641 if (!old_map->EquivalentToForTransition(root_map)) { |
| 2688 return CopyGeneralizeAllRepresentations( | 2642 return CopyGeneralizeAllRepresentations( |
| 2689 modify_index, store_mode, "not equivalent"); | 2643 modify_index, store_mode, old_details.attributes(), "not equivalent"); |
| 2690 } | 2644 } |
| 2691 | 2645 |
| 2692 int verbatim = root_map->NumberOfOwnDescriptors(); | 2646 int verbatim = root_map->NumberOfOwnDescriptors(); |
| 2693 | 2647 |
| 2694 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2648 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
| 2695 return CopyGeneralizeAllRepresentations( | 2649 return CopyGeneralizeAllRepresentations( |
| 2696 modify_index, store_mode, "root modification"); | 2650 modify_index, store_mode, |
| 2651 old_details.attributes(), "root modification"); | |
| 2697 } | 2652 } |
| 2698 | 2653 |
| 2699 Map* updated = root_map->FindUpdatedMap( | 2654 Map* updated = root_map->FindUpdatedMap( |
| 2700 verbatim, descriptors, old_descriptors); | 2655 verbatim, descriptors, old_descriptors); |
| 2701 if (updated == NULL) { | 2656 if (updated == NULL) { |
| 2702 return CopyGeneralizeAllRepresentations( | 2657 return CopyGeneralizeAllRepresentations( |
| 2703 modify_index, store_mode, "incompatible"); | 2658 modify_index, store_mode, old_details.attributes(), "incompatible"); |
| 2704 } | 2659 } |
| 2705 | 2660 |
| 2706 DescriptorArray* updated_descriptors = updated->instance_descriptors(); | 2661 DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
| 2707 | 2662 |
| 2708 int valid = updated->NumberOfOwnDescriptors(); | 2663 int valid = updated->NumberOfOwnDescriptors(); |
| 2709 | 2664 |
| 2710 // Directly change the map if the target map is more general. Ensure that the | 2665 // Directly change the map if the target map is more general. Ensure that the |
| 2711 // target type of the modify_index is a FIELD, unless we are migrating. | 2666 // target type of the modify_index is a FIELD, unless we are migrating. |
| 2712 if (updated_descriptors->IsMoreGeneralThan( | 2667 if (updated_descriptors->IsMoreGeneralThan( |
| 2713 verbatim, valid, descriptors, old_descriptors) && | 2668 verbatim, valid, descriptors, old_descriptors) && |
| (...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3809 Handle<Name> name, | 3764 Handle<Name> name, |
| 3810 Handle<Object> value, | 3765 Handle<Object> value, |
| 3811 PropertyAttributes attributes) { | 3766 PropertyAttributes attributes) { |
| 3812 Map* transition_map = lookup->GetTransitionTarget(); | 3767 Map* transition_map = lookup->GetTransitionTarget(); |
| 3813 int descriptor = transition_map->LastAdded(); | 3768 int descriptor = transition_map->LastAdded(); |
| 3814 | 3769 |
| 3815 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3770 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3816 PropertyDetails details = descriptors->GetDetails(descriptor); | 3771 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3817 | 3772 |
| 3818 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3773 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3819 return lookup->holder()->ConvertDescriptorToField( | 3774 // AddProperty will either normalize the object, or create a new fast copy |
| 3820 *name, *value, attributes); | 3775 // of the map. If we get a fast copy of the map, all field representations |
| 3776 // will be tagged since the transition is omitted. | |
| 3777 return lookup->holder()->AddProperty( | |
| 3778 *name, *value, attributes, kNonStrictMode, | |
| 3779 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | |
| 3780 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | |
| 3781 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | |
| 3821 } | 3782 } |
| 3822 | 3783 |
| 3823 // Keep the target CONSTANT if the same value is stored. | 3784 // Keep the target CONSTANT if the same value is stored. |
| 3824 // TODO(verwaest): Also support keeping the placeholder | 3785 // TODO(verwaest): Also support keeping the placeholder |
| 3825 // (value->IsUninitialized) as constant. | 3786 // (value->IsUninitialized) as constant. |
| 3826 if (details.type() == CONSTANT && | 3787 if (details.type() == CONSTANT && |
| 3827 descriptors->GetValue(descriptor) == *value) { | 3788 descriptors->GetValue(descriptor) == *value) { |
| 3828 lookup->holder()->set_map(transition_map); | 3789 lookup->holder()->set_map(transition_map); |
| 3829 return *value; | 3790 return *value; |
| 3830 } | 3791 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3875 storage->set_value(value->Number()); | 3836 storage->set_value(value->Number()); |
| 3876 return *value; | 3837 return *value; |
| 3877 } | 3838 } |
| 3878 | 3839 |
| 3879 lookup->holder()->FastPropertyAtPut( | 3840 lookup->holder()->FastPropertyAtPut( |
| 3880 lookup->GetFieldIndex().field_index(), *value); | 3841 lookup->GetFieldIndex().field_index(), *value); |
| 3881 return *value; | 3842 return *value; |
| 3882 } | 3843 } |
| 3883 | 3844 |
| 3884 | 3845 |
| 3846 static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup, | |
| 3847 Name* name, | |
| 3848 Object* value, | |
| 3849 PropertyAttributes attributes) { | |
| 3850 JSObject* object = lookup->holder(); | |
| 3851 if (object->TooManyFastProperties()) { | |
| 3852 MaybeObject* maybe_failure = object->NormalizeProperties( | |
| 3853 CLEAR_INOBJECT_PROPERTIES, 0); | |
| 3854 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3855 } | |
| 3856 | |
| 3857 if (!object->HasFastProperties()) { | |
| 3858 return object->ReplaceSlowProperty(name, value, attributes); | |
| 3859 } | |
| 3860 | |
| 3861 int descriptor_index = lookup->GetDescriptorIndex(); | |
| 3862 if (lookup->GetAttributes() == attributes) { | |
| 3863 MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation( | |
| 3864 descriptor_index, Representation::Tagged(), FORCE_FIELD); | |
| 3865 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3866 } else { | |
| 3867 Map* map; | |
| 3868 MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations( | |
| 3869 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | |
| 3870 if (!maybe_map->To(&map)) return maybe_map; | |
| 3871 MaybeObject* maybe_failure = object->MigrateToMap(map); | |
| 3872 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3873 } | |
| 3874 | |
| 3875 DescriptorArray* descriptors = object->map()->instance_descriptors(); | |
| 3876 int index = descriptors->GetDetails(descriptor_index).field_index(); | |
| 3877 object->FastPropertyAtPut(index, value); | |
| 3878 return value; | |
| 3879 } | |
| 3880 | |
| 3881 | |
| 3882 static MaybeObject* SetPropertyToFieldWithAttributes( | |
| 3883 LookupResult* lookup, | |
| 3884 Handle<Name> name, | |
| 3885 Handle<Object> value, | |
| 3886 PropertyAttributes attributes) { | |
| 3887 if (lookup->GetAttributes() == attributes) { | |
| 3888 if (value->IsUninitialized()) return *value; | |
| 3889 return SetPropertyToField(lookup, name, value); | |
| 3890 } else { | |
| 3891 return ConvertAndSetLocalProperty(lookup, *name, *value, attributes); | |
| 3892 } | |
| 3893 } | |
| 3894 | |
| 3895 | |
| 3885 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, | 3896 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, |
| 3886 Name* name_raw, | 3897 Name* name_raw, |
| 3887 Object* value_raw, | 3898 Object* value_raw, |
| 3888 PropertyAttributes attributes, | 3899 PropertyAttributes attributes, |
| 3889 StrictModeFlag strict_mode, | 3900 StrictModeFlag strict_mode, |
| 3890 StoreFromKeyed store_mode) { | 3901 StoreFromKeyed store_mode) { |
| 3891 Heap* heap = GetHeap(); | 3902 Heap* heap = GetHeap(); |
| 3892 Isolate* isolate = heap->isolate(); | 3903 Isolate* isolate = heap->isolate(); |
| 3893 // 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 |
| 3894 // interceptor calls. | 3905 // interceptor calls. |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4098 PropertyAttributes old_attributes = ABSENT; | 4109 PropertyAttributes old_attributes = ABSENT; |
| 4099 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 4110 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); |
| 4100 if (is_observed && lookup.IsProperty()) { | 4111 if (is_observed && lookup.IsProperty()) { |
| 4101 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name); | 4112 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name); |
| 4102 old_attributes = lookup.GetAttributes(); | 4113 old_attributes = lookup.GetAttributes(); |
| 4103 } | 4114 } |
| 4104 | 4115 |
| 4105 // Check of IsReadOnly removed from here in clone. | 4116 // Check of IsReadOnly removed from here in clone. |
| 4106 MaybeObject* result = *value; | 4117 MaybeObject* result = *value; |
| 4107 switch (lookup.type()) { | 4118 switch (lookup.type()) { |
| 4108 case NORMAL: { | 4119 case NORMAL: |
| 4109 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 4120 result = self->ReplaceSlowProperty(*name, *value, attributes); |
| 4110 result = self->SetNormalizedProperty(*name, *value, details); | |
| 4111 break; | 4121 break; |
| 4112 } | |
| 4113 case FIELD: | 4122 case FIELD: |
| 4114 if (value->IsUninitialized()) break; | 4123 result = SetPropertyToFieldWithAttributes( |
| 4115 result = SetPropertyToField(&lookup, name, value); | 4124 &lookup, name, value, attributes); |
| 4116 break; | 4125 break; |
| 4117 case CONSTANT: | 4126 case CONSTANT: |
| 4118 // Only replace the constant if necessary. | 4127 // Only replace the constant if necessary. |
| 4119 if (*value == lookup.GetConstant()) return *value; | 4128 if (lookup.GetAttributes() == attributes && |
| 4120 if (value->IsUninitialized()) break; | 4129 *value == lookup.GetConstant()) { |
| 4121 result = SetPropertyToField(&lookup, name, value); | 4130 break; |
|
rossberg
2013/08/26 15:13:39
Nit: use if-else instead
Toon Verwaest
2013/08/26 15:21:27
Done.
| |
| 4131 } | |
| 4132 result = SetPropertyToFieldWithAttributes( | |
| 4133 &lookup, name, value, attributes); | |
| 4122 break; | 4134 break; |
| 4123 case CALLBACKS: | 4135 case CALLBACKS: |
| 4136 // Callbacks are not guaranteed to be installed on the receiver. Also | |
| 4137 // perform a local lookup again. Fall through. | |
| 4124 case INTERCEPTOR: | 4138 case INTERCEPTOR: |
| 4125 // Override callback in clone | 4139 self->LocalLookupRealNamedProperty(*name, &lookup); |
| 4126 result = self->ConvertDescriptorToField(*name, *value, attributes); | 4140 if (lookup.IsFound()) { |
| 4141 if (lookup.IsPropertyCallbacks()) { | |
| 4142 result = ConvertAndSetLocalProperty( | |
| 4143 &lookup, *name, *value, attributes); | |
| 4144 } else if (lookup.IsNormal()) { | |
| 4145 result = self->ReplaceSlowProperty(*name, *value, attributes); | |
| 4146 } else { | |
| 4147 result = SetPropertyToFieldWithAttributes( | |
| 4148 &lookup, name, value, attributes); | |
| 4149 } | |
| 4150 } else { | |
| 4151 result = self->AddProperty( | |
| 4152 *name, *value, attributes, kNonStrictMode, MAY_BE_STORE_FROM_KEYED, | |
| 4153 extensibility_check, value_type, mode); | |
| 4154 } | |
| 4127 break; | 4155 break; |
| 4128 case TRANSITION: | 4156 case TRANSITION: |
| 4129 result = SetPropertyUsingTransition(&lookup, name, value, attributes); | 4157 result = SetPropertyUsingTransition(&lookup, name, value, attributes); |
| 4130 break; | 4158 break; |
| 4131 case HANDLER: | 4159 case HANDLER: |
| 4132 case NONEXISTENT: | 4160 case NONEXISTENT: |
| 4133 UNREACHABLE(); | 4161 UNREACHABLE(); |
| 4134 } | 4162 } |
| 4135 | 4163 |
| 4136 Handle<Object> hresult; | 4164 Handle<Object> hresult; |
| (...skipping 11845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15982 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16010 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 15983 static const char* error_messages_[] = { | 16011 static const char* error_messages_[] = { |
| 15984 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16012 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 15985 }; | 16013 }; |
| 15986 #undef ERROR_MESSAGES_TEXTS | 16014 #undef ERROR_MESSAGES_TEXTS |
| 15987 return error_messages_[reason]; | 16015 return error_messages_[reason]; |
| 15988 } | 16016 } |
| 15989 | 16017 |
| 15990 | 16018 |
| 15991 } } // namespace v8::internal | 16019 } } // namespace v8::internal |
| OLD | NEW |