Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: vm/dart_api_impl.cc

Issue 8417003: Enhance the array access API to deal with any objct that implements the list interface. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | vm/dart_api_impl_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "include/dart_api.h" 5 #include "include/dart_api.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart.h" 10 #include "vm/dart.h"
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 return Api::Success(); 846 return Api::Success();
847 } 847 }
848 return Api::Error("Object is not a String"); 848 return Api::Error("Object is not a String");
849 } 849 }
850 850
851 851
852 DART_EXPORT bool Dart_IsArray(Dart_Handle object) { 852 DART_EXPORT bool Dart_IsArray(Dart_Handle object) {
853 Zone zone; // Setup a VM zone as we are creating some handles. 853 Zone zone; // Setup a VM zone as we are creating some handles.
854 HandleScope scope; // Setup a VM handle scope. 854 HandleScope scope; // Setup a VM handle scope.
855 const Object& obj = Object::Handle(Api::UnwrapHandle(object)); 855 const Object& obj = Object::Handle(Api::UnwrapHandle(object));
856 return obj.IsArray(); 856 if (obj.IsArray()) {
857 return true;
858 }
859 // TODO(5526318): Make access to GrowableObjectArray more efficient.
860 if (obj.IsInstance()) {
Mads Ager (google) 2011/10/28 07:50:18 Maybe extract this into an ImplementsListInterface
siva 2011/10/31 20:30:49 Done.
861 Instance& instance = Instance::Handle();
862 instance ^= obj.raw();
863 Isolate* isolate = Isolate::Current();
864 const Type& type = Type::Handle(isolate->object_store()->list_interface());
865 return instance.Is(type);
turnidge 2011/10/27 21:29:46 A thought. Given that all of the other Is*() func
siva 2011/10/31 20:30:49 Regis and I discussed this, he felt that the only
866 }
867 return false;
857 } 868 }
858 869
859 870
860 DART_EXPORT Dart_Handle Dart_NewArray(intptr_t length) { 871 DART_EXPORT Dart_Handle Dart_NewArray(intptr_t length) {
861 Zone zone; // Setup a VM zone as we are creating some handles. 872 Zone zone; // Setup a VM zone as we are creating some handles.
862 HandleScope scope; // Setup a VM handle scope. 873 HandleScope scope; // Setup a VM handle scope.
863 const Array& obj = Array::Handle(Array::New(length)); 874 const Array& obj = Array::Handle(Array::New(length));
864 return Api::NewLocalHandle(obj); 875 return Api::NewLocalHandle(obj);
865 } 876 }
866 877
867 878
868 DART_EXPORT Dart_Handle Dart_GetLength(Dart_Handle array, intptr_t* len) { 879 DART_EXPORT Dart_Handle Dart_GetLength(Dart_Handle array, intptr_t* len) {
869 Zone zone; // Setup a VM zone as we are creating some handles. 880 Zone zone; // Setup a VM zone as we are creating some handles.
870 HandleScope scope; // Setup a VM handle scope. 881 HandleScope scope; // Setup a VM handle scope.
871 const Object& obj = Object::Handle(Api::UnwrapHandle(array)); 882 const Object& obj = Object::Handle(Api::UnwrapHandle(array));
872 if (obj.IsArray()) { 883 if (obj.IsArray()) {
873 Array& array_obj = Array::Handle(); 884 Array& array_obj = Array::Handle();
874 array_obj ^= obj.raw(); 885 array_obj ^= obj.raw();
875 *len = array_obj.Length(); 886 *len = array_obj.Length();
876 return Api::Success(); 887 return Api::Success();
877 } 888 }
878 return Api::Error("Object is not an Array"); 889 // TODO(5526318): Make access to GrowableObjectArray more efficient.
890 // Now check and handle a dart object that implements the List interface.
891 if (obj.IsInstance()) {
892 Instance& instance = Instance::Handle();
893 instance ^= obj.raw();
894 Isolate* isolate = Isolate::Current();
895 ASSERT(isolate != NULL);
896 const Type& type = Type::Handle(isolate->object_store()->list_interface());
897 if (instance.Is(type)) {
898 String& name = String::Handle(String::New("length"));
899 name = Field::GetterName(name);
900 const Function& function = Function::Handle(
901 Resolver::ResolveDynamic(instance, name, 1, 0));
902 if (!function.IsNull()) {
903 GrowableArray<const Object*> args(0);
904 LongJump* base = isolate->long_jump_base();
905 LongJump jump;
906 isolate->set_long_jump_base(&jump);
907 Dart_Handle result;
908 if (setjmp(*jump.Set()) == 0) {
909 const Array& kNoArgumentNames = Array::Handle();
910 const Instance& retval = Instance::Handle(
911 DartEntry::InvokeDynamic(instance,
912 function,
913 args,
914 kNoArgumentNames));
915 result = Api::Success();
916 if (retval.IsSmi() || retval.IsMint()) {
917 Integer& integer = Integer::Handle();
918 integer ^= retval.raw();
919 *len = integer.AsInt64Value();
920 } else if (retval.IsBigint()) {
921 Bigint& bigint = Bigint::Handle();
922 bigint ^= retval.raw();
923 if (BigintOperations::FitsIntoInt64(bigint)) {
924 *len = BigintOperations::ToInt64(bigint);
925 } else {
926 result = Api::Error("Object has an Invalid length");
turnidge 2011/10/27 21:29:46 Is it possible to create a List at the Dart level
siva 2011/10/31 20:30:49 Yes it is possible that an arbitrary List implemen
927 }
928 } else {
929 result = Api::Error("Object has an Invalid length");
turnidge 2011/10/27 21:29:46 Invalid -> "non-integer"?
siva 2011/10/31 20:30:49 Done.
930 }
931 } else {
932 SetupErrorResult(&result);
933 }
934 isolate->set_long_jump_base(base);
935 return result;
936 }
937 }
938 }
939 return Api::Error("Object does not implement the list inteface");
940 }
941
942
943 static RawObject* GetArrayAt(const Instance& instance,
944 const Integer& index,
945 const Function& function,
946 Dart_Handle* result) {
947 Isolate* isolate = Isolate::Current();
948 ASSERT(isolate != NULL);
949 ASSERT(result != NULL);
950 LongJump* base = isolate->long_jump_base();
Mads Ager (google) 2011/10/28 07:50:18 Maybe a scoped object would be nice for this at so
siva 2011/10/31 20:30:49 Yes Todd had indicated the same thing, he is going
951 LongJump jump;
952 isolate->set_long_jump_base(&jump);
953 if (setjmp(*jump.Set()) == 0) {
954 Instance& retval = Instance::Handle();
955 GrowableArray<const Object*> args(0);
956 args.Add(&index);
957 const Array& kNoArgumentNames = Array::Handle();
958 retval = DartEntry::InvokeDynamic(instance,
959 function,
960 args,
961 kNoArgumentNames);
962 if (retval.IsUnhandledException()) {
963 *result = Api::Error("Invalid implementation of '[]'");
turnidge 2011/10/27 21:29:46 What do you think of a more informative error mess
siva 2011/10/31 20:30:49 Done.
964 } else {
965 *result = Api::Success();
966 }
967 isolate->set_long_jump_base(base);
968 return retval.raw();
969 }
970 SetupErrorResult(result);
971 isolate->set_long_jump_base(base);
972 return Object::null();
879 } 973 }
880 974
881 975
882 DART_EXPORT Dart_Handle Dart_ArrayGet(Dart_Handle array, 976 DART_EXPORT Dart_Handle Dart_ArrayGet(Dart_Handle array,
883 intptr_t offset, 977 intptr_t offset,
884 uint8_t* native_array, 978 uint8_t* native_array,
885 intptr_t length) { 979 intptr_t length) {
886 Zone zone; // Setup a VM zone as we are creating some handles. 980 Zone zone; // Setup a VM zone as we are creating some handles.
887 HandleScope scope; // Setup a VM handle scope. 981 HandleScope scope; // Setup a VM handle scope.
888 const Object& obj = Object::Handle(Api::UnwrapHandle(array)); 982 const Object& obj = Object::Handle(Api::UnwrapHandle(array));
889 if (obj.IsArray()) { 983 if (obj.IsArray()) {
890 Array& array_obj = Array::Handle(); 984 Array& array_obj = Array::Handle();
891 array_obj ^= obj.raw(); 985 array_obj ^= obj.raw();
892 if ((offset + length) <= array_obj.Length()) { 986 if ((offset + length) <= array_obj.Length()) {
893 Object& element = Object::Handle(); 987 Object& element = Object::Handle();
894 Integer& integer = Integer::Handle(); 988 Integer& integer = Integer::Handle();
895 for (int i = 0; i < length; i++) { 989 for (int i = 0; i < length; i++) {
896 element = array_obj.At(offset + i); 990 element = array_obj.At(offset + i);
897 integer ^= element.raw(); 991 integer ^= element.raw();
898 native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff); 992 native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff);
899 ASSERT(integer.AsInt64Value() <= 0xff); 993 ASSERT(integer.AsInt64Value() <= 0xff);
900 // TODO(hpayer): value should always be smaller then 0xff. Add error 994 // TODO(hpayer): value should always be smaller then 0xff. Add error
901 // handling. 995 // handling.
902 } 996 }
903 return Api::Success(); 997 return Api::Success();
904 } 998 }
905 return Api::Error("Invalid length passed in to access array elements"); 999 return Api::Error("Invalid length passed in to access array elements");
906 } 1000 }
907 return Api::Error("Object is not an Array"); 1001 // TODO(5526318): Make access to GrowableObjectArray more efficient.
1002 // Now check and handle a dart object that implements the List interface.
1003 if (obj.IsInstance()) {
1004 Instance& instance = Instance::Handle();
1005 instance ^= obj.raw();
1006 Isolate* isolate = Isolate::Current();
1007 ASSERT(isolate != NULL);
1008 const Type& type = Type::Handle(isolate->object_store()->list_interface());
1009 if (instance.Is(type)) {
1010 String& name = String::Handle(String::New("[]"));
turnidge 2011/10/27 21:29:46 An aside: it will be nice when we can start using
siva 2011/10/31 20:30:49 Agree, there is a TODO somewhere in the VM code fo
1011 const Function& function = Function::Handle(
1012 Resolver::ResolveDynamic(instance, name, 2, 0));
1013 if (!function.IsNull()) {
1014 Object& element = Object::Handle();
1015 Integer& intobj = Integer::Handle();
1016 Dart_Handle result;
1017 for (int i = 0; i < length; i++) {
1018 intobj = Integer::New(offset + i);
1019 element = GetArrayAt(instance, intobj, function, &result);
1020 if (!Dart_IsValid(result)) {
1021 return result; // Error condition.
1022 }
1023 intobj ^= element.raw();
1024 ASSERT(intobj.AsInt64Value() <= 0xff);
1025 // TODO(hpayer): value should always be smaller then 0xff. Add error
1026 // handling.
1027 native_array[i] = static_cast<uint8_t>(intobj.AsInt64Value() & 0xff);
1028 }
1029 return Api::Success();
1030 }
1031 }
1032 }
1033 return Api::Error("Object does not implement the List interface");
908 } 1034 }
909 1035
910 1036
911 DART_EXPORT Dart_Handle Dart_ArrayGetAt(Dart_Handle array, intptr_t index) { 1037 DART_EXPORT Dart_Handle Dart_ArrayGetAt(Dart_Handle array, intptr_t index) {
912 Zone zone; // Setup a VM zone as we are creating some handles. 1038 Zone zone; // Setup a VM zone as we are creating some handles.
913 HandleScope scope; // Setup a VM handle scope. 1039 HandleScope scope; // Setup a VM handle scope.
914 const Object& obj = Object::Handle(Api::UnwrapHandle(array)); 1040 const Object& obj = Object::Handle(Api::UnwrapHandle(array));
915 if (obj.IsArray()) { 1041 if (obj.IsArray()) {
916 Array& array_obj = Array::Handle(); 1042 Array& array_obj = Array::Handle();
917 array_obj ^= obj.raw(); 1043 array_obj ^= obj.raw();
918 if ((index >= 0) && (index < array_obj.Length())) { 1044 if ((index >= 0) && (index < array_obj.Length())) {
919 const Object& element = Object::Handle(array_obj.At(index)); 1045 const Object& element = Object::Handle(array_obj.At(index));
920 return Api::NewLocalHandle(element); 1046 return Api::NewLocalHandle(element);
921 } 1047 }
922 return Api::Error("Invalid index passed in to access array element"); 1048 return Api::Error("Invalid index passed in to access array element");
923 } 1049 }
1050 // TODO(5526318): Make access to GrowableObjectArray more efficient.
1051 // Now check and handle a dart object that implements the List interface.
1052 if (obj.IsInstance()) {
1053 Instance& instance = Instance::Handle();
1054 instance ^= obj.raw();
1055 Isolate* isolate = Isolate::Current();
1056 ASSERT(isolate != NULL);
1057 const Type& type = Type::Handle(isolate->object_store()->list_interface());
1058 if (instance.Is(type)) {
1059 String& name = String::Handle(String::New("[]"));
1060 const Function& function = Function::Handle(
1061 Resolver::ResolveDynamic(instance, name, 2, 0));
1062 if (!function.IsNull()) {
1063 Object& element = Object::Handle();
1064 Integer& indexobj = Integer::Handle();
1065 Dart_Handle result;
1066 indexobj = Integer::New(index);
1067 element = GetArrayAt(instance, indexobj, function, &result);
1068 if (!Dart_IsValid(result)) {
1069 return result; // Error condition.
1070 }
1071 return Api::NewLocalHandle(element);
1072 }
1073 }
1074 }
924 return Api::Error("Object is not an Array"); 1075 return Api::Error("Object is not an Array");
turnidge 2011/10/27 21:29:46 Inconsistent w/ error msg above -> "Object does no
siva 2011/10/31 20:30:49 Done.
925 } 1076 }
926 1077
927 1078
1079 static void SetArrayAt(const Instance& instance,
1080 const Integer& index,
1081 const Object& value,
1082 const Function& function,
1083 Dart_Handle* result) {
1084 Isolate* isolate = Isolate::Current();
1085 ASSERT(isolate != NULL);
1086 ASSERT(result != NULL);
1087 LongJump* base = isolate->long_jump_base();
1088 LongJump jump;
1089 isolate->set_long_jump_base(&jump);
1090 if (setjmp(*jump.Set()) == 0) {
1091 GrowableArray<const Object*> args(1);
1092 args.Add(&index);
1093 args.Add(&value);
1094 Instance& retval = Instance::Handle();
1095 const Array& kNoArgumentNames = Array::Handle();
1096 retval = DartEntry::InvokeDynamic(instance,
1097 function,
1098 args,
1099 kNoArgumentNames);
1100 if (retval.IsUnhandledException()) {
1101 *result = Api::Error("Invalid implementation of '[]='");
turnidge 2011/10/27 21:29:46 Maybe different error msg here?
siva 2011/10/31 20:30:49 Done.
1102 } else {
1103 *result = Api::Success();
1104 }
1105 } else {
1106 SetupErrorResult(result);
1107 }
1108 isolate->set_long_jump_base(base);
1109 }
1110
1111
928 DART_EXPORT Dart_Handle Dart_ArraySet(Dart_Handle array, 1112 DART_EXPORT Dart_Handle Dart_ArraySet(Dart_Handle array,
929 intptr_t offset, 1113 intptr_t offset,
930 uint8_t* native_array, 1114 uint8_t* native_array,
931 intptr_t length) { 1115 intptr_t length) {
932 Zone zone; 1116 Zone zone;
933 HandleScope scope; 1117 HandleScope scope;
934 const Object& obj = Object::Handle(Api::UnwrapHandle(array)); 1118 const Object& obj = Object::Handle(Api::UnwrapHandle(array));
935 if (obj.IsArray()) { 1119 if (obj.IsArray()) {
936 Array& array_obj = Array::Handle(); 1120 Array& array_obj = Array::Handle();
937 array_obj ^= obj.raw(); 1121 array_obj ^= obj.raw();
938 Integer& integer = Integer::Handle(); 1122 Integer& integer = Integer::Handle();
939 if ((offset + length) <= array_obj.Length()) { 1123 if ((offset + length) <= array_obj.Length()) {
940 for (int i = 0; i < length; i++) { 1124 for (int i = 0; i < length; i++) {
941 integer ^= Integer::New(native_array[i]); 1125 integer ^= Integer::New(native_array[i]);
942 array_obj.SetAt(offset + i, integer); 1126 array_obj.SetAt(offset + i, integer);
943 } 1127 }
944 return Api::Success(); 1128 return Api::Success();
945 } 1129 }
946 return Api::Error("Invalid length passed in to set array elements"); 1130 return Api::Error("Invalid length passed in to set array elements");
947 } 1131 }
948 return Api::Error("Object is not an Array"); 1132 // TODO(5526318): Make access to GrowableObjectArray more efficient.
1133 // Now check and handle a dart object that implements the List interface.
1134 if (obj.IsInstance()) {
1135 Instance& instance = Instance::Handle();
1136 instance ^= obj.raw();
1137 Isolate* isolate = Isolate::Current();
1138 ASSERT(isolate != NULL);
1139 const Type& type = Type::Handle(isolate->object_store()->list_interface());
turnidge 2011/10/27 21:29:46 We are checking whether an object is a list many t
siva 2011/10/31 20:30:49 Done.
1140 if (instance.Is(type)) {
1141 String& name = String::Handle(String::New("[]="));
1142 const Function& function = Function::Handle(
1143 Resolver::ResolveDynamic(instance, name, 3, 0));
1144 if (!function.IsNull()) {
1145 Integer& indexobj = Integer::Handle();
1146 Integer& valueobj = Integer::Handle();
1147 Dart_Handle result;
1148 for (int i = 0; i < length; i++) {
1149 indexobj = Integer::New(offset + i);
1150 valueobj ^= Integer::New(native_array[i]);
1151 SetArrayAt(instance, indexobj, valueobj, function, &result);
1152 if (!Dart_IsValid(result)) {
1153 return result; // Error condition.
1154 }
1155 }
1156 return Api::Success();
1157 }
1158 }
1159 }
1160 return Api::Error("Object does not implement the list interface");
949 } 1161 }
950 1162
1163
951 DART_EXPORT Dart_Handle Dart_ArraySetAt(Dart_Handle array, 1164 DART_EXPORT Dart_Handle Dart_ArraySetAt(Dart_Handle array,
952 intptr_t index, 1165 intptr_t index,
953 Dart_Handle value) { 1166 Dart_Handle value) {
954 Zone zone; // Setup a VM zone as we are creating some handles. 1167 Zone zone; // Setup a VM zone as we are creating some handles.
955 HandleScope scope; // Setup a VM handle scope. 1168 HandleScope scope; // Setup a VM handle scope.
956 const Object& obj = Object::Handle(Api::UnwrapHandle(array)); 1169 const Object& obj = Object::Handle(Api::UnwrapHandle(array));
957 if (obj.IsArray()) { 1170 if (obj.IsArray()) {
958 Array& array_obj = Array::Handle(); 1171 Array& array_obj = Array::Handle();
959 array_obj ^= obj.raw(); 1172 array_obj ^= obj.raw();
960 const Object& value_obj = Object::Handle(Api::UnwrapHandle(value)); 1173 const Object& value_obj = Object::Handle(Api::UnwrapHandle(value));
961 if ((index >= 0) && (index < array_obj.Length())) { 1174 if ((index >= 0) && (index < array_obj.Length())) {
962 array_obj.SetAt(index, value_obj); 1175 array_obj.SetAt(index, value_obj);
963 return Api::Success(); 1176 return Api::Success();
964 } 1177 }
965 return Api::Error("Invalid index passed in to set array element"); 1178 return Api::Error("Invalid index passed in to set array element");
966 } 1179 }
967 return Api::Error("Object is not an Array"); 1180 // TODO(5526318): Make access to GrowableObjectArray more efficient.
1181 // Now check and handle a dart object that implements the List interface.
1182 if (obj.IsInstance()) {
1183 Instance& instance = Instance::Handle();
1184 instance ^= obj.raw();
1185 Isolate* isolate = Isolate::Current();
1186 ASSERT(isolate != NULL);
1187 const Type& type = Type::Handle(isolate->object_store()->list_interface());
1188 if (instance.Is(type)) {
1189 String& name = String::Handle(String::New("[]="));
1190 const Function& function = Function::Handle(
1191 Resolver::ResolveDynamic(instance, name, 3, 0));
1192 if (!function.IsNull()) {
1193 Dart_Handle result;
1194 const Integer& index_obj = Integer::Handle(Integer::New(index));
1195 const Object& value_obj = Object::Handle(Api::UnwrapHandle(value));
1196 SetArrayAt(instance, index_obj, value_obj, function, &result);
1197 return result;
1198 }
1199 }
1200 }
1201 return Api::Error("Object does not implement the list interface");
968 } 1202 }
969 1203
970 1204
971 // NOTE: Need to pass 'result' as a parameter here in order to avoid 1205 // NOTE: Need to pass 'result' as a parameter here in order to avoid
972 // warning: variable 'result' might be clobbered by 'longjmp' or 'vfork' 1206 // warning: variable 'result' might be clobbered by 'longjmp' or 'vfork'
973 // which shows up because of the use of setjmp. 1207 // which shows up because of the use of setjmp.
974 static void InvokeStatic(const Function& function, 1208 static void InvokeStatic(const Function& function,
975 GrowableArray<const Object*>& args, 1209 GrowableArray<const Object*>& args,
976 Dart_Handle* result) { 1210 Dart_Handle* result) {
977 Isolate* isolate = Isolate::Current(); 1211 Isolate* isolate = Isolate::Current();
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 ASSERT(isolate != NULL); 2007 ASSERT(isolate != NULL);
1774 ApiState* state = isolate->api_state(); 2008 ApiState* state = isolate->api_state();
1775 ASSERT(state != NULL); 2009 ASSERT(state != NULL);
1776 ApiLocalScope* scope = state->top_scope(); 2010 ApiLocalScope* scope = state->top_scope();
1777 ASSERT(scope != NULL); 2011 ASSERT(scope != NULL);
1778 return scope->zone().Reallocate(ptr, old_size, new_size); 2012 return scope->zone().Reallocate(ptr, old_size, new_size);
1779 } 2013 }
1780 2014
1781 2015
1782 } // namespace dart 2016 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | vm/dart_api_impl_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698