Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Unified Diff: runtime/vm/object_service.cc

Issue 1660063002: Remove many features when building product mode (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object_id_ring_test.cc ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « runtime/vm/object_id_ring_test.cc ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698