// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/service.h"

#include "include/dart_api.h"
#include "platform/globals.h"

#include "vm/compiler.h"
#include "vm/coverage.h"
#include "vm/cpu.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/isolate.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
#include "vm/native_arguments.h"
#include "vm/object.h"
#include "vm/object_graph.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/port.h"
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/unicode.h"
#include "vm/version.h"

namespace dart {

DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests.");
DEFINE_FLAG(bool, trace_service_pause_events, false,
            "Trace VM service isolate pause events.");
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, enable_asserts);

struct ResourcesEntry {
  const char* path_;
  const char* resource_;
  int length_;
};

extern ResourcesEntry __service_resources_[];

class Resources {
 public:
  static const int kNoSuchInstance = -1;
  static int ResourceLookup(const char* path, const char** resource) {
    ResourcesEntry* table = ResourceTable();
    for (int i = 0; table[i].path_ != NULL; i++) {
      const ResourcesEntry& entry = table[i];
      if (strcmp(path, entry.path_) == 0) {
        *resource = entry.resource_;
        ASSERT(entry.length_ > 0);
        return entry.length_;
      }
    }
    return kNoSuchInstance;
  }

  static const char* Path(int idx) {
    ASSERT(idx >= 0);
    ResourcesEntry* entry = At(idx);
    if (entry == NULL) {
      return NULL;
    }
    ASSERT(entry->path_ != NULL);
    return entry->path_;
  }

  static int Length(int idx) {
    ASSERT(idx >= 0);
    ResourcesEntry* entry = At(idx);
    if (entry == NULL) {
      return kNoSuchInstance;
    }
    ASSERT(entry->path_ != NULL);
    return entry->length_;
  }

  static const uint8_t* Resource(int idx) {
    ASSERT(idx >= 0);
    ResourcesEntry* entry = At(idx);
    if (entry == NULL) {
      return NULL;
    }
    return reinterpret_cast<const uint8_t*>(entry->resource_);
  }

 private:
  static ResourcesEntry* At(int idx) {
    ASSERT(idx >= 0);
    ResourcesEntry* table = ResourceTable();
    for (int i = 0; table[i].path_ != NULL; i++) {
      if (idx == i) {
        return &table[i];
      }
    }
    return NULL;
  }

  static ResourcesEntry* ResourceTable() {
    return &__service_resources_[0];
  }

  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(Resources);
};


class EmbedderServiceHandler {
 public:
  explicit EmbedderServiceHandler(const char* name) : name_(NULL),
                                                      callback_(NULL),
                                                      user_data_(NULL),
                                                      next_(NULL) {
    ASSERT(name != NULL);
    name_ = strdup(name);
  }

  ~EmbedderServiceHandler() {
    free(name_);
  }

  const char* name() const { return name_; }

  Dart_ServiceRequestCallback callback() const { return callback_; }
  void set_callback(Dart_ServiceRequestCallback callback) {
    callback_ = callback;
  }

  void* user_data() const { return user_data_; }
  void set_user_data(void* user_data) {
    user_data_ = user_data;
  }

  EmbedderServiceHandler* next() const { return next_; }
  void set_next(EmbedderServiceHandler* next) {
    next_ = next;
  }

 private:
  char* name_;
  Dart_ServiceRequestCallback callback_;
  void* user_data_;
  EmbedderServiceHandler* next_;
};


class LibraryCoverageFilter : public CoverageFilter {
 public:
  explicit LibraryCoverageFilter(const Library& lib) : lib_(lib) {}
  bool ShouldOutputCoverageFor(const Library& lib,
                               const Script& script,
                               const Class& cls,
                               const Function& func) const {
    return lib.raw() == lib_.raw();
  }
 private:
  const Library& lib_;
};


class ScriptCoverageFilter : public CoverageFilter {
 public:
  explicit ScriptCoverageFilter(const Script& script)
      : script_(script) {}
  bool ShouldOutputCoverageFor(const Library& lib,
                               const Script& script,
                               const Class& cls,
                               const Function& func) const {
    return script.raw() == script_.raw();
  }
 private:
  const Script& script_;
};


class ClassCoverageFilter : public CoverageFilter {
 public:
  explicit ClassCoverageFilter(const Class& cls) : cls_(cls) {}
  bool ShouldOutputCoverageFor(const Library& lib,
                               const Script& script,
                               const Class& cls,
                               const Function& func) const {
    return cls.raw() == cls_.raw();
  }
 private:
  const Class& cls_;
};


class FunctionCoverageFilter : public CoverageFilter {
 public:
  explicit FunctionCoverageFilter(const Function& func) : func_(func) {}
  bool ShouldOutputCoverageFor(const Library& lib,
                               const Script& script,
                               const Class& cls,
                               const Function& func) const {
    return func.raw() == func_.raw();
  }
 private:
  const Function& func_;
};


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);
}


static void SendIsolateServiceMessage(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  Isolate* isolate = arguments->isolate();
  StackZone zone(isolate);
  HANDLESCOPE(isolate);
  GET_NON_NULL_NATIVE_ARGUMENT(SendPort, sp, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(1));

  // Set the type of the OOB message.
  message.SetAt(0, Smi::Handle(isolate, Smi::New(Message::kServiceOOBMsg)));

  // Serialize message.
  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator);
  writer.WriteMessage(message);

  // TODO(turnidge): Throw an exception when the return value is false?
  PortMap::PostMessage(new Message(sp.Id(), data, writer.BytesWritten(),
                                   Message::kOOBPriority));
}


static void SendRootServiceMessage(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  Isolate* isolate = arguments->isolate();
  StackZone zone(isolate);
  HANDLESCOPE(isolate);
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(0));
  Service::HandleRootMessage(message);
}


void Service::SetEventMask(uint32_t mask) {
  event_mask_ = mask;
}


void SetEventMask(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  Isolate* isolate = arguments->isolate();
  StackZone zone(isolate);
  HANDLESCOPE(isolate);
  GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(0));
  Service::SetEventMask(mask.AsTruncatedUint32Value());
}


// These must be kept in sync with service/constants.dart
#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2


static RawArray* MakeServiceControlMessage(Dart_Port port_id, intptr_t code,
                                           const String& name) {
  const Array& list = Array::Handle(Array::New(4));
  ASSERT(!list.IsNull());
  const Integer& code_int = Integer::Handle(Integer::New(code));
  const Integer& port_int = Integer::Handle(Integer::New(port_id));
  const SendPort& send_port = SendPort::Handle(SendPort::New(port_id));
  list.SetAt(0, code_int);
  list.SetAt(1, port_int);
  list.SetAt(2, send_port);
  list.SetAt(3, name);
  return list.raw();
}


class RegisterRunningIsolatesVisitor : public IsolateVisitor {
 public:
  explicit RegisterRunningIsolatesVisitor(Isolate* service_isolate)
      : IsolateVisitor(),
        register_function_(Function::Handle(service_isolate)),
        service_isolate_(service_isolate) {
    ASSERT(Isolate::Current() == service_isolate_);
    // Get library.
    const String& library_url = Symbols::DartVMService();
    ASSERT(!library_url.IsNull());
    const Library& library =
        Library::Handle(Library::LookupLibrary(library_url));
    ASSERT(!library.IsNull());
    // Get function.
    const String& function_name =
        String::Handle(String::New("_registerIsolate"));
    ASSERT(!function_name.IsNull());
    register_function_ = library.LookupFunctionAllowPrivate(function_name);
    ASSERT(!register_function_.IsNull());
  }

  virtual void VisitIsolate(Isolate* isolate) {
    ASSERT(Isolate::Current() == service_isolate_);
    if ((isolate == service_isolate_) ||
        (isolate == Dart::vm_isolate())) {
      // We do not register the service or vm isolate.
      return;
    }
    // Setup arguments for call.
    Dart_Port port_id = isolate->main_port();
    const Integer& port_int = Integer::Handle(Integer::New(port_id));
    ASSERT(!port_int.IsNull());
    const SendPort& send_port = SendPort::Handle(SendPort::New(port_id));
    const String& name = String::Handle(String::New(isolate->name()));
    ASSERT(!name.IsNull());
    const Array& args = Array::Handle(Array::New(3));
    ASSERT(!args.IsNull());
    args.SetAt(0, port_int);
    args.SetAt(1, send_port);
    args.SetAt(2, name);
    Object& r = Object::Handle(service_isolate_);
    r = DartEntry::InvokeFunction(register_function_, args);
    ASSERT(!r.IsError());
  }

 private:
  Function& register_function_;
  Isolate* service_isolate_;
};


static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) {
  const ReceivePort& rp = Api::UnwrapReceivePortHandle(isolate, receivePort);
  if (rp.IsNull()) {
    return ILLEGAL_PORT;
  }
  return rp.Id();
}


static void OnStart(Dart_NativeArguments args) {
  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
  Isolate* isolate = arguments->isolate();
  StackZone zone(isolate);
  HANDLESCOPE(isolate);
  {
    // Boot the dart:vmservice library.
    Dart_EnterScope();
    Dart_Handle url_str =
        Dart_NewStringFromCString(Symbols::Name(Symbols::kDartVMServiceId));
    Dart_Handle library = Dart_LookupLibrary(url_str);
    ASSERT(Dart_IsLibrary(library));
    Dart_Handle result =
        Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL);
    ASSERT(!Dart_IsError(result));
    Dart_Port port = ExtractPort(isolate, result);
    ASSERT(port != ILLEGAL_PORT);
    Service::set_port(port);
    Dart_ExitScope();
  }
  {
    // Register running isolates with service.
    RegisterRunningIsolatesVisitor register_isolates(isolate);
    Isolate::VisitIsolates(&register_isolates);
  }
}


struct VmServiceNativeEntry {
  const char* name;
  int num_arguments;
  Dart_NativeFunction function;
};


static VmServiceNativeEntry _VmServiceNativeEntries[] = {
  {"VMService_SendIsolateServiceMessage", 2, SendIsolateServiceMessage},
  {"VMService_SendRootServiceMessage", 1, SendRootServiceMessage},
  {"VMService_SetEventMask", 1, SetEventMask},
  {"VMService_OnStart", 0, OnStart },
};


static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
                                                   int num_arguments,
                                                   bool* auto_setup_scope) {
  const Object& obj = Object::Handle(Api::UnwrapHandle(name));
  if (!obj.IsString()) {
    return NULL;
  }
  const char* function_name = obj.ToCString();
  ASSERT(function_name != NULL);
  ASSERT(auto_setup_scope != NULL);
  *auto_setup_scope = true;
  intptr_t n =
      sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]);
  for (intptr_t i = 0; i < n; i++) {
    VmServiceNativeEntry entry = _VmServiceNativeEntries[i];
    if ((strcmp(function_name, entry.name) == 0) &&
        (num_arguments == entry.num_arguments)) {
      return entry.function;
    }
  }
  return NULL;
}


EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
Isolate* Service::service_isolate_ = NULL;
Dart_LibraryTagHandler Service::embedder_provided_handler_ = NULL;
Dart_Port Service::port_ = ILLEGAL_PORT;
uint32_t Service::event_mask_ = 0;

Isolate* Service::GetServiceIsolate(void* callback_data) {
  if (service_isolate_ != NULL) {
    // Already initialized, return service isolate.
    return service_isolate_;
  }
  Dart_ServiceIsolateCreateCalback create_callback =
    Isolate::ServiceCreateCallback();
  if (create_callback == NULL) {
    return NULL;
  }
  Isolate::SetCurrent(NULL);
  char* error = NULL;
  Isolate* isolate =
      reinterpret_cast<Isolate*>(create_callback(callback_data, &error));
  if (isolate == NULL) {
    return NULL;
  }
  StartIsolateScope isolate_scope(isolate);
  {
    // Install the dart:vmservice library.
    StackZone zone(isolate);
    HANDLESCOPE(isolate);
    Library& library =
        Library::Handle(isolate, isolate->object_store()->root_library());
    // Isolate is empty.
    ASSERT(library.IsNull());
    // Grab embedder tag handler.
    embedder_provided_handler_ = isolate->library_tag_handler();
    // Temporarily install our own.
    isolate->set_library_tag_handler(LibraryTagHandler);
    // Get script resource.
    const char* resource = NULL;
    const char* path = "/vmservice.dart";
    intptr_t r = Resources::ResourceLookup(path, &resource);
    ASSERT(r != Resources::kNoSuchInstance);
    ASSERT(resource != NULL);
    const String& source_str = String::Handle(
        String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r));
    ASSERT(!source_str.IsNull());
    const String& url_str = String::Handle(Symbols::DartVMService().raw());
    library ^= Library::LookupLibrary(url_str);
    ASSERT(library.IsNull());
    // Setup library.
    library = Library::New(url_str);
    library.Register();
    const Script& script = Script::Handle(
      isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
    library.SetLoadInProgress();
    Dart_EnterScope();  // Need to enter scope for tag handler.
    const Error& error = Error::Handle(isolate,
                                       Compiler::Compile(library, script));
    ASSERT(error.IsNull());
    Dart_Handle result = Dart_FinalizeLoading(false);
    ASSERT(!Dart_IsError(result));
    Dart_ExitScope();

    // Install embedder default library tag handler again.
    isolate->set_library_tag_handler(embedder_provided_handler_);
    embedder_provided_handler_ = NULL;
    library.set_native_entry_resolver(VmServiceNativeResolver);
  }
  service_isolate_ = reinterpret_cast<Isolate*>(isolate);
  return service_isolate_;
}


bool Service::SendIsolateStartupMessage() {
  if (!IsRunning()) {
    return false;
  }
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  HANDLESCOPE(isolate);
  const String& name = String::Handle(String::New(isolate->name()));
  ASSERT(!name.IsNull());
  const Array& list = Array::Handle(
      MakeServiceControlMessage(Dart_GetMainPortId(),
                                VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID,
                                name));
  ASSERT(!list.IsNull());
  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator);
  writer.WriteMessage(list);
  intptr_t len = writer.BytesWritten();
  if (FLAG_trace_service) {
    OS::Print("Isolate %s %" Pd64 " registered with service \n",
              name.ToCString(),
              Dart_GetMainPortId());
  }
  return PortMap::PostMessage(
      new Message(port_, data, len, Message::kNormalPriority));
}


bool Service::SendIsolateShutdownMessage() {
  if (!IsRunning()) {
    return false;
  }
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  HANDLESCOPE(isolate);
  const String& name = String::Handle(String::New(isolate->name()));
  ASSERT(!name.IsNull());
  const Array& list = Array::Handle(
      MakeServiceControlMessage(Dart_GetMainPortId(),
                                VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID,
                                name));
  ASSERT(!list.IsNull());
  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator);
  writer.WriteMessage(list);
  intptr_t len = writer.BytesWritten();
  if (FLAG_trace_service) {
    OS::Print("Isolate %s %" Pd64 " deregistered with service \n",
              name.ToCString(),
              Dart_GetMainPortId());
  }
  return PortMap::PostMessage(
      new Message(port_, data, len, Message::kNormalPriority));
}


Dart_Handle Service::GetSource(const char* name) {
  ASSERT(name != NULL);
  int i = 0;
  while (true) {
    const char* path = Resources::Path(i);
    if (path == NULL) {
      break;
    }
    ASSERT(*path != '\0');
    // Skip the '/'.
    path++;
    if (strcmp(name, path) == 0) {
      const uint8_t* str = Resources::Resource(i);
      intptr_t length = Resources::Length(i);
      return Dart_NewStringFromUTF8(str, length);
    }
    i++;
  }
  return Dart_Null();
}


Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
                                       Dart_Handle url) {
  if (!Dart_IsLibrary(library)) {
    return Dart_NewApiError("not a library");
  }
  if (!Dart_IsString(url)) {
    return Dart_NewApiError("url is not a string");
  }
  const char* url_string = NULL;
  Dart_Handle result = Dart_StringToCString(url, &url_string);
  if (Dart_IsError(result)) {
    return result;
  }
  if (tag == Dart_kImportTag) {
    // Embedder handles all requests for external libraries.
    if (embedder_provided_handler_ == NULL) {
      return Dart_NewApiError("Unable to import module as no library tag "
                              "handler has been provided by embedder");
    }
    return embedder_provided_handler_(tag, library, url);
  }
  ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
  if (tag == Dart_kCanonicalizeUrl) {
    // url is already canonicalized.
    return url;
  }
  Dart_Handle source = GetSource(url_string);
  if (Dart_IsError(source)) {
    return source;
  }
  return Dart_LoadSource(library, url, source, 0, 0);
}


// A handler for a per-isolate request.
//
// If a handler returns true, the reply is complete and ready to be
// posted.  If a handler returns false, then it is responsible for
// posting the reply (this can be used for asynchronous delegation of
// the response handling).
typedef bool (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream);

struct IsolateMessageHandlerEntry {
  const char* command;
  IsolateMessageHandler handler;
};

static IsolateMessageHandler FindIsolateMessageHandler(const char* command);


// A handler for a root (vm-global) request.
//
// If a handler returns true, the reply is complete and ready to be
// posted.  If a handler returns false, then it is responsible for
// posting the reply (this can be used for asynchronous delegation of
// the response handling).
typedef bool (*RootMessageHandler)(JSONStream* stream);

struct RootMessageHandlerEntry {
  const char* command;
  RootMessageHandler handler;
};

static RootMessageHandler FindRootMessageHandler(const char* command);


static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) {
  JSONObject jsobj(&obj, "request");
  {
    JSONArray jsarr(&jsobj, "arguments");
    for (intptr_t i = 0; i < js->num_arguments(); i++) {
      jsarr.AddValue(js->GetArgument(i));
    }
  }
  {
    JSONArray jsarr(&jsobj, "option_keys");
    for (intptr_t i = 0; i < js->num_options(); i++) {
      jsarr.AddValue(js->GetOptionKey(i));
    }
  }
  {
    JSONArray jsarr(&jsobj, "option_values");
    for (intptr_t i = 0; i < js->num_options(); i++) {
      jsarr.AddValue(js->GetOptionValue(i));
    }
  }
}


static void PrintError(JSONStream* js,
                       const char* format, ...) {
  Isolate* isolate = Isolate::Current();

  va_list args;
  va_start(args, format);
  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
  va_end(args);

  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
  va_list args2;
  va_start(args2, format);
  OS::VSNPrint(buffer, (len + 1), format, args2);
  va_end(args2);

  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Error");
  jsobj.AddProperty("id", "");
  jsobj.AddProperty("message", buffer);
  PrintArgumentsAndOptions(jsobj, js);
}


static void PrintErrorWithKind(JSONStream* js,
                               const char* kind,
                               const char* format, ...) {
  Isolate* isolate = Isolate::Current();

  va_list args;
  va_start(args, format);
  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
  va_end(args);

  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
  va_list args2;
  va_start(args2, format);
  OS::VSNPrint(buffer, (len + 1), format, args2);
  va_end(args2);

  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Error");
  jsobj.AddProperty("id", "");
  jsobj.AddProperty("kind", kind);
  jsobj.AddProperty("message", buffer);
  PrintArgumentsAndOptions(jsobj, js);
}


void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
  ASSERT(isolate != NULL);
  ASSERT(!msg.IsNull());

  {
    StackZone zone(isolate);
    HANDLESCOPE(isolate);

    // Message is a list with five entries.
    ASSERT(msg.Length() == 5);

    Instance& reply_port = Instance::Handle(isolate);
    GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
    Array& option_keys = Array::Handle(isolate);
    Array& option_values = Array::Handle(isolate);
    reply_port ^= msg.At(1);
    path ^= msg.At(2);
    option_keys ^= msg.At(3);
    option_values ^= msg.At(4);

    ASSERT(!path.IsNull());
    ASSERT(!option_keys.IsNull());
    ASSERT(!option_values.IsNull());
    // Same number of option keys as values.
    ASSERT(option_keys.Length() == option_values.Length());

    if (!reply_port.IsSendPort()) {
      FATAL("SendPort expected.");
    }

    String& path_segment = String::Handle();
    if (path.Length() > 0) {
      path_segment ^= path.At(0);
    } else {
      path_segment ^= Symbols::Empty().raw();
    }
    ASSERT(!path_segment.IsNull());
    const char* path_segment_c = path_segment.ToCString();

    IsolateMessageHandler handler =
        FindIsolateMessageHandler(path_segment_c);
    {
      JSONStream js;
      js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
               path, option_keys, option_values);
      if (handler == NULL) {
        // Check for an embedder handler.
        EmbedderServiceHandler* e_handler =
            FindIsolateEmbedderHandler(path_segment_c);
        if (e_handler != NULL) {
          EmbedderHandleMessage(e_handler, &js);
        } else {
          PrintError(&js, "Unrecognized path");
        }
        js.PostReply();
      } else {
        if (handler(isolate, &js)) {
          // Handler returns true if the reply is ready to be posted.
          // TODO(johnmccutchan): Support asynchronous replies.
          js.PostReply();
        }
      }
    }
  }
}


static bool HandleIsolate(Isolate* isolate, JSONStream* js) {
  isolate->PrintJSON(js, false);
  return true;
}


