OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 4110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4121 IterateElements(Handle<JSObject>::cast(obj), range, visitor); | 4121 IterateElements(Handle<JSObject>::cast(obj), range, visitor); |
4122 } | 4122 } |
4123 | 4123 |
4124 return nof_elements; | 4124 return nof_elements; |
4125 } | 4125 } |
4126 | 4126 |
4127 | 4127 |
4128 /** | 4128 /** |
4129 * A helper function of Runtime_ArrayConcat. | 4129 * A helper function of Runtime_ArrayConcat. |
4130 * | 4130 * |
4131 * The first argument is an Array of Arrays and objects. It is the same as | 4131 * The first argument is an Array of arrays and objects. It is the |
4132 * the arguments array of Array::concat JS function. | 4132 * same as the arguments array of Array::concat JS function. |
4133 * | 4133 * |
4134 * If an argument is an Array object, the function visits array elements. | 4134 * If an argument is an Array object, the function visits array |
4135 * If an argument is not an Array object, the function visits the object | 4135 * elements. If an argument is not an Array object, the function |
4136 * as if it is an one-element array. | 4136 * visits the object as if it is an one-element array. |
4137 * | 4137 * |
4138 * If the result array index overflows 32-bit integer, the rounded non-negative | 4138 * If the result array index overflows 32-bit integer, the rounded |
4139 * number is used as new length. For example, if one array length is 2^32 - 1, | 4139 * non-negative number is used as new length. For example, if one |
4140 * second array length is 1, the concatenated array length is 0. | 4140 * array length is 2^32 - 1, second array length is 1, the |
| 4141 * concatenated array length is 0. |
4141 */ | 4142 */ |
4142 static uint32_t IterateArguments(Handle<JSArray> arguments, | 4143 static uint32_t IterateArguments(Handle<JSArray> arguments, |
4143 ArrayConcatVisitor* visitor) { | 4144 ArrayConcatVisitor* visitor) { |
4144 uint32_t visited_elements = 0; | 4145 uint32_t visited_elements = 0; |
4145 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); | 4146 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); |
4146 | 4147 |
4147 for (uint32_t i = 0; i < num_of_args; i++) { | 4148 for (uint32_t i = 0; i < num_of_args; i++) { |
4148 Handle<Object> obj(arguments->GetElement(i)); | 4149 Handle<Object> obj(arguments->GetElement(i)); |
4149 if (obj->IsJSArray()) { | 4150 if (obj->IsJSArray()) { |
4150 Handle<JSArray> array = Handle<JSArray>::cast(obj); | 4151 Handle<JSArray> array = Handle<JSArray>::cast(obj); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4194 } else { | 4195 } else { |
4195 result_length++; | 4196 result_length++; |
4196 } | 4197 } |
4197 } | 4198 } |
4198 } | 4199 } |
4199 | 4200 |
4200 // Allocate an empty array, will set length and content later. | 4201 // Allocate an empty array, will set length and content later. |
4201 Handle<JSArray> result = Factory::NewJSArray(0); | 4202 Handle<JSArray> result = Factory::NewJSArray(0); |
4202 | 4203 |
4203 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL); | 4204 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL); |
4204 // If estimated number of elements is more than half of length, | 4205 // If estimated number of elements is more than half of length, a |
4205 // A fixed array (fast case) is more time & space-efficient than a dictionary. | 4206 // fixed array (fast case) is more time and space-efficient than a |
| 4207 // dictionary. |
4206 bool fast_case = (estimate_nof_elements * 2) >= result_length; | 4208 bool fast_case = (estimate_nof_elements * 2) >= result_length; |
4207 | 4209 |
4208 Handle<FixedArray> storage; | 4210 Handle<FixedArray> storage; |
4209 if (fast_case) { | 4211 if (fast_case) { |
4210 storage = Factory::NewFixedArray(result_length); | 4212 // The backing storage array must have non-existing elements to |
| 4213 // preserve holes across concat operations. |
| 4214 storage = Factory::NewFixedArrayWithHoles(result_length); |
4211 | 4215 |
4212 } else { | 4216 } else { |
4213 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate | 4217 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate |
4214 uint32_t at_least_space_for = estimate_nof_elements + | 4218 uint32_t at_least_space_for = estimate_nof_elements + |
4215 (estimate_nof_elements >> 2); | 4219 (estimate_nof_elements >> 2); |
4216 storage = Handle<FixedArray>::cast( | 4220 storage = Handle<FixedArray>::cast( |
4217 Factory::NewDictionary(at_least_space_for)); | 4221 Factory::NewDictionary(at_least_space_for)); |
4218 } | 4222 } |
4219 | 4223 |
4220 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); | 4224 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); |
(...skipping 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5766 | 5770 |
5767 void Runtime::PerformGC(Object* result) { | 5771 void Runtime::PerformGC(Object* result) { |
5768 Failure* failure = Failure::cast(result); | 5772 Failure* failure = Failure::cast(result); |
5769 // Try to do a garbage collection; ignore it if it fails. The C | 5773 // Try to do a garbage collection; ignore it if it fails. The C |
5770 // entry stub will throw an out-of-memory exception in that case. | 5774 // entry stub will throw an out-of-memory exception in that case. |
5771 Heap::CollectGarbage(failure->requested(), failure->allocation_space()); | 5775 Heap::CollectGarbage(failure->requested(), failure->allocation_space()); |
5772 } | 5776 } |
5773 | 5777 |
5774 | 5778 |
5775 } } // namespace v8::internal | 5779 } } // namespace v8::internal |
OLD | NEW |