Chromium Code Reviews| 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 2938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2949 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 2949 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 2950 Map* old_map = array->map(); | 2950 Map* old_map = array->map(); |
| 2951 bool is_arguments = | 2951 bool is_arguments = |
| 2952 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 2952 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
| 2953 if (is_arguments) { | 2953 if (is_arguments) { |
| 2954 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 2954 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 2955 } | 2955 } |
| 2956 if (array->IsDictionary()) return array; | 2956 if (array->IsDictionary()) return array; |
| 2957 | 2957 |
| 2958 ASSERT(HasFastElements() || | 2958 ASSERT(HasFastElements() || |
| 2959 HasFastSmiOnlyElements() || | |
| 2959 HasFastDoubleElements() || | 2960 HasFastDoubleElements() || |
| 2960 HasFastArgumentsElements()); | 2961 HasFastArgumentsElements()); |
| 2961 // Compute the effective length and allocate a new backing store. | 2962 // Compute the effective length and allocate a new backing store. |
| 2962 int length = IsJSArray() | 2963 int length = IsJSArray() |
| 2963 ? Smi::cast(JSArray::cast(this)->length())->value() | 2964 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2964 : array->length(); | 2965 : array->length(); |
| 2965 int old_capacity = 0; | 2966 int old_capacity = 0; |
| 2966 int used_elements = 0; | 2967 int used_elements = 0; |
| 2967 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 2968 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 2968 NumberDictionary* dictionary = NULL; | 2969 NumberDictionary* dictionary = NULL; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2983 } else { | 2984 } else { |
| 2984 // Objects must be allocated in the old object space, since the | 2985 // Objects must be allocated in the old object space, since the |
| 2985 // overall number of HeapNumbers needed for the conversion might | 2986 // overall number of HeapNumbers needed for the conversion might |
| 2986 // exceed the capacity of new space, and we would fail repeatedly | 2987 // exceed the capacity of new space, and we would fail repeatedly |
| 2987 // trying to convert the FixedDoubleArray. | 2988 // trying to convert the FixedDoubleArray. |
| 2988 MaybeObject* maybe_value_object = | 2989 MaybeObject* maybe_value_object = |
| 2989 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 2990 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 2990 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 2991 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 2991 } | 2992 } |
| 2992 } else { | 2993 } else { |
| 2993 ASSERT(old_map->has_fast_elements()); | 2994 ASSERT(old_map->has_fast_elements() || |
| 2995 old_map->has_fast_smi_only_elements()); | |
| 2994 value = FixedArray::cast(array)->get(i); | 2996 value = FixedArray::cast(array)->get(i); |
| 2995 } | 2997 } |
| 2996 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2998 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2997 if (!value->IsTheHole()) { | 2999 if (!value->IsTheHole()) { |
| 2998 Object* result; | 3000 Object* result; |
| 2999 MaybeObject* maybe_result = | 3001 MaybeObject* maybe_result = |
| 3000 dictionary->AddNumberEntry(i, value, details); | 3002 dictionary->AddNumberEntry(i, value, details); |
| 3001 if (!maybe_result->ToObject(&result)) return maybe_result; | 3003 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3002 dictionary = NumberDictionary::cast(result); | 3004 dictionary = NumberDictionary::cast(result); |
| 3003 } | 3005 } |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3291 } | 3293 } |
| 3292 // Make sure the properties are normalized before removing the entry. | 3294 // Make sure the properties are normalized before removing the entry. |
| 3293 return DeleteNormalizedProperty(name, mode); | 3295 return DeleteNormalizedProperty(name, mode); |
| 3294 } | 3296 } |
| 3295 } | 3297 } |
| 3296 | 3298 |
| 3297 | 3299 |
| 3298 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 3300 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 3299 ElementsKind kind, | 3301 ElementsKind kind, |
| 3300 Object* object) { | 3302 Object* object) { |
| 3301 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); | 3303 ASSERT(kind == FAST_ELEMENTS || |
| 3304 kind == DICTIONARY_ELEMENTS); | |
| 3302 if (kind == FAST_ELEMENTS) { | 3305 if (kind == FAST_ELEMENTS) { |
| 3303 int length = IsJSArray() | 3306 int length = IsJSArray() |
| 3304 ? Smi::cast(JSArray::cast(this)->length())->value() | 3307 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3305 : elements->length(); | 3308 : elements->length(); |
| 3306 for (int i = 0; i < length; ++i) { | 3309 for (int i = 0; i < length; ++i) { |
| 3307 Object* element = elements->get(i); | 3310 Object* element = elements->get(i); |
| 3308 if (!element->IsTheHole() && element == object) return true; | 3311 if (!element->IsTheHole() && element == object) return true; |
| 3309 } | 3312 } |
| 3310 } else { | 3313 } else { |
| 3311 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); | 3314 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3346 case EXTERNAL_SHORT_ELEMENTS: | 3349 case EXTERNAL_SHORT_ELEMENTS: |
| 3347 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3350 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3348 case EXTERNAL_INT_ELEMENTS: | 3351 case EXTERNAL_INT_ELEMENTS: |
| 3349 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3352 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3350 case EXTERNAL_FLOAT_ELEMENTS: | 3353 case EXTERNAL_FLOAT_ELEMENTS: |
| 3351 case EXTERNAL_DOUBLE_ELEMENTS: | 3354 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3352 case FAST_DOUBLE_ELEMENTS: | 3355 case FAST_DOUBLE_ELEMENTS: |
| 3353 // Raw pixels and external arrays do not reference other | 3356 // Raw pixels and external arrays do not reference other |
| 3354 // objects. | 3357 // objects. |
| 3355 break; | 3358 break; |
| 3359 case FAST_SMI_ONLY_ELEMENTS: | |
| 3360 break; | |
| 3356 case FAST_ELEMENTS: | 3361 case FAST_ELEMENTS: |
| 3357 case DICTIONARY_ELEMENTS: { | 3362 case DICTIONARY_ELEMENTS: { |
| 3358 FixedArray* elements = FixedArray::cast(this->elements()); | 3363 FixedArray* elements = FixedArray::cast(this->elements()); |
| 3359 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 3364 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 3360 break; | 3365 break; |
| 3361 } | 3366 } |
| 3362 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 3367 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 3363 FixedArray* parameter_map = FixedArray::cast(elements()); | 3368 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 3364 // Check the mapped parameters. | 3369 // Check the mapped parameters. |
| 3365 int length = parameter_map->length(); | 3370 int length = parameter_map->length(); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3637 | 3642 |
| 3638 if (!CanSetCallback(name)) { | 3643 if (!CanSetCallback(name)) { |
| 3639 return heap->undefined_value(); | 3644 return heap->undefined_value(); |
| 3640 } | 3645 } |
| 3641 | 3646 |
| 3642 uint32_t index = 0; | 3647 uint32_t index = 0; |
| 3643 bool is_element = name->AsArrayIndex(&index); | 3648 bool is_element = name->AsArrayIndex(&index); |
| 3644 | 3649 |
| 3645 if (is_element) { | 3650 if (is_element) { |
| 3646 switch (GetElementsKind()) { | 3651 switch (GetElementsKind()) { |
| 3652 case FAST_SMI_ONLY_ELEMENTS: | |
| 3647 case FAST_ELEMENTS: | 3653 case FAST_ELEMENTS: |
| 3648 case FAST_DOUBLE_ELEMENTS: | 3654 case FAST_DOUBLE_ELEMENTS: |
| 3649 break; | 3655 break; |
| 3650 case EXTERNAL_PIXEL_ELEMENTS: | 3656 case EXTERNAL_PIXEL_ELEMENTS: |
| 3651 case EXTERNAL_BYTE_ELEMENTS: | 3657 case EXTERNAL_BYTE_ELEMENTS: |
| 3652 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3658 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3653 case EXTERNAL_SHORT_ELEMENTS: | 3659 case EXTERNAL_SHORT_ELEMENTS: |
| 3654 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3660 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3655 case EXTERNAL_INT_ELEMENTS: | 3661 case EXTERNAL_INT_ELEMENTS: |
| 3656 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3662 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3886 } | 3892 } |
| 3887 | 3893 |
| 3888 uint32_t index = 0; | 3894 uint32_t index = 0; |
| 3889 bool is_element = name->AsArrayIndex(&index); | 3895 bool is_element = name->AsArrayIndex(&index); |
| 3890 | 3896 |
| 3891 if (is_element) { | 3897 if (is_element) { |
| 3892 if (IsJSArray()) return isolate->heap()->undefined_value(); | 3898 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 3893 | 3899 |
| 3894 // Accessors overwrite previous callbacks (cf. with getters/setters). | 3900 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 3895 switch (GetElementsKind()) { | 3901 switch (GetElementsKind()) { |
| 3902 case FAST_SMI_ONLY_ELEMENTS: | |
| 3896 case FAST_ELEMENTS: | 3903 case FAST_ELEMENTS: |
| 3897 case FAST_DOUBLE_ELEMENTS: | 3904 case FAST_DOUBLE_ELEMENTS: |
| 3898 break; | 3905 break; |
| 3899 case EXTERNAL_PIXEL_ELEMENTS: | 3906 case EXTERNAL_PIXEL_ELEMENTS: |
| 3900 case EXTERNAL_BYTE_ELEMENTS: | 3907 case EXTERNAL_BYTE_ELEMENTS: |
| 3901 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3908 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3902 case EXTERNAL_SHORT_ELEMENTS: | 3909 case EXTERNAL_SHORT_ELEMENTS: |
| 3903 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3910 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3904 case EXTERNAL_INT_ELEMENTS: | 3911 case EXTERNAL_INT_ELEMENTS: |
| 3905 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3912 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| (...skipping 3389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7295 for (int i = 0; i < source->Capacity(); ++i) { | 7302 for (int i = 0; i < source->Capacity(); ++i) { |
| 7296 Object* key = source->KeyAt(i); | 7303 Object* key = source->KeyAt(i); |
| 7297 if (key->IsNumber()) { | 7304 if (key->IsNumber()) { |
| 7298 uint32_t entry = static_cast<uint32_t>(key->Number()); | 7305 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 7299 destination->set(entry, source->ValueAt(i), mode); | 7306 destination->set(entry, source->ValueAt(i), mode); |
| 7300 } | 7307 } |
| 7301 } | 7308 } |
| 7302 } | 7309 } |
| 7303 | 7310 |
| 7304 | 7311 |
| 7305 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, | 7312 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
| 7306 int length) { | 7313 int capacity, |
| 7314 int length, | |
| 7315 SetFastElementsCapacityMode set_capacity_mode) { | |
| 7307 Heap* heap = GetHeap(); | 7316 Heap* heap = GetHeap(); |
| 7308 // We should never end in here with a pixel or external array. | 7317 // We should never end in here with a pixel or external array. |
| 7309 ASSERT(!HasExternalArrayElements()); | 7318 ASSERT(!HasExternalArrayElements()); |
| 7310 | 7319 |
| 7311 // Allocate a new fast elements backing store. | 7320 // Allocate a new fast elements backing store. |
| 7312 FixedArray* new_elements = NULL; | 7321 FixedArray* new_elements = NULL; |
| 7313 { Object* object; | 7322 { Object* object; |
| 7314 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 7323 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
| 7315 if (!maybe->ToObject(&object)) return maybe; | 7324 if (!maybe->ToObject(&object)) return maybe; |
| 7316 new_elements = FixedArray::cast(object); | 7325 new_elements = FixedArray::cast(object); |
| 7317 } | 7326 } |
| 7318 | 7327 |
| 7319 // Find the new map to use for this object if there is a map change. | 7328 // Find the new map to use for this object if there is a map change. |
| 7320 Map* new_map = NULL; | 7329 Map* new_map = NULL; |
| 7321 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 7330 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
| 7322 Object* object; | 7331 Object* object; |
| 7323 MaybeObject* maybe = GetElementsTransitionMap(FAST_ELEMENTS); | 7332 bool has_fast_smi_only_elements = |
| 7333 FLAG_smi_only_arrays && | |
| 7334 (set_capacity_mode == kAllowSmiOnlyElements) && | |
| 7335 (elements()->map()->has_fast_smi_only_elements() || | |
| 7336 elements() == heap->empty_fixed_array()); | |
| 7337 ElementsKind elements_kind = has_fast_smi_only_elements | |
| 7338 ? FAST_SMI_ONLY_ELEMENTS | |
| 7339 : FAST_ELEMENTS; | |
| 7340 MaybeObject* maybe = GetElementsTransitionMap(elements_kind); | |
| 7324 if (!maybe->ToObject(&object)) return maybe; | 7341 if (!maybe->ToObject(&object)) return maybe; |
| 7325 new_map = Map::cast(object); | 7342 new_map = Map::cast(object); |
| 7326 } | 7343 } |
| 7327 | 7344 |
| 7328 switch (GetElementsKind()) { | 7345 ElementsKind elements_kind = GetElementsKind(); |
| 7346 switch (elements_kind) { | |
| 7347 case FAST_SMI_ONLY_ELEMENTS: | |
| 7329 case FAST_ELEMENTS: { | 7348 case FAST_ELEMENTS: { |
| 7330 AssertNoAllocation no_gc; | 7349 AssertNoAllocation no_gc; |
| 7331 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7350 WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc)); |
| 7332 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 7351 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); |
| 7333 set_map(new_map); | 7352 set_map(new_map); |
| 7334 set_elements(new_elements); | 7353 set_elements(new_elements); |
| 7335 break; | 7354 break; |
| 7336 } | 7355 } |
| 7337 case DICTIONARY_ELEMENTS: { | 7356 case DICTIONARY_ELEMENTS: { |
| 7338 AssertNoAllocation no_gc; | 7357 AssertNoAllocation no_gc; |
| 7339 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7358 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7340 CopySlowElementsToFast(NumberDictionary::cast(elements()), | 7359 CopySlowElementsToFast(NumberDictionary::cast(elements()), |
| 7341 new_elements, | 7360 new_elements, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7424 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); | 7443 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); |
| 7425 | 7444 |
| 7426 { MaybeObject* maybe_obj = | 7445 { MaybeObject* maybe_obj = |
| 7427 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); | 7446 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); |
| 7428 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7447 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7429 } | 7448 } |
| 7430 Map* new_map = Map::cast(obj); | 7449 Map* new_map = Map::cast(obj); |
| 7431 | 7450 |
| 7432 AssertNoAllocation no_gc; | 7451 AssertNoAllocation no_gc; |
| 7433 switch (GetElementsKind()) { | 7452 switch (GetElementsKind()) { |
| 7453 case FAST_SMI_ONLY_ELEMENTS: | |
| 7434 case FAST_ELEMENTS: { | 7454 case FAST_ELEMENTS: { |
| 7435 elems->Initialize(FixedArray::cast(elements())); | 7455 elems->Initialize(FixedArray::cast(elements())); |
| 7436 break; | 7456 break; |
| 7437 } | 7457 } |
| 7438 case FAST_DOUBLE_ELEMENTS: { | 7458 case FAST_DOUBLE_ELEMENTS: { |
| 7439 elems->Initialize(FixedDoubleArray::cast(elements())); | 7459 elems->Initialize(FixedDoubleArray::cast(elements())); |
| 7440 break; | 7460 break; |
| 7441 } | 7461 } |
| 7442 case DICTIONARY_ELEMENTS: { | 7462 case DICTIONARY_ELEMENTS: { |
| 7443 elems->Initialize(NumberDictionary::cast(elements())); | 7463 elems->Initialize(NumberDictionary::cast(elements())); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 7461 } | 7481 } |
| 7462 | 7482 |
| 7463 | 7483 |
| 7464 MaybeObject* JSObject::SetSlowElements(Object* len) { | 7484 MaybeObject* JSObject::SetSlowElements(Object* len) { |
| 7465 // We should never end in here with a pixel or external array. | 7485 // We should never end in here with a pixel or external array. |
| 7466 ASSERT(!HasExternalArrayElements()); | 7486 ASSERT(!HasExternalArrayElements()); |
| 7467 | 7487 |
| 7468 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 7488 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 7469 | 7489 |
| 7470 switch (GetElementsKind()) { | 7490 switch (GetElementsKind()) { |
| 7471 case FAST_ELEMENTS: { | 7491 case FAST_SMI_ONLY_ELEMENTS: |
| 7472 case FAST_DOUBLE_ELEMENTS: | 7492 case FAST_ELEMENTS: |
| 7493 case FAST_DOUBLE_ELEMENTS: { | |
| 7473 // Make sure we never try to shrink dense arrays into sparse arrays. | 7494 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 7474 ASSERT(static_cast<uint32_t>( | 7495 ASSERT(static_cast<uint32_t>( |
| 7475 FixedArrayBase::cast(elements())->length()) <= new_length); | 7496 FixedArrayBase::cast(elements())->length()) <= new_length); |
| 7476 MaybeObject* result = NormalizeElements(); | 7497 MaybeObject* result = NormalizeElements(); |
| 7477 if (result->IsFailure()) return result; | 7498 if (result->IsFailure()) return result; |
| 7478 | 7499 |
| 7479 // Update length for JSArrays. | 7500 // Update length for JSArrays. |
| 7480 if (IsJSArray()) JSArray::cast(this)->set_length(len); | 7501 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 7481 break; | 7502 break; |
| 7482 } | 7503 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7528 | 7549 |
| 7529 | 7550 |
| 7530 void JSArray::Expand(int required_size) { | 7551 void JSArray::Expand(int required_size) { |
| 7531 Handle<JSArray> self(this); | 7552 Handle<JSArray> self(this); |
| 7532 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 7553 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 7533 int old_size = old_backing->length(); | 7554 int old_size = old_backing->length(); |
| 7534 int new_size = required_size > old_size ? required_size : old_size; | 7555 int new_size = required_size > old_size ? required_size : old_size; |
| 7535 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); | 7556 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 7536 // Can't use this any more now because we may have had a GC! | 7557 // Can't use this any more now because we may have had a GC! |
| 7537 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 7558 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 7538 self->SetContent(*new_backing); | 7559 GetIsolate()->factory()->SetContent(self, new_backing); |
| 7539 } | 7560 } |
| 7540 | 7561 |
| 7541 | 7562 |
| 7542 static Failure* ArrayLengthRangeError(Heap* heap) { | 7563 static Failure* ArrayLengthRangeError(Heap* heap) { |
| 7543 HandleScope scope(heap->isolate()); | 7564 HandleScope scope(heap->isolate()); |
| 7544 return heap->isolate()->Throw( | 7565 return heap->isolate()->Throw( |
| 7545 *FACTORY->NewRangeError("invalid_array_length", | 7566 *FACTORY->NewRangeError("invalid_array_length", |
| 7546 HandleVector<Object>(NULL, 0))); | 7567 HandleVector<Object>(NULL, 0))); |
| 7547 } | 7568 } |
| 7548 | 7569 |
| 7549 | 7570 |
| 7550 MaybeObject* JSObject::SetElementsLength(Object* len) { | 7571 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 7551 // We should never end in here with a pixel or external array. | 7572 // We should never end in here with a pixel or external array. |
| 7552 ASSERT(AllowsSetElementsLength()); | 7573 ASSERT(AllowsSetElementsLength()); |
| 7553 | 7574 |
| 7554 MaybeObject* maybe_smi_length = len->ToSmi(); | 7575 MaybeObject* maybe_smi_length = len->ToSmi(); |
| 7555 Object* smi_length = Smi::FromInt(0); | 7576 Object* smi_length = Smi::FromInt(0); |
| 7556 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 7577 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 7557 const int value = Smi::cast(smi_length)->value(); | 7578 const int value = Smi::cast(smi_length)->value(); |
| 7558 if (value < 0) return ArrayLengthRangeError(GetHeap()); | 7579 if (value < 0) return ArrayLengthRangeError(GetHeap()); |
| 7559 ElementsKind elements_kind = GetElementsKind(); | 7580 ElementsKind elements_kind = GetElementsKind(); |
| 7560 switch (elements_kind) { | 7581 switch (elements_kind) { |
| 7582 case FAST_SMI_ONLY_ELEMENTS: | |
| 7561 case FAST_ELEMENTS: | 7583 case FAST_ELEMENTS: |
| 7562 case FAST_DOUBLE_ELEMENTS: { | 7584 case FAST_DOUBLE_ELEMENTS: { |
| 7563 int old_capacity = FixedArrayBase::cast(elements())->length(); | 7585 int old_capacity = FixedArrayBase::cast(elements())->length(); |
| 7564 if (value <= old_capacity) { | 7586 if (value <= old_capacity) { |
| 7565 if (IsJSArray()) { | 7587 if (IsJSArray()) { |
| 7566 Object* obj; | 7588 Object* obj; |
| 7567 if (elements_kind == FAST_ELEMENTS) { | 7589 if (elements_kind != FAST_DOUBLE_ELEMENTS) { |
|
fschneider
2011/09/22 07:46:38
Maybe make the condition consistent with the other
danno
2011/09/22 11:23:15
Done.
| |
| 7590 ASSERT(elements_kind == FAST_ELEMENTS || | |
| 7591 elements_kind == FAST_SMI_ONLY_ELEMENTS); | |
| 7568 MaybeObject* maybe_obj = EnsureWritableFastElements(); | 7592 MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 7569 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7593 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7570 } | 7594 } |
| 7571 if (2 * value <= old_capacity) { | 7595 if (2 * value <= old_capacity) { |
| 7572 // If more than half the elements won't be used, trim the array. | 7596 // If more than half the elements won't be used, trim the array. |
| 7573 if (value == 0) { | 7597 if (value == 0) { |
| 7574 initialize_elements(); | 7598 initialize_elements(); |
| 7575 } else { | 7599 } else { |
| 7576 Address filler_start; | 7600 Address filler_start; |
| 7577 int filler_size; | 7601 int filler_size; |
| 7578 if (GetElementsKind() == FAST_ELEMENTS) { | 7602 if (elements_kind == FAST_ELEMENTS || |
| 7603 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 7579 FixedArray* fast_elements = FixedArray::cast(elements()); | 7604 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7580 fast_elements->set_length(value); | 7605 fast_elements->set_length(value); |
| 7581 filler_start = fast_elements->address() + | 7606 filler_start = fast_elements->address() + |
| 7582 FixedArray::OffsetOfElementAt(value); | 7607 FixedArray::OffsetOfElementAt(value); |
| 7583 filler_size = (old_capacity - value) * kPointerSize; | 7608 filler_size = (old_capacity - value) * kPointerSize; |
| 7584 } else { | 7609 } else { |
| 7585 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7610 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); |
| 7586 FixedDoubleArray* fast_double_elements = | 7611 FixedDoubleArray* fast_double_elements = |
| 7587 FixedDoubleArray::cast(elements()); | 7612 FixedDoubleArray::cast(elements()); |
| 7588 fast_double_elements->set_length(value); | 7613 fast_double_elements->set_length(value); |
| 7589 filler_start = fast_double_elements->address() + | 7614 filler_start = fast_double_elements->address() + |
| 7590 FixedDoubleArray::OffsetOfElementAt(value); | 7615 FixedDoubleArray::OffsetOfElementAt(value); |
| 7591 filler_size = (old_capacity - value) * kDoubleSize; | 7616 filler_size = (old_capacity - value) * kDoubleSize; |
| 7592 } | 7617 } |
| 7593 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | 7618 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); |
| 7594 } | 7619 } |
| 7595 } else { | 7620 } else { |
| 7596 // Otherwise, fill the unused tail with holes. | 7621 // Otherwise, fill the unused tail with holes. |
| 7597 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 7622 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| 7598 if (GetElementsKind() == FAST_ELEMENTS) { | 7623 if (elements_kind == FAST_ELEMENTS || |
| 7624 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 7599 FixedArray* fast_elements = FixedArray::cast(elements()); | 7625 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7600 for (int i = value; i < old_length; i++) { | 7626 for (int i = value; i < old_length; i++) { |
| 7601 fast_elements->set_the_hole(i); | 7627 fast_elements->set_the_hole(i); |
| 7602 } | 7628 } |
| 7603 } else { | 7629 } else { |
| 7604 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7630 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); |
| 7605 FixedDoubleArray* fast_double_elements = | 7631 FixedDoubleArray* fast_double_elements = |
| 7606 FixedDoubleArray::cast(elements()); | 7632 FixedDoubleArray::cast(elements()); |
| 7607 for (int i = value; i < old_length; i++) { | 7633 for (int i = value; i < old_length; i++) { |
| 7608 fast_double_elements->set_the_hole(i); | 7634 fast_double_elements->set_the_hole(i); |
| 7609 } | 7635 } |
| 7610 } | 7636 } |
| 7611 } | 7637 } |
| 7612 JSArray::cast(this)->set_length(Smi::cast(smi_length)); | 7638 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 7613 } | 7639 } |
| 7614 return this; | 7640 return this; |
| 7615 } | 7641 } |
| 7616 int min = NewElementsCapacity(old_capacity); | 7642 int min = NewElementsCapacity(old_capacity); |
| 7617 int new_capacity = value > min ? value : min; | 7643 int new_capacity = value > min ? value : min; |
| 7618 if (!ShouldConvertToSlowElements(new_capacity)) { | 7644 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 7619 MaybeObject* result; | 7645 MaybeObject* result; |
| 7620 if (GetElementsKind() == FAST_ELEMENTS) { | 7646 if (elements_kind == FAST_ELEMENTS || |
| 7621 result = SetFastElementsCapacityAndLength(new_capacity, value); | 7647 elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 7648 SetFastElementsCapacityMode set_capacity_mode = | |
| 7649 elements_kind == FAST_SMI_ONLY_ELEMENTS | |
| 7650 ? kAllowSmiOnlyElements | |
| 7651 : kDontAllowSmiOnlyElements; | |
| 7652 result = SetFastElementsCapacityAndLength(new_capacity, | |
| 7653 value, | |
| 7654 set_capacity_mode); | |
| 7622 } else { | 7655 } else { |
| 7623 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7656 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); |
| 7624 result = SetFastDoubleElementsCapacityAndLength(new_capacity, | 7657 result = SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 7625 value); | 7658 value); |
| 7626 } | 7659 } |
| 7627 if (result->IsFailure()) return result; | 7660 if (result->IsFailure()) return result; |
| 7628 return this; | 7661 return this; |
| 7629 } | 7662 } |
| 7630 break; | 7663 break; |
| 7631 } | 7664 } |
| 7632 case DICTIONARY_ELEMENTS: { | 7665 case DICTIONARY_ELEMENTS: { |
| 7633 if (IsJSArray()) { | 7666 if (IsJSArray()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7670 if (len->ToArrayIndex(&length)) { | 7703 if (len->ToArrayIndex(&length)) { |
| 7671 return SetSlowElements(len); | 7704 return SetSlowElements(len); |
| 7672 } else { | 7705 } else { |
| 7673 return ArrayLengthRangeError(GetHeap()); | 7706 return ArrayLengthRangeError(GetHeap()); |
| 7674 } | 7707 } |
| 7675 } | 7708 } |
| 7676 | 7709 |
| 7677 // len is not a number so make the array size one and | 7710 // len is not a number so make the array size one and |
| 7678 // set only element to len. | 7711 // set only element to len. |
| 7679 Object* obj; | 7712 Object* obj; |
| 7680 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); | 7713 MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); |
| 7681 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7714 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7682 } | |
| 7683 FixedArray::cast(obj)->set(0, len); | 7715 FixedArray::cast(obj)->set(0, len); |
| 7716 | |
| 7717 maybe_obj = EnsureCanContainElements(&len, 1); | |
| 7718 if (maybe_obj->IsFailure()) return maybe_obj; | |
| 7719 | |
| 7684 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | 7720 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 7685 set_elements(FixedArray::cast(obj)); | 7721 set_elements(FixedArray::cast(obj)); |
| 7686 return this; | 7722 return this; |
| 7687 } | 7723 } |
| 7688 | 7724 |
| 7689 | 7725 |
| 7690 Object* Map::GetPrototypeTransition(Object* prototype) { | 7726 Object* Map::GetPrototypeTransition(Object* prototype) { |
| 7691 FixedArray* cache = prototype_transitions(); | 7727 FixedArray* cache = prototype_transitions(); |
| 7692 int number_of_transitions = NumberOfProtoTransitions(); | 7728 int number_of_transitions = NumberOfProtoTransitions(); |
| 7693 const int proto_offset = | 7729 const int proto_offset = |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7821 } | 7857 } |
| 7822 ASSERT(Map::cast(new_map)->prototype() == value); | 7858 ASSERT(Map::cast(new_map)->prototype() == value); |
| 7823 real_receiver->set_map(Map::cast(new_map)); | 7859 real_receiver->set_map(Map::cast(new_map)); |
| 7824 | 7860 |
| 7825 heap->ClearInstanceofCache(); | 7861 heap->ClearInstanceofCache(); |
| 7826 ASSERT(size == Size()); | 7862 ASSERT(size == Size()); |
| 7827 return value; | 7863 return value; |
| 7828 } | 7864 } |
| 7829 | 7865 |
| 7830 | 7866 |
| 7867 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | |
| 7868 uint32_t first_arg, | |
| 7869 uint32_t arg_count) { | |
| 7870 return EnsureCanContainElements(args->arguments() - first_arg, arg_count); | |
| 7871 } | |
| 7872 | |
| 7873 | |
| 7831 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { | 7874 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
| 7832 switch (GetElementsKind()) { | 7875 switch (GetElementsKind()) { |
| 7876 case FAST_SMI_ONLY_ELEMENTS: | |
| 7833 case FAST_ELEMENTS: { | 7877 case FAST_ELEMENTS: { |
| 7834 uint32_t length = IsJSArray() ? | 7878 uint32_t length = IsJSArray() ? |
| 7835 static_cast<uint32_t> | 7879 static_cast<uint32_t> |
| 7836 (Smi::cast(JSArray::cast(this)->length())->value()) : | 7880 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7837 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 7881 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7838 if ((index < length) && | 7882 if ((index < length) && |
| 7839 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 7883 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7840 return true; | 7884 return true; |
| 7841 } | 7885 } |
| 7842 break; | 7886 break; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7959 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 8003 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
| 7960 : UNDEFINED_ELEMENT; | 8004 : UNDEFINED_ELEMENT; |
| 7961 } | 8005 } |
| 7962 | 8006 |
| 7963 // Handle [] on String objects. | 8007 // Handle [] on String objects. |
| 7964 if (this->IsStringObjectWithCharacterAt(index)) { | 8008 if (this->IsStringObjectWithCharacterAt(index)) { |
| 7965 return STRING_CHARACTER_ELEMENT; | 8009 return STRING_CHARACTER_ELEMENT; |
| 7966 } | 8010 } |
| 7967 | 8011 |
| 7968 switch (GetElementsKind()) { | 8012 switch (GetElementsKind()) { |
| 8013 case FAST_SMI_ONLY_ELEMENTS: | |
| 7969 case FAST_ELEMENTS: { | 8014 case FAST_ELEMENTS: { |
| 7970 uint32_t length = IsJSArray() ? | 8015 uint32_t length = IsJSArray() ? |
| 7971 static_cast<uint32_t> | 8016 static_cast<uint32_t> |
| 7972 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8017 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7973 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8018 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7974 if ((index < length) && | 8019 if ((index < length) && |
| 7975 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8020 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7976 return FAST_ELEMENT; | 8021 return FAST_ELEMENT; |
| 7977 } | 8022 } |
| 7978 break; | 8023 break; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8073 } | 8118 } |
| 8074 } | 8119 } |
| 8075 | 8120 |
| 8076 // Check for lookup interceptor | 8121 // Check for lookup interceptor |
| 8077 if (HasIndexedInterceptor()) { | 8122 if (HasIndexedInterceptor()) { |
| 8078 return HasElementWithInterceptor(receiver, index); | 8123 return HasElementWithInterceptor(receiver, index); |
| 8079 } | 8124 } |
| 8080 | 8125 |
| 8081 ElementsKind kind = GetElementsKind(); | 8126 ElementsKind kind = GetElementsKind(); |
| 8082 switch (kind) { | 8127 switch (kind) { |
| 8128 case FAST_SMI_ONLY_ELEMENTS: | |
| 8083 case FAST_ELEMENTS: { | 8129 case FAST_ELEMENTS: { |
| 8084 uint32_t length = IsJSArray() ? | 8130 uint32_t length = IsJSArray() ? |
| 8085 static_cast<uint32_t> | 8131 static_cast<uint32_t> |
| 8086 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8132 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8087 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8133 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 8088 if ((index < length) && | 8134 if ((index < length) && |
| 8089 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | 8135 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| 8090 break; | 8136 break; |
| 8091 } | 8137 } |
| 8092 case FAST_DOUBLE_ELEMENTS: { | 8138 case FAST_DOUBLE_ELEMENTS: { |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8323 } | 8369 } |
| 8324 | 8370 |
| 8325 | 8371 |
| 8326 // Adding n elements in fast case is O(n*n). | 8372 // Adding n elements in fast case is O(n*n). |
| 8327 // Note: revisit design to have dual undefined values to capture absent | 8373 // Note: revisit design to have dual undefined values to capture absent |
| 8328 // elements. | 8374 // elements. |
| 8329 MaybeObject* JSObject::SetFastElement(uint32_t index, | 8375 MaybeObject* JSObject::SetFastElement(uint32_t index, |
| 8330 Object* value, | 8376 Object* value, |
| 8331 StrictModeFlag strict_mode, | 8377 StrictModeFlag strict_mode, |
| 8332 bool check_prototype) { | 8378 bool check_prototype) { |
| 8333 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 8379 ASSERT(HasFastTypeElements() || |
| 8380 HasFastArgumentsElements()); | |
| 8334 | 8381 |
| 8335 FixedArray* backing_store = FixedArray::cast(elements()); | 8382 FixedArray* backing_store = FixedArray::cast(elements()); |
| 8336 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 8383 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 8337 backing_store = FixedArray::cast(backing_store->get(1)); | 8384 backing_store = FixedArray::cast(backing_store->get(1)); |
| 8338 } else { | 8385 } else { |
| 8339 Object* writable; | 8386 Object* writable; |
| 8340 MaybeObject* maybe = EnsureWritableFastElements(); | 8387 MaybeObject* maybe = EnsureWritableFastElements(); |
| 8341 if (!maybe->ToObject(&writable)) return maybe; | 8388 if (!maybe->ToObject(&writable)) return maybe; |
| 8342 backing_store = FixedArray::cast(writable); | 8389 backing_store = FixedArray::cast(writable); |
| 8343 } | 8390 } |
| 8344 uint32_t length = static_cast<uint32_t>(backing_store->length()); | 8391 uint32_t length = static_cast<uint32_t>(backing_store->length()); |
| 8345 | 8392 |
| 8346 if (check_prototype && | 8393 if (check_prototype && |
| 8347 (index >= length || backing_store->get(index)->IsTheHole())) { | 8394 (index >= length || backing_store->get(index)->IsTheHole())) { |
| 8348 bool found; | 8395 bool found; |
| 8349 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 8396 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 8350 value, | 8397 value, |
| 8351 &found, | 8398 &found, |
| 8352 strict_mode); | 8399 strict_mode); |
| 8353 if (found) return result; | 8400 if (found) return result; |
| 8354 } | 8401 } |
| 8355 | 8402 |
| 8356 // Check whether there is extra space in fixed array. | 8403 // Check whether there is extra space in fixed array. |
| 8357 if (index < length) { | 8404 if (index < length) { |
| 8405 if (HasFastSmiOnlyElements()) { | |
| 8406 if (!value->IsSmi()) { | |
| 8407 // If the value is a number, transition from smi-only to | |
| 8408 // FastDoubleElements. | |
| 8409 if (value->IsNumber()) { | |
| 8410 MaybeObject* maybe = | |
| 8411 SetFastDoubleElementsCapacityAndLength(length, length); | |
| 8412 if (maybe->IsFailure()) return maybe; | |
| 8413 FixedDoubleArray::cast(elements())->set(index, value->Number()); | |
| 8414 return value; | |
| 8415 } | |
| 8416 // Value is not a number, transition to generic fast elements. | |
| 8417 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); | |
| 8418 Map* new_map; | |
| 8419 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | |
| 8420 set_map(new_map); | |
| 8421 } | |
| 8422 } | |
| 8358 backing_store->set(index, value); | 8423 backing_store->set(index, value); |
| 8359 if (IsJSArray()) { | 8424 if (IsJSArray()) { |
| 8360 // Update the length of the array if needed. | 8425 // Update the length of the array if needed. |
| 8361 uint32_t array_length = 0; | 8426 uint32_t array_length = 0; |
| 8362 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 8427 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 8363 if (index >= array_length) { | 8428 if (index >= array_length) { |
| 8364 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 8429 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 8365 } | 8430 } |
| 8366 } | 8431 } |
| 8367 return value; | 8432 return value; |
| 8368 } | 8433 } |
| 8369 | 8434 |
| 8370 // Allow gap in fast case. | 8435 // Allow gap in fast case. |
| 8371 if ((index - length) < kMaxGap) { | 8436 if ((index - length) < kMaxGap) { |
| 8372 // Try allocating extra space. | 8437 // Try allocating extra space. |
| 8373 int new_capacity = NewElementsCapacity(index + 1); | 8438 int new_capacity = NewElementsCapacity(index + 1); |
| 8374 if (!ShouldConvertToSlowElements(new_capacity)) { | 8439 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 8375 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 8440 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 8376 Object* new_elements; | 8441 Object* new_elements; |
| 8442 SetFastElementsCapacityMode set_capacity_mode = | |
| 8443 value->IsSmi() && HasFastSmiOnlyElements() | |
| 8444 ? kAllowSmiOnlyElements | |
| 8445 : kDontAllowSmiOnlyElements; | |
| 8377 MaybeObject* maybe = | 8446 MaybeObject* maybe = |
| 8378 SetFastElementsCapacityAndLength(new_capacity, index + 1); | 8447 SetFastElementsCapacityAndLength(new_capacity, |
| 8448 index + 1, | |
| 8449 set_capacity_mode); | |
| 8379 if (!maybe->ToObject(&new_elements)) return maybe; | 8450 if (!maybe->ToObject(&new_elements)) return maybe; |
| 8380 FixedArray::cast(new_elements)->set(index, value); | 8451 FixedArray::cast(new_elements)->set(index, value); |
| 8381 return value; | 8452 return value; |
| 8382 } | 8453 } |
| 8383 } | 8454 } |
| 8384 | 8455 |
| 8385 // Otherwise default to slow case. | 8456 // Otherwise default to slow case. |
| 8386 MaybeObject* result = NormalizeElements(); | 8457 MaybeObject* result = NormalizeElements(); |
| 8387 if (result->IsFailure()) return result; | 8458 if (result->IsFailure()) return result; |
| 8388 return SetDictionaryElement(index, value, strict_mode, check_prototype); | 8459 return SetDictionaryElement(index, value, strict_mode, check_prototype); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8474 // Attempt to put this object back in fast case. | 8545 // Attempt to put this object back in fast case. |
| 8475 if (ShouldConvertToFastElements()) { | 8546 if (ShouldConvertToFastElements()) { |
| 8476 uint32_t new_length = 0; | 8547 uint32_t new_length = 0; |
| 8477 if (IsJSArray()) { | 8548 if (IsJSArray()) { |
| 8478 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 8549 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
| 8479 } else { | 8550 } else { |
| 8480 new_length = dictionary->max_number_key() + 1; | 8551 new_length = dictionary->max_number_key() + 1; |
| 8481 } | 8552 } |
| 8482 MaybeObject* result = CanConvertToFastDoubleElements() | 8553 MaybeObject* result = CanConvertToFastDoubleElements() |
| 8483 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 8554 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
| 8484 : SetFastElementsCapacityAndLength(new_length, new_length); | 8555 : SetFastElementsCapacityAndLength(new_length, |
| 8556 new_length, | |
| 8557 kDontAllowSmiOnlyElements); | |
| 8485 if (result->IsFailure()) return result; | 8558 if (result->IsFailure()) return result; |
| 8486 #ifdef DEBUG | 8559 #ifdef DEBUG |
| 8487 if (FLAG_trace_normalization) { | 8560 if (FLAG_trace_normalization) { |
| 8488 PrintF("Object elements are fast case again:\n"); | 8561 PrintF("Object elements are fast case again:\n"); |
| 8489 Print(); | 8562 Print(); |
| 8490 } | 8563 } |
| 8491 #endif | 8564 #endif |
| 8492 } | 8565 } |
| 8493 return value; | 8566 return value; |
| 8494 } | 8567 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 8518 | 8591 |
| 8519 // If the value object is not a heap number, switch to fast elements and try | 8592 // If the value object is not a heap number, switch to fast elements and try |
| 8520 // again. | 8593 // again. |
| 8521 bool value_is_smi = value->IsSmi(); | 8594 bool value_is_smi = value->IsSmi(); |
| 8522 if (!value->IsNumber()) { | 8595 if (!value->IsNumber()) { |
| 8523 Object* obj; | 8596 Object* obj; |
| 8524 uint32_t length = elms_length; | 8597 uint32_t length = elms_length; |
| 8525 if (IsJSArray()) { | 8598 if (IsJSArray()) { |
| 8526 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 8599 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 8527 } | 8600 } |
| 8528 MaybeObject* maybe_obj = | 8601 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
| 8529 SetFastElementsCapacityAndLength(elms_length, length); | 8602 elms_length, |
| 8603 length, | |
| 8604 kDontAllowSmiOnlyElements); | |
| 8530 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8605 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8531 return SetFastElement(index, value, strict_mode, check_prototype); | 8606 return SetFastElement(index, |
| 8607 value, | |
| 8608 strict_mode, | |
| 8609 check_prototype); | |
| 8532 } | 8610 } |
| 8533 | 8611 |
| 8534 double double_value = value_is_smi | 8612 double double_value = value_is_smi |
| 8535 ? static_cast<double>(Smi::cast(value)->value()) | 8613 ? static_cast<double>(Smi::cast(value)->value()) |
| 8536 : HeapNumber::cast(value)->value(); | 8614 : HeapNumber::cast(value)->value(); |
| 8537 | 8615 |
| 8538 // Check whether there is extra space in the fixed array. | 8616 // Check whether there is extra space in the fixed array. |
| 8539 if (index < elms_length) { | 8617 if (index < elms_length) { |
| 8540 elms->set(index, double_value); | 8618 elms->set(index, double_value); |
| 8541 if (IsJSArray()) { | 8619 if (IsJSArray()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8618 check_prototype); | 8696 check_prototype); |
| 8619 } | 8697 } |
| 8620 | 8698 |
| 8621 | 8699 |
| 8622 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 8700 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 8623 Object* value, | 8701 Object* value, |
| 8624 StrictModeFlag strict_mode, | 8702 StrictModeFlag strict_mode, |
| 8625 bool check_prototype) { | 8703 bool check_prototype) { |
| 8626 Isolate* isolate = GetIsolate(); | 8704 Isolate* isolate = GetIsolate(); |
| 8627 switch (GetElementsKind()) { | 8705 switch (GetElementsKind()) { |
| 8706 case FAST_SMI_ONLY_ELEMENTS: | |
| 8628 case FAST_ELEMENTS: | 8707 case FAST_ELEMENTS: |
| 8629 return SetFastElement(index, value, strict_mode, check_prototype); | 8708 return SetFastElement(index, value, strict_mode, check_prototype); |
| 8630 case FAST_DOUBLE_ELEMENTS: | 8709 case FAST_DOUBLE_ELEMENTS: |
| 8631 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 8710 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
| 8632 case EXTERNAL_PIXEL_ELEMENTS: { | 8711 case EXTERNAL_PIXEL_ELEMENTS: { |
| 8633 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8712 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 8634 return pixels->SetValue(index, value); | 8713 return pixels->SetValue(index, value); |
| 8635 } | 8714 } |
| 8636 case EXTERNAL_BYTE_ELEMENTS: { | 8715 case EXTERNAL_BYTE_ELEMENTS: { |
| 8637 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 8716 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8780 backing_store_base = | 8859 backing_store_base = |
| 8781 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 8860 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 8782 backing_store = FixedArray::cast(backing_store_base); | 8861 backing_store = FixedArray::cast(backing_store_base); |
| 8783 if (backing_store->IsDictionary()) { | 8862 if (backing_store->IsDictionary()) { |
| 8784 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 8863 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 8785 *capacity = dictionary->Capacity(); | 8864 *capacity = dictionary->Capacity(); |
| 8786 *used = dictionary->NumberOfElements(); | 8865 *used = dictionary->NumberOfElements(); |
| 8787 break; | 8866 break; |
| 8788 } | 8867 } |
| 8789 // Fall through. | 8868 // Fall through. |
| 8869 case FAST_SMI_ONLY_ELEMENTS: | |
| 8790 case FAST_ELEMENTS: | 8870 case FAST_ELEMENTS: |
| 8791 backing_store = FixedArray::cast(backing_store_base); | 8871 backing_store = FixedArray::cast(backing_store_base); |
| 8792 *capacity = backing_store->length(); | 8872 *capacity = backing_store->length(); |
| 8793 for (int i = 0; i < *capacity; ++i) { | 8873 for (int i = 0; i < *capacity; ++i) { |
| 8794 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 8874 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
| 8795 } | 8875 } |
| 8796 break; | 8876 break; |
| 8797 case DICTIONARY_ELEMENTS: { | 8877 case DICTIONARY_ELEMENTS: { |
| 8798 NumberDictionary* dictionary = | 8878 NumberDictionary* dictionary = |
| 8799 NumberDictionary::cast(FixedArray::cast(elements())); | 8879 NumberDictionary::cast(FixedArray::cast(elements())); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9055 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 9135 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 9056 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 9136 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9057 return false; | 9137 return false; |
| 9058 } | 9138 } |
| 9059 } | 9139 } |
| 9060 | 9140 |
| 9061 // Handle [] on String objects. | 9141 // Handle [] on String objects. |
| 9062 if (this->IsStringObjectWithCharacterAt(index)) return true; | 9142 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 9063 | 9143 |
| 9064 switch (GetElementsKind()) { | 9144 switch (GetElementsKind()) { |
| 9145 case FAST_SMI_ONLY_ELEMENTS: | |
| 9065 case FAST_ELEMENTS: { | 9146 case FAST_ELEMENTS: { |
| 9066 uint32_t length = IsJSArray() ? | 9147 uint32_t length = IsJSArray() ? |
| 9067 static_cast<uint32_t>( | 9148 static_cast<uint32_t>( |
| 9068 Smi::cast(JSArray::cast(this)->length())->value()) : | 9149 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 9069 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 9150 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 9070 return (index < length) && | 9151 return (index < length) && |
| 9071 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 9152 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 9072 } | 9153 } |
| 9073 case FAST_DOUBLE_ELEMENTS: { | 9154 case FAST_DOUBLE_ELEMENTS: { |
| 9074 uint32_t length = IsJSArray() ? | 9155 uint32_t length = IsJSArray() ? |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9294 } | 9375 } |
| 9295 // Compute the number of enumerable elements. | 9376 // Compute the number of enumerable elements. |
| 9296 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 9377 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
| 9297 } | 9378 } |
| 9298 | 9379 |
| 9299 | 9380 |
| 9300 int JSObject::GetLocalElementKeys(FixedArray* storage, | 9381 int JSObject::GetLocalElementKeys(FixedArray* storage, |
| 9301 PropertyAttributes filter) { | 9382 PropertyAttributes filter) { |
| 9302 int counter = 0; | 9383 int counter = 0; |
| 9303 switch (GetElementsKind()) { | 9384 switch (GetElementsKind()) { |
| 9385 case FAST_SMI_ONLY_ELEMENTS: | |
| 9304 case FAST_ELEMENTS: { | 9386 case FAST_ELEMENTS: { |
| 9305 int length = IsJSArray() ? | 9387 int length = IsJSArray() ? |
| 9306 Smi::cast(JSArray::cast(this)->length())->value() : | 9388 Smi::cast(JSArray::cast(this)->length())->value() : |
| 9307 FixedArray::cast(elements())->length(); | 9389 FixedArray::cast(elements())->length(); |
| 9308 for (int i = 0; i < length; i++) { | 9390 for (int i = 0; i < length; i++) { |
| 9309 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 9391 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 9310 if (storage != NULL) { | 9392 if (storage != NULL) { |
| 9311 storage->set(counter, Smi::FromInt(i)); | 9393 storage->set(counter, Smi::FromInt(i)); |
| 9312 } | 9394 } |
| 9313 counter++; | 9395 counter++; |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10196 dict->CopyValuesTo(fast_elements); | 10278 dict->CopyValuesTo(fast_elements); |
| 10197 | 10279 |
| 10198 set_map(new_map); | 10280 set_map(new_map); |
| 10199 set_elements(fast_elements); | 10281 set_elements(fast_elements); |
| 10200 } else if (!HasFastDoubleElements()) { | 10282 } else if (!HasFastDoubleElements()) { |
| 10201 Object* obj; | 10283 Object* obj; |
| 10202 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 10284 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 10203 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10285 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 10204 } | 10286 } |
| 10205 } | 10287 } |
| 10206 ASSERT(HasFastElements() || HasFastDoubleElements()); | 10288 ASSERT(HasFastTypeElements() || |
| 10289 HasFastDoubleElements()); | |
| 10207 | 10290 |
| 10208 // Collect holes at the end, undefined before that and the rest at the | 10291 // Collect holes at the end, undefined before that and the rest at the |
| 10209 // start, and return the number of non-hole, non-undefined values. | 10292 // start, and return the number of non-hole, non-undefined values. |
| 10210 | 10293 |
| 10211 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 10294 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
| 10212 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 10295 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 10213 if (limit > elements_length) { | 10296 if (limit > elements_length) { |
| 10214 limit = elements_length ; | 10297 limit = elements_length ; |
| 10215 } | 10298 } |
| 10216 if (limit == 0) { | 10299 if (limit == 0) { |
| (...skipping 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11631 if (break_point_objects()->IsUndefined()) return 0; | 11714 if (break_point_objects()->IsUndefined()) return 0; |
| 11632 // Single break point. | 11715 // Single break point. |
| 11633 if (!break_point_objects()->IsFixedArray()) return 1; | 11716 if (!break_point_objects()->IsFixedArray()) return 1; |
| 11634 // Multiple break points. | 11717 // Multiple break points. |
| 11635 return FixedArray::cast(break_point_objects())->length(); | 11718 return FixedArray::cast(break_point_objects())->length(); |
| 11636 } | 11719 } |
| 11637 #endif | 11720 #endif |
| 11638 | 11721 |
| 11639 | 11722 |
| 11640 } } // namespace v8::internal | 11723 } } // namespace v8::internal |
| OLD | NEW |