// 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 "include/dart_native_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_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
#include "vm/native_arguments.h"
#include "vm/native_symbol.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_service.h"
#include "vm/reusable_handles.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
#include "vm/source_report.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/unicode.h"
#include "vm/version.h"

namespace dart {

#define Z (T->zone())


DECLARE_FLAG(bool, trace_service);
DECLARE_FLAG(bool, trace_service_pause_events);
DEFINE_FLAG(charp, vm_name, "vm",
            "The default name of this vm as reported by the VM service "
            "protocol");

DEFINE_FLAG(bool, warn_on_pause_with_no_debugger, false,
            "Print a message when an isolate is paused but there is no "
            "debugger attached.");

#ifndef PRODUCT
// The name of this of this vm as reported by the VM service protocol.
static char* vm_name = NULL;


static const char* GetVMName() {
  if (vm_name == NULL) {
    return FLAG_vm_name;
  }
  return vm_name;
}


ServiceIdZone::ServiceIdZone() {
}


ServiceIdZone::~ServiceIdZone() {
}


RingServiceIdZone::RingServiceIdZone()
    : ring_(NULL),
      policy_(ObjectIdRing::kAllocateId) {
}


RingServiceIdZone::~RingServiceIdZone() {
}


void RingServiceIdZone::Init(
    ObjectIdRing* ring, ObjectIdRing::IdPolicy policy) {
  ring_ = ring;
  policy_ = policy;
}


char* RingServiceIdZone::GetServiceId(const Object& obj) {
  ASSERT(ring_ != NULL);
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(zone != NULL);
  const intptr_t id = ring_->GetIdForObject(obj.raw(), policy_);
  return zone->PrintToString("objects/%" Pd "", id);
}


// TODO(johnmccutchan): Unify embedder service handler lists and their APIs.
EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
struct ServiceMethodDescriptor;
const ServiceMethodDescriptor* FindMethod(const char* method_name);


// Support for streams defined in embedders.
Dart_ServiceStreamListenCallback Service::stream_listen_callback_ = NULL;
Dart_ServiceStreamCancelCallback Service::stream_cancel_callback_ = NULL;
Dart_GetVMServiceAssetsArchive Service::get_service_assets_callback_ = NULL;

// These are the set of streams known to the core VM.
StreamInfo Service::vm_stream("VM");
StreamInfo Service::isolate_stream("Isolate");
StreamInfo Service::debug_stream("Debug");
StreamInfo Service::gc_stream("GC");
StreamInfo Service::echo_stream("_Echo");
StreamInfo Service::graph_stream("_Graph");
StreamInfo Service::logging_stream("_Logging");
StreamInfo Service::extension_stream("Extension");
StreamInfo Service::timeline_stream("Timeline");

static StreamInfo* streams_[] = {
  &Service::vm_stream,
  &Service::isolate_stream,
  &Service::debug_stream,
  &Service::gc_stream,
  &Service::echo_stream,
  &Service::graph_stream,
  &Service::logging_stream,
  &Service::extension_stream,
  &Service::timeline_stream,
};


bool Service::ListenStream(const char* stream_id) {
  if (FLAG_trace_service) {
    OS::Print("vm-service: starting stream '%s'\n",
              stream_id);
  }
  intptr_t num_streams = sizeof(streams_) /
                         sizeof(streams_[0]);
  for (intptr_t i = 0; i < num_streams; i++) {
    if (strcmp(stream_id, streams_[i]->id()) == 0) {
      streams_[i]->set_enabled(true);
      return true;
    }
  }
  if (stream_listen_callback_) {
    Thread* T = Thread::Current();
    TransitionVMToNative transition(T);
    return (*stream_listen_callback_)(stream_id);
  }
  return false;
}


void Service::CancelStream(const char* stream_id) {
  if (FLAG_trace_service) {
    OS::Print("vm-service: stopping stream '%s'\n",
              stream_id);
  }
  intptr_t num_streams = sizeof(streams_) /
                         sizeof(streams_[0]);
  for (intptr_t i = 0; i < num_streams; i++) {
    if (strcmp(stream_id, streams_[i]->id()) == 0) {
      streams_[i]->set_enabled(false);
      return;
    }
  }
  if (stream_cancel_callback_) {
    Thread* T = Thread::Current();
    TransitionVMToNative transition(T);
    return (*stream_cancel_callback_)(stream_id);
  }
}

RawObject* Service::RequestAssets() {
  Thread* T = Thread::Current();
  TransitionVMToNative transition(T);
  Api::Scope api_scope(T);
  if (get_service_assets_callback_ == NULL) {
    return Object::null();
  }
  Dart_Handle handle = get_service_assets_callback_();
  if (Dart_IsError(handle)) {
    Dart_PropagateError(handle);
  }
  const Object& object = Object::Handle(Api::UnwrapHandle(handle));
  if (object.IsNull()) {
    return Object::null();
  }
  if (!object.IsTypedData()) {
    const String& error_message =
        String::Handle(
            String::New("An implementation of Dart_GetVMServiceAssetsArchive "
                        "should return a Uint8Array or null."));
    const Error& error = Error::Handle(ApiError::New(error_message));
    Exceptions::PropagateError(error);
    return Object::null();
  }
  const TypedData& typed_data = TypedData::Cast(object);
  if (typed_data.ElementSizeInBytes() != 1) {
    const String& error_message =
        String::Handle(
            String::New("An implementation of Dart_GetVMServiceAssetsArchive "
                        "should return a Uint8Array or null."));
    const Error& error = Error::Handle(ApiError::New(error_message));
    Exceptions::PropagateError(error);
    return Object::null();
  }
  return Api::UnwrapHandle(handle);
}


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 PrintMissingParamError(JSONStream* js,
                                   const char* param) {
  js->PrintError(kInvalidParams,
                 "%s expects the '%s' parameter", js->method(), param);
}


static void PrintInvalidParamError(JSONStream* js,
                                   const char* param) {
  js->PrintError(kInvalidParams,
                 "%s: invalid '%s' parameter: %s",
                 js->method(), param, js->LookupParam(param));
}


static void PrintUnrecognizedMethodError(JSONStream* js) {
  js->PrintError(kMethodNotFound, NULL);
}


static void PrintSuccess(JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Success");
}


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.
static 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;
}


// Verifies that |s| begins with |prefix| and then calls |GetIntegerId| on
// the remainder of |s|.
static bool GetPrefixedIntegerId(const char* s,
                                 const char* prefix,
                                 intptr_t* service_id) {
  if (s == NULL) {
    return false;
  }
  ASSERT(prefix != NULL);
  const intptr_t kInputLen = strlen(s);
  const intptr_t kPrefixLen = strlen(prefix);
  ASSERT(kPrefixLen > 0);
  if (kInputLen <= kPrefixLen) {
    return false;
  }
  if (strncmp(s, prefix, kPrefixLen) != 0) {
    return false;
  }
  // Prefix satisfied. Move forward.
  s += kPrefixLen;
  // Attempt to read integer id.
  return GetIntegerId(s, service_id);
}


static bool IsValidClassId(Isolate* isolate, intptr_t cid) {
  ASSERT(isolate != NULL);
  ClassTable* class_table = isolate->class_table();
  ASSERT(class_table != NULL);
  return class_table->IsValidIndex(cid) && class_table->HasValidClassAt(cid);
}


static RawClass* GetClassForId(Isolate* isolate, intptr_t cid) {
  ASSERT(isolate == Isolate::Current());
  ASSERT(isolate != NULL);
  ClassTable* class_table = isolate->class_table();
  ASSERT(class_table != NULL);
  return class_table->At(cid);
}


// TODO(johnmccutchan): Split into separate file and write unit tests.
class MethodParameter {
 public:
  MethodParameter(const char* name, bool required)
      : name_(name), required_(required) {
  }

  virtual ~MethodParameter() { }

  virtual bool Validate(const char* value) const {
    return true;
  }

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

  bool required() const {
    return required_;
  }

  virtual void PrintError(const char* name,
                          const char* value,
                          JSONStream* js) const {
    PrintInvalidParamError(js, name);
  }

 private:
  const char* name_;
  bool required_;
};


class NoSuchParameter : public MethodParameter {
 public:
  explicit NoSuchParameter(const char* name)
    : MethodParameter(name, false) {
  }

  virtual bool Validate(const char* value) const {
    return (value == NULL);
  }
};


class BoolParameter : public MethodParameter {
 public:
  BoolParameter(const char* name, bool required)
      : MethodParameter(name, required) {
  }

  virtual bool Validate(const char* value) const {
    if (value == NULL) {
      return false;
    }
    return (strcmp("true", value) == 0) || (strcmp("false", value) == 0);
  }

  static bool Parse(const char* value, bool default_value = false) {
    if (value == NULL) {
      return default_value;
    }
    return strcmp("true", value) == 0;
  }
};


class UIntParameter : public MethodParameter {
 public:
  UIntParameter(const char* name, bool required)
      : MethodParameter(name, required) {
  }

  virtual bool Validate(const char* value) const {
    if (value == NULL) {
      return false;
    }
    for (const char* cp = value; *cp != '\0'; cp++) {
      if (*cp < '0' || *cp > '9') {
        return false;
      }
    }
    return true;
  }

  static intptr_t Parse(const char* value) {
    if (value == NULL) {
      return -1;
    }
    char* end_ptr = NULL;
    uintptr_t result = strtoul(value, &end_ptr, 10);
    ASSERT(*end_ptr == '\0');  // Parsed full string
    return result;
  }
};


class Int64Parameter : public MethodParameter {
 public:
  Int64Parameter(const char* name, bool required)
      : MethodParameter(name, required) {
  }

  virtual bool Validate(const char* value) const {
    if (value == NULL) {
      return false;
    }
    for (const char* cp = value; *cp != '\0'; cp++) {
      if ((*cp < '0' || *cp > '9') && (*cp != '-')) {
        return false;
      }
    }
    return true;
  }

  static int64_t Parse(const char* value, int64_t default_value = -1) {
    if ((value == NULL) || (*value == '\0')) {
      return default_value;
    }
    char* end_ptr = NULL;
    int64_t result = strtoll(value, &end_ptr, 10);
    ASSERT(*end_ptr == '\0');  // Parsed full string
    return result;
  }
};


class IdParameter : public MethodParameter {
 public:
  IdParameter(const char* name, bool required)
      : MethodParameter(name, required) {
  }

  virtual bool Validate(const char* value) const {
    return (value != NULL);
  }
};


class RunnableIsolateParameter : public MethodParameter {
 public:
  explicit RunnableIsolateParameter(const char* name)
      : MethodParameter(name, true) {
  }

  virtual bool Validate(const char* value) const {
    Isolate* isolate = Isolate::Current();
    return (value != NULL) && (isolate != NULL) && (isolate->is_runnable());
  }

  virtual void PrintError(const char* name,
                          const char* value,
                          JSONStream* js) const {
    js->PrintError(kIsolateMustBeRunnable,
                   "Isolate must be runnable before this request is made.");
  }
};


#define ISOLATE_PARAMETER new IdParameter("isolateId", true)
#define NO_ISOLATE_PARAMETER new NoSuchParameter("isolateId")
#define RUNNABLE_ISOLATE_PARAMETER new RunnableIsolateParameter("isolateId")

class EnumParameter : public MethodParameter {
 public:
  EnumParameter(const char* name, bool required, const char* const* enums)
      : MethodParameter(name, required),
        enums_(enums) {
  }

  virtual bool Validate(const char* value) const {
    if (value == NULL) {
      return true;
    }
    for (intptr_t i = 0; enums_[i] != NULL; i++) {
      if (strcmp(value, enums_[i]) == 0) {
        return true;
      }
    }
    return false;
  }

 private:
  const char* const* enums_;
};


// If the key is not found, this function returns the last element in the
// values array. This can be used to encode the default value.
template<typename T>
T EnumMapper(const char* value, const char* const* enums, T* values) {
  ASSERT(value != NULL);
  intptr_t i = 0;
  for (i = 0; enums[i] != NULL; i++) {
    if (strcmp(value, enums[i]) == 0) {
      return values[i];
    }
  }
  // Default value.
  return values[i];
}


class EnumListParameter : public MethodParameter {
 public:
  EnumListParameter(const char* name, bool required, const char* const* enums)
      : MethodParameter(name, required),
        enums_(enums) {
  }

  virtual bool Validate(const char* value) const {
    return ElementCount(value) >= 0;
  }

