OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 9522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9533 int result = SeededNumberDictionary::cast(elements)->NumberOfElements(); | 9533 int result = SeededNumberDictionary::cast(elements)->NumberOfElements(); |
9534 return Smi::FromInt(result); | 9534 return Smi::FromInt(result); |
9535 } else if (object->IsJSArray()) { | 9535 } else if (object->IsJSArray()) { |
9536 return JSArray::cast(object)->length(); | 9536 return JSArray::cast(object)->length(); |
9537 } else { | 9537 } else { |
9538 return Smi::FromInt(FixedArray::cast(elements)->length()); | 9538 return Smi::FromInt(FixedArray::cast(elements)->length()); |
9539 } | 9539 } |
9540 } | 9540 } |
9541 | 9541 |
9542 | 9542 |
| 9543 static Handle<Object> NewSingleInterval(Isolate* isolate, uint32_t length) { |
| 9544 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
| 9545 // -1 means start of array. |
| 9546 single_interval->set(0, Smi::FromInt(-1)); |
| 9547 single_interval->set(1, *isolate->factory()->NewNumberFromUint(length)); |
| 9548 return isolate->factory()->NewJSArrayWithElements(single_interval); |
| 9549 } |
| 9550 |
| 9551 |
9543 // Returns an array that tells you where in the [0, length) interval an array | 9552 // Returns an array that tells you where in the [0, length) interval an array |
9544 // might have elements. Can either return keys (positive integers) or | 9553 // might have elements. Can either return keys (positive integers) or |
9545 // intervals (pair of a negative integer (-start-1) followed by a | 9554 // intervals (pair of a negative integer (-start-1) followed by a |
9546 // positive (length)) or undefined values. | 9555 // positive (length)) or undefined values. |
9547 // Intervals can span over some keys that are not in the object. | 9556 // Intervals can span over some keys that are not in the object. |
9548 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) { | 9557 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) { |
9549 HandleScope scope(isolate); | 9558 HandleScope scope(isolate); |
9550 ASSERT(args.length() == 2); | 9559 ASSERT(args.length() == 2); |
9551 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); | 9560 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); |
9552 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); | 9561 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); |
9553 if (array->elements()->IsDictionary()) { | 9562 if (array->elements()->IsDictionary()) { |
9554 // Create an array and get all the keys into it, then remove all the | 9563 Handle<FixedArray> keys = isolate->factory()->empty_fixed_array(); |
9555 // keys that are not integers in the range 0 to length-1. | 9564 for (Handle<Object> p = array; |
9556 bool threw = false; | 9565 !p->IsNull(); |
9557 Handle<FixedArray> keys = | 9566 p = Handle<Object>(p->GetPrototype(isolate), isolate)) { |
9558 GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw); | 9567 if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) { |
9559 if (threw) return Failure::Exception(); | 9568 // Bail out if we find a proxy or interceptor, likely not worth |
9560 | 9569 // collecting keys in that case. |
9561 int keys_length = keys->length(); | 9570 return *NewSingleInterval(isolate, length); |
9562 for (int i = 0; i < keys_length; i++) { | |
9563 Object* key = keys->get(i); | |
9564 uint32_t index = 0; | |
9565 if (!key->ToArrayIndex(&index) || index >= length) { | |
9566 // Zap invalid keys. | |
9567 keys->set_undefined(i); | |
9568 } | 9571 } |
| 9572 Handle<JSObject> current = Handle<JSObject>::cast(p); |
| 9573 Handle<FixedArray> current_keys = |
| 9574 isolate->factory()->NewFixedArray( |
| 9575 current->NumberOfLocalElements(NONE)); |
| 9576 current->GetLocalElementKeys(*current_keys, NONE); |
| 9577 keys = UnionOfKeys(keys, current_keys); |
| 9578 } |
| 9579 // Erase any keys >= length. |
| 9580 // TODO(adamk): Remove this step when the contract of %GetArrayKeys |
| 9581 // is changed to let this happen on the JS side. |
| 9582 for (int i = 0; i < keys->length(); i++) { |
| 9583 if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i); |
9569 } | 9584 } |
9570 return *isolate->factory()->NewJSArrayWithElements(keys); | 9585 return *isolate->factory()->NewJSArrayWithElements(keys); |
9571 } else { | 9586 } else { |
9572 ASSERT(array->HasFastSmiOrObjectElements() || | 9587 ASSERT(array->HasFastSmiOrObjectElements() || |
9573 array->HasFastDoubleElements()); | 9588 array->HasFastDoubleElements()); |
9574 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); | 9589 uint32_t actual_length = static_cast<uint32_t>(array->elements()->length()); |
9575 // -1 means start of array. | 9590 return *NewSingleInterval(isolate, Min(actual_length, length)); |
9576 single_interval->set(0, Smi::FromInt(-1)); | |
9577 FixedArrayBase* elements = FixedArrayBase::cast(array->elements()); | |
9578 uint32_t actual_length = | |
9579 static_cast<uint32_t>(elements->length()); | |
9580 uint32_t min_length = actual_length < length ? actual_length : length; | |
9581 Handle<Object> length_object = | |
9582 isolate->factory()->NewNumber(static_cast<double>(min_length)); | |
9583 single_interval->set(1, *length_object); | |
9584 return *isolate->factory()->NewJSArrayWithElements(single_interval); | |
9585 } | 9591 } |
9586 } | 9592 } |
9587 | 9593 |
9588 | 9594 |
9589 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) { | 9595 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) { |
9590 NoHandleAllocation ha(isolate); | 9596 NoHandleAllocation ha(isolate); |
9591 ASSERT(args.length() == 3); | 9597 ASSERT(args.length() == 3); |
9592 CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); | 9598 CONVERT_ARG_CHECKED(JSReceiver, receiver, 0); |
9593 CONVERT_ARG_CHECKED(Name, name, 1); | 9599 CONVERT_ARG_CHECKED(Name, name, 1); |
9594 CONVERT_SMI_ARG_CHECKED(flag, 2); | 9600 CONVERT_SMI_ARG_CHECKED(flag, 2); |
(...skipping 3391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12986 // Handle last resort GC and make sure to allow future allocations | 12992 // Handle last resort GC and make sure to allow future allocations |
12987 // to grow the heap without causing GCs (if possible). | 12993 // to grow the heap without causing GCs (if possible). |
12988 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12994 isolate->counters()->gc_last_resort_from_js()->Increment(); |
12989 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 12995 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
12990 "Runtime::PerformGC"); | 12996 "Runtime::PerformGC"); |
12991 } | 12997 } |
12992 } | 12998 } |
12993 | 12999 |
12994 | 13000 |
12995 } } // namespace v8::internal | 13001 } } // namespace v8::internal |
OLD | NEW |