static bool HandleStackTrace(Isolate* isolate, JSONStream* js) {
  if (js->num_arguments() > 1) {
    PrintError(js, "Command too long");
    return true;
  }
  DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "StackTrace");
  jsobj.AddProperty("id", "stacktrace");
  JSONArray jsarr(&jsobj, "members");
  intptr_t num_frames = stack->Length();
  for (intptr_t i = 0; i < num_frames; i++) {
    ActivationFrame* frame = stack->FrameAt(i);
    JSONObject jsobj(&jsarr);
    frame->PrintToJSONObject(&jsobj);
    // TODO(turnidge): Implement depth differently -- differentiate
    // inlined frames.
    jsobj.AddProperty("depth", i);
  }
  return true;
}


static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) {
  jsobj->AddProperty("type", "message");
  PrintArgumentsAndOptions(*jsobj, js);
  return true;
}


void Service::SendEchoEvent(Isolate* isolate) {
  JSONStream js;
  {
    JSONObject jsobj(&js);
    jsobj.AddProperty("type", "ServiceEvent");
    jsobj.AddPropertyF("id", "_echoEvent");
    jsobj.AddProperty("eventType", "_Echo");
    jsobj.AddProperty("isolate", isolate);
  }
  const String& message = String::Handle(String::New(js.ToCString()));
  uint8_t data[] = {0, 128, 255};
  // TODO(koda): Add 'testing' event family.
  SendEvent(kEventFamilyDebug, message, data, sizeof(data));
}


bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("id", "_echo");
  if (js->num_arguments() == 2 && strcmp(js->GetArgument(1), "event") == 0) {
    Service::SendEchoEvent(isolate);
  }
  return HandleCommonEcho(&jsobj, js);
}


// Print an error message if there is no ID argument.
#define REQUIRE_COLLECTION_ID(collection)                                      \
  if (js->num_arguments() == 1) {                                              \
    PrintError(js, "Must specify collection object id: /%s/id", collection);   \
    return true;                                                               \
  }


#define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js)            \
  if (!GetIntegerId(arg, &id)) {                                               \
    PrintError(js, "Must specify collection object id: %s/id", collection);    \
    return true;                                                               \
  }                                                                            \
  if ((id < 0) || (id >= length)) {                                            \
    PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \
                                                               length);        \
    return true;                                                               \
  }


static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
  if ((s == NULL) || (*s == '\0')) {
    // Empty string.
    return false;
  }
  if (id == NULL) {
    // No id pointer.
    return false;
  }
  intptr_t r = 0;
  char* end_ptr = NULL;
  r = strtol(s, &end_ptr, base);
  if (end_ptr == s) {
    // String was not advanced at all, cannot be valid.
    return false;
  }
  *id = r;
  return true;
}


static bool GetUnsignedIntegerId(const char* s, uintptr_t* id, int base = 10) {
  if ((s == NULL) || (*s == '\0')) {
    // Empty string.
    return false;
  }
  if (id == NULL) {
    // No id pointer.
    return false;
  }
  uintptr_t r = 0;
  char* end_ptr = NULL;
  r = strtoul(s, &end_ptr, base);
  if (end_ptr == s) {
    // String was not advanced at all, cannot be valid.
    return false;
  }
  *id = r;
  return true;
}


static bool GetInteger64Id(const char* s, int64_t* id, int base = 10) {
  if ((s == NULL) || (*s == '\0')) {
    // Empty string.
    return false;
  }
  if (id == NULL) {
    // No id pointer.
    return false;
  }
  int64_t r = 0;
  char* end_ptr = NULL;
  r = strtoll(s, &end_ptr, base);
  if (end_ptr == s) {
    // String was not advanced at all, cannot be valid.
    return false;
  }
  *id = r;
  return true;
}

// Scans the string until the '-' character. Returns pointer to string
// at '-' character. Returns NULL if not found.
const char* ScanUntilDash(const char* s) {
  if ((s == NULL) || (*s == '\0')) {
    // Empty string.
    return NULL;
  }
  while (*s != '\0') {
    if (*s == '-') {
      return s;
    }
    s++;
  }
  return NULL;
}


static bool GetCodeId(const char* s, int64_t* timestamp, uword* address) {
  if ((s == NULL) || (*s == '\0')) {
    // Empty string.
    return false;
  }
  if ((timestamp == NULL) || (address == NULL)) {
    // Bad arguments.
    return false;
  }
  // Extract the timestamp.
  if (!GetInteger64Id(s, timestamp, 16) || (*timestamp < 0)) {
    return false;
  }
  s = ScanUntilDash(s);
  if (s == NULL) {
    return false;
  }
  // Skip the dash.
  s++;
  // Extract the PC.
  if (!GetUnsignedIntegerId(s, address, 16)) {
    return false;
  }
  return true;
}


static bool ContainsNonInstance(const Object& obj) {
  if (obj.IsArray()) {
    const Array& array = Array::Cast(obj);
    Object& element = Object::Handle();
    for (intptr_t i = 0; i < array.Length(); ++i) {
      element = array.At(i);
      if (!(element.IsInstance() || element.IsNull())) {
        return true;
      }
    }
    return false;
  } else if (obj.IsGrowableObjectArray()) {
    const GrowableObjectArray& array = GrowableObjectArray::Cast(obj);
    Object& element = Object::Handle();
    for (intptr_t i = 0; i < array.Length(); ++i) {
      element = array.At(i);
      if (!(element.IsInstance() || element.IsNull())) {
        return true;
      }
    }
    return false;
  } else {
    return !(obj.IsInstance() || obj.IsNull());
  }
}


static bool HandleInboundReferences(Isolate* isolate,
                                    Object* target,
                                    intptr_t limit,
                                    JSONStream* js) {
  ObjectGraph graph(isolate);
  Array& path = Array::Handle(Array::New(limit * 2));
  intptr_t length = graph.InboundReferences(target, path);
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "InboundReferences");
  jsobj.AddProperty("id", "inbound_references");
  {
    JSONArray elements(&jsobj, "references");
    Object& source = Object::Handle();
    Smi& slot_offset = Smi::Handle();
    Class& source_class = Class::Handle();
    Field& field = Field::Handle();
    Array& parent_field_map = Array::Handle();
    limit = Utils::Minimum(limit, length);
    for (intptr_t i = 0; i < limit; ++i) {
      JSONObject jselement(&elements);
      source = path.At(i * 2);
      slot_offset ^= path.At((i * 2) + 1);

      jselement.AddProperty("source", source);
      jselement.AddProperty("slot", "<unknown>");
      if (source.IsArray()) {
        intptr_t element_index = slot_offset.Value() -
            (Array::element_offset(0) >> kWordSizeLog2);
        jselement.AddProperty("slot", element_index);
      } else if (source.IsInstance()) {
        source_class ^= source.clazz();
        parent_field_map = source_class.OffsetToFieldMap();
        intptr_t offset = slot_offset.Value();
        if (offset > 0 && offset < parent_field_map.Length()) {
          field ^= parent_field_map.At(offset);
          jselement.AddProperty("slot", field);
        }
      }

      // We nil out the array after generating the response to prevent
      // reporting suprious references when repeatedly looking for the
      // references to an object.
      path.SetAt(i * 2, Object::null_object());
    }
  }
  return true;
}


static bool HandleRetainingPath(Isolate* isolate,
                                Object* obj,
                                intptr_t limit,
                                JSONStream* js) {
  ObjectGraph graph(isolate);
  Array& path = Array::Handle(Array::New(limit * 2));
  intptr_t length = graph.RetainingPath(obj, path);
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "RetainingPath");
  jsobj.AddProperty("id", "retaining_path");
  jsobj.AddProperty("length", length);
  JSONArray elements(&jsobj, "elements");
  Object& element = Object::Handle();
  Object& parent = Object::Handle();
  Smi& offset_from_parent = Smi::Handle();
  Class& parent_class = Class::Handle();
  Array& parent_field_map = Array::Handle();
  Field& field = Field::Handle();
  limit = Utils::Minimum(limit, length);
  for (intptr_t i = 0; i < limit; ++i) {
    JSONObject jselement(&elements);
    element = path.At(i * 2);
    jselement.AddProperty("index", i);
    jselement.AddProperty("value", element);
    // Interpret the word offset from parent as list index or instance field.
    // TODO(koda): User-friendly interpretation for map entries.
    offset_from_parent ^= path.At((i * 2) + 1);
    int parent_i = i + 1;
    if (parent_i < limit) {
      parent = path.At(parent_i * 2);
      if (parent.IsArray()) {
        intptr_t element_index = offset_from_parent.Value() -
            (Array::element_offset(0) >> kWordSizeLog2);
        jselement.AddProperty("parentListIndex", element_index);
      } else if (parent.IsInstance()) {
        parent_class ^= parent.clazz();
        parent_field_map = parent_class.OffsetToFieldMap();
        intptr_t offset = offset_from_parent.Value();
        if (offset > 0 && offset < parent_field_map.Length()) {
          field ^= parent_field_map.At(offset);
          jselement.AddProperty("parentField", field);
        }
      }
    }
  }

  // We nil out the array after generating the response to prevent
  // reporting suprious references when looking for inbound references
  // after looking for a retaining path.
  for (intptr_t i = 0; i < limit; ++i) {
    path.SetAt(i * 2, Object::null_object());
  }

  return true;
}