  const char** Parse(Zone* zone, const char* value_in) const {
    const char* kJsonChars = " \t\r\n[,]";

    // Make a writeable copy of the value.
    char* value = zone->MakeCopyOfString(value_in);
    intptr_t element_count = ElementCount(value);
    intptr_t element_pos = 0;

    // Allocate our element array.  +1 for NULL terminator.
    char** elements = zone->Alloc<char*>(element_count + 1);
    elements[element_count] = NULL;

    // Parse the string destructively.  Build the list of elements.
    while (element_pos < element_count) {
      // Skip to the next element.
      value += strspn(value, kJsonChars);

      intptr_t len = strcspn(value, kJsonChars);
      ASSERT(len > 0);  // We rely on the parameter being validated already.
      value[len] = '\0';
      elements[element_pos++] = value;

      // Advance.  +1 for null terminator.
      value += (len + 1);
    }
    return const_cast<const char**>(elements);
  }

 private:
  // For now observatory enums are ascii letters plus underscore.
  static bool IsEnumChar(char c) {
    return (((c >= 'a') && (c <= 'z')) ||
            ((c >= 'A') && (c <= 'Z')) ||
            (c == '_'));
  }

  // Returns number of elements in the list.  -1 on parse error.
  intptr_t ElementCount(const char* value) const {
    const char* kJsonWhitespaceChars = " \t\r\n";
    if (value == NULL) {
      return -1;
    }
    const char* cp = value;
    cp += strspn(cp, kJsonWhitespaceChars);
    if (*cp++ != '[') {
      // Missing initial [.
      return -1;
    }
    bool closed = false;
    bool element_allowed = true;
    intptr_t element_count = 0;
    while (true) {
      // Skip json whitespace.
      cp += strspn(cp, kJsonWhitespaceChars);
      switch (*cp) {
        case '\0':
          return closed ? element_count : -1;
        case ']':
          closed = true;
          cp++;
          break;
        case ',':
          if (element_allowed) {
            return -1;
          }
          element_allowed = true;
          cp++;
          break;
        default:
          if (!element_allowed) {
            return -1;
          }
          bool valid_enum = false;
          if (enums_ != NULL) {
            for (intptr_t i = 0; enums_[i] != NULL; i++) {
              intptr_t len = strlen(enums_[i]);
              if (strncmp(cp, enums_[i], len) == 0) {
                element_count++;
                valid_enum = true;
                cp += len;
                element_allowed = false;  // we need a comma first.
                break;
              }
            }
          } else {
            // Allow any identifiers
            const char* id_start = cp;
            while (IsEnumChar(*cp)) {
              cp++;
            }
            if (cp == id_start) {
              // Empty identifier, something like this [,].
              return -1;
            }
          }
          if (!valid_enum) {
            return -1;
          }
          break;
      }
    }
  }

  const char* const* enums_;
};


typedef bool (*ServiceMethodEntry)(Thread* thread, JSONStream* js);


struct ServiceMethodDescriptor {
  const char* name;
  const ServiceMethodEntry entry;
  const MethodParameter* const * parameters;
};


// TODO(johnmccutchan): Do we reject unexpected parameters?
static bool ValidateParameters(const MethodParameter* const* parameters,
                              JSONStream* js) {
  if (parameters == NULL) {
    return true;
  }
  for (intptr_t i = 0; parameters[i] != NULL; i++) {
    const MethodParameter* parameter = parameters[i];
    const char* name = parameter->name();
    const bool required = parameter->required();
    const char* value = js->LookupParam(name);
    const bool has_parameter = (value != NULL);
    if (required && !has_parameter) {
      PrintMissingParamError(js, name);
      return false;
    }
    if (has_parameter && !parameter->Validate(value)) {
      parameter->PrintError(name, value, js);
      return false;
    }
  }
  return true;
}


void Service::PostError(const String& method_name,
                        const Array& parameter_keys,
                        const Array& parameter_values,
                        const Instance& reply_port,
                        const Instance& id,
                        const Error& error) {
  Thread* T = Thread::Current();
  StackZone zone(T);
  HANDLESCOPE(T);
  JSONStream js;
  js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
           id, method_name, parameter_keys, parameter_values);
  js.PrintError(kExtensionError,
                "Error in extension `%s`: %s",
                js.method(), error.ToErrorCString());
  js.PostReply();
}


void Service::InvokeMethod(Isolate* I, const Array& msg) {
  Thread* T = Thread::Current();
  ASSERT(I == T->isolate());
  ASSERT(I != NULL);
  ASSERT(!msg.IsNull());
  ASSERT(msg.Length() == 6);

  {
    StackZone zone(T);
    HANDLESCOPE(T);

    Instance& reply_port = Instance::Handle(Z);
    Instance& seq = String::Handle(Z);
    String& method_name = String::Handle(Z);
    Array& param_keys = Array::Handle(Z);
    Array& param_values = Array::Handle(Z);
    reply_port ^= msg.At(1);
    seq ^= msg.At(2);
    method_name ^= msg.At(3);
    param_keys ^= msg.At(4);
    param_values ^= msg.At(5);

    ASSERT(!method_name.IsNull());
    ASSERT(seq.IsNull() || seq.IsString() || seq.IsNumber());
    ASSERT(!param_keys.IsNull());
    ASSERT(!param_values.IsNull());
    ASSERT(param_keys.Length() == param_values.Length());

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

    JSONStream js;
    js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
             seq, method_name, param_keys, param_values);

    // RPC came in with a custom service id zone.
    const char* id_zone_param = js.LookupParam("_idZone");

    if (id_zone_param != NULL) {
      // Override id zone.
      if (strcmp("default", id_zone_param) == 0) {
        // Ring with eager id allocation. This is the default ring and default
        // policy.
        // Nothing to do.
      } else if (strcmp("default.reuse", id_zone_param) == 0) {
        // Change the default ring's policy.
        RingServiceIdZone* zone =
            reinterpret_cast<RingServiceIdZone*>(js.id_zone());
        zone->set_policy(ObjectIdRing::kReuseId);
      } else {
        // TODO(johnmccutchan): Support creating, deleting, and selecting
        // custom service id zones.
        // For now, always return an error.
        PrintInvalidParamError(&js, "_idZone");
        js.PostReply();
        return;
      }
    }
    const char* c_method_name = method_name.ToCString();

    const ServiceMethodDescriptor* method = FindMethod(c_method_name);
    if (method != NULL) {
      if (!ValidateParameters(method->parameters, &js)) {
        js.PostReply();
        return;
      }
      if (method->entry(T, &js)) {
        js.PostReply();
      } else {
        // NOTE(turnidge): All message handlers currently return true,
        // so this case shouldn't be reached, at present.
        UNIMPLEMENTED();
      }
      return;
    }

    EmbedderServiceHandler* handler = FindIsolateEmbedderHandler(c_method_name);
    if (handler == NULL) {
      handler = FindRootEmbedderHandler(c_method_name);
    }

    if (handler != NULL) {
      EmbedderHandleMessage(handler, &js);
      js.PostReply();
      return;
    }

    const Instance& extension_handler = Instance::Handle(Z,
        I->LookupServiceExtensionHandler(method_name));
    if (!extension_handler.IsNull()) {
      ScheduleExtensionHandler(extension_handler,
                               method_name,
                               param_keys,
                               param_values,
                               reply_port,
                               seq);
      // Schedule was successful. Extension code will post a reply
      // asynchronously.
      return;
    }

    PrintUnrecognizedMethodError(&js);
    js.PostReply();
    return;
  }
}


void Service::HandleRootMessage(const Array& msg_instance) {
  Isolate* isolate = Isolate::Current();
  InvokeMethod(isolate, msg_instance);
}


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


void Service::SendEvent(const char* stream_id,
                        const char* event_type,
                        const Object& event_message) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(isolate));
  if (!ServiceIsolate::IsRunning()) {
    return;
  }
  HANDLESCOPE(thread);

  const Array& list = Array::Handle(Array::New(2));
  ASSERT(!list.IsNull());
  const String& stream_id_str = String::Handle(String::New(stream_id));
  list.SetAt(0, stream_id_str);
  list.SetAt(1, event_message);

  // Push the event to port_.
  uint8_t* data = NULL;
  MessageWriter writer(&data, &allocator, false);
  writer.WriteMessage(list);
  intptr_t len = writer.BytesWritten();
  if (FLAG_trace_service) {
    OS::Print("vm-service: Pushing ServiceEvent(isolate='%s', kind='%s',"
              " len=%" Pd ") to stream %s\n",
              isolate->name(), event_type, len, stream_id);
  }
  // TODO(turnidge): For now we ignore failure to send an event.  Revisit?
  PortMap::PostMessage(
      new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority));
}


// TODO(turnidge): Rewrite this method to use Post_CObject instead.
void Service::SendEventWithData(const char* stream_id,
                                const char* event_type,
                                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);
  {
    NoSafepointScope no_safepoint;
    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).
  {
    NoSafepointScope no_safepoint;
    memmove(message.DataAddr(offset), data, size);
    offset += size;
  }
  ASSERT(offset == total_bytes);
  SendEvent(stream_id, event_type, message);
}


static void ReportPauseOnConsole(ServiceEvent* event) {
  const char* name = event->isolate()->debugger_name();
  switch (event->kind())  {
    case ServiceEvent::kPauseStart:
      OS::PrintErr(
          "vm-service: isolate '%s' has no debugger attached and is paused at "
          "start.", name);
      break;
    case ServiceEvent::kPauseExit:
      OS::PrintErr(
          "vm-service: isolate '%s' has no debugger attached and is paused at "
          "exit.", name);
      break;
    case ServiceEvent::kPauseException:
      OS::PrintErr(
          "vm-service: isolate '%s' has no debugger attached and is paused due "
          "to exception.", name);
      break;
    case ServiceEvent::kPauseInterrupted:
      OS::PrintErr(
          "vm-service: isolate '%s' has no debugger attached and is paused due "
          "to interrupt.", name);
      break;
    case ServiceEvent::kPauseBreakpoint:
      OS::PrintErr(
          "vm-service: isolate '%s' has no debugger attached and is paused.",
          name);
      break;
    default:
      UNREACHABLE();
      break;
  }
  if (!ServiceIsolate::IsRunning()) {
    OS::PrintErr("  Start the vm-service to debug.\n");
  } else if (ServiceIsolate::server_address() == NULL) {
    OS::PrintErr("  Connect to Observatory to debug.\n");
  } else {
    OS::PrintErr("  Connect to Observatory at %s to debug.\n",
                 ServiceIsolate::server_address());
  }
  const Error& err = Error::Handle(Thread::Current()->sticky_error());
  if (!err.IsNull()) {
    OS::PrintErr("%s\n", err.ToErrorCString());
  }
}


void Service::HandleEvent(ServiceEvent* event) {
  if (event->isolate() != NULL &&
      ServiceIsolate::IsServiceIsolateDescendant(event->isolate())) {
    return;
  }
  if (FLAG_warn_on_pause_with_no_debugger &&
      event->IsPause() && !Service::debug_stream.enabled()) {
    // If we are about to pause a running program which has no
    // debugger connected, tell the user about it.
    ReportPauseOnConsole(event);
  }
  if (!ServiceIsolate::IsRunning()) {
    return;
  }
  JSONStream js;
  const char* stream_id = event->stream_id();
  ASSERT(stream_id != NULL);
  {
    JSONObject jsobj(&js);
    jsobj.AddProperty("jsonrpc", "2.0");
    jsobj.AddProperty("method", "streamNotify");
    JSONObject params(&jsobj, "params");
    params.AddProperty("streamId", stream_id);
    params.AddProperty("event", event);
  }
  PostEvent(event->isolate(), stream_id, event->KindAsCString(), &js);
}


void Service::PostEvent(Isolate* isolate,
                        const char* stream_id,
                        const char* kind,
                        JSONStream* event) {
  ASSERT(stream_id != NULL);
  ASSERT(kind != NULL);
  ASSERT(event != NULL);

  // Message is of the format [<stream id>, <json string>].
  //
  // Build the event message in the C heap to avoid dart heap
  // allocation.  This method can be called while we have acquired a
  // direct pointer to typed data, so we can't allocate here.
  Dart_CObject list_cobj;
  Dart_CObject* list_values[2];
  list_cobj.type = Dart_CObject_kArray;
  list_cobj.value.as_array.length = 2;
  list_cobj.value.as_array.values = list_values;

  Dart_CObject stream_id_cobj;
  stream_id_cobj.type = Dart_CObject_kString;
  stream_id_cobj.value.as_string = const_cast<char*>(stream_id);
  list_values[0] = &stream_id_cobj;

  Dart_CObject json_cobj;
  json_cobj.type = Dart_CObject_kString;
  json_cobj.value.as_string = const_cast<char*>(event->ToCString());
  list_values[1] = &json_cobj;

  if (FLAG_trace_service) {
    const char* isolate_name = "<no current isolate>";
    if (isolate != NULL) {
      isolate_name = isolate->name();
    }
    OS::Print("vm-service: Pushing ServiceEvent(isolate='%s', kind='%s') "
              "to stream %s\n",
              isolate_name, kind, stream_id);
  }

  Dart_PostCObject(ServiceIsolate::Port(), &list_cobj);
}


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


