| Index: runtime/vm/object_service.cc
|
| diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..54bd965a46ae7997e8b64aac3ee7c4a659c6fe52
|
| --- /dev/null
|
| +++ b/runtime/vm/object_service.cc
|
| @@ -0,0 +1,1602 @@
|
| +// Copyright (c) 2016, 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/debugger.h"
|
| +#include "vm/disassembler.h"
|
| +#include "vm/object.h"
|
| +#include "vm/object_store.h"
|
| +#include "vm/stub_code.h"
|
| +#include "vm/symbols.h"
|
| +
|
| +namespace dart {
|
| +
|
| +#ifndef PRODUCT
|
| +
|
| +static void AddNameProperties(JSONObject* jsobj,
|
| + const String& name,
|
| + const String& vm_name) {
|
| + jsobj->AddProperty("name", name.ToCString());
|
| + if (!name.Equals(vm_name)) {
|
| + jsobj->AddProperty("_vmName", vm_name.ToCString());
|
| + }
|
| +}
|
| +
|
| +
|
| +void Object::AddCommonObjectProperties(JSONObject* jsobj,
|
| + const char* protocol_type,
|
| + bool ref) const {
|
| + const char* vm_type = JSONType();
|
| + bool same_type = (strcmp(protocol_type, vm_type) == 0);
|
| + if (ref) {
|
| + jsobj->AddPropertyF("type", "@%s", protocol_type);
|
| + } else {
|
| + jsobj->AddProperty("type", protocol_type);
|
| + }
|
| + if (!same_type) {
|
| + jsobj->AddProperty("_vmType", vm_type);
|
| + }
|
| + if (!ref || IsInstance() || IsNull()) {
|
| + // TODO(turnidge): Provide the type arguments here too?
|
| + const Class& cls = Class::Handle(this->clazz());
|
| + jsobj->AddProperty("class", cls);
|
| + }
|
| + if (!ref) {
|
| + if (raw()->IsHeapObject()) {
|
| + jsobj->AddProperty("size", raw()->Size());
|
| + } else {
|
| + jsobj->AddProperty("size", (intptr_t)0);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void Object::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + jsobj.AddServiceId(*this);
|
| + if (ref) {
|
| + return;
|
| + }
|
| +}
|
| +
|
| +
|
| +void Object::PrintJSON(JSONStream* stream, bool ref) const {
|
| + if (IsNull()) {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Instance", ref);
|
| + jsobj.AddProperty("kind", "Null");
|
| + jsobj.AddFixedServiceId("objects/null");
|
| + jsobj.AddProperty("valueAsString", "null");
|
| + } else {
|
| + PrintJSONImpl(stream, ref);
|
| + }
|
| +}
|
| +
|
| +
|
| +void Class::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Isolate* isolate = Isolate::Current();
|
| + JSONObject jsobj(stream);
|
| + if ((raw() == Class::null()) || (id() == kFreeListElement)) {
|
| + // TODO(turnidge): This is weird and needs to be changed.
|
| + jsobj.AddProperty("type", "null");
|
| + return;
|
| + }
|
| + AddCommonObjectProperties(&jsobj, "Class", ref);
|
| + jsobj.AddFixedServiceId("classes/%" Pd "", id());
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + const Error& err = Error::Handle(EnsureIsFinalized(Thread::Current()));
|
| + if (!err.IsNull()) {
|
| + jsobj.AddProperty("error", err);
|
| + }
|
| + jsobj.AddProperty("abstract", is_abstract());
|
| + jsobj.AddProperty("const", is_const());
|
| + jsobj.AddProperty("_finalized", is_finalized());
|
| + jsobj.AddProperty("_implemented", is_implemented());
|
| + jsobj.AddProperty("_patch", is_patch());
|
| + jsobj.AddProperty("_traceAllocations", TraceAllocation(isolate));
|
| + const Class& superClass = Class::Handle(SuperClass());
|
| + if (!superClass.IsNull()) {
|
| + jsobj.AddProperty("super", superClass);
|
| + }
|
| + jsobj.AddProperty("library", Object::Handle(library()));
|
| + const Script& script = Script::Handle(this->script());
|
| + if (!script.IsNull()) {
|
| + jsobj.AddLocation(script, token_pos(), ComputeEndTokenPos());
|
| + }
|
| + {
|
| + JSONArray interfaces_array(&jsobj, "interfaces");
|
| + const Array& interface_array = Array::Handle(interfaces());
|
| + Type& interface_type = Type::Handle();
|
| + if (!interface_array.IsNull()) {
|
| + for (intptr_t i = 0; i < interface_array.Length(); ++i) {
|
| + interface_type ^= interface_array.At(i);
|
| + interfaces_array.AddValue(interface_type);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray fields_array(&jsobj, "fields");
|
| + const Array& field_array = Array::Handle(fields());
|
| + Field& field = Field::Handle();
|
| + if (!field_array.IsNull()) {
|
| + for (intptr_t i = 0; i < field_array.Length(); ++i) {
|
| + field ^= field_array.At(i);
|
| + fields_array.AddValue(field);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray functions_array(&jsobj, "functions");
|
| + const Array& function_array = Array::Handle(functions());
|
| + Function& function = Function::Handle();
|
| + if (!function_array.IsNull()) {
|
| + for (intptr_t i = 0; i < function_array.Length(); i++) {
|
| + function ^= function_array.At(i);
|
| + functions_array.AddValue(function);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray subclasses_array(&jsobj, "subclasses");
|
| + const GrowableObjectArray& subclasses =
|
| + GrowableObjectArray::Handle(direct_subclasses());
|
| + if (!subclasses.IsNull()) {
|
| + Class& subclass = Class::Handle();
|
| + for (intptr_t i = 0; i < subclasses.Length(); ++i) {
|
| + // TODO(turnidge): Use the Type directly once regis has added
|
| + // types to the vmservice.
|
| + subclass ^= subclasses.At(i);
|
| + subclasses_array.AddValue(subclass);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + ClassTable* class_table = Isolate::Current()->class_table();
|
| + const ClassHeapStats* stats = class_table->StatsWithUpdatedSize(id());
|
| + if (stats != NULL) {
|
| + JSONObject allocation_stats(&jsobj, "_allocationStats");
|
| + stats->PrintToJSONObject(*this, &allocation_stats);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void UnresolvedClass::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + // The index in the canonical_type_arguments table cannot be used as part of
|
| + // the object id (as in typearguments/id), because the indices are not
|
| + // preserved when the table grows and the entries get rehashed. Use the ring.
|
| + Isolate* isolate = Isolate::Current();
|
| + ObjectStore* object_store = isolate->object_store();
|
| + const Array& table = Array::Handle(object_store->canonical_type_arguments());
|
| + ASSERT(table.Length() > 0);
|
| + AddCommonObjectProperties(&jsobj, "TypeArguments", ref);
|
| + jsobj.AddServiceId(*this);
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + {
|
| + JSONArray jsarr(&jsobj, "types");
|
| + AbstractType& type_arg = AbstractType::Handle();
|
| + for (intptr_t i = 0; i < Length(); i++) {
|
| + type_arg = TypeAt(i);
|
| + jsarr.AddValue(type_arg);
|
| + }
|
| + }
|
| + if (!IsInstantiated()) {
|
| + JSONArray jsarr(&jsobj, "_instantiations");
|
| + Array& prior_instantiations = Array::Handle(instantiations());
|
| + ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
|
| + TypeArguments& type_args = TypeArguments::Handle();
|
| + intptr_t i = 0;
|
| + while (true) {
|
| + if (prior_instantiations.At(i) == Smi::New(StubCode::kNoInstantiator)) {
|
| + break;
|
| + }
|
| + JSONObject instantiation(&jsarr);
|
| + type_args ^= prior_instantiations.At(i);
|
| + instantiation.AddProperty("instantiator", type_args, true);
|
| + type_args ^= prior_instantiations.At(i + 1);
|
| + instantiation.AddProperty("instantiated", type_args, true);
|
| + i += 2;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void PatchClass::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +static void AddFunctionServiceId(const JSONObject& jsobj,
|
| + const Function& f,
|
| + const Class& cls) {
|
| + // Special kinds of functions use indices in their respective lists.
|
| + intptr_t id = -1;
|
| + const char* selector = NULL;
|
| + if (f.IsNonImplicitClosureFunction()) {
|
| + id = Isolate::Current()->FindClosureIndex(f);
|
| + selector = "closures";
|
| + } else if (f.IsImplicitClosureFunction()) {
|
| + id = cls.FindImplicitClosureFunctionIndex(f);
|
| + selector = "implicit_closures";
|
| + } else if (f.IsNoSuchMethodDispatcher() || f.IsInvokeFieldDispatcher()) {
|
| + id = cls.FindInvocationDispatcherFunctionIndex(f);
|
| + selector = "dispatchers";
|
| + }
|
| + if (id != -1) {
|
| + ASSERT(selector != NULL);
|
| + jsobj.AddFixedServiceId("classes/%" Pd "/%s/%" Pd "",
|
| + cls.id(), selector, id);
|
| + return;
|
| + }
|
| + // Regular functions known to their owner use their name (percent-encoded).
|
| + String& name = String::Handle(f.name());
|
| + if (cls.LookupFunction(name) == f.raw()) {
|
| + name = String::EncodeIRI(name);
|
| + jsobj.AddFixedServiceId("classes/%" Pd "/functions/%s",
|
| + cls.id(), name.ToCString());
|
| + return;
|
| + }
|
| + // Oddball functions (not known to their owner) fall back to use the object
|
| + // id ring. Current known examples are signature functions of closures
|
| + // and stubs like 'megamorphic_miss'.
|
| + jsobj.AddServiceId(f);
|
| +}
|
| +
|
| +
|
| +void Function::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Class& cls = Class::Handle(Owner());
|
| + ASSERT(!cls.IsNull());
|
| + Error& err = Error::Handle();
|
| + err ^= cls.EnsureIsFinalized(Thread::Current());
|
| + ASSERT(err.IsNull());
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Function", ref);
|
| + AddFunctionServiceId(jsobj, *this, cls);
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + const Function& parent = Function::Handle(parent_function());
|
| + if (!parent.IsNull()) {
|
| + jsobj.AddProperty("owner", parent);
|
| + } else if (cls.IsTopLevel()) {
|
| + const Library& library = Library::Handle(cls.library());
|
| + jsobj.AddProperty("owner", library);
|
| + } else {
|
| + jsobj.AddProperty("owner", cls);
|
| + }
|
| +
|
| + const char* kind_string = Function::KindToCString(kind());
|
| + jsobj.AddProperty("_kind", kind_string);
|
| + jsobj.AddProperty("static", is_static());
|
| + jsobj.AddProperty("const", is_const());
|
| + jsobj.AddProperty("_intrinsic", is_intrinsic());
|
| + jsobj.AddProperty("_native", is_native());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + Code& code = Code::Handle(CurrentCode());
|
| + if (!code.IsNull()) {
|
| + jsobj.AddProperty("code", code);
|
| + }
|
| + Array& ics = Array::Handle(ic_data_array());
|
| + if (!ics.IsNull()) {
|
| + jsobj.AddProperty("_icDataArray", ics);
|
| + }
|
| + jsobj.AddProperty("_optimizable", is_optimizable());
|
| + jsobj.AddProperty("_inlinable", is_inlinable());
|
| + jsobj.AddProperty("_recognized", IsRecognized());
|
| + code = unoptimized_code();
|
| + if (!code.IsNull()) {
|
| + jsobj.AddProperty("_unoptimizedCode", code);
|
| + }
|
| + jsobj.AddProperty("_usageCounter", usage_counter());
|
| + jsobj.AddProperty("_optimizedCallSiteCount", optimized_call_site_count());
|
| + jsobj.AddProperty("_deoptimizations",
|
| + static_cast<intptr_t>(deoptimization_counter()));
|
| + if ((kind() == RawFunction::kImplicitGetter) ||
|
| + (kind() == RawFunction::kImplicitSetter) ||
|
| + (kind() == RawFunction::kImplicitStaticFinalGetter)) {
|
| + const Field& field = Field::Handle(LookupImplicitGetterSetterField());
|
| + if (!field.IsNull()) {
|
| + jsobj.AddProperty("_field", field);
|
| + }
|
| + }
|
| +
|
| + const Script& script = Script::Handle(this->script());
|
| + if (!script.IsNull()) {
|
| + jsobj.AddLocation(script, token_pos(), end_token_pos());
|
| + }
|
| +}
|
| +
|
| +
|
| +void RedirectionData::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Field::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + Class& cls = Class::Handle(owner());
|
| + String& field_name = String::Handle(name());
|
| + field_name = String::EncodeIRI(field_name);
|
| + AddCommonObjectProperties(&jsobj, "Field", ref);
|
| + jsobj.AddFixedServiceId("classes/%" Pd "/fields/%s",
|
| + cls.id(), field_name.ToCString());
|
| +
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (cls.IsTopLevel()) {
|
| + const Library& library = Library::Handle(cls.library());
|
| + jsobj.AddProperty("owner", library);
|
| + } else {
|
| + jsobj.AddProperty("owner", cls);
|
| + }
|
| +
|
| + AbstractType& declared_type = AbstractType::Handle(type());
|
| + jsobj.AddProperty("declaredType", declared_type);
|
| + jsobj.AddProperty("static", is_static());
|
| + jsobj.AddProperty("final", is_final());
|
| + jsobj.AddProperty("const", is_const());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + if (is_static()) {
|
| + const Instance& valueObj = Instance::Handle(StaticValue());
|
| + jsobj.AddProperty("staticValue", valueObj);
|
| + }
|
| +
|
| + jsobj.AddProperty("_guardNullable", is_nullable());
|
| + if (guarded_cid() == kIllegalCid) {
|
| + jsobj.AddProperty("_guardClass", "unknown");
|
| + } else if (guarded_cid() == kDynamicCid) {
|
| + jsobj.AddProperty("_guardClass", "dynamic");
|
| + } else {
|
| + ClassTable* table = Isolate::Current()->class_table();
|
| + ASSERT(table->IsValidIndex(guarded_cid()));
|
| + cls ^= table->At(guarded_cid());
|
| + jsobj.AddProperty("_guardClass", cls);
|
| + }
|
| + if (guarded_list_length() == kUnknownFixedLength) {
|
| + jsobj.AddProperty("_guardLength", "unknown");
|
| + } else if (guarded_list_length() == kNoFixedLength) {
|
| + jsobj.AddProperty("_guardLength", "variable");
|
| + } else {
|
| + jsobj.AddProperty("_guardLength", guarded_list_length());
|
| + }
|
| + const Class& origin_cls = Class::Handle(origin());
|
| + const Script& script = Script::Handle(origin_cls.script());
|
| + if (!script.IsNull()) {
|
| + jsobj.AddLocation(script, token_pos());
|
| + }
|
| +}
|
| +
|
| +
|
| +void LiteralToken::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void TokenStream::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + // TODO(johnmccutchan): Generate a stable id. TokenStreams hang off
|
| + // a Script object but do not have a back reference to generate a stable id.
|
| + jsobj.AddServiceId(*this);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + const String& private_key = String::Handle(PrivateKey());
|
| + jsobj.AddProperty("privateKey", private_key);
|
| + // TODO(johnmccutchan): Add support for printing LiteralTokens and add
|
| + // them to members array.
|
| + JSONArray members(&jsobj, "members");
|
| +}
|
| +
|
| +
|
| +// See also Dart_ScriptGetTokenInfo.
|
| +void Script::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Script", ref);
|
| + const String& uri = String::Handle(url());
|
| + ASSERT(!uri.IsNull());
|
| + const String& encoded_uri = String::Handle(String::EncodeIRI(uri));
|
| + ASSERT(!encoded_uri.IsNull());
|
| + const Library& lib = Library::Handle(FindLibrary());
|
| + if (kind() == RawScript::kEvaluateTag) {
|
| + jsobj.AddServiceId(*this);
|
| + } else {
|
| + ASSERT(!lib.IsNull());
|
| + jsobj.AddFixedServiceId("libraries/%" Pd "/scripts/%s",
|
| + lib.index(), encoded_uri.ToCString());
|
| + }
|
| + jsobj.AddPropertyStr("uri", uri);
|
| + jsobj.AddProperty("_kind", GetKindAsCString());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + if (!lib.IsNull()) {
|
| + jsobj.AddProperty("library", lib);
|
| + }
|
| + const String& source = String::Handle(Source());
|
| + jsobj.AddProperty("lineOffset", line_offset());
|
| + jsobj.AddProperty("columnOffset", col_offset());
|
| + if (!source.IsNull()) {
|
| + jsobj.AddPropertyStr("source", source);
|
| + }
|
| +
|
| + // Print the line number table
|
| + if (!source.IsNull()) {
|
| + JSONArray tokenPosTable(&jsobj, "tokenPosTable");
|
| +
|
| + const GrowableObjectArray& lineNumberArray =
|
| + GrowableObjectArray::Handle(GenerateLineNumberArray());
|
| + Object& value = Object::Handle();
|
| + intptr_t pos = 0;
|
| +
|
| + // Skip leading null.
|
| + ASSERT(lineNumberArray.Length() > 0);
|
| + value = lineNumberArray.At(pos);
|
| + ASSERT(value.IsNull());
|
| + pos++;
|
| +
|
| + while (pos < lineNumberArray.Length()) {
|
| + JSONArray lineInfo(&tokenPosTable);
|
| + while (pos < lineNumberArray.Length()) {
|
| + value = lineNumberArray.At(pos);
|
| + pos++;
|
| + if (value.IsNull()) {
|
| + break;
|
| + }
|
| + const Smi& smi = Smi::Cast(value);
|
| + lineInfo.AddValue(smi.Value());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void Library::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + intptr_t id = index();
|
| + ASSERT(id >= 0);
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Library", ref);
|
| + jsobj.AddFixedServiceId("libraries/%" Pd "", id);
|
| + const String& vm_name = String::Handle(name());
|
| + const String& user_name =
|
| + String::Handle(String::IdentifierPrettyName(vm_name));
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + const String& library_url = String::Handle(url());
|
| + jsobj.AddPropertyStr("uri", library_url);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + jsobj.AddProperty("debuggable", IsDebuggable());
|
| + {
|
| + JSONArray jsarr(&jsobj, "classes");
|
| + ClassDictionaryIterator class_iter(*this);
|
| + Class& klass = Class::Handle();
|
| + while (class_iter.HasNext()) {
|
| + klass = class_iter.GetNextClass();
|
| + if (!klass.IsMixinApplication()) {
|
| + jsarr.AddValue(klass);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray jsarr(&jsobj, "dependencies");
|
| +
|
| + Array& ports = Array::Handle();
|
| + Namespace& ns = Namespace::Handle();
|
| + Library& target = Library::Handle();
|
| +
|
| + // Unprefixed imports.
|
| + ports = imports();
|
| + for (intptr_t i = 0; i < ports.Length(); i++) {
|
| + ns ^= ports.At(i);
|
| + if (ns.IsNull()) continue;
|
| +
|
| + JSONObject jsdep(&jsarr);
|
| + jsdep.AddProperty("isDeferred", false);
|
| + jsdep.AddProperty("isExport", false);
|
| + jsdep.AddProperty("isImport", true);
|
| + target = ns.library();
|
| + jsdep.AddProperty("target", target);
|
| + }
|
| +
|
| + // Exports.
|
| + ports = exports();
|
| + for (intptr_t i = 0; i < ports.Length(); i++) {
|
| + ns ^= ports.At(i);
|
| + if (ns.IsNull()) continue;
|
| +
|
| + JSONObject jsdep(&jsarr);
|
| + jsdep.AddProperty("isDeferred", false);
|
| + jsdep.AddProperty("isExport", true);
|
| + jsdep.AddProperty("isImport", false);
|
| + target = ns.library();
|
| + jsdep.AddProperty("target", target);
|
| + }
|
| +
|
| + // Prefixed imports.
|
| + DictionaryIterator entries(*this);
|
| + Object& entry = Object::Handle();
|
| + LibraryPrefix& prefix = LibraryPrefix::Handle();
|
| + String& prefixName = String::Handle();
|
| + while (entries.HasNext()) {
|
| + entry = entries.GetNext();
|
| + if (entry.IsLibraryPrefix()) {
|
| + prefix ^= entry.raw();
|
| + ports = prefix.imports();
|
| + for (intptr_t i = 0; i < ports.Length(); i++) {
|
| + ns ^= ports.At(i);
|
| + if (ns.IsNull()) continue;
|
| +
|
| + JSONObject jsdep(&jsarr);
|
| + jsdep.AddProperty("isDeferred", prefix.is_deferred_load());
|
| + jsdep.AddProperty("isExport", false);
|
| + jsdep.AddProperty("isImport", true);
|
| + prefixName = prefix.name();
|
| + ASSERT(!prefixName.IsNull());
|
| + jsdep.AddProperty("prefix", prefixName.ToCString());
|
| + target = ns.library();
|
| + jsdep.AddProperty("target", target);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray jsarr(&jsobj, "variables");
|
| + DictionaryIterator entries(*this);
|
| + Object& entry = Object::Handle();
|
| + while (entries.HasNext()) {
|
| + entry = entries.GetNext();
|
| + if (entry.IsField()) {
|
| + jsarr.AddValue(entry);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray jsarr(&jsobj, "functions");
|
| + DictionaryIterator entries(*this);
|
| + Object& entry = Object::Handle();
|
| + while (entries.HasNext()) {
|
| + entry = entries.GetNext();
|
| + if (entry.IsFunction()) {
|
| + const Function& func = Function::Cast(entry);
|
| + if (func.kind() == RawFunction::kRegularFunction ||
|
| + func.kind() == RawFunction::kGetterFunction ||
|
| + func.kind() == RawFunction::kSetterFunction) {
|
| + jsarr.AddValue(func);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + JSONArray jsarr(&jsobj, "scripts");
|
| + Array& scripts = Array::Handle(LoadedScripts());
|
| + Script& script = Script::Handle();
|
| + for (intptr_t i = 0; i < scripts.Length(); i++) {
|
| + script ^= scripts.At(i);
|
| + jsarr.AddValue(script);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void LibraryPrefix::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Namespace::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + jsobj.AddServiceId(*this);
|
| + if (ref) {
|
| + return;
|
| + }
|
| +}
|
| +
|
| +
|
| +void ObjectPool::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + {
|
| + JSONArray jsarr(&jsobj, "_entries");
|
| + uword imm;
|
| + Object& obj = Object::Handle();
|
| + for (intptr_t i = 0; i < Length(); i++) {
|
| + JSONObject jsentry(stream);
|
| + jsentry.AddProperty("offset", OffsetFromIndex(i));
|
| + switch (InfoAt(i)) {
|
| + case ObjectPool::kTaggedObject:
|
| + obj = ObjectAt(i);
|
| + jsentry.AddProperty("kind", "Object");
|
| + jsentry.AddProperty("value", obj);
|
| + break;
|
| + case ObjectPool::kImmediate:
|
| + imm = RawValueAt(i);
|
| + jsentry.AddProperty("kind", "Immediate");
|
| + jsentry.AddProperty64("value", imm);
|
| + break;
|
| + case ObjectPool::kNativeEntry:
|
| + imm = RawValueAt(i);
|
| + jsentry.AddProperty("kind", "NativeEntry");
|
| + jsentry.AddProperty64("value", imm);
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void PcDescriptors::PrintToJSONObject(JSONObject* jsobj, bool ref) const {
|
| + AddCommonObjectProperties(jsobj, "Object", ref);
|
| + // TODO(johnmccutchan): Generate a stable id. PcDescriptors hang off a Code
|
| + // object but do not have a back reference to generate an ID.
|
| + jsobj->AddServiceId(*this);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + JSONArray members(jsobj, "members");
|
| + Iterator iter(*this, RawPcDescriptors::kAnyKind);
|
| + while (iter.MoveNext()) {
|
| + JSONObject descriptor(&members);
|
| + descriptor.AddPropertyF("pcOffset", "%" Px "", iter.PcOffset());
|
| + descriptor.AddProperty("kind", KindAsStr(iter.Kind()));
|
| + descriptor.AddProperty("deoptId", iter.DeoptId());
|
| + // TODO(turnidge): Use AddLocation instead.
|
| + descriptor.AddProperty("tokenPos", iter.TokenPos());
|
| + descriptor.AddProperty("tryIndex", iter.TryIndex());
|
| + }
|
| +}
|
| +
|
| +
|
| +void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintToJSONObject(&jsobj, ref);
|
| +}
|
| +
|
| +
|
| +void CodeSourceMap::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Stackmap::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void LocalVarDescriptors::PrintJSONImpl(JSONStream* stream,
|
| + bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + // TODO(johnmccutchan): Generate a stable id. LocalVarDescriptors hang off
|
| + // a Code object but do not have a back reference to generate an ID.
|
| + jsobj.AddServiceId(*this);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + JSONArray members(&jsobj, "members");
|
| + String& var_name = String::Handle();
|
| + for (intptr_t i = 0; i < Length(); i++) {
|
| + RawLocalVarDescriptors::VarInfo info;
|
| + var_name = GetName(i);
|
| + GetInfo(i, &info);
|
| + JSONObject var(&members);
|
| + var.AddProperty("name", var_name.ToCString());
|
| + var.AddProperty("index", static_cast<intptr_t>(info.index()));
|
| + var.AddProperty("beginPos", info.begin_pos);
|
| + var.AddProperty("endPos", info.end_pos);
|
| + var.AddProperty("scopeId", static_cast<intptr_t>(info.scope_id));
|
| + var.AddProperty("kind", KindToCString(info.kind()));
|
| + }
|
| +}
|
| +
|
| +
|
| +void ExceptionHandlers::PrintJSONImpl(JSONStream* stream,
|
| + bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void ICData::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("_owner", Object::Handle(Owner()));
|
| + jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + jsobj.AddProperty("_argumentsDescriptor",
|
| + Object::Handle(arguments_descriptor()));
|
| + jsobj.AddProperty("_entries", Object::Handle(ic_data()));
|
| +}
|
| +
|
| +
|
| +void ICData::PrintToJSONArray(const JSONArray& jsarray,
|
| + TokenPosition token_pos,
|
| + bool is_static_call) const {
|
| + Isolate* isolate = Isolate::Current();
|
| + Class& cls = Class::Handle();
|
| + Function& func = Function::Handle();
|
| +
|
| + JSONObject jsobj(&jsarray);
|
| + jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
|
| + jsobj.AddProperty("tokenPos", token_pos);
|
| + // TODO(rmacnak): Figure out how to stringify DeoptReasons().
|
| + // jsobj.AddProperty("deoptReasons", ...);
|
| +
|
| + JSONArray cache_entries(&jsobj, "cacheEntries");
|
| + for (intptr_t i = 0; i < NumberOfChecks(); i++) {
|
| + func = GetTargetAt(i);
|
| + if (is_static_call) {
|
| + cls ^= func.Owner();
|
| + } else {
|
| + intptr_t cid = GetReceiverClassIdAt(i);
|
| + cls ^= isolate->class_table()->At(cid);
|
| + }
|
| + intptr_t count = GetCountAt(i);
|
| + JSONObject cache_entry(&cache_entries);
|
| + if (cls.IsTopLevel()) {
|
| + cache_entry.AddProperty("receiverContainer",
|
| + Library::Handle(cls.library()));
|
| + } else {
|
| + cache_entry.AddProperty("receiverContainer", cls);
|
| + }
|
| + cache_entry.AddProperty("count", count);
|
| + cache_entry.AddProperty("target", func);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ICData::PrintToJSONArrayNew(const JSONArray& jsarray,
|
| + TokenPosition token_pos,
|
| + bool is_static_call) const {
|
| + Isolate* isolate = Isolate::Current();
|
| + Class& cls = Class::Handle();
|
| + Function& func = Function::Handle();
|
| +
|
| + JSONObject jsobj(&jsarray);
|
| + jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
|
| + jsobj.AddProperty("tokenPos", token_pos.value());
|
| + // TODO(rmacnak): Figure out how to stringify DeoptReasons().
|
| + // jsobj.AddProperty("deoptReasons", ...);
|
| +
|
| + JSONArray cache_entries(&jsobj, "cacheEntries");
|
| + for (intptr_t i = 0; i < NumberOfChecks(); i++) {
|
| + JSONObject cache_entry(&cache_entries);
|
| + func = GetTargetAt(i);
|
| + intptr_t count = GetCountAt(i);
|
| + if (!is_static_call) {
|
| + intptr_t cid = GetReceiverClassIdAt(i);
|
| + cls ^= isolate->class_table()->At(cid);
|
| + cache_entry.AddProperty("receiver", cls);
|
| + }
|
| + cache_entry.AddProperty("target", func);
|
| + cache_entry.AddProperty("count", count);
|
| + }
|
| +}
|
| +
|
| +
|
| +void Code::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Code", ref);
|
| + jsobj.AddFixedServiceId("code/%" Px64"-%" Px "",
|
| + compile_timestamp(),
|
| + EntryPoint());
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + const bool is_stub = IsStubCode() || IsAllocationStubCode();
|
| + if (is_stub) {
|
| + jsobj.AddProperty("kind", "Stub");
|
| + } else {
|
| + jsobj.AddProperty("kind", "Dart");
|
| + }
|
| + jsobj.AddProperty("_optimized", is_optimized());
|
| + const Object& obj = Object::Handle(owner());
|
| + if (obj.IsFunction()) {
|
| + const Function& func = Function::Cast(obj);
|
| + jsobj.AddProperty("_intrinsic", func.is_intrinsic());
|
| + jsobj.AddProperty("_native", func.is_native());
|
| + } else {
|
| + jsobj.AddProperty("_intrinsic", false);
|
| + jsobj.AddProperty("_native", false);
|
| + }
|
| + if (ref) {
|
| + return;
|
| + }
|
| + if (obj.IsFunction()) {
|
| + jsobj.AddProperty("function", obj);
|
| + } else {
|
| + // Generate a fake function reference.
|
| + JSONObject func(&jsobj, "function");
|
| + func.AddProperty("type", "@Function");
|
| + func.AddProperty("_kind", "Stub");
|
| + func.AddProperty("name", user_name.ToCString());
|
| + AddNameProperties(&func, user_name, vm_name);
|
| + }
|
| + jsobj.AddPropertyF("_startAddress", "%" Px "", EntryPoint());
|
| + jsobj.AddPropertyF("_endAddress", "%" Px "", EntryPoint() + Size());
|
| + jsobj.AddProperty("_alive", is_alive());
|
| + const ObjectPool& object_pool = ObjectPool::Handle(GetObjectPool());
|
| + jsobj.AddProperty("_objectPool", object_pool);
|
| + {
|
| + JSONArray jsarr(&jsobj, "_disassembly");
|
| + if (is_alive()) {
|
| + // Only disassemble alive code objects.
|
| + DisassembleToJSONStream formatter(jsarr);
|
| + Disassemble(&formatter);
|
| + }
|
| + }
|
| + const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
|
| + if (!descriptors.IsNull()) {
|
| + JSONObject desc(&jsobj, "_descriptors");
|
| + descriptors.PrintToJSONObject(&desc, false);
|
| + }
|
| + const Array& inlined_function_table = Array::Handle(GetInlinedIdToFunction());
|
| + if (!inlined_function_table.IsNull() &&
|
| + (inlined_function_table.Length() > 0)) {
|
| + JSONArray inlined_functions(&jsobj, "_inlinedFunctions");
|
| + Function& function = Function::Handle();
|
| + for (intptr_t i = 0; i < inlined_function_table.Length(); i++) {
|
| + function ^= inlined_function_table.At(i);
|
| + ASSERT(!function.IsNull());
|
| + inlined_functions.AddValue(function);
|
| + }
|
| + }
|
| + const Array& intervals = Array::Handle(GetInlinedIntervals());
|
| + if (!intervals.IsNull() && (intervals.Length() > 0)) {
|
| + Smi& start = Smi::Handle();
|
| + Smi& end = Smi::Handle();
|
| + Smi& temp_smi = Smi::Handle();
|
| + JSONArray inline_intervals(&jsobj, "_inlinedIntervals");
|
| + for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries;
|
| + i += Code::kInlIntNumEntries) {
|
| + start ^= intervals.At(i + Code::kInlIntStart);
|
| + if (start.IsNull()) {
|
| + continue;
|
| + }
|
| + end ^= intervals.At(i + Code::kInlIntNumEntries + Code::kInlIntStart);
|
| +
|
| + // Format: [start, end, inline functions...]
|
| + JSONArray inline_interval(&inline_intervals);
|
| + inline_interval.AddValue(start.Value());
|
| + inline_interval.AddValue(end.Value());
|
| +
|
| + temp_smi ^= intervals.At(i + Code::kInlIntInliningId);
|
| + intptr_t inlining_id = temp_smi.Value();
|
| + ASSERT(inlining_id >= 0);
|
| + intptr_t caller_id = GetCallerId(inlining_id);
|
| + while (inlining_id >= 0) {
|
| + inline_interval.AddValue(inlining_id);
|
| + inlining_id = caller_id;
|
| + caller_id = GetCallerId(inlining_id);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void Context::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + // TODO(turnidge): Should the user level type for Context be Context
|
| + // or Object?
|
| + AddCommonObjectProperties(&jsobj, "Context", ref);
|
| + jsobj.AddServiceId(*this);
|
| +
|
| + jsobj.AddProperty("length", num_variables());
|
| +
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + const Context& parent_context = Context::Handle(parent());
|
| + if (!parent_context.IsNull()) {
|
| + jsobj.AddProperty("parent", parent_context);
|
| + }
|
| +
|
| + JSONArray jsarr(&jsobj, "variables");
|
| + Object& var = Object::Handle();
|
| + for (intptr_t index = 0; index < num_variables(); index++) {
|
| + var = At(index);
|
| + JSONObject jselement(&jsarr);
|
| + jselement.AddProperty("value", var);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ContextScope::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void MegamorphicCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Object", ref);
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + jsobj.AddProperty("_buckets", Object::Handle(buckets()));
|
| + jsobj.AddProperty("_mask", mask());
|
| + jsobj.AddProperty("_argumentsDescriptor",
|
| + Object::Handle(arguments_descriptor()));
|
| +}
|
| +
|
| +
|
| +void SubtypeTestCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Error::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| +void ApiError::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Error", ref);
|
| + jsobj.AddProperty("kind", "InternalError");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("message", ToErrorCString());
|
| +}
|
| +
|
| +
|
| +void LanguageError::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Error", ref);
|
| + jsobj.AddProperty("kind", "LanguageError");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("message", ToErrorCString());
|
| +}
|
| +
|
| +
|
| +void UnhandledException::PrintJSONImpl(JSONStream* stream,
|
| + bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Error", ref);
|
| + jsobj.AddProperty("kind", "UnhandledException");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("message", ToErrorCString());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + Instance& instance = Instance::Handle();
|
| + instance = exception();
|
| + jsobj.AddProperty("exception", instance);
|
| + instance = stacktrace();
|
| + jsobj.AddProperty("stacktrace", instance);
|
| +}
|
| +
|
| +
|
| +void UnwindError::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + AddCommonObjectProperties(&jsobj, "Error", ref);
|
| + jsobj.AddProperty("kind", "TerminationError");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("message", ToErrorCString());
|
| + jsobj.AddProperty("_is_user_initiated", is_user_initiated());
|
| + jsobj.AddProperty("_is_vm_restart", is_vm_restart());
|
| +}
|
| +
|
| +
|
| +void Instance::PrintSharedInstanceJSON(JSONObject* jsobj,
|
| + bool ref) const {
|
| + AddCommonObjectProperties(jsobj, "Instance", ref);
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + // Walk the superclass chain, adding all instance fields.
|
| + Class& cls = Class::Handle(this->clazz());
|
| + {
|
| + Instance& fieldValue = Instance::Handle();
|
| + JSONArray jsarr(jsobj, "fields");
|
| + while (!cls.IsNull()) {
|
| + const Array& field_array = Array::Handle(cls.fields());
|
| + Field& field = Field::Handle();
|
| + if (!field_array.IsNull()) {
|
| + for (intptr_t i = 0; i < field_array.Length(); i++) {
|
| + field ^= field_array.At(i);
|
| + if (!field.is_static()) {
|
| + fieldValue ^= GetField(field);
|
| + JSONObject jsfield(&jsarr);
|
| + jsfield.AddProperty("type", "BoundField");
|
| + jsfield.AddProperty("decl", field);
|
| + jsfield.AddProperty("value", fieldValue);
|
| + }
|
| + }
|
| + }
|
| + cls = cls.SuperClass();
|
| + }
|
| + }
|
| +
|
| + if (NumNativeFields() > 0) {
|
| + JSONArray jsarr(jsobj, "_nativeFields");
|
| + for (intptr_t i = 0; i < NumNativeFields(); i++) {
|
| + intptr_t value = GetNativeField(i);
|
| + JSONObject jsfield(&jsarr);
|
| + jsfield.AddProperty("index", i);
|
| + jsfield.AddProperty("value", value);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void Instance::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| +
|
| + // Handle certain special instance values.
|
| + if (raw() == Object::sentinel().raw()) {
|
| + jsobj.AddProperty("type", "Sentinel");
|
| + jsobj.AddProperty("kind", "NotInitialized");
|
| + jsobj.AddProperty("valueAsString", "<not initialized>");
|
| + return;
|
| + } else if (raw() == Object::transition_sentinel().raw()) {
|
| + jsobj.AddProperty("type", "Sentinel");
|
| + jsobj.AddProperty("kind", "BeingInitialized");
|
| + jsobj.AddProperty("valueAsString", "<being initialized>");
|
| + return;
|
| + }
|
| +
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + if (IsClosure()) {
|
| + jsobj.AddProperty("kind", "Closure");
|
| + } else {
|
| + jsobj.AddProperty("kind", "PlainInstance");
|
| + }
|
| + jsobj.AddServiceId(*this);
|
| + if (IsClosure()) {
|
| + jsobj.AddProperty("closureFunction",
|
| + Function::Handle(Closure::Cast(*this).function()));
|
| + jsobj.AddProperty("closureContext",
|
| + Context::Handle(Closure::Cast(*this).context()));
|
| + }
|
| + if (ref) {
|
| + return;
|
| + }
|
| + if (IsClosure()) {
|
| + Debugger* debugger = Isolate::Current()->debugger();
|
| + Breakpoint* bpt = debugger->BreakpointAtActivation(*this);
|
| + if (bpt != NULL) {
|
| + jsobj.AddProperty("_activationBreakpoint", bpt);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void AbstractType::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| +void Type::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Type");
|
| + if (IsCanonical()) {
|
| + const Class& type_cls = Class::Handle(type_class());
|
| + intptr_t id = type_cls.FindCanonicalTypeIndex(*this);
|
| + ASSERT(id >= 0);
|
| + intptr_t cid = type_cls.id();
|
| + jsobj.AddFixedServiceId("classes/%" Pd "/types/%" Pd "", cid, id);
|
| + jsobj.AddProperty("typeClass", type_cls);
|
| + } else {
|
| + jsobj.AddServiceId(*this);
|
| + }
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
|
| + if (!typeArgs.IsNull()) {
|
| + jsobj.AddProperty("typeArguments", typeArgs);
|
| + }
|
| +}
|
| +
|
| +
|
| +void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "FunctionType");
|
| + if (IsCanonical()) {
|
| + const Class& scope_cls = Class::Handle(scope_class());
|
| + intptr_t id = scope_cls.FindCanonicalTypeIndex(*this);
|
| + ASSERT(id >= 0);
|
| + intptr_t cid = scope_cls.id();
|
| + jsobj.AddFixedServiceId("classes/%" Pd "/types/%" Pd "", cid, id);
|
| + jsobj.AddProperty("scopeClass", scope_cls);
|
| + } else {
|
| + jsobj.AddServiceId(*this);
|
| + }
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
|
| + if (!typeArgs.IsNull()) {
|
| + jsobj.AddProperty("typeArguments", typeArgs);
|
| + }
|
| +}
|
| +
|
| +
|
| +void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "TypeRef");
|
| + jsobj.AddServiceId(*this);
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + jsobj.AddProperty("targetType", AbstractType::Handle(type()));
|
| +}
|
| +
|
| +
|
| +void TypeParameter::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "TypeParameter");
|
| + jsobj.AddServiceId(*this);
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + const Class& param_cls = Class::Handle(parameterized_class());
|
| + jsobj.AddProperty("parameterizedClass", param_cls);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + jsobj.AddProperty("parameterIndex", index());
|
| + const AbstractType& upper_bound = AbstractType::Handle(bound());
|
| + jsobj.AddProperty("bound", upper_bound);
|
| +}
|
| +
|
| +
|
| +void BoundedType::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "BoundedType");
|
| + jsobj.AddServiceId(*this);
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + jsobj.AddProperty("targetType", AbstractType::Handle(type()));
|
| + jsobj.AddProperty("bound", AbstractType::Handle(bound()));
|
| +}
|
| +
|
| +
|
| +void MixinAppType::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| +void Number::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| +void Integer::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Int");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("valueAsString", ToCString());
|
| +}
|
| +
|
| +
|
| +void Smi::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Int");
|
| + jsobj.AddFixedServiceId("objects/int-%" Pd "", Value());
|
| + jsobj.AddPropertyF("valueAsString", "%" Pd "", Value());
|
| +}
|
| +
|
| +
|
| +void Mint::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Integer::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Double::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Double");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("valueAsString", ToCString());
|
| +}
|
| +
|
| +
|
| +void Bigint::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Integer::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void String::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + if (raw() == Symbols::OptimizedOut().raw()) {
|
| + // TODO(turnidge): This is a hack. The user could have this
|
| + // special string in their program. Fixing this involves updating
|
| + // the debugging api a bit.
|
| + jsobj.AddProperty("type", "Sentinel");
|
| + jsobj.AddProperty("kind", "OptimizedOut");
|
| + jsobj.AddProperty("valueAsString", "<optimized out>");
|
| + return;
|
| + }
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "String");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + // String refs always truncate to a fixed count;
|
| + const intptr_t kFixedCount = 128;
|
| + if (jsobj.AddPropertyStr("valueAsString", *this, 0, kFixedCount)) {
|
| + jsobj.AddProperty("count", kFixedCount);
|
| + jsobj.AddProperty("valueAsStringIsTruncated", true);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + intptr_t offset;
|
| + intptr_t count;
|
| + stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
| + if (offset > 0) {
|
| + jsobj.AddProperty("offset", offset);
|
| + }
|
| + if (count < Length()) {
|
| + jsobj.AddProperty("count", count);
|
| + }
|
| + jsobj.AddPropertyStr("valueAsString", *this, offset, count);
|
| +}
|
| +
|
| +
|
| +void Bool::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + const char* str = ToCString();
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Bool");
|
| + jsobj.AddFixedServiceId("objects/bool-%s", str);
|
| + jsobj.AddPropertyF("valueAsString", "%s", str);
|
| +}
|
| +
|
| +
|
| +void Array::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "List");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + intptr_t offset;
|
| + intptr_t count;
|
| + stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
| + if (offset > 0) {
|
| + jsobj.AddProperty("offset", offset);
|
| + }
|
| + if (count < Length()) {
|
| + jsobj.AddProperty("count", count);
|
| + }
|
| + intptr_t limit = offset + count;
|
| + ASSERT(limit <= Length());
|
| + {
|
| + JSONArray jsarr(&jsobj, "elements");
|
| + Object& element = Object::Handle();
|
| + for (intptr_t index = offset; index < limit; index++) {
|
| + element = At(index);
|
| + jsarr.AddValue(element);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void GrowableObjectArray::PrintJSONImpl(JSONStream* stream,
|
| + bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "List");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + intptr_t offset;
|
| + intptr_t count;
|
| + stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
| + if (offset > 0) {
|
| + jsobj.AddProperty("offset", offset);
|
| + }
|
| + if (count < Length()) {
|
| + jsobj.AddProperty("count", count);
|
| + }
|
| + intptr_t limit = offset + count;
|
| + ASSERT(limit <= Length());
|
| + {
|
| + JSONArray jsarr(&jsobj, "elements");
|
| + Object& element = Object::Handle();
|
| + for (intptr_t index = offset; index < limit; index++) {
|
| + element = At(index);
|
| + jsarr.AddValue(element);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void LinkedHashMap::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Map");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + intptr_t offset;
|
| + intptr_t count;
|
| + stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
| + if (offset > 0) {
|
| + jsobj.AddProperty("offset", offset);
|
| + }
|
| + if (count < Length()) {
|
| + jsobj.AddProperty("count", count);
|
| + }
|
| + intptr_t limit = offset + count;
|
| + ASSERT(limit <= Length());
|
| + {
|
| + JSONArray jsarr(&jsobj, "associations");
|
| + Object& object = Object::Handle();
|
| + LinkedHashMap::Iterator iterator(*this);
|
| + int i = 0;
|
| + while (iterator.MoveNext() && i < limit) {
|
| + if (i >= offset) {
|
| + JSONObject jsassoc(&jsarr);
|
| + object = iterator.CurrentKey();
|
| + jsassoc.AddProperty("key", object);
|
| + object = iterator.CurrentValue();
|
| + jsassoc.AddProperty("value", object);
|
| + }
|
| + i++;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void Float32x4::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Float32x4");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("valueAsString", ToCString());
|
| +}
|
| +
|
| +
|
| +void Int32x4::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Int32x4");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("valueAsString", ToCString());
|
| +}
|
| +
|
| +
|
| +void Float64x2::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "Float64x2");
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("valueAsString", ToCString());
|
| +}
|
| +
|
| +
|
| +void TypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + const Class& cls = Class::Handle(clazz());
|
| + const String& kind = String::Handle(cls.UserVisibleName());
|
| + jsobj.AddProperty("kind", kind.ToCString());
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + intptr_t offset;
|
| + intptr_t count;
|
| + stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
| + if (offset > 0) {
|
| + jsobj.AddProperty("offset", offset);
|
| + }
|
| + if (count < Length()) {
|
| + jsobj.AddProperty("count", count);
|
| + }
|
| + if (count == 0) {
|
| + jsobj.AddProperty("bytes", "");
|
| + } else {
|
| + NoSafepointScope no_safepoint;
|
| + jsobj.AddPropertyBase64("bytes",
|
| + reinterpret_cast<const uint8_t*>(
|
| + DataAddr(offset * ElementSizeInBytes())),
|
| + count * ElementSizeInBytes());
|
| + }
|
| +}
|
| +
|
| +
|
| +void ExternalTypedData::PrintJSONImpl(JSONStream* stream,
|
| + bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + const Class& cls = Class::Handle(clazz());
|
| + const String& kind = String::Handle(cls.UserVisibleName());
|
| + jsobj.AddProperty("kind", kind.ToCString());
|
| + jsobj.AddServiceId(*this);
|
| + jsobj.AddProperty("length", Length());
|
| + if (ref) {
|
| + return;
|
| + }
|
| + intptr_t offset;
|
| + intptr_t count;
|
| + stream->ComputeOffsetAndCount(Length(), &offset, &count);
|
| + if (offset > 0) {
|
| + jsobj.AddProperty("offset", offset);
|
| + }
|
| + if (count < Length()) {
|
| + jsobj.AddProperty("count", count);
|
| + }
|
| + if (count == 0) {
|
| + jsobj.AddProperty("bytes", "");
|
| + } else {
|
| + NoSafepointScope no_safepoint;
|
| + jsobj.AddPropertyBase64("bytes",
|
| + reinterpret_cast<const uint8_t*>(
|
| + DataAddr(offset * ElementSizeInBytes())),
|
| + count * ElementSizeInBytes());
|
| + }
|
| +}
|
| +
|
| +
|
| +void Capability::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Instance::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void ReceivePort::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Instance::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void SendPort::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Instance::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void ClosureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Object::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Instance::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +void Stacktrace::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "StackTrace");
|
| + jsobj.AddServiceId(*this);
|
| + intptr_t idx = 0;
|
| + jsobj.AddProperty("valueAsString", ToCStringInternal(&idx));
|
| +}
|
| +
|
| +
|
| +void JSRegExp::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "RegExp");
|
| + jsobj.AddServiceId(*this);
|
| +
|
| + jsobj.AddProperty("pattern", String::Handle(pattern()));
|
| +
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + jsobj.AddProperty("isCaseSensitive", !is_ignore_case());
|
| + jsobj.AddProperty("isMultiLine", is_multi_line());
|
| +
|
| + Function& func = Function::Handle();
|
| + func = function(kOneByteStringCid);
|
| + jsobj.AddProperty("_oneByteFunction", func);
|
| + func = function(kTwoByteStringCid);
|
| + jsobj.AddProperty("_twoByteFunction", func);
|
| + func = function(kExternalOneByteStringCid);
|
| + jsobj.AddProperty("_externalOneByteFunction", func);
|
| + func = function(kExternalTwoByteStringCid);
|
| + jsobj.AddProperty("_externalTwoByteFunction", func);
|
| +}
|
| +
|
| +
|
| +void WeakProperty::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "WeakProperty");
|
| + jsobj.AddServiceId(*this);
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + const Object& key_handle = Object::Handle(key());
|
| + jsobj.AddProperty("propertyKey", key_handle);
|
| + const Object& value_handle = Object::Handle(value());
|
| + jsobj.AddProperty("propertyValue", value_handle);
|
| +}
|
| +
|
| +
|
| +void MirrorReference::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "MirrorReference");
|
| + jsobj.AddServiceId(*this);
|
| +
|
| + if (ref) {
|
| + return;
|
| + }
|
| +
|
| + const Object& referent_handle = Object::Handle(referent());
|
| + jsobj.AddProperty("mirrorReferent", referent_handle);
|
| +}
|
| +
|
| +void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Instance::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +#endif
|
| +
|
| +} // namespace dart
|
|
|