| Index: runtime/vm/service.cc | 
| =================================================================== | 
| --- runtime/vm/service.cc	(revision 34138) | 
| +++ runtime/vm/service.cc	(working copy) | 
| @@ -928,6 +928,40 @@ | 
| } | 
|  | 
|  | 
| +static bool HandleClassesTypes(Isolate* isolate, const Class& cls, | 
| +                               JSONStream* js) { | 
| +  if (js->num_arguments() == 3) { | 
| +    JSONObject jsobj(js); | 
| +    jsobj.AddProperty("type", "TypeList"); | 
| +    JSONArray members(&jsobj, "members"); | 
| +    const intptr_t num_types = cls.NumCanonicalTypes(); | 
| +    Type& type = Type::Handle(); | 
| +    for (intptr_t i = 0; i < num_types; i++) { | 
| +      type = cls.CanonicalTypeFromIndex(i); | 
| +      members.AddValue(type); | 
| +    } | 
| +    return true; | 
| +  } | 
| +  intptr_t id; | 
| +  if (js->num_arguments() > 4) { | 
| +    PrintError(js, "Command too long"); | 
| +    return true; | 
| +  } | 
| +  if (!GetIntegerId(js->GetArgument(3), &id)) { | 
| +    PrintError(js, "Must specify collection object id: types/id"); | 
| +    return true; | 
| +  } | 
| +  Type& type = Type::Handle(); | 
| +  type ^= cls.CanonicalTypeFromIndex(id); | 
| +  if (type.IsNull()) { | 
| +    PrintError(js, "Canonical type %" Pd " not found", id); | 
| +    return true; | 
| +  } | 
| +  type.PrintToJSONStream(js, false); | 
| +  return true; | 
| +} | 
| + | 
| + | 
| static bool HandleClasses(Isolate* isolate, JSONStream* js) { | 
| if (js->num_arguments() == 1) { | 
| ClassTable* table = isolate->class_table(); | 
| @@ -942,7 +976,7 @@ | 
| } | 
| ClassTable* table = isolate->class_table(); | 
| if (!table->IsValidIndex(id)) { | 
| -    PrintError(js, "%" Pd " is not a valid class id.", id);; | 
| +    PrintError(js, "%" Pd " is not a valid class id.", id); | 
| return true; | 
| } | 
| Class& cls = Class::Handle(table->At(id)); | 
| @@ -963,6 +997,8 @@ | 
| return HandleClassesImplicitClosures(isolate, cls, js); | 
| } else if (strcmp(second, "dispatchers") == 0) { | 
| return HandleClassesDispatchers(isolate, cls, js); | 
| +    } else if (!strcmp(second, "types")) { | 
| +      return HandleClassesTypes(isolate, cls, js); | 
| } else { | 
| PrintError(js, "Invalid sub collection %s", second); | 
| return true; | 
| @@ -1444,6 +1480,58 @@ | 
| } | 
|  | 
|  | 
| +static bool HandleTypeArguments(Isolate* isolate, JSONStream* js) { | 
| +  ObjectStore* object_store = isolate->object_store(); | 
| +  const Array& table = Array::Handle(object_store->canonical_type_arguments()); | 
| +  ASSERT(table.Length() > 0); | 
| +  TypeArguments& type_args = TypeArguments::Handle(); | 
| +  const intptr_t table_size = table.Length() - 1; | 
| +  const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size))); | 
| +  bool only_with_instantiations = false; | 
| +  if (js->num_arguments() >= 2) { | 
| +    const char* second = js->GetArgument(1); | 
| +    if (strcmp(second, "withinstantiations") == 0) { | 
| +      only_with_instantiations = true; | 
| +      if (js->num_arguments() > 2) { | 
| +        PrintError(js, "Command too long"); | 
| +        return true; | 
| +      } | 
| +    } | 
| +  } | 
| +  if ((js->num_arguments() == 1) || only_with_instantiations) { | 
| +    JSONObject jsobj(js); | 
| +    jsobj.AddProperty("type", "TypeArgumentsList"); | 
| +    jsobj.AddProperty("table_size", table_size); | 
| +    jsobj.AddProperty("table_used", table_used); | 
| +    JSONArray members(&jsobj, "members"); | 
| +    for (intptr_t i = 0; i < table_size; i++) { | 
| +      type_args ^= table.At(i); | 
| +      if (!type_args.IsNull()) { | 
| +        if (!only_with_instantiations || type_args.HasInstantiations()) { | 
| +          members.AddValue(type_args); | 
| +        } | 
| +      } | 
| +    } | 
| +    return true; | 
| +  } | 
| +  ASSERT((js->num_arguments() >= 2) && !only_with_instantiations); | 
| +  intptr_t id; | 
| +  if (!GetIntegerId(js->GetArgument(1), &id)) { | 
| +    // Note that the table index of the canonical type arguments will change | 
| +    // when the table grows. Should we not support this access at all? | 
| +    PrintError(js, "Must specify collection object id: /typearguments/id"); | 
| +    return true; | 
| +  } | 
| +  if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) { | 
| +    PrintError(js, "%" Pd " is not a valid typearguments id.", id); | 
| +    return true; | 
| +  } | 
| +  type_args ^= table.At(id); | 
| +  type_args.PrintToJSONStream(js, false); | 
| +  return true; | 
| +} | 
| + | 
| + | 
| static bool HandleHeapMap(Isolate* isolate, JSONStream* js) { | 
| isolate->heap()->PrintHeapMapToJSONStream(js); | 
| return true; | 
| @@ -1466,6 +1554,7 @@ | 
| { "resume", HandleResume }, | 
| { "scripts", HandleScripts }, | 
| { "stacktrace", HandleStackTrace }, | 
| +  { "typearguments", HandleTypeArguments }, | 
| }; | 
|  | 
|  | 
|  |