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