Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: src/objects.cc

Issue 7901016: Basic support for tracking smi-only arrays on ia32. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: deactivate by default Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698