OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "lib/invocation_mirror.h" | 5 #include "lib/invocation_mirror.h" |
6 #include "vm/bootstrap_natives.h" | 6 #include "vm/bootstrap_natives.h" |
7 #include "vm/class_finalizer.h" | 7 #include "vm/class_finalizer.h" |
8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
9 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
11 #include "vm/parser.h" | |
11 #include "vm/port.h" | 12 #include "vm/port.h" |
12 #include "vm/symbols.h" | 13 #include "vm/symbols.h" |
13 | 14 |
14 namespace dart { | 15 namespace dart { |
15 | 16 |
16 static RawInstance* CreateMirror(const String& mirror_class_name, | 17 static RawInstance* CreateMirror(const String& mirror_class_name, |
17 const Array& constructor_arguments) { | 18 const Array& constructor_arguments) { |
18 const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary()); | 19 const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary()); |
19 const String& constructor_name = Symbols::Dot(); | 20 const String& constructor_name = Symbols::Dot(); |
20 | 21 |
21 const Object& result = Object::Handle( | 22 const Object& result = Object::Handle( |
22 DartLibraryCalls::InstanceCreate(mirrors_lib, | 23 DartLibraryCalls::InstanceCreate(mirrors_lib, |
23 mirror_class_name, | 24 mirror_class_name, |
24 constructor_name, | 25 constructor_name, |
25 constructor_arguments)); | 26 constructor_arguments)); |
26 ASSERT(!result.IsError()); | 27 ASSERT(!result.IsError()); |
27 return Instance::Cast(result).raw(); | 28 return Instance::Cast(result).raw(); |
28 } | 29 } |
29 | 30 |
30 | 31 |
32 // Note a "raw type" is not the same as a RawType. | |
33 static RawAbstractType* RawTypeOfClass(const Class& cls) { | |
34 Type& type = Type::Handle(Type::New(cls, | |
35 Object::null_abstract_type_arguments(), | |
36 Scanner::kDummyTokenIndex)); | |
37 return ClassFinalizer::FinalizeType(cls, type, ClassFinalizer::kCanonicalize); | |
38 } | |
39 | |
40 | |
41 static void ThrowMirroredCompilationError(const String& message) { | |
42 Array& args = Array::Handle(Array::New(1)); | |
43 args.SetAt(0, message); | |
44 | |
45 Exceptions::ThrowByType(Exceptions::kMirroredCompilationError, args); | |
46 UNREACHABLE(); | |
47 } | |
48 | |
49 | |
50 static void ThrowInvokeError(const Error& error) { | |
51 if (error.IsLanguageError()) { | |
52 // A compilation error that was delayed by lazy compilation. | |
53 const LanguageError& compilation_error = LanguageError::Cast(error); | |
54 String& message = String::Handle(compilation_error.message()); | |
55 ThrowMirroredCompilationError(message); | |
56 UNREACHABLE(); | |
57 } | |
58 Exceptions::PropagateError(error); | |
59 UNREACHABLE(); | |
60 } | |
61 | |
62 | |
63 static void ThrowNoSuchMethod(const Instance& receiver, | |
64 const String& function_name, | |
65 const Function& function, | |
66 const InvocationMirror::Call call, | |
67 const InvocationMirror::Type type) { | |
68 const Smi& invocation_type = Smi::Handle(Smi::New( | |
69 InvocationMirror::EncodeType(call, type))); | |
70 | |
71 const Array& args = Array::Handle(Array::New(6)); | |
72 args.SetAt(0, receiver); | |
73 args.SetAt(1, function_name); | |
74 args.SetAt(2, invocation_type); | |
75 if (!function.IsNull()) { | |
76 const int total_num_parameters = function.NumParameters(); | |
77 const Array& array = Array::Handle(Array::New(total_num_parameters)); | |
78 String& param_name = String::Handle(); | |
79 for (int i = 0; i < total_num_parameters; i++) { | |
80 param_name = function.ParameterNameAt(i); | |
81 array.SetAt(i, param_name); | |
82 } | |
siva
2013/08/26 05:05:43
What about args 3 and 4, you should document those
Michael Lippautz (Google)
2013/08/26 19:45:57
Done.
| |
83 args.SetAt(5, array); | |
84 } | |
85 | |
86 Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args); | |
87 UNREACHABLE(); | |
88 } | |
89 | |
90 | |
91 static void ThrowNoSuchMethod(const Class& klass, | |
92 const String& function_name, | |
93 const Function& function, | |
94 const InvocationMirror::Call call, | |
95 const InvocationMirror::Type type) { | |
96 AbstractType& runtime_type = AbstractType::Handle(RawTypeOfClass(klass)); | |
97 | |
98 ThrowNoSuchMethod(runtime_type, | |
99 function_name, | |
100 function, | |
101 call, | |
102 type); | |
103 UNREACHABLE(); | |
104 } | |
105 | |
106 | |
107 static void ThrowNoSuchMethod(const Library& library, | |
108 const String& function_name, | |
109 const Function& function, | |
110 const InvocationMirror::Call call, | |
111 const InvocationMirror::Type type) { | |
112 ThrowNoSuchMethod(Instance::null_instance(), | |
113 function_name, | |
114 function, | |
115 call, | |
116 type); | |
117 UNREACHABLE(); | |
118 } | |
siva
2013/08/26 05:05:43
Not sure if it is worth having so many overloaded
Michael Lippautz (Google)
2013/08/26 19:45:57
Done.
| |
119 | |
120 | |
31 DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) { | 121 DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) { |
32 GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0)); | 122 GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0)); |
33 | 123 |
34 // Get the port id from the SendPort instance. | 124 // Get the port id from the SendPort instance. |
35 const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port)); | 125 const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port)); |
36 if (id_obj.IsError()) { | 126 if (id_obj.IsError()) { |
37 Exceptions::PropagateError(Error::Cast(id_obj)); | 127 Exceptions::PropagateError(Error::Cast(id_obj)); |
38 UNREACHABLE(); | 128 UNREACHABLE(); |
39 } | 129 } |
40 ASSERT(id_obj.IsSmi() || id_obj.IsMint()); | 130 ASSERT(id_obj.IsSmi() || id_obj.IsMint()); |
41 Integer& id = Integer::Handle(); | 131 Integer& id = Integer::Handle(); |
42 id ^= id_obj.raw(); | 132 id ^= id_obj.raw(); |
43 Dart_Port port_id = static_cast<Dart_Port>(id.AsInt64Value()); | 133 Dart_Port port_id = static_cast<Dart_Port>(id.AsInt64Value()); |
44 return Bool::Get(PortMap::IsLocalPort(port_id)); | 134 return Bool::Get(PortMap::IsLocalPort(port_id)); |
45 } | 135 } |
46 | 136 |
47 | 137 |
48 static RawInstance* CreateParameterMirrorList(const Function& func, | 138 static RawInstance* CreateParameterMirrorList(const Function& func, |
49 const Instance& owner_mirror) { | 139 const Instance& owner_mirror) { |
50 HANDLESCOPE(Isolate::Current()); | 140 HANDLESCOPE(Isolate::Current()); |
51 const intptr_t implicit_param_count = func.NumImplicitParameters(); | 141 const intptr_t implicit_param_count = func.NumImplicitParameters(); |
52 const intptr_t non_implicit_param_count = func.NumParameters() - | 142 const intptr_t non_implicit_param_count = func.NumParameters() - |
53 implicit_param_count; | 143 implicit_param_count; |
54 const intptr_t index_of_first_optional_param = | 144 const intptr_t index_of_first_optional_param = |
55 non_implicit_param_count - func.NumOptionalParameters(); | 145 non_implicit_param_count - func.NumOptionalParameters(); |
56 const intptr_t index_of_first_named_param = | 146 const intptr_t index_of_first_named_param = |
57 non_implicit_param_count - func.NumOptionalNamedParameters(); | 147 non_implicit_param_count - func.NumOptionalNamedParameters(); |
58 const Array& results = Array::Handle(Array::New(non_implicit_param_count)); | 148 const Array& results = Array::Handle(Array::New(non_implicit_param_count)); |
59 const Array& args = Array::Handle(Array::New(6)); | 149 const Array& args = Array::Handle(Array::New(8)); |
150 | |
151 // Return for synthetic functions and getters. | |
152 if (func.IsGetterFunction() || | |
153 func.IsImplicitConstructor() || | |
154 func.IsImplicitGetterFunction() || | |
155 func.IsImplicitSetterFunction()) { | |
156 return results.raw(); | |
157 } | |
158 | |
60 args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func))); | 159 args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func))); |
61 args.SetAt(2, owner_mirror); | 160 args.SetAt(2, owner_mirror); |
161 | |
62 Smi& pos = Smi::Handle(); | 162 Smi& pos = Smi::Handle(); |
63 String& name = String::Handle(); | 163 String& name = String::Handle(); |
64 Instance& param = Instance::Handle(); | 164 Instance& param = Instance::Handle(); |
165 Bool& is_final = Bool::Handle(); | |
166 Object& default_value = Object::Handle(); | |
167 | |
168 // Reparse the function for the following information: | |
169 // * The default value of a parameter. | |
170 // * Whether a parameters has been deflared as final. | |
171 const Object& result = Object::Handle(Parser::ParseFunctionParameters(func)); | |
172 if (result.IsError()) { | |
173 ThrowInvokeError(Error::Cast(result)); | |
174 UNREACHABLE(); | |
175 } | |
176 | |
177 const Array& param_descriptor = Array::Cast(result); | |
siva
2013/08/26 05:05:43
We normally use the Cast operator only after an if
Michael Lippautz (Google)
2013/08/26 19:45:57
result is either an error (which checked above) or
siva
2013/08/27 00:31:02
Ok.
On 2013/08/26 19:45:57, Michael Lippautz wrot
| |
178 ASSERT(param_descriptor.Length() == (2 * non_implicit_param_count)); | |
65 for (intptr_t i = 0; i < non_implicit_param_count; i++) { | 179 for (intptr_t i = 0; i < non_implicit_param_count; i++) { |
66 pos ^= Smi::New(i); | 180 pos ^= Smi::New(i); |
67 name ^= func.ParameterNameAt(implicit_param_count + i); | 181 name ^= func.ParameterNameAt(implicit_param_count + i); |
182 is_final ^= param_descriptor.At(i * 2); | |
183 default_value = param_descriptor.At(i * 2 + 1); | |
184 ASSERT(default_value.IsNull() || default_value.IsInstance()); | |
185 | |
68 args.SetAt(1, name); | 186 args.SetAt(1, name); |
69 args.SetAt(3, pos); | 187 args.SetAt(3, pos); |
70 args.SetAt(4, (i >= index_of_first_optional_param) ? | 188 args.SetAt(4, (i >= index_of_first_optional_param) ? |
71 Bool::True() : Bool::False()); | 189 Bool::True() : Bool::False()); |
72 args.SetAt(5, (i >= index_of_first_named_param) ? | 190 args.SetAt(5, (i >= index_of_first_named_param) ? |
73 Bool::True() : Bool::False()); | 191 Bool::True() : Bool::False()); |
192 args.SetAt(6, is_final); | |
193 args.SetAt(7, default_value); | |
74 param ^= CreateMirror(Symbols::_LocalParameterMirrorImpl(), args); | 194 param ^= CreateMirror(Symbols::_LocalParameterMirrorImpl(), args); |
75 results.SetAt(i, param); | 195 results.SetAt(i, param); |
76 } | 196 } |
77 results.MakeImmutable(); | 197 results.MakeImmutable(); |
78 return results.raw(); | 198 return results.raw(); |
79 } | 199 } |
80 | 200 |
81 | 201 |
82 static RawInstance* CreateTypeVariableMirror(const TypeParameter& param, | 202 static RawInstance* CreateTypeVariableMirror(const TypeParameter& param, |
83 const Instance& owner_mirror) { | 203 const Instance& owner_mirror) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 | 322 |
203 const Array& args = Array::Handle(Array::New(4)); | 323 const Array& args = Array::Handle(Array::New(4)); |
204 args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls))); | 324 args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls))); |
205 args.SetAt(1, type); | 325 args.SetAt(1, type); |
206 args.SetAt(2, String::Handle(cls.UserVisibleName())); | 326 args.SetAt(2, String::Handle(cls.UserVisibleName())); |
207 args.SetAt(3, is_generic); | 327 args.SetAt(3, is_generic); |
208 return CreateMirror(Symbols::_LocalClassMirrorImpl(), args); | 328 return CreateMirror(Symbols::_LocalClassMirrorImpl(), args); |
209 } | 329 } |
210 | 330 |
211 | 331 |
212 // Note a "raw type" is not the same as a RawType. | |
213 static RawAbstractType* RawTypeOfClass(const Class& cls) { | |
214 Type& type = Type::Handle(Type::New(cls, | |
215 Object::null_abstract_type_arguments(), | |
216 Scanner::kDummyTokenIndex)); | |
217 return ClassFinalizer::FinalizeType(cls, type, ClassFinalizer::kCanonicalize); | |
218 } | |
219 | |
220 | |
221 static RawInstance* CreateLibraryMirror(const Library& lib) { | 332 static RawInstance* CreateLibraryMirror(const Library& lib) { |
222 const Array& args = Array::Handle(Array::New(3)); | 333 const Array& args = Array::Handle(Array::New(3)); |
223 args.SetAt(0, MirrorReference::Handle(MirrorReference::New(lib))); | 334 args.SetAt(0, MirrorReference::Handle(MirrorReference::New(lib))); |
224 String& str = String::Handle(); | 335 String& str = String::Handle(); |
225 str = lib.name(); | 336 str = lib.name(); |
226 args.SetAt(1, str); | 337 args.SetAt(1, str); |
227 str = lib.url(); | 338 str = lib.url(); |
228 args.SetAt(2, str); | 339 args.SetAt(2, str); |
229 return CreateMirror(Symbols::_LocalLibraryMirrorImpl(), args); | 340 return CreateMirror(Symbols::_LocalLibraryMirrorImpl(), args); |
230 } | 341 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 } | 428 } |
318 } | 429 } |
319 | 430 |
320 | 431 |
321 DEFINE_NATIVE_ENTRY(Mirrors_makeLocalTypeMirror, 1) { | 432 DEFINE_NATIVE_ENTRY(Mirrors_makeLocalTypeMirror, 1) { |
322 GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0)); | 433 GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0)); |
323 return CreateTypeMirror(type); | 434 return CreateTypeMirror(type); |
324 } | 435 } |
325 | 436 |
326 | 437 |
327 static void ThrowMirroredCompilationError(const String& message) { | |
328 Array& args = Array::Handle(Array::New(1)); | |
329 args.SetAt(0, message); | |
330 | |
331 Exceptions::ThrowByType(Exceptions::kMirroredCompilationError, args); | |
332 UNREACHABLE(); | |
333 } | |
334 | |
335 | |
336 static void ThrowInvokeError(const Error& error) { | |
337 if (error.IsLanguageError()) { | |
338 // A compilation error that was delayed by lazy compilation. | |
339 const LanguageError& compilation_error = LanguageError::Cast(error); | |
340 String& message = String::Handle(compilation_error.message()); | |
341 ThrowMirroredCompilationError(message); | |
342 UNREACHABLE(); | |
343 } | |
344 Exceptions::PropagateError(error); | |
345 UNREACHABLE(); | |
346 } | |
347 | |
348 | |
349 DEFINE_NATIVE_ENTRY(MirrorReference_equals, 2) { | 438 DEFINE_NATIVE_ENTRY(MirrorReference_equals, 2) { |
350 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, a, arguments->NativeArgAt(0)); | 439 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, a, arguments->NativeArgAt(0)); |
351 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, b, arguments->NativeArgAt(1)); | 440 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, b, arguments->NativeArgAt(1)); |
352 return Bool::Get(a.referent() == b.referent()); | 441 return Bool::Get(a.referent() == b.referent()); |
353 } | 442 } |
354 | 443 |
355 | 444 |
356 DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) { | 445 DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) { |
357 const MirrorReference& decl_ref = | 446 const MirrorReference& decl_ref = |
358 MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); | 447 MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
834 ASSERT(!closure.IsNull()); | 923 ASSERT(!closure.IsNull()); |
835 | 924 |
836 Function& function = Function::Handle(); | 925 Function& function = Function::Handle(); |
837 bool callable = closure.IsCallable(&function, NULL); | 926 bool callable = closure.IsCallable(&function, NULL); |
838 ASSERT(callable); | 927 ASSERT(callable); |
839 | 928 |
840 return CreateMethodMirror(function, Instance::null_instance()); | 929 return CreateMethodMirror(function, Instance::null_instance()); |
841 } | 930 } |
842 | 931 |
843 | 932 |
844 static void ThrowNoSuchMethod(const Instance& receiver, | |
845 const String& function_name, | |
846 const Function& function, | |
847 const InvocationMirror::Call call, | |
848 const InvocationMirror::Type type) { | |
849 const Smi& invocation_type = Smi::Handle(Smi::New( | |
850 InvocationMirror::EncodeType(call, type))); | |
851 | |
852 const Array& args = Array::Handle(Array::New(6)); | |
853 args.SetAt(0, receiver); | |
854 args.SetAt(1, function_name); | |
855 args.SetAt(2, invocation_type); | |
856 if (!function.IsNull()) { | |
857 const int total_num_parameters = function.NumParameters(); | |
858 const Array& array = Array::Handle(Array::New(total_num_parameters)); | |
859 String& param_name = String::Handle(); | |
860 for (int i = 0; i < total_num_parameters; i++) { | |
861 param_name = function.ParameterNameAt(i); | |
862 array.SetAt(i, param_name); | |
863 } | |
864 args.SetAt(5, array); | |
865 } | |
866 | |
867 Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args); | |
868 UNREACHABLE(); | |
869 } | |
870 | |
871 | |
872 static void ThrowNoSuchMethod(const Class& klass, | |
873 const String& function_name, | |
874 const Function& function, | |
875 const InvocationMirror::Call call, | |
876 const InvocationMirror::Type type) { | |
877 AbstractType& runtime_type = AbstractType::Handle(RawTypeOfClass(klass)); | |
878 | |
879 ThrowNoSuchMethod(runtime_type, | |
880 function_name, | |
881 function, | |
882 call, | |
883 type); | |
884 UNREACHABLE(); | |
885 } | |
886 | |
887 | |
888 static void ThrowNoSuchMethod(const Library& library, | |
889 const String& function_name, | |
890 const Function& function, | |
891 const InvocationMirror::Call call, | |
892 const InvocationMirror::Type type) { | |
893 ThrowNoSuchMethod(Instance::null_instance(), | |
894 function_name, | |
895 function, | |
896 call, | |
897 type); | |
898 UNREACHABLE(); | |
899 } | |
900 | |
901 | |
902 DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) { | 933 DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) { |
903 // Argument 0 is the mirror, which is unused by the native. It exists | 934 // Argument 0 is the mirror, which is unused by the native. It exists |
904 // because this native is an instance method in order to be polymorphic | 935 // because this native is an instance method in order to be polymorphic |
905 // with its cousins. | 936 // with its cousins. |
906 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1)); | 937 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1)); |
907 const Class& klass = Class::Handle(ref.GetClassReferent()); | 938 const Class& klass = Class::Handle(ref.GetClassReferent()); |
908 GET_NON_NULL_NATIVE_ARGUMENT( | 939 GET_NON_NULL_NATIVE_ARGUMENT( |
909 String, function_name, arguments->NativeArgAt(2)); | 940 String, function_name, arguments->NativeArgAt(2)); |
910 GET_NON_NULL_NATIVE_ARGUMENT( | 941 GET_NON_NULL_NATIVE_ARGUMENT( |
911 Array, positional_args, arguments->NativeArgAt(3)); | 942 Array, positional_args, arguments->NativeArgAt(3)); |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1301 } | 1332 } |
1302 | 1333 |
1303 | 1334 |
1304 DEFINE_NATIVE_ENTRY(VariableMirror_type, 1) { | 1335 DEFINE_NATIVE_ENTRY(VariableMirror_type, 1) { |
1305 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0)); | 1336 GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0)); |
1306 const Field& field = Field::Handle(ref.GetFieldReferent()); | 1337 const Field& field = Field::Handle(ref.GetFieldReferent()); |
1307 return field.type(); | 1338 return field.type(); |
1308 } | 1339 } |
1309 | 1340 |
1310 } // namespace dart | 1341 } // namespace dart |
OLD | NEW |