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 1954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1965 static Handle<Object> NewStorageFor(Isolate* isolate, | 1965 static Handle<Object> NewStorageFor(Isolate* isolate, |
| 1966 Handle<Object> object, | 1966 Handle<Object> object, |
| 1967 Representation representation) { | 1967 Representation representation) { |
| 1968 Heap* heap = isolate->heap(); | 1968 Heap* heap = isolate->heap(); |
| 1969 CALL_HEAP_FUNCTION(isolate, | 1969 CALL_HEAP_FUNCTION(isolate, |
| 1970 object->AllocateNewStorageFor(heap, representation), | 1970 object->AllocateNewStorageFor(heap, representation), |
| 1971 Object); | 1971 Object); |
| 1972 } | 1972 } |
| 1973 | 1973 |
| 1974 | 1974 |
| 1975 static MaybeObject* CopyAddFieldDescriptor(Map* map, | 1975 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, |
| 1976 Name* name, | 1976 Handle<Name> name, |
| 1977 int index, | 1977 int index, |
| 1978 PropertyAttributes attributes, | 1978 PropertyAttributes attributes, |
| 1979 Representation representation, | 1979 Representation representation, |
| 1980 TransitionFlag flag) { | 1980 TransitionFlag flag) { |
| 1981 Map* new_map; | |
| 1982 FieldDescriptor new_field_desc(name, index, attributes, representation); | 1981 FieldDescriptor new_field_desc(name, index, attributes, representation); |
| 1983 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); | 1982 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); |
| 1984 if (!maybe_map->To(&new_map)) return maybe_map; | |
| 1985 int unused_property_fields = map->unused_property_fields() - 1; | 1983 int unused_property_fields = map->unused_property_fields() - 1; |
| 1986 if (unused_property_fields < 0) { | 1984 if (unused_property_fields < 0) { |
| 1987 unused_property_fields += JSObject::kFieldsAdded; | 1985 unused_property_fields += JSObject::kFieldsAdded; |
| 1988 } | 1986 } |
| 1989 new_map->set_unused_property_fields(unused_property_fields); | 1987 new_map->set_unused_property_fields(unused_property_fields); |
| 1990 return new_map; | 1988 return new_map; |
| 1991 } | 1989 } |
| 1992 | 1990 |
| 1993 | 1991 |
| 1994 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, | |
| 1995 Handle<Name> name, | |
| 1996 int index, | |
| 1997 PropertyAttributes attributes, | |
| 1998 Representation representation, | |
| 1999 TransitionFlag flag) { | |
| 2000 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
| 2001 CopyAddFieldDescriptor( | |
| 2002 *map, *name, index, attributes, representation, flag), | |
| 2003 Map); | |
| 2004 } | |
| 2005 | |
| 2006 | |
| 2007 void JSObject::AddFastProperty(Handle<JSObject> object, | 1992 void JSObject::AddFastProperty(Handle<JSObject> object, |
| 2008 Handle<Name> name, | 1993 Handle<Name> name, |
| 2009 Handle<Object> value, | 1994 Handle<Object> value, |
| 2010 PropertyAttributes attributes, | 1995 PropertyAttributes attributes, |
| 2011 StoreFromKeyed store_mode, | 1996 StoreFromKeyed store_mode, |
| 2012 ValueType value_type, | 1997 ValueType value_type, |
| 2013 TransitionFlag flag) { | 1998 TransitionFlag flag) { |
| 2014 ASSERT(!object->IsJSGlobalProxy()); | 1999 ASSERT(!object->IsJSGlobalProxy()); |
| 2015 ASSERT(DescriptorArray::kNotFound == | 2000 ASSERT(DescriptorArray::kNotFound == |
| 2016 object->map()->instance_descriptors()->Search( | 2001 object->map()->instance_descriptors()->Search( |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2042 // Nothing more to be done. | 2027 // Nothing more to be done. |
| 2043 if (value->IsUninitialized()) return; | 2028 if (value->IsUninitialized()) return; |
| 2044 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); | 2029 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); |
| 2045 box->set_value(value->Number()); | 2030 box->set_value(value->Number()); |
| 2046 } else { | 2031 } else { |
| 2047 object->FastPropertyAtPut(index, *value); | 2032 object->FastPropertyAtPut(index, *value); |
| 2048 } | 2033 } |
| 2049 } | 2034 } |
| 2050 | 2035 |
| 2051 | 2036 |
| 2052 static MaybeObject* CopyAddConstantDescriptor(Map* map, | |
| 2053 Name* name, | |
| 2054 Object* value, | |
| 2055 PropertyAttributes attributes, | |
| 2056 TransitionFlag flag) { | |
| 2057 ConstantDescriptor new_constant_desc(name, value, attributes); | |
| 2058 return map->CopyAddDescriptor(&new_constant_desc, flag); | |
| 2059 } | |
| 2060 | |
| 2061 | |
| 2062 static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map, | 2037 static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map, |
| 2063 Handle<Name> name, | 2038 Handle<Name> name, |
| 2064 Handle<Object> value, | 2039 Handle<Object> value, |
| 2065 PropertyAttributes attributes, | 2040 PropertyAttributes attributes, |
| 2066 TransitionFlag flag) { | 2041 TransitionFlag flag) { |
| 2067 CALL_HEAP_FUNCTION(map->GetIsolate(), | 2042 ConstantDescriptor new_constant_desc(name, value, attributes); |
| 2068 CopyAddConstantDescriptor( | 2043 return Map::CopyAddDescriptor(map, &new_constant_desc, flag); |
| 2069 *map, *name, *value, attributes, flag), | |
| 2070 Map); | |
| 2071 } | 2044 } |
| 2072 | 2045 |
| 2073 | 2046 |
| 2074 void JSObject::AddConstantProperty(Handle<JSObject> object, | 2047 void JSObject::AddConstantProperty(Handle<JSObject> object, |
| 2075 Handle<Name> name, | 2048 Handle<Name> name, |
| 2076 Handle<Object> constant, | 2049 Handle<Object> constant, |
| 2077 PropertyAttributes attributes, | 2050 PropertyAttributes attributes, |
| 2078 TransitionFlag initial_flag) { | 2051 TransitionFlag initial_flag) { |
| 2079 TransitionFlag flag = | 2052 TransitionFlag flag = |
| 2080 // Do not add transitions to global objects. | 2053 // Do not add transitions to global objects. |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2353 ASSERT(target_inobject < inobject_properties()); | 2326 ASSERT(target_inobject < inobject_properties()); |
| 2354 if (target_number_of_fields <= target_inobject) { | 2327 if (target_number_of_fields <= target_inobject) { |
| 2355 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2328 ASSERT(target_number_of_fields + target_unused == target_inobject); |
| 2356 return false; | 2329 return false; |
| 2357 } | 2330 } |
| 2358 // Otherwise, properties will need to be moved to the backing store. | 2331 // Otherwise, properties will need to be moved to the backing store. |
| 2359 return true; | 2332 return true; |
| 2360 } | 2333 } |
| 2361 | 2334 |
| 2362 | 2335 |
| 2336 Handle<TransitionArray> Map::SetElementsTransitionMap( | |
| 2337 Handle<Map> map, Handle<Map> transitioned_map) { | |
| 2338 Handle<TransitionArray> transitions = map->AddTransition( | |
| 2339 map, | |
| 2340 map->GetIsolate()->factory()->elements_transition_symbol(), | |
| 2341 transitioned_map, | |
| 2342 FULL_TRANSITION); | |
| 2343 map->set_transitions(*transitions); | |
| 2344 return transitions; | |
| 2345 } | |
| 2346 | |
| 2347 | |
| 2363 // To migrate an instance to a map: | 2348 // To migrate an instance to a map: |
| 2364 // - First check whether the instance needs to be rewritten. If not, simply | 2349 // - First check whether the instance needs to be rewritten. If not, simply |
| 2365 // change the map. | 2350 // change the map. |
| 2366 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2351 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
| 2367 // addition to unused space. | 2352 // addition to unused space. |
| 2368 // - Copy all existing properties in, in the following order: backing store | 2353 // - Copy all existing properties in, in the following order: backing store |
| 2369 // properties, unused fields, inobject properties. | 2354 // properties, unused fields, inobject properties. |
| 2370 // - If all allocation succeeded, commit the state atomically: | 2355 // - If all allocation succeeded, commit the state atomically: |
| 2371 // * Copy inobject properties from the backing store back into the object. | 2356 // * Copy inobject properties from the backing store back into the object. |
| 2372 // * Trim the difference in instance size of the object. This also cleanly | 2357 // * Trim the difference in instance size of the object. This also cleanly |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2477 // thread can not get confused with the filler creation. No synchronization | 2462 // thread can not get confused with the filler creation. No synchronization |
| 2478 // needed. | 2463 // needed. |
| 2479 object->set_map(*new_map); | 2464 object->set_map(*new_map); |
| 2480 } | 2465 } |
| 2481 | 2466 |
| 2482 | 2467 |
| 2483 Handle<TransitionArray> Map::AddTransition(Handle<Map> map, | 2468 Handle<TransitionArray> Map::AddTransition(Handle<Map> map, |
| 2484 Handle<Name> key, | 2469 Handle<Name> key, |
| 2485 Handle<Map> target, | 2470 Handle<Map> target, |
| 2486 SimpleTransitionFlag flag) { | 2471 SimpleTransitionFlag flag) { |
| 2487 CALL_HEAP_FUNCTION(map->GetIsolate(), | 2472 if (map->HasTransitionArray()) { |
| 2488 map->AddTransition(*key, *target, flag), | 2473 Handle<TransitionArray> transitions = handle(map->transitions()); |
| 2489 TransitionArray); | 2474 return TransitionArray::CopyInsert(transitions, key, target); |
| 2475 } | |
| 2476 return TransitionArray::NewWithHandle(flag, key, target, | |
| 2477 handle(map->GetBackPointer(), | |
| 2478 map->GetIsolate())); | |
| 2490 } | 2479 } |
| 2491 | 2480 |
| 2492 | 2481 |
| 2493 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2482 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
| 2494 int modify_index, | 2483 int modify_index, |
| 2495 Representation new_representation, | 2484 Representation new_representation, |
| 2496 StoreMode store_mode) { | 2485 StoreMode store_mode) { |
| 2497 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2486 Handle<Map> new_map = Map::GeneralizeRepresentation( |
| 2498 handle(object->map()), modify_index, new_representation, store_mode); | 2487 handle(object->map()), modify_index, new_representation, store_mode); |
| 2499 if (object->map() == *new_map) return; | 2488 if (object->map() == *new_map) return; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2517 PropertyAttributes attributes, | 2506 PropertyAttributes attributes, |
| 2518 const char* reason) { | 2507 const char* reason) { |
| 2519 Handle<Map> new_map = Copy(map); | 2508 Handle<Map> new_map = Copy(map); |
| 2520 | 2509 |
| 2521 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2510 DescriptorArray* descriptors = new_map->instance_descriptors(); |
| 2522 descriptors->InitializeRepresentations(Representation::Tagged()); | 2511 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 2523 | 2512 |
| 2524 // Unless the instance is being migrated, ensure that modify_index is a field. | 2513 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2525 PropertyDetails details = descriptors->GetDetails(modify_index); | 2514 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2526 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2515 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
| 2527 FieldDescriptor d(descriptors->GetKey(modify_index), | 2516 FieldDescriptor d(handle(descriptors->GetKey(modify_index), |
| 2517 map->GetIsolate()), | |
| 2528 new_map->NumberOfFields(), | 2518 new_map->NumberOfFields(), |
| 2529 attributes, | 2519 attributes, |
| 2530 Representation::Tagged()); | 2520 Representation::Tagged()); |
| 2531 d.SetSortedKeyIndex(details.pointer()); | 2521 d.SetSortedKeyIndex(details.pointer()); |
| 2532 descriptors->Set(modify_index, &d); | 2522 descriptors->Set(modify_index, &d); |
| 2533 int unused_property_fields = new_map->unused_property_fields() - 1; | 2523 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2534 if (unused_property_fields < 0) { | 2524 if (unused_property_fields < 0) { |
| 2535 unused_property_fields += JSObject::kFieldsAdded; | 2525 unused_property_fields += JSObject::kFieldsAdded; |
| 2536 } | 2526 } |
| 2537 new_map->set_unused_property_fields(unused_property_fields); | 2527 new_map->set_unused_property_fields(unused_property_fields); |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3153 } | 3143 } |
| 3154 | 3144 |
| 3155 struct DescriptorArrayAppender { | 3145 struct DescriptorArrayAppender { |
| 3156 typedef DescriptorArray Array; | 3146 typedef DescriptorArray Array; |
| 3157 static bool Contains(Name* key, | 3147 static bool Contains(Name* key, |
| 3158 AccessorInfo* entry, | 3148 AccessorInfo* entry, |
| 3159 int valid_descriptors, | 3149 int valid_descriptors, |
| 3160 Handle<DescriptorArray> array) { | 3150 Handle<DescriptorArray> array) { |
| 3161 return array->Search(key, valid_descriptors) != DescriptorArray::kNotFound; | 3151 return array->Search(key, valid_descriptors) != DescriptorArray::kNotFound; |
| 3162 } | 3152 } |
| 3163 static void Insert(Name* key, | 3153 static void Insert(Name* key, |
|
Toon Verwaest
2014/04/08 12:58:55
Can't call from unhandlified into handlified code!
mvstanton
2014/04/09 09:43:20
Fixed.
| |
| 3164 AccessorInfo* entry, | 3154 AccessorInfo* entry, |
| 3165 int valid_descriptors, | 3155 int valid_descriptors, |
| 3166 Handle<DescriptorArray> array) { | 3156 Handle<DescriptorArray> array) { |
| 3167 CallbacksDescriptor desc(key, entry, entry->property_attributes()); | 3157 CallbacksDescriptor desc(handle(key, array->GetIsolate()), |
| 3158 handle(entry, array->GetIsolate()), | |
| 3159 entry->property_attributes()); | |
| 3168 array->Append(&desc); | 3160 array->Append(&desc); |
| 3169 } | 3161 } |
| 3170 }; | 3162 }; |
| 3171 | 3163 |
| 3172 | 3164 |
| 3173 struct FixedArrayAppender { | 3165 struct FixedArrayAppender { |
| 3174 typedef FixedArray Array; | 3166 typedef FixedArray Array; |
| 3175 static bool Contains(Name* key, | 3167 static bool Contains(Name* key, |
| 3176 AccessorInfo* entry, | 3168 AccessorInfo* entry, |
| 3177 int valid_descriptors, | 3169 int valid_descriptors, |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3296 } | 3288 } |
| 3297 | 3289 |
| 3298 if (isolate->initial_object_prototype()->map() == this) { | 3290 if (isolate->initial_object_prototype()->map() == this) { |
| 3299 return true; | 3291 return true; |
| 3300 } | 3292 } |
| 3301 | 3293 |
| 3302 return false; | 3294 return false; |
| 3303 } | 3295 } |
| 3304 | 3296 |
| 3305 | 3297 |
| 3306 static MaybeObject* AddMissingElementsTransitions(Map* map, | 3298 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, |
| 3307 ElementsKind to_kind) { | 3299 ElementsKind to_kind) { |
| 3308 ASSERT(IsTransitionElementsKind(map->elements_kind())); | 3300 ASSERT(IsTransitionElementsKind(map->elements_kind())); |
| 3309 | 3301 |
| 3310 Map* current_map = map; | 3302 Handle<Map> current_map = map; |
| 3311 | 3303 |
| 3312 ElementsKind kind = map->elements_kind(); | 3304 ElementsKind kind = map->elements_kind(); |
| 3313 while (kind != to_kind && !IsTerminalElementsKind(kind)) { | 3305 while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
| 3314 kind = GetNextTransitionElementsKind(kind); | 3306 kind = GetNextTransitionElementsKind(kind); |
| 3315 MaybeObject* maybe_next_map = | 3307 current_map = Map::CopyAsElementsKind(current_map, kind, |
| 3316 current_map->CopyAsElementsKind(kind, INSERT_TRANSITION); | 3308 INSERT_TRANSITION); |
| 3317 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | |
| 3318 } | 3309 } |
| 3319 | 3310 |
| 3320 // In case we are exiting the fast elements kind system, just add the map in | 3311 // In case we are exiting the fast elements kind system, just add the map in |
| 3321 // the end. | 3312 // the end. |
| 3322 if (kind != to_kind) { | 3313 if (kind != to_kind) { |
| 3323 MaybeObject* maybe_next_map = | 3314 current_map = Map::CopyAsElementsKind(current_map, to_kind, |
| 3324 current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION); | 3315 INSERT_TRANSITION); |
| 3325 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | |
| 3326 } | 3316 } |
| 3327 | 3317 |
| 3328 ASSERT(current_map->elements_kind() == to_kind); | 3318 ASSERT(current_map->elements_kind() == to_kind); |
| 3329 return current_map; | 3319 return current_map; |
| 3330 } | 3320 } |
| 3331 | 3321 |
| 3332 | 3322 |
| 3333 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, | 3323 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
| 3334 ElementsKind to_kind) { | 3324 ElementsKind to_kind) { |
| 3335 Isolate* isolate = object->GetIsolate(); | 3325 Isolate* isolate = object->GetIsolate(); |
| 3336 CALL_HEAP_FUNCTION(isolate, | 3326 Handle<Map> current_map = handle(object->map()); |
| 3337 object->GetElementsTransitionMap(isolate, to_kind), | 3327 ElementsKind from_kind = current_map->elements_kind(); |
| 3338 Map); | 3328 if (from_kind == to_kind) return current_map; |
| 3329 | |
|
Toon Verwaest
2014/04/08 12:58:55
DisallowHeapAllocation?
mvstanton
2014/04/09 09:43:20
Done.
| |
| 3330 Context* native_context = isolate->context()->native_context(); | |
| 3331 Object* maybe_array_maps = native_context->js_array_maps(); | |
| 3332 if (maybe_array_maps->IsFixedArray()) { | |
| 3333 FixedArray* array_maps = FixedArray::cast(maybe_array_maps); | |
| 3334 if (array_maps->get(from_kind) == *current_map) { | |
| 3335 Object* maybe_transitioned_map = array_maps->get(to_kind); | |
| 3336 if (maybe_transitioned_map->IsMap()) { | |
| 3337 return handle(Map::cast(maybe_transitioned_map)); | |
| 3338 } | |
| 3339 } | |
| 3340 } | |
| 3341 | |
| 3342 return GetElementsTransitionMapSlow(object, to_kind); | |
| 3339 } | 3343 } |
| 3340 | 3344 |
| 3341 | 3345 |
| 3342 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) { | 3346 Handle<Map> JSObject::GetElementsTransitionMapSlow(Handle<JSObject> object, |
| 3343 Map* start_map = map(); | 3347 ElementsKind to_kind) { |
| 3348 Handle<Map> start_map = handle(object->map()); | |
| 3344 ElementsKind from_kind = start_map->elements_kind(); | 3349 ElementsKind from_kind = start_map->elements_kind(); |
| 3345 | 3350 |
| 3346 if (from_kind == to_kind) { | 3351 if (from_kind == to_kind) { |
| 3347 return start_map; | 3352 return start_map; |
| 3348 } | 3353 } |
| 3349 | 3354 |
| 3350 bool allow_store_transition = | 3355 bool allow_store_transition = |
| 3351 // Only remember the map transition if there is not an already existing | 3356 // Only remember the map transition if there is not an already existing |
| 3352 // non-matching element transition. | 3357 // non-matching element transition. |
| 3353 !start_map->IsUndefined() && !start_map->is_shared() && | 3358 !start_map->IsUndefined() && !start_map->is_shared() && |
| 3354 IsTransitionElementsKind(from_kind); | 3359 IsTransitionElementsKind(from_kind); |
| 3355 | 3360 |
| 3356 // Only store fast element maps in ascending generality. | 3361 // Only store fast element maps in ascending generality. |
| 3357 if (IsFastElementsKind(to_kind)) { | 3362 if (IsFastElementsKind(to_kind)) { |
| 3358 allow_store_transition &= | 3363 allow_store_transition &= |
| 3359 IsTransitionableFastElementsKind(from_kind) && | 3364 IsTransitionableFastElementsKind(from_kind) && |
| 3360 IsMoreGeneralElementsKindTransition(from_kind, to_kind); | 3365 IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
| 3361 } | 3366 } |
| 3362 | 3367 |
| 3363 if (!allow_store_transition) { | 3368 if (!allow_store_transition) { |
| 3364 return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION); | 3369 return Map::CopyAsElementsKind(start_map, to_kind, OMIT_TRANSITION); |
| 3365 } | 3370 } |
| 3366 | 3371 |
| 3367 return start_map->AsElementsKind(to_kind); | 3372 return Map::AsElementsKind(start_map, to_kind); |
| 3368 } | 3373 } |
| 3369 | 3374 |
| 3370 | 3375 |
| 3371 // TODO(ishell): Temporary wrapper until handlified. | |
| 3372 // static | 3376 // static |
| 3373 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { | 3377 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { |
| 3374 CALL_HEAP_FUNCTION(map->GetIsolate(), | 3378 Handle<Map> closest_map = handle(FindClosestElementsTransition(*map, kind)); |
| 3375 map->AsElementsKind(kind), | |
| 3376 Map); | |
| 3377 } | |
| 3378 | |
| 3379 | |
| 3380 MaybeObject* Map::AsElementsKind(ElementsKind kind) { | |
| 3381 Map* closest_map = FindClosestElementsTransition(this, kind); | |
| 3382 | 3379 |
| 3383 if (closest_map->elements_kind() == kind) { | 3380 if (closest_map->elements_kind() == kind) { |
| 3384 return closest_map; | 3381 return closest_map; |
| 3385 } | 3382 } |
| 3386 | 3383 |
| 3387 return AddMissingElementsTransitions(closest_map, kind); | 3384 return AddMissingElementsTransitions(closest_map, kind); |
| 3388 } | 3385 } |
| 3389 | 3386 |
| 3390 | 3387 |
| 3391 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { | 3388 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3832 return Handle<Object>(); | 3829 return Handle<Object>(); |
| 3833 } | 3830 } |
| 3834 trap = Handle<Object>(derived); | 3831 trap = Handle<Object>(derived); |
| 3835 } | 3832 } |
| 3836 | 3833 |
| 3837 bool threw; | 3834 bool threw; |
| 3838 return Execution::Call(isolate, trap, handler, argc, argv, &threw); | 3835 return Execution::Call(isolate, trap, handler, argc, argv, &threw); |
| 3839 } | 3836 } |
| 3840 | 3837 |
| 3841 | 3838 |
| 3842 // TODO(mstarzinger): Temporary wrapper until handlified. | |
| 3843 static Handle<Map> MapAsElementsKind(Handle<Map> map, ElementsKind kind) { | |
| 3844 CALL_HEAP_FUNCTION(map->GetIsolate(), map->AsElementsKind(kind), Map); | |
| 3845 } | |
| 3846 | |
| 3847 | |
| 3848 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { | 3839 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
| 3849 ASSERT(object->map()->inobject_properties() == map->inobject_properties()); | 3840 ASSERT(object->map()->inobject_properties() == map->inobject_properties()); |
| 3850 ElementsKind obj_kind = object->map()->elements_kind(); | 3841 ElementsKind obj_kind = object->map()->elements_kind(); |
| 3851 ElementsKind map_kind = map->elements_kind(); | 3842 ElementsKind map_kind = map->elements_kind(); |
| 3852 if (map_kind != obj_kind) { | 3843 if (map_kind != obj_kind) { |
| 3853 ElementsKind to_kind = map_kind; | 3844 ElementsKind to_kind = map_kind; |
| 3854 if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) || | 3845 if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) || |
| 3855 IsDictionaryElementsKind(obj_kind)) { | 3846 IsDictionaryElementsKind(obj_kind)) { |
| 3856 to_kind = obj_kind; | 3847 to_kind = obj_kind; |
| 3857 } | 3848 } |
| 3858 if (IsDictionaryElementsKind(to_kind)) { | 3849 if (IsDictionaryElementsKind(to_kind)) { |
| 3859 NormalizeElements(object); | 3850 NormalizeElements(object); |
| 3860 } else { | 3851 } else { |
| 3861 TransitionElementsKind(object, to_kind); | 3852 TransitionElementsKind(object, to_kind); |
| 3862 } | 3853 } |
| 3863 map = MapAsElementsKind(map, to_kind); | 3854 map = Map::AsElementsKind(map, to_kind); |
| 3864 } | 3855 } |
| 3865 JSObject::MigrateToMap(object, map); | 3856 JSObject::MigrateToMap(object, map); |
| 3866 } | 3857 } |
| 3867 | 3858 |
| 3868 | 3859 |
| 3869 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3860 void JSObject::MigrateInstance(Handle<JSObject> object) { |
| 3870 // Converting any field to the most specific type will cause the | 3861 // Converting any field to the most specific type will cause the |
| 3871 // GeneralizeFieldRepresentation algorithm to create the most general existing | 3862 // GeneralizeFieldRepresentation algorithm to create the most general existing |
| 3872 // transition that matches the object. This achieves what is needed. | 3863 // transition that matches the object. This achieves what is needed. |
| 3873 Handle<Map> original_map(object->map()); | 3864 Handle<Map> original_map(object->map()); |
| (...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4692 if (object->HasFastProperties()) return; | 4683 if (object->HasFastProperties()) return; |
| 4693 ASSERT(!object->IsGlobalObject()); | 4684 ASSERT(!object->IsGlobalObject()); |
| 4694 CALL_HEAP_FUNCTION_VOID( | 4685 CALL_HEAP_FUNCTION_VOID( |
| 4695 object->GetIsolate(), | 4686 object->GetIsolate(), |
| 4696 object->property_dictionary()->TransformPropertiesToFastFor( | 4687 object->property_dictionary()->TransformPropertiesToFastFor( |
| 4697 *object, unused_property_fields)); | 4688 *object, unused_property_fields)); |
| 4698 } | 4689 } |
| 4699 | 4690 |
| 4700 | 4691 |
| 4701 void JSObject::ResetElements(Handle<JSObject> object) { | 4692 void JSObject::ResetElements(Handle<JSObject> object) { |
| 4702 CALL_HEAP_FUNCTION_VOID( | 4693 if (object->map()->is_observed()) { |
| 4703 object->GetIsolate(), | 4694 // Maintain invariant that observed elements are always in dictionary mode. |
| 4704 object->ResetElements()); | 4695 Factory* factory = object->GetIsolate()->factory(); |
| 4696 Handle<SeededNumberDictionary> dictionary = | |
| 4697 factory->NewSeededNumberDictionary(0); | |
| 4698 if (object->map() == *factory->sloppy_arguments_elements_map()) { | |
| 4699 FixedArray::cast(object->elements())->set(1, *dictionary); | |
| 4700 } else { | |
| 4701 object->set_elements(*dictionary); | |
| 4702 } | |
| 4703 return; | |
| 4704 } | |
| 4705 | |
| 4706 ElementsKind elements_kind = GetInitialFastElementsKind(); | |
| 4707 if (!FLAG_smi_only_arrays) { | |
| 4708 elements_kind = FastSmiToObjectElementsKind(elements_kind); | |
| 4709 } | |
| 4710 Handle<Map> map = JSObject::GetElementsTransitionMap(object, elements_kind); | |
| 4711 object->set_map(*map); | |
|
Toon Verwaest
2014/04/08 12:58:55
JSObject::SetMapAndElements
mvstanton
2014/04/09 09:43:20
But initialize_elements() contains detailed logic
| |
| 4712 object->initialize_elements(); | |
| 4705 } | 4713 } |
| 4706 | 4714 |
| 4707 | 4715 |
| 4708 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( | 4716 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( |
| 4709 Handle<FixedArrayBase> array, | 4717 Handle<FixedArrayBase> array, |
| 4710 int length, | 4718 int length, |
| 4711 Handle<SeededNumberDictionary> dictionary) { | 4719 Handle<SeededNumberDictionary> dictionary) { |
| 4712 Isolate* isolate = array->GetIsolate(); | 4720 Isolate* isolate = array->GetIsolate(); |
| 4713 Factory* factory = isolate->factory(); | 4721 Factory* factory = isolate->factory(); |
| 4714 bool has_double_elements = array->IsFixedDoubleArray(); | 4722 bool has_double_elements = array->IsFixedDoubleArray(); |
| (...skipping 1707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6422 JSObject::MigrateToMap(self, transitioned_map); | 6430 JSObject::MigrateToMap(self, transitioned_map); |
| 6423 return true; | 6431 return true; |
| 6424 } | 6432 } |
| 6425 | 6433 |
| 6426 // If either not the same accessor, or not the same attributes, fall back to | 6434 // If either not the same accessor, or not the same attributes, fall back to |
| 6427 // the slow case. | 6435 // the slow case. |
| 6428 return false; | 6436 return false; |
| 6429 } | 6437 } |
| 6430 | 6438 |
| 6431 | 6439 |
| 6432 static MaybeObject* CopyInsertDescriptor(Map* map, | |
| 6433 Name* name, | |
| 6434 AccessorPair* accessors, | |
| 6435 PropertyAttributes attributes) { | |
| 6436 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); | |
| 6437 return map->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION); | |
| 6438 } | |
| 6439 | |
| 6440 | |
| 6441 static Handle<Map> CopyInsertDescriptor(Handle<Map> map, | 6440 static Handle<Map> CopyInsertDescriptor(Handle<Map> map, |
| 6442 Handle<Name> name, | 6441 Handle<Name> name, |
| 6443 Handle<AccessorPair> accessors, | 6442 Handle<AccessorPair> accessors, |
| 6444 PropertyAttributes attributes) { | 6443 PropertyAttributes attributes) { |
| 6445 CALL_HEAP_FUNCTION(map->GetIsolate(), | 6444 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); |
| 6446 CopyInsertDescriptor(*map, *name, *accessors, attributes), | 6445 return Map::CopyInsertDescriptor(map, &new_accessors_desc, INSERT_TRANSITION); |
| 6447 Map); | |
| 6448 } | 6446 } |
| 6449 | 6447 |
| 6450 | 6448 |
| 6451 bool JSObject::DefineFastAccessor(Handle<JSObject> object, | 6449 bool JSObject::DefineFastAccessor(Handle<JSObject> object, |
| 6452 Handle<Name> name, | 6450 Handle<Name> name, |
| 6453 AccessorComponent component, | 6451 AccessorComponent component, |
| 6454 Handle<Object> accessor, | 6452 Handle<Object> accessor, |
| 6455 PropertyAttributes attributes) { | 6453 PropertyAttributes attributes) { |
| 6456 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); | 6454 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); |
| 6457 Isolate* isolate = object->GetIsolate(); | 6455 Isolate* isolate = object->GetIsolate(); |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6764 result->set_unused_property_fields(unused_property_fields()); | 6762 result->set_unused_property_fields(unused_property_fields()); |
| 6765 | 6763 |
| 6766 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); | 6764 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
| 6767 result->set_is_shared(false); | 6765 result->set_is_shared(false); |
| 6768 result->ClearCodeCache(GetHeap()); | 6766 result->ClearCodeCache(GetHeap()); |
| 6769 NotifyLeafMapLayoutChange(); | 6767 NotifyLeafMapLayoutChange(); |
| 6770 return result; | 6768 return result; |
| 6771 } | 6769 } |
| 6772 | 6770 |
| 6773 | 6771 |
| 6774 MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors, | 6772 Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
| 6775 Descriptor* descriptor) { | 6773 Handle<DescriptorArray> descriptors, |
| 6774 Descriptor* descriptor) { | |
| 6776 // Sanity check. This path is only to be taken if the map owns its descriptor | 6775 // Sanity check. This path is only to be taken if the map owns its descriptor |
| 6777 // array, implying that its NumberOfOwnDescriptors equals the number of | 6776 // array, implying that its NumberOfOwnDescriptors equals the number of |
| 6778 // descriptors in the descriptor array. | 6777 // descriptors in the descriptor array. |
| 6779 ASSERT(NumberOfOwnDescriptors() == | 6778 ASSERT(map->NumberOfOwnDescriptors() == |
| 6780 instance_descriptors()->number_of_descriptors()); | 6779 map->instance_descriptors()->number_of_descriptors()); |
| 6781 Map* result; | 6780 Handle<Map> result = Map::CopyDropDescriptors(map); |
| 6782 MaybeObject* maybe_result = CopyDropDescriptors(); | |
| 6783 if (!maybe_result->To(&result)) return maybe_result; | |
| 6784 | 6781 |
| 6785 Name* name = descriptor->GetKey(); | 6782 Handle<Name> name = descriptor->GetKey(); |
| 6786 | 6783 |
| 6787 TransitionArray* transitions; | 6784 Handle<TransitionArray> transitions = |
| 6788 MaybeObject* maybe_transitions = | 6785 Map::AddTransition(map, name, result, SIMPLE_TRANSITION); |
| 6789 AddTransition(name, result, SIMPLE_TRANSITION); | |
| 6790 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
| 6791 | 6786 |
| 6792 int old_size = descriptors->number_of_descriptors(); | 6787 int old_size = descriptors->number_of_descriptors(); |
| 6793 | 6788 |
| 6794 DescriptorArray* new_descriptors; | 6789 Handle<DescriptorArray> new_descriptors; |
| 6795 | 6790 |
| 6796 if (descriptors->NumberOfSlackDescriptors() > 0) { | 6791 if (descriptors->NumberOfSlackDescriptors() > 0) { |
| 6797 new_descriptors = descriptors; | 6792 new_descriptors = descriptors; |
| 6798 new_descriptors->Append(descriptor); | 6793 new_descriptors->Append(descriptor); |
|
Toon Verwaest
2014/04/08 12:58:55
We cannot GC anymore after this has happened. Othe
mvstanton
2014/04/09 09:43:20
Okay, I re-ordered things for the desired effect.
| |
| 6799 } else { | 6794 } else { |
| 6800 // Descriptor arrays grow by 50%. | 6795 // Descriptor arrays grow by 50%. |
| 6801 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( | 6796 new_descriptors = map->GetIsolate()->factory()->NewDescriptorArray( |
| 6802 GetIsolate(), old_size, old_size < 4 ? 1 : old_size / 2); | 6797 old_size, old_size < 4 ? 1 : old_size / 2); |
| 6803 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 6804 | 6798 |
| 6805 DescriptorArray::WhitenessWitness witness(new_descriptors); | 6799 DescriptorArray::WhitenessWitness witness(*new_descriptors); |
| 6806 | 6800 |
| 6807 // Copy the descriptors, inserting a descriptor. | 6801 // Copy the descriptors, inserting a descriptor. |
| 6808 for (int i = 0; i < old_size; ++i) { | 6802 for (int i = 0; i < old_size; ++i) { |
| 6809 new_descriptors->CopyFrom(i, descriptors, i, witness); | 6803 new_descriptors->CopyFrom(i, *descriptors, i, witness); |
| 6810 } | 6804 } |
| 6811 | 6805 |
| 6812 new_descriptors->Append(descriptor, witness); | 6806 new_descriptors->Append(descriptor, witness); |
| 6813 | 6807 |
| 6814 if (old_size > 0) { | 6808 if (old_size > 0) { |
| 6815 // If the source descriptors had an enum cache we copy it. This ensures | 6809 // If the source descriptors had an enum cache we copy it. This ensures |
| 6816 // that the maps to which we push the new descriptor array back can rely | 6810 // that the maps to which we push the new descriptor array back can rely |
| 6817 // on a cache always being available once it is set. If the map has more | 6811 // on a cache always being available once it is set. If the map has more |
| 6818 // enumerated descriptors than available in the original cache, the cache | 6812 // enumerated descriptors than available in the original cache, the cache |
| 6819 // will be lazily replaced by the extended cache when needed. | 6813 // will be lazily replaced by the extended cache when needed. |
| 6820 if (descriptors->HasEnumCache()) { | 6814 if (descriptors->HasEnumCache()) { |
| 6821 new_descriptors->CopyEnumCacheFrom(descriptors); | 6815 new_descriptors->CopyEnumCacheFrom(*descriptors); |
| 6822 } | 6816 } |
| 6823 | 6817 |
| 6824 Map* map; | 6818 Map* walk_map; |
|
Toon Verwaest
2014/04/08 12:58:55
DisallowHeapAllocation no_gc from here down.
mvstanton
2014/04/09 09:43:20
I've got it above now, I think that is fine?
| |
| 6825 // Replace descriptors by new_descriptors in all maps that share it. | 6819 // Replace descriptors by new_descriptors in all maps that share it. |
| 6826 | 6820 |
| 6827 GetHeap()->incremental_marking()->RecordWrites(descriptors); | 6821 map->GetHeap()->incremental_marking()->RecordWrites(*descriptors); |
| 6828 for (Object* current = GetBackPointer(); | 6822 for (Object* current = map->GetBackPointer(); |
| 6829 !current->IsUndefined(); | 6823 !current->IsUndefined(); |
| 6830 current = map->GetBackPointer()) { | 6824 current = walk_map->GetBackPointer()) { |
| 6831 map = Map::cast(current); | 6825 walk_map = Map::cast(current); |
| 6832 if (map->instance_descriptors() != descriptors) break; | 6826 if (walk_map->instance_descriptors() != *descriptors) break; |
| 6833 map->set_instance_descriptors(new_descriptors); | 6827 walk_map->set_instance_descriptors(*new_descriptors); |
| 6834 } | 6828 } |
| 6835 | 6829 |
| 6836 set_instance_descriptors(new_descriptors); | 6830 map->set_instance_descriptors(*new_descriptors); |
| 6837 } | 6831 } |
| 6838 } | 6832 } |
| 6839 | 6833 |
| 6840 result->SetBackPointer(this); | 6834 result->SetBackPointer(*map); |
| 6841 result->InitializeDescriptors(new_descriptors); | 6835 result->InitializeDescriptors(*new_descriptors); |
| 6842 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 6836 ASSERT(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
| 6843 | 6837 |
| 6844 set_transitions(transitions); | 6838 map->set_transitions(*transitions); |
| 6845 set_owns_descriptors(false); | 6839 map->set_owns_descriptors(false); |
| 6846 | 6840 |
| 6847 return result; | 6841 return result; |
| 6848 } | 6842 } |
| 6849 | 6843 |
| 6850 | 6844 |
| 6851 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, | 6845 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
| 6852 Handle<DescriptorArray> descriptors, | 6846 Handle<DescriptorArray> descriptors, |
| 6853 TransitionFlag flag, | 6847 TransitionFlag flag, |
| 6854 Handle<Name> name) { | 6848 Handle<Name> name) { |
| 6855 CALL_HEAP_FUNCTION(map->GetIsolate(), | 6849 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6856 map->CopyReplaceDescriptors(*descriptors, flag, *name), | 6850 map->CopyReplaceDescriptorsFull(*descriptors, flag, *name), |
| 6857 Map); | 6851 Map); |
| 6858 } | 6852 } |
| 6859 | 6853 |
| 6860 | 6854 |
| 6861 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 6855 // TODO(mvstanton): Get rid of this method. |
| 6856 MaybeObject* Map::CopyReplaceDescriptorsFull(DescriptorArray* descriptors, | |
|
Toon Verwaest
2014/04/08 12:58:55
This name doesn't really make sense.
mvstanton
2014/04/09 09:43:20
Already gone.
| |
| 6862 TransitionFlag flag, | 6857 TransitionFlag flag, |
| 6863 Name* name, | 6858 Name* name, |
| 6864 SimpleTransitionFlag simple_flag) { | 6859 SimpleTransitionFlag simple_flag) { |
| 6865 ASSERT(descriptors->IsSortedNoDuplicates()); | 6860 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6866 | 6861 |
| 6867 Map* result; | 6862 Map* result; |
| 6868 MaybeObject* maybe_result = CopyDropDescriptors(); | 6863 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 6869 if (!maybe_result->To(&result)) return maybe_result; | 6864 if (!maybe_result->To(&result)) return maybe_result; |
| 6870 | 6865 |
| 6871 result->InitializeDescriptors(descriptors); | 6866 result->InitializeDescriptors(descriptors); |
| 6872 | 6867 |
| 6873 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6868 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
| 6874 TransitionArray* transitions; | 6869 TransitionArray* transitions; |
| 6875 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6870 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
| 6876 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6871 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 6877 set_transitions(transitions); | 6872 set_transitions(transitions); |
| 6878 result->SetBackPointer(this); | 6873 result->SetBackPointer(this); |
| 6879 } else { | 6874 } else { |
| 6880 descriptors->InitializeRepresentations(Representation::Tagged()); | 6875 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 6881 } | 6876 } |
| 6882 | 6877 |
| 6883 return result; | 6878 return result; |
| 6884 } | 6879 } |
| 6885 | 6880 |
| 6886 | 6881 |
| 6882 Handle<Map> Map::CopyReplaceDescriptorsFull(Handle<Map> map, | |
|
Toon Verwaest
2014/04/08 12:58:55
Can we get rid of this version of the method? Kind
mvstanton
2014/04/09 09:43:20
Already gone.
| |
| 6883 Handle<DescriptorArray> descriptors, | |
| 6884 TransitionFlag flag, | |
| 6885 SimpleTransitionFlag simple_flag) { | |
| 6886 return Map::CopyReplaceDescriptorsFull(map, descriptors, flag, | |
| 6887 Handle<Name>::null(), simple_flag); | |
| 6888 } | |
| 6889 | |
| 6890 | |
| 6891 Handle<Map> Map::CopyReplaceDescriptorsFull(Handle<Map> map, | |
| 6892 Handle<DescriptorArray> descriptors, | |
| 6893 TransitionFlag flag, | |
| 6894 Handle<Name> name, | |
| 6895 SimpleTransitionFlag simple_flag) { | |
| 6896 ASSERT(descriptors->IsSortedNoDuplicates()); | |
| 6897 | |
| 6898 Handle<Map> result = CopyDropDescriptors(map); | |
| 6899 result->InitializeDescriptors(*descriptors); | |
| 6900 | |
| 6901 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | |
| 6902 Handle<TransitionArray> transitions = Map::AddTransition( | |
| 6903 map, name, result, simple_flag); | |
| 6904 map->set_transitions(*transitions); | |
| 6905 result->SetBackPointer(*map); | |
| 6906 } else { | |
| 6907 descriptors->InitializeRepresentations(Representation::Tagged()); | |
| 6908 } | |
| 6909 | |
| 6910 return result; | |
| 6911 } | |
| 6912 | |
| 6913 | |
| 6887 // Since this method is used to rewrite an existing transition tree, it can | 6914 // Since this method is used to rewrite an existing transition tree, it can |
| 6888 // always insert transitions without checking. | 6915 // always insert transitions without checking. |
| 6889 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | 6916 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 6890 int new_descriptor, | 6917 int new_descriptor, |
| 6891 Handle<DescriptorArray> descriptors) { | 6918 Handle<DescriptorArray> descriptors) { |
| 6892 ASSERT(descriptors->IsSortedNoDuplicates()); | 6919 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6893 | 6920 |
| 6894 Handle<Map> result = Map::CopyDropDescriptors(map); | 6921 Handle<Map> result = Map::CopyDropDescriptors(map); |
| 6895 | 6922 |
| 6896 result->InitializeDescriptors(*descriptors); | 6923 result->InitializeDescriptors(*descriptors); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 6911 Handle<TransitionArray> transitions = Map::AddTransition(map, name, result, | 6938 Handle<TransitionArray> transitions = Map::AddTransition(map, name, result, |
| 6912 SIMPLE_TRANSITION); | 6939 SIMPLE_TRANSITION); |
| 6913 | 6940 |
| 6914 map->set_transitions(*transitions); | 6941 map->set_transitions(*transitions); |
| 6915 result->SetBackPointer(*map); | 6942 result->SetBackPointer(*map); |
| 6916 | 6943 |
| 6917 return result; | 6944 return result; |
| 6918 } | 6945 } |
| 6919 | 6946 |
| 6920 | 6947 |
| 6921 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { | 6948 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
| 6949 TransitionFlag flag) { | |
| 6922 if (flag == INSERT_TRANSITION) { | 6950 if (flag == INSERT_TRANSITION) { |
| 6923 ASSERT(!HasElementsTransition() || | 6951 ASSERT(!map->HasElementsTransition() || |
| 6924 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || | 6952 ((map->elements_transition_map()->elements_kind() == |
| 6953 DICTIONARY_ELEMENTS || | |
| 6925 IsExternalArrayElementsKind( | 6954 IsExternalArrayElementsKind( |
| 6926 elements_transition_map()->elements_kind())) && | 6955 map->elements_transition_map()->elements_kind())) && |
| 6927 (kind == DICTIONARY_ELEMENTS || | 6956 (kind == DICTIONARY_ELEMENTS || |
| 6928 IsExternalArrayElementsKind(kind)))); | 6957 IsExternalArrayElementsKind(kind)))); |
| 6929 ASSERT(!IsFastElementsKind(kind) || | 6958 ASSERT(!IsFastElementsKind(kind) || |
| 6930 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); | 6959 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); |
| 6931 ASSERT(kind != elements_kind()); | 6960 ASSERT(kind != map->elements_kind()); |
| 6932 } | 6961 } |
| 6933 | 6962 |
| 6934 bool insert_transition = | 6963 bool insert_transition = |
| 6935 flag == INSERT_TRANSITION && !HasElementsTransition(); | 6964 flag == INSERT_TRANSITION && !map->HasElementsTransition(); |
| 6936 | 6965 |
| 6937 if (insert_transition && owns_descriptors()) { | 6966 if (insert_transition && map->owns_descriptors()) { |
| 6938 // In case the map owned its own descriptors, share the descriptors and | 6967 // In case the map owned its own descriptors, share the descriptors and |
| 6939 // transfer ownership to the new map. | 6968 // transfer ownership to the new map. |
| 6940 Map* new_map; | 6969 Handle<Map> new_map = Map::CopyDropDescriptors(map); |
| 6941 MaybeObject* maybe_new_map = CopyDropDescriptors(); | |
| 6942 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 6943 | 6970 |
| 6944 MaybeObject* added_elements = set_elements_transition_map(new_map); | 6971 SetElementsTransitionMap(map, new_map); |
| 6945 if (added_elements->IsFailure()) return added_elements; | |
| 6946 | 6972 |
| 6947 new_map->set_elements_kind(kind); | 6973 new_map->set_elements_kind(kind); |
| 6948 new_map->InitializeDescriptors(instance_descriptors()); | 6974 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6949 new_map->SetBackPointer(this); | 6975 new_map->SetBackPointer(*map); |
| 6950 set_owns_descriptors(false); | 6976 map->set_owns_descriptors(false); |
| 6951 return new_map; | 6977 return new_map; |
| 6952 } | 6978 } |
| 6953 | 6979 |
| 6954 // In case the map did not own its own descriptors, a split is forced by | 6980 // In case the map did not own its own descriptors, a split is forced by |
| 6955 // copying the map; creating a new descriptor array cell. | 6981 // copying the map; creating a new descriptor array cell. |
| 6956 // Create a new free-floating map only if we are not allowed to store it. | 6982 // Create a new free-floating map only if we are not allowed to store it. |
| 6957 Map* new_map; | 6983 Handle<Map> new_map = Map::Copy(map); |
| 6958 MaybeObject* maybe_new_map = Copy(); | |
| 6959 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 6960 | 6984 |
| 6961 new_map->set_elements_kind(kind); | 6985 new_map->set_elements_kind(kind); |
| 6962 | 6986 |
| 6963 if (insert_transition) { | 6987 if (insert_transition) { |
| 6964 MaybeObject* added_elements = set_elements_transition_map(new_map); | 6988 SetElementsTransitionMap(map, new_map); |
| 6965 if (added_elements->IsFailure()) return added_elements; | 6989 new_map->SetBackPointer(*map); |
| 6966 new_map->SetBackPointer(this); | |
| 6967 } | 6990 } |
| 6968 | 6991 |
| 6969 return new_map; | 6992 return new_map; |
| 6970 } | 6993 } |
| 6971 | 6994 |
| 6972 | 6995 |
| 6973 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 6996 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
| 6974 ASSERT(!map->is_observed()); | 6997 ASSERT(!map->is_observed()); |
| 6975 | 6998 |
| 6976 Isolate* isolate = map->GetIsolate(); | 6999 Isolate* isolate = map->GetIsolate(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 6996 new_map->InitializeDescriptors(map->instance_descriptors()); | 7019 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6997 map->set_owns_descriptors(false); | 7020 map->set_owns_descriptors(false); |
| 6998 } | 7021 } |
| 6999 | 7022 |
| 7000 new_map->SetBackPointer(*map); | 7023 new_map->SetBackPointer(*map); |
| 7001 return new_map; | 7024 return new_map; |
| 7002 } | 7025 } |
| 7003 | 7026 |
| 7004 | 7027 |
| 7005 Handle<Map> Map::Copy(Handle<Map> map) { | 7028 Handle<Map> Map::Copy(Handle<Map> map) { |
| 7006 CALL_HEAP_FUNCTION(map->GetIsolate(), map->Copy(), Map); | 7029 Handle<DescriptorArray> descriptors = handle(map->instance_descriptors()); |
| 7030 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | |
| 7031 Handle<DescriptorArray> new_descriptors = | |
| 7032 DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors); | |
| 7033 return Map::CopyReplaceDescriptorsFull(map, new_descriptors, OMIT_TRANSITION); | |
| 7007 } | 7034 } |
| 7008 | 7035 |
| 7009 | 7036 |
| 7010 MaybeObject* Map::Copy() { | |
| 7011 DescriptorArray* descriptors = instance_descriptors(); | |
| 7012 DescriptorArray* new_descriptors; | |
| 7013 int number_of_own_descriptors = NumberOfOwnDescriptors(); | |
| 7014 MaybeObject* maybe_descriptors = | |
| 7015 descriptors->CopyUpTo(number_of_own_descriptors); | |
| 7016 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 7017 | |
| 7018 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | |
| 7019 } | |
| 7020 | |
| 7021 | |
| 7022 Handle<Map> Map::Create(Handle<JSFunction> constructor, | 7037 Handle<Map> Map::Create(Handle<JSFunction> constructor, |
| 7023 int extra_inobject_properties) { | 7038 int extra_inobject_properties) { |
| 7024 Handle<Map> copy = Copy(handle(constructor->initial_map())); | 7039 Handle<Map> copy = Copy(handle(constructor->initial_map())); |
| 7025 | 7040 |
| 7026 // Check that we do not overflow the instance size when adding the | 7041 // Check that we do not overflow the instance size when adding the |
| 7027 // extra inobject properties. | 7042 // extra inobject properties. |
| 7028 int instance_size_delta = extra_inobject_properties * kPointerSize; | 7043 int instance_size_delta = extra_inobject_properties * kPointerSize; |
| 7029 int max_instance_size_delta = | 7044 int max_instance_size_delta = |
| 7030 JSObject::kMaxInstanceSize - copy->instance_size(); | 7045 JSObject::kMaxInstanceSize - copy->instance_size(); |
| 7031 int max_extra_properties = max_instance_size_delta >> kPointerSizeLog2; | 7046 int max_extra_properties = max_instance_size_delta >> kPointerSizeLog2; |
| 7032 | 7047 |
| 7033 // If the instance size overflows, we allocate as many properties as we can as | 7048 // If the instance size overflows, we allocate as many properties as we can as |
| 7034 // inobject properties. | 7049 // inobject properties. |
| 7035 if (extra_inobject_properties > max_extra_properties) { | 7050 if (extra_inobject_properties > max_extra_properties) { |
| 7036 instance_size_delta = max_instance_size_delta; | 7051 instance_size_delta = max_instance_size_delta; |
| 7037 extra_inobject_properties = max_extra_properties; | 7052 extra_inobject_properties = max_extra_properties; |
| 7038 } | 7053 } |
| 7039 | 7054 |
| 7040 // Adjust the map with the extra inobject properties. | 7055 // Adjust the map with the extra inobject properties. |
| 7041 int inobject_properties = | 7056 int inobject_properties = |
| 7042 copy->inobject_properties() + extra_inobject_properties; | 7057 copy->inobject_properties() + extra_inobject_properties; |
| 7043 copy->set_inobject_properties(inobject_properties); | 7058 copy->set_inobject_properties(inobject_properties); |
| 7044 copy->set_unused_property_fields(inobject_properties); | 7059 copy->set_unused_property_fields(inobject_properties); |
| 7045 copy->set_instance_size(copy->instance_size() + instance_size_delta); | 7060 copy->set_instance_size(copy->instance_size() + instance_size_delta); |
| 7046 copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy)); | 7061 copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy)); |
| 7047 return copy; | 7062 return copy; |
| 7048 } | 7063 } |
| 7049 | 7064 |
| 7050 | 7065 |
| 7051 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, | 7066 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
| 7052 TransitionFlag flag) { | 7067 Descriptor* descriptor, |
| 7053 DescriptorArray* descriptors = instance_descriptors(); | 7068 TransitionFlag flag) { |
| 7069 Handle<DescriptorArray> descriptors = handle(map->instance_descriptors()); | |
| 7054 | 7070 |
| 7055 // Ensure the key is unique. | 7071 // Ensure the key is unique. |
| 7056 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); | 7072 descriptor->KeyToUniqueName(); |
| 7057 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 7058 | 7073 |
| 7059 int old_size = NumberOfOwnDescriptors(); | 7074 int old_size = map->NumberOfOwnDescriptors(); |
| 7060 int new_size = old_size + 1; | 7075 int new_size = old_size + 1; |
| 7061 | 7076 |
| 7062 if (flag == INSERT_TRANSITION && | 7077 if (flag == INSERT_TRANSITION && |
| 7063 owns_descriptors() && | 7078 map->owns_descriptors() && |
| 7064 CanHaveMoreTransitions()) { | 7079 map->CanHaveMoreTransitions()) { |
| 7065 return ShareDescriptor(descriptors, descriptor); | 7080 return Map::ShareDescriptor(map, descriptors, descriptor); |
| 7066 } | 7081 } |
| 7067 | 7082 |
| 7068 DescriptorArray* new_descriptors; | 7083 Handle<DescriptorArray> new_descriptors = |
| 7069 MaybeObject* maybe_descriptors = | 7084 map->GetIsolate()->factory()->NewDescriptorArray(old_size, 1); |
| 7070 DescriptorArray::Allocate(GetIsolate(), old_size, 1); | |
| 7071 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 7072 | 7085 |
| 7073 DescriptorArray::WhitenessWitness witness(new_descriptors); | 7086 DescriptorArray::WhitenessWitness witness(*new_descriptors); |
| 7074 | 7087 |
| 7075 // Copy the descriptors, inserting a descriptor. | 7088 // Copy the descriptors, inserting a descriptor. |
| 7076 for (int i = 0; i < old_size; ++i) { | 7089 for (int i = 0; i < old_size; ++i) { |
| 7077 new_descriptors->CopyFrom(i, descriptors, i, witness); | 7090 new_descriptors->CopyFrom(i, *descriptors, i, witness); |
| 7078 } | 7091 } |
| 7079 | 7092 |
| 7080 if (old_size != descriptors->number_of_descriptors()) { | 7093 if (old_size != descriptors->number_of_descriptors()) { |
| 7081 new_descriptors->SetNumberOfDescriptors(new_size); | 7094 new_descriptors->SetNumberOfDescriptors(new_size); |
| 7082 new_descriptors->Set(old_size, descriptor, witness); | 7095 new_descriptors->Set(old_size, descriptor, witness); |
| 7083 new_descriptors->Sort(); | 7096 new_descriptors->Sort(); |
| 7084 } else { | 7097 } else { |
| 7085 new_descriptors->Append(descriptor, witness); | 7098 new_descriptors->Append(descriptor, witness); |
| 7086 } | 7099 } |
| 7087 | 7100 |
| 7088 Name* key = descriptor->GetKey(); | 7101 Handle<Name> key = descriptor->GetKey(); |
| 7089 return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION); | 7102 return Map::CopyReplaceDescriptorsFull(map, new_descriptors, flag, |
| 7103 key, SIMPLE_TRANSITION); | |
| 7090 } | 7104 } |
| 7091 | 7105 |
| 7092 | 7106 |
| 7093 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, | 7107 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map, |
| 7094 TransitionFlag flag) { | 7108 Descriptor* descriptor, |
| 7095 DescriptorArray* old_descriptors = instance_descriptors(); | 7109 TransitionFlag flag) { |
| 7110 Handle<DescriptorArray> old_descriptors = handle(map->instance_descriptors()); | |
| 7096 | 7111 |
| 7097 // Ensure the key is unique. | 7112 // Ensure the key is unique. |
| 7098 MaybeObject* maybe_result = descriptor->KeyToUniqueName(); | 7113 descriptor->KeyToUniqueName(); |
| 7099 if (maybe_result->IsFailure()) return maybe_result; | |
| 7100 | 7114 |
| 7101 // We replace the key if it is already present. | 7115 // We replace the key if it is already present. |
| 7102 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 7116 int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map); |
| 7103 if (index != DescriptorArray::kNotFound) { | 7117 if (index != DescriptorArray::kNotFound) { |
| 7104 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); | 7118 return Map::CopyReplaceDescriptor(map, old_descriptors, descriptor, |
| 7119 index, flag); | |
| 7105 } | 7120 } |
| 7106 return CopyAddDescriptor(descriptor, flag); | 7121 return Map::CopyAddDescriptor(map, descriptor, flag); |
| 7122 } | |
| 7123 | |
| 7124 | |
| 7125 Handle<DescriptorArray> DescriptorArray::CopyUpTo( | |
| 7126 Handle<DescriptorArray> desc, | |
| 7127 int enumeration_index) { | |
| 7128 return DescriptorArray::CopyUpToAddAttributes(desc, | |
| 7129 enumeration_index, | |
| 7130 NONE); | |
| 7107 } | 7131 } |
| 7108 | 7132 |
| 7109 | 7133 |
| 7110 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( | 7134 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( |
| 7111 Handle<DescriptorArray> desc, | 7135 Handle<DescriptorArray> desc, |
| 7112 int enumeration_index, | 7136 int enumeration_index, |
| 7113 PropertyAttributes attributes) { | 7137 PropertyAttributes attributes) { |
| 7114 CALL_HEAP_FUNCTION(desc->GetIsolate(), | 7138 if (enumeration_index == 0) { |
| 7115 desc->CopyUpToAddAttributes(enumeration_index, attributes), | 7139 return desc->GetIsolate()->factory()->empty_descriptor_array(); |
| 7116 DescriptorArray); | 7140 } |
| 7117 } | |
| 7118 | |
| 7119 | |
| 7120 MaybeObject* DescriptorArray::CopyUpToAddAttributes( | |
| 7121 int enumeration_index, PropertyAttributes attributes) { | |
| 7122 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | |
| 7123 | 7141 |
| 7124 int size = enumeration_index; | 7142 int size = enumeration_index; |
| 7125 | 7143 |
| 7126 DescriptorArray* descriptors; | 7144 Handle<DescriptorArray> descriptors = |
| 7127 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size); | 7145 desc->GetIsolate()->factory()->NewDescriptorArray(size); |
| 7128 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 7146 DescriptorArray::WhitenessWitness witness(*descriptors); |
| 7129 DescriptorArray::WhitenessWitness witness(descriptors); | |
| 7130 | 7147 |
| 7131 if (attributes != NONE) { | 7148 if (attributes != NONE) { |
| 7132 for (int i = 0; i < size; ++i) { | 7149 for (int i = 0; i < size; ++i) { |
| 7133 Object* value = GetValue(i); | 7150 Object* value = desc->GetValue(i); |
| 7134 PropertyDetails details = GetDetails(i); | 7151 PropertyDetails details = desc->GetDetails(i); |
| 7135 int mask = DONT_DELETE | DONT_ENUM; | 7152 int mask = DONT_DELETE | DONT_ENUM; |
| 7136 // READ_ONLY is an invalid attribute for JS setters/getters. | 7153 // READ_ONLY is an invalid attribute for JS setters/getters. |
| 7137 if (details.type() != CALLBACKS || !value->IsAccessorPair()) { | 7154 if (details.type() != CALLBACKS || !value->IsAccessorPair()) { |
| 7138 mask |= READ_ONLY; | 7155 mask |= READ_ONLY; |
| 7139 } | 7156 } |
| 7140 details = details.CopyAddAttributes( | 7157 details = details.CopyAddAttributes( |
| 7141 static_cast<PropertyAttributes>(attributes & mask)); | 7158 static_cast<PropertyAttributes>(attributes & mask)); |
| 7142 Descriptor desc(GetKey(i), value, details); | 7159 Descriptor inner_desc(handle(desc->GetKey(i)), |
| 7143 descriptors->Set(i, &desc, witness); | 7160 handle(value, desc->GetIsolate()), |
| 7161 details); | |
| 7162 descriptors->Set(i, &inner_desc, witness); | |
| 7144 } | 7163 } |
| 7145 } else { | 7164 } else { |
| 7146 for (int i = 0; i < size; ++i) { | 7165 for (int i = 0; i < size; ++i) { |
| 7147 descriptors->CopyFrom(i, this, i, witness); | 7166 descriptors->CopyFrom(i, *desc, i, witness); |
| 7148 } | 7167 } |
| 7149 } | 7168 } |
| 7150 | 7169 |
| 7151 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); | 7170 if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort(); |
| 7152 | 7171 |
| 7153 return descriptors; | 7172 return descriptors; |
| 7154 } | 7173 } |
| 7155 | 7174 |
| 7156 | 7175 |
| 7157 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, | 7176 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map, |
| 7158 Descriptor* descriptor, | 7177 Handle<DescriptorArray> descriptors, |
| 7159 int insertion_index, | 7178 Descriptor* descriptor, |
| 7160 TransitionFlag flag) { | 7179 int insertion_index, |
| 7180 TransitionFlag flag) { | |
| 7161 // Ensure the key is unique. | 7181 // Ensure the key is unique. |
| 7162 MaybeObject* maybe_failure = descriptor->KeyToUniqueName(); | 7182 descriptor->KeyToUniqueName(); |
| 7163 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 7164 | 7183 |
| 7165 Name* key = descriptor->GetKey(); | 7184 Handle<Name> key = descriptor->GetKey(); |
| 7166 ASSERT(key == descriptors->GetKey(insertion_index)); | 7185 ASSERT(*key == descriptors->GetKey(insertion_index)); |
| 7167 | 7186 |
| 7168 int new_size = NumberOfOwnDescriptors(); | 7187 int new_size = map->NumberOfOwnDescriptors(); |
| 7169 ASSERT(0 <= insertion_index && insertion_index < new_size); | 7188 ASSERT(0 <= insertion_index && insertion_index < new_size); |
| 7170 | 7189 |
| 7171 ASSERT_LT(insertion_index, new_size); | 7190 ASSERT_LT(insertion_index, new_size); |
| 7172 | 7191 |
| 7173 DescriptorArray* new_descriptors; | 7192 Handle<DescriptorArray> new_descriptors = |
| 7174 MaybeObject* maybe_descriptors = | 7193 map->GetIsolate()->factory()->NewDescriptorArray(new_size); |
| 7175 DescriptorArray::Allocate(GetIsolate(), new_size); | 7194 DescriptorArray::WhitenessWitness witness(*new_descriptors); |
| 7176 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 7177 DescriptorArray::WhitenessWitness witness(new_descriptors); | |
| 7178 | 7195 |
| 7179 for (int i = 0; i < new_size; ++i) { | 7196 for (int i = 0; i < new_size; ++i) { |
| 7180 if (i == insertion_index) { | 7197 if (i == insertion_index) { |
| 7181 new_descriptors->Set(i, descriptor, witness); | 7198 new_descriptors->Set(i, descriptor, witness); |
|
Toon Verwaest
2014/04/08 12:58:55
In this Set case, the "pointer" will be wrong.
Ca
mvstanton
2014/04/09 09:43:20
I followed your suggestion to just add
descriptor
| |
| 7182 } else { | 7199 } else { |
| 7183 new_descriptors->CopyFrom(i, descriptors, i, witness); | 7200 new_descriptors->CopyFrom(i, *descriptors, i, witness); |
| 7184 } | 7201 } |
| 7185 } | 7202 } |
| 7186 | 7203 |
| 7187 // Re-sort if descriptors were removed. | 7204 // Re-sort if descriptors were removed. |
| 7188 if (new_size != descriptors->length()) new_descriptors->Sort(); | 7205 if (new_size != descriptors->length()) new_descriptors->Sort(); |
| 7189 | 7206 |
| 7190 SimpleTransitionFlag simple_flag = | 7207 SimpleTransitionFlag simple_flag = |
| 7191 (insertion_index == descriptors->number_of_descriptors() - 1) | 7208 (insertion_index == descriptors->number_of_descriptors() - 1) |
| 7192 ? SIMPLE_TRANSITION | 7209 ? SIMPLE_TRANSITION |
| 7193 : FULL_TRANSITION; | 7210 : FULL_TRANSITION; |
| 7194 return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag); | 7211 return Map::CopyReplaceDescriptorsFull(map, new_descriptors, flag, key, |
| 7212 simple_flag); | |
| 7195 } | 7213 } |
| 7196 | 7214 |
| 7197 | 7215 |
| 7198 void Map::UpdateCodeCache(Handle<Map> map, | 7216 void Map::UpdateCodeCache(Handle<Map> map, |
| 7199 Handle<Name> name, | 7217 Handle<Name> name, |
| 7200 Handle<Code> code) { | 7218 Handle<Code> code) { |
| 7201 Isolate* isolate = map->GetIsolate(); | 7219 Isolate* isolate = map->GetIsolate(); |
| 7202 CALL_HEAP_FUNCTION_VOID(isolate, | 7220 CALL_HEAP_FUNCTION_VOID(isolate, |
| 7203 map->UpdateCodeCache(*name, *code)); | 7221 map->UpdateCodeCache(*name, *code)); |
| 7204 } | 7222 } |
| (...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8028 set(kEnumCacheIndex, bridge_storage); | 8046 set(kEnumCacheIndex, bridge_storage); |
| 8029 } | 8047 } |
| 8030 | 8048 |
| 8031 | 8049 |
| 8032 void DescriptorArray::CopyFrom(int dst_index, | 8050 void DescriptorArray::CopyFrom(int dst_index, |
| 8033 DescriptorArray* src, | 8051 DescriptorArray* src, |
| 8034 int src_index, | 8052 int src_index, |
| 8035 const WhitenessWitness& witness) { | 8053 const WhitenessWitness& witness) { |
| 8036 Object* value = src->GetValue(src_index); | 8054 Object* value = src->GetValue(src_index); |
| 8037 PropertyDetails details = src->GetDetails(src_index); | 8055 PropertyDetails details = src->GetDetails(src_index); |
| 8038 Descriptor desc(src->GetKey(src_index), value, details); | 8056 Descriptor desc(handle(src->GetKey(src_index)), |
| 8057 handle(value, src->GetIsolate()), | |
| 8058 details); | |
| 8039 Set(dst_index, &desc, witness); | 8059 Set(dst_index, &desc, witness); |
| 8040 } | 8060 } |
| 8041 | 8061 |
| 8042 | 8062 |
| 8043 // Creates a new descriptor array by merging the descriptor array of |right_map| | 8063 // Creates a new descriptor array by merging the descriptor array of |right_map| |
| 8044 // into the (at least partly) updated descriptor array of |left_map|. | 8064 // into the (at least partly) updated descriptor array of |left_map|. |
| 8045 // The method merges two descriptor array in three parts. Both descriptor arrays | 8065 // The method merges two descriptor array in three parts. Both descriptor arrays |
| 8046 // are identical up to |verbatim|. They also overlap in keys up to |valid|. | 8066 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
| 8047 // Between |verbatim| and |valid|, the resulting descriptor type as well as the | 8067 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
| 8048 // representation are generalized from both |left_map| and |right_map|. Beyond | 8068 // representation are generalized from both |left_map| and |right_map|. Beyond |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 8071 result->NumberOfSlackDescriptors() > 0 || | 8091 result->NumberOfSlackDescriptors() > 0 || |
| 8072 result->number_of_descriptors() == right->number_of_descriptors()); | 8092 result->number_of_descriptors() == right->number_of_descriptors()); |
| 8073 ASSERT(result->number_of_descriptors() == new_size); | 8093 ASSERT(result->number_of_descriptors() == new_size); |
| 8074 | 8094 |
| 8075 int descriptor; | 8095 int descriptor; |
| 8076 | 8096 |
| 8077 // 0 -> |verbatim| | 8097 // 0 -> |verbatim| |
| 8078 int current_offset = 0; | 8098 int current_offset = 0; |
| 8079 for (descriptor = 0; descriptor < verbatim; descriptor++) { | 8099 for (descriptor = 0; descriptor < verbatim; descriptor++) { |
| 8080 if (left->GetDetails(descriptor).type() == FIELD) current_offset++; | 8100 if (left->GetDetails(descriptor).type() == FIELD) current_offset++; |
| 8081 Descriptor d(right->GetKey(descriptor), | 8101 Descriptor d(handle(right->GetKey(descriptor)), |
| 8082 right->GetValue(descriptor), | 8102 handle(right->GetValue(descriptor), right->GetIsolate()), |
| 8083 right->GetDetails(descriptor)); | 8103 right->GetDetails(descriptor)); |
| 8084 result->Set(descriptor, &d); | 8104 result->Set(descriptor, &d); |
| 8085 } | 8105 } |
| 8086 | 8106 |
| 8087 // |verbatim| -> |valid| | 8107 // |verbatim| -> |valid| |
| 8088 for (; descriptor < valid; descriptor++) { | 8108 for (; descriptor < valid; descriptor++) { |
| 8089 PropertyDetails left_details = left->GetDetails(descriptor); | 8109 PropertyDetails left_details = left->GetDetails(descriptor); |
| 8090 PropertyDetails right_details = right->GetDetails(descriptor); | 8110 PropertyDetails right_details = right->GetDetails(descriptor); |
| 8091 if (left_details.type() == FIELD || right_details.type() == FIELD || | 8111 if (left_details.type() == FIELD || right_details.type() == FIELD || |
| 8092 (store_mode == FORCE_FIELD && descriptor == modify_index) || | 8112 (store_mode == FORCE_FIELD && descriptor == modify_index) || |
| 8093 (left_details.type() == CONSTANT && | 8113 (left_details.type() == CONSTANT && |
| 8094 right_details.type() == CONSTANT && | 8114 right_details.type() == CONSTANT && |
| 8095 left->GetValue(descriptor) != right->GetValue(descriptor))) { | 8115 left->GetValue(descriptor) != right->GetValue(descriptor))) { |
| 8096 Representation representation = left_details.representation().generalize( | 8116 Representation representation = left_details.representation().generalize( |
| 8097 right_details.representation()); | 8117 right_details.representation()); |
| 8098 FieldDescriptor d(left->GetKey(descriptor), | 8118 FieldDescriptor d(handle(left->GetKey(descriptor)), |
| 8099 current_offset++, | 8119 current_offset++, |
| 8100 right_details.attributes(), | 8120 right_details.attributes(), |
| 8101 representation); | 8121 representation); |
| 8102 result->Set(descriptor, &d); | 8122 result->Set(descriptor, &d); |
| 8103 } else { | 8123 } else { |
| 8104 Descriptor d(right->GetKey(descriptor), | 8124 Descriptor d(handle(right->GetKey(descriptor)), |
| 8105 right->GetValue(descriptor), | 8125 handle(right->GetValue(descriptor), right->GetIsolate()), |
| 8106 right_details); | 8126 right_details); |
| 8107 result->Set(descriptor, &d); | 8127 result->Set(descriptor, &d); |
| 8108 } | 8128 } |
| 8109 } | 8129 } |
| 8110 | 8130 |
| 8111 // |valid| -> |new_size| | 8131 // |valid| -> |new_size| |
| 8112 for (; descriptor < new_size; descriptor++) { | 8132 for (; descriptor < new_size; descriptor++) { |
| 8113 PropertyDetails right_details = right->GetDetails(descriptor); | 8133 PropertyDetails right_details = right->GetDetails(descriptor); |
| 8114 if (right_details.type() == FIELD || | 8134 if (right_details.type() == FIELD || |
| 8115 (store_mode == FORCE_FIELD && descriptor == modify_index)) { | 8135 (store_mode == FORCE_FIELD && descriptor == modify_index)) { |
| 8116 FieldDescriptor d(right->GetKey(descriptor), | 8136 FieldDescriptor d(handle(right->GetKey(descriptor)), |
| 8117 current_offset++, | 8137 current_offset++, |
| 8118 right_details.attributes(), | 8138 right_details.attributes(), |
| 8119 right_details.representation()); | 8139 right_details.representation()); |
| 8120 result->Set(descriptor, &d); | 8140 result->Set(descriptor, &d); |
| 8121 } else { | 8141 } else { |
| 8122 Descriptor d(right->GetKey(descriptor), | 8142 Descriptor d(handle(right->GetKey(descriptor)), |
| 8123 right->GetValue(descriptor), | 8143 handle(right->GetValue(descriptor), right->GetIsolate()), |
| 8124 right_details); | 8144 right_details); |
| 8125 result->Set(descriptor, &d); | 8145 result->Set(descriptor, &d); |
| 8126 } | 8146 } |
| 8127 } | 8147 } |
| 8128 | 8148 |
| 8129 result->Sort(); | 8149 result->Sort(); |
| 8130 return result; | 8150 return result; |
| 8131 } | 8151 } |
| 8132 | 8152 |
| 8133 | 8153 |
| (...skipping 1583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9717 if (object->IsGlobalObject()) return; | 9737 if (object->IsGlobalObject()) return; |
| 9718 | 9738 |
| 9719 // Make sure prototypes are fast objects and their maps have the bit set | 9739 // Make sure prototypes are fast objects and their maps have the bit set |
| 9720 // so they remain fast. | 9740 // so they remain fast. |
| 9721 if (!object->HasFastProperties()) { | 9741 if (!object->HasFastProperties()) { |
| 9722 TransformToFastProperties(object, 0); | 9742 TransformToFastProperties(object, 0); |
| 9723 } | 9743 } |
| 9724 } | 9744 } |
| 9725 | 9745 |
| 9726 | 9746 |
| 9727 static MUST_USE_RESULT MaybeObject* CacheInitialJSArrayMaps( | 9747 Handle<Object> CacheInitialJSArrayMaps( |
| 9728 Context* native_context, Map* initial_map) { | 9748 Handle<Context> native_context, Handle<Map> initial_map) { |
| 9729 // Replace all of the cached initial array maps in the native context with | 9749 // Replace all of the cached initial array maps in the native context with |
| 9730 // the appropriate transitioned elements kind maps. | 9750 // the appropriate transitioned elements kind maps. |
| 9731 Heap* heap = native_context->GetHeap(); | 9751 Factory* factory = native_context->GetIsolate()->factory(); |
| 9732 MaybeObject* maybe_maps = | 9752 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( |
| 9733 heap->AllocateFixedArrayWithHoles(kElementsKindCount, TENURED); | 9753 kElementsKindCount, TENURED); |
| 9734 FixedArray* maps; | |
| 9735 if (!maybe_maps->To(&maps)) return maybe_maps; | |
| 9736 | 9754 |
| 9737 Map* current_map = initial_map; | 9755 Handle<Map> current_map = initial_map; |
| 9738 ElementsKind kind = current_map->elements_kind(); | 9756 ElementsKind kind = current_map->elements_kind(); |
| 9739 ASSERT(kind == GetInitialFastElementsKind()); | 9757 ASSERT(kind == GetInitialFastElementsKind()); |
| 9740 maps->set(kind, current_map); | 9758 maps->set(kind, *current_map); |
| 9741 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 9759 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
| 9742 i < kFastElementsKindCount; ++i) { | 9760 i < kFastElementsKindCount; ++i) { |
| 9743 Map* new_map; | 9761 Handle<Map> new_map; |
| 9744 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); | 9762 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
| 9745 if (current_map->HasElementsTransition()) { | 9763 if (current_map->HasElementsTransition()) { |
| 9746 new_map = current_map->elements_transition_map(); | 9764 new_map = handle(current_map->elements_transition_map()); |
| 9747 ASSERT(new_map->elements_kind() == next_kind); | 9765 ASSERT(new_map->elements_kind() == next_kind); |
| 9748 } else { | 9766 } else { |
| 9749 MaybeObject* maybe_new_map = | 9767 new_map = Map::CopyAsElementsKind(current_map, next_kind, |
| 9750 current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION); | 9768 INSERT_TRANSITION); |
| 9751 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 9752 } | 9769 } |
| 9753 maps->set(next_kind, new_map); | 9770 maps->set(next_kind, *new_map); |
| 9754 current_map = new_map; | 9771 current_map = new_map; |
| 9755 } | 9772 } |
| 9756 native_context->set_js_array_maps(maps); | 9773 native_context->set_js_array_maps(*maps); |
| 9757 return initial_map; | 9774 return initial_map; |
| 9758 } | 9775 } |
| 9759 | 9776 |
| 9760 | 9777 |
| 9761 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context, | |
| 9762 Handle<Map> initial_map) { | |
| 9763 CALL_HEAP_FUNCTION(native_context->GetIsolate(), | |
| 9764 CacheInitialJSArrayMaps(*native_context, *initial_map), | |
| 9765 Object); | |
| 9766 } | |
| 9767 | |
| 9768 | |
| 9769 void JSFunction::SetInstancePrototype(Handle<JSFunction> function, | 9778 void JSFunction::SetInstancePrototype(Handle<JSFunction> function, |
| 9770 Handle<Object> value) { | 9779 Handle<Object> value) { |
| 9771 ASSERT(value->IsJSReceiver()); | 9780 ASSERT(value->IsJSReceiver()); |
| 9772 | 9781 |
| 9773 // First some logic for the map of the prototype to make sure it is in fast | 9782 // First some logic for the map of the prototype to make sure it is in fast |
| 9774 // mode. | 9783 // mode. |
| 9775 if (value->IsJSObject()) { | 9784 if (value->IsJSObject()) { |
| 9776 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); | 9785 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 9777 } | 9786 } |
| 9778 | 9787 |
| (...skipping 5876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15655 // instance descriptor. | 15664 // instance descriptor. |
| 15656 MaybeObject* maybe_key = heap->InternalizeString(String::cast(k)); | 15665 MaybeObject* maybe_key = heap->InternalizeString(String::cast(k)); |
| 15657 if (!maybe_key->To(&key)) return maybe_key; | 15666 if (!maybe_key->To(&key)) return maybe_key; |
| 15658 } | 15667 } |
| 15659 | 15668 |
| 15660 PropertyDetails details = DetailsAt(i); | 15669 PropertyDetails details = DetailsAt(i); |
| 15661 int enumeration_index = details.dictionary_index(); | 15670 int enumeration_index = details.dictionary_index(); |
| 15662 PropertyType type = details.type(); | 15671 PropertyType type = details.type(); |
| 15663 | 15672 |
| 15664 if (value->IsJSFunction()) { | 15673 if (value->IsJSFunction()) { |
| 15665 ConstantDescriptor d(key, value, details.attributes()); | 15674 ConstantDescriptor d(handle(key), |
| 15675 handle(value, GetIsolate()), | |
| 15676 details.attributes()); | |
| 15666 descriptors->Set(enumeration_index - 1, &d, witness); | 15677 descriptors->Set(enumeration_index - 1, &d, witness); |
| 15667 } else if (type == NORMAL) { | 15678 } else if (type == NORMAL) { |
| 15668 if (current_offset < inobject_props) { | 15679 if (current_offset < inobject_props) { |
| 15669 obj->InObjectPropertyAtPut(current_offset, | 15680 obj->InObjectPropertyAtPut(current_offset, |
| 15670 value, | 15681 value, |
| 15671 UPDATE_WRITE_BARRIER); | 15682 UPDATE_WRITE_BARRIER); |
| 15672 } else { | 15683 } else { |
| 15673 int offset = current_offset - inobject_props; | 15684 int offset = current_offset - inobject_props; |
| 15674 fields->set(offset, value); | 15685 fields->set(offset, value); |
| 15675 } | 15686 } |
| 15676 FieldDescriptor d(key, | 15687 FieldDescriptor d(handle(key), |
| 15677 current_offset++, | 15688 current_offset++, |
| 15678 details.attributes(), | 15689 details.attributes(), |
| 15679 // TODO(verwaest): value->OptimalRepresentation(); | 15690 // TODO(verwaest): value->OptimalRepresentation(); |
| 15680 Representation::Tagged()); | 15691 Representation::Tagged()); |
| 15681 descriptors->Set(enumeration_index - 1, &d, witness); | 15692 descriptors->Set(enumeration_index - 1, &d, witness); |
| 15682 } else if (type == CALLBACKS) { | 15693 } else if (type == CALLBACKS) { |
| 15683 CallbacksDescriptor d(key, | 15694 CallbacksDescriptor d(handle(key), |
| 15684 value, | 15695 handle(value, GetIsolate()), |
| 15685 details.attributes()); | 15696 details.attributes()); |
| 15686 descriptors->Set(enumeration_index - 1, &d, witness); | 15697 descriptors->Set(enumeration_index - 1, &d, witness); |
| 15687 } else { | 15698 } else { |
| 15688 UNREACHABLE(); | 15699 UNREACHABLE(); |
| 15689 } | 15700 } |
| 15690 } | 15701 } |
| 15691 } | 15702 } |
| 15692 ASSERT(current_offset == number_of_fields); | 15703 ASSERT(current_offset == number_of_fields); |
| 15693 | 15704 |
| 15694 descriptors->Sort(); | 15705 descriptors->Sort(); |
| (...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16677 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16688 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16678 static const char* error_messages_[] = { | 16689 static const char* error_messages_[] = { |
| 16679 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16690 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16680 }; | 16691 }; |
| 16681 #undef ERROR_MESSAGES_TEXTS | 16692 #undef ERROR_MESSAGES_TEXTS |
| 16682 return error_messages_[reason]; | 16693 return error_messages_[reason]; |
| 16683 } | 16694 } |
| 16684 | 16695 |
| 16685 | 16696 |
| 16686 } } // namespace v8::internal | 16697 } } // namespace v8::internal |
| OLD | NEW |