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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 result = DeepCopyBoilerplate(jsObject); | 149 result = DeepCopyBoilerplate(jsObject); |
150 if (result->IsFailure()) return result; | 150 if (result->IsFailure()) return result; |
151 result = copy->SetProperty(keyString, result, NONE); | 151 result = copy->SetProperty(keyString, result, NONE); |
152 if (result->IsFailure()) return result; | 152 if (result->IsFailure()) return result; |
153 } | 153 } |
154 } | 154 } |
155 } | 155 } |
156 | 156 |
157 // Deep copy local elements. | 157 // Deep copy local elements. |
158 // Pixel elements cannot be created using an object literal. | 158 // Pixel elements cannot be created using an object literal. |
159 ASSERT(!copy->HasPixelElements()); | 159 ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements()); |
160 switch (copy->GetElementsKind()) { | 160 switch (copy->GetElementsKind()) { |
161 case JSObject::FAST_ELEMENTS: { | 161 case JSObject::FAST_ELEMENTS: { |
162 FixedArray* elements = FixedArray::cast(copy->elements()); | 162 FixedArray* elements = FixedArray::cast(copy->elements()); |
163 WriteBarrierMode mode = elements->GetWriteBarrierMode(); | 163 WriteBarrierMode mode = elements->GetWriteBarrierMode(); |
164 for (int i = 0; i < elements->length(); i++) { | 164 for (int i = 0; i < elements->length(); i++) { |
165 Object* value = elements->get(i); | 165 Object* value = elements->get(i); |
166 if (value->IsJSObject()) { | 166 if (value->IsJSObject()) { |
167 JSObject* jsObject = JSObject::cast(value); | 167 JSObject* jsObject = JSObject::cast(value); |
168 result = DeepCopyBoilerplate(jsObject); | 168 result = DeepCopyBoilerplate(jsObject); |
169 if (result->IsFailure()) return result; | 169 if (result->IsFailure()) return result; |
(...skipping 2403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2573 HandleVector(args, 2)); | 2573 HandleVector(args, 2)); |
2574 return Top::Throw(*error); | 2574 return Top::Throw(*error); |
2575 } | 2575 } |
2576 | 2576 |
2577 // Check if the given key is an array index. | 2577 // Check if the given key is an array index. |
2578 uint32_t index; | 2578 uint32_t index; |
2579 if (Array::IndexFromObject(*key, &index)) { | 2579 if (Array::IndexFromObject(*key, &index)) { |
2580 return GetElementOrCharAt(object, index); | 2580 return GetElementOrCharAt(object, index); |
2581 } | 2581 } |
2582 | 2582 |
| 2583 // If the target object is a JSObject and has an ExternalArray as |
| 2584 // its elements, we need to check for negative indices and report |
| 2585 // exceptions. Indices larger than the array's length will be caught |
| 2586 // elsewhere. |
| 2587 if (key->IsSmi() && Smi::cast(*key)->value() < 0) { |
| 2588 if (object->IsJSObject() && |
| 2589 JSObject::cast(*object)->HasExternalArrayElements()) { |
| 2590 uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); |
| 2591 return Top::Throw(*Factory::NewIndexError(index)); |
| 2592 } |
| 2593 } |
| 2594 |
2583 // Convert the key to a string - possibly by calling back into JavaScript. | 2595 // Convert the key to a string - possibly by calling back into JavaScript. |
2584 Handle<String> name; | 2596 Handle<String> name; |
2585 if (key->IsString()) { | 2597 if (key->IsString()) { |
2586 name = Handle<String>::cast(key); | 2598 name = Handle<String>::cast(key); |
2587 } else { | 2599 } else { |
2588 bool has_pending_exception = false; | 2600 bool has_pending_exception = false; |
2589 Handle<Object> converted = | 2601 Handle<Object> converted = |
2590 Execution::ToString(key, &has_pending_exception); | 2602 Execution::ToString(key, &has_pending_exception); |
2591 if (has_pending_exception) return Failure::Exception(); | 2603 if (has_pending_exception) return Failure::Exception(); |
2592 name = Handle<String>::cast(converted); | 2604 name = Handle<String>::cast(converted); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2707 // assignments. | 2719 // assignments. |
2708 if (js_object->IsStringObjectWithCharacterAt(index)) { | 2720 if (js_object->IsStringObjectWithCharacterAt(index)) { |
2709 return *value; | 2721 return *value; |
2710 } | 2722 } |
2711 | 2723 |
2712 Handle<Object> result = SetElement(js_object, index, value); | 2724 Handle<Object> result = SetElement(js_object, index, value); |
2713 if (result.is_null()) return Failure::Exception(); | 2725 if (result.is_null()) return Failure::Exception(); |
2714 return *value; | 2726 return *value; |
2715 } | 2727 } |
2716 | 2728 |
| 2729 // If the target object is a JSObject and has an ExternalArray as |
| 2730 // its elements, we need to check for negative indices and report |
| 2731 // exceptions. Indices larger than the array's length will be caught |
| 2732 // elsewhere. |
| 2733 if (key->IsSmi() && Smi::cast(*key)->value() < 0) { |
| 2734 if (object->IsJSObject() && |
| 2735 JSObject::cast(*object)->HasExternalArrayElements()) { |
| 2736 uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); |
| 2737 return Top::Throw(*Factory::NewIndexError(index)); |
| 2738 } |
| 2739 } |
| 2740 |
2717 if (key->IsString()) { | 2741 if (key->IsString()) { |
2718 Handle<Object> result; | 2742 Handle<Object> result; |
2719 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 2743 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
2720 ASSERT(attr == NONE); | 2744 ASSERT(attr == NONE); |
2721 result = SetElement(js_object, index, value); | 2745 result = SetElement(js_object, index, value); |
2722 } else { | 2746 } else { |
2723 Handle<String> key_string = Handle<String>::cast(key); | 2747 Handle<String> key_string = Handle<String>::cast(key); |
2724 key_string->TryFlattenIfNotFlat(); | 2748 key_string->TryFlattenIfNotFlat(); |
2725 result = SetProperty(js_object, key_string, value, attr); | 2749 result = SetProperty(js_object, key_string, value, attr); |
2726 } | 2750 } |
(...skipping 2539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5266 } | 5290 } |
5267 | 5291 |
5268 private: | 5292 private: |
5269 Handle<FixedArray> storage_; | 5293 Handle<FixedArray> storage_; |
5270 uint32_t index_limit_; | 5294 uint32_t index_limit_; |
5271 bool fast_elements_; | 5295 bool fast_elements_; |
5272 uint32_t index_offset_; | 5296 uint32_t index_offset_; |
5273 }; | 5297 }; |
5274 | 5298 |
5275 | 5299 |
| 5300 template<class ExternalArrayClass, class ElementType> |
| 5301 static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver, |
| 5302 bool elements_are_ints, |
| 5303 bool elements_are_guaranteed_smis, |
| 5304 uint32_t range, |
| 5305 ArrayConcatVisitor* visitor) { |
| 5306 Handle<ExternalArrayClass> array( |
| 5307 ExternalArrayClass::cast(receiver->elements())); |
| 5308 uint32_t len = Min(static_cast<uint32_t>(array->length()), range); |
| 5309 |
| 5310 if (visitor != NULL) { |
| 5311 if (elements_are_ints) { |
| 5312 if (elements_are_guaranteed_smis) { |
| 5313 for (uint32_t j = 0; j < len; j++) { |
| 5314 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j)))); |
| 5315 visitor->visit(j, e); |
| 5316 } |
| 5317 } else { |
| 5318 for (uint32_t j = 0; j < len; j++) { |
| 5319 int64_t val = static_cast<int64_t>(array->get(j)); |
| 5320 if (Smi::IsValid(static_cast<intptr_t>(val))) { |
| 5321 Handle<Smi> e(Smi::FromInt(static_cast<int>(val))); |
| 5322 visitor->visit(j, e); |
| 5323 } else { |
| 5324 Handle<Object> e( |
| 5325 Heap::AllocateHeapNumber(static_cast<ElementType>(val))); |
| 5326 visitor->visit(j, e); |
| 5327 } |
| 5328 } |
| 5329 } |
| 5330 } else { |
| 5331 for (uint32_t j = 0; j < len; j++) { |
| 5332 Handle<Object> e(Heap::AllocateHeapNumber(array->get(j))); |
| 5333 visitor->visit(j, e); |
| 5334 } |
| 5335 } |
| 5336 } |
| 5337 |
| 5338 return len; |
| 5339 } |
| 5340 |
5276 /** | 5341 /** |
5277 * A helper function that visits elements of a JSObject. Only elements | 5342 * A helper function that visits elements of a JSObject. Only elements |
5278 * whose index between 0 and range (exclusive) are visited. | 5343 * whose index between 0 and range (exclusive) are visited. |
5279 * | 5344 * |
5280 * If the third parameter, visitor, is not NULL, the visitor is called | 5345 * If the third parameter, visitor, is not NULL, the visitor is called |
5281 * with parameters, 'visitor_index_offset + element index' and the element. | 5346 * with parameters, 'visitor_index_offset + element index' and the element. |
5282 * | 5347 * |
5283 * It returns the number of visisted elements. | 5348 * It returns the number of visisted elements. |
5284 */ | 5349 */ |
5285 static uint32_t IterateElements(Handle<JSObject> receiver, | 5350 static uint32_t IterateElements(Handle<JSObject> receiver, |
(...skipping 29 matching lines...) Expand all Loading... |
5315 | 5380 |
5316 for (uint32_t j = 0; j < len; j++) { | 5381 for (uint32_t j = 0; j < len; j++) { |
5317 num_of_elements++; | 5382 num_of_elements++; |
5318 if (visitor != NULL) { | 5383 if (visitor != NULL) { |
5319 Handle<Smi> e(Smi::FromInt(pixels->get(j))); | 5384 Handle<Smi> e(Smi::FromInt(pixels->get(j))); |
5320 visitor->visit(j, e); | 5385 visitor->visit(j, e); |
5321 } | 5386 } |
5322 } | 5387 } |
5323 break; | 5388 break; |
5324 } | 5389 } |
| 5390 case JSObject::EXTERNAL_BYTE_ELEMENTS: { |
| 5391 num_of_elements = |
| 5392 IterateExternalArrayElements<ExternalByteArray, int8_t>( |
| 5393 receiver, true, true, range, visitor); |
| 5394 break; |
| 5395 } |
| 5396 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| 5397 num_of_elements = |
| 5398 IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>( |
| 5399 receiver, true, true, range, visitor); |
| 5400 break; |
| 5401 } |
| 5402 case JSObject::EXTERNAL_SHORT_ELEMENTS: { |
| 5403 num_of_elements = |
| 5404 IterateExternalArrayElements<ExternalShortArray, int16_t>( |
| 5405 receiver, true, true, range, visitor); |
| 5406 break; |
| 5407 } |
| 5408 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
| 5409 num_of_elements = |
| 5410 IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>( |
| 5411 receiver, true, true, range, visitor); |
| 5412 break; |
| 5413 } |
| 5414 case JSObject::EXTERNAL_INT_ELEMENTS: { |
| 5415 num_of_elements = |
| 5416 IterateExternalArrayElements<ExternalIntArray, int32_t>( |
| 5417 receiver, true, false, range, visitor); |
| 5418 break; |
| 5419 } |
| 5420 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 5421 num_of_elements = |
| 5422 IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>( |
| 5423 receiver, true, false, range, visitor); |
| 5424 break; |
| 5425 } |
| 5426 case JSObject::EXTERNAL_FLOAT_ELEMENTS: { |
| 5427 num_of_elements = |
| 5428 IterateExternalArrayElements<ExternalFloatArray, float>( |
| 5429 receiver, false, false, range, visitor); |
| 5430 break; |
| 5431 } |
5325 case JSObject::DICTIONARY_ELEMENTS: { | 5432 case JSObject::DICTIONARY_ELEMENTS: { |
5326 Handle<NumberDictionary> dict(receiver->element_dictionary()); | 5433 Handle<NumberDictionary> dict(receiver->element_dictionary()); |
5327 uint32_t capacity = dict->Capacity(); | 5434 uint32_t capacity = dict->Capacity(); |
5328 for (uint32_t j = 0; j < capacity; j++) { | 5435 for (uint32_t j = 0; j < capacity; j++) { |
5329 Handle<Object> k(dict->KeyAt(j)); | 5436 Handle<Object> k(dict->KeyAt(j)); |
5330 if (dict->IsKey(*k)) { | 5437 if (dict->IsKey(*k)) { |
5331 ASSERT(k->IsNumber()); | 5438 ASSERT(k->IsNumber()); |
5332 uint32_t index = static_cast<uint32_t>(k->Number()); | 5439 uint32_t index = static_cast<uint32_t>(k->Number()); |
5333 if (index < range) { | 5440 if (index < range) { |
5334 num_of_elements++; | 5441 num_of_elements++; |
(...skipping 2416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7751 } else { | 7858 } else { |
7752 // Handle last resort GC and make sure to allow future allocations | 7859 // Handle last resort GC and make sure to allow future allocations |
7753 // to grow the heap without causing GCs (if possible). | 7860 // to grow the heap without causing GCs (if possible). |
7754 Counters::gc_last_resort_from_js.Increment(); | 7861 Counters::gc_last_resort_from_js.Increment(); |
7755 Heap::CollectAllGarbage(false); | 7862 Heap::CollectAllGarbage(false); |
7756 } | 7863 } |
7757 } | 7864 } |
7758 | 7865 |
7759 | 7866 |
7760 } } // namespace v8::internal | 7867 } } // namespace v8::internal |
OLD | NEW |