| 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 |