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 2896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2907 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 2907 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 2908 Map* old_map = array->map(); | 2908 Map* old_map = array->map(); |
| 2909 bool is_arguments = | 2909 bool is_arguments = |
| 2910 (old_map == old_map->heap()->non_strict_arguments_elements_map()); | 2910 (old_map == old_map->heap()->non_strict_arguments_elements_map()); |
| 2911 if (is_arguments) { | 2911 if (is_arguments) { |
| 2912 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 2912 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 2913 } | 2913 } |
| 2914 if (array->IsDictionary()) return array; | 2914 if (array->IsDictionary()) return array; |
| 2915 | 2915 |
| 2916 ASSERT(HasFastElements() || | 2916 ASSERT(HasFastElements() || |
| 2917 HasFastSmiOnlyElements() || | |
| 2917 HasFastDoubleElements() || | 2918 HasFastDoubleElements() || |
| 2918 HasFastArgumentsElements()); | 2919 HasFastArgumentsElements()); |
| 2919 // Compute the effective length and allocate a new backing store. | 2920 // Compute the effective length and allocate a new backing store. |
| 2920 int length = IsJSArray() | 2921 int length = IsJSArray() |
| 2921 ? Smi::cast(JSArray::cast(this)->length())->value() | 2922 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2922 : array->length(); | 2923 : array->length(); |
| 2923 int old_capacity = 0; | 2924 int old_capacity = 0; |
| 2924 int used_elements = 0; | 2925 int used_elements = 0; |
| 2925 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 2926 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 2926 NumberDictionary* dictionary = NULL; | 2927 NumberDictionary* dictionary = NULL; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2941 } else { | 2942 } else { |
| 2942 // Objects must be allocated in the old object space, since the | 2943 // Objects must be allocated in the old object space, since the |
| 2943 // overall number of HeapNumbers needed for the conversion might | 2944 // overall number of HeapNumbers needed for the conversion might |
| 2944 // exceed the capacity of new space, and we would fail repeatedly | 2945 // exceed the capacity of new space, and we would fail repeatedly |
| 2945 // trying to convert the FixedDoubleArray. | 2946 // trying to convert the FixedDoubleArray. |
| 2946 MaybeObject* maybe_value_object = | 2947 MaybeObject* maybe_value_object = |
| 2947 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 2948 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 2948 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 2949 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 2949 } | 2950 } |
| 2950 } else { | 2951 } else { |
| 2951 ASSERT(old_map->has_fast_elements()); | 2952 ASSERT(old_map->has_fast_elements() || |
| 2953 old_map->has_fast_smi_only_elements()); | |
| 2952 value = FixedArray::cast(array)->get(i); | 2954 value = FixedArray::cast(array)->get(i); |
| 2953 } | 2955 } |
| 2954 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2956 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2955 if (!value->IsTheHole()) { | 2957 if (!value->IsTheHole()) { |
| 2956 Object* result; | 2958 Object* result; |
| 2957 MaybeObject* maybe_result = | 2959 MaybeObject* maybe_result = |
| 2958 dictionary->AddNumberEntry(i, value, details); | 2960 dictionary->AddNumberEntry(i, value, details); |
| 2959 if (!maybe_result->ToObject(&result)) return maybe_result; | 2961 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2960 dictionary = NumberDictionary::cast(result); | 2962 dictionary = NumberDictionary::cast(result); |
| 2961 } | 2963 } |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3248 } | 3250 } |
| 3249 // Make sure the properties are normalized before removing the entry. | 3251 // Make sure the properties are normalized before removing the entry. |
| 3250 return DeleteNormalizedProperty(name, mode); | 3252 return DeleteNormalizedProperty(name, mode); |
| 3251 } | 3253 } |
| 3252 } | 3254 } |
| 3253 | 3255 |
| 3254 | 3256 |
| 3255 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 3257 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 3256 ElementsKind kind, | 3258 ElementsKind kind, |
| 3257 Object* object) { | 3259 Object* object) { |
| 3258 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); | 3260 ASSERT(kind == FAST_ELEMENTS || |
| 3261 kind == FAST_SMI_ONLY_ELEMENTS || | |
| 3262 kind == DICTIONARY_ELEMENTS); | |
| 3259 if (kind == FAST_ELEMENTS) { | 3263 if (kind == FAST_ELEMENTS) { |
| 3260 int length = IsJSArray() | 3264 int length = IsJSArray() |
| 3261 ? Smi::cast(JSArray::cast(this)->length())->value() | 3265 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3262 : elements->length(); | 3266 : elements->length(); |
| 3263 for (int i = 0; i < length; ++i) { | 3267 for (int i = 0; i < length; ++i) { |
| 3264 Object* element = elements->get(i); | 3268 Object* element = elements->get(i); |
| 3265 if (!element->IsTheHole() && element == object) return true; | 3269 if (!element->IsTheHole() && element == object) return true; |
| 3266 } | 3270 } |
| 3267 } else { | 3271 } else if (kind != FAST_SMI_ONLY_ELEMENTS) { |
|
Rico
2011/09/16 09:40:10
kind == DICTIONARY_ELEMENTS
seems much more readab
danno
2011/09/21 14:32:04
Done.
| |
| 3268 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); | 3272 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); |
| 3269 if (!key->IsUndefined()) return true; | 3273 if (!key->IsUndefined()) return true; |
| 3270 } | 3274 } |
| 3271 return false; | 3275 return false; |
| 3272 } | 3276 } |
| 3273 | 3277 |
| 3274 | 3278 |
| 3275 // Check whether this object references another object. | 3279 // Check whether this object references another object. |
| 3276 bool JSObject::ReferencesObject(Object* obj) { | 3280 bool JSObject::ReferencesObject(Object* obj) { |
| 3277 Map* map_of_this = map(); | 3281 Map* map_of_this = map(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 3303 case EXTERNAL_SHORT_ELEMENTS: | 3307 case EXTERNAL_SHORT_ELEMENTS: |
| 3304 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3308 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3305 case EXTERNAL_INT_ELEMENTS: | 3309 case EXTERNAL_INT_ELEMENTS: |
| 3306 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3310 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3307 case EXTERNAL_FLOAT_ELEMENTS: | 3311 case EXTERNAL_FLOAT_ELEMENTS: |
| 3308 case EXTERNAL_DOUBLE_ELEMENTS: | 3312 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3309 case FAST_DOUBLE_ELEMENTS: | 3313 case FAST_DOUBLE_ELEMENTS: |
| 3310 // Raw pixels and external arrays do not reference other | 3314 // Raw pixels and external arrays do not reference other |
| 3311 // objects. | 3315 // objects. |
| 3312 break; | 3316 break; |
| 3317 case FAST_SMI_ONLY_ELEMENTS: | |
|
Rico
2011/09/16 09:40:10
Why not just break here and remove the new extra k
danno
2011/09/21 14:32:04
Done.
| |
| 3313 case FAST_ELEMENTS: | 3318 case FAST_ELEMENTS: |
| 3314 case DICTIONARY_ELEMENTS: { | 3319 case DICTIONARY_ELEMENTS: { |
| 3315 FixedArray* elements = FixedArray::cast(this->elements()); | 3320 FixedArray* elements = FixedArray::cast(this->elements()); |
| 3316 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 3321 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 3317 break; | 3322 break; |
| 3318 } | 3323 } |
| 3319 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 3324 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 3320 FixedArray* parameter_map = FixedArray::cast(elements()); | 3325 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 3321 // Check the mapped parameters. | 3326 // Check the mapped parameters. |
| 3322 int length = parameter_map->length(); | 3327 int length = parameter_map->length(); |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3595 | 3600 |
| 3596 if (!CanSetCallback(name)) { | 3601 if (!CanSetCallback(name)) { |
| 3597 return heap->undefined_value(); | 3602 return heap->undefined_value(); |
| 3598 } | 3603 } |
| 3599 | 3604 |
| 3600 uint32_t index = 0; | 3605 uint32_t index = 0; |
| 3601 bool is_element = name->AsArrayIndex(&index); | 3606 bool is_element = name->AsArrayIndex(&index); |
| 3602 | 3607 |
| 3603 if (is_element) { | 3608 if (is_element) { |
| 3604 switch (GetElementsKind()) { | 3609 switch (GetElementsKind()) { |
| 3610 case FAST_SMI_ONLY_ELEMENTS: | |
| 3605 case FAST_ELEMENTS: | 3611 case FAST_ELEMENTS: |
| 3606 case FAST_DOUBLE_ELEMENTS: | 3612 case FAST_DOUBLE_ELEMENTS: |
| 3607 break; | 3613 break; |
| 3608 case EXTERNAL_PIXEL_ELEMENTS: | 3614 case EXTERNAL_PIXEL_ELEMENTS: |
| 3609 case EXTERNAL_BYTE_ELEMENTS: | 3615 case EXTERNAL_BYTE_ELEMENTS: |
| 3610 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3616 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3611 case EXTERNAL_SHORT_ELEMENTS: | 3617 case EXTERNAL_SHORT_ELEMENTS: |
| 3612 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3618 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3613 case EXTERNAL_INT_ELEMENTS: | 3619 case EXTERNAL_INT_ELEMENTS: |
| 3614 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3620 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3844 } | 3850 } |
| 3845 | 3851 |
| 3846 uint32_t index = 0; | 3852 uint32_t index = 0; |
| 3847 bool is_element = name->AsArrayIndex(&index); | 3853 bool is_element = name->AsArrayIndex(&index); |
| 3848 | 3854 |
| 3849 if (is_element) { | 3855 if (is_element) { |
| 3850 if (IsJSArray()) return isolate->heap()->undefined_value(); | 3856 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 3851 | 3857 |
| 3852 // Accessors overwrite previous callbacks (cf. with getters/setters). | 3858 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 3853 switch (GetElementsKind()) { | 3859 switch (GetElementsKind()) { |
| 3860 case FAST_SMI_ONLY_ELEMENTS: | |
| 3854 case FAST_ELEMENTS: | 3861 case FAST_ELEMENTS: |
| 3855 case FAST_DOUBLE_ELEMENTS: | 3862 case FAST_DOUBLE_ELEMENTS: |
| 3856 break; | 3863 break; |
| 3857 case EXTERNAL_PIXEL_ELEMENTS: | 3864 case EXTERNAL_PIXEL_ELEMENTS: |
| 3858 case EXTERNAL_BYTE_ELEMENTS: | 3865 case EXTERNAL_BYTE_ELEMENTS: |
| 3859 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3866 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3860 case EXTERNAL_SHORT_ELEMENTS: | 3867 case EXTERNAL_SHORT_ELEMENTS: |
| 3861 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3868 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3862 case EXTERNAL_INT_ELEMENTS: | 3869 case EXTERNAL_INT_ELEMENTS: |
| 3863 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3870 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| (...skipping 3388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7252 for (int i = 0; i < source->Capacity(); ++i) { | 7259 for (int i = 0; i < source->Capacity(); ++i) { |
| 7253 Object* key = source->KeyAt(i); | 7260 Object* key = source->KeyAt(i); |
| 7254 if (key->IsNumber()) { | 7261 if (key->IsNumber()) { |
| 7255 uint32_t entry = static_cast<uint32_t>(key->Number()); | 7262 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 7256 destination->set(entry, source->ValueAt(i), mode); | 7263 destination->set(entry, source->ValueAt(i), mode); |
| 7257 } | 7264 } |
| 7258 } | 7265 } |
| 7259 } | 7266 } |
| 7260 | 7267 |
| 7261 | 7268 |
| 7262 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, | 7269 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
| 7263 int length) { | 7270 int capacity, |
| 7271 int length, | |
| 7272 SetFastElementsCapacityMode set_capacity_mode) { | |
| 7264 Heap* heap = GetHeap(); | 7273 Heap* heap = GetHeap(); |
| 7265 // We should never end in here with a pixel or external array. | 7274 // We should never end in here with a pixel or external array. |
| 7266 ASSERT(!HasExternalArrayElements()); | 7275 ASSERT(!HasExternalArrayElements()); |
| 7267 | 7276 |
| 7268 // Allocate a new fast elements backing store. | 7277 // Allocate a new fast elements backing store. |
| 7269 FixedArray* new_elements = NULL; | 7278 FixedArray* new_elements = NULL; |
| 7270 { Object* object; | 7279 { Object* object; |
| 7271 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 7280 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
| 7272 if (!maybe->ToObject(&object)) return maybe; | 7281 if (!maybe->ToObject(&object)) return maybe; |
| 7273 new_elements = FixedArray::cast(object); | 7282 new_elements = FixedArray::cast(object); |
| 7274 } | 7283 } |
| 7275 | 7284 |
| 7276 // Find the new map to use for this object if there is a map change. | 7285 // Find the new map to use for this object if there is a map change. |
| 7277 Map* new_map = NULL; | 7286 Map* new_map = NULL; |
| 7278 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 7287 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
| 7279 Object* object; | 7288 Object* object; |
| 7280 MaybeObject* maybe = GetElementsTransitionMap(FAST_ELEMENTS); | 7289 bool has_fast_smi_only_elements = |
| 7290 FLAG_smi_only_arrays && | |
| 7291 (set_capacity_mode == kAllowSmiOnlyElements) && | |
| 7292 (elements()->map()->has_fast_smi_only_elements() || | |
| 7293 elements() == heap->empty_fixed_array()); | |
| 7294 ElementsKind elements_kind = has_fast_smi_only_elements | |
| 7295 ? FAST_SMI_ONLY_ELEMENTS | |
| 7296 : FAST_ELEMENTS; | |
| 7297 MaybeObject* maybe = GetElementsTransitionMap(elements_kind); | |
| 7281 if (!maybe->ToObject(&object)) return maybe; | 7298 if (!maybe->ToObject(&object)) return maybe; |
| 7282 new_map = Map::cast(object); | 7299 new_map = Map::cast(object); |
| 7283 } | 7300 } |
| 7284 | 7301 |
| 7285 switch (GetElementsKind()) { | 7302 ElementsKind elements_kind = GetElementsKind(); |
| 7303 switch (elements_kind) { | |
| 7304 case FAST_SMI_ONLY_ELEMENTS: | |
| 7286 case FAST_ELEMENTS: { | 7305 case FAST_ELEMENTS: { |
| 7287 AssertNoAllocation no_gc; | 7306 AssertNoAllocation no_gc; |
| 7288 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7307 WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc)); |
| 7289 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 7308 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); |
| 7290 set_map(new_map); | 7309 set_map(new_map); |
| 7291 set_elements(new_elements); | 7310 set_elements(new_elements); |
| 7292 break; | 7311 break; |
| 7293 } | 7312 } |
| 7294 case DICTIONARY_ELEMENTS: { | 7313 case DICTIONARY_ELEMENTS: { |
| 7295 AssertNoAllocation no_gc; | 7314 AssertNoAllocation no_gc; |
| 7296 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7315 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7297 CopySlowElementsToFast(NumberDictionary::cast(elements()), | 7316 CopySlowElementsToFast(NumberDictionary::cast(elements()), |
| 7298 new_elements, | 7317 new_elements, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7381 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); | 7400 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); |
| 7382 | 7401 |
| 7383 { MaybeObject* maybe_obj = | 7402 { MaybeObject* maybe_obj = |
| 7384 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); | 7403 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); |
| 7385 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7404 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7386 } | 7405 } |
| 7387 Map* new_map = Map::cast(obj); | 7406 Map* new_map = Map::cast(obj); |
| 7388 | 7407 |
| 7389 AssertNoAllocation no_gc; | 7408 AssertNoAllocation no_gc; |
| 7390 switch (GetElementsKind()) { | 7409 switch (GetElementsKind()) { |
| 7410 case FAST_SMI_ONLY_ELEMENTS: | |
| 7391 case FAST_ELEMENTS: { | 7411 case FAST_ELEMENTS: { |
| 7392 elems->Initialize(FixedArray::cast(elements())); | 7412 elems->Initialize(FixedArray::cast(elements())); |
| 7393 break; | 7413 break; |
| 7394 } | 7414 } |
| 7395 case FAST_DOUBLE_ELEMENTS: { | 7415 case FAST_DOUBLE_ELEMENTS: { |
| 7396 elems->Initialize(FixedDoubleArray::cast(elements())); | 7416 elems->Initialize(FixedDoubleArray::cast(elements())); |
| 7397 break; | 7417 break; |
| 7398 } | 7418 } |
| 7399 case DICTIONARY_ELEMENTS: { | 7419 case DICTIONARY_ELEMENTS: { |
| 7400 elems->Initialize(NumberDictionary::cast(elements())); | 7420 elems->Initialize(NumberDictionary::cast(elements())); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 7418 } | 7438 } |
| 7419 | 7439 |
| 7420 | 7440 |
| 7421 MaybeObject* JSObject::SetSlowElements(Object* len) { | 7441 MaybeObject* JSObject::SetSlowElements(Object* len) { |
| 7422 // We should never end in here with a pixel or external array. | 7442 // We should never end in here with a pixel or external array. |
| 7423 ASSERT(!HasExternalArrayElements()); | 7443 ASSERT(!HasExternalArrayElements()); |
| 7424 | 7444 |
| 7425 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 7445 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 7426 | 7446 |
| 7427 switch (GetElementsKind()) { | 7447 switch (GetElementsKind()) { |
| 7428 case FAST_ELEMENTS: { | 7448 case FAST_SMI_ONLY_ELEMENTS: |
| 7429 case FAST_DOUBLE_ELEMENTS: | 7449 case FAST_ELEMENTS: |
| 7450 case FAST_DOUBLE_ELEMENTS: { | |
| 7430 // Make sure we never try to shrink dense arrays into sparse arrays. | 7451 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 7431 ASSERT(static_cast<uint32_t>( | 7452 ASSERT(static_cast<uint32_t>( |
| 7432 FixedArrayBase::cast(elements())->length()) <= new_length); | 7453 FixedArrayBase::cast(elements())->length()) <= new_length); |
| 7433 MaybeObject* result = NormalizeElements(); | 7454 MaybeObject* result = NormalizeElements(); |
| 7434 if (result->IsFailure()) return result; | 7455 if (result->IsFailure()) return result; |
| 7435 | 7456 |
| 7436 // Update length for JSArrays. | 7457 // Update length for JSArrays. |
| 7437 if (IsJSArray()) JSArray::cast(this)->set_length(len); | 7458 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 7438 break; | 7459 break; |
| 7439 } | 7460 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7485 | 7506 |
| 7486 | 7507 |
| 7487 void JSArray::Expand(int required_size) { | 7508 void JSArray::Expand(int required_size) { |
| 7488 Handle<JSArray> self(this); | 7509 Handle<JSArray> self(this); |
| 7489 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 7510 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 7490 int old_size = old_backing->length(); | 7511 int old_size = old_backing->length(); |
| 7491 int new_size = required_size > old_size ? required_size : old_size; | 7512 int new_size = required_size > old_size ? required_size : old_size; |
| 7492 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); | 7513 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 7493 // Can't use this any more now because we may have had a GC! | 7514 // Can't use this any more now because we may have had a GC! |
| 7494 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 7515 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 7495 self->SetContent(*new_backing); | 7516 GetIsolate()->factory()->SetContent(self, new_backing); |
| 7496 } | 7517 } |
| 7497 | 7518 |
| 7498 | 7519 |
| 7499 static Failure* ArrayLengthRangeError(Heap* heap) { | 7520 static Failure* ArrayLengthRangeError(Heap* heap) { |
| 7500 HandleScope scope(heap->isolate()); | 7521 HandleScope scope(heap->isolate()); |
| 7501 return heap->isolate()->Throw( | 7522 return heap->isolate()->Throw( |
| 7502 *FACTORY->NewRangeError("invalid_array_length", | 7523 *FACTORY->NewRangeError("invalid_array_length", |
| 7503 HandleVector<Object>(NULL, 0))); | 7524 HandleVector<Object>(NULL, 0))); |
| 7504 } | 7525 } |
| 7505 | 7526 |
| 7506 | 7527 |
| 7507 MaybeObject* JSObject::SetElementsLength(Object* len) { | 7528 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 7508 // We should never end in here with a pixel or external array. | 7529 // We should never end in here with a pixel or external array. |
| 7509 ASSERT(AllowsSetElementsLength()); | 7530 ASSERT(AllowsSetElementsLength()); |
| 7510 | 7531 |
| 7511 MaybeObject* maybe_smi_length = len->ToSmi(); | 7532 MaybeObject* maybe_smi_length = len->ToSmi(); |
| 7512 Object* smi_length = Smi::FromInt(0); | 7533 Object* smi_length = Smi::FromInt(0); |
| 7513 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 7534 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 7514 const int value = Smi::cast(smi_length)->value(); | 7535 const int value = Smi::cast(smi_length)->value(); |
| 7515 if (value < 0) return ArrayLengthRangeError(GetHeap()); | 7536 if (value < 0) return ArrayLengthRangeError(GetHeap()); |
| 7516 ElementsKind elements_kind = GetElementsKind(); | 7537 ElementsKind elements_kind = GetElementsKind(); |
| 7517 switch (elements_kind) { | 7538 switch (elements_kind) { |
| 7539 case FAST_SMI_ONLY_ELEMENTS: | |
| 7518 case FAST_ELEMENTS: | 7540 case FAST_ELEMENTS: |
| 7519 case FAST_DOUBLE_ELEMENTS: { | 7541 case FAST_DOUBLE_ELEMENTS: { |
| 7520 int old_capacity = FixedArrayBase::cast(elements())->length(); | 7542 int old_capacity = FixedArrayBase::cast(elements())->length(); |
| 7521 if (value <= old_capacity) { | 7543 if (value <= old_capacity) { |
| 7522 if (IsJSArray()) { | 7544 if (IsJSArray()) { |
| 7523 Object* obj; | 7545 Object* obj; |
| 7524 if (elements_kind == FAST_ELEMENTS) { | 7546 if (elements_kind != FAST_DOUBLE_ELEMENTS) { |
| 7547 ASSERT(elements_kind == FAST_ELEMENTS || | |
| 7548 elements_kind == FAST_SMI_ONLY_ELEMENTS); | |
| 7525 MaybeObject* maybe_obj = EnsureWritableFastElements(); | 7549 MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 7526 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7550 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7527 } | 7551 } |
| 7528 if (2 * value <= old_capacity) { | 7552 if (2 * value <= old_capacity) { |
| 7529 // If more than half the elements won't be used, trim the array. | 7553 // If more than half the elements won't be used, trim the array. |
| 7530 if (value == 0) { | 7554 if (value == 0) { |
| 7531 initialize_elements(); | 7555 initialize_elements(); |
| 7532 } else { | 7556 } else { |
| 7533 Address filler_start; | 7557 Address filler_start; |
| 7534 int filler_size; | 7558 int filler_size; |
| 7535 if (GetElementsKind() == FAST_ELEMENTS) { | 7559 if (elements_kind == FAST_ELEMENTS || |
| 7560 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 7536 FixedArray* fast_elements = FixedArray::cast(elements()); | 7561 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7537 fast_elements->set_length(value); | 7562 fast_elements->set_length(value); |
| 7538 filler_start = fast_elements->address() + | 7563 filler_start = fast_elements->address() + |
| 7539 FixedArray::OffsetOfElementAt(value); | 7564 FixedArray::OffsetOfElementAt(value); |
| 7540 filler_size = (old_capacity - value) * kPointerSize; | 7565 filler_size = (old_capacity - value) * kPointerSize; |
| 7541 } else { | 7566 } else { |
| 7542 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7567 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); |
| 7543 FixedDoubleArray* fast_double_elements = | 7568 FixedDoubleArray* fast_double_elements = |
| 7544 FixedDoubleArray::cast(elements()); | 7569 FixedDoubleArray::cast(elements()); |
| 7545 fast_double_elements->set_length(value); | 7570 fast_double_elements->set_length(value); |
| 7546 filler_start = fast_double_elements->address() + | 7571 filler_start = fast_double_elements->address() + |
| 7547 FixedDoubleArray::OffsetOfElementAt(value); | 7572 FixedDoubleArray::OffsetOfElementAt(value); |
| 7548 filler_size = (old_capacity - value) * kDoubleSize; | 7573 filler_size = (old_capacity - value) * kDoubleSize; |
| 7549 } | 7574 } |
| 7550 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | 7575 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); |
| 7551 } | 7576 } |
| 7552 } else { | 7577 } else { |
| 7553 // Otherwise, fill the unused tail with holes. | 7578 // Otherwise, fill the unused tail with holes. |
| 7554 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 7579 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| 7555 if (GetElementsKind() == FAST_ELEMENTS) { | 7580 if (elements_kind == FAST_ELEMENTS || |
| 7581 elements_kind == FAST_SMI_ONLY_ELEMENTS) { | |
| 7556 FixedArray* fast_elements = FixedArray::cast(elements()); | 7582 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7557 for (int i = value; i < old_length; i++) { | 7583 for (int i = value; i < old_length; i++) { |
| 7558 fast_elements->set_the_hole(i); | 7584 fast_elements->set_the_hole(i); |
| 7559 } | 7585 } |
| 7560 } else { | 7586 } else { |
| 7561 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7587 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); |
| 7562 FixedDoubleArray* fast_double_elements = | 7588 FixedDoubleArray* fast_double_elements = |
| 7563 FixedDoubleArray::cast(elements()); | 7589 FixedDoubleArray::cast(elements()); |
| 7564 for (int i = value; i < old_length; i++) { | 7590 for (int i = value; i < old_length; i++) { |
| 7565 fast_double_elements->set_the_hole(i); | 7591 fast_double_elements->set_the_hole(i); |
| 7566 } | 7592 } |
| 7567 } | 7593 } |
| 7568 } | 7594 } |
| 7569 JSArray::cast(this)->set_length(Smi::cast(smi_length)); | 7595 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 7570 } | 7596 } |
| 7571 return this; | 7597 return this; |
| 7572 } | 7598 } |
| 7573 int min = NewElementsCapacity(old_capacity); | 7599 int min = NewElementsCapacity(old_capacity); |
| 7574 int new_capacity = value > min ? value : min; | 7600 int new_capacity = value > min ? value : min; |
| 7575 if (!ShouldConvertToSlowElements(new_capacity)) { | 7601 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 7576 MaybeObject* result; | 7602 MaybeObject* result; |
| 7577 if (GetElementsKind() == FAST_ELEMENTS) { | 7603 if (elements_kind == FAST_ELEMENTS || |
| 7578 result = SetFastElementsCapacityAndLength(new_capacity, value); | 7604 elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 7605 SetFastElementsCapacityMode set_capacity_mode = | |
| 7606 elements_kind == FAST_SMI_ONLY_ELEMENTS | |
| 7607 ? kAllowSmiOnlyElements | |
| 7608 : kDontAllowSmiOnlyElements; | |
| 7609 result = SetFastElementsCapacityAndLength(new_capacity, | |
| 7610 value, | |
| 7611 set_capacity_mode); | |
| 7579 } else { | 7612 } else { |
| 7580 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 7613 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS); |
| 7581 result = SetFastDoubleElementsCapacityAndLength(new_capacity, | 7614 result = SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 7582 value); | 7615 value); |
| 7583 } | 7616 } |
| 7584 if (result->IsFailure()) return result; | 7617 if (result->IsFailure()) return result; |
| 7585 return this; | 7618 return this; |
| 7586 } | 7619 } |
| 7587 break; | 7620 break; |
| 7588 } | 7621 } |
| 7589 case DICTIONARY_ELEMENTS: { | 7622 case DICTIONARY_ELEMENTS: { |
| 7590 if (IsJSArray()) { | 7623 if (IsJSArray()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7627 if (len->ToArrayIndex(&length)) { | 7660 if (len->ToArrayIndex(&length)) { |
| 7628 return SetSlowElements(len); | 7661 return SetSlowElements(len); |
| 7629 } else { | 7662 } else { |
| 7630 return ArrayLengthRangeError(GetHeap()); | 7663 return ArrayLengthRangeError(GetHeap()); |
| 7631 } | 7664 } |
| 7632 } | 7665 } |
| 7633 | 7666 |
| 7634 // len is not a number so make the array size one and | 7667 // len is not a number so make the array size one and |
| 7635 // set only element to len. | 7668 // set only element to len. |
| 7636 Object* obj; | 7669 Object* obj; |
| 7637 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); | 7670 MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); |
| 7638 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7671 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7639 } | |
| 7640 FixedArray::cast(obj)->set(0, len); | 7672 FixedArray::cast(obj)->set(0, len); |
| 7673 | |
| 7674 maybe_obj = EnsureCanContainElements(&len, 1); | |
| 7675 if (maybe_obj->IsFailure()) return maybe_obj; | |
| 7676 | |
| 7641 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | 7677 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 7642 set_elements(FixedArray::cast(obj)); | 7678 set_elements(FixedArray::cast(obj)); |
| 7643 return this; | 7679 return this; |
| 7644 } | 7680 } |
| 7645 | 7681 |
| 7646 | 7682 |
| 7647 Object* Map::GetPrototypeTransition(Object* prototype) { | 7683 Object* Map::GetPrototypeTransition(Object* prototype) { |
| 7648 FixedArray* cache = prototype_transitions(); | 7684 FixedArray* cache = prototype_transitions(); |
| 7649 int number_of_transitions = NumberOfProtoTransitions(); | 7685 int number_of_transitions = NumberOfProtoTransitions(); |
| 7650 const int proto_offset = | 7686 const int proto_offset = |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7778 } | 7814 } |
| 7779 ASSERT(Map::cast(new_map)->prototype() == value); | 7815 ASSERT(Map::cast(new_map)->prototype() == value); |
| 7780 real_receiver->set_map(Map::cast(new_map)); | 7816 real_receiver->set_map(Map::cast(new_map)); |
| 7781 | 7817 |
| 7782 heap->ClearInstanceofCache(); | 7818 heap->ClearInstanceofCache(); |
| 7783 ASSERT(size == Size()); | 7819 ASSERT(size == Size()); |
| 7784 return value; | 7820 return value; |
| 7785 } | 7821 } |
| 7786 | 7822 |
| 7787 | 7823 |
| 7824 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | |
| 7825 uint32_t first_arg, | |
| 7826 uint32_t arg_count) { | |
| 7827 return EnsureCanContainElements(args->arguments() - first_arg, arg_count); | |
| 7828 } | |
| 7829 | |
| 7830 | |
| 7788 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { | 7831 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
| 7789 switch (GetElementsKind()) { | 7832 switch (GetElementsKind()) { |
| 7833 case FAST_SMI_ONLY_ELEMENTS: | |
| 7790 case FAST_ELEMENTS: { | 7834 case FAST_ELEMENTS: { |
| 7791 uint32_t length = IsJSArray() ? | 7835 uint32_t length = IsJSArray() ? |
| 7792 static_cast<uint32_t> | 7836 static_cast<uint32_t> |
| 7793 (Smi::cast(JSArray::cast(this)->length())->value()) : | 7837 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7794 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 7838 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7795 if ((index < length) && | 7839 if ((index < length) && |
| 7796 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 7840 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7797 return true; | 7841 return true; |
| 7798 } | 7842 } |
| 7799 break; | 7843 break; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7916 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 7960 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
| 7917 : UNDEFINED_ELEMENT; | 7961 : UNDEFINED_ELEMENT; |
| 7918 } | 7962 } |
| 7919 | 7963 |
| 7920 // Handle [] on String objects. | 7964 // Handle [] on String objects. |
| 7921 if (this->IsStringObjectWithCharacterAt(index)) { | 7965 if (this->IsStringObjectWithCharacterAt(index)) { |
| 7922 return STRING_CHARACTER_ELEMENT; | 7966 return STRING_CHARACTER_ELEMENT; |
| 7923 } | 7967 } |
| 7924 | 7968 |
| 7925 switch (GetElementsKind()) { | 7969 switch (GetElementsKind()) { |
| 7970 case FAST_SMI_ONLY_ELEMENTS: | |
| 7926 case FAST_ELEMENTS: { | 7971 case FAST_ELEMENTS: { |
| 7927 uint32_t length = IsJSArray() ? | 7972 uint32_t length = IsJSArray() ? |
| 7928 static_cast<uint32_t> | 7973 static_cast<uint32_t> |
| 7929 (Smi::cast(JSArray::cast(this)->length())->value()) : | 7974 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7930 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 7975 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7931 if ((index < length) && | 7976 if ((index < length) && |
| 7932 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 7977 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7933 return FAST_ELEMENT; | 7978 return FAST_ELEMENT; |
| 7934 } | 7979 } |
| 7935 break; | 7980 break; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8030 } | 8075 } |
| 8031 } | 8076 } |
| 8032 | 8077 |
| 8033 // Check for lookup interceptor | 8078 // Check for lookup interceptor |
| 8034 if (HasIndexedInterceptor()) { | 8079 if (HasIndexedInterceptor()) { |
| 8035 return HasElementWithInterceptor(receiver, index); | 8080 return HasElementWithInterceptor(receiver, index); |
| 8036 } | 8081 } |
| 8037 | 8082 |
| 8038 ElementsKind kind = GetElementsKind(); | 8083 ElementsKind kind = GetElementsKind(); |
| 8039 switch (kind) { | 8084 switch (kind) { |
| 8085 case FAST_SMI_ONLY_ELEMENTS: | |
| 8040 case FAST_ELEMENTS: { | 8086 case FAST_ELEMENTS: { |
| 8041 uint32_t length = IsJSArray() ? | 8087 uint32_t length = IsJSArray() ? |
| 8042 static_cast<uint32_t> | 8088 static_cast<uint32_t> |
| 8043 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8089 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8044 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8090 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 8045 if ((index < length) && | 8091 if ((index < length) && |
| 8046 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | 8092 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| 8047 break; | 8093 break; |
| 8048 } | 8094 } |
| 8049 case FAST_DOUBLE_ELEMENTS: { | 8095 case FAST_DOUBLE_ELEMENTS: { |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8276 return false; | 8322 return false; |
| 8277 } | 8323 } |
| 8278 FixedArray* arguments = FixedArray::cast(elements->get(1)); | 8324 FixedArray* arguments = FixedArray::cast(elements->get(1)); |
| 8279 return arguments->IsDictionary(); | 8325 return arguments->IsDictionary(); |
| 8280 } | 8326 } |
| 8281 | 8327 |
| 8282 | 8328 |
| 8283 // Adding n elements in fast case is O(n*n). | 8329 // Adding n elements in fast case is O(n*n). |
| 8284 // Note: revisit design to have dual undefined values to capture absent | 8330 // Note: revisit design to have dual undefined values to capture absent |
| 8285 // elements. | 8331 // elements. |
| 8286 MaybeObject* JSObject::SetFastElement(uint32_t index, | 8332 MaybeObject* JSObject::SetFastElement( |
| 8287 Object* value, | 8333 uint32_t index, |
|
Jakob Kummerow
2011/09/16 16:30:34
Why the new line break?
danno
2011/09/21 14:32:04
Done.
| |
| 8288 StrictModeFlag strict_mode, | 8334 Object* value, |
| 8289 bool check_prototype) { | 8335 StrictModeFlag strict_mode, |
| 8290 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 8336 bool check_prototype) { |
| 8337 ASSERT(HasFastElements() || | |
| 8338 HasFastSmiOnlyElements() || | |
| 8339 HasFastArgumentsElements()); | |
| 8291 | 8340 |
| 8292 FixedArray* backing_store = FixedArray::cast(elements()); | 8341 FixedArray* backing_store = FixedArray::cast(elements()); |
| 8293 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 8342 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 8294 backing_store = FixedArray::cast(backing_store->get(1)); | 8343 backing_store = FixedArray::cast(backing_store->get(1)); |
| 8295 } else { | 8344 } else { |
| 8296 Object* writable; | 8345 Object* writable; |
| 8297 MaybeObject* maybe = EnsureWritableFastElements(); | 8346 MaybeObject* maybe = EnsureWritableFastElements(); |
| 8298 if (!maybe->ToObject(&writable)) return maybe; | 8347 if (!maybe->ToObject(&writable)) return maybe; |
| 8299 backing_store = FixedArray::cast(writable); | 8348 backing_store = FixedArray::cast(writable); |
| 8300 } | 8349 } |
| 8301 uint32_t length = static_cast<uint32_t>(backing_store->length()); | 8350 uint32_t length = static_cast<uint32_t>(backing_store->length()); |
| 8302 | 8351 |
| 8303 if (check_prototype && | 8352 if (check_prototype && |
| 8304 (index >= length || backing_store->get(index)->IsTheHole())) { | 8353 (index >= length || backing_store->get(index)->IsTheHole())) { |
| 8305 bool found; | 8354 bool found; |
| 8306 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 8355 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 8307 value, | 8356 value, |
| 8308 &found, | 8357 &found, |
| 8309 strict_mode); | 8358 strict_mode); |
| 8310 if (found) return result; | 8359 if (found) return result; |
| 8311 } | 8360 } |
| 8312 | 8361 |
| 8313 // Check whether there is extra space in fixed array. | 8362 // Check whether there is extra space in fixed array. |
| 8314 if (index < length) { | 8363 if (index < length) { |
| 8364 if (HasFastSmiOnlyElements()) { | |
| 8365 if (!value->IsSmi()) { | |
| 8366 // If the value is a number, transition from smi-only to | |
| 8367 // FastDoubleElements | |
|
Jakob Kummerow
2011/09/16 16:30:34
nit: missing period
danno
2011/09/21 14:32:04
Done.
| |
| 8368 if (value->IsNumber()) { | |
| 8369 MaybeObject* maybe = | |
| 8370 SetFastDoubleElementsCapacityAndLength(length, length); | |
| 8371 if (maybe->IsFailure()) return maybe; | |
| 8372 FixedDoubleArray::cast(elements())->set(index, value->Number()); | |
| 8373 return value; | |
| 8374 } | |
| 8375 // Value is not a number, transition to generic fast elements. | |
| 8376 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); | |
| 8377 Map* new_map; | |
| 8378 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | |
| 8379 set_map(new_map); | |
| 8380 } | |
| 8381 } | |
| 8315 backing_store->set(index, value); | 8382 backing_store->set(index, value); |
| 8316 if (IsJSArray()) { | 8383 if (IsJSArray()) { |
| 8317 // Update the length of the array if needed. | 8384 // Update the length of the array if needed. |
| 8318 uint32_t array_length = 0; | 8385 uint32_t array_length = 0; |
| 8319 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 8386 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 8320 if (index >= array_length) { | 8387 if (index >= array_length) { |
| 8321 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 8388 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 8322 } | 8389 } |
| 8323 } | 8390 } |
| 8324 return value; | 8391 return value; |
| 8325 } | 8392 } |
| 8326 | 8393 |
| 8327 // Allow gap in fast case. | 8394 // Allow gap in fast case. |
| 8328 if ((index - length) < kMaxGap) { | 8395 if ((index - length) < kMaxGap) { |
| 8329 // Try allocating extra space. | 8396 // Try allocating extra space. |
| 8330 int new_capacity = NewElementsCapacity(index + 1); | 8397 int new_capacity = NewElementsCapacity(index + 1); |
| 8331 if (!ShouldConvertToSlowElements(new_capacity)) { | 8398 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 8332 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 8399 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 8333 Object* new_elements; | 8400 Object* new_elements; |
| 8401 SetFastElementsCapacityMode set_capacity_mode = | |
| 8402 value->IsSmi() && HasFastSmiOnlyElements() | |
| 8403 ? kAllowSmiOnlyElements | |
| 8404 : kDontAllowSmiOnlyElements; | |
| 8334 MaybeObject* maybe = | 8405 MaybeObject* maybe = |
| 8335 SetFastElementsCapacityAndLength(new_capacity, index + 1); | 8406 SetFastElementsCapacityAndLength(new_capacity, |
| 8407 index + 1, | |
| 8408 set_capacity_mode); | |
| 8336 if (!maybe->ToObject(&new_elements)) return maybe; | 8409 if (!maybe->ToObject(&new_elements)) return maybe; |
| 8337 FixedArray::cast(new_elements)->set(index, value); | 8410 FixedArray::cast(new_elements)->set(index, value); |
| 8338 return value; | 8411 return value; |
| 8339 } | 8412 } |
| 8340 } | 8413 } |
| 8341 | 8414 |
| 8342 // Otherwise default to slow case. | 8415 // Otherwise default to slow case. |
| 8343 MaybeObject* result = NormalizeElements(); | 8416 MaybeObject* result = NormalizeElements(); |
| 8344 if (result->IsFailure()) return result; | 8417 if (result->IsFailure()) return result; |
| 8345 return SetDictionaryElement(index, value, strict_mode, check_prototype); | 8418 return SetDictionaryElement(index, value, strict_mode, check_prototype); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8431 // Attempt to put this object back in fast case. | 8504 // Attempt to put this object back in fast case. |
| 8432 if (ShouldConvertToFastElements()) { | 8505 if (ShouldConvertToFastElements()) { |
| 8433 uint32_t new_length = 0; | 8506 uint32_t new_length = 0; |
| 8434 if (IsJSArray()) { | 8507 if (IsJSArray()) { |
| 8435 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 8508 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
| 8436 } else { | 8509 } else { |
| 8437 new_length = dictionary->max_number_key() + 1; | 8510 new_length = dictionary->max_number_key() + 1; |
| 8438 } | 8511 } |
| 8439 MaybeObject* result = CanConvertToFastDoubleElements() | 8512 MaybeObject* result = CanConvertToFastDoubleElements() |
| 8440 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 8513 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
| 8441 : SetFastElementsCapacityAndLength(new_length, new_length); | 8514 : SetFastElementsCapacityAndLength(new_length, |
| 8515 new_length, | |
| 8516 kDontAllowSmiOnlyElements); | |
| 8442 if (result->IsFailure()) return result; | 8517 if (result->IsFailure()) return result; |
| 8443 #ifdef DEBUG | 8518 #ifdef DEBUG |
| 8444 if (FLAG_trace_normalization) { | 8519 if (FLAG_trace_normalization) { |
| 8445 PrintF("Object elements are fast case again:\n"); | 8520 PrintF("Object elements are fast case again:\n"); |
| 8446 Print(); | 8521 Print(); |
| 8447 } | 8522 } |
| 8448 #endif | 8523 #endif |
| 8449 } | 8524 } |
| 8450 return value; | 8525 return value; |
| 8451 } | 8526 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 8475 | 8550 |
| 8476 // If the value object is not a heap number, switch to fast elements and try | 8551 // If the value object is not a heap number, switch to fast elements and try |
| 8477 // again. | 8552 // again. |
| 8478 bool value_is_smi = value->IsSmi(); | 8553 bool value_is_smi = value->IsSmi(); |
| 8479 if (!value->IsNumber()) { | 8554 if (!value->IsNumber()) { |
| 8480 Object* obj; | 8555 Object* obj; |
| 8481 uint32_t length = elms_length; | 8556 uint32_t length = elms_length; |
| 8482 if (IsJSArray()) { | 8557 if (IsJSArray()) { |
| 8483 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 8558 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 8484 } | 8559 } |
| 8485 MaybeObject* maybe_obj = | 8560 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
| 8486 SetFastElementsCapacityAndLength(elms_length, length); | 8561 elms_length, |
| 8562 length, | |
| 8563 kDontAllowSmiOnlyElements); | |
| 8487 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8564 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8488 return SetFastElement(index, value, strict_mode, check_prototype); | 8565 return SetFastElement(index, |
|
Jakob Kummerow
2011/09/16 16:30:34
Why the line breaks?
| |
| 8566 value, | |
| 8567 strict_mode, | |
| 8568 check_prototype); | |
| 8489 } | 8569 } |
| 8490 | 8570 |
| 8491 double double_value = value_is_smi | 8571 double double_value = value_is_smi |
| 8492 ? static_cast<double>(Smi::cast(value)->value()) | 8572 ? static_cast<double>(Smi::cast(value)->value()) |
| 8493 : HeapNumber::cast(value)->value(); | 8573 : HeapNumber::cast(value)->value(); |
| 8494 | 8574 |
| 8495 // Check whether there is extra space in the fixed array. | 8575 // Check whether there is extra space in the fixed array. |
| 8496 if (index < elms_length) { | 8576 if (index < elms_length) { |
| 8497 elms->set(index, double_value); | 8577 elms->set(index, double_value); |
| 8498 if (IsJSArray()) { | 8578 if (IsJSArray()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8575 check_prototype); | 8655 check_prototype); |
| 8576 } | 8656 } |
| 8577 | 8657 |
| 8578 | 8658 |
| 8579 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 8659 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 8580 Object* value, | 8660 Object* value, |
| 8581 StrictModeFlag strict_mode, | 8661 StrictModeFlag strict_mode, |
| 8582 bool check_prototype) { | 8662 bool check_prototype) { |
| 8583 Isolate* isolate = GetIsolate(); | 8663 Isolate* isolate = GetIsolate(); |
| 8584 switch (GetElementsKind()) { | 8664 switch (GetElementsKind()) { |
| 8665 case FAST_SMI_ONLY_ELEMENTS: | |
| 8585 case FAST_ELEMENTS: | 8666 case FAST_ELEMENTS: |
| 8586 return SetFastElement(index, value, strict_mode, check_prototype); | 8667 return SetFastElement(index, value, strict_mode, check_prototype); |
| 8587 case FAST_DOUBLE_ELEMENTS: | 8668 case FAST_DOUBLE_ELEMENTS: |
| 8588 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 8669 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
| 8589 case EXTERNAL_PIXEL_ELEMENTS: { | 8670 case EXTERNAL_PIXEL_ELEMENTS: { |
| 8590 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8671 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 8591 return pixels->SetValue(index, value); | 8672 return pixels->SetValue(index, value); |
| 8592 } | 8673 } |
| 8593 case EXTERNAL_BYTE_ELEMENTS: { | 8674 case EXTERNAL_BYTE_ELEMENTS: { |
| 8594 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 8675 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8737 backing_store_base = | 8818 backing_store_base = |
| 8738 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 8819 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 8739 backing_store = FixedArray::cast(backing_store_base); | 8820 backing_store = FixedArray::cast(backing_store_base); |
| 8740 if (backing_store->IsDictionary()) { | 8821 if (backing_store->IsDictionary()) { |
| 8741 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 8822 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 8742 *capacity = dictionary->Capacity(); | 8823 *capacity = dictionary->Capacity(); |
| 8743 *used = dictionary->NumberOfElements(); | 8824 *used = dictionary->NumberOfElements(); |
| 8744 break; | 8825 break; |
| 8745 } | 8826 } |
| 8746 // Fall through. | 8827 // Fall through. |
| 8828 case FAST_SMI_ONLY_ELEMENTS: | |
| 8747 case FAST_ELEMENTS: | 8829 case FAST_ELEMENTS: |
| 8748 backing_store = FixedArray::cast(backing_store_base); | 8830 backing_store = FixedArray::cast(backing_store_base); |
| 8749 *capacity = backing_store->length(); | 8831 *capacity = backing_store->length(); |
| 8750 for (int i = 0; i < *capacity; ++i) { | 8832 for (int i = 0; i < *capacity; ++i) { |
| 8751 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 8833 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
| 8752 } | 8834 } |
| 8753 break; | 8835 break; |
| 8754 case DICTIONARY_ELEMENTS: { | 8836 case DICTIONARY_ELEMENTS: { |
| 8755 NumberDictionary* dictionary = | 8837 NumberDictionary* dictionary = |
| 8756 NumberDictionary::cast(FixedArray::cast(elements())); | 8838 NumberDictionary::cast(FixedArray::cast(elements())); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9012 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 9094 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 9013 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 9095 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9014 return false; | 9096 return false; |
| 9015 } | 9097 } |
| 9016 } | 9098 } |
| 9017 | 9099 |
| 9018 // Handle [] on String objects. | 9100 // Handle [] on String objects. |
| 9019 if (this->IsStringObjectWithCharacterAt(index)) return true; | 9101 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 9020 | 9102 |
| 9021 switch (GetElementsKind()) { | 9103 switch (GetElementsKind()) { |
| 9104 case FAST_SMI_ONLY_ELEMENTS: | |
| 9022 case FAST_ELEMENTS: { | 9105 case FAST_ELEMENTS: { |
| 9023 uint32_t length = IsJSArray() ? | 9106 uint32_t length = IsJSArray() ? |
| 9024 static_cast<uint32_t>( | 9107 static_cast<uint32_t>( |
| 9025 Smi::cast(JSArray::cast(this)->length())->value()) : | 9108 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 9026 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 9109 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 9027 return (index < length) && | 9110 return (index < length) && |
| 9028 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 9111 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 9029 } | 9112 } |
| 9030 case FAST_DOUBLE_ELEMENTS: { | 9113 case FAST_DOUBLE_ELEMENTS: { |
| 9031 uint32_t length = IsJSArray() ? | 9114 uint32_t length = IsJSArray() ? |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9251 } | 9334 } |
| 9252 // Compute the number of enumerable elements. | 9335 // Compute the number of enumerable elements. |
| 9253 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 9336 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
| 9254 } | 9337 } |
| 9255 | 9338 |
| 9256 | 9339 |
| 9257 int JSObject::GetLocalElementKeys(FixedArray* storage, | 9340 int JSObject::GetLocalElementKeys(FixedArray* storage, |
| 9258 PropertyAttributes filter) { | 9341 PropertyAttributes filter) { |
| 9259 int counter = 0; | 9342 int counter = 0; |
| 9260 switch (GetElementsKind()) { | 9343 switch (GetElementsKind()) { |
| 9344 case FAST_SMI_ONLY_ELEMENTS: | |
| 9261 case FAST_ELEMENTS: { | 9345 case FAST_ELEMENTS: { |
| 9262 int length = IsJSArray() ? | 9346 int length = IsJSArray() ? |
| 9263 Smi::cast(JSArray::cast(this)->length())->value() : | 9347 Smi::cast(JSArray::cast(this)->length())->value() : |
| 9264 FixedArray::cast(elements())->length(); | 9348 FixedArray::cast(elements())->length(); |
| 9265 for (int i = 0; i < length; i++) { | 9349 for (int i = 0; i < length; i++) { |
| 9266 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 9350 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 9267 if (storage != NULL) { | 9351 if (storage != NULL) { |
| 9268 storage->set(counter, Smi::FromInt(i)); | 9352 storage->set(counter, Smi::FromInt(i)); |
| 9269 } | 9353 } |
| 9270 counter++; | 9354 counter++; |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10153 dict->CopyValuesTo(fast_elements); | 10237 dict->CopyValuesTo(fast_elements); |
| 10154 | 10238 |
| 10155 set_map(new_map); | 10239 set_map(new_map); |
| 10156 set_elements(fast_elements); | 10240 set_elements(fast_elements); |
| 10157 } else if (!HasFastDoubleElements()) { | 10241 } else if (!HasFastDoubleElements()) { |
| 10158 Object* obj; | 10242 Object* obj; |
| 10159 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 10243 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 10160 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10244 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 10161 } | 10245 } |
| 10162 } | 10246 } |
| 10163 ASSERT(HasFastElements() || HasFastDoubleElements()); | 10247 ASSERT(HasFastElements() || |
| 10248 HasFastSmiOnlyElements() || | |
| 10249 HasFastDoubleElements()); | |
| 10164 | 10250 |
| 10165 // Collect holes at the end, undefined before that and the rest at the | 10251 // Collect holes at the end, undefined before that and the rest at the |
| 10166 // start, and return the number of non-hole, non-undefined values. | 10252 // start, and return the number of non-hole, non-undefined values. |
| 10167 | 10253 |
| 10168 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 10254 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
| 10169 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 10255 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 10170 if (limit > elements_length) { | 10256 if (limit > elements_length) { |
| 10171 limit = elements_length ; | 10257 limit = elements_length ; |
| 10172 } | 10258 } |
| 10173 if (limit == 0) { | 10259 if (limit == 0) { |
| (...skipping 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11588 if (break_point_objects()->IsUndefined()) return 0; | 11674 if (break_point_objects()->IsUndefined()) return 0; |
| 11589 // Single break point. | 11675 // Single break point. |
| 11590 if (!break_point_objects()->IsFixedArray()) return 1; | 11676 if (!break_point_objects()->IsFixedArray()) return 1; |
| 11591 // Multiple break points. | 11677 // Multiple break points. |
| 11592 return FixedArray::cast(break_point_objects())->length(); | 11678 return FixedArray::cast(break_point_objects())->length(); |
| 11593 } | 11679 } |
| 11594 #endif | 11680 #endif |
| 11595 | 11681 |
| 11596 | 11682 |
| 11597 } } // namespace v8::internal | 11683 } } // namespace v8::internal |
| OLD | NEW |