OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 10558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10569 // Returns an array that tells you where in the [0, length) interval an array | 10569 // Returns an array that tells you where in the [0, length) interval an array |
10570 // might have elements. Can either return an array of keys (positive integers | 10570 // might have elements. Can either return an array of keys (positive integers |
10571 // or undefined) or a number representing the positive length of an interval | 10571 // or undefined) or a number representing the positive length of an interval |
10572 // starting at index 0. | 10572 // starting at index 0. |
10573 // Intervals can span over some keys that are not in the object. | 10573 // Intervals can span over some keys that are not in the object. |
10574 RUNTIME_FUNCTION(Runtime_GetArrayKeys) { | 10574 RUNTIME_FUNCTION(Runtime_GetArrayKeys) { |
10575 HandleScope scope(isolate); | 10575 HandleScope scope(isolate); |
10576 ASSERT(args.length() == 2); | 10576 ASSERT(args.length() == 2); |
10577 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); | 10577 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); |
10578 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); | 10578 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]); |
10579 if (array->elements()->IsDictionary()) { | 10579 |
| 10580 ElementsKind kind = array->GetElementsKind(); |
| 10581 bool estimate_keys_as_length = IsFastPackedElementsKind(kind); |
| 10582 if (IsHoleyElementsKind(kind)) { |
| 10583 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 10584 // If more than 10% of the array is holes, then calculate the key set, it's |
| 10585 // much faster than using the runtime to walk the prototype chain in the |
| 10586 // hole case. |
| 10587 int holes = 0; |
| 10588 int length = array->elements()->length(); |
| 10589 for (int i = 0; i < length; ++i) { |
| 10590 if (!accessor->HasElement(array, array, i)) { |
| 10591 ++holes; |
| 10592 } |
| 10593 } |
| 10594 estimate_keys_as_length = holes < static_cast<int>(length / 10); |
| 10595 } |
| 10596 |
| 10597 if (estimate_keys_as_length) { |
| 10598 RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() || |
| 10599 array->HasFastDoubleElements()); |
| 10600 uint32_t actual_length = static_cast<uint32_t>(array->elements()->length()); |
| 10601 return *isolate->factory()->NewNumberFromUint(Min(actual_length, length)); |
| 10602 } else { |
10580 Handle<FixedArray> keys = isolate->factory()->empty_fixed_array(); | 10603 Handle<FixedArray> keys = isolate->factory()->empty_fixed_array(); |
10581 for (PrototypeIterator iter(isolate, array, | 10604 for (PrototypeIterator iter(isolate, array, |
10582 PrototypeIterator::START_AT_RECEIVER); | 10605 PrototypeIterator::START_AT_RECEIVER); |
10583 !iter.IsAtEnd(); iter.Advance()) { | 10606 !iter.IsAtEnd(); iter.Advance()) { |
10584 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() || | 10607 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() || |
10585 JSObject::cast(*PrototypeIterator::GetCurrent(iter)) | 10608 JSObject::cast(*PrototypeIterator::GetCurrent(iter)) |
10586 ->HasIndexedInterceptor()) { | 10609 ->HasIndexedInterceptor()) { |
10587 // Bail out if we find a proxy or interceptor, likely not worth | 10610 // Bail out if we find a proxy or interceptor, likely not worth |
10588 // collecting keys in that case. | 10611 // collecting keys in that case. |
10589 return *isolate->factory()->NewNumberFromUint(length); | 10612 return *isolate->factory()->NewNumberFromUint(length); |
10590 } | 10613 } |
10591 Handle<JSObject> current = | 10614 Handle<JSObject> current = |
10592 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 10615 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
10593 Handle<FixedArray> current_keys = | 10616 Handle<FixedArray> current_keys = |
10594 isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE)); | 10617 isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE)); |
10595 current->GetOwnElementKeys(*current_keys, NONE); | 10618 current->GetOwnElementKeys(*current_keys, NONE); |
10596 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 10619 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
10597 isolate, keys, FixedArray::UnionOfKeys(keys, current_keys)); | 10620 isolate, keys, FixedArray::UnionOfKeys(keys, current_keys)); |
10598 } | 10621 } |
10599 // Erase any keys >= length. | 10622 // Erase any keys >= length. |
10600 // TODO(adamk): Remove this step when the contract of %GetArrayKeys | 10623 // TODO(adamk): Remove this step when the contract of %GetArrayKeys |
10601 // is changed to let this happen on the JS side. | 10624 // is changed to let this happen on the JS side. |
10602 for (int i = 0; i < keys->length(); i++) { | 10625 for (int i = 0; i < keys->length(); i++) { |
10603 if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i); | 10626 if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i); |
10604 } | 10627 } |
10605 return *isolate->factory()->NewJSArrayWithElements(keys); | 10628 return *isolate->factory()->NewJSArrayWithElements(keys); |
10606 } else { | |
10607 RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() || | |
10608 array->HasFastDoubleElements()); | |
10609 uint32_t actual_length = static_cast<uint32_t>(array->elements()->length()); | |
10610 return *isolate->factory()->NewNumberFromUint(Min(actual_length, length)); | |
10611 } | 10629 } |
10612 } | 10630 } |
10613 | 10631 |
10614 | 10632 |
10615 RUNTIME_FUNCTION(Runtime_LookupAccessor) { | 10633 RUNTIME_FUNCTION(Runtime_LookupAccessor) { |
10616 HandleScope scope(isolate); | 10634 HandleScope scope(isolate); |
10617 ASSERT(args.length() == 3); | 10635 ASSERT(args.length() == 3); |
10618 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); | 10636 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); |
10619 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 10637 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
10620 CONVERT_SMI_ARG_CHECKED(flag, 2); | 10638 CONVERT_SMI_ARG_CHECKED(flag, 2); |
(...skipping 4303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14924 ASSERT(arg_count == caller_args->length()); | 14942 ASSERT(arg_count == caller_args->length()); |
14925 } | 14943 } |
14926 #endif | 14944 #endif |
14927 return ArrayConstructorCommon(isolate, | 14945 return ArrayConstructorCommon(isolate, |
14928 constructor, | 14946 constructor, |
14929 Handle<AllocationSite>::null(), | 14947 Handle<AllocationSite>::null(), |
14930 caller_args); | 14948 caller_args); |
14931 } | 14949 } |
14932 | 14950 |
14933 | 14951 |
| 14952 RUNTIME_FUNCTION(Runtime_NormalizeElements) { |
| 14953 HandleScope scope(isolate); |
| 14954 ASSERT(args.length() == 1); |
| 14955 CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0); |
| 14956 JSObject::NormalizeElements(array); |
| 14957 return *array; |
| 14958 } |
| 14959 |
| 14960 |
14934 RUNTIME_FUNCTION(Runtime_MaxSmi) { | 14961 RUNTIME_FUNCTION(Runtime_MaxSmi) { |
14935 ASSERT(args.length() == 0); | 14962 ASSERT(args.length() == 0); |
14936 return Smi::FromInt(Smi::kMaxValue); | 14963 return Smi::FromInt(Smi::kMaxValue); |
14937 } | 14964 } |
14938 | 14965 |
14939 | 14966 |
14940 // ---------------------------------------------------------------------------- | 14967 // ---------------------------------------------------------------------------- |
14941 // Implementation of Runtime | 14968 // Implementation of Runtime |
14942 | 14969 |
14943 #define F(name, number_of_args, result_size) \ | 14970 #define F(name, number_of_args, result_size) \ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14995 } | 15022 } |
14996 return NULL; | 15023 return NULL; |
14997 } | 15024 } |
14998 | 15025 |
14999 | 15026 |
15000 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15027 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15001 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15028 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15002 } | 15029 } |
15003 | 15030 |
15004 } } // namespace v8::internal | 15031 } } // namespace v8::internal |
OLD | NEW |