void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
                                    JSONStream* js) {
  ASSERT(handler != NULL);
  Dart_ServiceRequestCallback callback = handler->callback();
  ASSERT(callback != NULL);
  const char* r = NULL;
  const char* method = js->method();
  const char** keys = js->param_keys();
  const char** values = js->param_values();
  r = callback(method, keys, values, js->num_params(), 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;
}


void Service::SetEmbedderStreamCallbacks(
    Dart_ServiceStreamListenCallback listen_callback,
    Dart_ServiceStreamCancelCallback cancel_callback) {
  stream_listen_callback_ = listen_callback;
  stream_cancel_callback_ = cancel_callback;
}


void Service::SetGetServiceAssetsCallback(
    Dart_GetVMServiceAssetsArchive get_service_assets) {
  get_service_assets_callback_ = get_service_assets;
}


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


void Service::ScheduleExtensionHandler(const Instance& handler,
                                       const String& method_name,
                                       const Array& parameter_keys,
                                       const Array& parameter_values,
                                       const Instance& reply_port,
                                       const Instance& id) {
  ASSERT(!handler.IsNull());
  ASSERT(!method_name.IsNull());
  ASSERT(!parameter_keys.IsNull());
  ASSERT(!parameter_values.IsNull());
  ASSERT(!reply_port.IsNull());
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != NULL);
  isolate->AppendServiceExtensionCall(handler,
                                      method_name,
                                      parameter_keys,
                                      parameter_values,
                                      reply_port,
                                      id);
}


static const MethodParameter* get_isolate_params[] = {
  ISOLATE_PARAMETER,
  NULL,
};


static bool GetIsolate(Thread* thread, JSONStream* js) {
  thread->isolate()->PrintJSON(js, false);
  return true;
}


static const MethodParameter* get_stack_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new BoolParameter("_full", false),
  NULL,
};


static bool GetStack(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot get stack when running a precompiled program.");
    return true;
  }
  Isolate* isolate = thread->isolate();
  DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
  // Do we want the complete script object and complete local variable objects?
  // This is true for dump requests.
  const bool full = BoolParameter::Parse(js->LookupParam("_full"), false);
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Stack");
  {
    JSONArray jsarr(&jsobj, "frames");

    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, full);
      jsobj.AddProperty("index", i);
    }
  }

  {
    MessageHandler::AcquiredQueues aq(isolate->message_handler());
    jsobj.AddProperty("messages", aq.queue());
  }

  return true;
}


static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) {
  jsobj->AddProperty("type", "_EchoResponse");
  if (js->HasParam("text")) {
    jsobj->AddProperty("text", js->LookupParam("text"));
  }
  return true;
}


void Service::SendEchoEvent(Isolate* isolate, const char* text) {
  JSONStream js;
  {
    JSONObject jsobj(&js);
    jsobj.AddProperty("jsonrpc", "2.0");
    jsobj.AddProperty("method", "streamNotify");
    {
      JSONObject params(&jsobj, "params");
      params.AddProperty("streamId", echo_stream.id());
      {
        JSONObject event(&params, "event");
        event.AddProperty("type", "Event");
        event.AddProperty("kind", "_Echo");
        event.AddProperty("isolate", isolate);
        if (text != NULL) {
          event.AddProperty("text", text);
        }
        event.AddPropertyTimeMillis("timestamp", OS::GetCurrentTimeMillis());
      }
    }
  }
  const String& message = String::Handle(String::New(js.ToCString()));
  uint8_t data[] = {0, 128, 255};
  SendEventWithData(echo_stream.id(), "_Echo", message, data, sizeof(data));
}


static bool TriggerEchoEvent(Thread* thread, JSONStream* js) {
  if (Service::echo_stream.enabled()) {
    Service::SendEchoEvent(thread->isolate(), js->LookupParam("text"));
  }
  JSONObject jsobj(js);
  return HandleCommonEcho(&jsobj, js);
}


static bool DumpIdZone(Thread* thread, JSONStream* js) {
  // TODO(johnmccutchan): Respect _idZone parameter passed to RPC. For now,
  // always send the ObjectIdRing.
  //
  ObjectIdRing* ring = thread->isolate()->object_id_ring();
  ASSERT(ring != NULL);
  // When printing the ObjectIdRing, force object id reuse policy.
  RingServiceIdZone reuse_zone;
  reuse_zone.Init(ring, ObjectIdRing::kReuseId);
  js->set_id_zone(&reuse_zone);
  ring->PrintJSON(js);
  return true;
}


static bool Echo(Thread* thread, JSONStream* js) {
  JSONObject jsobj(js);
  return HandleCommonEcho(&jsobj, js);
}


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 RawObject* LookupObjectId(Thread* thread,
                                 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(thread->zone(),
        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();
  }

  ObjectIdRing* ring = thread->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 RawObject* LookupHeapObjectLibraries(Isolate* isolate,
                                            char** parts, int num_parts) {
  // Library ids look like "libraries/35"
  if (num_parts < 2) {
    return Object::sentinel().raw();
  }
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate->object_store()->libraries());
  ASSERT(!libs.IsNull());
  intptr_t id = 0;
  if (!GetIntegerId(parts[1], &id)) {
    return Object::sentinel().raw();
  }
  if ((id < 0) || (id >= libs.Length())) {
    return Object::sentinel().raw();
  }
  Library& lib = Library::Handle();
  lib ^= libs.At(id);
  ASSERT(!lib.IsNull());
  if (num_parts == 2) {
    return lib.raw();
  }
  if (strcmp(parts[2], "scripts") == 0) {
    // Script ids look like "libraries/35/scripts/library%2Furl.dart"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    const String& id = String::Handle(String::New(parts[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)) {
        return script.raw();
      }
    }
  }

  // Not found.
  return Object::sentinel().raw();
}

static RawObject* LookupHeapObjectClasses(Thread* thread,
                                          char** parts, int num_parts) {
  // Class ids look like: "classes/17"
  if (num_parts < 2) {
    return Object::sentinel().raw();
  }
  Isolate* isolate = thread->isolate();
  Zone* zone = thread->zone();
  ClassTable* table = isolate->class_table();
  intptr_t id;
  if (!GetIntegerId(parts[1], &id) ||
      !table->IsValidIndex(id)) {
    return Object::sentinel().raw();
  }
  Class& cls = Class::Handle(zone, table->At(id));
  if (num_parts == 2) {
    return cls.raw();
  }
  if (strcmp(parts[2], "closures") == 0) {
    // Closure ids look like: "classes/17/closures/11"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    intptr_t id;
    if (!GetIntegerId(parts[3], &id)) {
      return Object::sentinel().raw();
    }
    Function& func = Function::Handle(zone);
    func ^= isolate->ClosureFunctionFromIndex(id);
    if (func.IsNull()) {
      return Object::sentinel().raw();
    }
    return func.raw();

  } else if (strcmp(parts[2], "fields") == 0) {
    // Field ids look like: "classes/17/fields/name"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    const char* encoded_id = parts[3];
    String& id = String::Handle(zone, String::New(encoded_id));
    id = String::DecodeIRI(id);
    if (id.IsNull()) {
      return Object::sentinel().raw();
    }
    Field& field = Field::Handle(zone, cls.LookupField(id));
    if (field.IsNull()) {
      return Object::sentinel().raw();
    }
    return field.raw();

  } else if (strcmp(parts[2], "functions") == 0) {
    // Function ids look like: "classes/17/functions/name"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    const char* encoded_id = parts[3];
    String& id = String::Handle(zone, String::New(encoded_id));
    id = String::DecodeIRI(id);
    if (id.IsNull()) {
      return Object::sentinel().raw();
    }
    Function& func = Function::Handle(zone, cls.LookupFunction(id));
    if (func.IsNull()) {
      return Object::sentinel().raw();
    }
    return func.raw();

  } else if (strcmp(parts[2], "implicit_closures") == 0) {
    // Function ids look like: "classes/17/implicit_closures/11"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    intptr_t id;
    if (!GetIntegerId(parts[3], &id)) {
      return Object::sentinel().raw();
    }
    Function& func = Function::Handle(zone);
    func ^= cls.ImplicitClosureFunctionFromIndex(id);
    if (func.IsNull()) {
      return Object::sentinel().raw();
    }
    return func.raw();

  } else if (strcmp(parts[2], "dispatchers") == 0) {
    // Dispatcher Function ids look like: "classes/17/dispatchers/11"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    intptr_t id;
    if (!GetIntegerId(parts[3], &id)) {
      return Object::sentinel().raw();
    }
    Function& func = Function::Handle(zone);
    func ^= cls.InvocationDispatcherFunctionFromIndex(id);
    if (func.IsNull()) {
      return Object::sentinel().raw();
    }
    return func.raw();

  } else if (strcmp(parts[2], "types") == 0) {
    // Type ids look like: "classes/17/types/11"
    if (num_parts != 4) {
      return Object::sentinel().raw();
    }
    intptr_t id;
    if (!GetIntegerId(parts[3], &id)) {
      return Object::sentinel().raw();
    }
    Type& type = Type::Handle(zone);
    type ^= cls.CanonicalTypeFromIndex(id);
    if (type.IsNull()) {
      return Object::sentinel().raw();
    }
    return type.raw();
  }

  // Not found.
  return Object::sentinel().raw();
}


static RawObject* LookupHeapObjectTypeArguments(Thread* thread,
                                                char** parts, int num_parts) {
  Isolate* isolate = thread->isolate();
  // TypeArguments ids look like: "typearguments/17"
  if (num_parts < 2) {
    return Object::sentinel().raw();
  }
  intptr_t id;
  if (!GetIntegerId(parts[1], &id)) {
    return Object::sentinel().raw();
  }
  ObjectStore* object_store = isolate->object_store();
  const Array& table = Array::Handle(thread->zone(),
                                     object_store->canonical_type_arguments());
  ASSERT(table.Length() > 0);
  const intptr_t table_size = table.Length() - 1;
  if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) {
    return Object::sentinel().raw();
  }
  return table.At(id);
}


static RawObject* LookupHeapObjectCode(Isolate* isolate,
                                       char** parts, int num_parts) {
  if (num_parts != 2) {
    return Object::sentinel().raw();
  }
  uword pc;
  static const char* const kCollectedPrefix = "collected-";
  static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix);
  static const char* const kNativePrefix = "native-";
  static const intptr_t kNativePrefixLen = strlen(kNativePrefix);
  static const char* const kReusedPrefix = "reused-";
  static const intptr_t kReusedPrefixLen = strlen(kReusedPrefix);
  const char* id = parts[1];
  if (strncmp(kCollectedPrefix, id, kCollectedPrefixLen) == 0) {
    if (!GetUnsignedIntegerId(&id[kCollectedPrefixLen], &pc, 16)) {
      return Object::sentinel().raw();
    }
    // TODO(turnidge): Return "collected" instead.
    return Object::null();
  }
  if (strncmp(kNativePrefix, id, kNativePrefixLen) == 0) {
    if (!GetUnsignedIntegerId(&id[kNativePrefixLen], &pc, 16)) {
      return Object::sentinel().raw();
    }
    // TODO(johnmccutchan): Support native Code.
    return Object::null();
  }
  if (strncmp(kReusedPrefix, id, kReusedPrefixLen) == 0) {
    if (!GetUnsignedIntegerId(&id[kReusedPrefixLen], &pc, 16)) {
      return Object::sentinel().raw();
    }
    // TODO(turnidge): Return "expired" instead.
    return Object::null();
  }
  int64_t timestamp = 0;
  if (!GetCodeId(id, &timestamp, &pc) || (timestamp < 0)) {
    return Object::sentinel().raw();
  }
  Code& code = Code::Handle(Code::FindCode(pc, timestamp));
  if (!code.IsNull()) {
    return code.raw();
  }

  // Not found.
  return Object::sentinel().raw();
}


static RawObject* LookupHeapObjectMessage(Thread* thread,
                                          char** parts, int num_parts) {
  if (num_parts != 2) {
    return Object::sentinel().raw();
  }
  uword message_id = 0;
  if (!GetUnsignedIntegerId(parts[1], &message_id, 16)) {
    return Object::sentinel().raw();
  }
  MessageHandler::AcquiredQueues aq(thread->isolate()->message_handler());
  Message* message = aq.queue()->FindMessageById(message_id);
  if (message == NULL) {
    // The user may try to load an expired message.
    return Object::sentinel().raw();
  }
  if (message->len() > 0) {
    MessageSnapshotReader reader(message->data(),
                                 message->len(),
                                 thread);
    return reader.ReadObject();
  } else {
    return message->raw_obj();
  }
}


