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 | |
13 | namespace dart { |
14 | |
15 | #ifndef PRODUCT |
16 | |
17 | static 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 | |
26 | void 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 | |
53 | void 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 | |
62 | void 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 | |
74 | void 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 | |
169 | void 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 | |
223 | void PatchClass::PrintJSONImpl(JSONStream* stream, bool ref) const { |
224 | Object::PrintJSONImpl(stream, ref); |
225 | } |
226 | |
227 | static 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 | |
282 | void 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 | |
359 | void RedirectionData::PrintJSONImpl(JSONStream* stream, bool ref) const { |
360 | Object::PrintJSONImpl(stream, ref); |
361 | } |
362 | |
363 | void FfiTrampolineData::PrintJSONImpl(JSONStream* stream, bool ref) const { |
364 | Object::PrintJSONImpl(stream, ref); |
365 | } |
366 | |
367 | void 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. |
431 | void 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 | |
491 | void 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 | |
662 | void LibraryPrefix::PrintJSONImpl(JSONStream* stream, bool ref) const { |
663 | Object::PrintJSONImpl(stream, ref); |
664 | } |
665 | |
666 | void Namespace::PrintJSONImpl(JSONStream* stream, bool ref) const { |
667 | Object::PrintJSONImpl(stream, ref); |
668 | } |
669 | |
670 | void KernelProgramInfo::PrintJSONImpl(JSONStream* stream, bool ref) const { |
671 | Object::PrintJSONImpl(stream, ref); |
672 | } |
673 | |
674 | void 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 | |
683 | void InstructionsSection::PrintJSONImpl(JSONStream* stream, bool ref) const { |
684 | Object::PrintJSONImpl(stream, ref); |
685 | } |
686 | |
687 | void 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 | |
697 | void 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 | |
746 | void 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 | |
767 | void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const { |
768 | JSONObject jsobj(stream); |
769 | PrintToJSONObject(&jsobj, ref); |
770 | } |
771 | |
772 | void CodeSourceMap::PrintJSONImpl(JSONStream* stream, bool ref) const { |
773 | Object::PrintJSONImpl(stream, ref); |
774 | } |
775 | |
776 | void CompressedStackMaps::PrintJSONImpl(JSONStream* stream, bool ref) const { |
777 | Object::PrintJSONImpl(stream, ref); |
778 | } |
779 | |
780 | void 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 | |
806 | void ExceptionHandlers::PrintJSONImpl(JSONStream* stream, bool ref) const { |
807 | Object::PrintJSONImpl(stream, ref); |
808 | } |
809 | |
810 | void ParameterTypeCheck::PrintJSONImpl(JSONStream* stream, bool ref) const { |
811 | Object::PrintJSONImpl(stream, ref); |
812 | } |
813 | |
814 | void 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 | |
826 | void 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 | |
838 | void 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 | |
849 | void CallSiteData::PrintJSONImpl(JSONStream* stream, bool ref) const { |
850 | UNREACHABLE(); |
851 | } |
852 | |
853 | void 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 | |
867 | void 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 | |
894 | void 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 | |
958 | void 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 | |
999 | void 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 | |
1026 | void ContextScope::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1027 | Object::PrintJSONImpl(stream, ref); |
1028 | } |
1029 | |
1030 | void 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 | |
1044 | void 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 | |
1054 | void 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 | |
1068 | void Error::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1069 | UNREACHABLE(); |
1070 | } |
1071 | |
1072 | void 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 | |
1080 | void 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 | |
1088 | void 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 | |
1104 | void 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 | |
1113 | void 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 | |
1164 | void 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 | |
1208 | void AbstractType::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1209 | UNREACHABLE(); |
1210 | } |
1211 | |
1212 | void 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 | |
1237 | void 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 | |
1251 | void 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 | |
1269 | void Number::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1270 | UNREACHABLE(); |
1271 | } |
1272 | |
1273 | void 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 | |
1281 | void 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 | |
1289 | void Mint::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1290 | Integer::PrintJSONImpl(stream, ref); |
1291 | } |
1292 | |
1293 | void 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 | |
1301 | void 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 | |
1338 | void 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 | |
1347 | void 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 | |
1377 | void 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 | |
1407 | void 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 | |
1445 | void 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 | |
1453 | void 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 | |
1461 | void 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 | |
1469 | void TypedDataBase::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1470 | UNREACHABLE(); |
1471 | } |
1472 | |
1473 | void 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 | |
1504 | void TypedDataView::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1505 | Instance::PrintJSONImpl(stream, ref); |
1506 | } |
1507 | |
1508 | void 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 | |
1539 | void 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 | |
1546 | void 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 | |
1553 | void Capability::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1554 | Instance::PrintJSONImpl(stream, ref); |
1555 | } |
1556 | |
1557 | void ReceivePort::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1558 | Instance::PrintJSONImpl(stream, ref); |
1559 | } |
1560 | |
1561 | void SendPort::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1562 | Instance::PrintJSONImpl(stream, ref); |
1563 | } |
1564 | |
1565 | void TransferableTypedData::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1566 | Instance::PrintJSONImpl(stream, ref); |
1567 | } |
1568 | |
1569 | void ClosureData::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1570 | Object::PrintJSONImpl(stream, ref); |
1571 | } |
1572 | |
1573 | void SignatureData::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1574 | Object::PrintJSONImpl(stream, ref); |
1575 | } |
1576 | |
1577 | void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1578 | Instance::PrintJSONImpl(stream, ref); |
1579 | } |
1580 | |
1581 | void 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 | |
1589 | void 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 | |
1635 | void 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 | |
1650 | void 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 | |
1664 | void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1665 | Instance::PrintJSONImpl(stream, ref); |
1666 | } |
1667 | |
1668 | void FutureOr::PrintJSONImpl(JSONStream* stream, bool ref) const { |
1669 | Instance::PrintJSONImpl(stream, ref); |
1670 | } |
1671 | |
1672 | #endif |
1673 | |
1674 | } // namespace dart |
1675 | |