OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 3182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3193 Object* value = other->get(y); | 3193 Object* value = other->get(y); |
3194 if (!value->IsTheHole() && !HasKey(this, value)) extra++; | 3194 if (!value->IsTheHole() && !HasKey(this, value)) extra++; |
3195 } | 3195 } |
3196 | 3196 |
3197 if (extra == 0) return this; | 3197 if (extra == 0) return this; |
3198 | 3198 |
3199 // Allocate the result | 3199 // Allocate the result |
3200 Object* obj = Heap::AllocateFixedArray(len0 + extra); | 3200 Object* obj = Heap::AllocateFixedArray(len0 + extra); |
3201 if (obj->IsFailure()) return obj; | 3201 if (obj->IsFailure()) return obj; |
3202 // Fill in the content | 3202 // Fill in the content |
| 3203 AssertNoAllocation no_gc; |
3203 FixedArray* result = FixedArray::cast(obj); | 3204 FixedArray* result = FixedArray::cast(obj); |
3204 WriteBarrierMode mode = result->GetWriteBarrierMode(); | 3205 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
3205 for (int i = 0; i < len0; i++) { | 3206 for (int i = 0; i < len0; i++) { |
3206 result->set(i, get(i), mode); | 3207 result->set(i, get(i), mode); |
3207 } | 3208 } |
3208 // Fill in the extra keys. | 3209 // Fill in the extra keys. |
3209 int index = 0; | 3210 int index = 0; |
3210 for (int y = 0; y < len1; y++) { | 3211 for (int y = 0; y < len1; y++) { |
3211 Object* value = other->get(y); | 3212 Object* value = other->get(y); |
3212 if (!value->IsTheHole() && !HasKey(this, value)) { | 3213 if (!value->IsTheHole() && !HasKey(this, value)) { |
3213 result->set(len0 + index, other->get(y), mode); | 3214 result->set(len0 + index, other->get(y), mode); |
3214 index++; | 3215 index++; |
3215 } | 3216 } |
3216 } | 3217 } |
3217 ASSERT(extra == index); | 3218 ASSERT(extra == index); |
3218 return result; | 3219 return result; |
3219 } | 3220 } |
3220 | 3221 |
3221 | 3222 |
3222 Object* FixedArray::CopySize(int new_length) { | 3223 Object* FixedArray::CopySize(int new_length) { |
3223 if (new_length == 0) return Heap::empty_fixed_array(); | 3224 if (new_length == 0) return Heap::empty_fixed_array(); |
3224 Object* obj = Heap::AllocateFixedArray(new_length); | 3225 Object* obj = Heap::AllocateFixedArray(new_length); |
3225 if (obj->IsFailure()) return obj; | 3226 if (obj->IsFailure()) return obj; |
3226 FixedArray* result = FixedArray::cast(obj); | 3227 FixedArray* result = FixedArray::cast(obj); |
3227 // Copy the content | 3228 // Copy the content |
| 3229 AssertNoAllocation no_gc; |
3228 int len = length(); | 3230 int len = length(); |
3229 if (new_length < len) len = new_length; | 3231 if (new_length < len) len = new_length; |
3230 result->set_map(map()); | 3232 result->set_map(map()); |
3231 WriteBarrierMode mode = result->GetWriteBarrierMode(); | 3233 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
3232 for (int i = 0; i < len; i++) { | 3234 for (int i = 0; i < len; i++) { |
3233 result->set(i, get(i), mode); | 3235 result->set(i, get(i), mode); |
3234 } | 3236 } |
3235 return result; | 3237 return result; |
3236 } | 3238 } |
3237 | 3239 |
3238 | 3240 |
3239 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { | 3241 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { |
3240 WriteBarrierMode mode = dest->GetWriteBarrierMode(); | 3242 AssertNoAllocation no_gc; |
| 3243 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); |
3241 for (int index = 0; index < len; index++) { | 3244 for (int index = 0; index < len; index++) { |
3242 dest->set(dest_pos+index, get(pos+index), mode); | 3245 dest->set(dest_pos+index, get(pos+index), mode); |
3243 } | 3246 } |
3244 } | 3247 } |
3245 | 3248 |
3246 | 3249 |
3247 #ifdef DEBUG | 3250 #ifdef DEBUG |
3248 bool FixedArray::IsEqualTo(FixedArray* other) { | 3251 bool FixedArray::IsEqualTo(FixedArray* other) { |
3249 if (length() != other->length()) return false; | 3252 if (length() != other->length()) return false; |
3250 for (int i = 0 ; i < length(); ++i) { | 3253 for (int i = 0 ; i < length(); ++i) { |
(...skipping 13 matching lines...) Expand all Loading... |
3264 Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); | 3267 Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
3265 if (array->IsFailure()) return array; | 3268 if (array->IsFailure()) return array; |
3266 // Do not use DescriptorArray::cast on incomplete object. | 3269 // Do not use DescriptorArray::cast on incomplete object. |
3267 FixedArray* result = FixedArray::cast(array); | 3270 FixedArray* result = FixedArray::cast(array); |
3268 | 3271 |
3269 // Allocate the content array and set it in the descriptor array. | 3272 // Allocate the content array and set it in the descriptor array. |
3270 array = Heap::AllocateFixedArray(number_of_descriptors << 1); | 3273 array = Heap::AllocateFixedArray(number_of_descriptors << 1); |
3271 if (array->IsFailure()) return array; | 3274 if (array->IsFailure()) return array; |
3272 result->set(kContentArrayIndex, array); | 3275 result->set(kContentArrayIndex, array); |
3273 result->set(kEnumerationIndexIndex, | 3276 result->set(kEnumerationIndexIndex, |
3274 Smi::FromInt(PropertyDetails::kInitialIndex), | 3277 Smi::FromInt(PropertyDetails::kInitialIndex)); |
3275 SKIP_WRITE_BARRIER); | |
3276 return result; | 3278 return result; |
3277 } | 3279 } |
3278 | 3280 |
3279 | 3281 |
3280 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 3282 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
3281 FixedArray* new_cache) { | 3283 FixedArray* new_cache) { |
3282 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 3284 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
3283 if (HasEnumCache()) { | 3285 if (HasEnumCache()) { |
3284 FixedArray::cast(get(kEnumerationIndexIndex))-> | 3286 FixedArray::cast(get(kEnumerationIndexIndex))-> |
3285 set(kEnumCacheBridgeCacheIndex, new_cache); | 3287 set(kEnumCacheBridgeCacheIndex, new_cache); |
(...skipping 1407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4693 // check if the target is live. If not, null the descriptor. | 4695 // check if the target is live. If not, null the descriptor. |
4694 // Also drop the back pointer for that map transition, so that this | 4696 // Also drop the back pointer for that map transition, so that this |
4695 // map is not reached again by following a back pointer from a | 4697 // map is not reached again by following a back pointer from a |
4696 // non-live object. | 4698 // non-live object. |
4697 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 4699 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
4698 if (details.type() == MAP_TRANSITION) { | 4700 if (details.type() == MAP_TRANSITION) { |
4699 Map* target = reinterpret_cast<Map*>(contents->get(i)); | 4701 Map* target = reinterpret_cast<Map*>(contents->get(i)); |
4700 ASSERT(target->IsHeapObject()); | 4702 ASSERT(target->IsHeapObject()); |
4701 if (!target->IsMarked()) { | 4703 if (!target->IsMarked()) { |
4702 ASSERT(target->IsMap()); | 4704 ASSERT(target->IsMap()); |
4703 contents->set(i + 1, NullDescriptorDetails, SKIP_WRITE_BARRIER); | 4705 contents->set(i + 1, NullDescriptorDetails); |
4704 contents->set(i, Heap::null_value(), SKIP_WRITE_BARRIER); | 4706 contents->set_null(i); |
4705 ASSERT(target->prototype() == this || | 4707 ASSERT(target->prototype() == this || |
4706 target->prototype() == real_prototype); | 4708 target->prototype() == real_prototype); |
4707 // Getter prototype() is read-only, set_prototype() has side effects. | 4709 // Getter prototype() is read-only, set_prototype() has side effects. |
4708 *RawField(target, Map::kPrototypeOffset) = real_prototype; | 4710 *RawField(target, Map::kPrototypeOffset) = real_prototype; |
4709 } | 4711 } |
4710 } | 4712 } |
4711 } | 4713 } |
4712 } | 4714 } |
4713 | 4715 |
4714 | 4716 |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5154 | 5156 |
5155 | 5157 |
5156 void JSObject::SetFastElements(FixedArray* elems) { | 5158 void JSObject::SetFastElements(FixedArray* elems) { |
5157 // We should never end in here with a pixel or external array. | 5159 // We should never end in here with a pixel or external array. |
5158 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); | 5160 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
5159 #ifdef DEBUG | 5161 #ifdef DEBUG |
5160 // Check the provided array is filled with the_hole. | 5162 // Check the provided array is filled with the_hole. |
5161 uint32_t len = static_cast<uint32_t>(elems->length()); | 5163 uint32_t len = static_cast<uint32_t>(elems->length()); |
5162 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); | 5164 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); |
5163 #endif | 5165 #endif |
5164 WriteBarrierMode mode = elems->GetWriteBarrierMode(); | 5166 AssertNoAllocation no_gc; |
| 5167 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); |
5165 switch (GetElementsKind()) { | 5168 switch (GetElementsKind()) { |
5166 case FAST_ELEMENTS: { | 5169 case FAST_ELEMENTS: { |
5167 FixedArray* old_elements = FixedArray::cast(elements()); | 5170 FixedArray* old_elements = FixedArray::cast(elements()); |
5168 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 5171 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
5169 // Fill out the new array with this content and array holes. | 5172 // Fill out the new array with this content and array holes. |
5170 for (uint32_t i = 0; i < old_length; i++) { | 5173 for (uint32_t i = 0; i < old_length; i++) { |
5171 elems->set(i, old_elements->get(i), mode); | 5174 elems->set(i, old_elements->get(i), mode); |
5172 } | 5175 } |
5173 break; | 5176 break; |
5174 } | 5177 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5221 default: | 5224 default: |
5222 UNREACHABLE(); | 5225 UNREACHABLE(); |
5223 break; | 5226 break; |
5224 } | 5227 } |
5225 return this; | 5228 return this; |
5226 } | 5229 } |
5227 | 5230 |
5228 | 5231 |
5229 Object* JSArray::Initialize(int capacity) { | 5232 Object* JSArray::Initialize(int capacity) { |
5230 ASSERT(capacity >= 0); | 5233 ASSERT(capacity >= 0); |
5231 set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER); | 5234 set_length(Smi::FromInt(0)); |
5232 FixedArray* new_elements; | 5235 FixedArray* new_elements; |
5233 if (capacity == 0) { | 5236 if (capacity == 0) { |
5234 new_elements = Heap::empty_fixed_array(); | 5237 new_elements = Heap::empty_fixed_array(); |
5235 } else { | 5238 } else { |
5236 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); | 5239 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
5237 if (obj->IsFailure()) return obj; | 5240 if (obj->IsFailure()) return obj; |
5238 new_elements = FixedArray::cast(obj); | 5241 new_elements = FixedArray::cast(obj); |
5239 } | 5242 } |
5240 set_elements(new_elements); | 5243 set_elements(new_elements); |
5241 return this; | 5244 return this; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5281 int old_capacity = FixedArray::cast(elements())->length(); | 5284 int old_capacity = FixedArray::cast(elements())->length(); |
5282 if (value <= old_capacity) { | 5285 if (value <= old_capacity) { |
5283 if (IsJSArray()) { | 5286 if (IsJSArray()) { |
5284 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 5287 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
5285 // NOTE: We may be able to optimize this by removing the | 5288 // NOTE: We may be able to optimize this by removing the |
5286 // last part of the elements backing storage array and | 5289 // last part of the elements backing storage array and |
5287 // setting the capacity to the new size. | 5290 // setting the capacity to the new size. |
5288 for (int i = value; i < old_length; i++) { | 5291 for (int i = value; i < old_length; i++) { |
5289 FixedArray::cast(elements())->set_the_hole(i); | 5292 FixedArray::cast(elements())->set_the_hole(i); |
5290 } | 5293 } |
5291 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); | 5294 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
5292 } | 5295 } |
5293 return this; | 5296 return this; |
5294 } | 5297 } |
5295 int min = NewElementsCapacity(old_capacity); | 5298 int min = NewElementsCapacity(old_capacity); |
5296 int new_capacity = value > min ? value : min; | 5299 int new_capacity = value > min ? value : min; |
5297 if (new_capacity <= kMaxFastElementsLength || | 5300 if (new_capacity <= kMaxFastElementsLength || |
5298 !ShouldConvertToSlowElements(new_capacity)) { | 5301 !ShouldConvertToSlowElements(new_capacity)) { |
5299 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); | 5302 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); |
5300 if (obj->IsFailure()) return obj; | 5303 if (obj->IsFailure()) return obj; |
5301 if (IsJSArray()) JSArray::cast(this)->set_length(smi_length, | 5304 if (IsJSArray()) { |
5302 SKIP_WRITE_BARRIER); | 5305 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 5306 } |
5303 SetFastElements(FixedArray::cast(obj)); | 5307 SetFastElements(FixedArray::cast(obj)); |
5304 return this; | 5308 return this; |
5305 } | 5309 } |
5306 break; | 5310 break; |
5307 } | 5311 } |
5308 case DICTIONARY_ELEMENTS: { | 5312 case DICTIONARY_ELEMENTS: { |
5309 if (IsJSArray()) { | 5313 if (IsJSArray()) { |
5310 if (value == 0) { | 5314 if (value == 0) { |
5311 // If the length of a slow array is reset to zero, we clear | 5315 // If the length of a slow array is reset to zero, we clear |
5312 // the array and flush backing storage. This has the added | 5316 // the array and flush backing storage. This has the added |
5313 // benefit that the array returns to fast mode. | 5317 // benefit that the array returns to fast mode. |
5314 initialize_elements(); | 5318 initialize_elements(); |
5315 } else { | 5319 } else { |
5316 // Remove deleted elements. | 5320 // Remove deleted elements. |
5317 uint32_t old_length = | 5321 uint32_t old_length = |
5318 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | 5322 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); |
5319 element_dictionary()->RemoveNumberEntries(value, old_length); | 5323 element_dictionary()->RemoveNumberEntries(value, old_length); |
5320 } | 5324 } |
5321 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); | 5325 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
5322 } | 5326 } |
5323 return this; | 5327 return this; |
5324 } | 5328 } |
5325 default: | 5329 default: |
5326 UNREACHABLE(); | 5330 UNREACHABLE(); |
5327 break; | 5331 break; |
5328 } | 5332 } |
5329 } | 5333 } |
5330 | 5334 |
5331 // General slow case. | 5335 // General slow case. |
5332 if (len->IsNumber()) { | 5336 if (len->IsNumber()) { |
5333 uint32_t length; | 5337 uint32_t length; |
5334 if (Array::IndexFromObject(len, &length)) { | 5338 if (Array::IndexFromObject(len, &length)) { |
5335 return SetSlowElements(len); | 5339 return SetSlowElements(len); |
5336 } else { | 5340 } else { |
5337 return ArrayLengthRangeError(); | 5341 return ArrayLengthRangeError(); |
5338 } | 5342 } |
5339 } | 5343 } |
5340 | 5344 |
5341 // len is not a number so make the array size one and | 5345 // len is not a number so make the array size one and |
5342 // set only element to len. | 5346 // set only element to len. |
5343 Object* obj = Heap::AllocateFixedArray(1); | 5347 Object* obj = Heap::AllocateFixedArray(1); |
5344 if (obj->IsFailure()) return obj; | 5348 if (obj->IsFailure()) return obj; |
5345 FixedArray::cast(obj)->set(0, len); | 5349 FixedArray::cast(obj)->set(0, len); |
5346 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1), | 5350 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
5347 SKIP_WRITE_BARRIER); | |
5348 set_elements(FixedArray::cast(obj)); | 5351 set_elements(FixedArray::cast(obj)); |
5349 return this; | 5352 return this; |
5350 } | 5353 } |
5351 | 5354 |
5352 | 5355 |
5353 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { | 5356 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
5354 switch (GetElementsKind()) { | 5357 switch (GetElementsKind()) { |
5355 case FAST_ELEMENTS: { | 5358 case FAST_ELEMENTS: { |
5356 uint32_t length = IsJSArray() ? | 5359 uint32_t length = IsJSArray() ? |
5357 static_cast<uint32_t> | 5360 static_cast<uint32_t> |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5607 | 5610 |
5608 // Check whether there is extra space in fixed array.. | 5611 // Check whether there is extra space in fixed array.. |
5609 if (index < elms_length) { | 5612 if (index < elms_length) { |
5610 elms->set(index, value); | 5613 elms->set(index, value); |
5611 if (IsJSArray()) { | 5614 if (IsJSArray()) { |
5612 // Update the length of the array if needed. | 5615 // Update the length of the array if needed. |
5613 uint32_t array_length = 0; | 5616 uint32_t array_length = 0; |
5614 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), | 5617 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), |
5615 &array_length)); | 5618 &array_length)); |
5616 if (index >= array_length) { | 5619 if (index >= array_length) { |
5617 JSArray::cast(this)->set_length(Smi::FromInt(index + 1), | 5620 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
5618 SKIP_WRITE_BARRIER); | |
5619 } | 5621 } |
5620 } | 5622 } |
5621 return value; | 5623 return value; |
5622 } | 5624 } |
5623 | 5625 |
5624 // Allow gap in fast case. | 5626 // Allow gap in fast case. |
5625 if ((index - elms_length) < kMaxGap) { | 5627 if ((index - elms_length) < kMaxGap) { |
5626 // Try allocating extra space. | 5628 // Try allocating extra space. |
5627 int new_capacity = NewElementsCapacity(index+1); | 5629 int new_capacity = NewElementsCapacity(index+1); |
5628 if (new_capacity <= kMaxFastElementsLength || | 5630 if (new_capacity <= kMaxFastElementsLength || |
5629 !ShouldConvertToSlowElements(new_capacity)) { | 5631 !ShouldConvertToSlowElements(new_capacity)) { |
5630 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 5632 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
5631 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); | 5633 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); |
5632 if (obj->IsFailure()) return obj; | 5634 if (obj->IsFailure()) return obj; |
5633 SetFastElements(FixedArray::cast(obj)); | 5635 SetFastElements(FixedArray::cast(obj)); |
5634 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1), | 5636 if (IsJSArray()) { |
5635 SKIP_WRITE_BARRIER); | 5637 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 5638 } |
5636 FixedArray::cast(elements())->set(index, value); | 5639 FixedArray::cast(elements())->set(index, value); |
5637 return value; | 5640 return value; |
5638 } | 5641 } |
5639 } | 5642 } |
5640 | 5643 |
5641 // Otherwise default to slow case. | 5644 // Otherwise default to slow case. |
5642 Object* obj = NormalizeElements(); | 5645 Object* obj = NormalizeElements(); |
5643 if (obj->IsFailure()) return obj; | 5646 if (obj->IsFailure()) return obj; |
5644 ASSERT(HasDictionaryElements()); | 5647 ASSERT(HasDictionaryElements()); |
5645 return SetElement(index, value); | 5648 return SetElement(index, value); |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6122 } | 6125 } |
6123 } | 6126 } |
6124 } | 6127 } |
6125 #endif | 6128 #endif |
6126 | 6129 |
6127 | 6130 |
6128 template<typename Shape, typename Key> | 6131 template<typename Shape, typename Key> |
6129 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { | 6132 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { |
6130 int pos = 0; | 6133 int pos = 0; |
6131 int capacity = HashTable<Shape, Key>::Capacity(); | 6134 int capacity = HashTable<Shape, Key>::Capacity(); |
6132 WriteBarrierMode mode = elements->GetWriteBarrierMode(); | 6135 AssertNoAllocation no_gc; |
| 6136 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc); |
6133 for (int i = 0; i < capacity; i++) { | 6137 for (int i = 0; i < capacity; i++) { |
6134 Object* k = Dictionary<Shape, Key>::KeyAt(i); | 6138 Object* k = Dictionary<Shape, Key>::KeyAt(i); |
6135 if (Dictionary<Shape, Key>::IsKey(k)) { | 6139 if (Dictionary<Shape, Key>::IsKey(k)) { |
6136 elements->set(pos++, ValueAt(i), mode); | 6140 elements->set(pos++, ValueAt(i), mode); |
6137 } | 6141 } |
6138 } | 6142 } |
6139 ASSERT(pos == elements->length()); | 6143 ASSERT(pos == elements->length()); |
6140 } | 6144 } |
6141 | 6145 |
6142 | 6146 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6493 PropertyAttributes filter) { | 6497 PropertyAttributes filter) { |
6494 int counter = 0; | 6498 int counter = 0; |
6495 switch (GetElementsKind()) { | 6499 switch (GetElementsKind()) { |
6496 case FAST_ELEMENTS: { | 6500 case FAST_ELEMENTS: { |
6497 int length = IsJSArray() ? | 6501 int length = IsJSArray() ? |
6498 Smi::cast(JSArray::cast(this)->length())->value() : | 6502 Smi::cast(JSArray::cast(this)->length())->value() : |
6499 FixedArray::cast(elements())->length(); | 6503 FixedArray::cast(elements())->length(); |
6500 for (int i = 0; i < length; i++) { | 6504 for (int i = 0; i < length; i++) { |
6501 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 6505 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
6502 if (storage != NULL) { | 6506 if (storage != NULL) { |
6503 storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 6507 storage->set(counter, Smi::FromInt(i)); |
6504 } | 6508 } |
6505 counter++; | 6509 counter++; |
6506 } | 6510 } |
6507 } | 6511 } |
6508 ASSERT(!storage || storage->length() >= counter); | 6512 ASSERT(!storage || storage->length() >= counter); |
6509 break; | 6513 break; |
6510 } | 6514 } |
6511 case PIXEL_ELEMENTS: { | 6515 case PIXEL_ELEMENTS: { |
6512 int length = PixelArray::cast(elements())->length(); | 6516 int length = PixelArray::cast(elements())->length(); |
6513 while (counter < length) { | 6517 while (counter < length) { |
6514 if (storage != NULL) { | 6518 if (storage != NULL) { |
6515 storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); | 6519 storage->set(counter, Smi::FromInt(counter)); |
6516 } | 6520 } |
6517 counter++; | 6521 counter++; |
6518 } | 6522 } |
6519 ASSERT(!storage || storage->length() >= counter); | 6523 ASSERT(!storage || storage->length() >= counter); |
6520 break; | 6524 break; |
6521 } | 6525 } |
6522 case EXTERNAL_BYTE_ELEMENTS: | 6526 case EXTERNAL_BYTE_ELEMENTS: |
6523 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 6527 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
6524 case EXTERNAL_SHORT_ELEMENTS: | 6528 case EXTERNAL_SHORT_ELEMENTS: |
6525 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 6529 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
6526 case EXTERNAL_INT_ELEMENTS: | 6530 case EXTERNAL_INT_ELEMENTS: |
6527 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 6531 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
6528 case EXTERNAL_FLOAT_ELEMENTS: { | 6532 case EXTERNAL_FLOAT_ELEMENTS: { |
6529 int length = ExternalArray::cast(elements())->length(); | 6533 int length = ExternalArray::cast(elements())->length(); |
6530 while (counter < length) { | 6534 while (counter < length) { |
6531 if (storage != NULL) { | 6535 if (storage != NULL) { |
6532 storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); | 6536 storage->set(counter, Smi::FromInt(counter)); |
6533 } | 6537 } |
6534 counter++; | 6538 counter++; |
6535 } | 6539 } |
6536 ASSERT(!storage || storage->length() >= counter); | 6540 ASSERT(!storage || storage->length() >= counter); |
6537 break; | 6541 break; |
6538 } | 6542 } |
6539 case DICTIONARY_ELEMENTS: { | 6543 case DICTIONARY_ELEMENTS: { |
6540 if (storage != NULL) { | 6544 if (storage != NULL) { |
6541 element_dictionary()->CopyKeysTo(storage, filter); | 6545 element_dictionary()->CopyKeysTo(storage, filter); |
6542 } | 6546 } |
6543 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); | 6547 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); |
6544 break; | 6548 break; |
6545 } | 6549 } |
6546 default: | 6550 default: |
6547 UNREACHABLE(); | 6551 UNREACHABLE(); |
6548 break; | 6552 break; |
6549 } | 6553 } |
6550 | 6554 |
6551 if (this->IsJSValue()) { | 6555 if (this->IsJSValue()) { |
6552 Object* val = JSValue::cast(this)->value(); | 6556 Object* val = JSValue::cast(this)->value(); |
6553 if (val->IsString()) { | 6557 if (val->IsString()) { |
6554 String* str = String::cast(val); | 6558 String* str = String::cast(val); |
6555 if (storage) { | 6559 if (storage) { |
6556 for (int i = 0; i < str->length(); i++) { | 6560 for (int i = 0; i < str->length(); i++) { |
6557 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 6561 storage->set(counter + i, Smi::FromInt(i)); |
6558 } | 6562 } |
6559 } | 6563 } |
6560 counter += str->length(); | 6564 counter += str->length(); |
6561 } | 6565 } |
6562 } | 6566 } |
6563 ASSERT(!storage || storage->length() == counter); | 6567 ASSERT(!storage || storage->length() == counter); |
6564 return counter; | 6568 return counter; |
6565 } | 6569 } |
6566 | 6570 |
6567 | 6571 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6879 int nof = NumberOfElements() + n; | 6883 int nof = NumberOfElements() + n; |
6880 int nod = NumberOfDeletedElements(); | 6884 int nod = NumberOfDeletedElements(); |
6881 // Return if: | 6885 // Return if: |
6882 // 50% is still free after adding n elements and | 6886 // 50% is still free after adding n elements and |
6883 // at most 50% of the free elements are deleted elements. | 6887 // at most 50% of the free elements are deleted elements. |
6884 if ((nof + (nof >> 1) <= capacity) && | 6888 if ((nof + (nof >> 1) <= capacity) && |
6885 (nod <= (capacity - nof) >> 1)) return this; | 6889 (nod <= (capacity - nof) >> 1)) return this; |
6886 | 6890 |
6887 Object* obj = Allocate(nof * 2); | 6891 Object* obj = Allocate(nof * 2); |
6888 if (obj->IsFailure()) return obj; | 6892 if (obj->IsFailure()) return obj; |
| 6893 |
| 6894 AssertNoAllocation no_gc; |
6889 HashTable* table = HashTable::cast(obj); | 6895 HashTable* table = HashTable::cast(obj); |
6890 WriteBarrierMode mode = table->GetWriteBarrierMode(); | 6896 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); |
6891 | 6897 |
6892 // Copy prefix to new array. | 6898 // Copy prefix to new array. |
6893 for (int i = kPrefixStartIndex; | 6899 for (int i = kPrefixStartIndex; |
6894 i < kPrefixStartIndex + Shape::kPrefixSize; | 6900 i < kPrefixStartIndex + Shape::kPrefixSize; |
6895 i++) { | 6901 i++) { |
6896 table->set(i, get(i), mode); | 6902 table->set(i, get(i), mode); |
6897 } | 6903 } |
6898 // Rehash the elements. | 6904 // Rehash the elements. |
6899 for (int i = 0; i < capacity; i++) { | 6905 for (int i = 0; i < capacity; i++) { |
6900 uint32_t from_index = EntryToIndex(i); | 6906 uint32_t from_index = EntryToIndex(i); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7127 // we start mutating the array. | 7133 // we start mutating the array. |
7128 Object* new_double = Heap::AllocateHeapNumber(0.0); | 7134 Object* new_double = Heap::AllocateHeapNumber(0.0); |
7129 if (new_double->IsFailure()) return new_double; | 7135 if (new_double->IsFailure()) return new_double; |
7130 result_double = HeapNumber::cast(new_double); | 7136 result_double = HeapNumber::cast(new_double); |
7131 } | 7137 } |
7132 | 7138 |
7133 AssertNoAllocation no_alloc; | 7139 AssertNoAllocation no_alloc; |
7134 | 7140 |
7135 // Split elements into defined, undefined and the_hole, in that order. | 7141 // Split elements into defined, undefined and the_hole, in that order. |
7136 // Only count locations for undefined and the hole, and fill them afterwards. | 7142 // Only count locations for undefined and the hole, and fill them afterwards. |
7137 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(); | 7143 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc); |
7138 unsigned int undefs = limit; | 7144 unsigned int undefs = limit; |
7139 unsigned int holes = limit; | 7145 unsigned int holes = limit; |
7140 // Assume most arrays contain no holes and undefined values, so minimize the | 7146 // Assume most arrays contain no holes and undefined values, so minimize the |
7141 // number of stores of non-undefined, non-the-hole values. | 7147 // number of stores of non-undefined, non-the-hole values. |
7142 for (unsigned int i = 0; i < undefs; i++) { | 7148 for (unsigned int i = 0; i < undefs; i++) { |
7143 Object* current = elements->get(i); | 7149 Object* current = elements->get(i); |
7144 if (current->IsTheHole()) { | 7150 if (current->IsTheHole()) { |
7145 holes--; | 7151 holes--; |
7146 undefs--; | 7152 undefs--; |
7147 } else if (current->IsUndefined()) { | 7153 } else if (current->IsUndefined()) { |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7622 | 7628 |
7623 template<typename Shape, typename Key> | 7629 template<typename Shape, typename Key> |
7624 Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { | 7630 Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { |
7625 int length = HashTable<Shape, Key>::NumberOfElements(); | 7631 int length = HashTable<Shape, Key>::NumberOfElements(); |
7626 | 7632 |
7627 // Allocate and initialize iteration order array. | 7633 // Allocate and initialize iteration order array. |
7628 Object* obj = Heap::AllocateFixedArray(length); | 7634 Object* obj = Heap::AllocateFixedArray(length); |
7629 if (obj->IsFailure()) return obj; | 7635 if (obj->IsFailure()) return obj; |
7630 FixedArray* iteration_order = FixedArray::cast(obj); | 7636 FixedArray* iteration_order = FixedArray::cast(obj); |
7631 for (int i = 0; i < length; i++) { | 7637 for (int i = 0; i < length; i++) { |
7632 iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 7638 iteration_order->set(i, Smi::FromInt(i)); |
7633 } | 7639 } |
7634 | 7640 |
7635 // Allocate array with enumeration order. | 7641 // Allocate array with enumeration order. |
7636 obj = Heap::AllocateFixedArray(length); | 7642 obj = Heap::AllocateFixedArray(length); |
7637 if (obj->IsFailure()) return obj; | 7643 if (obj->IsFailure()) return obj; |
7638 FixedArray* enumeration_order = FixedArray::cast(obj); | 7644 FixedArray* enumeration_order = FixedArray::cast(obj); |
7639 | 7645 |
7640 // Fill the enumeration order array with property details. | 7646 // Fill the enumeration order array with property details. |
7641 int capacity = HashTable<Shape, Key>::Capacity(); | 7647 int capacity = HashTable<Shape, Key>::Capacity(); |
7642 int pos = 0; | 7648 int pos = 0; |
7643 for (int i = 0; i < capacity; i++) { | 7649 for (int i = 0; i < capacity; i++) { |
7644 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 7650 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
7645 enumeration_order->set(pos++, | 7651 enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index())); |
7646 Smi::FromInt(DetailsAt(i).index()), | |
7647 SKIP_WRITE_BARRIER); | |
7648 } | 7652 } |
7649 } | 7653 } |
7650 | 7654 |
7651 // Sort the arrays wrt. enumeration order. | 7655 // Sort the arrays wrt. enumeration order. |
7652 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); | 7656 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); |
7653 | 7657 |
7654 // Overwrite the enumeration_order with the enumeration indices. | 7658 // Overwrite the enumeration_order with the enumeration indices. |
7655 for (int i = 0; i < length; i++) { | 7659 for (int i = 0; i < length; i++) { |
7656 int index = Smi::cast(iteration_order->get(i))->value(); | 7660 int index = Smi::cast(iteration_order->get(i))->value(); |
7657 int enum_index = PropertyDetails::kInitialIndex + i; | 7661 int enum_index = PropertyDetails::kInitialIndex + i; |
7658 enumeration_order->set(index, | 7662 enumeration_order->set(index, Smi::FromInt(enum_index)); |
7659 Smi::FromInt(enum_index), | |
7660 SKIP_WRITE_BARRIER); | |
7661 } | 7663 } |
7662 | 7664 |
7663 // Update the dictionary with new indices. | 7665 // Update the dictionary with new indices. |
7664 capacity = HashTable<Shape, Key>::Capacity(); | 7666 capacity = HashTable<Shape, Key>::Capacity(); |
7665 pos = 0; | 7667 pos = 0; |
7666 for (int i = 0; i < capacity; i++) { | 7668 for (int i = 0; i < capacity; i++) { |
7667 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 7669 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
7668 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); | 7670 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); |
7669 PropertyDetails details = DetailsAt(i); | 7671 PropertyDetails details = DetailsAt(i); |
7670 PropertyDetails new_details = | 7672 PropertyDetails new_details = |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7798 // Check if this index is high enough that we should require slow | 7800 // Check if this index is high enough that we should require slow |
7799 // elements. | 7801 // elements. |
7800 if (key > kRequiresSlowElementsLimit) { | 7802 if (key > kRequiresSlowElementsLimit) { |
7801 set_requires_slow_elements(); | 7803 set_requires_slow_elements(); |
7802 return; | 7804 return; |
7803 } | 7805 } |
7804 // Update max key value. | 7806 // Update max key value. |
7805 Object* max_index_object = get(kMaxNumberKeyIndex); | 7807 Object* max_index_object = get(kMaxNumberKeyIndex); |
7806 if (!max_index_object->IsSmi() || max_number_key() < key) { | 7808 if (!max_index_object->IsSmi() || max_number_key() < key) { |
7807 FixedArray::set(kMaxNumberKeyIndex, | 7809 FixedArray::set(kMaxNumberKeyIndex, |
7808 Smi::FromInt(key << kRequiresSlowElementsTagSize), | 7810 Smi::FromInt(key << kRequiresSlowElementsTagSize)); |
7809 SKIP_WRITE_BARRIER); | |
7810 } | 7811 } |
7811 } | 7812 } |
7812 | 7813 |
7813 | 7814 |
7814 Object* NumberDictionary::AddNumberEntry(uint32_t key, | 7815 Object* NumberDictionary::AddNumberEntry(uint32_t key, |
7815 Object* value, | 7816 Object* value, |
7816 PropertyDetails details) { | 7817 PropertyDetails details) { |
7817 UpdateMaxNumberKey(key); | 7818 UpdateMaxNumberKey(key); |
7818 SLOW_ASSERT(FindEntry(key) == kNotFound); | 7819 SLOW_ASSERT(FindEntry(key) == kNotFound); |
7819 return Add(key, value, details); | 7820 return Add(key, value, details); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7890 FixedArray* sort_array) { | 7891 FixedArray* sort_array) { |
7891 ASSERT(storage->length() >= NumberOfEnumElements()); | 7892 ASSERT(storage->length() >= NumberOfEnumElements()); |
7892 int capacity = Capacity(); | 7893 int capacity = Capacity(); |
7893 int index = 0; | 7894 int index = 0; |
7894 for (int i = 0; i < capacity; i++) { | 7895 for (int i = 0; i < capacity; i++) { |
7895 Object* k = KeyAt(i); | 7896 Object* k = KeyAt(i); |
7896 if (IsKey(k)) { | 7897 if (IsKey(k)) { |
7897 PropertyDetails details = DetailsAt(i); | 7898 PropertyDetails details = DetailsAt(i); |
7898 if (details.IsDeleted() || details.IsDontEnum()) continue; | 7899 if (details.IsDeleted() || details.IsDontEnum()) continue; |
7899 storage->set(index, k); | 7900 storage->set(index, k); |
7900 sort_array->set(index, | 7901 sort_array->set(index, Smi::FromInt(details.index())); |
7901 Smi::FromInt(details.index()), | |
7902 SKIP_WRITE_BARRIER); | |
7903 index++; | 7902 index++; |
7904 } | 7903 } |
7905 } | 7904 } |
7906 storage->SortPairs(sort_array, sort_array->length()); | 7905 storage->SortPairs(sort_array, sort_array->length()); |
7907 ASSERT(storage->length() >= index); | 7906 ASSERT(storage->length() >= index); |
7908 } | 7907 } |
7909 | 7908 |
7910 | 7909 |
7911 template<typename Shape, typename Key> | 7910 template<typename Shape, typename Key> |
7912 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { | 7911 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8301 if (break_point_objects()->IsUndefined()) return 0; | 8300 if (break_point_objects()->IsUndefined()) return 0; |
8302 // Single beak point. | 8301 // Single beak point. |
8303 if (!break_point_objects()->IsFixedArray()) return 1; | 8302 if (!break_point_objects()->IsFixedArray()) return 1; |
8304 // Multiple break points. | 8303 // Multiple break points. |
8305 return FixedArray::cast(break_point_objects())->length(); | 8304 return FixedArray::cast(break_point_objects())->length(); |
8306 } | 8305 } |
8307 #endif | 8306 #endif |
8308 | 8307 |
8309 | 8308 |
8310 } } // namespace v8::internal | 8309 } } // namespace v8::internal |
OLD | NEW |