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 | 10579 if (array->elements()->IsDictionary()) { |
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 { | |
10603 Handle<FixedArray> keys = isolate->factory()->empty_fixed_array(); | 10580 Handle<FixedArray> keys = isolate->factory()->empty_fixed_array(); |
10604 for (PrototypeIterator iter(isolate, array, | 10581 for (PrototypeIterator iter(isolate, array, |
10605 PrototypeIterator::START_AT_RECEIVER); | 10582 PrototypeIterator::START_AT_RECEIVER); |
10606 !iter.IsAtEnd(); iter.Advance()) { | 10583 !iter.IsAtEnd(); iter.Advance()) { |
10607 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() || | 10584 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() || |
10608 JSObject::cast(*PrototypeIterator::GetCurrent(iter)) | 10585 JSObject::cast(*PrototypeIterator::GetCurrent(iter)) |
10609 ->HasIndexedInterceptor()) { | 10586 ->HasIndexedInterceptor()) { |
10610 // Bail out if we find a proxy or interceptor, likely not worth | 10587 // Bail out if we find a proxy or interceptor, likely not worth |
10611 // collecting keys in that case. | 10588 // collecting keys in that case. |
10612 return *isolate->factory()->NewNumberFromUint(length); | 10589 return *isolate->factory()->NewNumberFromUint(length); |
10613 } | 10590 } |
10614 Handle<JSObject> current = | 10591 Handle<JSObject> current = |
10615 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 10592 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
10616 Handle<FixedArray> current_keys = | 10593 Handle<FixedArray> current_keys = |
10617 isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE)); | 10594 isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE)); |
10618 current->GetOwnElementKeys(*current_keys, NONE); | 10595 current->GetOwnElementKeys(*current_keys, NONE); |
10619 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 10596 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
10620 isolate, keys, FixedArray::UnionOfKeys(keys, current_keys)); | 10597 isolate, keys, FixedArray::UnionOfKeys(keys, current_keys)); |
10621 } | 10598 } |
10622 // Erase any keys >= length. | 10599 // Erase any keys >= length. |
10623 // TODO(adamk): Remove this step when the contract of %GetArrayKeys | 10600 // TODO(adamk): Remove this step when the contract of %GetArrayKeys |
10624 // is changed to let this happen on the JS side. | 10601 // is changed to let this happen on the JS side. |
10625 for (int i = 0; i < keys->length(); i++) { | 10602 for (int i = 0; i < keys->length(); i++) { |
10626 if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i); | 10603 if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i); |
10627 } | 10604 } |
10628 return *isolate->factory()->NewJSArrayWithElements(keys); | 10605 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)); |
10629 } | 10611 } |
10630 } | 10612 } |
10631 | 10613 |
10632 | 10614 |
10633 RUNTIME_FUNCTION(Runtime_LookupAccessor) { | 10615 RUNTIME_FUNCTION(Runtime_LookupAccessor) { |
10634 HandleScope scope(isolate); | 10616 HandleScope scope(isolate); |
10635 ASSERT(args.length() == 3); | 10617 ASSERT(args.length() == 3); |
10636 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); | 10618 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); |
10637 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 10619 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
10638 CONVERT_SMI_ARG_CHECKED(flag, 2); | 10620 CONVERT_SMI_ARG_CHECKED(flag, 2); |
(...skipping 4303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14942 ASSERT(arg_count == caller_args->length()); | 14924 ASSERT(arg_count == caller_args->length()); |
14943 } | 14925 } |
14944 #endif | 14926 #endif |
14945 return ArrayConstructorCommon(isolate, | 14927 return ArrayConstructorCommon(isolate, |
14946 constructor, | 14928 constructor, |
14947 Handle<AllocationSite>::null(), | 14929 Handle<AllocationSite>::null(), |
14948 caller_args); | 14930 caller_args); |
14949 } | 14931 } |
14950 | 14932 |
14951 | 14933 |
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 | |
14961 RUNTIME_FUNCTION(Runtime_MaxSmi) { | 14934 RUNTIME_FUNCTION(Runtime_MaxSmi) { |
14962 ASSERT(args.length() == 0); | 14935 ASSERT(args.length() == 0); |
14963 return Smi::FromInt(Smi::kMaxValue); | 14936 return Smi::FromInt(Smi::kMaxValue); |
14964 } | 14937 } |
14965 | 14938 |
14966 | 14939 |
14967 // ---------------------------------------------------------------------------- | 14940 // ---------------------------------------------------------------------------- |
14968 // Implementation of Runtime | 14941 // Implementation of Runtime |
14969 | 14942 |
14970 #define F(name, number_of_args, result_size) \ | 14943 #define F(name, number_of_args, result_size) \ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15022 } | 14995 } |
15023 return NULL; | 14996 return NULL; |
15024 } | 14997 } |
15025 | 14998 |
15026 | 14999 |
15027 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15000 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15028 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15001 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15029 } | 15002 } |
15030 | 15003 |
15031 } } // namespace v8::internal | 15004 } } // namespace v8::internal |
OLD | NEW |