| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
| 10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 isolate, content, JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS, | 789 isolate, content, JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS, |
| 790 ENUMERABLE_STRINGS)); | 790 ENUMERABLE_STRINGS)); |
| 791 | 791 |
| 792 // Test again, since cache may have been built by preceding call. | 792 // Test again, since cache may have been built by preceding call. |
| 793 if (object->IsSimpleEnum()) return object->map(); | 793 if (object->IsSimpleEnum()) return object->map(); |
| 794 | 794 |
| 795 return *content; | 795 return *content; |
| 796 } | 796 } |
| 797 | 797 |
| 798 | 798 |
| 799 // Return the names of the own named properties. | 799 RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) { |
| 800 // args[0]: object | |
| 801 // args[1]: PropertyAttributes as int | |
| 802 // TODO(cbruni/jkummerow): Use JSReceiver::GetKeys() internally, merge with | |
| 803 // Runtime_GetOwnElementNames. | |
| 804 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { | |
| 805 HandleScope scope(isolate); | 800 HandleScope scope(isolate); |
| 806 DCHECK(args.length() == 2); | 801 DCHECK(args.length() == 2); |
| 807 if (!args[0]->IsJSObject()) { | 802 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
| 808 return isolate->heap()->undefined_value(); | |
| 809 } | |
| 810 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | |
| 811 CONVERT_SMI_ARG_CHECKED(filter_value, 1); | 803 CONVERT_SMI_ARG_CHECKED(filter_value, 1); |
| 804 PropertyFilter filter = static_cast<PropertyFilter>(filter_value); |
| 812 | 805 |
| 813 // TODO(jkummerow): Temporary compatibility measure. Refactor callers. | 806 Handle<FixedArray> keys; |
| 814 // Values of filter_value are defined in macros.py. | 807 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 815 PropertyFilter filter = ALL_PROPERTIES; | 808 isolate, keys, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY, filter, |
| 816 if (filter_value & 2) { | 809 CONVERT_TO_STRING)); |
| 817 filter = static_cast<PropertyFilter>(filter | ONLY_ENUMERABLE); | |
| 818 } | |
| 819 if (filter_value & 8) { | |
| 820 filter = static_cast<PropertyFilter>(filter | SKIP_STRINGS); | |
| 821 } | |
| 822 if (filter_value & 16) { | |
| 823 filter = static_cast<PropertyFilter>(filter | SKIP_SYMBOLS); | |
| 824 } | |
| 825 DCHECK(filter_value & 32); | |
| 826 | 810 |
| 827 // Find the number of own properties for each of the objects. | 811 return *isolate->factory()->NewJSArrayWithElements(keys); |
| 828 int total_property_count = 0; | |
| 829 for (PrototypeIterator iter(isolate, object, | |
| 830 PrototypeIterator::START_AT_RECEIVER); | |
| 831 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { | |
| 832 // Casting to JSObject is fine because |object| is guaranteed to be one, | |
| 833 // and we'll only look at hidden prototypes which are never JSProxies. | |
| 834 Handle<JSObject> jsproto = PrototypeIterator::GetCurrent<JSObject>(iter); | |
| 835 total_property_count += jsproto->NumberOfOwnProperties(filter); | |
| 836 } | |
| 837 | |
| 838 // Allocate an array with storage for all the property names. | |
| 839 Handle<FixedArray> names = | |
| 840 isolate->factory()->NewFixedArray(total_property_count); | |
| 841 | |
| 842 // Get the property names. | |
| 843 int next_copy_index = 0; | |
| 844 int hidden_strings = 0; | |
| 845 Handle<Object> hidden_string = isolate->factory()->hidden_string(); | |
| 846 for (PrototypeIterator iter(isolate, object, | |
| 847 PrototypeIterator::START_AT_RECEIVER); | |
| 848 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { | |
| 849 // Casting to JSObject is fine because |object| is guaranteed to be one, | |
| 850 // and we'll only look at hidden prototypes which are never JSProxies. | |
| 851 Handle<JSObject> jsproto = PrototypeIterator::GetCurrent<JSObject>(iter); | |
| 852 int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); | |
| 853 // Names from hidden prototypes may already have been added | |
| 854 // for inherited function template instances. Count the duplicates | |
| 855 // and stub them out; the final copy pass at the end ignores holes. | |
| 856 for (int j = next_copy_index; j < next_copy_index + own; j++) { | |
| 857 Object* name_from_hidden_proto = names->get(j); | |
| 858 if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) { | |
| 859 hidden_strings++; | |
| 860 } else { | |
| 861 for (int k = 0; k < next_copy_index; k++) { | |
| 862 Object* name = names->get(k); | |
| 863 if (name_from_hidden_proto == name) { | |
| 864 names->set(j, *hidden_string); | |
| 865 hidden_strings++; | |
| 866 break; | |
| 867 } | |
| 868 } | |
| 869 } | |
| 870 } | |
| 871 next_copy_index += own; | |
| 872 } | |
| 873 | |
| 874 CHECK_EQ(total_property_count, next_copy_index); | |
| 875 | |
| 876 if (object->IsAccessCheckNeeded() && | |
| 877 !isolate->MayAccess(handle(isolate->context()), object)) { | |
| 878 for (int i = 0; i < total_property_count; i++) { | |
| 879 Handle<Name> name(Name::cast(names->get(i))); | |
| 880 if (name.is_identical_to(hidden_string)) continue; | |
| 881 LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); | |
| 882 if (!JSObject::AllCanRead(&it)) { | |
| 883 names->set(i, *hidden_string); | |
| 884 hidden_strings++; | |
| 885 } | |
| 886 } | |
| 887 } | |
| 888 | |
| 889 // Filter out name of hidden properties object and | |
| 890 // hidden prototype duplicates. | |
| 891 if (hidden_strings > 0) { | |
| 892 if (hidden_strings == total_property_count) { | |
| 893 names = isolate->factory()->empty_fixed_array(); | |
| 894 } else { | |
| 895 int i; | |
| 896 for (i = 0; i < total_property_count; i++) { | |
| 897 Object* name = names->get(i); | |
| 898 if (name == *hidden_string) break; | |
| 899 } | |
| 900 int dest_pos = i; | |
| 901 for (; i < total_property_count; i++) { | |
| 902 Object* name = names->get(i); | |
| 903 if (name == *hidden_string) continue; | |
| 904 names->set(dest_pos++, name); | |
| 905 } | |
| 906 | |
| 907 isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | |
| 908 *names, hidden_strings); | |
| 909 } | |
| 910 } | |
| 911 | |
| 912 return *isolate->factory()->NewJSArrayWithElements(names); | |
| 913 } | 812 } |
| 914 | 813 |
| 915 | 814 |
| 916 // Return the names of the own indexed properties. | |
| 917 // args[0]: object | |
| 918 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) { | |
| 919 HandleScope scope(isolate); | |
| 920 DCHECK(args.length() == 1); | |
| 921 if (!args[0]->IsJSObject()) { | |
| 922 return isolate->heap()->undefined_value(); | |
| 923 } | |
| 924 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | |
| 925 | |
| 926 // TODO(cbruni): implement proper prototype lookup like in GetOwnPropertyNames | |
| 927 if (object->IsJSGlobalProxy()) { | |
| 928 // All the elements are stored on the globa_object and not directly on the | |
| 929 // global object proxy. | |
| 930 PrototypeIterator iter(isolate, object, | |
| 931 PrototypeIterator::START_AT_PROTOTYPE); | |
| 932 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | |
| 933 return *isolate->factory()->NewJSArray(0); | |
| 934 } | |
| 935 // Casting to JSObject is fine because |object| is guaranteed to be one, | |
| 936 // and we'll only look at hidden prototypes which are never JSProxies. | |
| 937 object = PrototypeIterator::GetCurrent<JSObject>(iter); | |
| 938 } | |
| 939 | |
| 940 int n = object->NumberOfOwnElements(ALL_PROPERTIES); | |
| 941 Handle<FixedArray> names = isolate->factory()->NewFixedArray(n); | |
| 942 object->GetOwnElementKeys(*names, ALL_PROPERTIES); | |
| 943 return *isolate->factory()->NewJSArrayWithElements(names); | |
| 944 } | |
| 945 | |
| 946 | |
| 947 // Return information on whether an object has a named or indexed interceptor. | 815 // Return information on whether an object has a named or indexed interceptor. |
| 948 // args[0]: object | 816 // args[0]: object |
| 949 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) { | 817 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) { |
| 950 HandleScope scope(isolate); | 818 HandleScope scope(isolate); |
| 951 DCHECK(args.length() == 1); | 819 DCHECK(args.length() == 1); |
| 952 if (!args[0]->IsJSObject()) { | 820 if (!args[0]->IsJSObject()) { |
| 953 return Smi::FromInt(0); | 821 return Smi::FromInt(0); |
| 954 } | 822 } |
| 955 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | 823 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
| 956 | 824 |
| 957 int result = 0; | 825 int result = 0; |
| 958 if (obj->HasNamedInterceptor()) result |= 2; | 826 if (obj->HasNamedInterceptor()) result |= 2; |
| 959 if (obj->HasIndexedInterceptor()) result |= 1; | 827 if (obj->HasIndexedInterceptor()) result |= 1; |
| 960 | 828 |
| 961 return Smi::FromInt(result); | 829 return Smi::FromInt(result); |
| 962 } | 830 } |
| 963 | 831 |
| 964 | 832 |
| 965 // Return property names from named interceptor. | |
| 966 // args[0]: object | |
| 967 RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) { | |
| 968 HandleScope scope(isolate); | |
| 969 DCHECK(args.length() == 1); | |
| 970 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
| 971 | |
| 972 if (obj->HasNamedInterceptor()) { | |
| 973 Handle<JSObject> result; | |
| 974 if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) { | |
| 975 return *result; | |
| 976 } | |
| 977 } | |
| 978 return isolate->heap()->undefined_value(); | |
| 979 } | |
| 980 | |
| 981 | |
| 982 // Return element names from indexed interceptor. | |
| 983 // args[0]: object | |
| 984 RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) { | |
| 985 HandleScope scope(isolate); | |
| 986 DCHECK(args.length() == 1); | |
| 987 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | |
| 988 | |
| 989 if (obj->HasIndexedInterceptor()) { | |
| 990 Handle<JSObject> result; | |
| 991 if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) { | |
| 992 return *result; | |
| 993 } | |
| 994 } | |
| 995 return isolate->heap()->undefined_value(); | |
| 996 } | |
| 997 | |
| 998 | |
| 999 RUNTIME_FUNCTION(Runtime_OwnKeys) { | |
| 1000 HandleScope scope(isolate); | |
| 1001 DCHECK(args.length() == 1); | |
| 1002 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | |
| 1003 | |
| 1004 Handle<FixedArray> contents; | |
| 1005 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 1006 isolate, contents, | |
| 1007 JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY, ENUMERABLE_STRINGS, | |
| 1008 CONVERT_TO_STRING)); | |
| 1009 return *isolate->factory()->NewJSArrayWithElements(contents); | |
| 1010 } | |
| 1011 | |
| 1012 | |
| 1013 RUNTIME_FUNCTION(Runtime_ToFastProperties) { | 833 RUNTIME_FUNCTION(Runtime_ToFastProperties) { |
| 1014 HandleScope scope(isolate); | 834 HandleScope scope(isolate); |
| 1015 DCHECK(args.length() == 1); | 835 DCHECK(args.length() == 1); |
| 1016 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); | 836 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); |
| 1017 if (object->IsJSObject() && !object->IsJSGlobalObject()) { | 837 if (object->IsJSObject() && !object->IsJSGlobalObject()) { |
| 1018 JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0, | 838 JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0, |
| 1019 "RuntimeToFastProperties"); | 839 "RuntimeToFastProperties"); |
| 1020 } | 840 } |
| 1021 return *object; | 841 return *object; |
| 1022 } | 842 } |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 | 1418 |
| 1599 RUNTIME_FUNCTION(Runtime_ObjectDefineProperties) { | 1419 RUNTIME_FUNCTION(Runtime_ObjectDefineProperties) { |
| 1600 HandleScope scope(isolate); | 1420 HandleScope scope(isolate); |
| 1601 DCHECK(args.length() == 2); | 1421 DCHECK(args.length() == 2); |
| 1602 CONVERT_ARG_HANDLE_CHECKED(Object, o, 0); | 1422 CONVERT_ARG_HANDLE_CHECKED(Object, o, 0); |
| 1603 CONVERT_ARG_HANDLE_CHECKED(Object, properties, 1); | 1423 CONVERT_ARG_HANDLE_CHECKED(Object, properties, 1); |
| 1604 return JSReceiver::DefineProperties(isolate, o, properties); | 1424 return JSReceiver::DefineProperties(isolate, o, properties); |
| 1605 } | 1425 } |
| 1606 } // namespace internal | 1426 } // namespace internal |
| 1607 } // namespace v8 | 1427 } // namespace v8 |
| OLD | NEW |