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 |