static RawObject* LookupHeapObject(Thread* thread,
                                   const char* id_original,
                                   ObjectIdRing::LookupResult* result) {
  char* id = thread->zone()->MakeCopyOfString(id_original);

  // Parse the id by splitting at each '/'.
  const int MAX_PARTS = 8;
  char* parts[MAX_PARTS];
  int num_parts = 0;
  int i = 0;
  int start_pos = 0;
  while (id[i] != '\0') {
    if (id[i] == '/') {
      id[i++] = '\0';
      parts[num_parts++] = &id[start_pos];
      if (num_parts == MAX_PARTS) {
        break;
      }
      start_pos = i;
    } else {
      i++;
    }
  }
  if (num_parts < MAX_PARTS) {
    parts[num_parts++] = &id[start_pos];
  }

  if (result != NULL) {
    *result = ObjectIdRing::kValid;
  }

  Isolate* isolate = thread->isolate();
  if (strcmp(parts[0], "objects") == 0) {
    // Object ids look like "objects/1123"
    Object& obj = Object::Handle(thread->zone());
    ObjectIdRing::LookupResult lookup_result;
    obj = LookupObjectId(thread, parts[1], &lookup_result);
    if (lookup_result != ObjectIdRing::kValid) {
      if (result != NULL) {
        *result = lookup_result;
      }
      return Object::sentinel().raw();
    }
    return obj.raw();

  } else if (strcmp(parts[0], "libraries") == 0) {
    return LookupHeapObjectLibraries(isolate, parts, num_parts);
  } else if (strcmp(parts[0], "classes") == 0) {
    return LookupHeapObjectClasses(thread, parts, num_parts);
  } else if (strcmp(parts[0], "typearguments") == 0) {
    return LookupHeapObjectTypeArguments(thread, parts, num_parts);
  } else if (strcmp(parts[0], "code") == 0) {
    return LookupHeapObjectCode(isolate, parts, num_parts);
  } else if (strcmp(parts[0], "messages") == 0) {
    return LookupHeapObjectMessage(thread, parts, num_parts);
  }

  // Not found.
  return Object::sentinel().raw();
}


enum SentinelType {
  kCollectedSentinel,
  kExpiredSentinel,
  kFreeSentinel,
};


static void PrintSentinel(JSONStream* js, SentinelType sentinel_type) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Sentinel");
  switch (sentinel_type) {
    case kCollectedSentinel:
      jsobj.AddProperty("kind", "Collected");
      jsobj.AddProperty("valueAsString", "<collected>");
      break;
    case kExpiredSentinel:
      jsobj.AddProperty("kind", "Expired");
      jsobj.AddProperty("valueAsString", "<expired>");
      break;
    case kFreeSentinel:
      jsobj.AddProperty("kind", "Free");
      jsobj.AddProperty("valueAsString", "<free>");
      break;
    default:
      UNIMPLEMENTED();
      break;
  }
}


static Breakpoint* LookupBreakpoint(Isolate* isolate,
                                    const char* id,
                                    ObjectIdRing::LookupResult* result) {
  *result = ObjectIdRing::kInvalid;
  size_t end_pos = strcspn(id, "/");
  if (end_pos == strlen(id)) {
    return NULL;
  }
  const char* rest = id + end_pos + 1;  // +1 for '/'.
  if (strncmp("breakpoints", id, end_pos) == 0) {
    intptr_t bpt_id = 0;
    Breakpoint* bpt = NULL;
    if (GetIntegerId(rest, &bpt_id)) {
      bpt = isolate->debugger()->GetBreakpointById(bpt_id);
      if (bpt) {
        *result = ObjectIdRing::kValid;
        return bpt;
      }
      if (bpt_id < isolate->debugger()->limitBreakpointId()) {
        *result = ObjectIdRing::kCollected;
        return NULL;
      }
    }
  }
  return NULL;
}


static bool PrintInboundReferences(Thread* thread,
                                   Object* target,
                                   intptr_t limit,
                                   JSONStream* js) {
  ObjectGraph graph(thread);
  Array& path = Array::Handle(Array::New(limit * 2));
  intptr_t length = graph.InboundReferences(target, path);
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "InboundReferences");
  {
    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);
      if (source.IsArray()) {
        intptr_t element_index = slot_offset.Value() -
            (Array::element_offset(0) >> kWordSizeLog2);
        jselement.AddProperty("parentListIndex", 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("parentField", field);
        }
      } else {
        intptr_t element_index = slot_offset.Value();
        jselement.AddProperty("_parentWordOffset", element_index);
      }

      // 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 const MethodParameter* get_inbound_references_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetInboundReferences(Thread* thread, JSONStream* js) {
  const char* target_id = js->LookupParam("targetId");
  if (target_id == NULL) {
    PrintMissingParamError(js, "targetId");
    return true;
  }
  const char* limit_cstr = js->LookupParam("limit");
  if (limit_cstr == NULL) {
    PrintMissingParamError(js, "limit");
    return true;
  }
  intptr_t limit;
  if (!GetIntegerId(limit_cstr, &limit)) {
    PrintInvalidParamError(js, "limit");
    return true;
  }

  Object& obj = Object::Handle(thread->zone());
  ObjectIdRing::LookupResult lookup_result;
  {
    HANDLESCOPE(thread);
    obj = LookupHeapObject(thread, target_id, &lookup_result);
  }
  if (obj.raw() == Object::sentinel().raw()) {
    if (lookup_result == ObjectIdRing::kCollected) {
      PrintSentinel(js, kCollectedSentinel);
    } else if (lookup_result == ObjectIdRing::kExpired) {
      PrintSentinel(js, kExpiredSentinel);
    } else {
      PrintInvalidParamError(js, "targetId");
    }
    return true;
  }
  return PrintInboundReferences(thread, &obj, limit, js);
}


static bool PrintRetainingPath(Thread* thread,
                               Object* obj,
                               intptr_t limit,
                               JSONStream* js) {
  ObjectGraph graph(thread);
  Array& path = Array::Handle(Array::New(limit * 2));
  intptr_t length = graph.RetainingPath(obj, path);
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "RetainingPath");
  jsobj.AddProperty("length", length);
  JSONArray elements(&jsobj, "elements");
  Object& element = Object::Handle();
  Smi& slot_offset = Smi::Handle();
  Class& element_class = Class::Handle();
  Array& element_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.
    if (i > 0) {
      slot_offset ^= path.At((i * 2) - 1);
      if (element.IsArray()) {
        intptr_t element_index = slot_offset.Value() -
            (Array::element_offset(0) >> kWordSizeLog2);
        jselement.AddProperty("parentListIndex", element_index);
      } else if (element.IsInstance()) {
        element_class ^= element.clazz();
        element_field_map = element_class.OffsetToFieldMap();
        intptr_t offset = slot_offset.Value();
        if (offset > 0 && offset < element_field_map.Length()) {
          field ^= element_field_map.At(offset);
          jselement.AddProperty("parentField", field);
        }
      } else {
        intptr_t element_index = slot_offset.Value();
        jselement.AddProperty("_parentWordOffset", element_index);
      }
    }
  }

  // We nil out the array after generating the response to prevent
  // reporting spurious 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;
}


static const MethodParameter* get_retaining_path_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetRetainingPath(Thread* thread, JSONStream* js) {
  const char* target_id = js->LookupParam("targetId");
  if (target_id == NULL) {
    PrintMissingParamError(js, "targetId");
    return true;
  }
  const char* limit_cstr = js->LookupParam("limit");
  if (limit_cstr == NULL) {
    PrintMissingParamError(js, "limit");
    return true;
  }
  intptr_t limit;
  if (!GetIntegerId(limit_cstr, &limit)) {
    PrintInvalidParamError(js, "limit");
    return true;
  }

  Object& obj = Object::Handle(thread->zone());
  ObjectIdRing::LookupResult lookup_result;
  {
    HANDLESCOPE(thread);
    obj = LookupHeapObject(thread, target_id, &lookup_result);
  }
  if (obj.raw() == Object::sentinel().raw()) {
    if (lookup_result == ObjectIdRing::kCollected) {
      PrintSentinel(js, kCollectedSentinel);
    } else if (lookup_result == ObjectIdRing::kExpired) {
      PrintSentinel(js, kExpiredSentinel);
    } else {
      PrintInvalidParamError(js, "targetId");
    }
    return true;
  }
  return PrintRetainingPath(thread, &obj, limit, js);
}


static const MethodParameter* get_retained_size_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("targetId", true),
  NULL,
};


static bool GetRetainedSize(Thread* thread, JSONStream* js) {
  const char* target_id = js->LookupParam("targetId");
  ASSERT(target_id != NULL);
  ObjectIdRing::LookupResult lookup_result;
  Object& obj = Object::Handle(LookupHeapObject(thread, target_id,
                                                &lookup_result));
  if (obj.raw() == Object::sentinel().raw()) {
    if (lookup_result == ObjectIdRing::kCollected) {
      PrintSentinel(js, kCollectedSentinel);
    } else if (lookup_result == ObjectIdRing::kExpired) {
      PrintSentinel(js, kExpiredSentinel);
    } else {
      PrintInvalidParamError(js, "targetId");
    }
    return true;
  }
  // TODO(rmacnak): There is no way to get the size retained by a class object.
  // SizeRetainedByClass should be a separate RPC.
  if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    ObjectGraph graph(thread);
    intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
    const Object& result = Object::Handle(Integer::New(retained_size));
    result.PrintJSON(js, true);
    return true;
  }

  ObjectGraph graph(thread);
  intptr_t retained_size = graph.SizeRetainedByInstance(obj);
  const Object& result = Object::Handle(Integer::New(retained_size));
  result.PrintJSON(js, true);
  return true;
}


static const MethodParameter* get_reachable_size_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("targetId", true),
  NULL,
};


static bool GetReachableSize(Thread* thread, JSONStream* js) {
  const char* target_id = js->LookupParam("targetId");
  ASSERT(target_id != NULL);
  ObjectIdRing::LookupResult lookup_result;
  Object& obj = Object::Handle(LookupHeapObject(thread, target_id,
                                                &lookup_result));
  if (obj.raw() == Object::sentinel().raw()) {
    if (lookup_result == ObjectIdRing::kCollected) {
      PrintSentinel(js, kCollectedSentinel);
    } else if (lookup_result == ObjectIdRing::kExpired) {
      PrintSentinel(js, kExpiredSentinel);
    } else {
      PrintInvalidParamError(js, "targetId");
    }
    return true;
  }
  // TODO(rmacnak): There is no way to get the size retained by a class object.
  // SizeRetainedByClass should be a separate RPC.
  if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    ObjectGraph graph(thread);
    intptr_t retained_size = graph.SizeReachableByClass(cls.id());
    const Object& result = Object::Handle(Integer::New(retained_size));
    result.PrintJSON(js, true);
    return true;
  }

  ObjectGraph graph(thread);
  intptr_t retained_size = graph.SizeReachableByInstance(obj);
  const Object& result = Object::Handle(Integer::New(retained_size));
  result.PrintJSON(js, true);
  return true;
}


static const MethodParameter* evaluate_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool Evaluate(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
                   "Cannot evaluate when running a precompiled program.");
    return true;
  }
  const char* target_id = js->LookupParam("targetId");
  if (target_id == NULL) {
    PrintMissingParamError(js, "targetId");
    return true;
  }
  const char* expr = js->LookupParam("expression");
  if (expr == NULL) {
    PrintMissingParamError(js, "expression");
    return true;
  }
  Zone* zone = thread->zone();
  const String& expr_str = String::Handle(zone, String::New(expr));
  ObjectIdRing::LookupResult lookup_result;
  Object& obj = Object::Handle(zone, LookupHeapObject(thread, target_id,
                                                      &lookup_result));
  if (obj.raw() == Object::sentinel().raw()) {
    if (lookup_result == ObjectIdRing::kCollected) {
      PrintSentinel(js, kCollectedSentinel);
    } else if (lookup_result == ObjectIdRing::kExpired) {
      PrintSentinel(js, kExpiredSentinel);
    } else {
      PrintInvalidParamError(js, "targetId");
    }
    return true;
  }
  if (obj.IsLibrary()) {
    const Library& lib = Library::Cast(obj);
    const Object& result = Object::Handle(zone,
        lib.Evaluate(expr_str, Array::empty_array(), Array::empty_array()));
    result.PrintJSON(js, true);
    return true;
  }
  if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    const Object& result = Object::Handle(zone,
        cls.Evaluate(expr_str, Array::empty_array(), Array::empty_array()));
    result.PrintJSON(js, true);
    return true;
  }
  if ((obj.IsInstance() || obj.IsNull()) &&
      !ContainsNonInstance(obj)) {
    // We don't use Instance::Cast here because it doesn't allow null.
    Instance& instance = Instance::Handle(zone);
    instance ^= obj.raw();
    const Object& result =
        Object::Handle(zone, instance.Evaluate(expr_str,
                                               Array::empty_array(),
                                               Array::empty_array()));
    result.PrintJSON(js, true);
    return true;
  }
  js->PrintError(kInvalidParams,
                 "%s: invalid 'targetId' parameter: "
                 "id '%s' does not correspond to a "
                 "library, class, or instance", js->method(), target_id);
  return true;
}


