Index: runtime/lib/mirrors.cc |
=================================================================== |
--- runtime/lib/mirrors.cc (revision 8116) |
+++ runtime/lib/mirrors.cc (working copy) |
@@ -5,6 +5,8 @@ |
#include "vm/bootstrap_natives.h" |
#include "platform/json.h" |
+#include "include/dart_api.h" |
+#include "include/dart_debugger_api.h" |
#include "vm/dart_entry.h" |
#include "vm/exceptions.h" |
#include "vm/message.h" |
@@ -13,149 +15,321 @@ |
namespace dart { |
-static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
- void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
- return reinterpret_cast<uint8_t*>(new_ptr); |
+DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) { |
+ GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); |
+ |
+ // Get the port id from the SendPort instance. |
+ const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port)); |
+ if (id_obj.IsError()) { |
+ Exceptions::PropagateError(id_obj); |
+ UNREACHABLE(); |
+ } |
+ ASSERT(id_obj.IsSmi() || id_obj.IsMint()); |
+ Integer& id = Integer::Handle(); |
+ id ^= id_obj.raw(); |
+ Dart_Port port_id = static_cast<Dart_Port>(id.AsInt64Value()); |
+ const Bool& is_local = Bool::Handle(Bool::Get(PortMap::IsLocalPort(port_id))); |
+ arguments->SetReturn(is_local); |
} |
-DEFINE_NATIVE_ENTRY(Mirrors_send, 3) { |
- GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); |
- GET_NATIVE_ARGUMENT(Instance, message, arguments->At(1)); |
- GET_NATIVE_ARGUMENT(Instance, replyTo, arguments->At(2)); |
+// TODO(turnidge): Add Map support to the dart embedding api instead |
+// of implementing it here. |
+static Dart_Handle CoreLib() { |
+ Dart_Handle core_lib_name = Dart_NewString("dart:core"); |
+ return Dart_LookupLibrary(core_lib_name); |
+} |
- // Get the send port id. |
- Object& result = Object::Handle(); |
- result = DartLibraryCalls::PortGetId(port); |
- if (result.IsError()) { |
- Exceptions::PropagateError(result); |
+ |
+static Dart_Handle MapNew() { |
+ Dart_Handle cls = Dart_GetClass(CoreLib(), Dart_NewString("Map")); |
+ if (Dart_IsError(cls)) { |
+ return cls; |
} |
+ return Dart_New(cls, Dart_Null(), 0, NULL); |
+} |
- Integer& value = Integer::Handle(); |
- value ^= result.raw(); |
- int64_t send_port_id = value.AsInt64Value(); |
- // Get the reply port id. |
- result = DartLibraryCalls::PortGetId(replyTo); |
- if (result.IsError()) { |
- Exceptions::PropagateError(result); |
+static Dart_Handle MapAdd(Dart_Handle map, Dart_Handle key, Dart_Handle value) { |
+ const int kNumArgs = 2; |
+ Dart_Handle args[kNumArgs]; |
+ args[0] = key; |
+ args[1] = value; |
+ return Dart_Invoke(map, Dart_NewString("[]="), kNumArgs, args); |
+} |
+ |
+ |
+static Dart_Handle MapGet(Dart_Handle map, Dart_Handle key) { |
+ const int kNumArgs = 1; |
+ Dart_Handle args[kNumArgs]; |
+ args[0] = key; |
+ return Dart_Invoke(map, Dart_NewString("[]"), kNumArgs, args); |
+} |
+ |
+ |
+static Dart_Handle MirrorLib() { |
+ Dart_Handle mirror_lib_name = Dart_NewString("dart:mirrors"); |
+ return Dart_LookupLibrary(mirror_lib_name); |
+} |
+ |
+ |
+static Dart_Handle IsMirror(Dart_Handle object, bool* is_mirror) { |
+ Dart_Handle cls_name = Dart_NewString("Mirror"); |
+ Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
+ if (Dart_IsError(cls)) { |
+ return cls; |
} |
- value ^= result.raw(); |
- int64_t reply_port_id = value.AsInt64Value(); |
+ Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror); |
+ if (Dart_IsError(result)) { |
+ return result; |
+ } |
+ return Dart_True(); // Indicates success. Result is in is_mirror. |
+} |
- // Construct the message. |
- uint8_t* data = NULL; |
- SnapshotWriter writer(Snapshot::kMessage, &data, &allocator); |
- writer.WriteObject(message.raw()); |
- writer.FinalizeBuffer(); |
- // Post the message. |
- bool retval = PortMap::PostMessage(new Message( |
- send_port_id, reply_port_id, data, Message::kOOBPriority)); |
- const Bool& retval_obj = Bool::Handle(Bool::Get(retval)); |
- arguments->SetReturn(retval_obj); |
+static bool IsSimpleValue(Dart_Handle object) { |
+ return (Dart_IsNull(object) || |
+ Dart_IsNumber(object) || |
+ Dart_IsString(object) || |
+ Dart_IsBoolean(object)); |
} |
-static bool JSONGetString(JSONReader* reader, |
- const char** value_chars, |
- int* value_len) { |
- if (reader->Type() != JSONReader::kString) { |
- return false; |
+static void FreeVMReference(Dart_Handle weak_ref, void* data) { |
+ Dart_Handle perm_handle = reinterpret_cast<Dart_Handle>(data); |
+ Dart_DeletePersistentHandle(perm_handle); |
+ Dart_DeletePersistentHandle(weak_ref); |
+} |
+ |
+ |
+static Dart_Handle CreateVMReference(Dart_Handle handle) { |
+ // Create the VMReference object. |
+ Dart_Handle cls_name = Dart_NewString("VMReference"); |
+ Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
+ if (Dart_IsError(cls)) { |
+ return cls; |
} |
- *value_chars = reader->ValueChars(); |
- *value_len = reader->ValueLen(); |
- return true; |
+ Dart_Handle vm_ref = Dart_New(cls, Dart_Null(), 0, NULL); |
+ if (Dart_IsError(vm_ref)) { |
+ return vm_ref; |
+ } |
+ |
+ // Allocate a persistent handle. |
+ Dart_Handle perm_handle = Dart_NewPersistentHandle(handle); |
+ if (Dart_IsError(perm_handle)) { |
+ return perm_handle; |
+ } |
+ |
+ // Store the persistent handle in the VMReference. |
+ intptr_t perm_handle_value = reinterpret_cast<intptr_t>(perm_handle); |
+ Dart_Handle result = |
+ Dart_SetNativeInstanceField(vm_ref, 0, perm_handle_value); |
+ if (Dart_IsError(result)) { |
+ Dart_DeletePersistentHandle(perm_handle); |
+ return result; |
+ } |
+ |
+ // Create a weak reference. We use the callback to be informed when |
+ // the VMReference is collected, so we can release the persistent |
+ // handle. |
+ void* perm_handle_data = reinterpret_cast<void*>(perm_handle); |
+ Dart_Handle weak_ref = |
+ Dart_NewWeakPersistentHandle(vm_ref, perm_handle_data, FreeVMReference); |
+ if (Dart_IsError(weak_ref)) { |
+ Dart_DeletePersistentHandle(perm_handle); |
+ return weak_ref; |
+ } |
+ |
+ // Success. |
+ return vm_ref; |
} |
-DEFINE_NATIVE_ENTRY(Mirrors_processResponse, 3) { |
- GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); |
- GET_NATIVE_ARGUMENT(String, command, arguments->At(1)); |
- GET_NATIVE_ARGUMENT(String, response, arguments->At(2)); |
+static Dart_Handle UnwrapVMReference(Dart_Handle vm_ref) { |
+ // Retrieve the persistent handle from the VMReference |
+ intptr_t perm_handle_value = 0; |
+ Dart_Handle result = |
+ Dart_GetNativeInstanceField(vm_ref, 0, &perm_handle_value); |
+ if (Dart_IsError(result)) { |
+ return result; |
+ } |
+ Dart_Handle perm_handle = reinterpret_cast<Dart_Handle>(perm_handle_value); |
+ ASSERT(!Dart_IsError(perm_handle)); |
+ return perm_handle; |
+} |
- const char* json_text = response.ToCString(); |
- if (command.Equals("isolateMirrorOf")) { |
- JSONReader reader(json_text); |
- const char* debug_name = ""; |
- int debug_name_len = 0; |
- if (!reader.Seek("ok") || !reader.IsTrue() || |
- !reader.Seek("debugName") || |
- !JSONGetString(&reader, &debug_name, &debug_name_len)) { |
- // TODO(turnidge): Use an exception class instead of a String. |
- Exceptions::Throw(Instance::Handle(String::NewFormatted( |
- "Error while processing mirror request."))); |
- UNREACHABLE(); |
+ |
+static Dart_Handle UnwrapMirror(Dart_Handle mirror) { |
+ Dart_Handle field_name = Dart_NewString("_reference"); |
+ Dart_Handle vm_ref = Dart_GetField(mirror, field_name); |
+ if (Dart_IsError(vm_ref)) { |
+ return vm_ref; |
+ } |
+ return UnwrapVMReference(vm_ref); |
+} |
+ |
+ |
+static Dart_Handle UnwrapArgList(Dart_Handle arg_list, |
+ GrowableArray<Dart_Handle>* arg_array) { |
+ intptr_t len = 0; |
+ Dart_Handle result = Dart_ListLength(arg_list, &len); |
+ if (Dart_IsError(result)) { |
+ return result; |
+ } |
+ for (int i = 0; i < len; i++) { |
+ Dart_Handle arg = Dart_ListGetAt(arg_list, i); |
+ if (Dart_IsError(arg)) { |
+ return arg; |
} |
+ bool is_mirror = false; |
+ result = IsMirror(arg, &is_mirror); |
+ if (Dart_IsError(result)) { |
+ return result; |
+ } |
+ if (is_mirror) { |
+ arg_array->Add(UnwrapMirror(arg)); |
+ } else { |
+ // Simple value. |
+ ASSERT(IsSimpleValue(arg)); |
+ arg_array->Add(arg); |
+ } |
+ } |
+ return Dart_True(); |
+} |
- // Create and return a new instance of _IsolateMirrorImpl. |
- Library& lib = Library::Handle(Library::MirrorsLibrary()); |
- const String& public_class_name = |
- String::Handle(String::NewSymbol("_IsolateMirrorImpl")); |
- const String& class_name = |
- String::Handle(lib.PrivateName(public_class_name)); |
- const String& function_name = |
- String::Handle(String::NewSymbol("_make")); |
- const int kNumArgs = 2; |
- const Array& kNoArgNames = Array::Handle(); |
- const Function& function = Function::Handle( |
- Resolver::ResolveStatic(lib, |
- class_name, |
- function_name, |
- kNumArgs, |
- kNoArgNames, |
- Resolver::kIsQualified)); |
- ASSERT(!function.IsNull()); |
- GrowableArray<const Object*> args(kNumArgs); |
- args.Add(&port); |
- const String& debug_name_str = String::Handle( |
- String::NewFormatted("%.*s", debug_name_len, debug_name)); |
- args.Add(&debug_name_str); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeStatic(function, args, kNoArgNames)); |
- arguments->SetReturn(result); |
+ |
+static Dart_Handle CreateLibraryMirror(Dart_Handle lib) { |
+ Dart_Handle cls_name = Dart_NewString("_LocalLibraryMirrorImpl"); |
+ Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
+ if (Dart_IsError(cls)) { |
+ return cls; |
} |
+ const int kNumArgs = 3; |
+ Dart_Handle args[kNumArgs]; |
+ args[0] = CreateVMReference(lib); |
+ args[1] = Dart_LibraryName(lib); |
+ args[2] = Dart_LibraryUrl(lib); |
+ return Dart_New(cls, Dart_Null(), kNumArgs, args); |
} |
-void HandleMirrorsMessage(Isolate* isolate, |
- Dart_Port reply_port, |
- const Instance& message) { |
- TextBuffer buffer(64); |
- if (!message.IsString()) { |
- buffer.Printf( |
- "{ \"ok\": false, \"error\": \"Malformed mirrors request\" }"); |
- } else { |
- String& json_string = String::Handle(); |
- json_string ^= message.raw(); |
- const char* json_text = json_string.ToCString(); |
- JSONReader reader(json_text); |
+static Dart_Handle CreateLibrariesMap() { |
+ // TODO(turnidge): This should be an immutable map. |
+ Dart_Handle map = MapNew(); |
- if (reader.Seek("command")) { |
- if (reader.IsStringLiteral("isolateMirrorOf")) { |
- buffer.Printf("{ \"ok\": true, \"debugName\": \"%s\" }", |
- isolate->name()); |
- } else { |
- const char* command = ""; |
- int command_len = 0; |
- JSONGetString(&reader, &command, &command_len); |
- buffer.Printf( |
- "{ \"ok\": false, \"error\": \"Command '%.*s' not recognized\" }", |
- command_len, command); |
- } |
- } else { |
- buffer.Printf( |
- "{ \"ok\": false, \"error\": \"Field 'command' not found\" }"); |
+ Dart_Handle lib_urls = Dart_GetLibraryURLs(); |
+ if (Dart_IsError(lib_urls)) { |
+ return lib_urls; |
+ } |
+ intptr_t len; |
+ Dart_Handle result = Dart_ListLength(lib_urls, &len); |
+ if (Dart_IsError(result)) { |
+ return result; |
+ } |
+ for (int i = 0; i < len; i++) { |
+ Dart_Handle lib_url = Dart_ListGetAt(lib_urls, i); |
+ Dart_Handle lib = Dart_LookupLibrary(lib_url); |
+ if (Dart_IsError(lib)) { |
+ return lib; |
} |
+ Dart_Handle lib_key = Dart_LibraryName(lib); |
+ Dart_Handle lib_mirror = CreateLibraryMirror(lib); |
+ if (Dart_IsError(lib_mirror)) { |
+ return lib_mirror; |
+ } |
+ // TODO(turnidge): Check for duplicate library names. |
+ result = MapAdd(map, lib_key, lib_mirror); |
} |
+ return map; |
+} |
- Dart_CObject reply; |
- reply.type = Dart_CObject::kString; |
- reply.value.as_string = buffer.buf(); |
- if (!Dart_PostCObject(reply_port, &reply)) { |
- OS::PrintErr("Unable to post mirrors reply"); |
- return; |
+ |
+static Dart_Handle CreateLocalIsolateMirror() { |
+ Dart_Handle cls_name = Dart_NewString("_LocalIsolateMirrorImpl"); |
+ Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
+ if (Dart_IsError(cls)) { |
+ return cls; |
} |
+ |
+ Dart_Handle libraries = CreateLibrariesMap(); |
+ if (Dart_IsError(libraries)) { |
+ return libraries; |
+ } |
+ |
+ // Lookup the root_lib_mirror from the library list to canonicalize it. |
+ Dart_Handle root_lib_name = Dart_LibraryName(Dart_RootLibrary()); |
+ Dart_Handle root_lib_mirror = MapGet(libraries, root_lib_name); |
+ if (Dart_IsError(root_lib_mirror)) { |
+ return root_lib_mirror; |
+ } |
+ |
+ const int kNumArgs = 3; |
+ Dart_Handle args[kNumArgs]; |
+ args[0] = Dart_DebugName(); |
+ args[1] = root_lib_mirror; |
+ args[2] = libraries; |
+ Dart_Handle mirror = Dart_New(cls, Dart_Null(), kNumArgs, args); |
+ return mirror; |
} |
+ |
+static Dart_Handle CreateLocalInstanceMirror(Dart_Handle instance) { |
+ // ASSERT(Dart_IsInstance(instance)); |
+ Dart_Handle cls_name = Dart_NewString("_LocalInstanceMirrorImpl"); |
+ Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name); |
+ if (Dart_IsError(cls)) { |
+ return cls; |
+ } |
+ const int kNumArgs = 2; |
+ Dart_Handle args[kNumArgs]; |
+ args[0] = CreateVMReference(instance); |
+ if (IsSimpleValue(instance)) { |
+ args[1] = instance; |
+ } else { |
+ args[1] = Dart_Null(); |
+ } |
+ Dart_Handle mirror = Dart_New(cls, Dart_Null(), kNumArgs, args); |
+ return mirror; |
+} |
+ |
+ |
+void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalIsolateMirror)( |
+ Dart_NativeArguments args) { |
+ Dart_Handle mirror = CreateLocalIsolateMirror(); |
+ if (Dart_IsError(mirror)) { |
+ Dart_PropagateError(mirror); |
+ } |
+ Dart_SetReturnValue(args, mirror); |
+} |
+ |
+void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_invoke)( |
+ Dart_NativeArguments args) { |
+ Dart_Handle mirror = Dart_GetNativeArgument(args, 0); |
+ Dart_Handle member = Dart_GetNativeArgument(args, 1); |
+ Dart_Handle raw_invoke_args = Dart_GetNativeArgument(args, 2); |
+ |
+ Dart_Handle reflectee = UnwrapMirror(mirror); |
+ GrowableArray<Dart_Handle> invoke_args; |
+ Dart_Handle result = UnwrapArgList(raw_invoke_args, &invoke_args); |
+ if (Dart_IsError(result)) { |
+ Dart_PropagateError(result); |
+ } |
+ result = |
+ Dart_Invoke(reflectee, member, invoke_args.length(), invoke_args.data()); |
+ if (Dart_IsError(result)) { |
+ Dart_PropagateError(result); |
+ } |
+ Dart_Handle wrapped_result = CreateLocalInstanceMirror(result); |
+ if (Dart_IsError(wrapped_result)) { |
+ Dart_PropagateError(wrapped_result); |
+ } |
+ Dart_SetReturnValue(args, wrapped_result); |
+} |
+ |
+void HandleMirrorsMessage(Isolate* isolate, |
+ Dart_Port reply_port, |
+ const Instance& message) { |
+ UNIMPLEMENTED(); |
+} |
+ |
} // namespace dart |