// Takes an Object* only because RetainingPath temporarily clears it.
static bool HandleInstanceCommands(Isolate* isolate,
                                   Object* obj,
                                   ObjectIdRing::LookupResult kind,
                                   JSONStream* js,
                                   intptr_t arg_pos) {
  ASSERT(js->num_arguments() > arg_pos);
  ASSERT(kind != ObjectIdRing::kInvalid);
  const char* action = js->GetArgument(arg_pos);
  if (strcmp(action, "eval") == 0) {
    if (js->num_arguments() > (arg_pos + 1)) {
      PrintError(js, "expected at most %" Pd " arguments but found %" Pd "\n",
                 arg_pos + 1,
                 js->num_arguments());
      return true;
    }
    if (kind == ObjectIdRing::kCollected) {
      PrintErrorWithKind(js, "EvalCollected",
                         "attempt to evaluate against collected object\n",
                         js->num_arguments());
      return true;
    }
    if (kind == ObjectIdRing::kExpired) {
      PrintErrorWithKind(js, "EvalExpired",
                         "attempt to evaluate against expired object\n",
                         js->num_arguments());
      return true;
    }
    if (ContainsNonInstance(*obj)) {
      PrintError(js, "attempt to evaluate against internal VM object\n");
      return true;
    }
    const char* expr = js->LookupOption("expr");
    if (expr == NULL) {
      PrintError(js, "eval expects an 'expr' option\n",
                 js->num_arguments());
      return true;
    }
    const String& expr_str = String::Handle(isolate, String::New(expr));
    ASSERT(obj->IsInstance() || obj->IsNull());
    Instance& instance = Instance::Handle();
    instance ^= obj->raw();
    const Object& result =
        Object::Handle(instance.Evaluate(expr_str,
                                         Array::empty_array(),
                                         Array::empty_array()));
    result.PrintJSON(js, true);
    return true;
  } else if (strcmp(action, "retained") == 0) {
    if (kind == ObjectIdRing::kCollected) {
      PrintErrorWithKind(
          js, "RetainedCollected",
          "attempt to calculate size retained by a collected object\n",
          js->num_arguments());
      return true;
    }
    if (kind == ObjectIdRing::kExpired) {
      PrintErrorWithKind(
          js, "RetainedExpired",
          "attempt to calculate size retained by an expired object\n",
          js->num_arguments());
      return true;
    }
    ObjectGraph graph(isolate);
    intptr_t retained_size = graph.SizeRetainedByInstance(*obj);
    const Object& result = Object::Handle(Integer::New(retained_size));
    result.PrintJSON(js, true);
    return true;
  } else if (strcmp(action, "retaining_path") == 0) {
    if (kind == ObjectIdRing::kCollected) {
      PrintErrorWithKind(
          js, "RetainingPathCollected",
          "attempt to find a retaining path for a collected object\n",
          js->num_arguments());
      return true;
    }
    if (kind == ObjectIdRing::kExpired) {
      PrintErrorWithKind(
          js, "RetainingPathExpired",
          "attempt to find a retaining path for an expired object\n",
          js->num_arguments());
      return true;
    }
    intptr_t limit;
    if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
      PrintError(js, "retaining_path expects a 'limit' option\n",
                 js->num_arguments());
      return true;
    }
    return HandleRetainingPath(isolate, obj, limit, js);
  } else if (strcmp(action, "inbound_references") == 0) {
    if (kind == ObjectIdRing::kCollected) {
      PrintErrorWithKind(
          js, "InboundReferencesCollected",
          "attempt to find inbound references for a collected object\n",
          js->num_arguments());
      return true;
    }
    if (kind == ObjectIdRing::kExpired) {
      PrintErrorWithKind(
          js, "InboundReferencesExpired",
          "attempt to find inbound references for an expired object\n",
          js->num_arguments());
      return true;
    }
    intptr_t limit;
    if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
      PrintError(js, "inbound_references expects a 'limit' option\n",
                 js->num_arguments());
      return true;
    }
    return HandleInboundReferences(isolate, obj, limit, js);
  }

  PrintError(js, "unrecognized action '%s'\n", action);
  return true;
}


static bool HandleClassesClosures(Isolate* isolate, const Class& cls,
                                  JSONStream* js) {
  intptr_t id;
  if (js->num_arguments() > 4) {
    PrintError(js, "Command too long");
    return true;
  }
  if (!GetIntegerId(js->GetArgument(3), &id)) {
    PrintError(js, "Must specify collection object id: closures/id");
    return true;
  }
  Function& func = Function::Handle();
  func ^= cls.ClosureFunctionFromIndex(id);
  if (func.IsNull()) {
    PrintError(js, "Closure function %" Pd " not found", id);
    return true;
  }
  func.PrintJSON(js, false);
  return true;
}


static bool HandleClassesEval(Isolate* isolate, const Class& cls,
                              JSONStream* js) {
  if (js->num_arguments() > 3) {
    PrintError(js, "Command too long");
    return true;
  }
  const char* expr = js->LookupOption("expr");
  if (expr == NULL) {
    PrintError(js, "eval expects an 'expr' option\n",
               js->num_arguments());
    return true;
  }
  const String& expr_str = String::Handle(isolate, String::New(expr));
  const Object& result = Object::Handle(cls.Evaluate(expr_str,
                                                     Array::empty_array(),
                                                     Array::empty_array()));
  result.PrintJSON(js, true);
  return true;
}


static bool HandleClassesDispatchers(Isolate* isolate, const Class& cls,
                                     JSONStream* js) {
  intptr_t id;
  if (js->num_arguments() > 4) {
    PrintError(js, "Command too long");
    return true;
  }
  if (!GetIntegerId(js->GetArgument(3), &id)) {
    PrintError(js, "Must specify collection object id: dispatchers/id");
    return true;
  }
  Function& func = Function::Handle();
  func ^= cls.InvocationDispatcherFunctionFromIndex(id);
  if (func.IsNull()) {
    PrintError(js, "Dispatcher %" Pd " not found", id);
    return true;
  }
  func.PrintJSON(js, false);
  return true;
}


static bool HandleClassesFunctionsCoverage(
    Isolate* isolate, const Function& func, JSONStream* js) {
  FunctionCoverageFilter filter(func);
  CodeCoverage::PrintJSON(isolate, js, &filter);
  return true;
}


static bool HandleFunctionSetSource(
    Isolate* isolate, const Class& cls, const Function& func, JSONStream* js) {
  if (js->LookupOption("source") == NULL) {
    PrintError(js, "set_source expects a 'source' option\n");
    return true;
  }
  const String& source =
      String::Handle(String::New(js->LookupOption("source")));
  const Object& result = Object::Handle(
      Parser::ParseFunctionFromSource(cls, source));
  if (result.IsError()) {
    Error::Cast(result).PrintJSON(js, false);
    return true;
  }
  if (!result.IsFunction()) {
    PrintError(js, "source did not compile to a function.\n");
    return true;
  }

  // Replace function.
  cls.RemoveFunction(func);
  cls.AddFunction(Function::Cast(result));

  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Success");
  jsobj.AddProperty("id", "");
  return true;
}


static bool HandleClassesFunctions(Isolate* isolate, const Class& cls,
                                   JSONStream* js) {
  if (js->num_arguments() != 4 && js->num_arguments() != 5) {
    PrintError(js, "Command should have 4 or 5 arguments");
    return true;
  }
  const char* encoded_id = js->GetArgument(3);
  String& id = String::Handle(isolate, String::New(encoded_id));
  id = String::DecodeIRI(id);
  if (id.IsNull()) {
    PrintError(js, "Function id %s is malformed", encoded_id);
    return true;
  }
  Function& func = Function::Handle(cls.LookupFunction(id));
  if (func.IsNull()) {
    PrintError(js, "Function %s not found", encoded_id);
    return true;
  }
  if (js->num_arguments() == 4) {
    func.PrintJSON(js, false);
    return true;
  } else {
    const char* subcommand = js->GetArgument(4);
    if (strcmp(subcommand, "coverage") == 0) {
      return HandleClassesFunctionsCoverage(isolate, func, js);
    } else if (strcmp(subcommand, "set_source") == 0) {
      return HandleFunctionSetSource(isolate, cls, func, js);
    } else {
      PrintError(js, "Invalid sub command %s", subcommand);
      return true;
    }
  }
  UNREACHABLE();
  return true;
}


static bool HandleClassesImplicitClosures(Isolate* isolate, const Class& cls,
                                          JSONStream* js) {
  intptr_t id;
  if (js->num_arguments() > 4) {
    PrintError(js, "Command too long");
    return true;
  }
  if (!GetIntegerId(js->GetArgument(3), &id)) {
    PrintError(js, "Must specify collection object id: implicit_closures/id");
    return true;
  }
  Function& func = Function::Handle();
  func ^= cls.ImplicitClosureFunctionFromIndex(id);
  if (func.IsNull()) {
    PrintError(js, "Implicit closure function %" Pd " not found", id);
    return true;
  }
  func.PrintJSON(js, false);
  return true;
}


static bool HandleClassesFields(Isolate* isolate, const Class& cls,
                                JSONStream* js) {
  intptr_t id;
  if (js->num_arguments() > 4) {
    PrintError(js, "Command too long");
    return true;
  }
  if (!GetIntegerId(js->GetArgument(3), &id)) {
    PrintError(js, "Must specify collection object id: fields/id");
    return true;
  }
  Field& field = Field::Handle(cls.FieldFromIndex(id));
  if (field.IsNull()) {
    PrintError(js, "Field %" Pd " not found", id);
    return true;
  }
  field.PrintJSON(js, false);
  return true;
}


static bool HandleClassesTypes(Isolate* isolate, const Class& cls,
                               JSONStream* js) {
  if (js->num_arguments() == 3) {
    JSONObject jsobj(js);
    jsobj.AddProperty("type", "TypeList");
    JSONArray members(&jsobj, "members");
    const intptr_t num_types = cls.NumCanonicalTypes();
    Type& type = Type::Handle();
    for (intptr_t i = 0; i < num_types; i++) {
      type = cls.CanonicalTypeFromIndex(i);
      members.AddValue(type);
    }
    return true;
  }
  ASSERT(js->num_arguments() >= 4);
  intptr_t id;
  if (!GetIntegerId(js->GetArgument(3), &id)) {
    PrintError(js, "Must specify collection object id: types/id");
    return true;
  }
  Type& type = Type::Handle();
  type ^= cls.CanonicalTypeFromIndex(id);
  if (type.IsNull()) {
    PrintError(js, "Canonical type %" Pd " not found", id);
    return true;
  }
  if (js->num_arguments() == 4) {
    type.PrintJSON(js, false);
    return true;
  }
  return HandleInstanceCommands(isolate, &type, ObjectIdRing::kValid, js, 4);
}


static bool HandleClassesRetained(Isolate* isolate, const Class& cls,
                                  JSONStream* js) {
  if (js->num_arguments() != 3) {
    PrintError(js, "Command too long");
    return true;
  }
  ObjectGraph graph(isolate);
  intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
  const Object& result = Object::Handle(Integer::New(retained_size));
  result.PrintJSON(js, true);
  return true;
}


class GetInstancesVisitor : public ObjectGraph::Visitor {
 public:
  GetInstancesVisitor(const Class& cls, const Array& storage)
      : cls_(cls), storage_(storage), count_(0) {}

  virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
    RawObject* raw_obj = it->Get();
    if (raw_obj->IsFreeListElement()) {
      return kProceed;
    }
    Isolate* isolate = Isolate::Current();
    REUSABLE_OBJECT_HANDLESCOPE(isolate);
    Object& obj = isolate->ObjectHandle();
    obj = raw_obj;
    if (obj.GetClassId() == cls_.id()) {
      if (!storage_.IsNull() && count_ < storage_.Length()) {
        storage_.SetAt(count_, obj);
      }
      ++count_;
    }
    return kProceed;
  }

  intptr_t count() const { return count_; }

 private:
  const Class& cls_;
  const Array& storage_;
  intptr_t count_;
};