static const MethodParameter* evaluate_in_frame_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new UIntParameter("frameIndex", true),
  new MethodParameter("expression", true),
  NULL,
};


static bool EvaluateInFrame(Thread* thread, JSONStream* js) {
  Isolate* isolate = thread->isolate();
  if (!isolate->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
                   "Cannot evaluate when running a precompiled program.");
    return true;
  }
  DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
  intptr_t framePos = UIntParameter::Parse(js->LookupParam("frameIndex"));
  if (framePos > stack->Length()) {
    PrintInvalidParamError(js, "frameIndex");
    return true;
  }
  ActivationFrame* frame = stack->FrameAt(framePos);

  Zone* zone = thread->zone();
  const char* expr = js->LookupParam("expression");
  const String& expr_str = String::Handle(zone, String::New(expr));

  const Object& result = Object::Handle(zone, frame->Evaluate(expr_str));
  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;
    }
    Thread* thread = Thread::Current();
    REUSABLE_OBJECT_HANDLESCOPE(thread);
    Object& obj = thread->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 const MethodParameter* get_instances_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetInstances(Thread* thread, JSONStream* js) {
  const char* target_id = js->LookupParam("classId");
  if (target_id == NULL) {
    PrintMissingParamError(js, "classId");
    return true;
  }
  const char* limit_cstr = js->LookupParam("limit");
  if (limit_cstr == NULL) {
    PrintMissingParamError(js, "limit");
    return true;
  }
  intptr_t limit;
  if (!GetIntegerId(limit_cstr, &limit)) {
    PrintInvalidParamError(js, "limit");
    return true;
  }
  const Object& obj =
      Object::Handle(LookupHeapObject(thread, target_id, NULL));
  if (obj.raw() == Object::sentinel().raw() ||
      !obj.IsClass()) {
    PrintInvalidParamError(js, "classId");
    return true;
  }
  const Class& cls = Class::Cast(obj);
  Array& storage = Array::Handle(Array::New(limit));
  GetInstancesVisitor visitor(cls, storage);
  ObjectGraph graph(thread);
  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("totalCount", count);
  {
    JSONArray samples(&jsobj, "samples");
    for (int i = 0; i < storage.Length(); i++) {
      const Object& sample = Object::Handle(storage.At(i));
      samples.AddValue(sample);
    }
  }
  return true;
}


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 bool GetHitsOrSites(Thread* thread, JSONStream* js, bool as_sites) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot get coverage data when running a precompiled program.");
    return true;
  }
  if (!js->HasParam("targetId")) {
    CodeCoverage::PrintJSON(thread, js, NULL, as_sites);
    return true;
  }
  const char* target_id = js->LookupParam("targetId");
  Object& obj = Object::Handle(LookupHeapObject(thread, target_id, NULL));
  if (obj.raw() == Object::sentinel().raw()) {
    PrintInvalidParamError(js, "targetId");
    return true;
  }
  if (obj.IsScript()) {
    ScriptCoverageFilter sf(Script::Cast(obj));
    CodeCoverage::PrintJSON(thread, js, &sf, as_sites);
    return true;
  }
  if (obj.IsLibrary()) {
    LibraryCoverageFilter lf(Library::Cast(obj));
    CodeCoverage::PrintJSON(thread, js, &lf, as_sites);
    return true;
  }
  if (obj.IsClass()) {
    ClassCoverageFilter cf(Class::Cast(obj));
    CodeCoverage::PrintJSON(thread, js, &cf, as_sites);
    return true;
  }
  if (obj.IsFunction()) {
    FunctionCoverageFilter ff(Function::Cast(obj));
    CodeCoverage::PrintJSON(thread, js, &ff, as_sites);
    return true;
  }
  js->PrintError(kInvalidParams,
                 "%s: invalid 'targetId' parameter: "
                 "id '%s' does not correspond to a "
                 "script, library, class, or function",
                 js->method(), target_id);
  return true;
}


static const MethodParameter* get_coverage_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("targetId", false),
  NULL,
};


static bool GetCoverage(Thread* thread, JSONStream* js) {
  // TODO(rmacnak): Remove this response; it is subsumed by GetCallSiteData.
  return GetHitsOrSites(thread, js, false);
}


static const char* kCallSitesStr = "_CallSites";
static const char* kCoverageStr = "Coverage";
static const char* kPossibleBreakpointsStr = "PossibleBreakpoints";


static const char* const report_enum_names[] = {
  kCallSitesStr,
  kCoverageStr,
  kPossibleBreakpointsStr,
  NULL,
};


static const MethodParameter* get_source_report_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new EnumListParameter("reports", true, report_enum_names),
  new IdParameter("scriptId", false),
  new UIntParameter("tokenPos", false),
  new UIntParameter("endTokenPos", false),
  new BoolParameter("forceCompile", false),
  NULL,
};


static bool GetSourceReport(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot get source report when running a precompiled program.");
    return true;
  }
  const char* reports_str = js->LookupParam("reports");
  const EnumListParameter* reports_parameter =
      static_cast<const EnumListParameter*>(get_source_report_params[1]);
  const char** reports = reports_parameter->Parse(thread->zone(), reports_str);
  intptr_t report_set = 0;
  while (*reports != NULL) {
    if (strcmp(*reports, kCallSitesStr) == 0) {
      report_set |= SourceReport::kCallSites;
    } else if (strcmp(*reports, kCoverageStr) == 0) {
      report_set |= SourceReport::kCoverage;
    } else if (strcmp(*reports, kPossibleBreakpointsStr) == 0) {
      report_set |= SourceReport::kPossibleBreakpoints;
    }
    reports++;
  }

  SourceReport::CompileMode compile_mode = SourceReport::kNoCompile;
  if (BoolParameter::Parse(js->LookupParam("forceCompile"), false)) {
    compile_mode = SourceReport::kForceCompile;
  }

  Script& script = Script::Handle();
  intptr_t start_pos = UIntParameter::Parse(js->LookupParam("tokenPos"));
  intptr_t end_pos = UIntParameter::Parse(js->LookupParam("endTokenPos"));

  if (js->HasParam("scriptId")) {
    // Get the target script.
    const char* script_id_param = js->LookupParam("scriptId");
    const Object& obj =
        Object::Handle(LookupHeapObject(thread, script_id_param, NULL));
    if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
      PrintInvalidParamError(js, "scriptId");
      return true;
    }
    script ^= obj.raw();
  } else {
    if (js->HasParam("tokenPos")) {
      js->PrintError(
          kInvalidParams,
          "%s: the 'tokenPos' parameter requires the 'scriptId' parameter",
          js->method());
      return true;
    }
    if (js->HasParam("endTokenPos")) {
      js->PrintError(
          kInvalidParams,
          "%s: the 'endTokenPos' parameter requires the 'scriptId' parameter",
          js->method());
      return true;
    }
  }
  SourceReport report(report_set, compile_mode);
  report.PrintJSON(js,
                   script,
                   TokenPosition(start_pos),
                   TokenPosition(end_pos));
  return true;
}


static const MethodParameter* get_call_site_data_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("targetId", false),
  NULL,
};


static bool GetCallSiteData(Thread* thread, JSONStream* js) {
  return GetHitsOrSites(thread, js, true);
}


static bool AddBreakpointCommon(Thread* thread,
                                JSONStream* js,
                                const String& script_uri) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot use breakpoints when running a precompiled program.");
    return true;
  }
  const char* line_param = js->LookupParam("line");
  intptr_t line = UIntParameter::Parse(line_param);
  const char* col_param = js->LookupParam("column");
  intptr_t col = -1;
  if (col_param != NULL) {
    col = UIntParameter::Parse(col_param);
    if (col == 0) {
      // Column number is 1-based.
      PrintInvalidParamError(js, "column");
      return true;
    }
  }
  ASSERT(!script_uri.IsNull());
  Breakpoint* bpt = NULL;
  bpt = thread->isolate()->debugger()->
      SetBreakpointAtLineCol(script_uri, line, col);
  if (bpt == NULL) {
    js->PrintError(kCannotAddBreakpoint,
                   "%s: Cannot add breakpoint at line '%s'",
                   js->method(), line_param);
    return true;
  }
  bpt->PrintJSON(js);
  return true;
}


static const MethodParameter* add_breakpoint_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("scriptId", true),
  new UIntParameter("line", true),
  new UIntParameter("column", false),
  NULL,
};


static bool AddBreakpoint(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot use breakpoints when running a precompiled program.");
    return true;
  }
  const char* script_id_param = js->LookupParam("scriptId");
  Object& obj = Object::Handle(LookupHeapObject(thread, script_id_param, NULL));
  if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
    PrintInvalidParamError(js, "scriptId");
    return true;
  }
  const Script& script = Script::Cast(obj);
  const String& script_uri = String::Handle(script.url());
  ASSERT(!script_uri.IsNull());
  return AddBreakpointCommon(thread, js, script_uri);
}


static const MethodParameter* add_breakpoint_with_script_uri_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("scriptUri", true),
  new UIntParameter("line", true),
  new UIntParameter("column", false),
  NULL,
};


static bool AddBreakpointWithScriptUri(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot use breakpoints when running a precompiled program.");
    return true;
  }
  const char* script_uri_param = js->LookupParam("scriptUri");
  const String& script_uri = String::Handle(String::New(script_uri_param));
  return AddBreakpointCommon(thread, js, script_uri);
}


static const MethodParameter* add_breakpoint_at_entry_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("functionId", true),
  NULL,
};


static bool AddBreakpointAtEntry(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot use breakpoints when running a precompiled program.");
    return true;
  }
  const char* function_id = js->LookupParam("functionId");
  Object& obj = Object::Handle(LookupHeapObject(thread, function_id, NULL));
  if (obj.raw() == Object::sentinel().raw() || !obj.IsFunction()) {
    PrintInvalidParamError(js, "functionId");
    return true;
  }
  const Function& function = Function::Cast(obj);
  Breakpoint* bpt =
      thread->isolate()->debugger()->SetBreakpointAtEntry(function, false);
  if (bpt == NULL) {
    js->PrintError(kCannotAddBreakpoint,
                   "%s: Cannot add breakpoint at function '%s'",
                   js->method(), function.ToCString());
    return true;
  }
  bpt->PrintJSON(js);
  return true;
}


static const MethodParameter* add_breakpoint_at_activation_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("objectId", true),
  NULL,
};


static bool AddBreakpointAtActivation(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot use breakpoints when running a precompiled program.");
    return true;
  }
  const char* object_id = js->LookupParam("objectId");
  Object& obj = Object::Handle(LookupHeapObject(thread, object_id, NULL));
  if (obj.raw() == Object::sentinel().raw() || !obj.IsInstance()) {
    PrintInvalidParamError(js, "objectId");
    return true;
  }
  const Instance& closure = Instance::Cast(obj);
  Breakpoint* bpt =
      thread->isolate()->debugger()->SetBreakpointAtActivation(closure, false);
  if (bpt == NULL) {
    js->PrintError(kCannotAddBreakpoint,
                   "%s: Cannot add breakpoint at activation",
                   js->method());
    return true;
  }
  bpt->PrintJSON(js);
  return true;
}


static const MethodParameter* remove_breakpoint_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool RemoveBreakpoint(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot use breakpoints when running a precompiled program.");
    return true;
  }
  if (!js->HasParam("breakpointId")) {
    PrintMissingParamError(js, "breakpointId");
    return true;
  }
  const char* bpt_id = js->LookupParam("breakpointId");
  ObjectIdRing::LookupResult lookup_result;
  Isolate* isolate = thread->isolate();
  Breakpoint* bpt = LookupBreakpoint(isolate, bpt_id, &lookup_result);
  // TODO(turnidge): Should we return a different error for bpts whic
  // have been already removed?
  if (bpt == NULL) {
    PrintInvalidParamError(js, "breakpointId");
    return true;
  }
  isolate->debugger()->RemoveBreakpoint(bpt->id());
  PrintSuccess(js);
  return true;
}


static RawClass* GetMetricsClass(Thread* thread) {
  Zone* zone = thread->zone();
  const Library& prof_lib =
      Library::Handle(zone, Library::DeveloperLibrary());
  ASSERT(!prof_lib.IsNull());
  const String& metrics_cls_name =
      String::Handle(zone, String::New("Metrics"));
  ASSERT(!metrics_cls_name.IsNull());
  const Class& metrics_cls =
      Class::Handle(zone, prof_lib.LookupClass(metrics_cls_name));
  ASSERT(!metrics_cls.IsNull());
  return metrics_cls.raw();
}



