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 3976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3987 } | 3987 } |
3988 | 3988 |
3989 | 3989 |
3990 /** | 3990 /** |
3991 * A simple visitor visits every element of Array's. | 3991 * A simple visitor visits every element of Array's. |
3992 * The backend storage can be a fixed array for fast elements case, | 3992 * The backend storage can be a fixed array for fast elements case, |
3993 * or a dictionary for sparse array. Since Dictionary is a subtype | 3993 * or a dictionary for sparse array. Since Dictionary is a subtype |
3994 * of FixedArray, the class can be used by both fast and slow cases. | 3994 * of FixedArray, the class can be used by both fast and slow cases. |
3995 * The second parameter of the constructor, fast_elements, specifies | 3995 * The second parameter of the constructor, fast_elements, specifies |
3996 * whether the storage is a FixedArray or Dictionary. | 3996 * whether the storage is a FixedArray or Dictionary. |
| 3997 * |
| 3998 * An index limit is used to deal with the situation that a result array |
| 3999 * length overflows 32-bit non-negative integer. |
3997 */ | 4000 */ |
3998 class ArrayConcatVisitor { | 4001 class ArrayConcatVisitor { |
3999 public: | 4002 public: |
4000 ArrayConcatVisitor(Handle<FixedArray> storage, bool fast_elements) | 4003 ArrayConcatVisitor(Handle<FixedArray> storage, |
4001 : storage_(storage), fast_elements_(fast_elements), index_offset_(0) { } | 4004 uint32_t index_limit, |
| 4005 bool fast_elements) : |
| 4006 storage_(storage), index_limit_(index_limit), |
| 4007 fast_elements_(fast_elements), index_offset_(0) { } |
4002 | 4008 |
4003 void visit(uint32_t i, Handle<Object> elm) { | 4009 void visit(uint32_t i, Handle<Object> elm) { |
4004 uint32_t index = i + index_offset_; | 4010 uint32_t index = i + index_offset_; |
4005 | 4011 if (index >= index_limit_) return; |
| 4012 |
4006 if (fast_elements_) { | 4013 if (fast_elements_) { |
4007 ASSERT(index < static_cast<uint32_t>(storage_->length())); | 4014 ASSERT(index < static_cast<uint32_t>(storage_->length())); |
4008 storage_->set(index, *elm); | 4015 storage_->set(index, *elm); |
4009 | 4016 |
4010 } else { | 4017 } else { |
4011 Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_); | 4018 Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_); |
4012 Handle<Dictionary> result = | 4019 Handle<Dictionary> result = |
4013 Factory::DictionaryAtNumberPut(dict, index, elm); | 4020 Factory::DictionaryAtNumberPut(dict, index, elm); |
4014 if (!result.is_identical_to(dict)) | 4021 if (!result.is_identical_to(dict)) |
4015 storage_ = result; | 4022 storage_ = result; |
4016 } | 4023 } |
4017 } | 4024 } |
4018 | 4025 |
4019 void increase_index_offset(uint32_t delta) { | 4026 void increase_index_offset(uint32_t delta) { |
4020 index_offset_ += delta; | 4027 index_offset_ += delta; |
4021 } | 4028 } |
4022 | 4029 |
4023 private: | 4030 private: |
4024 Handle<FixedArray> storage_; | 4031 Handle<FixedArray> storage_; |
| 4032 uint32_t index_limit_; |
4025 bool fast_elements_; | 4033 bool fast_elements_; |
4026 uint32_t index_offset_; | 4034 uint32_t index_offset_; |
4027 }; | 4035 }; |
4028 | 4036 |
4029 | 4037 |
4030 /** | 4038 /** |
4031 * A helper function that visits elements of a JSObject. Only elements | 4039 * A helper function that visits elements of a JSObject. Only elements |
4032 * whose index between 0 and range (exclusive) are visited. | 4040 * whose index between 0 and range (exclusive) are visited. |
4033 * | 4041 * |
4034 * If the third parameter, visitor, is not NULL, the visitor is called | 4042 * If the third parameter, visitor, is not NULL, the visitor is called |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4119 | 4127 |
4120 /** | 4128 /** |
4121 * A helper function of Runtime_ArrayConcat. | 4129 * A helper function of Runtime_ArrayConcat. |
4122 * | 4130 * |
4123 * 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 same as |
4124 * the arguments array of Array::concat JS function. | 4132 * the arguments array of Array::concat JS function. |
4125 * | 4133 * |
4126 * If an argument is an Array object, the function visits array elements. | 4134 * If an argument is an Array object, the function visits array elements. |
4127 * If an argument is not an Array object, the function visits the object | 4135 * If an argument is not an Array object, the function visits the object |
4128 * as if it is an one-element array. | 4136 * as if it is an one-element array. |
| 4137 * |
| 4138 * If the result array index overflows 32-bit integer, the rounded non-negative |
| 4139 * number is used as new length. For example, if one array length is 2^32 - 1, |
| 4140 * second array length is 1, the concatenated array length is 0. |
4129 */ | 4141 */ |
4130 static uint32_t IterateArguments(Handle<JSArray> arguments, | 4142 static uint32_t IterateArguments(Handle<JSArray> arguments, |
4131 ArrayConcatVisitor* visitor) { | 4143 ArrayConcatVisitor* visitor) { |
4132 uint32_t visited_elements = 0; | 4144 uint32_t visited_elements = 0; |
4133 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); | 4145 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); |
4134 | 4146 |
4135 for (uint32_t i = 0; i < num_of_args; i++) { | 4147 for (uint32_t i = 0; i < num_of_args; i++) { |
4136 Handle<Object> obj(arguments->GetElement(i)); | 4148 Handle<Object> obj(arguments->GetElement(i)); |
4137 if (obj->IsJSArray()) { | 4149 if (obj->IsJSArray()) { |
4138 Handle<JSArray> array = Handle<JSArray>::cast(obj); | 4150 Handle<JSArray> array = Handle<JSArray>::cast(obj); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4200 } else { | 4212 } else { |
4201 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate | 4213 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate |
4202 uint32_t at_least_space_for = estimate_nof_elements + | 4214 uint32_t at_least_space_for = estimate_nof_elements + |
4203 (estimate_nof_elements >> 2); | 4215 (estimate_nof_elements >> 2); |
4204 storage = Handle<FixedArray>::cast( | 4216 storage = Handle<FixedArray>::cast( |
4205 Factory::NewDictionary(at_least_space_for)); | 4217 Factory::NewDictionary(at_least_space_for)); |
4206 } | 4218 } |
4207 | 4219 |
4208 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); | 4220 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); |
4209 | 4221 |
4210 ArrayConcatVisitor visitor(storage, fast_case); | 4222 ArrayConcatVisitor visitor(storage, result_length, fast_case); |
4211 | 4223 |
4212 IterateArguments(arguments, &visitor); | 4224 IterateArguments(arguments, &visitor); |
4213 | 4225 |
4214 result->set_length(*len); | 4226 result->set_length(*len); |
4215 result->set_elements(*storage); | 4227 result->set_elements(*storage); |
4216 | 4228 |
4217 return *result; | 4229 return *result; |
4218 } | 4230 } |
4219 | 4231 |
4220 | 4232 |
(...skipping 1533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5754 | 5766 |
5755 void Runtime::PerformGC(Object* result) { | 5767 void Runtime::PerformGC(Object* result) { |
5756 Failure* failure = Failure::cast(result); | 5768 Failure* failure = Failure::cast(result); |
5757 // Try to do a garbage collection; ignore it if it fails. The C | 5769 // Try to do a garbage collection; ignore it if it fails. The C |
5758 // entry stub will throw an out-of-memory exception in that case. | 5770 // entry stub will throw an out-of-memory exception in that case. |
5759 Heap::CollectGarbage(failure->requested(), failure->allocation_space()); | 5771 Heap::CollectGarbage(failure->requested(), failure->allocation_space()); |
5760 } | 5772 } |
5761 | 5773 |
5762 | 5774 |
5763 } } // namespace v8::internal | 5775 } } // namespace v8::internal |
OLD | NEW |