static bool HandleClassesInstances(Isolate* isolate, const Class& cls,
                                   JSONStream* js) {
  if (js->num_arguments() != 3) {
    PrintError(js, "Command too long");
    return true;
  }
  intptr_t limit;
  if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
    PrintError(js, "instances expects a 'limit' option\n",
               js->num_arguments());
    return true;
  }
  Array& storage = Array::Handle(Array::New(limit));
  GetInstancesVisitor visitor(cls, storage);
  ObjectGraph graph(isolate);
  graph.IterateObjects(&visitor);
  intptr_t count = visitor.count();
  if (count < limit) {
    // Truncate the list using utility method for GrowableObjectArray.
    GrowableObjectArray& wrapper = GrowableObjectArray::Handle(
        GrowableObjectArray::New(storage));
    wrapper.SetLength(count);
    storage = Array::MakeArray(wrapper);
  }
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "InstanceSet");
  jsobj.AddProperty("id", "instance_set");
  jsobj.AddProperty("totalCount", count);
  jsobj.AddProperty("sampleCount", storage.Length());
  jsobj.AddProperty("sample", storage);
  return true;
}


static bool HandleClassesCoverage(Isolate* isolate,
                                  const Class& cls,
                                  JSONStream* stream) {
  ClassCoverageFilter cf(cls);
  CodeCoverage::PrintJSON(isolate, stream, &cf);
  return true;
}


static bool HandleClasses(Isolate* isolate, JSONStream* js) {
  if (js->num_arguments() == 1) {
    ClassTable* table = isolate->class_table();
    JSONObject jsobj(js);
    table->PrintToJSONObject(&jsobj);
    return true;
  }
  ASSERT(js->num_arguments() >= 2);
  intptr_t id;
  if (!GetIntegerId(js->GetArgument(1), &id)) {
    PrintError(js, "Must specify collection object id: /classes/id");
    return true;
  }
  ClassTable* table = isolate->class_table();
  if (!table->IsValidIndex(id)) {
    PrintError(js, "%" Pd " is not a valid class id.", id);
    return true;
  }
  Class& cls = Class::Handle(table->At(id));
  if (js->num_arguments() == 2) {
    cls.PrintJSON(js, false);
    return true;
  } else if (js->num_arguments() >= 3) {
    const char* second = js->GetArgument(2);
    if (strcmp(second, "eval") == 0) {
      return HandleClassesEval(isolate, cls, js);
    } else if (strcmp(second, "closures") == 0) {
      return HandleClassesClosures(isolate, cls, js);
    } else if (strcmp(second, "fields") == 0) {
      return HandleClassesFields(isolate, cls, js);
    } else if (strcmp(second, "functions") == 0) {
      return HandleClassesFunctions(isolate, cls, js);
    } else if (strcmp(second, "implicit_closures") == 0) {
      return HandleClassesImplicitClosures(isolate, cls, js);
    } else if (strcmp(second, "dispatchers") == 0) {
      return HandleClassesDispatchers(isolate, cls, js);
    } else if (strcmp(second, "types") == 0) {
      return HandleClassesTypes(isolate, cls, js);
    } else if (strcmp(second, "retained") == 0) {
      return HandleClassesRetained(isolate, cls, js);
    } else if (strcmp(second, "instances") == 0) {
      return HandleClassesInstances(isolate, cls, js);
    } else if (strcmp(second, "coverage") == 0) {
      return HandleClassesCoverage(isolate, cls, js);
    } else {
      PrintError(js, "Invalid sub collection %s", second);
      return true;
    }
  }
  UNREACHABLE();
  return true;
}


static bool HandleLibrariesEval(Isolate* isolate, const Library& lib,
                                JSONStream* js) {
  if (js->num_arguments() > 3) {
    PrintError(js, "Command too long");
    return true;
  }
  const char* expr = js->LookupOption("expr");
  if (expr == NULL) {
    PrintError(js, "eval expects an 'expr' option\n",
               js->num_arguments());
    return true;
  }
  const String& expr_str = String::Handle(isolate, String::New(expr));
  const Object& result = Object::Handle(lib.Evaluate(expr_str,
                                                     Array::empty_array(),
                                                     Array::empty_array()));
  result.PrintJSON(js, true);
  return true;
}


static bool HandleLibrariesScriptsCoverage(
    Isolate* isolate, const Script& script, JSONStream* js) {
  ScriptCoverageFilter sf(script);
  CodeCoverage::PrintJSON(isolate, js, &sf);
  return true;
}


static bool HandleLibrariesScriptsSetBreakpoint(
    Isolate* isolate, const Script& script, JSONStream* js) {
  if (!js->HasOption("line")) {
    PrintError(js, "Missing 'line' option");
    return true;
  }
  const char* line_option = js->LookupOption("line");
  intptr_t line = -1;
  if (!GetIntegerId(line_option, &line)) {
    PrintError(js, "Invalid 'line' value: %s", line_option);
    return true;
  }
  const String& script_url = String::Handle(script.url());
  SourceBreakpoint* bpt =
      isolate->debugger()->SetBreakpointAtLine(script_url, line);
  if (bpt == NULL) {
    PrintError(js, "Unable to set breakpoint at line %s", line_option);
    return true;
  }
  bpt->PrintJSON(js);
  return true;
}


static bool HandleLibrariesScripts(Isolate* isolate,
                                   const Library& lib,
                                   JSONStream* js) {
  if (js->num_arguments() > 5) {
    PrintError(js, "Command too long");
    return true;
  } else if (js->num_arguments() < 4) {
    PrintError(js, "Must specify collection object id: scripts/id");
    return true;
  }
  const String& id = String::Handle(String::New(js->GetArgument(3)));
  ASSERT(!id.IsNull());
  // The id is the url of the script % encoded, decode it.
  const String& requested_url = String::Handle(String::DecodeIRI(id));
  Script& script = Script::Handle();
  String& script_url = String::Handle();
  const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
  ASSERT(!loaded_scripts.IsNull());
  intptr_t i;
  for (i = 0; i < loaded_scripts.Length(); i++) {
    script ^= loaded_scripts.At(i);
    ASSERT(!script.IsNull());
    script_url ^= script.url();
    if (script_url.Equals(requested_url)) {
      break;
    }
  }
  if (i == loaded_scripts.Length()) {
    PrintError(js, "Script %s not found", requested_url.ToCString());
    return true;
  }
  if (js->num_arguments() == 4) {
    script.PrintJSON(js, false);
    return true;
  } else {
    const char* subcollection = js->GetArgument(4);
    if (strcmp(subcollection, "coverage") == 0) {
      return HandleLibrariesScriptsCoverage(isolate, script, js);
    } else if (strcmp(subcollection, "setBreakpoint") == 0) {
      return HandleLibrariesScriptsSetBreakpoint(isolate, script, js);
    } else {
      PrintError(js, "Invalid sub collection %s", subcollection);
      return true;
    }
  }
  UNREACHABLE();
  return true;
}


static bool HandleLibrariesCoverage(Isolate* isolate,
                                    const Library& lib,
                                    JSONStream* js) {
  LibraryCoverageFilter lf(lib);
  CodeCoverage::PrintJSON(isolate, js, &lf);
  return true;
}


static bool HandleLibraries(Isolate* isolate, JSONStream* js) {
  // TODO(johnmccutchan): Support fields and functions on libraries.
  REQUIRE_COLLECTION_ID("libraries");
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate->object_store()->libraries());
  ASSERT(!libs.IsNull());
  intptr_t id = 0;
  CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
                             id, js);
  Library& lib = Library::Handle();
  lib ^= libs.At(id);
  ASSERT(!lib.IsNull());
  if (js->num_arguments() == 2) {
    lib.PrintJSON(js, false);
    return true;
  } else if (js->num_arguments() >= 3) {
    const char* second = js->GetArgument(2);
    if (strcmp(second, "eval") == 0) {
      return HandleLibrariesEval(isolate, lib, js);
    } else if (strcmp(second, "scripts") == 0) {
      return HandleLibrariesScripts(isolate, lib, js);
    } else if (strcmp(second, "coverage") == 0) {
      return HandleLibrariesCoverage(isolate, lib, js);
    } else {
      PrintError(js, "Invalid sub collection %s", second);
      return true;
    }
  }
  UNREACHABLE();
  return true;
}


static void PrintSentinel(JSONStream* js,
                          const char* id,
                          const char* preview) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Sentinel");
  jsobj.AddProperty("id", id);
  jsobj.AddProperty("valueAsString", preview);
}


static RawObject* LookupObjectId(Isolate* isolate,
                                 const char* arg,
                                 ObjectIdRing::LookupResult* kind) {
  *kind = ObjectIdRing::kValid;
  if (strncmp(arg, "int-", 4) == 0) {
    arg += 4;
    int64_t value = 0;
    if (!OS::StringToInt64(arg, &value) ||
        !Smi::IsValid(value)) {
      *kind = ObjectIdRing::kInvalid;
      return Object::null();
    }
    const Integer& obj =
        Integer::Handle(isolate, Smi::New(static_cast<intptr_t>(value)));
    return obj.raw();
  } else if (strcmp(arg, "bool-true") == 0) {
    return Bool::True().raw();
  } else if (strcmp(arg, "bool-false") == 0) {
    return Bool::False().raw();
  } else if (strcmp(arg, "null") == 0) {
    return Object::null();
  } else if (strcmp(arg, "not-initialized") == 0) {
    return Object::sentinel().raw();
  } else if (strcmp(arg, "being-initialized") == 0) {
    return Object::transition_sentinel().raw();
  }

  ObjectIdRing* ring = isolate->object_id_ring();
  ASSERT(ring != NULL);
  intptr_t id = -1;
  if (!GetIntegerId(arg, &id)) {
    *kind = ObjectIdRing::kInvalid;
    return Object::null();
  }
  return ring->GetObjectForId(id, kind);
}


static RawClass* GetMetricsClass(Isolate* isolate) {
  const Library& prof_lib =
      Library::Handle(isolate, Library::ProfilerLibrary());
  ASSERT(!prof_lib.IsNull());
  const String& metrics_cls_name =
      String::Handle(isolate, String::New("Metrics"));
  ASSERT(!metrics_cls_name.IsNull());
  const Class& metrics_cls =
      Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name));
  ASSERT(!metrics_cls.IsNull());
  return metrics_cls.raw();
}


static bool HandleIsolateMetricsList(Isolate* isolate, JSONStream* js) {
  JSONObject obj(js);
  obj.AddProperty("type", "MetricList");
  obj.AddProperty("id", "metrics/vm");
  {
    JSONArray members(&obj, "members");
    Metric* current = isolate->metrics_list_head();
    while (current != NULL) {
      members.AddValue(current);
      current = current->next();
    }
  }
  return true;
}


