| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3056 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 3056 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 3057 Map* old_map = array->map(); | 3057 Map* old_map = array->map(); |
| 3058 bool is_arguments = | 3058 bool is_arguments = |
| 3059 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 3059 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
| 3060 if (is_arguments) { | 3060 if (is_arguments) { |
| 3061 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 3061 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 3062 } | 3062 } |
| 3063 if (array->IsDictionary()) return array; | 3063 if (array->IsDictionary()) return array; |
| 3064 | 3064 |
| 3065 ASSERT(HasFastElements() || | 3065 ASSERT(HasFastElements() || |
| 3066 HasFastSmiOnlyElements() || |
| 3066 HasFastDoubleElements() || | 3067 HasFastDoubleElements() || |
| 3067 HasFastArgumentsElements()); | 3068 HasFastArgumentsElements()); |
| 3068 // Compute the effective length and allocate a new backing store. | 3069 // Compute the effective length and allocate a new backing store. |
| 3069 int length = IsJSArray() | 3070 int length = IsJSArray() |
| 3070 ? Smi::cast(JSArray::cast(this)->length())->value() | 3071 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3071 : array->length(); | 3072 : array->length(); |
| 3072 int old_capacity = 0; | 3073 int old_capacity = 0; |
| 3073 int used_elements = 0; | 3074 int used_elements = 0; |
| 3074 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 3075 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 3075 NumberDictionary* dictionary = NULL; | 3076 NumberDictionary* dictionary = NULL; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3090 } else { | 3091 } else { |
| 3091 // Objects must be allocated in the old object space, since the | 3092 // Objects must be allocated in the old object space, since the |
| 3092 // overall number of HeapNumbers needed for the conversion might | 3093 // overall number of HeapNumbers needed for the conversion might |
| 3093 // exceed the capacity of new space, and we would fail repeatedly | 3094 // exceed the capacity of new space, and we would fail repeatedly |
| 3094 // trying to convert the FixedDoubleArray. | 3095 // trying to convert the FixedDoubleArray. |
| 3095 MaybeObject* maybe_value_object = | 3096 MaybeObject* maybe_value_object = |
| 3096 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 3097 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 3097 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 3098 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 3098 } | 3099 } |
| 3099 } else { | 3100 } else { |
| 3100 ASSERT(old_map->has_fast_elements()); | 3101 ASSERT(old_map->has_fast_elements() || |
| 3102 old_map->has_fast_smi_only_elements()); |
| 3101 value = FixedArray::cast(array)->get(i); | 3103 value = FixedArray::cast(array)->get(i); |
| 3102 } | 3104 } |
| 3103 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 3105 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 3104 if (!value->IsTheHole()) { | 3106 if (!value->IsTheHole()) { |
| 3105 Object* result; | 3107 Object* result; |
| 3106 MaybeObject* maybe_result = | 3108 MaybeObject* maybe_result = |
| 3107 dictionary->AddNumberEntry(i, value, details); | 3109 dictionary->AddNumberEntry(i, value, details); |
| 3108 if (!maybe_result->ToObject(&result)) return maybe_result; | 3110 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3109 dictionary = NumberDictionary::cast(result); | 3111 dictionary = NumberDictionary::cast(result); |
| 3110 } | 3112 } |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3405 } | 3407 } |
| 3406 // Make sure the properties are normalized before removing the entry. | 3408 // Make sure the properties are normalized before removing the entry. |
| 3407 return DeleteNormalizedProperty(name, mode); | 3409 return DeleteNormalizedProperty(name, mode); |
| 3408 } | 3410 } |
| 3409 } | 3411 } |
| 3410 | 3412 |
| 3411 | 3413 |
| 3412 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 3414 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 3413 ElementsKind kind, | 3415 ElementsKind kind, |
| 3414 Object* object) { | 3416 Object* object) { |
| 3415 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); | 3417 ASSERT(kind == FAST_ELEMENTS || |
| 3418 kind == DICTIONARY_ELEMENTS); |
| 3416 if (kind == FAST_ELEMENTS) { | 3419 if (kind == FAST_ELEMENTS) { |
| 3417 int length = IsJSArray() | 3420 int length = IsJSArray() |
| 3418 ? Smi::cast(JSArray::cast(this)->length())->value() | 3421 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3419 : elements->length(); | 3422 : elements->length(); |
| 3420 for (int i = 0; i < length; ++i) { | 3423 for (int i = 0; i < length; ++i) { |
| 3421 Object* element = elements->get(i); | 3424 Object* element = elements->get(i); |
| 3422 if (!element->IsTheHole() && element == object) return true; | 3425 if (!element->IsTheHole() && element == object) return true; |
| 3423 } | 3426 } |
| 3424 } else { | 3427 } else { |
| 3425 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); | 3428 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3460 case EXTERNAL_SHORT_ELEMENTS: | 3463 case EXTERNAL_SHORT_ELEMENTS: |
| 3461 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3464 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3462 case EXTERNAL_INT_ELEMENTS: | 3465 case EXTERNAL_INT_ELEMENTS: |
| 3463 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3466 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3464 case EXTERNAL_FLOAT_ELEMENTS: | 3467 case EXTERNAL_FLOAT_ELEMENTS: |
| 3465 case EXTERNAL_DOUBLE_ELEMENTS: | 3468 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3466 case FAST_DOUBLE_ELEMENTS: | 3469 case FAST_DOUBLE_ELEMENTS: |
| 3467 // Raw pixels and external arrays do not reference other | 3470 // Raw pixels and external arrays do not reference other |
| 3468 // objects. | 3471 // objects. |
| 3469 break; | 3472 break; |
| 3473 case FAST_SMI_ONLY_ELEMENTS: |
| 3474 break; |
| 3470 case FAST_ELEMENTS: | 3475 case FAST_ELEMENTS: |
| 3471 case DICTIONARY_ELEMENTS: { | 3476 case DICTIONARY_ELEMENTS: { |
| 3472 FixedArray* elements = FixedArray::cast(this->elements()); | 3477 FixedArray* elements = FixedArray::cast(this->elements()); |
| 3473 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 3478 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 3474 break; | 3479 break; |
| 3475 } | 3480 } |
| 3476 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 3481 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 3477 FixedArray* parameter_map = FixedArray::cast(elements()); | 3482 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 3478 // Check the mapped parameters. | 3483 // Check the mapped parameters. |
| 3479 int length = parameter_map->length(); | 3484 int length = parameter_map->length(); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3751 | 3756 |
| 3752 if (!CanSetCallback(name)) { | 3757 if (!CanSetCallback(name)) { |
| 3753 return heap->undefined_value(); | 3758 return heap->undefined_value(); |
| 3754 } | 3759 } |
| 3755 | 3760 |
| 3756 uint32_t index = 0; | 3761 uint32_t index = 0; |
| 3757 bool is_element = name->AsArrayIndex(&index); | 3762 bool is_element = name->AsArrayIndex(&index); |
| 3758 | 3763 |
| 3759 if (is_element) { | 3764 if (is_element) { |
| 3760 switch (GetElementsKind()) { | 3765 switch (GetElementsKind()) { |
| 3766 case FAST_SMI_ONLY_ELEMENTS: |
| 3761 case FAST_ELEMENTS: | 3767 case FAST_ELEMENTS: |
| 3762 case FAST_DOUBLE_ELEMENTS: | 3768 case FAST_DOUBLE_ELEMENTS: |
| 3763 break; | 3769 break; |
| 3764 case EXTERNAL_PIXEL_ELEMENTS: | 3770 case EXTERNAL_PIXEL_ELEMENTS: |
| 3765 case EXTERNAL_BYTE_ELEMENTS: | 3771 case EXTERNAL_BYTE_ELEMENTS: |
| 3766 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3772 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3767 case EXTERNAL_SHORT_ELEMENTS: | 3773 case EXTERNAL_SHORT_ELEMENTS: |
| 3768 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3774 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3769 case EXTERNAL_INT_ELEMENTS: | 3775 case EXTERNAL_INT_ELEMENTS: |
| 3770 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3776 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4000 } | 4006 } |
| 4001 | 4007 |
| 4002 uint32_t index = 0; | 4008 uint32_t index = 0; |
| 4003 bool is_element = name->AsArrayIndex(&index); | 4009 bool is_element = name->AsArrayIndex(&index); |
| 4004 | 4010 |
| 4005 if (is_element) { | 4011 if (is_element) { |
| 4006 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4012 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 4007 | 4013 |
| 4008 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4014 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 4009 switch (GetElementsKind()) { | 4015 switch (GetElementsKind()) { |
| 4016 case FAST_SMI_ONLY_ELEMENTS: |
| 4010 case FAST_ELEMENTS: | 4017 case FAST_ELEMENTS: |
| 4011 case FAST_DOUBLE_ELEMENTS: | 4018 case FAST_DOUBLE_ELEMENTS: |
| 4012 break; | 4019 break; |
| 4013 case EXTERNAL_PIXEL_ELEMENTS: | 4020 case EXTERNAL_PIXEL_ELEMENTS: |
| 4014 case EXTERNAL_BYTE_ELEMENTS: | 4021 case EXTERNAL_BYTE_ELEMENTS: |
| 4015 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4022 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4016 case EXTERNAL_SHORT_ELEMENTS: | 4023 case EXTERNAL_SHORT_ELEMENTS: |
| 4017 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4024 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4018 case EXTERNAL_INT_ELEMENTS: | 4025 case EXTERNAL_INT_ELEMENTS: |
| 4019 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4026 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| (...skipping 3389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7409 for (int i = 0; i < source->Capacity(); ++i) { | 7416 for (int i = 0; i < source->Capacity(); ++i) { |
| 7410 Object* key = source->KeyAt(i); | 7417 Object* key = source->KeyAt(i); |
| 7411 if (key->IsNumber()) { | 7418 if (key->IsNumber()) { |
| 7412 uint32_t entry = static_cast<uint32_t>(key->Number()); | 7419 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 7413 destination->set(entry, source->ValueAt(i), mode); | 7420 destination->set(entry, source->ValueAt(i), mode); |
| 7414 } | 7421 } |
| 7415 } | 7422 } |
| 7416 } | 7423 } |
| 7417 | 7424 |
| 7418 | 7425 |
| 7419 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, | 7426 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
| 7420 int length) { | 7427 int capacity, |
| 7428 int length, |
| 7429 SetFastElementsCapacityMode set_capacity_mode) { |
| 7421 Heap* heap = GetHeap(); | 7430 Heap* heap = GetHeap(); |
| 7422 // We should never end in here with a pixel or external array. | 7431 // We should never end in here with a pixel or external array. |
| 7423 ASSERT(!HasExternalArrayElements()); | 7432 ASSERT(!HasExternalArrayElements()); |
| 7424 | 7433 |
| 7425 // Allocate a new fast elements backing store. | 7434 // Allocate a new fast elements backing store. |
| 7426 FixedArray* new_elements = NULL; | 7435 FixedArray* new_elements = NULL; |
| 7427 { Object* object; | 7436 { Object* object; |
| 7428 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 7437 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
| 7429 if (!maybe->ToObject(&object)) return maybe; | 7438 if (!maybe->ToObject(&object)) return maybe; |
| 7430 new_elements = FixedArray::cast(object); | 7439 new_elements = FixedArray::cast(object); |
| 7431 } | 7440 } |
| 7432 | 7441 |
| 7433 // Find the new map to use for this object if there is a map change. | 7442 // Find the new map to use for this object if there is a map change. |
| 7434 Map* new_map = NULL; | 7443 Map* new_map = NULL; |
| 7435 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 7444 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
| 7436 Object* object; | 7445 Object* object; |
| 7437 MaybeObject* maybe = GetElementsTransitionMap(FAST_ELEMENTS); | 7446 bool has_fast_smi_only_elements = |
| 7447 FLAG_smi_only_arrays && |
| 7448 (set_capacity_mode == kAllowSmiOnlyElements) && |
| 7449 (elements()->map()->has_fast_smi_only_elements() || |
| 7450 elements() == heap->empty_fixed_array()); |
| 7451 ElementsKind elements_kind = has_fast_smi_only_elements |
| 7452 ? FAST_SMI_ONLY_ELEMENTS |
| 7453 : FAST_ELEMENTS; |
| 7454 MaybeObject* maybe = GetElementsTransitionMap(elements_kind); |
| 7438 if (!maybe->ToObject(&object)) return maybe; | 7455 if (!maybe->ToObject(&object)) return maybe; |
| 7439 new_map = Map::cast(object); | 7456 new_map = Map::cast(object); |
| 7440 } | 7457 } |
| 7441 | 7458 |
| 7442 switch (GetElementsKind()) { | 7459 ElementsKind elements_kind = GetElementsKind(); |
| 7460 switch (elements_kind) { |
| 7461 case FAST_SMI_ONLY_ELEMENTS: |
| 7443 case FAST_ELEMENTS: { | 7462 case FAST_ELEMENTS: { |
| 7444 AssertNoAllocation no_gc; | 7463 AssertNoAllocation no_gc; |
| 7445 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7464 WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc)); |
| 7446 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 7465 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); |
| 7447 set_map(new_map); | 7466 set_map(new_map); |
| 7448 set_elements(new_elements); | 7467 set_elements(new_elements); |
| 7449 break; | 7468 break; |
| 7450 } | 7469 } |
| 7451 case DICTIONARY_ELEMENTS: { | 7470 case DICTIONARY_ELEMENTS: { |
| 7452 AssertNoAllocation no_gc; | 7471 AssertNoAllocation no_gc; |
| 7453 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7472 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7454 CopySlowElementsToFast(NumberDictionary::cast(elements()), | 7473 CopySlowElementsToFast(NumberDictionary::cast(elements()), |
| 7455 new_elements, | 7474 new_elements, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7538 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); | 7557 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); |
| 7539 | 7558 |
| 7540 { MaybeObject* maybe_obj = | 7559 { MaybeObject* maybe_obj = |
| 7541 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); | 7560 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); |
| 7542 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7561 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7543 } | 7562 } |
| 7544 Map* new_map = Map::cast(obj); | 7563 Map* new_map = Map::cast(obj); |
| 7545 | 7564 |
| 7546 AssertNoAllocation no_gc; | 7565 AssertNoAllocation no_gc; |
| 7547 switch (GetElementsKind()) { | 7566 switch (GetElementsKind()) { |
| 7567 case FAST_SMI_ONLY_ELEMENTS: |
| 7548 case FAST_ELEMENTS: { | 7568 case FAST_ELEMENTS: { |
| 7549 elems->Initialize(FixedArray::cast(elements())); | 7569 elems->Initialize(FixedArray::cast(elements())); |
| 7550 break; | 7570 break; |
| 7551 } | 7571 } |
| 7552 case FAST_DOUBLE_ELEMENTS: { | 7572 case FAST_DOUBLE_ELEMENTS: { |
| 7553 elems->Initialize(FixedDoubleArray::cast(elements())); | 7573 elems->Initialize(FixedDoubleArray::cast(elements())); |
| 7554 break; | 7574 break; |
| 7555 } | 7575 } |
| 7556 case DICTIONARY_ELEMENTS: { | 7576 case DICTIONARY_ELEMENTS: { |
| 7557 elems->Initialize(NumberDictionary::cast(elements())); | 7577 elems->Initialize(NumberDictionary::cast(elements())); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 7575 } | 7595 } |
| 7576 | 7596 |
| 7577 | 7597 |
| 7578 MaybeObject* JSObject::SetSlowElements(Object* len) { | 7598 MaybeObject* JSObject::SetSlowElements(Object* len) { |
| 7579 // We should never end in here with a pixel or external array. | 7599 // We should never end in here with a pixel or external array. |
| 7580 ASSERT(!HasExternalArrayElements()); | 7600 ASSERT(!HasExternalArrayElements()); |
| 7581 | 7601 |
| 7582 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 7602 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 7583 | 7603 |
| 7584 switch (GetElementsKind()) { | 7604 switch (GetElementsKind()) { |
| 7585 case FAST_ELEMENTS: { | 7605 case FAST_SMI_ONLY_ELEMENTS: |
| 7586 case FAST_DOUBLE_ELEMENTS: | 7606 case FAST_ELEMENTS: |
| 7607 case FAST_DOUBLE_ELEMENTS: { |
| 7587 // Make sure we never try to shrink dense arrays into sparse arrays. | 7608 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 7588 ASSERT(static_cast<uint32_t>( | 7609 ASSERT(static_cast<uint32_t>( |
| 7589 FixedArrayBase::cast(elements())->length()) <= new_length); | 7610 FixedArrayBase::cast(elements())->length()) <= new_length); |
| 7590 MaybeObject* result = NormalizeElements(); | 7611 MaybeObject* result = NormalizeElements(); |
| 7591 if (result->IsFailure()) return result; | 7612 if (result->IsFailure()) return result; |
| 7592 | 7613 |
| 7593 // Update length for JSArrays. | 7614 // Update length for JSArrays. |
| 7594 if (IsJSArray()) JSArray::cast(this)->set_length(len); | 7615 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 7595 break; | 7616 break; |
| 7596 } | 7617 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7642 | 7663 |
| 7643 | 7664 |
| 7644 void JSArray::Expand(int required_size) { | 7665 void JSArray::Expand(int required_size) { |
| 7645 Handle<JSArray> self(this); | 7666 Handle<JSArray> self(this); |
| 7646 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 7667 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 7647 int old_size = old_backing->length(); | 7668 int old_size = old_backing->length(); |
| 7648 int new_size = required_size > old_size ? required_size : old_size; | 7669 int new_size = required_size > old_size ? required_size : old_size; |
| 7649 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); | 7670 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 7650 // Can't use this any more now because we may have had a GC! | 7671 // Can't use this any more now because we may have had a GC! |
| 7651 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 7672 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 7652 self->SetContent(*new_backing); | 7673 GetIsolate()->factory()->SetContent(self, new_backing); |
| 7653 } | 7674 } |
| 7654 | 7675 |
| 7655 | 7676 |
| 7656 static Failure* ArrayLengthRangeError(Heap* heap) { | 7677 static Failure* ArrayLengthRangeError(Heap* heap) { |
| 7657 HandleScope scope(heap->isolate()); | 7678 HandleScope scope(heap->isolate()); |
| 7658 return heap->isolate()->Throw( | 7679 return heap->isolate()->Throw( |
| 7659 *FACTORY->NewRangeError("invalid_array_length", | 7680 *FACTORY->NewRangeError("invalid_array_length", |
| 7660 HandleVector<Object>(NULL, 0))); | 7681 HandleVector<Object>(NULL, 0))); |
| 7661 } | 7682 } |
| 7662 | 7683 |
| 7663 | 7684 |
| 7664 MaybeObject* JSObject::SetElementsLength(Object* len) { | 7685 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 7665 // We should never end in here with a pixel or external array. | 7686 // We should never end in here with a pixel or external array. |
| 7666 ASSERT(AllowsSetElementsLength()); | 7687 ASSERT(AllowsSetElementsLength()); |
| 7667 | 7688 |
| 7668 MaybeObject* maybe_smi_length = len->ToSmi(); | 7689 MaybeObject* maybe_smi_length = len->ToSmi(); |
| 7669 Object* smi_length = Smi::FromInt(0); | 7690 Object* smi_length = Smi::FromInt(0); |
| 7670 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 7691 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 7671 const int value = Smi::cast(smi_length)->value(); | 7692 const int value = Smi::cast(smi_length)->value(); |
| 7672 if (value < 0) return ArrayLengthRangeError(GetHeap()); | 7693 if (value < 0) return ArrayLengthRangeError(GetHeap()); |
| 7673 ElementsKind elements_kind = GetElementsKind(); | 7694 ElementsKind elements_kind = GetElementsKind(); |
| 7674 switch (elements_kind) { | 7695 switch (elements_kind) { |
| 7696 case FAST_SMI_ONLY_ELEMENTS: |
| 7675 case FAST_ELEMENTS: | 7697 case FAST_ELEMENTS: |
| 7676 case FAST_DOUBLE_ELEMENTS: { | 7698 case FAST_DOUBLE_ELEMENTS: { |
| 7677 int old_capacity = FixedArrayBase::cast(elements())->length(); | 7699 int old_capacity = FixedArrayBase::cast(elements())->length(); |
| 7678 if (value <= old_capacity) { | 7700 if (value <= old_capacity) { |
| 7679 if (IsJSArray()) { | 7701 if (IsJSArray()) { |
| 7680 Object* obj; | 7702 Object* obj; |
| 7681 if (elements_kind == FAST_ELEMENTS) { | 7703 if (elements_kind == FAST_ELEMENTS || |
| 7704 elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 7682 MaybeObject* maybe_obj = EnsureWritableFastElements(); | 7705 MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 7683 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7706 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7684 } | 7707 } |
| 7685 if (2 * value <= old_capacity) { | 7708 if (2 * value <= old_capacity) { |
| 7686 // If more than half the elements won't be used, trim the array. | 7709 // If more than half the elements won't be used, trim the array. |
| 7687 if (value == 0) { | 7710 if (value == 0) { |
| 7688 initialize_elements(); | 7711 initialize_elements(); |
| 7689 } else { | 7712 } else { |
| 7690 Address filler_start; | 7713 Address filler_start; |
| 7691 int filler_size; | 7714 int filler_size; |
| 7692 if (GetElementsKind() == FAST_ELEMENTS) { | 7715 if (elements_kind == FAST_ELEMENTS || |
| 7716 elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 7693 FixedArray* fast_elements = FixedArray::cast(elements()); | 7717 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7694 fast_elements->set_length(value); | 7718 fast_elements->set_length(value); |
| 7695 filler_start = fast_elements->address() + | 7719 filler_start = fast_elements->address() + |
| 7696 FixedArray::OffsetOfElementAt(value); | 7720 FixedArray::OffsetOfElementAt(value); |
| 7697 filler_size = (old_capacity - value) * kPointerSize; | 7721 filler_size = (old_capacity - value) * kPointerSize; |
| 7698 } else { | 7722 } else { |
| 7699 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7723 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); |
| 7700 FixedDoubleArray* fast_double_elements = | 7724 FixedDoubleArray* fast_double_elements = |
| 7701 FixedDoubleArray::cast(elements()); | 7725 FixedDoubleArray::cast(elements()); |
| 7702 fast_double_elements->set_length(value); | 7726 fast_double_elements->set_length(value); |
| 7703 filler_start = fast_double_elements->address() + | 7727 filler_start = fast_double_elements->address() + |
| 7704 FixedDoubleArray::OffsetOfElementAt(value); | 7728 FixedDoubleArray::OffsetOfElementAt(value); |
| 7705 filler_size = (old_capacity - value) * kDoubleSize; | 7729 filler_size = (old_capacity - value) * kDoubleSize; |
| 7706 } | 7730 } |
| 7707 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | 7731 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); |
| 7708 } | 7732 } |
| 7709 } else { | 7733 } else { |
| 7710 // Otherwise, fill the unused tail with holes. | 7734 // Otherwise, fill the unused tail with holes. |
| 7711 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 7735 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| 7712 if (GetElementsKind() == FAST_ELEMENTS) { | 7736 if (elements_kind == FAST_ELEMENTS || |
| 7737 elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 7713 FixedArray* fast_elements = FixedArray::cast(elements()); | 7738 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7714 for (int i = value; i < old_length; i++) { | 7739 for (int i = value; i < old_length; i++) { |
| 7715 fast_elements->set_the_hole(i); | 7740 fast_elements->set_the_hole(i); |
| 7716 } | 7741 } |
| 7717 } else { | 7742 } else { |
| 7718 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7743 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); |
| 7719 FixedDoubleArray* fast_double_elements = | 7744 FixedDoubleArray* fast_double_elements = |
| 7720 FixedDoubleArray::cast(elements()); | 7745 FixedDoubleArray::cast(elements()); |
| 7721 for (int i = value; i < old_length; i++) { | 7746 for (int i = value; i < old_length; i++) { |
| 7722 fast_double_elements->set_the_hole(i); | 7747 fast_double_elements->set_the_hole(i); |
| 7723 } | 7748 } |
| 7724 } | 7749 } |
| 7725 } | 7750 } |
| 7726 JSArray::cast(this)->set_length(Smi::cast(smi_length)); | 7751 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 7727 } | 7752 } |
| 7728 return this; | 7753 return this; |
| 7729 } | 7754 } |
| 7730 int min = NewElementsCapacity(old_capacity); | 7755 int min = NewElementsCapacity(old_capacity); |
| 7731 int new_capacity = value > min ? value : min; | 7756 int new_capacity = value > min ? value : min; |
| 7732 if (!ShouldConvertToSlowElements(new_capacity)) { | 7757 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 7733 MaybeObject* result; | 7758 MaybeObject* result; |
| 7734 if (GetElementsKind() == FAST_ELEMENTS) { | 7759 if (elements_kind == FAST_ELEMENTS || |
| 7735 result = SetFastElementsCapacityAndLength(new_capacity, value); | 7760 elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 7761 SetFastElementsCapacityMode set_capacity_mode = |
| 7762 elements_kind == FAST_SMI_ONLY_ELEMENTS |
| 7763 ? kAllowSmiOnlyElements |
| 7764 : kDontAllowSmiOnlyElements; |
| 7765 result = SetFastElementsCapacityAndLength(new_capacity, |
| 7766 value, |
| 7767 set_capacity_mode); |
| 7736 } else { | 7768 } else { |
| 7737 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7769 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); |
| 7738 result = SetFastDoubleElementsCapacityAndLength(new_capacity, | 7770 result = SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 7739 value); | 7771 value); |
| 7740 } | 7772 } |
| 7741 if (result->IsFailure()) return result; | 7773 if (result->IsFailure()) return result; |
| 7742 return this; | 7774 return this; |
| 7743 } | 7775 } |
| 7744 break; | 7776 break; |
| 7745 } | 7777 } |
| 7746 case DICTIONARY_ELEMENTS: { | 7778 case DICTIONARY_ELEMENTS: { |
| 7747 if (IsJSArray()) { | 7779 if (IsJSArray()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7784 if (len->ToArrayIndex(&length)) { | 7816 if (len->ToArrayIndex(&length)) { |
| 7785 return SetSlowElements(len); | 7817 return SetSlowElements(len); |
| 7786 } else { | 7818 } else { |
| 7787 return ArrayLengthRangeError(GetHeap()); | 7819 return ArrayLengthRangeError(GetHeap()); |
| 7788 } | 7820 } |
| 7789 } | 7821 } |
| 7790 | 7822 |
| 7791 // len is not a number so make the array size one and | 7823 // len is not a number so make the array size one and |
| 7792 // set only element to len. | 7824 // set only element to len. |
| 7793 Object* obj; | 7825 Object* obj; |
| 7794 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); | 7826 MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); |
| 7795 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7827 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7796 } | |
| 7797 FixedArray::cast(obj)->set(0, len); | 7828 FixedArray::cast(obj)->set(0, len); |
| 7829 |
| 7830 maybe_obj = EnsureCanContainElements(&len, 1); |
| 7831 if (maybe_obj->IsFailure()) return maybe_obj; |
| 7832 |
| 7798 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | 7833 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 7799 set_elements(FixedArray::cast(obj)); | 7834 set_elements(FixedArray::cast(obj)); |
| 7800 return this; | 7835 return this; |
| 7801 } | 7836 } |
| 7802 | 7837 |
| 7803 | 7838 |
| 7804 Object* Map::GetPrototypeTransition(Object* prototype) { | 7839 Object* Map::GetPrototypeTransition(Object* prototype) { |
| 7805 FixedArray* cache = prototype_transitions(); | 7840 FixedArray* cache = prototype_transitions(); |
| 7806 int number_of_transitions = NumberOfProtoTransitions(); | 7841 int number_of_transitions = NumberOfProtoTransitions(); |
| 7807 const int proto_offset = | 7842 const int proto_offset = |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7935 } | 7970 } |
| 7936 ASSERT(Map::cast(new_map)->prototype() == value); | 7971 ASSERT(Map::cast(new_map)->prototype() == value); |
| 7937 real_receiver->set_map(Map::cast(new_map)); | 7972 real_receiver->set_map(Map::cast(new_map)); |
| 7938 | 7973 |
| 7939 heap->ClearInstanceofCache(); | 7974 heap->ClearInstanceofCache(); |
| 7940 ASSERT(size == Size()); | 7975 ASSERT(size == Size()); |
| 7941 return value; | 7976 return value; |
| 7942 } | 7977 } |
| 7943 | 7978 |
| 7944 | 7979 |
| 7980 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
| 7981 uint32_t first_arg, |
| 7982 uint32_t arg_count) { |
| 7983 return EnsureCanContainElements(args->arguments() - first_arg, arg_count); |
| 7984 } |
| 7985 |
| 7986 |
| 7945 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { | 7987 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
| 7946 switch (GetElementsKind()) { | 7988 switch (GetElementsKind()) { |
| 7989 case FAST_SMI_ONLY_ELEMENTS: |
| 7947 case FAST_ELEMENTS: { | 7990 case FAST_ELEMENTS: { |
| 7948 uint32_t length = IsJSArray() ? | 7991 uint32_t length = IsJSArray() ? |
| 7949 static_cast<uint32_t> | 7992 static_cast<uint32_t> |
| 7950 (Smi::cast(JSArray::cast(this)->length())->value()) : | 7993 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7951 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 7994 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7952 if ((index < length) && | 7995 if ((index < length) && |
| 7953 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 7996 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7954 return true; | 7997 return true; |
| 7955 } | 7998 } |
| 7956 break; | 7999 break; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8078 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 8121 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
| 8079 : UNDEFINED_ELEMENT; | 8122 : UNDEFINED_ELEMENT; |
| 8080 } | 8123 } |
| 8081 | 8124 |
| 8082 // Handle [] on String objects. | 8125 // Handle [] on String objects. |
| 8083 if (this->IsStringObjectWithCharacterAt(index)) { | 8126 if (this->IsStringObjectWithCharacterAt(index)) { |
| 8084 return STRING_CHARACTER_ELEMENT; | 8127 return STRING_CHARACTER_ELEMENT; |
| 8085 } | 8128 } |
| 8086 | 8129 |
| 8087 switch (GetElementsKind()) { | 8130 switch (GetElementsKind()) { |
| 8131 case FAST_SMI_ONLY_ELEMENTS: |
| 8088 case FAST_ELEMENTS: { | 8132 case FAST_ELEMENTS: { |
| 8089 uint32_t length = IsJSArray() ? | 8133 uint32_t length = IsJSArray() ? |
| 8090 static_cast<uint32_t> | 8134 static_cast<uint32_t> |
| 8091 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8135 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8092 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8136 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 8093 if ((index < length) && | 8137 if ((index < length) && |
| 8094 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8138 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 8095 return FAST_ELEMENT; | 8139 return FAST_ELEMENT; |
| 8096 } | 8140 } |
| 8097 break; | 8141 break; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8192 } | 8236 } |
| 8193 } | 8237 } |
| 8194 | 8238 |
| 8195 // Check for lookup interceptor | 8239 // Check for lookup interceptor |
| 8196 if (HasIndexedInterceptor()) { | 8240 if (HasIndexedInterceptor()) { |
| 8197 return HasElementWithInterceptor(receiver, index); | 8241 return HasElementWithInterceptor(receiver, index); |
| 8198 } | 8242 } |
| 8199 | 8243 |
| 8200 ElementsKind kind = GetElementsKind(); | 8244 ElementsKind kind = GetElementsKind(); |
| 8201 switch (kind) { | 8245 switch (kind) { |
| 8246 case FAST_SMI_ONLY_ELEMENTS: |
| 8202 case FAST_ELEMENTS: { | 8247 case FAST_ELEMENTS: { |
| 8203 uint32_t length = IsJSArray() ? | 8248 uint32_t length = IsJSArray() ? |
| 8204 static_cast<uint32_t> | 8249 static_cast<uint32_t> |
| 8205 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8250 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8206 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8251 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 8207 if ((index < length) && | 8252 if ((index < length) && |
| 8208 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | 8253 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| 8209 break; | 8254 break; |
| 8210 } | 8255 } |
| 8211 case FAST_DOUBLE_ELEMENTS: { | 8256 case FAST_DOUBLE_ELEMENTS: { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8446 } | 8491 } |
| 8447 | 8492 |
| 8448 | 8493 |
| 8449 // Adding n elements in fast case is O(n*n). | 8494 // Adding n elements in fast case is O(n*n). |
| 8450 // Note: revisit design to have dual undefined values to capture absent | 8495 // Note: revisit design to have dual undefined values to capture absent |
| 8451 // elements. | 8496 // elements. |
| 8452 MaybeObject* JSObject::SetFastElement(uint32_t index, | 8497 MaybeObject* JSObject::SetFastElement(uint32_t index, |
| 8453 Object* value, | 8498 Object* value, |
| 8454 StrictModeFlag strict_mode, | 8499 StrictModeFlag strict_mode, |
| 8455 bool check_prototype) { | 8500 bool check_prototype) { |
| 8456 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 8501 ASSERT(HasFastTypeElements() || |
| 8502 HasFastArgumentsElements()); |
| 8457 | 8503 |
| 8458 FixedArray* backing_store = FixedArray::cast(elements()); | 8504 FixedArray* backing_store = FixedArray::cast(elements()); |
| 8459 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 8505 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 8460 backing_store = FixedArray::cast(backing_store->get(1)); | 8506 backing_store = FixedArray::cast(backing_store->get(1)); |
| 8461 } else { | 8507 } else { |
| 8462 Object* writable; | 8508 Object* writable; |
| 8463 MaybeObject* maybe = EnsureWritableFastElements(); | 8509 MaybeObject* maybe = EnsureWritableFastElements(); |
| 8464 if (!maybe->ToObject(&writable)) return maybe; | 8510 if (!maybe->ToObject(&writable)) return maybe; |
| 8465 backing_store = FixedArray::cast(writable); | 8511 backing_store = FixedArray::cast(writable); |
| 8466 } | 8512 } |
| 8467 uint32_t length = static_cast<uint32_t>(backing_store->length()); | 8513 uint32_t length = static_cast<uint32_t>(backing_store->length()); |
| 8468 | 8514 |
| 8469 if (check_prototype && | 8515 if (check_prototype && |
| 8470 (index >= length || backing_store->get(index)->IsTheHole())) { | 8516 (index >= length || backing_store->get(index)->IsTheHole())) { |
| 8471 bool found; | 8517 bool found; |
| 8472 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 8518 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 8473 value, | 8519 value, |
| 8474 &found, | 8520 &found, |
| 8475 strict_mode); | 8521 strict_mode); |
| 8476 if (found) return result; | 8522 if (found) return result; |
| 8477 } | 8523 } |
| 8478 | 8524 |
| 8479 // Check whether there is extra space in fixed array. | 8525 // Check whether there is extra space in fixed array. |
| 8480 if (index < length) { | 8526 if (index < length) { |
| 8527 if (HasFastSmiOnlyElements()) { |
| 8528 if (!value->IsSmi()) { |
| 8529 // If the value is a number, transition from smi-only to |
| 8530 // FastDoubleElements. |
| 8531 if (value->IsNumber()) { |
| 8532 MaybeObject* maybe = |
| 8533 SetFastDoubleElementsCapacityAndLength(length, length); |
| 8534 if (maybe->IsFailure()) return maybe; |
| 8535 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
| 8536 return value; |
| 8537 } |
| 8538 // Value is not a number, transition to generic fast elements. |
| 8539 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); |
| 8540 Map* new_map; |
| 8541 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; |
| 8542 set_map(new_map); |
| 8543 } |
| 8544 } |
| 8481 backing_store->set(index, value); | 8545 backing_store->set(index, value); |
| 8482 if (IsJSArray()) { | 8546 if (IsJSArray()) { |
| 8483 // Update the length of the array if needed. | 8547 // Update the length of the array if needed. |
| 8484 uint32_t array_length = 0; | 8548 uint32_t array_length = 0; |
| 8485 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 8549 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 8486 if (index >= array_length) { | 8550 if (index >= array_length) { |
| 8487 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 8551 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 8488 } | 8552 } |
| 8489 } | 8553 } |
| 8490 return value; | 8554 return value; |
| 8491 } | 8555 } |
| 8492 | 8556 |
| 8493 // Allow gap in fast case. | 8557 // Allow gap in fast case. |
| 8494 if ((index - length) < kMaxGap) { | 8558 if ((index - length) < kMaxGap) { |
| 8495 // Try allocating extra space. | 8559 // Try allocating extra space. |
| 8496 int new_capacity = NewElementsCapacity(index + 1); | 8560 int new_capacity = NewElementsCapacity(index + 1); |
| 8497 if (!ShouldConvertToSlowElements(new_capacity)) { | 8561 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 8498 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 8562 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 8499 Object* new_elements; | 8563 Object* new_elements; |
| 8564 SetFastElementsCapacityMode set_capacity_mode = |
| 8565 value->IsSmi() && HasFastSmiOnlyElements() |
| 8566 ? kAllowSmiOnlyElements |
| 8567 : kDontAllowSmiOnlyElements; |
| 8500 MaybeObject* maybe = | 8568 MaybeObject* maybe = |
| 8501 SetFastElementsCapacityAndLength(new_capacity, index + 1); | 8569 SetFastElementsCapacityAndLength(new_capacity, |
| 8570 index + 1, |
| 8571 set_capacity_mode); |
| 8502 if (!maybe->ToObject(&new_elements)) return maybe; | 8572 if (!maybe->ToObject(&new_elements)) return maybe; |
| 8503 FixedArray::cast(new_elements)->set(index, value); | 8573 FixedArray::cast(new_elements)->set(index, value); |
| 8504 return value; | 8574 return value; |
| 8505 } | 8575 } |
| 8506 } | 8576 } |
| 8507 | 8577 |
| 8508 // Otherwise default to slow case. | 8578 // Otherwise default to slow case. |
| 8509 MaybeObject* result = NormalizeElements(); | 8579 MaybeObject* result = NormalizeElements(); |
| 8510 if (result->IsFailure()) return result; | 8580 if (result->IsFailure()) return result; |
| 8511 return SetDictionaryElement(index, value, strict_mode, check_prototype); | 8581 return SetDictionaryElement(index, value, strict_mode, check_prototype); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8597 // Attempt to put this object back in fast case. | 8667 // Attempt to put this object back in fast case. |
| 8598 if (ShouldConvertToFastElements()) { | 8668 if (ShouldConvertToFastElements()) { |
| 8599 uint32_t new_length = 0; | 8669 uint32_t new_length = 0; |
| 8600 if (IsJSArray()) { | 8670 if (IsJSArray()) { |
| 8601 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 8671 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
| 8602 } else { | 8672 } else { |
| 8603 new_length = dictionary->max_number_key() + 1; | 8673 new_length = dictionary->max_number_key() + 1; |
| 8604 } | 8674 } |
| 8605 MaybeObject* result = CanConvertToFastDoubleElements() | 8675 MaybeObject* result = CanConvertToFastDoubleElements() |
| 8606 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 8676 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
| 8607 : SetFastElementsCapacityAndLength(new_length, new_length); | 8677 : SetFastElementsCapacityAndLength(new_length, |
| 8678 new_length, |
| 8679 kDontAllowSmiOnlyElements); |
| 8608 if (result->IsFailure()) return result; | 8680 if (result->IsFailure()) return result; |
| 8609 #ifdef DEBUG | 8681 #ifdef DEBUG |
| 8610 if (FLAG_trace_normalization) { | 8682 if (FLAG_trace_normalization) { |
| 8611 PrintF("Object elements are fast case again:\n"); | 8683 PrintF("Object elements are fast case again:\n"); |
| 8612 Print(); | 8684 Print(); |
| 8613 } | 8685 } |
| 8614 #endif | 8686 #endif |
| 8615 } | 8687 } |
| 8616 return value; | 8688 return value; |
| 8617 } | 8689 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 8641 | 8713 |
| 8642 // If the value object is not a heap number, switch to fast elements and try | 8714 // If the value object is not a heap number, switch to fast elements and try |
| 8643 // again. | 8715 // again. |
| 8644 bool value_is_smi = value->IsSmi(); | 8716 bool value_is_smi = value->IsSmi(); |
| 8645 if (!value->IsNumber()) { | 8717 if (!value->IsNumber()) { |
| 8646 Object* obj; | 8718 Object* obj; |
| 8647 uint32_t length = elms_length; | 8719 uint32_t length = elms_length; |
| 8648 if (IsJSArray()) { | 8720 if (IsJSArray()) { |
| 8649 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 8721 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 8650 } | 8722 } |
| 8651 MaybeObject* maybe_obj = | 8723 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
| 8652 SetFastElementsCapacityAndLength(elms_length, length); | 8724 elms_length, |
| 8725 length, |
| 8726 kDontAllowSmiOnlyElements); |
| 8653 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8727 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8654 return SetFastElement(index, value, strict_mode, check_prototype); | 8728 return SetFastElement(index, |
| 8729 value, |
| 8730 strict_mode, |
| 8731 check_prototype); |
| 8655 } | 8732 } |
| 8656 | 8733 |
| 8657 double double_value = value_is_smi | 8734 double double_value = value_is_smi |
| 8658 ? static_cast<double>(Smi::cast(value)->value()) | 8735 ? static_cast<double>(Smi::cast(value)->value()) |
| 8659 : HeapNumber::cast(value)->value(); | 8736 : HeapNumber::cast(value)->value(); |
| 8660 | 8737 |
| 8661 // Check whether there is extra space in the fixed array. | 8738 // Check whether there is extra space in the fixed array. |
| 8662 if (index < elms_length) { | 8739 if (index < elms_length) { |
| 8663 elms->set(index, double_value); | 8740 elms->set(index, double_value); |
| 8664 if (IsJSArray()) { | 8741 if (IsJSArray()) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8752 check_prototype); | 8829 check_prototype); |
| 8753 } | 8830 } |
| 8754 | 8831 |
| 8755 | 8832 |
| 8756 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 8833 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 8757 Object* value, | 8834 Object* value, |
| 8758 StrictModeFlag strict_mode, | 8835 StrictModeFlag strict_mode, |
| 8759 bool check_prototype) { | 8836 bool check_prototype) { |
| 8760 Isolate* isolate = GetIsolate(); | 8837 Isolate* isolate = GetIsolate(); |
| 8761 switch (GetElementsKind()) { | 8838 switch (GetElementsKind()) { |
| 8839 case FAST_SMI_ONLY_ELEMENTS: |
| 8762 case FAST_ELEMENTS: | 8840 case FAST_ELEMENTS: |
| 8763 return SetFastElement(index, value, strict_mode, check_prototype); | 8841 return SetFastElement(index, value, strict_mode, check_prototype); |
| 8764 case FAST_DOUBLE_ELEMENTS: | 8842 case FAST_DOUBLE_ELEMENTS: |
| 8765 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 8843 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
| 8766 case EXTERNAL_PIXEL_ELEMENTS: { | 8844 case EXTERNAL_PIXEL_ELEMENTS: { |
| 8767 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8845 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 8768 return pixels->SetValue(index, value); | 8846 return pixels->SetValue(index, value); |
| 8769 } | 8847 } |
| 8770 case EXTERNAL_BYTE_ELEMENTS: { | 8848 case EXTERNAL_BYTE_ELEMENTS: { |
| 8771 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 8849 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8914 backing_store_base = | 8992 backing_store_base = |
| 8915 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 8993 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 8916 backing_store = FixedArray::cast(backing_store_base); | 8994 backing_store = FixedArray::cast(backing_store_base); |
| 8917 if (backing_store->IsDictionary()) { | 8995 if (backing_store->IsDictionary()) { |
| 8918 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 8996 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 8919 *capacity = dictionary->Capacity(); | 8997 *capacity = dictionary->Capacity(); |
| 8920 *used = dictionary->NumberOfElements(); | 8998 *used = dictionary->NumberOfElements(); |
| 8921 break; | 8999 break; |
| 8922 } | 9000 } |
| 8923 // Fall through. | 9001 // Fall through. |
| 9002 case FAST_SMI_ONLY_ELEMENTS: |
| 8924 case FAST_ELEMENTS: | 9003 case FAST_ELEMENTS: |
| 8925 backing_store = FixedArray::cast(backing_store_base); | 9004 backing_store = FixedArray::cast(backing_store_base); |
| 8926 *capacity = backing_store->length(); | 9005 *capacity = backing_store->length(); |
| 8927 for (int i = 0; i < *capacity; ++i) { | 9006 for (int i = 0; i < *capacity; ++i) { |
| 8928 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 9007 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
| 8929 } | 9008 } |
| 8930 break; | 9009 break; |
| 8931 case DICTIONARY_ELEMENTS: { | 9010 case DICTIONARY_ELEMENTS: { |
| 8932 NumberDictionary* dictionary = | 9011 NumberDictionary* dictionary = |
| 8933 NumberDictionary::cast(FixedArray::cast(elements())); | 9012 NumberDictionary::cast(FixedArray::cast(elements())); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9189 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 9268 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 9190 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 9269 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9191 return false; | 9270 return false; |
| 9192 } | 9271 } |
| 9193 } | 9272 } |
| 9194 | 9273 |
| 9195 // Handle [] on String objects. | 9274 // Handle [] on String objects. |
| 9196 if (this->IsStringObjectWithCharacterAt(index)) return true; | 9275 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 9197 | 9276 |
| 9198 switch (GetElementsKind()) { | 9277 switch (GetElementsKind()) { |
| 9278 case FAST_SMI_ONLY_ELEMENTS: |
| 9199 case FAST_ELEMENTS: { | 9279 case FAST_ELEMENTS: { |
| 9200 uint32_t length = IsJSArray() ? | 9280 uint32_t length = IsJSArray() ? |
| 9201 static_cast<uint32_t>( | 9281 static_cast<uint32_t>( |
| 9202 Smi::cast(JSArray::cast(this)->length())->value()) : | 9282 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 9203 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 9283 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 9204 return (index < length) && | 9284 return (index < length) && |
| 9205 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 9285 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 9206 } | 9286 } |
| 9207 case FAST_DOUBLE_ELEMENTS: { | 9287 case FAST_DOUBLE_ELEMENTS: { |
| 9208 uint32_t length = IsJSArray() ? | 9288 uint32_t length = IsJSArray() ? |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9428 } | 9508 } |
| 9429 // Compute the number of enumerable elements. | 9509 // Compute the number of enumerable elements. |
| 9430 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 9510 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
| 9431 } | 9511 } |
| 9432 | 9512 |
| 9433 | 9513 |
| 9434 int JSObject::GetLocalElementKeys(FixedArray* storage, | 9514 int JSObject::GetLocalElementKeys(FixedArray* storage, |
| 9435 PropertyAttributes filter) { | 9515 PropertyAttributes filter) { |
| 9436 int counter = 0; | 9516 int counter = 0; |
| 9437 switch (GetElementsKind()) { | 9517 switch (GetElementsKind()) { |
| 9518 case FAST_SMI_ONLY_ELEMENTS: |
| 9438 case FAST_ELEMENTS: { | 9519 case FAST_ELEMENTS: { |
| 9439 int length = IsJSArray() ? | 9520 int length = IsJSArray() ? |
| 9440 Smi::cast(JSArray::cast(this)->length())->value() : | 9521 Smi::cast(JSArray::cast(this)->length())->value() : |
| 9441 FixedArray::cast(elements())->length(); | 9522 FixedArray::cast(elements())->length(); |
| 9442 for (int i = 0; i < length; i++) { | 9523 for (int i = 0; i < length; i++) { |
| 9443 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 9524 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 9444 if (storage != NULL) { | 9525 if (storage != NULL) { |
| 9445 storage->set(counter, Smi::FromInt(i)); | 9526 storage->set(counter, Smi::FromInt(i)); |
| 9446 } | 9527 } |
| 9447 counter++; | 9528 counter++; |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10330 dict->CopyValuesTo(fast_elements); | 10411 dict->CopyValuesTo(fast_elements); |
| 10331 | 10412 |
| 10332 set_map(new_map); | 10413 set_map(new_map); |
| 10333 set_elements(fast_elements); | 10414 set_elements(fast_elements); |
| 10334 } else if (!HasFastDoubleElements()) { | 10415 } else if (!HasFastDoubleElements()) { |
| 10335 Object* obj; | 10416 Object* obj; |
| 10336 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 10417 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 10337 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10418 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 10338 } | 10419 } |
| 10339 } | 10420 } |
| 10340 ASSERT(HasFastElements() || HasFastDoubleElements()); | 10421 ASSERT(HasFastTypeElements() || |
| 10422 HasFastDoubleElements()); |
| 10341 | 10423 |
| 10342 // Collect holes at the end, undefined before that and the rest at the | 10424 // Collect holes at the end, undefined before that and the rest at the |
| 10343 // start, and return the number of non-hole, non-undefined values. | 10425 // start, and return the number of non-hole, non-undefined values. |
| 10344 | 10426 |
| 10345 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 10427 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
| 10346 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 10428 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 10347 if (limit > elements_length) { | 10429 if (limit > elements_length) { |
| 10348 limit = elements_length ; | 10430 limit = elements_length ; |
| 10349 } | 10431 } |
| 10350 if (limit == 0) { | 10432 if (limit == 0) { |
| (...skipping 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11765 if (break_point_objects()->IsUndefined()) return 0; | 11847 if (break_point_objects()->IsUndefined()) return 0; |
| 11766 // Single break point. | 11848 // Single break point. |
| 11767 if (!break_point_objects()->IsFixedArray()) return 1; | 11849 if (!break_point_objects()->IsFixedArray()) return 1; |
| 11768 // Multiple break points. | 11850 // Multiple break points. |
| 11769 return FixedArray::cast(break_point_objects())->length(); | 11851 return FixedArray::cast(break_point_objects())->length(); |
| 11770 } | 11852 } |
| 11771 #endif | 11853 #endif |
| 11772 | 11854 |
| 11773 | 11855 |
| 11774 } } // namespace v8::internal | 11856 } } // namespace v8::internal |
| OLD | NEW |