static bool HandleNativeMetricsList(Thread* thread, JSONStream* js) {
  JSONObject obj(js);
  obj.AddProperty("type", "MetricList");
  {
    JSONArray metrics(&obj, "metrics");
    Metric* current = thread->isolate()->metrics_list_head();
    while (current != NULL) {
      metrics.AddValue(current);
      current = current->next();
    }
  }
  return true;
}


static bool HandleNativeMetric(Thread* thread, JSONStream* js, const char* id) {
  Metric* current = thread->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();
  }
  PrintInvalidParamError(js, "metricId");
  return true;
}


static bool HandleDartMetricsList(Thread* thread, JSONStream* js) {
  Zone* zone = thread->zone();
  const Class& metrics_cls =
      Class::Handle(zone, GetMetricsClass(thread));
  const String& print_metrics_name =
      String::Handle(String::New("_printMetrics"));
  ASSERT(!print_metrics_name.IsNull());
  const Function& print_metrics = Function::Handle(
      zone,
      metrics_cls.LookupStaticFunctionAllowPrivate(print_metrics_name));
  ASSERT(!print_metrics.IsNull());
  const Array& args = Object::empty_array();
  const Object& result =
      Object::Handle(zone, 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 HandleDartMetric(Thread* thread, JSONStream* js, const char* id) {
  Zone* zone = thread->zone();
  const Class& metrics_cls =
      Class::Handle(zone, GetMetricsClass(thread));
  const String& print_metric_name =
      String::Handle(String::New("_printMetric"));
  ASSERT(!print_metric_name.IsNull());
  const Function& print_metric = Function::Handle(
      zone,
      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(zone, DartEntry::InvokeFunction(print_metric, args));
  if (!result.IsNull()) {
    ASSERT(result.IsString());
    TextBuffer* buffer = js->buffer();
    buffer->AddString(String::Cast(result).ToCString());
    return true;
  }
  PrintInvalidParamError(js, "metricId");
  return true;
}


static const MethodParameter* get_isolate_metric_list_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetIsolateMetricList(Thread* thread, JSONStream* js) {
  bool native_metrics = false;
  if (js->HasParam("type")) {
    if (js->ParamIs("type", "Native")) {
      native_metrics = true;
    } else if (js->ParamIs("type", "Dart")) {
      native_metrics = false;
    } else {
      PrintInvalidParamError(js, "type");
      return true;
    }
  } else {
    PrintMissingParamError(js, "type");
    return true;
  }
  if (native_metrics) {
    return HandleNativeMetricsList(thread, js);
  }
  return HandleDartMetricsList(thread, js);
}


static const MethodParameter* get_isolate_metric_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetIsolateMetric(Thread* thread, JSONStream* js) {
  const char* metric_id = js->LookupParam("metricId");
  if (metric_id == NULL) {
    PrintMissingParamError(js, "metricId");
    return true;
  }
  // Verify id begins with "metrics/".
  static const char* const kMetricIdPrefix = "metrics/";
  static intptr_t kMetricIdPrefixLen = strlen(kMetricIdPrefix);
  if (strncmp(metric_id, kMetricIdPrefix, kMetricIdPrefixLen) != 0) {
    PrintInvalidParamError(js, "metricId");
    return true;
  }
  // Check if id begins with "metrics/native/".
  static const char* const kNativeMetricIdPrefix = "metrics/native/";
  static intptr_t kNativeMetricIdPrefixLen = strlen(kNativeMetricIdPrefix);
  const bool native_metric =
      strncmp(metric_id, kNativeMetricIdPrefix, kNativeMetricIdPrefixLen) == 0;
  if (native_metric) {
    const char* id = metric_id + kNativeMetricIdPrefixLen;
    return HandleNativeMetric(thread, js, id);
  }
  const char* id = metric_id + kMetricIdPrefixLen;
  return HandleDartMetric(thread, js, id);
}


static const MethodParameter* get_vm_metric_list_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool GetVMMetricList(Thread* thread, JSONStream* js) {
  return false;
}


static const MethodParameter* get_vm_metric_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool GetVMMetric(Thread* thread, JSONStream* js) {
  const char* metric_id = js->LookupParam("metricId");
  if (metric_id == NULL) {
    PrintMissingParamError(js, "metricId");
  }
  return false;
}

static const char* const timeline_streams_enum_names[] = {
  "all",
#define DEFINE_NAME(name, unused)                                              \
  #name,
ISOLATE_TIMELINE_STREAM_LIST(DEFINE_NAME)
#undef DEFINE_NAME
  "VM",
  NULL
};

static const MethodParameter* set_vm_timeline_flags_params[] = {
  NO_ISOLATE_PARAMETER,
  new EnumListParameter("recordedStreams",
                        false,
                        timeline_streams_enum_names),
  NULL,
};


static bool HasStream(const char** recorded_streams, const char* stream) {
  while (*recorded_streams != NULL) {
    if ((strstr(*recorded_streams, "all") != NULL) ||
        (strstr(*recorded_streams, stream) != NULL)) {
      return true;
    }
    recorded_streams++;
  }
  return false;
}


static bool SetVMTimelineFlags(Thread* thread, JSONStream* js) {
  if (!FLAG_support_timeline) {
    PrintSuccess(js);
    return true;
  }
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  StackZone zone(thread);

  const EnumListParameter* recorded_streams_param =
      static_cast<const EnumListParameter*>(set_vm_timeline_flags_params[1]);

  const char* recorded_streams_str = js->LookupParam("recordedStreams");
  const char** recorded_streams =
      recorded_streams_param->Parse(thread->zone(), recorded_streams_str);

#define SET_ENABLE_STREAM(name, unused)                                        \
  Timeline::SetStream##name##Enabled(HasStream(recorded_streams, #name));
ISOLATE_TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
#undef SET_ENABLE_STREAM
  Timeline::SetVMStreamEnabled(HasStream(recorded_streams, "VM"));

  PrintSuccess(js);

  return true;
}


static const MethodParameter* get_vm_timeline_flags_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool GetVMTimelineFlags(Thread* thread, JSONStream* js) {
  if (!FLAG_support_timeline) {
    JSONObject obj(js);
    obj.AddProperty("type", "TimelineFlags");
    return true;
  }
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  StackZone zone(thread);
  Timeline::PrintFlagsToJSON(js);
  return true;
}


static const MethodParameter* clear_vm_timeline_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool ClearVMTimeline(Thread* thread, JSONStream* js) {
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  StackZone zone(thread);

  Timeline::Clear();

  PrintSuccess(js);

  return true;
}


static const MethodParameter* get_vm_timeline_params[] = {
  NO_ISOLATE_PARAMETER,
  new Int64Parameter("timeOriginMicros", false),
  new Int64Parameter("timeExtentMicros", false),
  NULL,
};


static bool GetVMTimeline(Thread* thread, JSONStream* js) {
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  StackZone zone(thread);
  Timeline::ReclaimCachedBlocksFromThreads();
  TimelineEventRecorder* timeline_recorder = Timeline::recorder();
  // TODO(johnmccutchan): Return an error.
  ASSERT(timeline_recorder != NULL);
  int64_t time_origin_micros =
      Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
  int64_t time_extent_micros =
      Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
  TimelineEventFilter filter(time_origin_micros, time_extent_micros);
  timeline_recorder->PrintJSON(js, &filter);
  return true;
}


static const MethodParameter* resume_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool Resume(Thread* thread, JSONStream* js) {
  const char* step_param = js->LookupParam("step");
  Isolate* isolate = thread->isolate();
  if (isolate->message_handler()->is_paused_on_start()) {
    // If the user is issuing a 'Over' or an 'Out' step, that is the
    // same as a regular resume request.
    if ((step_param != NULL) && (strcmp(step_param, "Into") == 0)) {
      isolate->debugger()->EnterSingleStepMode();
    }
    isolate->message_handler()->set_should_pause_on_start(false);
    isolate->SetResumeRequest();
    if (Service::debug_stream.enabled()) {
      ServiceEvent event(isolate, ServiceEvent::kResume);
      Service::HandleEvent(&event);
    }
    PrintSuccess(js);
    return true;
  }
  if (isolate->message_handler()->should_pause_on_start()) {
    isolate->message_handler()->set_should_pause_on_start(false);
    isolate->SetResumeRequest();
    if (Service::debug_stream.enabled()) {
      ServiceEvent event(isolate, ServiceEvent::kResume);
      Service::HandleEvent(&event);
    }
    PrintSuccess(js);
    return true;
  }
  if (isolate->message_handler()->is_paused_on_exit()) {
    isolate->message_handler()->set_should_pause_on_exit(false);
    isolate->SetResumeRequest();
    // We don't send a resume event because we will be exiting.
    PrintSuccess(js);
    return true;
  }
  if (isolate->debugger()->PauseEvent() != NULL) {
    if (step_param != NULL) {
      if (strcmp(step_param, "Into") == 0) {
        isolate->debugger()->SetSingleStep();
      } else if (strcmp(step_param, "Over") == 0) {
        isolate->debugger()->SetStepOver();
      } else if (strcmp(step_param, "Out") == 0) {
        isolate->debugger()->SetStepOut();
      } else if (strcmp(step_param, "OverAsyncSuspension") == 0) {
        if (!isolate->debugger()->SetupStepOverAsyncSuspension()) {
          js->PrintError(kInvalidParams,
                         "Isolate must be paused at an async suspension point");
          return true;
        }
      } else {
        PrintInvalidParamError(js, "step");
        return true;
      }
    }
    isolate->SetResumeRequest();
    PrintSuccess(js);
    return true;
  }

  js->PrintError(kVMMustBePaused, NULL);
  return true;
}


static const MethodParameter* pause_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool Pause(Thread* thread, JSONStream* js) {
  // TODO(turnidge): This interrupt message could have been sent from
  // the service isolate directly, but would require some special case
  // code.  That would prevent this isolate getting double-interrupted
  // with OOB messages.
  Isolate* isolate = thread->isolate();
  isolate->SendInternalLibMessage(Isolate::kInterruptMsg,
                                  isolate->pause_capability());
  PrintSuccess(js);
  return true;
}


static const MethodParameter* get_tag_profile_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetTagProfile(Thread* thread, JSONStream* js) {
  JSONObject miniProfile(js);
  miniProfile.AddProperty("type", "TagProfile");
  thread->isolate()->vm_tag_counters()->PrintToJSONObject(&miniProfile);
  return true;
}


static const char* const tags_enum_names[] = {
  "None",
  "UserVM",
  "UserOnly",
  "VMUser",
  "VMOnly",
  NULL,
};


static const Profile::TagOrder tags_enum_values[] = {
  Profile::kNoTags,
  Profile::kUserVM,
  Profile::kUser,
  Profile::kVMUser,
  Profile::kVM,
  Profile::kNoTags,  // Default value.
};


static const MethodParameter* get_cpu_profile_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new EnumParameter("tags", true, tags_enum_names),
  new BoolParameter("_codeTransitionTags", false),
  new Int64Parameter("timeOriginMicros", false),
  new Int64Parameter("timeExtentMicros", false),
  NULL,
};


// TODO(johnmccutchan): Rename this to GetCpuSamples.
static bool GetCpuProfile(Thread* thread, JSONStream* js) {
  Profile::TagOrder tag_order =
      EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
  intptr_t extra_tags = 0;
  if (BoolParameter::Parse(js->LookupParam("_codeTransitionTags"))) {
    extra_tags |= ProfilerService::kCodeTransitionTagsBit;
  }
  int64_t time_origin_micros =
      Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
  int64_t time_extent_micros =
      Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
  ProfilerService::PrintJSON(js,
                             tag_order,
                             extra_tags,
                             time_origin_micros,
                             time_extent_micros);
  return true;
}


static const MethodParameter* get_cpu_profile_timeline_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new EnumParameter("tags", true, tags_enum_names),
  new Int64Parameter("timeOriginMicros", false),
  new Int64Parameter("timeExtentMicros", false),
  NULL,
};


static bool GetCpuProfileTimeline(Thread* thread, JSONStream* js) {
  Profile::TagOrder tag_order =
      EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
  int64_t time_origin_micros =
      UIntParameter::Parse(js->LookupParam("timeOriginMicros"));
  int64_t time_extent_micros =
      UIntParameter::Parse(js->LookupParam("timeExtentMicros"));
  ProfilerService::PrintTimelineJSON(js,
                                     tag_order,
                                     time_origin_micros,
                                     time_extent_micros);
  return true;
}


static const MethodParameter* get_allocation_samples_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new EnumParameter("tags", true, tags_enum_names),
  new IdParameter("classId", false),
  new Int64Parameter("timeOriginMicros", false),
  new Int64Parameter("timeExtentMicros", false),
  NULL,
};