static bool HandleIsolateMetric(Isolate* isolate,
                                JSONStream* js,
                                const char* id) {
  Metric* current = isolate->metrics_list_head();
  while (current != NULL) {
    const char* name = current->name();
    ASSERT(name != NULL);
    if (strcmp(name, id) == 0) {
      current->PrintJSON(js);
      return true;
    }
    current = current->next();
  }
  PrintError(js, "Metric %s not found\n", id);
  return true;
}


static bool HandleMetricsList(Isolate* isolate, JSONStream* js) {
  const Class& metrics_cls = Class::Handle(isolate, GetMetricsClass(isolate));
  const String& print_metrics_name =
      String::Handle(String::New("_printMetrics"));
  ASSERT(!print_metrics_name.IsNull());
  const Function& print_metrics = Function::Handle(
      isolate,
      metrics_cls.LookupStaticFunctionAllowPrivate(print_metrics_name));
  ASSERT(!print_metrics.IsNull());
  const Array& args = Object::empty_array();
  const Object& result =
      Object::Handle(isolate, DartEntry::InvokeFunction(print_metrics, args));
  ASSERT(!result.IsNull());
  ASSERT(result.IsString());
  TextBuffer* buffer = js->buffer();
  buffer->AddString(String::Cast(result).ToCString());
  return true;
}


static bool HandleMetric(Isolate* isolate, JSONStream* js, const char* id) {
  const Class& metrics_cls = Class::Handle(isolate, GetMetricsClass(isolate));
  const String& print_metric_name =
      String::Handle(String::New("_printMetric"));
  ASSERT(!print_metric_name.IsNull());
  const Function& print_metric = Function::Handle(
      isolate,
      metrics_cls.LookupStaticFunctionAllowPrivate(print_metric_name));
  ASSERT(!print_metric.IsNull());
  const String& arg0 = String::Handle(String::New(id));
  ASSERT(!arg0.IsNull());
  const Array& args = Array::Handle(Array::New(1));
  ASSERT(!args.IsNull());
  args.SetAt(0, arg0);
  const Object& result =
      Object::Handle(isolate, DartEntry::InvokeFunction(print_metric, args));
  if (!result.IsNull()) {
    ASSERT(result.IsString());
    TextBuffer* buffer = js->buffer();
    buffer->AddString(String::Cast(result).ToCString());
    return true;
  }
  PrintError(js, "Metric %s not found\n", id);
  return true;
}


static bool HandleMetrics(Isolate* isolate, JSONStream* js) {
  if (js->num_arguments() == 1) {
    return HandleMetricsList(isolate, js);
  }
  ASSERT(js->num_arguments() > 1);
  const char* arg = js->GetArgument(1);
  if (strcmp(arg, "vm") == 0) {
    if (js->num_arguments() == 2) {
      return HandleIsolateMetricsList(isolate, js);
    } else {
      if (js->num_arguments() > 3) {
        PrintError(js, "Command too long");
        return true;
      }
      return HandleIsolateMetric(isolate, js, js->GetArgument(2));
    }
  }
  if (js->num_arguments() > 2) {
    PrintError(js, "Command too long");
    return true;
  }
  return HandleMetric(isolate, js, arg);
}


static bool HandleObjects(Isolate* isolate, JSONStream* js) {
  REQUIRE_COLLECTION_ID("objects");
  if (js->num_arguments() < 2) {
    PrintError(js, "expected at least 2 arguments but found %" Pd "\n",
               js->num_arguments());
    return true;
  }
  const char* arg = js->GetArgument(1);

  // Handle special non-objects first.
  if (strcmp(arg, "optimized-out") == 0) {
    if (js->num_arguments() > 2) {
      PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
                 js->num_arguments());
    } else {
      Symbols::OptimizedOut().PrintJSON(js, false);
    }
    return true;

  } else if (strcmp(arg, "collected") == 0) {
    if (js->num_arguments() > 2) {
      PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
                 js->num_arguments());
    } else {
      PrintSentinel(js, "objects/collected", "<collected>");
    }
    return true;

  } else if (strcmp(arg, "expired") == 0) {
    if (js->num_arguments() > 2) {
      PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
                 js->num_arguments());
    } else {
      PrintSentinel(js, "objects/expired", "<expired>");
    }
    return true;
  }

  // Lookup the object.
  Object& obj = Object::Handle(isolate);
  ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
  obj = LookupObjectId(isolate, arg, &kind);
  if (kind == ObjectIdRing::kInvalid) {
    PrintError(js, "unrecognized object id '%s'", arg);
    return true;
  }
  if (js->num_arguments() == 2) {
    // Print.
    if (kind == ObjectIdRing::kCollected) {
      // The object has been collected by the gc.
      PrintSentinel(js, "objects/collected", "<collected>");
      return true;
    } else if (kind == ObjectIdRing::kExpired) {
      // The object id has expired.
      PrintSentinel(js, "objects/expired", "<expired>");
      return true;
    }
    obj.PrintJSON(js, false);
    return true;
  }
  return HandleInstanceCommands(isolate, &obj, kind, js, 2);
}


static bool HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "ScriptList");
  jsobj.AddProperty("id", "scripts");
  JSONArray members(&jsobj, "members");
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate->object_store()->libraries());
  intptr_t num_libs = libs.Length();
  Library &lib = Library::Handle();
  Script& script = Script::Handle();
  for (intptr_t i = 0; i < num_libs; i++) {
    lib ^= libs.At(i);
    ASSERT(!lib.IsNull());
    ASSERT(Smi::IsValid(lib.index()));
    const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
    ASSERT(!loaded_scripts.IsNull());
    intptr_t num_scripts = loaded_scripts.Length();
    for (intptr_t i = 0; i < num_scripts; i++) {
      script ^= loaded_scripts.At(i);
      members.AddValue(script);
    }
  }
  return true;
}


static bool HandleScripts(Isolate* isolate, JSONStream* js) {
  if (js->num_arguments() == 1) {
    // Enumerate all scripts.
    return HandleScriptsEnumerate(isolate, js);
  }
  PrintError(js, "Command too long");
  return true;
}


static bool HandleDebugResume(Isolate* isolate,
                              const char* step_option,
                              JSONStream* js) {
  if (isolate->message_handler()->paused_on_start()) {
    isolate->message_handler()->set_pause_on_start(false);
    JSONObject jsobj(js);
    jsobj.AddProperty("type", "Success");
    jsobj.AddProperty("id", "");
    return true;
  }
  if (isolate->message_handler()->paused_on_exit()) {
    isolate->message_handler()->set_pause_on_exit(false);
    JSONObject jsobj(js);
    jsobj.AddProperty("type", "Success");
    jsobj.AddProperty("id", "");
    return true;
  }
  if (isolate->debugger()->PauseEvent() != NULL) {
    if (step_option != NULL) {
      if (strcmp(step_option, "into") == 0) {
        isolate->debugger()->SetSingleStep();
      } else if (strcmp(step_option, "over") == 0) {
        isolate->debugger()->SetStepOver();
      } else if (strcmp(step_option, "out") == 0) {
        isolate->debugger()->SetStepOut();
      } else {
        PrintError(js, "Invalid 'step' option: %s", step_option);
        return true;
      }
    }
    isolate->Resume();
    JSONObject jsobj(js);
    jsobj.AddProperty("type", "Success");
    jsobj.AddProperty("id", "");
    return true;
  }

  PrintError(js, "VM was not paused");
  return true;
}


static bool HandleDebug(Isolate* isolate, JSONStream* js) {
  if (js->num_arguments() == 1) {
    PrintError(js, "Must specify a subcommand");
    return true;
  }
  const char* command = js->GetArgument(1);
  if (strcmp(command, "breakpoints") == 0) {
    if (js->num_arguments() == 2) {
      // Print breakpoint list.
      JSONObject jsobj(js);
      jsobj.AddProperty("type", "BreakpointList");
      jsobj.AddProperty("id", "debug/breakpoints");
      JSONArray jsarr(&jsobj, "breakpoints");
      isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
      return true;
    } else {
      intptr_t id = 0;
      SourceBreakpoint* bpt = NULL;
      if (GetIntegerId(js->GetArgument(2), &id)) {
        bpt = isolate->debugger()->GetBreakpointById(id);
      }
      if (bpt == NULL) {
        PrintError(js, "Unrecognized breakpoint id: %s", js->GetArgument(2));
        return true;
      }
      if (js->num_arguments() == 3) {
        // Print individual breakpoint.
        bpt->PrintJSON(js);
        return true;
      } else if (js->num_arguments() == 4) {
        const char* sub_command = js->GetArgument(3);
        if (strcmp(sub_command, "clear") == 0) {
          // Clear this breakpoint.
          isolate->debugger()->RemoveBreakpoint(id);

          JSONObject jsobj(js);
          jsobj.AddProperty("type", "Success");
          jsobj.AddProperty("id", "");
          return true;
        } else {
          PrintError(js, "Unrecognized subcommand: %s", sub_command);
          return true;
        }
      } else {
        PrintError(js, "Command too long");
        return true;
      }
    }
  } else if (strcmp(command, "pause") == 0) {
    if (js->num_arguments() == 2) {
      // TODO(turnidge): Don't double-interrupt the isolate here.
      isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
      JSONObject jsobj(js);
      jsobj.AddProperty("type", "Success");
      jsobj.AddProperty("id", "");
      return true;
    } else {
      PrintError(js, "Command too long");
      return true;
    }
  } else if (strcmp(command, "resume") == 0) {
    if (js->num_arguments() == 2) {
      const char* step_option = js->LookupOption("step");
      return HandleDebugResume(isolate, step_option, js);
    } else {
      PrintError(js, "Command too long");
      return true;
    }
  } else {
    PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1));
    return true;
  }
}


static bool HandleNullCode(uintptr_t pc, JSONStream* js) {
  // TODO(turnidge): Consider adding/using Object::null_code() for
  // consistent "type".
  Object::null_object().PrintJSON(js, false);
  return true;
}


