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 "vm/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
6 | 6 |
7 #include "platform/json.h" | 7 #include "platform/json.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/message.h" | 10 #include "vm/message.h" |
11 #include "vm/port.h" | 11 #include "vm/port.h" |
12 #include "vm/resolver.h" | 12 #include "vm/resolver.h" |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
16 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 16 DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) { |
17 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | |
18 return reinterpret_cast<uint8_t*>(new_ptr); | |
19 } | |
20 | |
21 | |
22 DEFINE_NATIVE_ENTRY(Mirrors_send, 3) { | |
23 GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); | 17 GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); |
24 GET_NATIVE_ARGUMENT(Instance, message, arguments->At(1)); | 18 |
25 GET_NATIVE_ARGUMENT(Instance, replyTo, arguments->At(2)); | 19 // Get the port id from the SendPort instance. |
26 | 20 const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port)); |
27 // Get the send port id. | 21 if (id_obj.IsError()) { |
28 Object& result = Object::Handle(); | 22 Exceptions::PropagateError(id_obj); |
29 result = DartLibraryCalls::PortGetId(port); | 23 UNREACHABLE(); |
30 if (result.IsError()) { | 24 } |
31 Exceptions::PropagateError(result); | 25 ASSERT(id_obj.IsSmi() || id_obj.IsMint()); |
32 } | 26 Integer& id = Integer::Handle(); |
33 | 27 id ^= id_obj.raw(); |
34 Integer& value = Integer::Handle(); | 28 Dart_Port port_id = static_cast<Dart_Port>(id.AsInt64Value()); |
35 value ^= result.raw(); | 29 const Bool& is_local = Bool::Handle(Bool::Get(PortMap::IsLocalPort(port_id))); |
36 int64_t send_port_id = value.AsInt64Value(); | 30 arguments->SetReturn(is_local); |
37 | 31 } |
38 // Get the reply port id. | 32 |
39 result = DartLibraryCalls::PortGetId(replyTo); | 33 |
40 if (result.IsError()) { | 34 // TODO(turnidge): Add Map support to the dart embedding api instead |
41 Exceptions::PropagateError(result); | 35 // of implementing it here. |
42 } | 36 static Dart_Handle CoreLib() { |
43 value ^= result.raw(); | 37 Dart_Handle core_lib_name = Dart_NewString("dart:core"); |
44 int64_t reply_port_id = value.AsInt64Value(); | 38 return Dart_LookupLibrary(core_lib_name); |
45 | 39 } |
46 // Construct the message. | 40 |
47 uint8_t* data = NULL; | 41 |
48 SnapshotWriter writer(Snapshot::kMessage, &data, &allocator); | 42 static Dart_Handle MapNew() { |
49 writer.WriteObject(message.raw()); | 43 Dart_Handle cls = Dart_GetClass(CoreLib(), Dart_NewString("Map")); |
50 writer.FinalizeBuffer(); | 44 if (Dart_IsError(cls)) { |
51 | 45 return cls; |
52 // Post the message. | 46 } |
53 bool retval = PortMap::PostMessage(new Message( | 47 return Dart_New(cls, Dart_Null(), 0, NULL); |
54 send_port_id, reply_port_id, data, Message::kOOBPriority)); | 48 } |
55 const Bool& retval_obj = Bool::Handle(Bool::Get(retval)); | 49 |
56 arguments->SetReturn(retval_obj); | 50 |
57 } | 51 static Dart_Handle MapAdd(Dart_Handle map, Dart_Handle key, Dart_Handle value) { |
58 | 52 const int kNumArgs = 2; |
59 | 53 Dart_Handle args[kNumArgs]; |
60 static bool JSONGetString(JSONReader* reader, | 54 args[0] = key; |
61 const char** value_chars, | 55 args[1] = value; |
62 int* value_len) { | 56 return Dart_Invoke(map, Dart_NewString("[]="), kNumArgs, args); |
63 if (reader->Type() != JSONReader::kString) { | 57 } |
64 return false; | 58 |
65 } | 59 |
66 *value_chars = reader->ValueChars(); | 60 static Dart_Handle MapGet(Dart_Handle map, Dart_Handle key) { |
67 *value_len = reader->ValueLen(); | 61 const int kNumArgs = 1; |
68 return true; | 62 Dart_Handle args[kNumArgs]; |
69 } | 63 args[0] = key; |
70 | 64 return Dart_Invoke(map, Dart_NewString("[]"), kNumArgs, args); |
71 | 65 } |
72 DEFINE_NATIVE_ENTRY(Mirrors_processResponse, 3) { | 66 |
73 GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); | 67 |
74 GET_NATIVE_ARGUMENT(String, command, arguments->At(1)); | 68 static Dart_Handle MirrorLib() { |
75 GET_NATIVE_ARGUMENT(String, response, arguments->At(2)); | 69 Dart_Handle mirror_lib_name = Dart_NewString("dart:mirrors"); |
76 | 70 return Dart_LookupLibrary(mirror_lib_name); |
77 const char* json_text = response.ToCString(); | 71 } |
78 if (command.Equals("isolateMirrorOf")) { | 72 |
79 JSONReader reader(json_text); | 73 |
80 const char* debug_name = ""; | 74 static Dart_Handle IsMirror(Dart_Handle object, bool* is_mirror) { |
81 int debug_name_len = 0; | 75 Dart_Handle cls_name = Dart_NewString("Mirror"); |
82 if (!reader.Seek("ok") || !reader.IsTrue() || | 76 Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
83 !reader.Seek("debugName") || | 77 if (Dart_IsError(cls)) { |
84 !JSONGetString(&reader, &debug_name, &debug_name_len)) { | 78 return cls; |
85 // TODO(turnidge): Use an exception class instead of a String. | 79 } |
86 Exceptions::Throw(Instance::Handle(String::NewFormatted( | 80 Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror); |
87 "Error while processing mirror request."))); | 81 if (Dart_IsError(result)) { |
88 UNREACHABLE(); | 82 return result; |
89 } | 83 } |
90 | 84 return Dart_True(); // Indicates success. Result is in is_mirror. |
91 // Create and return a new instance of _IsolateMirrorImpl. | 85 } |
92 Library& lib = Library::Handle(Library::MirrorsLibrary()); | 86 |
93 const String& public_class_name = | 87 |
94 String::Handle(String::NewSymbol("_IsolateMirrorImpl")); | 88 static bool IsSimpleValue(Dart_Handle object) { |
95 const String& class_name = | 89 return (Dart_IsNull(object) || |
96 String::Handle(lib.PrivateName(public_class_name)); | 90 Dart_IsNumber(object) || |
97 const String& function_name = | 91 Dart_IsString(object) || |
98 String::Handle(String::NewSymbol("_make")); | 92 Dart_IsBoolean(object)); |
99 const int kNumArgs = 2; | 93 } |
100 const Array& kNoArgNames = Array::Handle(); | 94 |
101 const Function& function = Function::Handle( | 95 |
102 Resolver::ResolveStatic(lib, | 96 static void FreeVMReference(Dart_Handle weak_ref, void* data) { |
103 class_name, | 97 Dart_Handle perm_handle = reinterpret_cast<Dart_Handle>(data); |
104 function_name, | 98 Dart_DeletePersistentHandle(perm_handle); |
105 kNumArgs, | 99 Dart_DeletePersistentHandle(weak_ref); |
106 kNoArgNames, | 100 } |
107 Resolver::kIsQualified)); | 101 |
108 ASSERT(!function.IsNull()); | 102 |
109 GrowableArray<const Object*> args(kNumArgs); | 103 static Dart_Handle CreateVMReference(Dart_Handle handle) { |
110 args.Add(&port); | 104 // Create the VMReference object. |
111 const String& debug_name_str = String::Handle( | 105 Dart_Handle cls_name = Dart_NewString("VMReference"); |
112 String::NewFormatted("%.*s", debug_name_len, debug_name)); | 106 Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
113 args.Add(&debug_name_str); | 107 if (Dart_IsError(cls)) { |
114 const Object& result = Object::Handle( | 108 return cls; |
115 DartEntry::InvokeStatic(function, args, kNoArgNames)); | 109 } |
116 arguments->SetReturn(result); | 110 Dart_Handle vm_ref = Dart_New(cls, Dart_Null(), 0, NULL); |
117 } | 111 if (Dart_IsError(vm_ref)) { |
118 } | 112 return vm_ref; |
119 | 113 } |
114 | |
115 // Allocate a persistent handle. | |
116 Dart_Handle perm_handle = Dart_NewPersistentHandle(handle); | |
117 if (Dart_IsError(perm_handle)) { | |
118 return perm_handle; | |
119 } | |
120 | |
121 // Store the persistent handle in the VMReference. | |
122 intptr_t perm_handle_value = reinterpret_cast<intptr_t>(perm_handle); | |
123 Dart_Handle result = | |
124 Dart_SetNativeInstanceField(vm_ref, 0, perm_handle_value); | |
125 if (Dart_IsError(result)) { | |
126 Dart_DeletePersistentHandle(perm_handle); | |
127 return result; | |
128 } | |
129 | |
130 // Create a weak reference. We use the callback to be informed when | |
131 // the VMReference is collected, so we can release the persistent | |
132 // handle. | |
133 void* perm_handle_data = reinterpret_cast<void*>(perm_handle); | |
134 Dart_Handle weak_ref = | |
135 Dart_NewWeakPersistentHandle(vm_ref, perm_handle_data, FreeVMReference); | |
136 if (Dart_IsError(weak_ref)) { | |
137 Dart_DeletePersistentHandle(perm_handle); | |
138 return weak_ref; | |
139 } | |
140 | |
141 // Success. | |
142 return vm_ref; | |
143 } | |
144 | |
145 | |
146 static Dart_Handle UnwrapVMReference(Dart_Handle vm_ref) { | |
147 // Retrieve the persistent handle from the VMReference | |
148 intptr_t perm_handle_value = 0; | |
149 Dart_Handle result = | |
150 Dart_GetNativeInstanceField(vm_ref, 0, &perm_handle_value); | |
151 if (Dart_IsError(result)) { | |
152 return result; | |
153 } | |
154 Dart_Handle perm_handle = reinterpret_cast<Dart_Handle>(perm_handle_value); | |
155 ASSERT(!Dart_IsError(perm_handle)); | |
156 return perm_handle; | |
157 } | |
158 | |
159 | |
160 static Dart_Handle UnwrapMirror(Dart_Handle mirror) { | |
161 Dart_Handle field_name = Dart_NewString("_reference"); | |
162 Dart_Handle vm_ref = Dart_GetField(mirror, field_name); | |
163 if (Dart_IsError(vm_ref)) { | |
164 return vm_ref; | |
165 } | |
166 return UnwrapVMReference(vm_ref); | |
167 } | |
168 | |
169 | |
170 static Dart_Handle UnwrapArgList(Dart_Handle arg_list, | |
171 GrowableArray<Dart_Handle>* arg_array) { | |
172 intptr_t len = 0; | |
173 Dart_Handle result = Dart_ListLength(arg_list, &len); | |
174 if (Dart_IsError(result)) { | |
175 return result; | |
176 } | |
177 for (int i = 0; i < len; i++) { | |
178 Dart_Handle arg = Dart_ListGetAt(arg_list, i); | |
179 if (Dart_IsError(arg)) { | |
180 return arg; | |
181 } | |
182 bool is_mirror = false; | |
183 result = IsMirror(arg, &is_mirror); | |
184 if (Dart_IsError(result)) { | |
185 return result; | |
186 } | |
187 if (is_mirror) { | |
188 arg_array->Add(UnwrapMirror(arg)); | |
189 } else { | |
190 // Simple value. | |
191 ASSERT(IsSimpleValue(arg)); | |
192 arg_array->Add(arg); | |
193 } | |
194 } | |
195 return Dart_True(); | |
196 } | |
197 | |
198 | |
199 static Dart_Handle CreateLibraryMirror(Dart_Handle lib) { | |
200 Dart_Handle cls_name = Dart_NewString("_LocalLibraryMirrorImpl"); | |
201 Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); | |
202 if (Dart_IsError(cls)) { | |
203 return cls; | |
204 } | |
205 const int kNumArgs = 3; | |
206 Dart_Handle args[kNumArgs]; | |
207 args[0] = CreateVMReference(lib); | |
208 args[1] = Dart_LibraryName(lib); | |
209 args[2] = Dart_LibraryUrl(lib); | |
210 return Dart_New(cls, Dart_Null(), kNumArgs, args); | |
211 } | |
212 | |
213 | |
214 static Dart_Handle CreateLibrariesMap() { | |
215 // TODO(turnidge): This should be an immutable map. | |
216 Dart_Handle map = MapNew(); | |
217 | |
218 Dart_Handle lib_urls = Dart_RegisteredLibraryUrls(); | |
219 if (Dart_IsError(lib_urls)) { | |
220 return lib_urls; | |
221 } | |
222 intptr_t len; | |
223 Dart_Handle result = Dart_ListLength(lib_urls, &len); | |
224 if (Dart_IsError(result)) { | |
225 return result; | |
226 } | |
227 for (int i = 0; i < len; i++) { | |
228 Dart_Handle lib_url = Dart_ListGetAt(lib_urls, i); | |
229 Dart_Handle lib = Dart_LookupLibrary(lib_url); | |
230 if (Dart_IsError(lib)) { | |
231 return lib; | |
232 } | |
233 Dart_Handle lib_key = Dart_LibraryName(lib); | |
234 Dart_Handle lib_mirror = CreateLibraryMirror(lib); | |
235 if (Dart_IsError(lib_mirror)) { | |
236 return lib_mirror; | |
237 } | |
238 // TODO(turnidge): Check for duplicate library names. | |
239 result = MapAdd(map, lib_key, lib_mirror); | |
240 } | |
241 return map; | |
242 } | |
243 | |
244 | |
245 static Dart_Handle CreateLocalIsolateMirror() { | |
246 Dart_Handle cls_name = Dart_NewString("_LocalIsolateMirrorImpl"); | |
247 Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); | |
248 if (Dart_IsError(cls)) { | |
249 return cls; | |
250 } | |
251 | |
252 Dart_Handle libraries = CreateLibrariesMap(); | |
253 if (Dart_IsError(libraries)) { | |
254 return libraries; | |
255 } | |
256 | |
257 // Lookup the root_lib_mirror from the library list to canonicalize it. | |
258 Dart_Handle root_lib_name = Dart_LibraryName(Dart_RootLibrary()); | |
259 Dart_Handle root_lib_mirror = MapGet(libraries, root_lib_name); | |
260 if (Dart_IsError(root_lib_mirror)) { | |
261 return root_lib_mirror; | |
262 } | |
263 | |
264 const int kNumArgs = 3; | |
265 Dart_Handle args[kNumArgs]; | |
266 args[0] = Dart_DebugName(); | |
267 args[1] = root_lib_mirror; | |
268 args[2] = libraries; | |
269 Dart_Handle mirror = Dart_New(cls, Dart_Null(), kNumArgs, args); | |
270 return mirror; | |
271 } | |
272 | |
273 | |
274 static Dart_Handle CreateLocalInstanceMirror(Dart_Handle instance) { | |
275 // ASSERT(Dart_IsInstance(instance)); | |
276 Dart_Handle cls_name = Dart_NewString("_LocalInstanceMirrorImpl"); | |
277 Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); | |
278 if (Dart_IsError(cls)) { | |
279 return cls; | |
280 } | |
281 const int kNumArgs = 2; | |
282 Dart_Handle args[kNumArgs]; | |
283 args[0] = CreateVMReference(instance); | |
284 if (IsSimpleValue(instance)) { | |
285 args[1] = instance; | |
286 } else { | |
287 args[1] = Dart_Null(); | |
288 } | |
289 Dart_Handle mirror = Dart_New(cls, Dart_Null(), kNumArgs, args); | |
290 return mirror; | |
291 } | |
292 | |
293 | |
294 void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalIsolateMirror)( | |
295 Dart_NativeArguments args) { | |
296 Dart_Handle mirror = CreateLocalIsolateMirror(); | |
297 if (Dart_IsError(mirror)) { | |
298 Dart_PropagateError(mirror); | |
299 } | |
300 Dart_SetReturnValue(args, mirror); | |
301 } | |
302 | |
303 void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_invoke)( | |
304 Dart_NativeArguments args) { | |
305 Dart_Handle mirror = Dart_GetNativeArgument(args, 0); | |
306 Dart_Handle member = Dart_GetNativeArgument(args, 1); | |
307 Dart_Handle raw_invoke_args = Dart_GetNativeArgument(args, 2); | |
308 | |
309 Dart_Handle reflectee = UnwrapMirror(mirror); | |
310 GrowableArray<Dart_Handle> invoke_args; | |
311 Dart_Handle result = UnwrapArgList(raw_invoke_args, &invoke_args); | |
312 if (Dart_IsError(result)) { | |
313 Dart_PropagateError(result); | |
314 } | |
315 result = | |
316 Dart_Invoke(reflectee, member, invoke_args.length(), invoke_args.data()); | |
Ivan Posva
2012/05/29 22:13:45
Dart_Invoke might want a sister function at some p
turnidge
2012/05/29 23:13:47
Yes.
On 2012/05/29 22:13:45, Ivan Posva wrote:
| |
317 if (Dart_IsError(result)) { | |
318 Dart_PropagateError(result); | |
319 } | |
320 Dart_Handle wrapped_result = CreateLocalInstanceMirror(result); | |
321 if (Dart_IsError(wrapped_result)) { | |
322 Dart_PropagateError(wrapped_result); | |
323 } | |
324 Dart_SetReturnValue(args, wrapped_result); | |
325 } | |
120 | 326 |
121 void HandleMirrorsMessage(Isolate* isolate, | 327 void HandleMirrorsMessage(Isolate* isolate, |
122 Dart_Port reply_port, | 328 Dart_Port reply_port, |
123 const Instance& message) { | 329 const Instance& message) { |
124 TextBuffer buffer(64); | 330 UNIMPLEMENTED(); |
125 if (!message.IsString()) { | |
126 buffer.Printf( | |
127 "{ \"ok\": false, \"error\": \"Malformed mirrors request\" }"); | |
128 } else { | |
129 String& json_string = String::Handle(); | |
130 json_string ^= message.raw(); | |
131 const char* json_text = json_string.ToCString(); | |
132 JSONReader reader(json_text); | |
133 | |
134 if (reader.Seek("command")) { | |
135 if (reader.IsStringLiteral("isolateMirrorOf")) { | |
136 buffer.Printf("{ \"ok\": true, \"debugName\": \"%s\" }", | |
137 isolate->name()); | |
138 } else { | |
139 const char* command = ""; | |
140 int command_len = 0; | |
141 JSONGetString(&reader, &command, &command_len); | |
142 buffer.Printf( | |
143 "{ \"ok\": false, \"error\": \"Command '%.*s' not recognized\" }", | |
144 command_len, command); | |
145 } | |
146 } else { | |
147 buffer.Printf( | |
148 "{ \"ok\": false, \"error\": \"Field 'command' not found\" }"); | |
149 } | |
150 } | |
151 | |
152 Dart_CObject reply; | |
153 reply.type = Dart_CObject::kString; | |
154 reply.value.as_string = buffer.buf(); | |
155 if (!Dart_PostCObject(reply_port, &reply)) { | |
156 OS::PrintErr("Unable to post mirrors reply"); | |
157 return; | |
158 } | |
159 } | 331 } |
160 | 332 |
161 } // namespace dart | 333 } // namespace dart |
OLD | NEW |