1// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/compiler/assembler/disassembler.h"
6#include "vm/debugger.h"
7#include "vm/object.h"
8#include "vm/object_store.h"
9#include "vm/stub_code.h"
10#include "vm/symbols.h"
11#include "vm/type_table.h"
12
13namespace dart {
14
15#ifndef PRODUCT
16
17static void AddNameProperties(JSONObject* jsobj,
18 const char* name,
19 const char* vm_name) {
20 jsobj->AddProperty("name", name);
21 if (strcmp(name, vm_name) != 0) {
22 jsobj->AddProperty("_vmName", vm_name);
23 }
24}
25
26void Object::AddCommonObjectProperties(JSONObject* jsobj,
27 const char* protocol_type,
28 bool ref) const {
29 const char* vm_type = JSONType();
30 bool same_type = (strcmp(protocol_type, vm_type) == 0);
31 if (ref) {
32 jsobj->AddPropertyF("type", "@%s", protocol_type);
33 } else {
34 jsobj->AddProperty("type", protocol_type);
35 }
36 if (!same_type) {
37 jsobj->AddProperty("_vmType", vm_type);
38 }
39 if (!ref || IsInstance() || IsNull()) {
40 // TODO(turnidge): Provide the type arguments here too?
41 const Class& cls = Class::Handle(this->clazz());
42 jsobj->AddProperty("class", cls);
43 }
44 if (!ref) {
45 if (raw()->IsHeapObject()) {
46 jsobj->AddProperty("size", raw()->ptr()->HeapSize());
47 } else {
48 jsobj->AddProperty("size", (intptr_t)0);
49 }
50 }
51}
52
53void Object::PrintJSONImpl(JSONStream* stream, bool ref) const {
54 JSONObject jsobj(stream);
55 AddCommonObjectProperties(&jsobj, "Object", ref);
56 jsobj.AddServiceId(*this);
57 if (ref) {
58 return;
59 }
60}
61
62void Object::PrintJSON(JSONStream* stream, bool ref) const {
63 if (IsNull()) {
64 JSONObject jsobj(stream);
65 AddCommonObjectProperties(&jsobj, "Instance", ref);
66 jsobj.AddProperty("kind", "Null");
67 jsobj.AddFixedServiceId("objects/null");
68 jsobj.AddProperty("valueAsString", "null");
69 } else {
70 PrintJSONImpl(stream, ref);
71 }
72}
73
74void Class::PrintJSONImpl(JSONStream* stream, bool ref) const {
75 Isolate* isolate = Isolate::Current();
76 JSONObject jsobj(stream);
77 if ((raw() == Class::null()) || (id() == kFreeListElement)) {
78 // TODO(turnidge): This is weird and needs to be changed.
79 jsobj.AddProperty("type", "null");
80 return;
81 }
82 AddCommonObjectProperties(&jsobj, "Class", ref);
83 jsobj.AddFixedServiceId("classes/%" Pd "", id());
84 const String& scrubbed_name = String::Handle(ScrubbedName());
85 const String& vm_name = String::Handle(Name());
86 AddNameProperties(&jsobj, scrubbed_name.ToCString(), vm_name.ToCString());
87 if (ref) {
88 return;
89 }
90
91 const Error& err = Error::Handle(EnsureIsFinalized(Thread::Current()));
92 if (!err.IsNull()) {
93 jsobj.AddProperty("error", err);
94 }
95 jsobj.AddProperty("abstract", is_abstract());
96 jsobj.AddProperty("const", is_const());
97 jsobj.AddProperty("_finalized", is_finalized());
98 jsobj.AddProperty("_implemented", is_implemented());
99 jsobj.AddProperty("_patch", false);
100 jsobj.AddProperty("_traceAllocations", TraceAllocation(isolate));
101
102 const Class& superClass = Class::Handle(SuperClass());
103 if (!superClass.IsNull()) {
104 jsobj.AddProperty("super", superClass);
105 }
106 const AbstractType& superType = AbstractType::Handle(super_type());
107 if (!superType.IsNull()) {
108 jsobj.AddProperty("superType", superType);
109 }
110 const Array& interface_array = Array::Handle(interfaces());
111 if (is_transformed_mixin_application()) {
112 Type& mix = Type::Handle();
113 mix ^= interface_array.At(interface_array.Length() - 1);
114 jsobj.AddProperty("mixin", mix);
115 }
116 jsobj.AddProperty("library", Object::Handle(library()));
117 const Script& script = Script::Handle(this->script());
118 if (!script.IsNull()) {
119 jsobj.AddLocation(script, token_pos(), end_token_pos());
120 }
121 {
122 JSONArray interfaces_array(&jsobj, "interfaces");
123 Type& interface_type = Type::Handle();
124 if (!interface_array.IsNull()) {
125 for (intptr_t i = 0; i < interface_array.Length(); ++i) {
126 interface_type ^= interface_array.At(i);
127 interfaces_array.AddValue(interface_type);
128 }
129 }
130 }
131 {
132 JSONArray fields_array(&jsobj, "fields");
133 const Array& field_array = Array::Handle(fields());
134 Field& field = Field::Handle();
135 if (!field_array.IsNull()) {
136 for (intptr_t i = 0; i < field_array.Length(); ++i) {
137 field ^= field_array.At(i);
138 fields_array.AddValue(field);
139 }
140 }
141 }
142 {
143 JSONArray functions_array(&jsobj, "functions");
144 const Array& function_array = Array::Handle(functions());
145 Function& function = Function::Handle();
146 if (!function_array.IsNull()) {
147 for (intptr_t i = 0; i < function_array.Length(); i++) {
148 function ^= function_array.At(i);
149 functions_array.AddValue(function);
150 }
151 }
152 }
153 {
154 JSONArray subclasses_array(&jsobj, "subclasses");
155 const GrowableObjectArray& subclasses =
156 GrowableObjectArray::Handle(direct_subclasses());
157 if (!subclasses.IsNull()) {
158 Class& subclass = Class::Handle();
159 for (intptr_t i = 0; i < subclasses.Length(); ++i) {
160 // TODO(turnidge): Use the Type directly once regis has added
161 // types to the vmservice.
162 subclass ^= subclasses.At(i);
163 subclasses_array.AddValue(subclass);
164 }
165 }
166 }
167}
168
169void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
170 JSONObject jsobj(stream);
171 // The index in the canonical_type_arguments table cannot be used as part of
172 // the object id (as in typearguments/id), because the indices are not
173 // preserved when the table grows and the entries get rehashed. Use the ring.
174 Thread* thread = Thread::Current();
175 Zone* zone = thread->zone();
176 Isolate* isolate = thread->isolate();
177 ObjectStore* object_store = isolate->object_store();
178 CanonicalTypeArgumentsSet typeargs_table(
179 zone, object_store->canonical_type_arguments());
180 const Array& table =
181 Array::Handle(HashTables::ToArray(typeargs_table, false));
182 typeargs_table.Release();
183 ASSERT(table.Length() > 0);
184 AddCommonObjectProperties(&jsobj, "TypeArguments", ref);
185 jsobj.AddServiceId(*this);
186 const String& user_name = String::Handle(UserVisibleName());
187 const String& vm_name = String::Handle(Name());
188 AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
189 if (ref) {
190 return;
191 }
192 {
193 JSONArray jsarr(&jsobj, "types");
194 AbstractType& type_arg = AbstractType::Handle();
195 for (intptr_t i = 0; i < Length(); i++) {
196 type_arg = TypeAt(i);
197 jsarr.AddValue(type_arg);
198 }
199 }
200 if (!IsInstantiated()) {
201 JSONArray jsarr(&jsobj, "_instantiations");
202 Array& prior_instantiations = Array::Handle(instantiations());
203 ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
204 TypeArguments& type_args = TypeArguments::Handle();
205 intptr_t i = 0;
206 while (prior_instantiations.At(i) !=
207 Smi::New(TypeArguments::kNoInstantiator)) {
208 JSONObject instantiation(&jsarr);
209 type_args ^= prior_instantiations.At(
210 i + TypeArguments::Instantiation::kInstantiatorTypeArgsIndex);
211 instantiation.AddProperty("instantiatorTypeArguments", type_args, true);
212 type_args ^= prior_instantiations.At(
213 i + TypeArguments::Instantiation::kFunctionTypeArgsIndex);
214 instantiation.AddProperty("functionTypeArguments", type_args, true);
215 type_args ^= prior_instantiations.At(
216 i + TypeArguments::Instantiation::kInstantiatedTypeArgsIndex);
217 instantiation.AddProperty("instantiated", type_args, true);
218 i += TypeArguments::Instantiation::kSizeInWords;
219 }
220 }
221}
222
223void PatchClass::PrintJSONImpl(JSONStream* stream, bool ref) const {
224 Object::PrintJSONImpl(stream, ref);
225}
226
227static void AddFunctionServiceId(const JSONObject& jsobj,
228 const Function& f,
229 const Class& cls) {
230 if (cls.IsNull()) {
231 ASSERT(f.IsSignatureFunction());
232 jsobj.AddServiceId(f);
233 return;
234 }
235 // Special kinds of functions use indices in their respective lists.
236 intptr_t id = -1;
237 const char* selector = NULL;
238 if (f.IsNonImplicitClosureFunction()) {
239 id = Isolate::Current()->FindClosureIndex(f);
240 selector = "closures";
241 } else if (f.IsImplicitClosureFunction()) {
242 id = cls.FindImplicitClosureFunctionIndex(f);
243 selector = "implicit_closures";
244 } else if (f.IsNoSuchMethodDispatcher() || f.IsInvokeFieldDispatcher()) {
245 id = cls.FindInvocationDispatcherFunctionIndex(f);
246 selector = "dispatchers";
247 }
248 if (id != -1) {
249 ASSERT(selector != NULL);
250 if (cls.IsTopLevel()) {
251 const auto& library = Library::Handle(cls.library());
252 const auto& private_key = String::Handle(library.private_key());
253 jsobj.AddFixedServiceId("libraries/%s/%s/%" Pd "",
254 private_key.ToCString(), selector, id);
255 } else {
256 jsobj.AddFixedServiceId("classes/%" Pd "/%s/%" Pd "", cls.id(), selector,
257 id);
258 }
259 return;
260 }
261 // Regular functions known to their owner use their name (percent-encoded).
262 String& name = String::Handle(f.name());
263 if (cls.LookupFunction(name) == f.raw()) {
264 const char* encoded_name = String::EncodeIRI(name);
265 if (cls.IsTopLevel()) {
266 const auto& library = Library::Handle(cls.library());
267 const auto& private_key = String::Handle(library.private_key());
268 jsobj.AddFixedServiceId("libraries/%s/functions/%s",
269 private_key.ToCString(), encoded_name);
270 } else {
271 jsobj.AddFixedServiceId("classes/%" Pd "/functions/%s", cls.id(),
272 encoded_name);
273 }
274 return;
275 }
276 // Oddball functions (not known to their owner) fall back to use the object
277 // id ring. Current known examples are signature functions of closures
278 // and stubs like 'megamorphic_call_miss'.
279 jsobj.AddServiceId(f);
280}
281
282void Function::PrintJSONImpl(JSONStream* stream, bool ref) const {
283 Class& cls = Class::Handle(Owner());
284 if (!cls.IsNull()) {
285 Error& err = Error::Handle();
286 err = cls.EnsureIsFinalized(Thread::Current());
287 ASSERT(err.IsNull());
288 } else {
289 ASSERT(IsSignatureFunction());
290 }
291 JSONObject jsobj(stream);
292 AddCommonObjectProperties(&jsobj, "Function", ref);
293 AddFunctionServiceId(jsobj, *this, cls);
294 const char* user_name = UserVisibleNameCString();
295 const String& vm_name = String::Handle(name());
296 AddNameProperties(&jsobj, user_name, vm_name.ToCString());
297 const Function& parent = Function::Handle(parent_function());
298 if (!parent.IsNull()) {
299 jsobj.AddProperty("owner", parent);
300 } else if (!cls.IsNull()) {
301 if (cls.IsTopLevel()) {
302 const Library& library = Library::Handle(cls.library());
303 jsobj.AddProperty("owner", library);
304 } else {
305 jsobj.AddProperty("owner", cls);
306 }
307 }
308
309 const char* kind_string = Function::KindToCString(kind());
310 jsobj.AddProperty("_kind", kind_string);
311 jsobj.AddProperty("static", is_static());
312 jsobj.AddProperty("const", is_const());
313 jsobj.AddProperty("_intrinsic", is_intrinsic());
314 jsobj.AddProperty("_native", is_native());
315 if (ref) {
316 return;
317 }
318 Code& code = Code::Handle(CurrentCode());
319 if (!code.IsNull()) {
320 jsobj.AddProperty("code", code);
321 }
322#if !defined(DART_PRECOMPILED_RUNTIME)
323 Bytecode& bytecode = Bytecode::Handle(this->bytecode());
324 if (!bytecode.IsNull()) {
325 jsobj.AddProperty("_bytecode", bytecode);
326 }
327#endif // !DART_PRECOMPILED_RUNTIME
328 Array& ics = Array::Handle(ic_data_array());
329 if (!ics.IsNull()) {
330 jsobj.AddProperty("_icDataArray", ics);
331 }
332 jsobj.AddProperty("_optimizable", is_optimizable());
333 jsobj.AddProperty("_inlinable", is_inlinable());
334 jsobj.AddProperty("_recognized", IsRecognized());
335 code = unoptimized_code();
336 if (!code.IsNull()) {
337 jsobj.AddProperty("_unoptimizedCode", code);
338 }
339 jsobj.AddProperty("_usageCounter", usage_counter());
340 jsobj.AddProperty("_optimizedCallSiteCount", optimized_call_site_count());
341 jsobj.AddProperty("_deoptimizations",
342 static_cast<intptr_t>(deoptimization_counter()));
343 if ((kind() == FunctionLayout::kImplicitGetter) ||
344 (kind() == FunctionLayout::kImplicitSetter) ||
345 (kind() == FunctionLayout::kImplicitStaticGetter) ||
346 (kind() == FunctionLayout::kFieldInitializer)) {
347 const Field& field = Field::Handle(accessor_field());
348 if (!field.IsNull()) {
349 jsobj.AddProperty("_field", field);
350 }
351 }
352
353 const Script& script = Script::Handle(this->script());
354 if (!script.IsNull()) {
355 jsobj.AddLocation(script, token_pos(), end_token_pos());
356 }
357}
358
359void RedirectionData::PrintJSONImpl(JSONStream* stream, bool ref) const {
360 Object::PrintJSONImpl(stream, ref);
361}
362
363void FfiTrampolineData::PrintJSONImpl(JSONStream* stream, bool ref) const {
364 Object::PrintJSONImpl(stream, ref);
365}
366
367void Field::PrintJSONImpl(JSONStream* stream, bool ref) const {
368 JSONObject jsobj(stream);
369 Class& cls = Class::Handle(Owner());
370 String& field_name = String::Handle(name());
371 const char* encoded_field_name = String::EncodeIRI(field_name);
372 AddCommonObjectProperties(&jsobj, "Field", ref);
373 if (cls.IsTopLevel()) {
374 const auto& library = Library::Handle(cls.library());
375 const auto& private_key = String::Handle(library.private_key());
376 jsobj.AddFixedServiceId("libraries/%s/fields/%s", private_key.ToCString(),
377 encoded_field_name);
378 } else {
379 jsobj.AddFixedServiceId("classes/%" Pd "/fields/%s", cls.id(),
380 encoded_field_name);
381 }
382
383 const char* user_name = UserVisibleNameCString();
384 const String& vm_name = String::Handle(name());
385 AddNameProperties(&jsobj, user_name, vm_name.ToCString());
386 if (cls.IsTopLevel()) {
387 const Library& library = Library::Handle(cls.library());
388 jsobj.AddProperty("owner", library);
389 } else {
390 jsobj.AddProperty("owner", cls);
391 }
392
393 AbstractType& declared_type = AbstractType::Handle(type());
394 jsobj.AddProperty("declaredType", declared_type);
395 jsobj.AddProperty("static", is_static());
396 jsobj.AddProperty("final", is_final());
397 jsobj.AddProperty("const", is_const());
398 if (ref) {
399 return;
400 }
401 if (is_static()) {
402 const Instance& valueObj = Instance::Handle(StaticValue());
403 jsobj.AddProperty("staticValue", valueObj);
404 }
405
406 jsobj.AddProperty("_guardNullable", is_nullable());
407 if (guarded_cid() == kIllegalCid) {
408 jsobj.AddProperty("_guardClass", "unknown");
409 } else if (guarded_cid() == kDynamicCid) {
410 jsobj.AddProperty("_guardClass", "dynamic");
411 } else {
412 ClassTable* table = Isolate::Current()->class_table();
413 ASSERT(table->IsValidIndex(guarded_cid()));
414 cls = table->At(guarded_cid());
415 jsobj.AddProperty("_guardClass", cls);
416 }
417 if (guarded_list_length() == kUnknownFixedLength) {
418 jsobj.AddProperty("_guardLength", "unknown");
419 } else if (guarded_list_length() == kNoFixedLength) {
420 jsobj.AddProperty("_guardLength", "variable");
421 } else {
422 jsobj.AddPropertyF("_guardLength", "%" Pd, guarded_list_length());
423 }
424 const class Script& script = Script::Handle(Script());
425 if (!script.IsNull()) {
426 jsobj.AddLocation(script, token_pos());
427 }
428}
429
430// See also Dart_ScriptGetTokenInfo.
431void Script::PrintJSONImpl(JSONStream* stream, bool ref) const {
432 JSONObject jsobj(stream);
433 AddCommonObjectProperties(&jsobj, "Script", ref);
434 const String& uri = String::Handle(url());
435 ASSERT(!uri.IsNull());
436 const char* encoded_uri = String::EncodeIRI(uri);
437 const Library& lib = Library::Handle(FindLibrary());
438 if (lib.IsNull()) {
439 jsobj.AddServiceId(*this);
440 } else {
441 const String& lib_id = String::Handle(lib.private_key());
442 jsobj.AddFixedServiceId("libraries/%s/scripts/%s/%" Px64 "",
443 lib_id.ToCString(), encoded_uri, load_timestamp());
444 }
445 jsobj.AddPropertyStr("uri", uri);
446 jsobj.AddProperty("_kind", "kernel");
447 if (ref) {
448 return;
449 }
450 jsobj.AddPropertyTimeMillis("_loadTime", load_timestamp());
451 if (!lib.IsNull()) {
452 jsobj.AddProperty("library", lib);
453 }
454 const String& source = String::Handle(Source());
455 jsobj.AddProperty("lineOffset", line_offset());
456 jsobj.AddProperty("columnOffset", col_offset());
457 if (!source.IsNull()) {
458 jsobj.AddPropertyStr("source", source);
459 }
460
461 // Print the line number table
462 const GrowableObjectArray& lineNumberArray =
463 GrowableObjectArray::Handle(GenerateLineNumberArray());
464 if (!lineNumberArray.IsNull() && (lineNumberArray.Length() > 0)) {
465 JSONArray tokenPosTable(&jsobj, "tokenPosTable");
466
467 Object& value = Object::Handle();
468 intptr_t pos = 0;
469
470 // Skip leading null.
471 ASSERT(lineNumberArray.Length() > 0);
472 value = lineNumberArray.At(pos);
473 ASSERT(value.IsNull());
474 pos++;
475
476 while (pos < lineNumberArray.Length()) {
477 JSONArray lineInfo(&tokenPosTable);
478 while (pos < lineNumberArray.Length()) {
479 value = lineNumberArray.At(pos);
480 pos++;
481 if (value.IsNull()) {
482 break;
483 }
484 const Smi& smi = Smi::Cast(value);
485 lineInfo.AddValue(smi.Value());
486 }
487 }
488 }
489}
490
491void Library::PrintJSONImpl(JSONStream* stream, bool ref) const {
492 const String& id = String::Handle(private_key());
493 JSONObject jsobj(stream);
494 AddCommonObjectProperties(&jsobj, "Library", ref);
495 jsobj.AddFixedServiceId("libraries/%s", id.ToCString());
496 const String& vm_name = String::Handle(name());
497 const char* scrubbed_name = String::ScrubName(vm_name);
498 AddNameProperties(&jsobj, scrubbed_name, vm_name.ToCString());
499 const String& library_url = String::Handle(url());
500 jsobj.AddPropertyStr("uri", library_url);
501 if (ref) {
502 return;
503 }
504 jsobj.AddProperty("debuggable", IsDebuggable());
505 {
506 JSONArray jsarr(&jsobj, "classes");
507 ClassDictionaryIterator class_iter(*this);
508 Class& klass = Class::Handle();
509 while (class_iter.HasNext()) {
510 klass = class_iter.GetNextClass();
511 jsarr.AddValue(klass);
512 }
513 }
514 {
515 JSONArray jsarr(&jsobj, "dependencies");
516
517 Namespace& ns = Namespace::Handle();
518 Library& target = Library::Handle();
519
520 // Unprefixed imports.
521 Array& imports = Array::Handle(this->imports());
522 for (intptr_t i = 0; i < imports.Length(); i++) {
523 ns ^= imports.At(i);
524 if (ns.IsNull()) continue;
525
526 JSONObject jsdep(&jsarr);
527 jsdep.AddProperty("isDeferred", false);
528 jsdep.AddProperty("isExport", false);
529 jsdep.AddProperty("isImport", true);
530 target = ns.library();
531 jsdep.AddProperty("target", target);
532 }
533
534 // Exports.
535 const Array& exports = Array::Handle(this->exports());
536 for (intptr_t i = 0; i < exports.Length(); i++) {
537 ns ^= exports.At(i);
538 if (ns.IsNull()) continue;
539
540 JSONObject jsdep(&jsarr);
541 jsdep.AddProperty("isDeferred", false);
542 jsdep.AddProperty("isExport", true);
543 jsdep.AddProperty("isImport", false);
544 target = ns.library();
545 jsdep.AddProperty("target", target);
546 }
547
548 // Prefixed imports.
549 DictionaryIterator entries(*this);
550 Object& entry = Object::Handle();
551 LibraryPrefix& prefix = LibraryPrefix::Handle();
552 String& prefix_name = String::Handle();
553 while (entries.HasNext()) {
554 entry = entries.GetNext();
555 if (entry.IsLibraryPrefix()) {
556 prefix ^= entry.raw();
557 imports = prefix.imports();
558 if (!imports.IsNull()) {
559 for (intptr_t i = 0; i < imports.Length(); i++) {
560 ns ^= imports.At(i);
561 if (ns.IsNull()) continue;
562
563 JSONObject jsdep(&jsarr);
564 jsdep.AddProperty("isDeferred", prefix.is_deferred_load());
565 jsdep.AddProperty("isExport", false);
566 jsdep.AddProperty("isImport", true);
567 prefix_name = prefix.name();
568 ASSERT(!prefix_name.IsNull());
569 jsdep.AddProperty("prefix", prefix_name.ToCString());
570 target = ns.library();
571 jsdep.AddProperty("target", target);
572 }
573 }
574 }
575 }
576
577 if (is_declared_in_bytecode()) {
578 // Make sure top level class (containing annotations) is fully loaded.
579 EnsureTopLevelClassIsFinalized();
580 Array& metadata = Array::Handle(GetExtendedMetadata(*this, 1));
581 if (metadata.Length() != 0) {
582 // Library has the only element in the extended metadata.
583 metadata ^= metadata.At(0);
584 if (!metadata.IsNull()) {
585 Thread* thread = Thread::Current();
586 auto& desc = Array::Handle();
587 auto& target_uri = String::Handle();
588 auto& is_export = Bool::Handle();
589 auto& is_deferred = Bool::Handle();
590 for (intptr_t i = 0, n = metadata.Length(); i < n; ++i) {
591 desc ^= metadata.At(i);
592 // Each dependency is represented as an array with the following
593 // layout:
594 // [0] = target library URI (String)
595 // [1] = is_export (bool)
596 // [2] = is_deferred (bool)
597 // [3] = prefix (String or null)
598 // ...
599 // The library dependencies are encoded by getLibraryAnnotations(),
600 // pkg/vm/lib/bytecode/gen_bytecode.dart.
601 target_uri ^= desc.At(0);
602 is_export ^= desc.At(1);
603 is_deferred ^= desc.At(2);
604 prefix_name ^= desc.At(3);
605
606 target = Library::LookupLibrary(thread, target_uri);
607 if (target.IsNull()) {
608 continue;
609 }
610
611 JSONObject jsdep(&jsarr);
612 jsdep.AddProperty("isDeferred", is_deferred.value());
613 jsdep.AddProperty("isExport", is_export.value());
614 jsdep.AddProperty("isImport", !is_export.value());
615 if (!prefix_name.IsNull()) {
616 jsdep.AddProperty("prefix", prefix_name.ToCString());
617 }
618 jsdep.AddProperty("target", target);
619 }
620 }
621 }
622 }
623 }
624 {
625 JSONArray jsarr(&jsobj, "variables");
626 DictionaryIterator entries(*this);
627 Object& entry = Object::Handle();
628 while (entries.HasNext()) {
629 entry = entries.GetNext();
630 if (entry.IsField()) {
631 jsarr.AddValue(entry);
632 }
633 }
634 }
635 {
636 JSONArray jsarr(&jsobj, "functions");
637 DictionaryIterator entries(*this);
638 Object& entry = Object::Handle();
639 while (entries.HasNext()) {
640 entry = entries.GetNext();
641 if (entry.IsFunction()) {
642 const Function& func = Function::Cast(entry);
643 if (func.kind() == FunctionLayout::kRegularFunction ||
644 func.kind() == FunctionLayout::kGetterFunction ||
645 func.kind() == FunctionLayout::kSetterFunction) {
646 jsarr.AddValue(func);
647 }
648 }
649 }
650 }
651 {
652 JSONArray jsarr(&jsobj, "scripts");
653 Array& scripts = Array::Handle(LoadedScripts());
654 Script& script = Script::Handle();
655 for (intptr_t i = 0; i < scripts.Length(); i++) {
656 script ^= scripts.At(i);
657 jsarr.AddValue(script);
658 }
659 }
660}
661
662void LibraryPrefix::PrintJSONImpl(JSONStream* stream, bool ref) const {
663 Object::PrintJSONImpl(stream, ref);
664}
665
666void Namespace::PrintJSONImpl(JSONStream* stream, bool ref) const {
667 Object::PrintJSONImpl(stream, ref);
668}
669
670void KernelProgramInfo::PrintJSONImpl(JSONStream* stream, bool ref) const {
671 Object::PrintJSONImpl(stream, ref);
672}
673
674void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const {
675 JSONObject jsobj(stream);
676 AddCommonObjectProperties(&jsobj, "Object", ref);
677 jsobj.AddServiceId(*this);
678 if (ref) {
679 return;
680 }
681}
682
683void InstructionsSection::PrintJSONImpl(JSONStream* stream, bool ref) const {
684 Object::PrintJSONImpl(stream, ref);
685}
686
687void WeakSerializationReference::PrintJSONImpl(JSONStream* stream,
688 bool ref) const {
689 JSONObject jsobj(stream);
690 AddCommonObjectProperties(&jsobj, "Object", ref);
691 jsobj.AddServiceId(*this);
692 if (ref) return;
693 auto& obj = Object::Handle(target());
694 jsobj.AddProperty("target", obj);
695}
696
697void ObjectPool::PrintJSONImpl(JSONStream* stream, bool ref) const {
698 JSONObject jsobj(stream);
699 AddCommonObjectProperties(&jsobj, "Object", ref);
700 jsobj.AddServiceId(*this);
701 jsobj.AddProperty("length", Length());
702 if (ref) {
703 return;
704 }
705
706 {
707 JSONArray jsarr(&jsobj, "_entries");
708 uword imm;
709 Object& obj = Object::Handle();
710 for (intptr_t i = 0; i < Length(); i++) {
711 JSONObject jsentry(stream);
712 jsentry.AddProperty("offset", OffsetFromIndex(i));
713 switch (TypeAt(i)) {
714 case ObjectPool::EntryType::kTaggedObject:
715 obj = ObjectAt(i);
716 jsentry.AddProperty("kind", "Object");
717 jsentry.AddProperty("value", obj);
718 break;
719 case ObjectPool::EntryType::kImmediate:
720 imm = RawValueAt(i);
721 jsentry.AddProperty("kind", "Immediate");
722 jsentry.AddProperty64("value", imm);
723 break;
724 case ObjectPool::EntryType::kNativeEntryData:
725 obj = ObjectAt(i);
726 jsentry.AddProperty("kind", "NativeEntryData");
727 jsentry.AddProperty("value", obj);
728 break;
729 case ObjectPool::EntryType::kNativeFunction:
730 imm = RawValueAt(i);
731 jsentry.AddProperty("kind", "NativeFunction");
732 jsentry.AddProperty64("value", imm);
733 break;
734 case ObjectPool::EntryType::kNativeFunctionWrapper:
735 imm = RawValueAt(i);
736 jsentry.AddProperty("kind", "NativeFunctionWrapper");
737 jsentry.AddProperty64("value", imm);
738 break;
739 default:
740 UNREACHABLE();
741 }
742 }
743 }
744}
745
746void PcDescriptors::PrintToJSONObject(JSONObject* jsobj, bool ref) const {
747 AddCommonObjectProperties(jsobj, "Object", ref);
748 // TODO(johnmccutchan): Generate a stable id. PcDescriptors hang off a Code
749 // object but do not have a back reference to generate an ID.
750 jsobj->AddServiceId(*this);
751 if (ref) {
752 return;
753 }
754 JSONArray members(jsobj, "members");
755 Iterator iter(*this, PcDescriptorsLayout::kAnyKind);
756 while (iter.MoveNext()) {
757 JSONObject descriptor(&members);
758 descriptor.AddPropertyF("pcOffset", "%" Px "", iter.PcOffset());
759 descriptor.AddProperty("kind", KindAsStr(iter.Kind()));
760 descriptor.AddProperty("deoptId", iter.DeoptId());
761 // TODO(turnidge): Use AddLocation instead.
762 descriptor.AddProperty("tokenPos", iter.TokenPos());
763 descriptor.AddProperty("tryIndex", iter.TryIndex());
764 }
765}
766
767void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const {
768 JSONObject jsobj(stream);
769 PrintToJSONObject(&jsobj, ref);
770}
771
772void CodeSourceMap::PrintJSONImpl(JSONStream* stream, bool ref) const {
773 Object::PrintJSONImpl(stream, ref);
774}
775
776void CompressedStackMaps::PrintJSONImpl(JSONStream* stream, bool ref) const {
777 Object::PrintJSONImpl(stream, ref);
778}
779
780void LocalVarDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const {
781 JSONObject jsobj(stream);
782 AddCommonObjectProperties(&jsobj, "Object", ref);
783 // TODO(johnmccutchan): Generate a stable id. LocalVarDescriptors hang off
784 // a Code object but do not have a back reference to generate an ID.
785 jsobj.AddServiceId(*this);
786 if (ref) {
787 return;
788 }
789 JSONArray members(&jsobj, "members");
790 String& var_name = String::Handle();
791 for (intptr_t i = 0; i < Length(); i++) {
792 LocalVarDescriptorsLayout::VarInfo info;
793 var_name = GetName(i);
794 GetInfo(i, &info);
795 JSONObject var(&members);
796 var.AddProperty("name", var_name.ToCString());
797 var.AddProperty("index", static_cast<intptr_t>(info.index()));
798 var.AddProperty("declarationTokenPos", info.declaration_pos);
799 var.AddProperty("scopeStartTokenPos", info.begin_pos);
800 var.AddProperty("scopeEndTokenPos", info.end_pos);
801 var.AddProperty("scopeId", static_cast<intptr_t>(info.scope_id));
802 var.AddProperty("kind", KindToCString(info.kind()));
803 }
804}
805
806void ExceptionHandlers::PrintJSONImpl(JSONStream* stream, bool ref) const {
807 Object::PrintJSONImpl(stream, ref);
808}
809
810void ParameterTypeCheck::PrintJSONImpl(JSONStream* stream, bool ref) const {
811 Object::PrintJSONImpl(stream, ref);
812}
813
814void SingleTargetCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
815 JSONObject jsobj(stream);
816 AddCommonObjectProperties(&jsobj, "Object", ref);
817 jsobj.AddServiceId(*this);
818 jsobj.AddProperty("_target", Code::Handle(target()));
819 if (ref) {
820 return;
821 }
822 jsobj.AddProperty("_lowerLimit", lower_limit());
823 jsobj.AddProperty("_upperLimit", upper_limit());
824}
825
826void UnlinkedCall::PrintJSONImpl(JSONStream* stream, bool ref) const {
827 JSONObject jsobj(stream);
828 AddCommonObjectProperties(&jsobj, "Object", ref);
829 jsobj.AddServiceId(*this);
830 jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
831 if (ref) {
832 return;
833 }
834 jsobj.AddProperty("_argumentsDescriptor",
835 Array::Handle(arguments_descriptor()));
836}
837
838void MonomorphicSmiableCall::PrintJSONImpl(JSONStream* stream, bool ref) const {
839 JSONObject jsobj(stream);
840 AddCommonObjectProperties(&jsobj, "Object", ref);
841 jsobj.AddServiceId(*this);
842 jsobj.AddProperty("_expectedClassId", Smi::Handle(Smi::New(expected_cid())));
843 if (ref) {
844 return;
845 }
846 jsobj.AddProperty("_target", Code::Handle(target()));
847}
848
849void CallSiteData::PrintJSONImpl(JSONStream* stream, bool ref) const {
850 UNREACHABLE();
851}
852
853void ICData::PrintJSONImpl(JSONStream* stream, bool ref) const {
854 JSONObject jsobj(stream);
855 AddCommonObjectProperties(&jsobj, "Object", ref);
856 jsobj.AddServiceId(*this);
857 jsobj.AddProperty("_owner", Object::Handle(Owner()));
858 jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
859 if (ref) {
860 return;
861 }
862 jsobj.AddProperty("_argumentsDescriptor",
863 Object::Handle(arguments_descriptor()));
864 jsobj.AddProperty("_entries", Object::Handle(entries()));
865}
866
867void ICData::PrintToJSONArray(const JSONArray& jsarray,
868 TokenPosition token_pos) const {
869 Isolate* isolate = Isolate::Current();
870 Class& cls = Class::Handle();
871 Function& func = Function::Handle();
872
873 JSONObject jsobj(&jsarray);
874 jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
875 jsobj.AddProperty("tokenPos", token_pos.value());
876 // TODO(rmacnak): Figure out how to stringify DeoptReasons().
877 // jsobj.AddProperty("deoptReasons", ...);
878
879 JSONArray cache_entries(&jsobj, "cacheEntries");
880 for (intptr_t i = 0; i < NumberOfChecks(); i++) {
881 JSONObject cache_entry(&cache_entries);
882 func = GetTargetAt(i);
883 intptr_t count = GetCountAt(i);
884 if (!is_static_call()) {
885 intptr_t cid = GetReceiverClassIdAt(i);
886 cls = isolate->class_table()->At(cid);
887 cache_entry.AddProperty("receiver", cls);
888 }
889 cache_entry.AddProperty("target", func);
890 cache_entry.AddProperty("count", count);
891 }
892}
893
894void Code::PrintJSONImpl(JSONStream* stream, bool ref) const {
895 // N.B. This is polymorphic with Bytecode.
896
897 JSONObject jsobj(stream);
898 AddCommonObjectProperties(&jsobj, "Code", ref);
899 jsobj.AddFixedServiceId("code/%" Px64 "-%" Px "", compile_timestamp(),
900 PayloadStart());
901 const char* qualified_name = QualifiedName(
902 NameFormattingParams(kUserVisibleName, NameDisambiguation::kNo));
903 const char* vm_name = Name();
904 AddNameProperties(&jsobj, qualified_name, vm_name);
905 const bool is_stub =
906 IsStubCode() || IsAllocationStubCode() || IsTypeTestStubCode();
907 if (is_stub) {
908 jsobj.AddProperty("kind", "Stub");
909 } else {
910 jsobj.AddProperty("kind", "Dart");
911 }
912 jsobj.AddProperty("_optimized", is_optimized());
913 const Object& obj = Object::Handle(owner());
914 if (obj.IsFunction()) {
915 const Function& func = Function::Cast(obj);
916 jsobj.AddProperty("_intrinsic", func.is_intrinsic());
917 jsobj.AddProperty("_native", func.is_native());
918 } else {
919 jsobj.AddProperty("_intrinsic", false);
920 jsobj.AddProperty("_native", false);
921 }
922 if (ref) {
923 return;
924 }
925 if (obj.IsFunction()) {
926 jsobj.AddProperty("function", obj);
927 } else {
928 // Generate a fake function reference.
929 JSONObject func(&jsobj, "function");
930 func.AddProperty("type", "@Function");
931 func.AddProperty("_kind", "Stub");
932 ASSERT(strcmp(qualified_name, vm_name) == 0);
933 func.AddProperty("name", vm_name);
934 AddNameProperties(&func, vm_name, vm_name);
935 }
936 jsobj.AddPropertyF("_startAddress", "%" Px "", PayloadStart());
937 jsobj.AddPropertyF("_endAddress", "%" Px "", PayloadStart() + Size());
938 jsobj.AddProperty("_alive", is_alive());
939 const ObjectPool& object_pool = ObjectPool::Handle(GetObjectPool());
940 jsobj.AddProperty("_objectPool", object_pool);
941 {
942 JSONArray jsarr(&jsobj, "_disassembly");
943 if (is_alive()) {
944 // Only disassemble alive code objects.
945 DisassembleToJSONStream formatter(jsarr);
946 Disassemble(&formatter);
947 }
948 }
949 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
950 if (!descriptors.IsNull()) {
951 JSONObject desc(&jsobj, "_descriptors");
952 descriptors.PrintToJSONObject(&desc, false);
953 }
954
955 PrintJSONInlineIntervals(&jsobj);
956}
957
958void Bytecode::PrintJSONImpl(JSONStream* stream, bool ref) const {
959 // N.B. This is polymorphic with Code.
960
961 JSONObject jsobj(stream);
962 AddCommonObjectProperties(&jsobj, "Code", ref);
963 int64_t compile_timestamp = 0;
964 jsobj.AddFixedServiceId("code/%" Px64 "-%" Px "", compile_timestamp,
965 PayloadStart());
966 const char* qualified_name = QualifiedName();
967 const char* vm_name = Name();
968 AddNameProperties(&jsobj, qualified_name, vm_name);
969
970 jsobj.AddProperty("kind", "Dart");
971 jsobj.AddProperty("_optimized", false);
972 jsobj.AddProperty("_intrinsic", false);
973 jsobj.AddProperty("_native", false);
974 if (ref) {
975 return;
976 }
977 const Function& fun = Function::Handle(function());
978 jsobj.AddProperty("function", fun);
979 jsobj.AddPropertyF("_startAddress", "%" Px "", PayloadStart());
980 jsobj.AddPropertyF("_endAddress", "%" Px "", PayloadStart() + Size());
981 jsobj.AddProperty("_alive", true);
982 const ObjectPool& obj_pool = ObjectPool::Handle(object_pool());
983 jsobj.AddProperty("_objectPool", obj_pool);
984 {
985 JSONArray jsarr(&jsobj, "_disassembly");
986 DisassembleToJSONStream formatter(jsarr);
987 Disassemble(&formatter);
988 }
989 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
990 if (!descriptors.IsNull()) {
991 JSONObject desc(&jsobj, "_descriptors");
992 descriptors.PrintToJSONObject(&desc, false);
993 }
994
995 { JSONArray inlined_functions(&jsobj, "_inlinedFunctions"); }
996 { JSONArray inline_intervals(&jsobj, "_inlinedIntervals"); }
997}
998
999void Context::PrintJSONImpl(JSONStream* stream, bool ref) const {
1000 JSONObject jsobj(stream);
1001 // TODO(turnidge): Should the user level type for Context be Context
1002 // or Object?
1003 AddCommonObjectProperties(&jsobj, "Context", ref);
1004 jsobj.AddServiceId(*this);
1005
1006 jsobj.AddProperty("length", num_variables());
1007
1008 if (ref) {
1009 return;
1010 }
1011
1012 const Context& parent_context = Context::Handle(parent());
1013 if (!parent_context.IsNull()) {
1014 jsobj.AddProperty("parent", parent_context);
1015 }
1016
1017 JSONArray jsarr(&jsobj, "variables");
1018 Object& var = Object::Handle();
1019 for (intptr_t index = 0; index < num_variables(); index++) {
1020 var = At(index);
1021 JSONObject jselement(&jsarr);
1022 jselement.AddProperty("value", var);
1023 }
1024}
1025
1026void ContextScope::PrintJSONImpl(JSONStream* stream, bool ref) const {
1027 Object::PrintJSONImpl(stream, ref);
1028}
1029
1030void MegamorphicCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
1031 JSONObject jsobj(stream);
1032 AddCommonObjectProperties(&jsobj, "Object", ref);
1033 jsobj.AddServiceId(*this);
1034 jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
1035 if (ref) {
1036 return;
1037 }
1038 jsobj.AddProperty("_buckets", Object::Handle(buckets()));
1039 jsobj.AddProperty("_mask", mask());
1040 jsobj.AddProperty("_argumentsDescriptor",
1041 Object::Handle(arguments_descriptor()));
1042}
1043
1044void SubtypeTestCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
1045 JSONObject jsobj(stream);
1046 AddCommonObjectProperties(&jsobj, "Object", ref);
1047 jsobj.AddServiceId(*this);
1048 if (ref) {
1049 return;
1050 }
1051 jsobj.AddProperty("_cache", Array::Handle(cache()));
1052}
1053
1054void LoadingUnit::PrintJSONImpl(JSONStream* stream, bool ref) const {
1055 JSONObject jsobj(stream);
1056 AddCommonObjectProperties(&jsobj, "Object", ref);
1057 jsobj.AddServiceId(*this);
1058 if (ref) {
1059 return;
1060 }
1061 jsobj.AddProperty("_parent", LoadingUnit::Handle(parent()));
1062 jsobj.AddProperty("_baseObjects", Array::Handle(base_objects()));
1063 jsobj.AddProperty("_id", static_cast<intptr_t>(id()));
1064 jsobj.AddProperty("_loaded", loaded());
1065 jsobj.AddProperty("_loadOutstanding", load_outstanding());
1066}
1067
1068void Error::PrintJSONImpl(JSONStream* stream, bool ref) const {
1069 UNREACHABLE();
1070}
1071
1072void ApiError::PrintJSONImpl(JSONStream* stream, bool ref) const {
1073 JSONObject jsobj(stream);
1074 AddCommonObjectProperties(&jsobj, "Error", ref);
1075 jsobj.AddProperty("kind", "InternalError");
1076 jsobj.AddServiceId(*this);
1077 jsobj.AddProperty("message", ToErrorCString());
1078}
1079
1080void LanguageError::PrintJSONImpl(JSONStream* stream, bool ref) const {
1081 JSONObject jsobj(stream);
1082 AddCommonObjectProperties(&jsobj, "Error", ref);
1083 jsobj.AddProperty("kind", "LanguageError");
1084 jsobj.AddServiceId(*this);
1085 jsobj.AddProperty("message", ToErrorCString());
1086}
1087
1088void UnhandledException::PrintJSONImpl(JSONStream* stream, bool ref) const {
1089 JSONObject jsobj(stream);
1090 AddCommonObjectProperties(&jsobj, "Error", ref);
1091 jsobj.AddProperty("kind", "UnhandledException");
1092 jsobj.AddServiceId(*this);
1093 jsobj.AddProperty("message", ToErrorCString());
1094 if (ref) {
1095 return;
1096 }
1097 Instance& instance = Instance::Handle();
1098 instance = exception();
1099 jsobj.AddProperty("exception", instance);
1100 instance = stacktrace();
1101 jsobj.AddProperty("stacktrace", instance);
1102}
1103
1104void UnwindError::PrintJSONImpl(JSONStream* stream, bool ref) const {
1105 JSONObject jsobj(stream);
1106 AddCommonObjectProperties(&jsobj, "Error", ref);
1107 jsobj.AddProperty("kind", "TerminationError");
1108 jsobj.AddServiceId(*this);
1109 jsobj.AddProperty("message", ToErrorCString());
1110 jsobj.AddProperty("_is_user_initiated", is_user_initiated());
1111}
1112
1113void Instance::PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const {
1114 AddCommonObjectProperties(jsobj, "Instance", ref);
1115 if (ref) {
1116 return;
1117 }
1118
1119 // Add all fields in layout order, from superclass to subclass.
1120 GrowableArray<Class*> classes;
1121 Class& cls = Class::Handle(this->clazz());
1122 if (IsClosure()) {
1123 // Closure fields are not instances. Skip them.
1124 cls = cls.SuperClass();
1125 }
1126 do {
1127 classes.Add(&Class::Handle(cls.raw()));
1128 cls = cls.SuperClass();
1129 } while (!cls.IsNull());
1130
1131 Array& field_array = Array::Handle();
1132 Field& field = Field::Handle();
1133 Instance& field_value = Instance::Handle();
1134 {
1135 JSONArray jsarr(jsobj, "fields");
1136 for (intptr_t i = classes.length() - 1; i >= 0; i--) {
1137 field_array = classes[i]->fields();
1138 if (!field_array.IsNull()) {
1139 for (intptr_t j = 0; j < field_array.Length(); j++) {
1140 field ^= field_array.At(j);
1141 if (!field.is_static()) {
1142 field_value ^= GetField(field);
1143 JSONObject jsfield(&jsarr);
1144 jsfield.AddProperty("type", "BoundField");
1145 jsfield.AddProperty("decl", field);
1146 jsfield.AddProperty("value", field_value);
1147 }
1148 }
1149 }
1150 }
1151 }
1152
1153 if (NumNativeFields() > 0) {
1154 JSONArray jsarr(jsobj, "_nativeFields");
1155 for (intptr_t i = 0; i < NumNativeFields(); i++) {
1156 intptr_t value = GetNativeField(i);
1157 JSONObject jsfield(&jsarr);
1158 jsfield.AddProperty("index", i);
1159 jsfield.AddProperty("value", value);
1160 }
1161 }
1162}
1163
1164void Instance::PrintJSONImpl(JSONStream* stream, bool ref) const {
1165 JSONObject jsobj(stream);
1166
1167 // Handle certain special instance values.
1168 if (raw() == Object::sentinel().raw()) {
1169 jsobj.AddProperty("type", "Sentinel");
1170 jsobj.AddProperty("kind", "NotInitialized");
1171 jsobj.AddProperty("valueAsString", "<not initialized>");
1172 return;
1173 } else if (raw() == Object::transition_sentinel().raw()) {
1174 jsobj.AddProperty("type", "Sentinel");
1175 jsobj.AddProperty("kind", "BeingInitialized");
1176 jsobj.AddProperty("valueAsString", "<being initialized>");
1177 return;
1178 }
1179
1180 PrintSharedInstanceJSON(&jsobj, ref);
1181 // TODO(regis): Wouldn't it be simpler to provide a Closure::PrintJSONImpl()?
1182 if (IsClosure()) {
1183 jsobj.AddProperty("kind", "Closure");
1184 } else {
1185 jsobj.AddProperty("kind", "PlainInstance");
1186 }
1187 jsobj.AddServiceId(*this);
1188 if (IsClosure()) {
1189 // TODO(regis): How about closureInstantiatorTypeArguments and
1190 // closureFunctionTypeArguments?
1191 jsobj.AddProperty("closureFunction",
1192 Function::Handle(Closure::Cast(*this).function()));
1193 jsobj.AddProperty("closureContext",
1194 Context::Handle(Closure::Cast(*this).context()));
1195 }
1196 if (ref) {
1197 return;
1198 }
1199 if (IsClosure()) {
1200 Debugger* debugger = Isolate::Current()->debugger();
1201 Breakpoint* bpt = debugger->BreakpointAtActivation(*this);
1202 if (bpt != NULL) {
1203 jsobj.AddProperty("_activationBreakpoint", bpt);
1204 }
1205 }
1206}
1207
1208void AbstractType::PrintJSONImpl(JSONStream* stream, bool ref) const {
1209 UNREACHABLE();
1210}
1211
1212void Type::PrintJSONImpl(JSONStream* stream, bool ref) const {
1213 // TODO(regis): Function types are not handled properly.
1214 JSONObject jsobj(stream);
1215 PrintSharedInstanceJSON(&jsobj, ref);
1216 jsobj.AddProperty("kind", "Type");
1217 const Class& type_cls = Class::Handle(type_class());
1218 if (type_cls.DeclarationType() == raw()) {
1219 intptr_t cid = type_cls.id();
1220 jsobj.AddFixedServiceId("classes/%" Pd "/types/%d", cid, 0);
1221 } else {
1222 jsobj.AddServiceId(*this);
1223 }
1224 jsobj.AddProperty("typeClass", type_cls);
1225 const String& user_name = String::Handle(UserVisibleName());
1226 const String& vm_name = String::Handle(Name());
1227 AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
1228 if (ref) {
1229 return;
1230 }
1231 const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
1232 if (!typeArgs.IsNull()) {
1233 jsobj.AddProperty("typeArguments", typeArgs);
1234 }
1235}
1236
1237void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
1238 JSONObject jsobj(stream);
1239 PrintSharedInstanceJSON(&jsobj, ref);
1240 jsobj.AddProperty("kind", "TypeRef");
1241 jsobj.AddServiceId(*this);
1242 const String& user_name = String::Handle(UserVisibleName());
1243 const String& vm_name = String::Handle(Name());
1244 AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
1245 if (ref) {
1246 return;
1247 }
1248 jsobj.AddProperty("targetType", AbstractType::Handle(type()));
1249}
1250
1251void TypeParameter::PrintJSONImpl(JSONStream* stream, bool ref) const {
1252 JSONObject jsobj(stream);
1253 PrintSharedInstanceJSON(&jsobj, ref);
1254 jsobj.AddProperty("kind", "TypeParameter");
1255 jsobj.AddServiceId(*this);
1256 const String& user_name = String::Handle(UserVisibleName());
1257 const String& vm_name = String::Handle(Name());
1258 AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
1259 const Class& param_cls = Class::Handle(parameterized_class());
1260 jsobj.AddProperty("parameterizedClass", param_cls);
1261 if (ref) {
1262 return;
1263 }
1264 jsobj.AddProperty("parameterIndex", index());
1265 const AbstractType& upper_bound = AbstractType::Handle(bound());
1266 jsobj.AddProperty("bound", upper_bound);
1267}
1268
1269void Number::PrintJSONImpl(JSONStream* stream, bool ref) const {
1270 UNREACHABLE();
1271}
1272
1273void Integer::PrintJSONImpl(JSONStream* stream, bool ref) const {
1274 JSONObject jsobj(stream);
1275 PrintSharedInstanceJSON(&jsobj, ref);
1276 jsobj.AddProperty("kind", "Int");
1277 jsobj.AddServiceId(*this);
1278 jsobj.AddProperty("valueAsString", ToCString());
1279}
1280
1281void Smi::PrintJSONImpl(JSONStream* stream, bool ref) const {
1282 JSONObject jsobj(stream);
1283 PrintSharedInstanceJSON(&jsobj, ref);
1284 jsobj.AddProperty("kind", "Int");
1285 jsobj.AddFixedServiceId("objects/int-%" Pd "", Value());
1286 jsobj.AddPropertyF("valueAsString", "%" Pd "", Value());
1287}
1288
1289void Mint::PrintJSONImpl(JSONStream* stream, bool ref) const {
1290 Integer::PrintJSONImpl(stream, ref);
1291}
1292
1293void Double::PrintJSONImpl(JSONStream* stream, bool ref) const {
1294 JSONObject jsobj(stream);
1295 PrintSharedInstanceJSON(&jsobj, ref);
1296 jsobj.AddProperty("kind", "Double");
1297 jsobj.AddServiceId(*this);
1298 jsobj.AddProperty("valueAsString", ToCString());
1299}
1300
1301void String::PrintJSONImpl(JSONStream* stream, bool ref) const {
1302 JSONObject jsobj(stream);
1303 if (raw() == Symbols::OptimizedOut().raw()) {
1304 // TODO(turnidge): This is a hack. The user could have this
1305 // special string in their program. Fixing this involves updating
1306 // the debugging api a bit.
1307 jsobj.AddProperty("type", "Sentinel");
1308 jsobj.AddProperty("kind", "OptimizedOut");
1309 jsobj.AddProperty("valueAsString", "<optimized out>");
1310 return;
1311 }
1312 PrintSharedInstanceJSON(&jsobj, ref);
1313 jsobj.AddProperty("kind", "String");
1314 jsobj.AddServiceId(*this);
1315 jsobj.AddProperty("length", Length());
1316 if (ref) {
1317 // String refs always truncate to a fixed count;
1318 const intptr_t kFixedCount = 128;
1319 if (jsobj.AddPropertyStr("valueAsString", *this, 0, kFixedCount)) {
1320 jsobj.AddProperty("count", kFixedCount);
1321 jsobj.AddProperty("valueAsStringIsTruncated", true);
1322 }
1323 return;
1324 }
1325
1326 intptr_t offset;
1327 intptr_t count;
1328 stream->ComputeOffsetAndCount(Length(), &offset, &count);
1329 if (offset > 0) {
1330 jsobj.AddProperty("offset", offset);
1331 }
1332 if (count < Length()) {
1333 jsobj.AddProperty("count", count);
1334 }
1335 jsobj.AddPropertyStr("valueAsString", *this, offset, count);
1336}
1337
1338void Bool::PrintJSONImpl(JSONStream* stream, bool ref) const {
1339 const char* str = ToCString();
1340 JSONObject jsobj(stream);
1341 PrintSharedInstanceJSON(&jsobj, ref);
1342 jsobj.AddProperty("kind", "Bool");
1343 jsobj.AddFixedServiceId("objects/bool-%s", str);
1344 jsobj.AddPropertyF("valueAsString", "%s", str);
1345}
1346
1347void Array::PrintJSONImpl(JSONStream* stream, bool ref) const {
1348 JSONObject jsobj(stream);
1349 PrintSharedInstanceJSON(&jsobj, ref);
1350 jsobj.AddProperty("kind", "List");
1351 jsobj.AddServiceId(*this);
1352 jsobj.AddProperty("length", Length());
1353 if (ref) {
1354 return;
1355 }
1356 intptr_t offset;
1357 intptr_t count;
1358 stream->ComputeOffsetAndCount(Length(), &offset, &count);
1359 if (offset > 0) {
1360 jsobj.AddProperty("offset", offset);
1361 }
1362 if (count < Length()) {
1363 jsobj.AddProperty("count", count);
1364 }
1365 intptr_t limit = offset + count;
1366 ASSERT(limit <= Length());
1367 {
1368 JSONArray jsarr(&jsobj, "elements");
1369 Object& element = Object::Handle();
1370 for (intptr_t index = offset; index < limit; index++) {
1371 element = At(index);
1372 jsarr.AddValue(element);
1373 }
1374 }
1375}
1376
1377void GrowableObjectArray::PrintJSONImpl(JSONStream* stream, bool ref) const {
1378 JSONObject jsobj(stream);
1379 PrintSharedInstanceJSON(&jsobj, ref);
1380 jsobj.AddProperty("kind", "List");
1381 jsobj.AddServiceId(*this);
1382 jsobj.AddProperty("length", Length());
1383 if (ref) {
1384 return;
1385 }
1386 intptr_t offset;
1387 intptr_t count;
1388 stream->ComputeOffsetAndCount(Length(), &offset, &count);
1389 if (offset > 0) {
1390 jsobj.AddProperty("offset", offset);
1391 }
1392 if (count < Length()) {
1393 jsobj.AddProperty("count", count);
1394 }
1395 intptr_t limit = offset + count;
1396 ASSERT(limit <= Length());
1397 {
1398 JSONArray jsarr(&jsobj, "elements");
1399 Object& element = Object::Handle();
1400 for (intptr_t index = offset; index < limit; index++) {
1401 element = At(index);
1402 jsarr.AddValue(element);
1403 }
1404 }
1405}
1406
1407void LinkedHashMap::PrintJSONImpl(JSONStream* stream, bool ref) const {
1408 JSONObject jsobj(stream);
1409 PrintSharedInstanceJSON(&jsobj, ref);
1410 jsobj.AddProperty("kind", "Map");
1411 jsobj.AddServiceId(*this);
1412 jsobj.AddProperty("length", Length());
1413 if (ref) {
1414 return;
1415 }
1416 intptr_t offset;
1417 intptr_t count;
1418 stream->ComputeOffsetAndCount(Length(), &offset, &count);
1419 if (offset > 0) {
1420 jsobj.AddProperty("offset", offset);
1421 }
1422 if (count < Length()) {
1423 jsobj.AddProperty("count", count);
1424 }
1425 intptr_t limit = offset + count;
1426 ASSERT(limit <= Length());
1427 {
1428 JSONArray jsarr(&jsobj, "associations");
1429 Object& object = Object::Handle();
1430 LinkedHashMap::Iterator iterator(*this);
1431 int i = 0;
1432 while (iterator.MoveNext() && i < limit) {
1433 if (i >= offset) {
1434 JSONObject jsassoc(&jsarr);
1435 object = iterator.CurrentKey();
1436 jsassoc.AddProperty("key", object);
1437 object = iterator.CurrentValue();
1438 jsassoc.AddProperty("value", object);
1439 }
1440 i++;
1441 }
1442 }
1443}
1444
1445void Float32x4::PrintJSONImpl(JSONStream* stream, bool ref) const {
1446 JSONObject jsobj(stream);
1447 PrintSharedInstanceJSON(&jsobj, ref);
1448 jsobj.AddProperty("kind", "Float32x4");
1449 jsobj.AddServiceId(*this);
1450 jsobj.AddProperty("valueAsString", ToCString());
1451}
1452
1453void Int32x4::PrintJSONImpl(JSONStream* stream, bool ref) const {
1454 JSONObject jsobj(stream);
1455 PrintSharedInstanceJSON(&jsobj, ref);
1456 jsobj.AddProperty("kind", "Int32x4");
1457 jsobj.AddServiceId(*this);
1458 jsobj.AddProperty("valueAsString", ToCString());
1459}
1460
1461void Float64x2::PrintJSONImpl(JSONStream* stream, bool ref) const {
1462 JSONObject jsobj(stream);
1463 PrintSharedInstanceJSON(&jsobj, ref);
1464 jsobj.AddProperty("kind", "Float64x2");
1465 jsobj.AddServiceId(*this);
1466 jsobj.AddProperty("valueAsString", ToCString());
1467}
1468
1469void TypedDataBase::PrintJSONImpl(JSONStream* stream, bool ref) const {
1470 UNREACHABLE();
1471}
1472
1473void TypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
1474 JSONObject jsobj(stream);
1475 PrintSharedInstanceJSON(&jsobj, ref);
1476 const Class& cls = Class::Handle(clazz());
1477 const char* kind = cls.UserVisibleNameCString();
1478 jsobj.AddProperty("kind", kind);
1479 jsobj.AddServiceId(*this);
1480 jsobj.AddProperty("length", Length());
1481 if (ref) {
1482 return;
1483 }
1484 intptr_t offset;
1485 intptr_t count;
1486 stream->ComputeOffsetAndCount(Length(), &offset, &count);
1487 if (offset > 0) {
1488 jsobj.AddProperty("offset", offset);
1489 }
1490 if (count < Length()) {
1491 jsobj.AddProperty("count", count);
1492 }
1493 if (count == 0) {
1494 jsobj.AddProperty("bytes", "");
1495 } else {
1496 NoSafepointScope no_safepoint;
1497 jsobj.AddPropertyBase64("bytes",
1498 reinterpret_cast<const uint8_t*>(
1499 DataAddr(offset * ElementSizeInBytes())),
1500 count * ElementSizeInBytes());
1501 }
1502}
1503
1504void TypedDataView::PrintJSONImpl(JSONStream* stream, bool ref) const {
1505 Instance::PrintJSONImpl(stream, ref);
1506}
1507
1508void ExternalTypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
1509 JSONObject jsobj(stream);
1510 PrintSharedInstanceJSON(&jsobj, ref);
1511 const Class& cls = Class::Handle(clazz());
1512 const char* kind = cls.UserVisibleNameCString();
1513 jsobj.AddProperty("kind", kind);
1514 jsobj.AddServiceId(*this);
1515 jsobj.AddProperty("length", Length());
1516 if (ref) {
1517 return;
1518 }
1519 intptr_t offset;
1520 intptr_t count;
1521 stream->ComputeOffsetAndCount(Length(), &offset, &count);
1522 if (offset > 0) {
1523 jsobj.AddProperty("offset", offset);
1524 }
1525 if (count < Length()) {
1526 jsobj.AddProperty("count", count);
1527 }
1528 if (count == 0) {
1529 jsobj.AddProperty("bytes", "");
1530 } else {
1531 NoSafepointScope no_safepoint;
1532 jsobj.AddPropertyBase64("bytes",
1533 reinterpret_cast<const uint8_t*>(
1534 DataAddr(offset * ElementSizeInBytes())),
1535 count * ElementSizeInBytes());
1536 }
1537}
1538
1539void Pointer::PrintJSONImpl(JSONStream* stream, bool ref) const {
1540 // TODO(dacoharkes): what is the JSONStream used for?
1541 // should it fail because it's not supported?
1542 // or should it print something reasonable as default?
1543 Instance::PrintJSONImpl(stream, ref);
1544}
1545
1546void DynamicLibrary::PrintJSONImpl(JSONStream* stream, bool ref) const {
1547 // TODO(dacoharkes): what is the JSONStream used for?
1548 // should it fail because it's not supported?
1549 // or should it print something reasonable as default?
1550 Instance::PrintJSONImpl(stream, ref);
1551}
1552
1553void Capability::PrintJSONImpl(JSONStream* stream, bool ref) const {
1554 Instance::PrintJSONImpl(stream, ref);
1555}
1556
1557void ReceivePort::PrintJSONImpl(JSONStream* stream, bool ref) const {
1558 Instance::PrintJSONImpl(stream, ref);
1559}
1560
1561void SendPort::PrintJSONImpl(JSONStream* stream, bool ref) const {
1562 Instance::PrintJSONImpl(stream, ref);
1563}
1564
1565void TransferableTypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
1566 Instance::PrintJSONImpl(stream, ref);
1567}
1568
1569void ClosureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
1570 Object::PrintJSONImpl(stream, ref);
1571}
1572
1573void SignatureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
1574 Object::PrintJSONImpl(stream, ref);
1575}
1576
1577void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
1578 Instance::PrintJSONImpl(stream, ref);
1579}
1580
1581void StackTrace::PrintJSONImpl(JSONStream* stream, bool ref) const {
1582 JSONObject jsobj(stream);
1583 PrintSharedInstanceJSON(&jsobj, ref);
1584 jsobj.AddProperty("kind", "StackTrace");
1585 jsobj.AddServiceId(*this);
1586 jsobj.AddProperty("valueAsString", ToCString());
1587}
1588
1589void RegExp::PrintJSONImpl(JSONStream* stream, bool ref) const {
1590 JSONObject jsobj(stream);
1591 PrintSharedInstanceJSON(&jsobj, ref);
1592 jsobj.AddProperty("kind", "RegExp");
1593 jsobj.AddServiceId(*this);
1594
1595 jsobj.AddProperty("pattern", String::Handle(pattern()));
1596
1597 if (ref) {
1598 return;
1599 }
1600
1601 jsobj.AddProperty("isCaseSensitive", !flags().IgnoreCase());
1602 jsobj.AddProperty("isMultiLine", flags().IsMultiLine());
1603
1604 if (!FLAG_interpret_irregexp) {
1605 Function& func = Function::Handle();
1606 func = function(kOneByteStringCid, /*sticky=*/false);
1607 jsobj.AddProperty("_oneByteFunction", func);
1608 func = function(kTwoByteStringCid, /*sticky=*/false);
1609 jsobj.AddProperty("_twoByteFunction", func);
1610 func = function(kExternalOneByteStringCid, /*sticky=*/false);
1611 jsobj.AddProperty("_externalOneByteFunction", func);
1612 func = function(kExternalTwoByteStringCid, /*sticky=*/false);
1613 jsobj.AddProperty("_externalTwoByteFunction", func);
1614 func = function(kOneByteStringCid, /*sticky=*/true);
1615 jsobj.AddProperty("_oneByteFunctionSticky", func);
1616 func = function(kTwoByteStringCid, /*sticky=*/true);
1617 jsobj.AddProperty("_twoByteFunctionSticky", func);
1618 func = function(kExternalOneByteStringCid, /*sticky=*/true);
1619 jsobj.AddProperty("_externalOneByteFunctionSticky", func);
1620 func = function(kExternalTwoByteStringCid, /*sticky=*/true);
1621 jsobj.AddProperty("_externalTwoByteFunctionSticky", func);
1622 } else {
1623 TypedData& bc = TypedData::Handle();
1624 bc = bytecode(/*is_one_byte=*/true, /*sticky=*/false);
1625 jsobj.AddProperty("_oneByteBytecode", bc);
1626 bc = bytecode(/*is_one_byte=*/false, /*sticky=*/false);
1627 jsobj.AddProperty("_twoByteBytecode", bc);
1628 bc = bytecode(/*is_one_byte=*/true, /*sticky=*/true);
1629 jsobj.AddProperty("_oneByteBytecodeSticky", bc);
1630 bc = bytecode(/*is_one_byte=*/false, /*sticky=*/true);
1631 jsobj.AddProperty("_twoByteBytecodeSticky", bc);
1632 }
1633}
1634
1635void WeakProperty::PrintJSONImpl(JSONStream* stream, bool ref) const {
1636 JSONObject jsobj(stream);
1637 PrintSharedInstanceJSON(&jsobj, ref);
1638 jsobj.AddProperty("kind", "WeakProperty");
1639 jsobj.AddServiceId(*this);
1640 if (ref) {
1641 return;
1642 }
1643
1644 const Object& key_handle = Object::Handle(key());
1645 jsobj.AddProperty("propertyKey", key_handle);
1646 const Object& value_handle = Object::Handle(value());
1647 jsobj.AddProperty("propertyValue", value_handle);
1648}
1649
1650void MirrorReference::PrintJSONImpl(JSONStream* stream, bool ref) const {
1651 JSONObject jsobj(stream);
1652 PrintSharedInstanceJSON(&jsobj, ref);
1653 jsobj.AddProperty("kind", "MirrorReference");
1654 jsobj.AddServiceId(*this);
1655
1656 if (ref) {
1657 return;
1658 }
1659
1660 const Object& referent_handle = Object::Handle(referent());
1661 jsobj.AddProperty("mirrorReferent", referent_handle);
1662}
1663
1664void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
1665 Instance::PrintJSONImpl(stream, ref);
1666}
1667
1668void FutureOr::PrintJSONImpl(JSONStream* stream, bool ref) const {
1669 Instance::PrintJSONImpl(stream, ref);
1670}
1671
1672#endif
1673
1674} // namespace dart
1675