static bool HandleCode(Isolate* isolate, JSONStream* js) {
  REQUIRE_COLLECTION_ID("code");
  uword pc;
  if (js->num_arguments() > 2) {
    PrintError(js, "Command too long");
    return true;
  }
  ASSERT(js->num_arguments() == 2);
  static const char* kCollectedPrefix = "collected-";
  static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix);
  static const char* kNativePrefix = "native-";
  static intptr_t kNativePrefixLen = strlen(kNativePrefix);
  static const char* kReusedPrefix = "reused-";
  static intptr_t kReusedPrefixLen = strlen(kReusedPrefix);
  const char* command = js->GetArgument(1);
  if (strncmp(kCollectedPrefix, command, kCollectedPrefixLen) == 0) {
    if (!GetUnsignedIntegerId(&command[kCollectedPrefixLen], &pc, 16)) {
      PrintError(js, "Must specify code address: code/%sc0deadd0.",
                 kCollectedPrefix);
      return true;
    }
    return HandleNullCode(pc, js);
  }
  if (strncmp(kNativePrefix, command, kNativePrefixLen) == 0) {
    if (!GetUnsignedIntegerId(&command[kNativePrefixLen], &pc, 16)) {
      PrintError(js, "Must specify code address: code/%sc0deadd0.",
                 kNativePrefix);
      return true;
    }
    // TODO(johnmccutchan): Support native Code.
    return HandleNullCode(pc, js);
  }
  if (strncmp(kReusedPrefix, command, kReusedPrefixLen) == 0) {
    if (!GetUnsignedIntegerId(&command[kReusedPrefixLen], &pc, 16)) {
      PrintError(js, "Must specify code address: code/%sc0deadd0.",
                 kReusedPrefix);
      return true;
    }
    return HandleNullCode(pc, js);
  }
  int64_t timestamp = 0;
  if (!GetCodeId(command, &timestamp, &pc) || (timestamp < 0)) {
    PrintError(js, "Malformed code id: %s", command);
    return true;
  }
  Code& code = Code::Handle(Code::FindCode(pc, timestamp));
  if (!code.IsNull()) {
    code.PrintJSON(js, false);
    return true;
  }
  PrintError(js, "Could not find code with id: %s", command);
  return true;
}


static bool HandleProfile(Isolate* isolate, JSONStream* js) {
  if (js->num_arguments() == 2) {
    const char* sub_command = js->GetArgument(1);
    if (!strcmp(sub_command, "tag")) {
      {
        JSONObject miniProfile(js);
        miniProfile.AddProperty("type", "TagProfile");
        miniProfile.AddProperty("id", "profile/tag");
        isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile);
      }
      return true;
    } else {
      PrintError(js, "Unrecognized subcommand '%s'", sub_command);
      return true;
    }
  }
  // A full profile includes disassembly of all Dart code objects.
  // TODO(johnmccutchan): Add sub command to trigger full code dump.
  bool full_profile = false;
  const char* tags_option = js->LookupOption("tags");
  Profiler::TagOrder tag_order = Profiler::kUserVM;
  if (js->HasOption("tags")) {
    if (js->OptionIs("tags", "hide")) {
      tag_order = Profiler::kNoTags;
    } else if (js->OptionIs("tags", "uv")) {
      tag_order = Profiler::kUserVM;
    } else if (js->OptionIs("tags", "u")) {
      tag_order = Profiler::kUser;
    } else if (js->OptionIs("tags", "vu")) {
      tag_order = Profiler::kVMUser;
    } else if (js->OptionIs("tags", "v")) {
      tag_order = Profiler::kVM;
    } else {
      PrintError(js, "Invalid tags option value: %s\n", tags_option);
      return true;
    }
  }
  Profiler::PrintJSON(isolate, js, full_profile, tag_order);
  return true;
}

static bool HandleCoverage(Isolate* isolate, JSONStream* js) {
  CodeCoverage::PrintJSON(isolate, js, NULL);
  return true;
}


static bool HandleAllocationProfile(Isolate* isolate, JSONStream* js) {
  bool should_reset_accumulator = false;
  bool should_collect = false;
  if (js->num_arguments() != 1) {
    PrintError(js, "Command too long");
    return true;
  }
  if (js->HasOption("reset")) {
    if (js->OptionIs("reset", "true")) {
      should_reset_accumulator = true;
    } else {
      PrintError(js, "Unrecognized reset option '%s'",
                 js->LookupOption("reset"));
      return true;
    }
  }
  if (js->HasOption("gc")) {
    if (js->OptionIs("gc", "full")) {
      should_collect = true;
    } else {
      PrintError(js, "Unrecognized gc option '%s'", js->LookupOption("gc"));
      return true;
    }
  }
  if (should_reset_accumulator) {
    isolate->UpdateLastAllocationProfileAccumulatorResetTimestamp();
    isolate->class_table()->ResetAllocationAccumulators();
  }
  if (should_collect) {
    isolate->UpdateLastAllocationProfileGCTimestamp();
    isolate->heap()->CollectAllGarbage();
  }
  isolate->class_table()->AllocationProfilePrintJSON(js);
  return true;
}


static bool HandleTypeArguments(Isolate* isolate, JSONStream* js) {
  ObjectStore* object_store = isolate->object_store();
  const Array& table = Array::Handle(object_store->canonical_type_arguments());
  ASSERT(table.Length() > 0);
  TypeArguments& type_args = TypeArguments::Handle();
  const intptr_t table_size = table.Length() - 1;
  const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size)));
  bool only_with_instantiations = false;
  if (js->num_arguments() >= 2) {
    const char* second = js->GetArgument(1);
    if (strcmp(second, "withinstantiations") == 0) {
      only_with_instantiations = true;
      if (js->num_arguments() > 2) {
        PrintError(js, "Command too long");
        return true;
      }
    }
  }
  if ((js->num_arguments() == 1) || only_with_instantiations) {
    JSONObject jsobj(js);
    jsobj.AddProperty("type", "TypeArgumentsList");
    jsobj.AddProperty("table_size", table_size);
    jsobj.AddProperty("table_used", table_used);
    JSONArray members(&jsobj, "members");
    for (intptr_t i = 0; i < table_size; i++) {
      type_args ^= table.At(i);
      if (!type_args.IsNull()) {
        if (!only_with_instantiations || type_args.HasInstantiations()) {
          members.AddValue(type_args);
        }
      }
    }
    return true;
  }
  ASSERT((js->num_arguments() >= 2) && !only_with_instantiations);
  intptr_t id;
  if (!GetIntegerId(js->GetArgument(1), &id)) {
    // Note that the table index of the canonical type arguments will change
    // when the table grows. Should we not support this access at all?
    PrintError(js, "Must specify collection object id: /typearguments/id");
    return true;
  }
  if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) {
    PrintError(js, "%" Pd " is not a valid typearguments id.", id);
    return true;
  }
  type_args ^= table.At(id);
  type_args.PrintJSON(js, false);
  return true;
}


static bool HandleHeapMap(Isolate* isolate, JSONStream* js) {
  isolate->heap()->PrintHeapMapToJSONStream(isolate, js);
  return true;
}


static bool HandleGraph(Isolate* isolate, JSONStream* js) {
  Service::SendGraphEvent(isolate);
  // TODO(koda): Provide some id that ties this request to async response(s).
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "OK");
  jsobj.AddProperty("id", "ok");
  return true;
}


void Service::SendGraphEvent(Isolate* isolate) {
  uint8_t* buffer = NULL;
  WriteStream stream(&buffer, &allocator, 1 * MB);
  ObjectGraph graph(isolate);
  graph.Serialize(&stream);
  JSONStream js;
  {
    JSONObject jsobj(&js);
    jsobj.AddProperty("type", "ServiceEvent");
    jsobj.AddPropertyF("id", "_graphEvent");
    jsobj.AddProperty("eventType", "_Graph");
    jsobj.AddProperty("isolate", isolate);
  }
  const String& message = String::Handle(String::New(js.ToCString()));
  SendEvent(kEventFamilyDebug, message, buffer, stream.bytes_written());
}


class ContainsAddressVisitor : public FindObjectVisitor {
 public:
  ContainsAddressVisitor(Isolate* isolate, uword addr)
      : FindObjectVisitor(isolate), addr_(addr) { }
  virtual ~ContainsAddressVisitor() { }

  virtual uword filter_addr() const { return addr_; }

  virtual bool FindObject(RawObject* obj) const {
    // Free list elements are not real objects, so skip them.
    if (obj->IsFreeListElement()) {
      return false;
    }
    uword obj_begin = RawObject::ToAddr(obj);
    uword obj_end = obj_begin + obj->Size();
    return obj_begin <= addr_ && addr_ < obj_end;
  }
 private:
  uword addr_;
};


static bool HandleAddress(Isolate* isolate, JSONStream* js) {
  uword addr = 0;
  if (js->num_arguments() != 2 ||
      !GetUnsignedIntegerId(js->GetArgument(1), &addr, 16)) {
    static const uword kExampleAddr = static_cast<uword>(kIntptrMax / 7);
    PrintError(js, "Must specify address: address/" Px ".", kExampleAddr);
    return true;
  }
  bool ref = js->HasOption("ref") && js->OptionIs("ref", "true");
  Object& object = Object::Handle(isolate);
  {
    NoGCScope no_gc;
    ContainsAddressVisitor visitor(isolate, addr);
    object = isolate->heap()->FindObject(&visitor);
  }
  object.PrintJSON(js, ref);
  return true;
}


static bool HandleMalformedJson(Isolate* isolate, JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("a", "a");
  JSONObject jsobj1(js);
  jsobj1.AddProperty("a", "a");
  JSONObject jsobj2(js);
  jsobj2.AddProperty("a", "a");
  JSONObject jsobj3(js);
  jsobj3.AddProperty("a", "a");
  return true;
}


static bool HandleMalformedObject(Isolate* isolate, JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("bart", "simpson");
  return true;
}


static IsolateMessageHandlerEntry isolate_handlers[] = {
  { "_malformedjson", HandleMalformedJson },
  { "_malformedobject", HandleMalformedObject },
  { "_echo", HandleIsolateEcho },
  { "", HandleIsolate },
  { "address", HandleAddress },
  { "allocationprofile", HandleAllocationProfile },
  { "classes", HandleClasses },
  { "code", HandleCode },
  { "coverage", HandleCoverage },
  { "debug", HandleDebug },
  { "graph", HandleGraph },
  { "heapmap", HandleHeapMap },
  { "libraries", HandleLibraries },
  { "metrics", HandleMetrics },
  { "objects", HandleObjects },
  { "profile", HandleProfile },
  { "scripts", HandleScripts },
  { "stacktrace", HandleStackTrace },
  { "typearguments", HandleTypeArguments },
};


static IsolateMessageHandler FindIsolateMessageHandler(const char* command) {
  intptr_t num_message_handlers = sizeof(isolate_handlers) /
                                  sizeof(isolate_handlers[0]);
  for (intptr_t i = 0; i < num_message_handlers; i++) {
    const IsolateMessageHandlerEntry& entry = isolate_handlers[i];
    if (strcmp(command, entry.command) == 0) {
      return entry.handler;
    }
  }
  if (FLAG_trace_service) {
    OS::Print("Service has no isolate message handler for <%s>\n", command);
  }
  return NULL;
}