static bool GetAllocationSamples(Thread* thread, JSONStream* js) {
  Profile::TagOrder tag_order =
      EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
  int64_t time_origin_micros =
      Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
  int64_t time_extent_micros =
      Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
  const char* class_id = js->LookupParam("classId");
  intptr_t cid = -1;
  GetPrefixedIntegerId(class_id, "classes/", &cid);
  Isolate* isolate = thread->isolate();
  if (IsValidClassId(isolate, cid)) {
    const Class& cls = Class::Handle(GetClassForId(isolate, cid));
    ProfilerService::PrintAllocationJSON(js,
                                         tag_order,
                                         cls,
                                         time_origin_micros,
                                         time_extent_micros);
  } else {
    PrintInvalidParamError(js, "classId");
  }
  return true;
}


static const MethodParameter* clear_cpu_profile_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool ClearCpuProfile(Thread* thread, JSONStream* js) {
  ProfilerService::ClearSamples();
  PrintSuccess(js);
  return true;
}


static const MethodParameter* get_allocation_profile_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetAllocationProfile(Thread* thread, JSONStream* js) {
  bool should_reset_accumulator = false;
  bool should_collect = false;
  if (js->HasParam("reset")) {
    if (js->ParamIs("reset", "true")) {
      should_reset_accumulator = true;
    } else {
      PrintInvalidParamError(js, "reset");
      return true;
    }
  }
  if (js->HasParam("gc")) {
    if (js->ParamIs("gc", "full")) {
      should_collect = true;
    } else {
      PrintInvalidParamError(js, "gc");
      return true;
    }
  }
  Isolate* isolate = thread->isolate();
  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 const MethodParameter* get_heap_map_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetHeapMap(Thread* thread, JSONStream* js) {
  Isolate* isolate = thread->isolate();
  isolate->heap()->PrintHeapMapToJSONStream(isolate, js);
  return true;
}


static const MethodParameter* request_heap_snapshot_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool RequestHeapSnapshot(Thread* thread, JSONStream* js) {
  if (Service::graph_stream.enabled()) {
    Service::SendGraphEvent(thread);
  }
  // TODO(koda): Provide some id that ties this request to async response(s).
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "OK");
  return true;
}


void Service::SendGraphEvent(Thread* thread) {
  uint8_t* buffer = NULL;
  WriteStream stream(&buffer, &allocator, 1 * MB);
  ObjectGraph graph(thread);
  intptr_t node_count = graph.Serialize(&stream);

  // Chrome crashes receiving a single tens-of-megabytes blob, so send the
  // snapshot in megabyte-sized chunks instead.
  const intptr_t kChunkSize = 1 * MB;
  intptr_t num_chunks =
      (stream.bytes_written() + (kChunkSize - 1)) / kChunkSize;
  for (intptr_t i = 0; i < num_chunks; i++) {
    JSONStream js;
    {
      JSONObject jsobj(&js);
      jsobj.AddProperty("jsonrpc", "2.0");
      jsobj.AddProperty("method", "streamNotify");
      {
        JSONObject params(&jsobj, "params");
        params.AddProperty("streamId", graph_stream.id());
        {
          JSONObject event(&params, "event");
          event.AddProperty("type", "Event");
          event.AddProperty("kind", "_Graph");
          event.AddProperty("isolate", thread->isolate());
          event.AddPropertyTimeMillis("timestamp", OS::GetCurrentTimeMillis());

          event.AddProperty("chunkIndex", i);
          event.AddProperty("chunkCount", num_chunks);
          event.AddProperty("nodeCount", node_count);
        }
      }
    }

    const String& message = String::Handle(String::New(js.ToCString()));

    uint8_t* chunk_start = buffer + (i * kChunkSize);
    intptr_t chunk_size = (i + 1 == num_chunks)
        ? stream.bytes_written() - (i * kChunkSize)
        : kChunkSize;

    SendEventWithData(graph_stream.id(), "_Graph", message,
                      chunk_start, chunk_size);
  }
}


void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) {
  if (!Service::debug_stream.enabled()) {
    return;
  }
  ServiceEvent event(isolate, ServiceEvent::kInspect);
  event.set_inspectee(&inspectee);
  Service::HandleEvent(&event);
}


void Service::SendEmbedderEvent(Isolate* isolate,
                                const char* stream_id,
                                const char* event_kind,
                                const uint8_t* bytes,
                                intptr_t bytes_len) {
  if (!Service::debug_stream.enabled()) {
    return;
  }
  ServiceEvent event(isolate, ServiceEvent::kEmbedder);
  event.set_embedder_kind(event_kind);
  event.set_embedder_stream_id(stream_id);
  event.set_bytes(bytes, bytes_len);
  Service::HandleEvent(&event);
}


void Service::SendLogEvent(Isolate* isolate,
                           int64_t sequence_number,
                           int64_t timestamp,
                           intptr_t level,
                           const String& name,
                           const String& message,
                           const Instance& zone,
                           const Object& error,
                           const Instance& stack_trace) {
  if (!Service::logging_stream.enabled()) {
    return;
  }
  ServiceEvent::LogRecord log_record;
  log_record.sequence_number = sequence_number;
  log_record.timestamp = timestamp;
  log_record.level = level;
  log_record.name = &name;
  log_record.message = &message;
  log_record.zone = &zone;
  log_record.error = &error;
  log_record.stack_trace = &stack_trace;
  ServiceEvent event(isolate, ServiceEvent::kLogging);
  event.set_log_record(log_record);
  Service::HandleEvent(&event);
}


void Service::SendExtensionEvent(Isolate* isolate,
                                 const String& event_kind,
                                 const String& event_data) {
  if (!Service::extension_stream.enabled()) {
    return;
  }
  ServiceEvent::ExtensionEvent extension_event;
  extension_event.event_kind = &event_kind;
  extension_event.event_data = &event_data;
  ServiceEvent event(isolate, ServiceEvent::kExtension);
  event.set_extension_event(extension_event);
  Service::HandleEvent(&event);
}


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 const MethodParameter* get_object_by_address_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static RawObject* GetObjectHelper(Thread* thread, uword addr) {
  Object& object = Object::Handle(thread->zone());

  {
    NoSafepointScope no_safepoint;
    Isolate* isolate = thread->isolate();
    ContainsAddressVisitor visitor(isolate, addr);
    object = isolate->heap()->FindObject(&visitor);
  }

  if (!object.IsNull()) {
    return object.raw();
  }

  {
    NoSafepointScope no_safepoint;
    ContainsAddressVisitor visitor(Dart::vm_isolate(), addr);
    object = Dart::vm_isolate()->heap()->FindObject(&visitor);
  }

  return object.raw();
}


static bool GetObjectByAddress(Thread* thread, JSONStream* js) {
  const char* addr_str = js->LookupParam("address");
  if (addr_str == NULL) {
    PrintMissingParamError(js, "address");
    return true;
  }

  // Handle heap objects.
  uword addr = 0;
  if (!GetUnsignedIntegerId(addr_str, &addr, 16)) {
    PrintInvalidParamError(js, "address");
    return true;
  }
  bool ref = js->HasParam("ref") && js->ParamIs("ref", "true");
  const Object& obj = Object::Handle(thread->zone(),
      GetObjectHelper(thread, addr));
  if (obj.IsNull()) {
    PrintSentinel(js, kFreeSentinel);
  } else {
    obj.PrintJSON(js, ref);
  }
  return true;
}


static const MethodParameter* get_persistent_handles_params[] = {
  ISOLATE_PARAMETER,
  NULL,
};


template<typename T>
class PersistentHandleVisitor : public HandleVisitor {
 public:
  PersistentHandleVisitor(Thread* thread, JSONArray* handles)
      : HandleVisitor(thread),
        handles_(handles) {
    ASSERT(handles_ != NULL);
  }

  void Append(PersistentHandle* persistent_handle) {
    JSONObject obj(handles_);
    obj.AddProperty("type", "_PersistentHandle");
    const Object& object = Object::Handle(persistent_handle->raw());
    obj.AddProperty("object", object);
  }

  void Append(FinalizablePersistentHandle* weak_persistent_handle) {
    JSONObject obj(handles_);
    obj.AddProperty("type", "_WeakPersistentHandle");
    const Object& object =
        Object::Handle(weak_persistent_handle->raw());
    obj.AddProperty("object", object);
    obj.AddPropertyF(
        "peer",
        "0x%" Px "",
        reinterpret_cast<uintptr_t>(weak_persistent_handle->peer()));
    obj.AddPropertyF(
        "callbackAddress",
        "0x%" Px "",
        reinterpret_cast<uintptr_t>(weak_persistent_handle->callback()));
    // Attempt to include a native symbol name.
    char* name = NativeSymbolResolver::LookupSymbolName(
        reinterpret_cast<uintptr_t>(weak_persistent_handle->callback()),
        NULL);
    obj.AddProperty("callbackSymbolName",
                    (name == NULL) ? "" : name);
    if (name != NULL) {
      NativeSymbolResolver::FreeSymbolName(name);
    }
    obj.AddPropertyF("externalSize",
                     "%" Pd "",
                     weak_persistent_handle->external_size());
  }

 protected:
  virtual void VisitHandle(uword addr) {
    T* handle = reinterpret_cast<T*>(addr);
    Append(handle);
  }

  JSONArray* handles_;
};


static bool GetPersistentHandles(Thread* thread, JSONStream* js) {
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);

  ApiState* api_state = isolate->api_state();
  ASSERT(api_state != NULL);

  {
    JSONObject obj(js);
    obj.AddProperty("type", "_PersistentHandles");
    // Persistent handles.
    {
      JSONArray persistent_handles(&obj, "persistentHandles");
      PersistentHandles& handles = api_state->persistent_handles();
      PersistentHandleVisitor<PersistentHandle> visitor(
          thread, &persistent_handles);
      handles.Visit(&visitor);
    }
    // Weak persistent handles.
    {
      JSONArray weak_persistent_handles(&obj, "weakPersistentHandles");
      FinalizablePersistentHandles& handles =
          api_state->weak_persistent_handles();
      PersistentHandleVisitor<FinalizablePersistentHandle> visitor(
          thread, &weak_persistent_handles);
      handles.VisitHandles(&visitor);
    }
  }

  return true;
}


static const MethodParameter* get_ports_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetPorts(Thread* thread, JSONStream* js) {
  MessageHandler* message_handler = thread->isolate()->message_handler();
  PortMap::PrintPortsForMessageHandler(message_handler, js);
  return true;
}


static bool RespondWithMalformedJson(Thread* thread, 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 RespondWithMalformedObject(Thread* thread, JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("bart", "simpson");
  return true;
}


static const MethodParameter* get_object_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new UIntParameter("offset", false),
  new UIntParameter("count", false),
  NULL,
};


static bool GetObject(Thread* thread, JSONStream* js) {
  const char* id = js->LookupParam("objectId");
  if (id == NULL) {
    PrintMissingParamError(js, "objectId");
    return true;
  }
  if (js->HasParam("offset")) {
    intptr_t value = UIntParameter::Parse(js->LookupParam("offset"));
    if (value < 0) {
      PrintInvalidParamError(js, "offset");
      return true;
    }
    js->set_offset(value);
  }
  if (js->HasParam("count")) {
    intptr_t value = UIntParameter::Parse(js->LookupParam("count"));
    if (value < 0) {
      PrintInvalidParamError(js, "count");
      return true;
    }
    js->set_count(value);
  }

  // Handle heap objects.
  ObjectIdRing::LookupResult lookup_result;
  const Object& obj =
      Object::Handle(LookupHeapObject(thread, id, &lookup_result));
  if (obj.raw() != Object::sentinel().raw()) {
    // We found a heap object for this id.  Return it.
    obj.PrintJSON(js, false);
    return true;
  } else if (lookup_result == ObjectIdRing::kCollected) {
    PrintSentinel(js, kCollectedSentinel);
    return true;
  } else if (lookup_result == ObjectIdRing::kExpired) {
    PrintSentinel(js, kExpiredSentinel);
    return true;
  }

  // Handle non-heap objects.
  Breakpoint* bpt = LookupBreakpoint(thread->isolate(), id, &lookup_result);
  if (bpt != NULL) {
    bpt->PrintJSON(js);
    return true;
  } else if (lookup_result == ObjectIdRing::kCollected) {
    PrintSentinel(js, kCollectedSentinel);
    return true;
  }

  PrintInvalidParamError(js, "objectId");
  return true;
}


static const MethodParameter* get_class_list_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetClassList(Thread* thread, JSONStream* js) {
  ClassTable* table = thread->isolate()->class_table();
  JSONObject jsobj(js);
  table->PrintToJSONObject(&jsobj);
  return true;
}


