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