void Service::HandleRootMessage(const Instance& msg) {
  Isolate* isolate = Isolate::Current();
  ASSERT(!msg.IsNull());
  ASSERT(msg.IsArray());

  {
    StackZone zone(isolate);
    HANDLESCOPE(isolate);

    const Array& message = Array::Cast(msg);
    // Message is a list with five entries.
    ASSERT(message.Length() == 5);

    Instance& reply_port = Instance::Handle(isolate);
    GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
    Array& option_keys = Array::Handle(isolate);
    Array& option_values = Array::Handle(isolate);

    reply_port ^= message.At(1);
    path ^= message.At(2);
    option_keys ^= message.At(3);
    option_values ^= message.At(4);

    ASSERT(!path.IsNull());
    ASSERT(!option_keys.IsNull());
    ASSERT(!option_values.IsNull());
    // Path always has at least one entry in it.
    ASSERT(path.Length() > 0);
    // Same number of option keys as values.
    ASSERT(option_keys.Length() == option_values.Length());

    if (!reply_port.IsSendPort()) {
      FATAL("SendPort expected.");
    }

    String& path_segment = String::Handle();
    if (path.Length() > 0) {
      path_segment ^= path.At(0);
    } else {
      path_segment ^= Symbols::Empty().raw();
    }
    ASSERT(!path_segment.IsNull());
    const char* path_segment_c = path_segment.ToCString();

    RootMessageHandler handler =
        FindRootMessageHandler(path_segment_c);
    {
      JSONStream js;
      js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
               path, option_keys, option_values);
      if (handler == NULL) {
        // Check for an embedder handler.
        EmbedderServiceHandler* e_handler =
            FindRootEmbedderHandler(path_segment_c);
        if (e_handler != NULL) {
          EmbedderHandleMessage(e_handler, &js);
        } else {
          PrintError(&js, "Unrecognized path");
        }
        js.PostReply();
      } else {
        if (handler(&js)) {
          // Handler returns true if the reply is ready to be posted.
          // TODO(johnmccutchan): Support asynchronous replies.
          js.PostReply();
        }
      }
    }
  }
}


static bool HandleRootEcho(JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("id", "_echo");
  return HandleCommonEcho(&jsobj, js);
}


class ServiceIsolateVisitor : public IsolateVisitor {
 public:
  explicit ServiceIsolateVisitor(JSONArray* jsarr)
      : jsarr_(jsarr) {
  }

  virtual ~ServiceIsolateVisitor() {}

  void VisitIsolate(Isolate* isolate) {
    if (isolate != Dart::vm_isolate() && !Service::IsServiceIsolate(isolate)) {
      jsarr_->AddValue(isolate);
    }
  }

 private:
  JSONArray* jsarr_;
};


static bool HandleVM(JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "VM");
  jsobj.AddProperty("id", "vm");
  jsobj.AddProperty("architectureBits", static_cast<intptr_t>(kBitsPerWord));
  jsobj.AddProperty("targetCPU", CPU::Id());
  jsobj.AddProperty("hostCPU", HostCPUFeatures::hardware());
  jsobj.AddPropertyF("date", "%" Pd64 "", OS::GetCurrentTimeMillis());
  jsobj.AddProperty("version", Version::String());
  // Send pid as a string because it allows us to avoid any issues with
  // pids > 53-bits (when consumed by JavaScript).
  // TODO(johnmccutchan): Codify how integers are sent across the service.
  jsobj.AddPropertyF("pid", "%" Pd "", OS::ProcessId());
  jsobj.AddProperty("assertsEnabled", FLAG_enable_asserts);
  jsobj.AddProperty("typeChecksEnabled", FLAG_enable_type_checks);
  int64_t start_time_micros = Dart::vm_isolate()->start_time();
  int64_t uptime_micros = (OS::GetCurrentTimeMicros() - start_time_micros);
  double seconds = (static_cast<double>(uptime_micros) /
                    static_cast<double>(kMicrosecondsPerSecond));
  jsobj.AddProperty("uptime", seconds);

  // Construct the isolate list.
  {
    JSONArray jsarr(&jsobj, "isolates");
    ServiceIsolateVisitor visitor(&jsarr);
    Isolate::VisitIsolates(&visitor);
  }
  return true;
}


static bool HandleFlags(JSONStream* js) {
  if (js->num_arguments() == 1) {
    Flags::PrintJSON(js);
    return true;
  } else if (js->num_arguments() == 2) {
    const char* arg = js->GetArgument(1);
    if (strcmp(arg, "set") == 0) {
      if (js->num_arguments() > 2) {
        PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
                   js->num_arguments());
      } else {
        if (js->HasOption("name") && js->HasOption("value")) {
          JSONObject jsobj(js);
          const char* flag_name = js->LookupOption("name");
          const char* flag_value = js->LookupOption("value");
          const char* error = NULL;
          if (Flags::SetFlag(flag_name, flag_value, &error)) {
            jsobj.AddProperty("type", "Success");
            jsobj.AddProperty("id", "");
          } else {
            jsobj.AddProperty("type", "Failure");
            jsobj.AddProperty("id", "");
            jsobj.AddProperty("message", error);
          }
        } else {
          PrintError(js, "expected to find 'name' and 'value' options");
        }
      }
    }
    return true;
  } else {
    PrintError(js, "Command too long");
    return true;
  }
}


static RootMessageHandlerEntry root_handlers[] = {
  { "_echo", HandleRootEcho },
  { "vm", HandleVM },
  { "flags", HandleFlags },
};


static RootMessageHandler FindRootMessageHandler(const char* command) {
  intptr_t num_message_handlers = sizeof(root_handlers) /
                                  sizeof(root_handlers[0]);
  for (intptr_t i = 0; i < num_message_handlers; i++) {
    const RootMessageHandlerEntry& entry = root_handlers[i];
    if (strcmp(command, entry.command) == 0) {
      return entry.handler;
    }
  }
  if (FLAG_trace_service) {
    OS::Print("Service has no root message handler for <%s>\n", command);
  }
  return NULL;
}


void Service::SendEvent(intptr_t eventId, const Object& eventMessage) {
  if (!IsRunning()) {
    return;
  }
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  HANDLESCOPE(isolate);

  // Construct a list of the form [eventId, eventMessage].
  const Array& list = Array::Handle(Array::New(2));
  ASSERT(!list.IsNull());
  list.SetAt(0, Integer::Handle(Integer::New(eventId)));
  list.SetAt(1, eventMessage);

  // Push the event to port_.
  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator);
  writer.WriteMessage(list);
  intptr_t len = writer.BytesWritten();
  if (FLAG_trace_service) {
    OS::Print("Pushing event of type %" Pd ", len %" Pd "\n", eventId, len);
  }
  // TODO(turnidge): For now we ignore failure to send an event.  Revisit?
  PortMap::PostMessage(
      new Message(port_, data, len, Message::kNormalPriority));
}


void Service::SendEvent(intptr_t eventId,
                        const String& meta,
                        const uint8_t* data,
                        intptr_t size) {
  // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
  const intptr_t meta_bytes = Utf8::Length(meta);
  const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size;
  const TypedData& message = TypedData::Handle(
      TypedData::New(kTypedDataUint8ArrayCid, total_bytes));
  intptr_t offset = 0;
  // TODO(koda): Rename these methods SetHostUint64, etc.
  message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes));
  offset += sizeof(uint64_t);
  {
    NoGCScope no_gc;
    meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes);
    offset += meta_bytes;
  }
  // TODO(koda): It would be nice to avoid this copy (requires changes to
  // MessageWriter code).
  {
    NoGCScope no_gc;
    memmove(message.DataAddr(offset), data, size);
    offset += size;
  }
  ASSERT(offset == total_bytes);
  SendEvent(eventId, message);
}


void Service::HandleGCEvent(GCEvent* event) {
  JSONStream js;
  event->PrintJSON(&js);
  const String& message = String::Handle(String::New(js.ToCString()));
  SendEvent(kEventFamilyGC, message);
}


void Service::HandleDebuggerEvent(DebuggerEvent* event) {
  JSONStream js;
  event->PrintJSON(&js);
  const String& message = String::Handle(String::New(js.ToCString()));
  SendEvent(kEventFamilyDebug, message);
}


void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
                                    JSONStream* js) {
  ASSERT(handler != NULL);
  Dart_ServiceRequestCallback callback = handler->callback();
  ASSERT(callback != NULL);
  const char* r = NULL;
  const char* name = js->command();
  const char** arguments = js->arguments();
  const char** keys = js->option_keys();
  const char** values = js->option_values();
  r = callback(name, arguments, js->num_arguments(), keys, values,
               js->num_options(), handler->user_data());
  ASSERT(r != NULL);
  // TODO(johnmccutchan): Allow for NULL returns?
  TextBuffer* buffer = js->buffer();
  buffer->AddString(r);
  free(const_cast<char*>(r));
}


void Service::RegisterIsolateEmbedderCallback(
    const char* name,
    Dart_ServiceRequestCallback callback,
    void* user_data) {
  if (name == NULL) {
    return;
  }
  EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(name);
  if (handler != NULL) {
    // Update existing handler entry.
    handler->set_callback(callback);
    handler->set_user_data(user_data);
    return;
  }
  // Create a new handler.
  handler = new EmbedderServiceHandler(name);
  handler->set_callback(callback);
  handler->set_user_data(user_data);

  // Insert into isolate_service_handler_head_ list.
  handler->set_next(isolate_service_handler_head_);
  isolate_service_handler_head_ = handler;
}


EmbedderServiceHandler* Service::FindIsolateEmbedderHandler(
    const char* name) {
  EmbedderServiceHandler* current = isolate_service_handler_head_;
  while (current != NULL) {
    if (strcmp(name, current->name()) == 0) {
      return current;
    }
    current = current->next();
  }
  return NULL;
}


void Service::RegisterRootEmbedderCallback(
    const char* name,
    Dart_ServiceRequestCallback callback,
    void* user_data) {
  if (name == NULL) {
    return;
  }
  EmbedderServiceHandler* handler = FindRootEmbedderHandler(name);
  if (handler != NULL) {
    // Update existing handler entry.
    handler->set_callback(callback);
    handler->set_user_data(user_data);
    return;
  }
  // Create a new handler.
  handler = new EmbedderServiceHandler(name);
  handler->set_callback(callback);
  handler->set_user_data(user_data);

  // Insert into root_service_handler_head_ list.
  handler->set_next(root_service_handler_head_);
  root_service_handler_head_ = handler;
}


EmbedderServiceHandler* Service::FindRootEmbedderHandler(
    const char* name) {
  EmbedderServiceHandler* current = root_service_handler_head_;
  while (current != NULL) {
    if (strcmp(name, current->name()) == 0) {
      return current;
    }
    current = current->next();
  }
  return NULL;
}

}  // namespace dart
