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 |