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 3238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3249 } | 3249 } |
| 3250 current_map = maybe_transitioned_map; | 3250 current_map = maybe_transitioned_map; |
| 3251 } | 3251 } |
| 3252 } | 3252 } |
| 3253 return transitioned_map; | 3253 return transitioned_map; |
| 3254 } | 3254 } |
| 3255 | 3255 |
| 3256 | 3256 |
| 3257 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { | 3257 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { |
| 3258 Map* current_map = map; | 3258 Map* current_map = map; |
| 3259 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); | 3259 int target_kind = |
| 3260 int to_index = IsFastElementsKind(to_kind) | 3260 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) |
|
Toon Verwaest
2014/03/10 14:15:34
IsTransitionElementsKind(to_kind)?
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
No, this is not IsTransitionElementsKind.
| |
| 3261 ? GetSequenceIndexFromFastElementsKind(to_kind) | 3261 ? to_kind |
| 3262 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); | 3262 : TERMINAL_FAST_ELEMENTS_KIND; |
| 3263 | 3263 |
| 3264 ASSERT(index <= to_index); | 3264 // Support for legacy API. |
| 3265 if (IsExternalArrayElementsKind(to_kind) && | |
| 3266 !IsFixedTypedArrayElementsKind(map->elements_kind())) { | |
| 3267 return map; | |
| 3268 } | |
| 3265 | 3269 |
| 3266 for (; index < to_index; ++index) { | 3270 ElementsKind kind = map->elements_kind(); |
| 3271 while (kind != target_kind) { | |
| 3272 kind = GetNextTransitionElementsKind(kind); | |
| 3267 if (!current_map->HasElementsTransition()) return current_map; | 3273 if (!current_map->HasElementsTransition()) return current_map; |
| 3268 current_map = current_map->elements_transition_map(); | 3274 current_map = current_map->elements_transition_map(); |
| 3269 } | 3275 } |
| 3270 if (!IsFastElementsKind(to_kind) && current_map->HasElementsTransition()) { | 3276 |
| 3277 if (to_kind != kind && current_map->HasElementsTransition()) { | |
|
Toon Verwaest
2014/03/10 14:15:34
Can this only happen for DICTIONARY elements now?
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
Done.
| |
| 3271 Map* next_map = current_map->elements_transition_map(); | 3278 Map* next_map = current_map->elements_transition_map(); |
| 3272 if (next_map->elements_kind() == to_kind) return next_map; | 3279 if (next_map->elements_kind() == to_kind) return next_map; |
| 3273 } | 3280 } |
| 3274 ASSERT(IsFastElementsKind(to_kind) | 3281 |
| 3275 ? current_map->elements_kind() == to_kind | 3282 ASSERT(current_map->elements_kind() == target_kind); |
|
Toon Verwaest
2014/03/10 14:15:34
This ASSERT is wrong afaict. If we didnt' have an
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
target_kind is not DICTIONARY_ELEMENTS in that cas
| |
| 3276 : current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND); | |
| 3277 return current_map; | 3283 return current_map; |
| 3278 } | 3284 } |
| 3279 | 3285 |
| 3280 | 3286 |
| 3281 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 3287 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
| 3282 Map* to_map = FindClosestElementsTransition(this, to_kind); | 3288 Map* to_map = FindClosestElementsTransition(this, to_kind); |
| 3283 if (to_map->elements_kind() == to_kind) return to_map; | 3289 if (to_map->elements_kind() == to_kind) return to_map; |
| 3284 return NULL; | 3290 return NULL; |
| 3285 } | 3291 } |
| 3286 | 3292 |
| 3287 | 3293 |
| 3288 bool Map::IsMapInArrayPrototypeChain() { | 3294 bool Map::IsMapInArrayPrototypeChain() { |
| 3289 Isolate* isolate = GetIsolate(); | 3295 Isolate* isolate = GetIsolate(); |
| 3290 if (isolate->initial_array_prototype()->map() == this) { | 3296 if (isolate->initial_array_prototype()->map() == this) { |
| 3291 return true; | 3297 return true; |
| 3292 } | 3298 } |
| 3293 | 3299 |
| 3294 if (isolate->initial_object_prototype()->map() == this) { | 3300 if (isolate->initial_object_prototype()->map() == this) { |
| 3295 return true; | 3301 return true; |
| 3296 } | 3302 } |
| 3297 | 3303 |
| 3298 return false; | 3304 return false; |
| 3299 } | 3305 } |
| 3300 | 3306 |
| 3301 | 3307 |
| 3302 static MaybeObject* AddMissingElementsTransitions(Map* map, | 3308 static MaybeObject* AddMissingElementsTransitions(Map* map, |
| 3303 ElementsKind to_kind) { | 3309 ElementsKind to_kind) { |
| 3304 ASSERT(IsFastElementsKind(map->elements_kind())); | 3310 ASSERT(IsTransitionElementsKind(map->elements_kind())); |
| 3305 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); | |
| 3306 int to_index = IsFastElementsKind(to_kind) | |
| 3307 ? GetSequenceIndexFromFastElementsKind(to_kind) | |
| 3308 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); | |
| 3309 | |
| 3310 ASSERT(index <= to_index); | |
| 3311 | 3311 |
| 3312 Map* current_map = map; | 3312 Map* current_map = map; |
| 3313 | 3313 |
| 3314 for (; index < to_index; ++index) { | 3314 ElementsKind kind = map->elements_kind(); |
| 3315 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1); | 3315 while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
| 3316 kind = GetNextTransitionElementsKind(kind); | |
| 3316 MaybeObject* maybe_next_map = | 3317 MaybeObject* maybe_next_map = |
| 3317 current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION); | 3318 current_map->CopyAsElementsKind(kind, INSERT_TRANSITION); |
| 3318 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | 3319 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
| 3319 } | 3320 } |
| 3320 | 3321 |
| 3321 // In case we are exiting the fast elements kind system, just add the map in | 3322 // In case we are exiting the fast elements kind system, just add the map in |
| 3322 // the end. | 3323 // the end. |
| 3323 if (!IsFastElementsKind(to_kind)) { | 3324 if (kind != to_kind) { |
|
Toon Verwaest
2014/03/10 14:15:34
Can this only happen for DICTIONARY elements now?
Dmitry Lomov (no reviews)
2014/03/24 08:31:22
No, this happens at the end of all chains.
| |
| 3324 MaybeObject* maybe_next_map = | 3325 MaybeObject* maybe_next_map = |
| 3325 current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION); | 3326 current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION); |
| 3326 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | 3327 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
| 3327 } | 3328 } |
| 3328 | 3329 |
| 3329 ASSERT(current_map->elements_kind() == to_kind); | 3330 ASSERT(current_map->elements_kind() == to_kind); |
| 3330 return current_map; | 3331 return current_map; |
| 3331 } | 3332 } |
| 3332 | 3333 |
| 3333 | 3334 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3345 ElementsKind from_kind = start_map->elements_kind(); | 3346 ElementsKind from_kind = start_map->elements_kind(); |
| 3346 | 3347 |
| 3347 if (from_kind == to_kind) { | 3348 if (from_kind == to_kind) { |
| 3348 return start_map; | 3349 return start_map; |
| 3349 } | 3350 } |
| 3350 | 3351 |
| 3351 bool allow_store_transition = | 3352 bool allow_store_transition = |
| 3352 // Only remember the map transition if there is not an already existing | 3353 // Only remember the map transition if there is not an already existing |
| 3353 // non-matching element transition. | 3354 // non-matching element transition. |
| 3354 !start_map->IsUndefined() && !start_map->is_shared() && | 3355 !start_map->IsUndefined() && !start_map->is_shared() && |
| 3355 IsFastElementsKind(from_kind); | 3356 IsTransitionElementsKind(from_kind); |
| 3356 | 3357 |
| 3357 // Only store fast element maps in ascending generality. | 3358 // Only store fast element maps in ascending generality. |
| 3358 if (IsFastElementsKind(to_kind)) { | 3359 if (IsFastElementsKind(to_kind)) { |
| 3359 allow_store_transition &= | 3360 allow_store_transition &= |
| 3360 IsTransitionableFastElementsKind(from_kind) && | 3361 IsTransitionableFastElementsKind(from_kind) && |
| 3361 IsMoreGeneralElementsKindTransition(from_kind, to_kind); | 3362 IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
| 3362 } | 3363 } |
| 3363 | 3364 |
| 3364 if (!allow_store_transition) { | 3365 if (!allow_store_transition) { |
| 3365 return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION); | 3366 return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION); |
| 3366 } | 3367 } |
| 3367 | 3368 |
| 3368 return start_map->AsElementsKind(to_kind); | 3369 return start_map->AsElementsKind(to_kind); |
| 3369 } | 3370 } |
| 3370 | 3371 |
| 3371 | 3372 |
| 3372 MaybeObject* Map::AsElementsKind(ElementsKind kind) { | 3373 MaybeObject* Map::AsElementsKind(ElementsKind kind) { |
| 3373 Map* closest_map = FindClosestElementsTransition(this, kind); | 3374 Map* closest_map = FindClosestElementsTransition(this, kind); |
| 3374 | 3375 |
| 3375 if (closest_map->elements_kind() == kind) { | 3376 if (closest_map->elements_kind() == kind) { |
| 3376 return closest_map; | 3377 return closest_map; |
| 3377 } | 3378 } |
| 3378 | 3379 |
| 3379 return AddMissingElementsTransitions(closest_map, kind); | 3380 return AddMissingElementsTransitions(closest_map, kind); |
| 3380 } | 3381 } |
| 3381 | 3382 |
| 3382 | 3383 |
| 3384 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) { | |
| 3385 CALL_HEAP_FUNCTION(map->GetIsolate(), map->AsElementsKind(kind), Map); | |
| 3386 } | |
| 3387 | |
| 3388 | |
| 3383 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { | 3389 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { |
| 3384 DisallowHeapAllocation no_gc; | 3390 DisallowHeapAllocation no_gc; |
| 3385 if (IsJSGlobalProxy()) { | 3391 if (IsJSGlobalProxy()) { |
| 3386 Object* proto = GetPrototype(); | 3392 Object* proto = GetPrototype(); |
| 3387 if (proto->IsNull()) return result->NotFound(); | 3393 if (proto->IsNull()) return result->NotFound(); |
| 3388 ASSERT(proto->IsJSGlobalObject()); | 3394 ASSERT(proto->IsJSGlobalObject()); |
| 3389 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); | 3395 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); |
| 3390 } | 3396 } |
| 3391 | 3397 |
| 3392 if (HasFastProperties()) { | 3398 if (HasFastProperties()) { |
| (...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4722 | 4728 |
| 4723 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4729 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
| 4724 Handle<JSObject> object) { | 4730 Handle<JSObject> object) { |
| 4725 CALL_HEAP_FUNCTION(object->GetIsolate(), | 4731 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 4726 object->NormalizeElements(), | 4732 object->NormalizeElements(), |
| 4727 SeededNumberDictionary); | 4733 SeededNumberDictionary); |
| 4728 } | 4734 } |
| 4729 | 4735 |
| 4730 | 4736 |
| 4731 MaybeObject* JSObject::NormalizeElements() { | 4737 MaybeObject* JSObject::NormalizeElements() { |
| 4732 ASSERT(!HasExternalArrayElements()); | 4738 ASSERT(!HasExternalArrayElements() && !HasFixedTypedArrayElements()); |
| 4733 | 4739 |
| 4734 // Find the backing store. | 4740 // Find the backing store. |
| 4735 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 4741 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 4736 Map* old_map = array->map(); | 4742 Map* old_map = array->map(); |
| 4737 bool is_arguments = | 4743 bool is_arguments = |
| 4738 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 4744 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
| 4739 if (is_arguments) { | 4745 if (is_arguments) { |
| 4740 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 4746 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 4741 } | 4747 } |
| 4742 if (array->IsDictionary()) return array; | 4748 if (array->IsDictionary()) return array; |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5468 } | 5474 } |
| 5469 | 5475 |
| 5470 if (object->IsJSGlobalProxy()) { | 5476 if (object->IsJSGlobalProxy()) { |
| 5471 Handle<Object> proto(object->GetPrototype(), isolate); | 5477 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5472 if (proto->IsNull()) return object; | 5478 if (proto->IsNull()) return object; |
| 5473 ASSERT(proto->IsJSGlobalObject()); | 5479 ASSERT(proto->IsJSGlobalObject()); |
| 5474 return PreventExtensions(Handle<JSObject>::cast(proto)); | 5480 return PreventExtensions(Handle<JSObject>::cast(proto)); |
| 5475 } | 5481 } |
| 5476 | 5482 |
| 5477 // It's not possible to seal objects with external array elements | 5483 // It's not possible to seal objects with external array elements |
| 5478 if (object->HasExternalArrayElements()) { | 5484 if (object->HasExternalArrayElements() || |
| 5485 object->HasFixedTypedArrayElements()) { | |
| 5479 Handle<Object> error = | 5486 Handle<Object> error = |
| 5480 isolate->factory()->NewTypeError( | 5487 isolate->factory()->NewTypeError( |
| 5481 "cant_prevent_ext_external_array_elements", | 5488 "cant_prevent_ext_external_array_elements", |
| 5482 HandleVector(&object, 1)); | 5489 HandleVector(&object, 1)); |
| 5483 isolate->Throw(*error); | 5490 isolate->Throw(*error); |
| 5484 return Handle<Object>(); | 5491 return Handle<Object>(); |
| 5485 } | 5492 } |
| 5486 | 5493 |
| 5487 // If there are fast elements we normalize. | 5494 // If there are fast elements we normalize. |
| 5488 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 5495 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5548 } | 5555 } |
| 5549 | 5556 |
| 5550 if (object->IsJSGlobalProxy()) { | 5557 if (object->IsJSGlobalProxy()) { |
| 5551 Handle<Object> proto(object->GetPrototype(), isolate); | 5558 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5552 if (proto->IsNull()) return object; | 5559 if (proto->IsNull()) return object; |
| 5553 ASSERT(proto->IsJSGlobalObject()); | 5560 ASSERT(proto->IsJSGlobalObject()); |
| 5554 return Freeze(Handle<JSObject>::cast(proto)); | 5561 return Freeze(Handle<JSObject>::cast(proto)); |
| 5555 } | 5562 } |
| 5556 | 5563 |
| 5557 // It's not possible to freeze objects with external array elements | 5564 // It's not possible to freeze objects with external array elements |
| 5558 if (object->HasExternalArrayElements()) { | 5565 if (object->HasExternalArrayElements() || |
| 5566 object->HasFixedTypedArrayElements()) { | |
| 5559 Handle<Object> error = | 5567 Handle<Object> error = |
| 5560 isolate->factory()->NewTypeError( | 5568 isolate->factory()->NewTypeError( |
| 5561 "cant_prevent_ext_external_array_elements", | 5569 "cant_prevent_ext_external_array_elements", |
| 5562 HandleVector(&object, 1)); | 5570 HandleVector(&object, 1)); |
| 5563 isolate->Throw(*error); | 5571 isolate->Throw(*error); |
| 5564 return Handle<Object>(); | 5572 return Handle<Object>(); |
| 5565 } | 5573 } |
| 5566 | 5574 |
| 5567 Handle<SeededNumberDictionary> new_element_dictionary; | 5575 Handle<SeededNumberDictionary> new_element_dictionary; |
| 5568 if (!object->elements()->IsDictionary()) { | 5576 if (!object->elements()->IsDictionary()) { |
| (...skipping 6960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12529 Handle<Object> proto(object->GetPrototype(), isolate); | 12537 Handle<Object> proto(object->GetPrototype(), isolate); |
| 12530 if (proto->IsNull()) return value; | 12538 if (proto->IsNull()) return value; |
| 12531 ASSERT(proto->IsJSGlobalObject()); | 12539 ASSERT(proto->IsJSGlobalObject()); |
| 12532 return SetElement(Handle<JSObject>::cast(proto), index, value, attributes, | 12540 return SetElement(Handle<JSObject>::cast(proto), index, value, attributes, |
| 12533 strict_mode, | 12541 strict_mode, |
| 12534 check_prototype, | 12542 check_prototype, |
| 12535 set_mode); | 12543 set_mode); |
| 12536 } | 12544 } |
| 12537 | 12545 |
| 12538 // Don't allow element properties to be redefined for external arrays. | 12546 // Don't allow element properties to be redefined for external arrays. |
| 12539 if (object->HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { | 12547 if ((object->HasExternalArrayElements() || |
| 12548 object->HasFixedTypedArrayElements()) && | |
| 12549 set_mode == DEFINE_PROPERTY) { | |
| 12540 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12550 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12541 Handle<Object> args[] = { object, number }; | 12551 Handle<Object> args[] = { object, number }; |
| 12542 Handle<Object> error = isolate->factory()->NewTypeError( | 12552 Handle<Object> error = isolate->factory()->NewTypeError( |
| 12543 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); | 12553 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); |
| 12544 isolate->Throw(*error); | 12554 isolate->Throw(*error); |
| 12545 return Handle<Object>(); | 12555 return Handle<Object>(); |
| 12546 } | 12556 } |
| 12547 | 12557 |
| 12548 // Normalize the elements to enable attributes on the property. | 12558 // Normalize the elements to enable attributes on the property. |
| 12549 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { | 12559 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { |
| (...skipping 1916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14466 JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS); | 14476 JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS); |
| 14467 | 14477 |
| 14468 PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ? | 14478 PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ? |
| 14469 NOT_TENURED: TENURED; | 14479 NOT_TENURED: TENURED; |
| 14470 Handle<FixedArray> fast_elements = | 14480 Handle<FixedArray> fast_elements = |
| 14471 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure); | 14481 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure); |
| 14472 dict->CopyValuesTo(*fast_elements); | 14482 dict->CopyValuesTo(*fast_elements); |
| 14473 object->ValidateElements(); | 14483 object->ValidateElements(); |
| 14474 | 14484 |
| 14475 object->set_map_and_elements(*new_map, *fast_elements); | 14485 object->set_map_and_elements(*new_map, *fast_elements); |
| 14476 } else if (object->HasExternalArrayElements()) { | 14486 } else if (object->HasExternalArrayElements() || |
| 14477 // External arrays cannot have holes or undefined elements. | 14487 object->HasFixedTypedArrayElements()) { |
| 14488 // Typed arrays cannot have holes or undefined elements. | |
| 14478 return handle(Smi::FromInt( | 14489 return handle(Smi::FromInt( |
| 14479 ExternalArray::cast(object->elements())->length()), isolate); | 14490 FixedArrayBase::cast(object->elements())->length()), isolate); |
| 14480 } else if (!object->HasFastDoubleElements()) { | 14491 } else if (!object->HasFastDoubleElements()) { |
| 14481 EnsureWritableFastElements(object); | 14492 EnsureWritableFastElements(object); |
| 14482 } | 14493 } |
| 14483 ASSERT(object->HasFastSmiOrObjectElements() || | 14494 ASSERT(object->HasFastSmiOrObjectElements() || |
| 14484 object->HasFastDoubleElements()); | 14495 object->HasFastDoubleElements()); |
| 14485 | 14496 |
| 14486 // Collect holes at the end, undefined before that and the rest at the | 14497 // Collect holes at the end, undefined before that and the rest at the |
| 14487 // start, and return the number of non-hole, non-undefined values. | 14498 // start, and return the number of non-hole, non-undefined values. |
| 14488 | 14499 |
| 14489 Handle<FixedArrayBase> elements_base(object->elements()); | 14500 Handle<FixedArrayBase> elements_base(object->elements()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14570 } | 14581 } |
| 14571 | 14582 |
| 14572 return isolate->factory()->NewNumberFromUint(result); | 14583 return isolate->factory()->NewNumberFromUint(result); |
| 14573 } | 14584 } |
| 14574 | 14585 |
| 14575 | 14586 |
| 14576 ExternalArrayType JSTypedArray::type() { | 14587 ExternalArrayType JSTypedArray::type() { |
| 14577 switch (elements()->map()->instance_type()) { | 14588 switch (elements()->map()->instance_type()) { |
| 14578 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \ | 14589 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \ |
| 14579 case EXTERNAL_##TYPE##_ARRAY_TYPE: \ | 14590 case EXTERNAL_##TYPE##_ARRAY_TYPE: \ |
| 14591 case FIXED_##TYPE##_ARRAY_TYPE: \ | |
| 14580 return kExternal##Type##Array; | 14592 return kExternal##Type##Array; |
| 14581 | 14593 |
| 14582 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE) | 14594 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE) |
| 14583 #undef INSTANCE_TYPE_TO_ARRAY_TYPE | 14595 #undef INSTANCE_TYPE_TO_ARRAY_TYPE |
| 14584 | 14596 |
| 14585 default: | 14597 default: |
| 14598 UNREACHABLE(); | |
| 14586 return static_cast<ExternalArrayType>(-1); | 14599 return static_cast<ExternalArrayType>(-1); |
| 14587 } | 14600 } |
| 14588 } | 14601 } |
| 14589 | 14602 |
| 14590 | 14603 |
| 14591 size_t JSTypedArray::element_size() { | 14604 size_t JSTypedArray::element_size() { |
| 14592 switch (elements()->map()->instance_type()) { | 14605 switch (elements()->map()->instance_type()) { |
| 14593 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \ | 14606 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \ |
| 14594 case EXTERNAL_##TYPE##_ARRAY_TYPE: \ | 14607 case EXTERNAL_##TYPE##_ARRAY_TYPE: \ |
| 14595 return size; | 14608 return size; |
| (...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16433 } | 16446 } |
| 16434 | 16447 |
| 16435 | 16448 |
| 16436 void JSTypedArray::Neuter() { | 16449 void JSTypedArray::Neuter() { |
| 16437 NeuterView(); | 16450 NeuterView(); |
| 16438 set_length(Smi::FromInt(0)); | 16451 set_length(Smi::FromInt(0)); |
| 16439 set_elements(GetHeap()->EmptyExternalArrayForMap(map())); | 16452 set_elements(GetHeap()->EmptyExternalArrayForMap(map())); |
| 16440 } | 16453 } |
| 16441 | 16454 |
| 16442 | 16455 |
| 16456 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) { | |
| 16457 switch (elements_kind) { | |
| 16458 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
| 16459 case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS; | |
| 16460 | |
| 16461 TYPED_ARRAYS(TYPED_ARRAY_CASE) | |
| 16462 #undef TYPED_ARRAY_CASE | |
| 16463 | |
| 16464 default: | |
| 16465 UNREACHABLE(); | |
| 16466 return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND; | |
| 16467 } | |
| 16468 } | |
| 16469 | |
| 16470 | |
| 16471 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer( | |
| 16472 Handle<JSTypedArray> typed_array) { | |
| 16473 | |
| 16474 Handle<Map> map(typed_array->map()); | |
| 16475 Isolate* isolate = typed_array->GetIsolate(); | |
| 16476 | |
| 16477 ASSERT(IsFixedTypedArrayElementsKind(map->elements_kind())); | |
| 16478 | |
| 16479 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | |
| 16480 Handle<FixedTypedArrayBase> fixed_typed_array( | |
| 16481 FixedTypedArrayBase::cast(typed_array->elements())); | |
| 16482 Runtime::SetupArrayBufferAllocatingData(isolate, buffer, | |
| 16483 fixed_typed_array->DataSize(), false); | |
| 16484 memcpy(buffer->backing_store(), | |
| 16485 fixed_typed_array->DataPtr(), | |
| 16486 fixed_typed_array->DataSize()); | |
| 16487 Handle<ExternalArray> new_elements = | |
| 16488 isolate->factory()->NewExternalArray( | |
| 16489 fixed_typed_array->length(), typed_array->type(), | |
| 16490 static_cast<uint8_t*>(buffer->backing_store())); | |
| 16491 Handle<Map> new_map = | |
| 16492 isolate->factory()->GetElementsTransitionMap( | |
| 16493 typed_array, | |
| 16494 FixedToExternalElementsKind(map->elements_kind())); | |
| 16495 | |
| 16496 buffer->set_weak_first_view(*typed_array); | |
| 16497 ASSERT(typed_array->weak_next() == isolate->heap()->undefined_value()); | |
| 16498 typed_array->set_buffer(*buffer); | |
| 16499 typed_array->set_map_and_elements(*new_map, *new_elements); | |
| 16500 | |
| 16501 return buffer; | |
| 16502 } | |
| 16503 | |
| 16504 | |
| 16505 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() { | |
| 16506 Handle<Object> result(buffer(), GetIsolate()); | |
| 16507 if (*result != Smi::FromInt(0)) { | |
| 16508 ASSERT(IsExternalArrayElementsKind(map()->elements_kind())); | |
| 16509 return Handle<JSArrayBuffer>::cast(result); | |
| 16510 } | |
| 16511 Handle<JSTypedArray> self(this); | |
| 16512 return MaterializeArrayBuffer(self); | |
| 16513 } | |
| 16514 | |
| 16515 | |
| 16443 HeapType* PropertyCell::type() { | 16516 HeapType* PropertyCell::type() { |
| 16444 return static_cast<HeapType*>(type_raw()); | 16517 return static_cast<HeapType*>(type_raw()); |
| 16445 } | 16518 } |
| 16446 | 16519 |
| 16447 | 16520 |
| 16448 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) { | 16521 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) { |
| 16449 ASSERT(IsPropertyCell()); | 16522 ASSERT(IsPropertyCell()); |
| 16450 set_type_raw(type, ignored); | 16523 set_type_raw(type, ignored); |
| 16451 } | 16524 } |
| 16452 | 16525 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16501 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16574 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16502 static const char* error_messages_[] = { | 16575 static const char* error_messages_[] = { |
| 16503 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16576 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16504 }; | 16577 }; |
| 16505 #undef ERROR_MESSAGES_TEXTS | 16578 #undef ERROR_MESSAGES_TEXTS |
| 16506 return error_messages_[reason]; | 16579 return error_messages_[reason]; |
| 16507 } | 16580 } |
| 16508 | 16581 |
| 16509 | 16582 |
| 16510 } } // namespace v8::internal | 16583 } } // namespace v8::internal |
| OLD | NEW |