Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index 38f77d07137eb06acec574d67d409cdfca073cd1..dade9c45d56890a9b6f36ef523407355835df068 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -9540,6 +9540,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) { |
| } |
| +static Object* NewSingleInterval(Isolate* isolate, uint32_t length) { |
|
Michael Starzinger
2013/03/22 10:12:20
It is dangerous to have a method returning an unha
adamk
2013/03/22 15:11:18
Fair point. Going back and forth between JS and C+
|
| + Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
| + // -1 means start of array. |
| + single_interval->set(0, Smi::FromInt(-1)); |
| + single_interval->set(1, *isolate->factory()->NewNumberFromUint(length)); |
| + return *isolate->factory()->NewJSArrayWithElements(single_interval); |
| +} |
| + |
| + |
| // Returns an array that tells you where in the [0, length) interval an array |
| // might have elements. Can either return keys (positive integers) or |
| // intervals (pair of a negative integer (-start-1) followed by a |
| @@ -9551,13 +9560,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) { |
| CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); |
| CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); |
| if (array->elements()->IsDictionary()) { |
| - // Create an array and get all the keys into it, then remove all the |
| - // keys that are not integers in the range 0 to length-1. |
| - bool threw = false; |
| - Handle<FixedArray> keys = |
| - GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw); |
| - if (threw) return Failure::Exception(); |
| - |
| + Handle<FixedArray> keys = isolate->factory()->empty_fixed_array(); |
| + for (Handle<Object> p = array; |
| + !p->IsNull(); |
| + p = Handle<Object>(p->GetPrototype(isolate), isolate)) { |
| + if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) { |
| + // Bail out if we find a proxy or interceptor, likely not worth |
| + // collecting keys in that case. |
| + return NewSingleInterval(isolate, length); |
| + } |
| + Handle<JSObject> current = Handle<JSObject>::cast(p); |
| + Handle<FixedArray> current_keys = |
| + isolate->factory()->NewFixedArray( |
| + current->NumberOfLocalElements(NONE)); |
| + current->GetLocalElementKeys(*current_keys, NONE); |
| + keys = UnionOfKeys(keys, current_keys); |
| + } |
| int keys_length = keys->length(); |
|
rossberg
2013/03/22 14:22:34
Isn't the filtering below redundant now? You only
adamk
2013/03/22 15:11:18
I thought so too, but a test caught me: still need
rossberg
2013/03/22 17:27:22
Oh dear. Well, since the spec of the function says
adamk
2013/03/22 17:51:34
Added a comment, and a TODO (as I plan to change t
|
| for (int i = 0; i < keys_length; i++) { |
| Object* key = keys->get(i); |
| @@ -9571,17 +9589,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) { |
| } else { |
| ASSERT(array->HasFastSmiOrObjectElements() || |
| array->HasFastDoubleElements()); |
| - Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
| - // -1 means start of array. |
| - single_interval->set(0, Smi::FromInt(-1)); |
| - FixedArrayBase* elements = FixedArrayBase::cast(array->elements()); |
| - uint32_t actual_length = |
| - static_cast<uint32_t>(elements->length()); |
| - uint32_t min_length = actual_length < length ? actual_length : length; |
| - Handle<Object> length_object = |
| - isolate->factory()->NewNumber(static_cast<double>(min_length)); |
| - single_interval->set(1, *length_object); |
| - return *isolate->factory()->NewJSArrayWithElements(single_interval); |
| + uint32_t actual_length = static_cast<uint32_t>(array->elements()->length()); |
| + return NewSingleInterval(isolate, Min(actual_length, length)); |
| } |
| } |