static const MethodParameter* get_type_arguments_list_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  NULL,
};


static bool GetTypeArgumentsList(Thread* thread, JSONStream* js) {
  bool only_with_instantiations = false;
  if (js->ParamIs("onlyWithInstantiations", "true")) {
    only_with_instantiations = true;
  }
  ObjectStore* object_store = thread->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)));
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "TypeArgumentsList");
  jsobj.AddProperty("canonicalTypeArgumentsTableSize", table_size);
  jsobj.AddProperty("canonicalTypeArgumentsTableUsed", table_used);
  JSONArray members(&jsobj, "typeArguments");
  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;
}


static const MethodParameter* get_version_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool GetVersion(Thread* thread, JSONStream* js) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", "Version");
  jsobj.AddProperty("major", static_cast<intptr_t>(3));
  jsobj.AddProperty("minor", static_cast<intptr_t>(3));
  jsobj.AddProperty("_privateMajor", static_cast<intptr_t>(0));
  jsobj.AddProperty("_privateMinor", static_cast<intptr_t>(0));
  return true;
}


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

  virtual ~ServiceIsolateVisitor() {}

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

 private:
  JSONArray* jsarr_;
};


static const MethodParameter* get_vm_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


void Service::PrintJSONForVM(JSONStream* js, bool ref) {
  JSONObject jsobj(js);
  jsobj.AddProperty("type", (ref ? "@VM" : "VM"));
  jsobj.AddProperty("name", GetVMName());
  if (ref) {
    return;
  }
  Isolate* vm_isolate = Dart::vm_isolate();
  jsobj.AddProperty("architectureBits", static_cast<intptr_t>(kBitsPerWord));
  jsobj.AddProperty("targetCPU", CPU::Id());
  jsobj.AddProperty("hostCPU", HostCPUFeatures::hardware());
  jsobj.AddProperty("version", Version::String());
  jsobj.AddProperty64("pid", OS::ProcessId());
  int64_t start_time_millis = (vm_isolate->start_time() /
                               kMicrosecondsPerMillisecond);
  jsobj.AddPropertyTimeMillis("startTime", start_time_millis);
  // Construct the isolate list.
  {
    JSONArray jsarr(&jsobj, "isolates");
    ServiceIsolateVisitor visitor(&jsarr);
    Isolate::VisitIsolates(&visitor);
  }
}


static bool GetVM(Thread* thread, JSONStream* js) {
  Service::PrintJSONForVM(js, false);
  return true;
}


static const MethodParameter* restart_vm_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool RestartVM(Thread* thread, JSONStream* js) {
  Isolate::KillAllIsolates(Isolate::kVMRestartMsg);
  PrintSuccess(js);
  return true;
}


static const char* exception_pause_mode_names[] = {
  "All",
  "None",
  "Unhandled",
  NULL,
};


static Dart_ExceptionPauseInfo exception_pause_mode_values[] = {
  kPauseOnAllExceptions,
  kNoPauseOnExceptions,
  kPauseOnUnhandledExceptions,
  kInvalidExceptionPauseInfo,
};


static const MethodParameter* set_exception_pause_mode_params[] = {
  ISOLATE_PARAMETER,
  new EnumParameter("mode", true, exception_pause_mode_names),
  NULL,
};


static bool SetExceptionPauseMode(Thread* thread, JSONStream* js) {
  const char* mode = js->LookupParam("mode");
  if (mode == NULL) {
    PrintMissingParamError(js, "mode");
    return true;
  }
  Dart_ExceptionPauseInfo info =
      EnumMapper(mode, exception_pause_mode_names, exception_pause_mode_values);
  if (info == kInvalidExceptionPauseInfo) {
    PrintInvalidParamError(js, "mode");
    return true;
  }
  Isolate* isolate = thread->isolate();
  isolate->debugger()->SetExceptionPauseInfo(info);
  if (Service::debug_stream.enabled()) {
    ServiceEvent event(isolate, ServiceEvent::kDebuggerSettingsUpdate);
    Service::HandleEvent(&event);
  }
  PrintSuccess(js);
  return true;
}


static const MethodParameter* get_flag_list_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool GetFlagList(Thread* thread, JSONStream* js) {
  Flags::PrintJSON(js);
  return true;
}


static const MethodParameter* set_flags_params[] = {
  NO_ISOLATE_PARAMETER,
  NULL,
};


static bool SetFlag(Thread* thread, JSONStream* js) {
  const char* flag_name = js->LookupParam("name");
  if (flag_name == NULL) {
    PrintMissingParamError(js, "name");
    return true;
  }
  const char* flag_value = js->LookupParam("value");
  if (flag_value == NULL) {
    PrintMissingParamError(js, "value");
    return true;
  }
  const char* error = NULL;
  if (Flags::SetFlag(flag_name, flag_value, &error)) {
    PrintSuccess(js);
    return true;
  } else {
    JSONObject jsobj(js);
    jsobj.AddProperty("type", "Error");
    jsobj.AddProperty("message", error);
    return true;
  }
}


static const MethodParameter* set_library_debuggable_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("libraryId", true),
  new BoolParameter("isDebuggable", true),
  NULL,
};


static bool SetLibraryDebuggable(Thread* thread, JSONStream* js) {
  const char* lib_id = js->LookupParam("libraryId");
  ObjectIdRing::LookupResult lookup_result;
  Object& obj = Object::Handle(LookupHeapObject(thread, lib_id,
                                                &lookup_result));
  const bool is_debuggable =
      BoolParameter::Parse(js->LookupParam("isDebuggable"), false);
  if (obj.IsLibrary()) {
    const Library& lib = Library::Cast(obj);
    lib.set_debuggable(is_debuggable);
    PrintSuccess(js);
    return true;
  }
  PrintInvalidParamError(js, "libraryId");
  return true;
}


static const MethodParameter* set_name_params[] = {
  ISOLATE_PARAMETER,
  new MethodParameter("name", true),
  NULL,
};


static bool SetName(Thread* thread, JSONStream* js) {
  Isolate* isolate = thread->isolate();
  isolate->set_debugger_name(js->LookupParam("name"));
  if (Service::isolate_stream.enabled()) {
    ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate);
    Service::HandleEvent(&event);
  }
  PrintSuccess(js);
  return true;
}


static const MethodParameter* set_vm_name_params[] = {
  new MethodParameter("name", true),
  NULL,
};


static bool SetVMName(Thread* thread, JSONStream* js) {
  const char* name_param = js->LookupParam("name");
  free(vm_name);
  vm_name = strdup(name_param);
  if (Service::vm_stream.enabled()) {
    ServiceEvent event(NULL, ServiceEvent::kVMUpdate);
    Service::HandleEvent(&event);
  }
  PrintSuccess(js);
  return true;
}


static const MethodParameter* set_trace_class_allocation_params[] = {
  RUNNABLE_ISOLATE_PARAMETER,
  new IdParameter("classId", true),
  new BoolParameter("enable", true),
  NULL,
};


static bool SetTraceClassAllocation(Thread* thread, JSONStream* js) {
  if (!thread->isolate()->compilation_allowed()) {
    js->PrintError(kFeatureDisabled,
        "Cannot trace allocation when running a precompiled program.");
    return true;
  }
  const char* class_id = js->LookupParam("classId");
  const bool enable = BoolParameter::Parse(js->LookupParam("enable"));
  intptr_t cid = -1;
  GetPrefixedIntegerId(class_id, "classes/", &cid);
  Isolate* isolate = thread->isolate();
  if (!IsValidClassId(isolate, cid)) {
    PrintInvalidParamError(js, "classId");
    return true;
  }
  const Class& cls = Class::Handle(GetClassForId(isolate, cid));
  ASSERT(!cls.IsNull());
  cls.SetTraceAllocation(enable);
  PrintSuccess(js);
  return true;
}


static const ServiceMethodDescriptor service_methods_[] = {
  { "_dumpIdZone", DumpIdZone, NULL },
  { "_echo", Echo,
    NULL },
  { "_respondWithMalformedJson", RespondWithMalformedJson,
    NULL },
  { "_respondWithMalformedObject", RespondWithMalformedObject,
    NULL },
  { "_triggerEchoEvent", TriggerEchoEvent,
    NULL },
  { "addBreakpoint", AddBreakpoint,
    add_breakpoint_params },
  { "addBreakpointWithScriptUri", AddBreakpointWithScriptUri,
    add_breakpoint_with_script_uri_params },
  { "addBreakpointAtEntry", AddBreakpointAtEntry,
    add_breakpoint_at_entry_params },
  { "_addBreakpointAtActivation", AddBreakpointAtActivation,
    add_breakpoint_at_activation_params },
  { "_clearCpuProfile", ClearCpuProfile,
    clear_cpu_profile_params },
  { "_clearVMTimeline", ClearVMTimeline,
    clear_vm_timeline_params, },
  { "evaluate", Evaluate,
    evaluate_params },
  { "evaluateInFrame", EvaluateInFrame,
    evaluate_in_frame_params },
  { "_getAllocationProfile", GetAllocationProfile,
    get_allocation_profile_params },
  { "_getAllocationSamples", GetAllocationSamples,
      get_allocation_samples_params },
  { "_getCallSiteData", GetCallSiteData,
    get_call_site_data_params },
  { "getClassList", GetClassList,
    get_class_list_params },
  { "_getCoverage", GetCoverage,
    get_coverage_params },
  { "_getCpuProfile", GetCpuProfile,
    get_cpu_profile_params },
  { "_getCpuProfileTimeline", GetCpuProfileTimeline,
    get_cpu_profile_timeline_params },
  { "getFlagList", GetFlagList,
    get_flag_list_params },
  { "_getHeapMap", GetHeapMap,
    get_heap_map_params },
  { "_getInboundReferences", GetInboundReferences,
    get_inbound_references_params },
  { "_getInstances", GetInstances,
    get_instances_params },
  { "getIsolate", GetIsolate,
    get_isolate_params },
  { "_getIsolateMetric", GetIsolateMetric,
    get_isolate_metric_params },
  { "_getIsolateMetricList", GetIsolateMetricList,
    get_isolate_metric_list_params },
  { "getObject", GetObject,
    get_object_params },
  { "_getObjectByAddress", GetObjectByAddress,
    get_object_by_address_params },
  { "_getPersistentHandles", GetPersistentHandles,
      get_persistent_handles_params, },
  { "_getPorts", GetPorts,
    get_ports_params },
  { "_getReachableSize", GetReachableSize,
    get_reachable_size_params },
  { "_getRetainedSize", GetRetainedSize,
    get_retained_size_params },
  { "_getRetainingPath", GetRetainingPath,
    get_retaining_path_params },
  { "getSourceReport", GetSourceReport,
    get_source_report_params },
  { "getStack", GetStack,
    get_stack_params },
  { "_getTagProfile", GetTagProfile,
    get_tag_profile_params },
  { "_getTypeArgumentsList", GetTypeArgumentsList,
    get_type_arguments_list_params },
  { "getVersion", GetVersion,
    get_version_params },
  { "getVM", GetVM,
    get_vm_params },
  { "_getVMMetric", GetVMMetric,
    get_vm_metric_params },
  { "_getVMMetricList", GetVMMetricList,
    get_vm_metric_list_params },
  { "_getVMTimeline", GetVMTimeline,
    get_vm_timeline_params },
  { "_getVMTimelineFlags", GetVMTimelineFlags,
    get_vm_timeline_flags_params },
  { "pause", Pause,
    pause_params },
  { "removeBreakpoint", RemoveBreakpoint,
    remove_breakpoint_params },
  { "_restartVM", RestartVM,
    restart_vm_params },
  { "resume", Resume,
    resume_params },
  { "_requestHeapSnapshot", RequestHeapSnapshot,
    request_heap_snapshot_params },
  { "setExceptionPauseMode", SetExceptionPauseMode,
    set_exception_pause_mode_params },
  { "_setFlag", SetFlag,
    set_flags_params },
  { "setLibraryDebuggable", SetLibraryDebuggable,
    set_library_debuggable_params },
  { "setName", SetName,
    set_name_params },
  { "_setTraceClassAllocation", SetTraceClassAllocation,
    set_trace_class_allocation_params },
  { "setVMName", SetVMName,
    set_vm_name_params },
  { "_setVMTimelineFlags", SetVMTimelineFlags,
    set_vm_timeline_flags_params },
};


const ServiceMethodDescriptor* FindMethod(const char* method_name) {
  intptr_t num_methods = sizeof(service_methods_) /
                         sizeof(service_methods_[0]);
  for (intptr_t i = 0; i < num_methods; i++) {
    const ServiceMethodDescriptor& method = service_methods_[i];
    if (strcmp(method_name, method.name) == 0) {
      return &method;
    }
  }
  return NULL;
}

#endif  // !PRODUCT

}  // namespace dart
