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

Side by Side Diff: runtime/vm/object.cc

Issue 1289933002: Trace CHA optimizations (where, when, why) (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: s Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/il_printer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 "Huge method cutoff in tokens: Disables optimizations for huge methods."); 55 "Huge method cutoff in tokens: Disables optimizations for huge methods.");
56 DEFINE_FLAG(bool, overlap_type_arguments, true, 56 DEFINE_FLAG(bool, overlap_type_arguments, true,
57 "When possible, partially or fully overlap the type arguments of a type " 57 "When possible, partially or fully overlap the type arguments of a type "
58 "with the type arguments of its super type."); 58 "with the type arguments of its super type.");
59 DEFINE_FLAG(bool, show_internal_names, false, 59 DEFINE_FLAG(bool, show_internal_names, false,
60 "Show names of internal classes (e.g. \"OneByteString\") in error messages " 60 "Show names of internal classes (e.g. \"OneByteString\") in error messages "
61 "instead of showing the corresponding interface names (e.g. \"String\")"); 61 "instead of showing the corresponding interface names (e.g. \"String\")");
62 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, 62 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
63 "Throw an exception when the result of an integer calculation will not " 63 "Throw an exception when the result of an integer calculation will not "
64 "fit into a javascript integer."); 64 "fit into a javascript integer.");
65 DEFINE_FLAG(bool, trace_cha, false, "Trace CHA operations");
65 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids."); 66 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
66 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache"); 67 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
67 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids."); 68 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
68 69
69 DECLARE_FLAG(charp, coverage_dir); 70 DECLARE_FLAG(charp, coverage_dir);
70 DECLARE_FLAG(bool, load_deferred_eagerly); 71 DECLARE_FLAG(bool, load_deferred_eagerly);
71 DECLARE_FLAG(bool, show_invisible_frames); 72 DECLARE_FLAG(bool, show_invisible_frames);
72 DECLARE_FLAG(bool, trace_compiler); 73 DECLARE_FLAG(bool, trace_compiler);
73 DECLARE_FLAG(bool, trace_deoptimization); 74 DECLARE_FLAG(bool, trace_deoptimization);
74 DECLARE_FLAG(bool, trace_deoptimization_verbose); 75 DECLARE_FLAG(bool, trace_deoptimization_verbose);
(...skipping 1527 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 Context::New(0, Heap::kOld)); 1603 Context::New(0, Heap::kOld));
1603 object_store->set_empty_context(context); 1604 object_store->set_empty_context(context);
1604 1605
1605 #endif // defined(DART_NO_SNAPSHOT). 1606 #endif // defined(DART_NO_SNAPSHOT).
1606 1607
1607 return Error::null(); 1608 return Error::null();
1608 } 1609 }
1609 1610
1610 1611
1611 void Object::Print() const { 1612 void Object::Print() const {
1612 OS::Print("%s\n", ToCString()); 1613 ISL_Print("%s\n", ToCString());
1613 } 1614 }
1614 1615
1615 1616
1616 static void AddNameProperties(JSONObject* jsobj, 1617 static void AddNameProperties(JSONObject* jsobj,
1617 const String& name, 1618 const String& name,
1618 const String& vm_name) { 1619 const String& vm_name) {
1619 jsobj->AddProperty("name", name.ToCString()); 1620 jsobj->AddProperty("name", name.ToCString());
1620 if (!name.Equals(vm_name)) { 1621 if (!name.Equals(vm_name)) {
1621 jsobj->AddProperty("_vmName", vm_name.ToCString()); 1622 jsobj->AddProperty("_vmName", vm_name.ToCString());
1622 } 1623 }
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 } 2709 }
2709 2710
2710 virtual void UpdateArrayTo(const Array& value) { 2711 virtual void UpdateArrayTo(const Array& value) {
2711 // TODO(fschneider): Fails for classes in the VM isolate. 2712 // TODO(fschneider): Fails for classes in the VM isolate.
2712 cls_.set_cha_codes(value); 2713 cls_.set_cha_codes(value);
2713 } 2714 }
2714 2715
2715 virtual void ReportDeoptimization(const Code& code) { 2716 virtual void ReportDeoptimization(const Code& code) {
2716 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { 2717 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
2717 Function& function = Function::Handle(code.function()); 2718 Function& function = Function::Handle(code.function());
2718 OS::PrintErr("Deoptimizing %s because CHA optimized (%s).\n", 2719 ISL_Print("Deoptimizing %s because CHA optimized (%s).\n",
2719 function.ToFullyQualifiedCString(), 2720 function.ToFullyQualifiedCString(),
2720 cls_.ToCString()); 2721 cls_.ToCString());
2721 } 2722 }
2722 } 2723 }
2723 2724
2724 virtual void ReportSwitchingCode(const Code& code) { 2725 virtual void ReportSwitchingCode(const Code& code) {
2725 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { 2726 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
2726 Function& function = Function::Handle(code.function()); 2727 Function& function = Function::Handle(code.function());
2727 OS::PrintErr("Switching %s to unoptimized code because CHA invalid" 2728 ISL_Print("Switching %s to unoptimized code because CHA invalid"
2728 " (%s)\n", 2729 " (%s)\n",
2729 function.ToFullyQualifiedCString(), 2730 function.ToFullyQualifiedCString(),
2730 cls_.ToCString()); 2731 cls_.ToCString());
2731 } 2732 }
2732 } 2733 }
2733 2734
2734 private: 2735 private:
2735 const Class& cls_; 2736 const Class& cls_;
2736 DISALLOW_COPY_AND_ASSIGN(CHACodeArray); 2737 DISALLOW_COPY_AND_ASSIGN(CHACodeArray);
2737 }; 2738 };
2738 2739
2739 2740
2740 void Class::RegisterCHACode(const Code& code) { 2741 void Class::RegisterCHACode(const Code& code) {
2742 if (FLAG_trace_cha) {
2743 ISL_Print("RegisterCHACode %s class %s\n",
2744 Function::Handle(code.function()).ToQualifiedCString(), ToCString());
2745 }
2741 ASSERT(code.is_optimized()); 2746 ASSERT(code.is_optimized());
2742 CHACodeArray a(*this); 2747 CHACodeArray a(*this);
2743 a.Register(code); 2748 a.Register(code);
2744 } 2749 }
2745 2750
2746 2751
2747 void Class::DisableCHAOptimizedCode() { 2752 void Class::DisableCHAOptimizedCode() {
2748 CHACodeArray a(*this); 2753 CHACodeArray a(*this);
2749 a.DisableCode(); 2754 a.DisableCode();
2750 } 2755 }
(...skipping 2461 matching lines...) Expand 10 before | Expand all | Expand 10 after
5212 5217
5213 5218
5214 void Function::SwitchToUnoptimizedCode() const { 5219 void Function::SwitchToUnoptimizedCode() const {
5215 ASSERT(HasOptimizedCode()); 5220 ASSERT(HasOptimizedCode());
5216 Thread* thread = Thread::Current(); 5221 Thread* thread = Thread::Current();
5217 Isolate* isolate = thread->isolate(); 5222 Isolate* isolate = thread->isolate();
5218 Zone* zone = thread->zone(); 5223 Zone* zone = thread->zone();
5219 const Code& current_code = Code::Handle(zone, CurrentCode()); 5224 const Code& current_code = Code::Handle(zone, CurrentCode());
5220 5225
5221 if (FLAG_trace_deoptimization_verbose) { 5226 if (FLAG_trace_deoptimization_verbose) {
5222 OS::Print("Disabling optimized code: '%s' entry: %#" Px "\n", 5227 ISL_Print("Disabling optimized code: '%s' entry: %#" Px "\n",
5223 ToFullyQualifiedCString(), 5228 ToFullyQualifiedCString(),
5224 current_code.EntryPoint()); 5229 current_code.EntryPoint());
5225 } 5230 }
5226 // Patch entry of the optimized code. 5231 // Patch entry of the optimized code.
5227 CodePatcher::PatchEntry(current_code); 5232 CodePatcher::PatchEntry(current_code);
5228 const Error& error = Error::Handle(zone, 5233 const Error& error = Error::Handle(zone,
5229 Compiler::EnsureUnoptimizedCode(thread, *this)); 5234 Compiler::EnsureUnoptimizedCode(thread, *this));
5230 if (!error.IsNull()) { 5235 if (!error.IsNull()) {
5231 Exceptions::PropagateError(error); 5236 Exceptions::PropagateError(error);
5232 } 5237 }
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after
6890 6895
6891 6896
6892 bool Function::CheckSourceFingerprint(const char* prefix, int32_t fp) const { 6897 bool Function::CheckSourceFingerprint(const char* prefix, int32_t fp) const {
6893 if (SourceFingerprint() != fp) { 6898 if (SourceFingerprint() != fp) {
6894 const bool recalculatingFingerprints = false; 6899 const bool recalculatingFingerprints = false;
6895 if (recalculatingFingerprints) { 6900 if (recalculatingFingerprints) {
6896 // This output can be copied into a file, then used with sed 6901 // This output can be copied into a file, then used with sed
6897 // to replace the old values. 6902 // to replace the old values.
6898 // sed -i .bak -f /tmp/newkeys runtime/vm/method_recognizer.h 6903 // sed -i .bak -f /tmp/newkeys runtime/vm/method_recognizer.h
6899 // sed -i .bak -f /tmp/newkeys runtime/vm/flow_graph_builder.h 6904 // sed -i .bak -f /tmp/newkeys runtime/vm/flow_graph_builder.h
6900 OS::Print("s/V(%s, %d)/V(%s, %d)/\n", 6905 ISL_Print("s/V(%s, %d)/V(%s, %d)/\n",
6901 prefix, fp, prefix, SourceFingerprint()); 6906 prefix, fp, prefix, SourceFingerprint());
6902 } else { 6907 } else {
6903 OS::Print("FP mismatch while recognizing method %s:" 6908 ISL_Print("FP mismatch while recognizing method %s:"
6904 " expecting %d found %d\n", 6909 " expecting %d found %d\n",
6905 ToFullyQualifiedCString(), 6910 ToFullyQualifiedCString(),
6906 fp, 6911 fp,
6907 SourceFingerprint()); 6912 SourceFingerprint());
6908 return false; 6913 return false;
6909 } 6914 }
6910 } 6915 }
6911 return true; 6916 return true;
6912 } 6917 }
6913 6918
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
7494 : WeakCodeReferences(Array::Handle(field.dependent_code())), 7499 : WeakCodeReferences(Array::Handle(field.dependent_code())),
7495 field_(field) {} 7500 field_(field) {}
7496 7501
7497 virtual void UpdateArrayTo(const Array& value) { 7502 virtual void UpdateArrayTo(const Array& value) {
7498 field_.set_dependent_code(value); 7503 field_.set_dependent_code(value);
7499 } 7504 }
7500 7505
7501 virtual void ReportDeoptimization(const Code& code) { 7506 virtual void ReportDeoptimization(const Code& code) {
7502 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { 7507 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
7503 Function& function = Function::Handle(code.function()); 7508 Function& function = Function::Handle(code.function());
7504 OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", 7509 ISL_Print("Deoptimizing %s because guard on field %s failed.\n",
7505 function.ToFullyQualifiedCString(), 7510 function.ToFullyQualifiedCString(), field_.ToCString());
7506 field_.ToCString());
7507 } 7511 }
7508 } 7512 }
7509 7513
7510 virtual void ReportSwitchingCode(const Code& code) { 7514 virtual void ReportSwitchingCode(const Code& code) {
7511 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { 7515 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
7512 Function& function = Function::Handle(code.function()); 7516 Function& function = Function::Handle(code.function());
7513 OS::PrintErr("Switching %s to unoptimized code because guard" 7517 ISL_Print("Switching %s to unoptimized code because guard"
7514 " on field %s was violated.\n", 7518 " on field %s was violated.\n",
7515 function.ToFullyQualifiedCString(), 7519 function.ToFullyQualifiedCString(),
7516 field_.ToCString()); 7520 field_.ToCString());
7517 } 7521 }
7518 } 7522 }
7519 7523
7520 private: 7524 private:
7521 const Field& field_; 7525 const Field& field_;
7522 DISALLOW_COPY_AND_ASSIGN(FieldDependentArray); 7526 DISALLOW_COPY_AND_ASSIGN(FieldDependentArray);
7523 }; 7527 };
7524 7528
7525 7529
7526 void Field::RegisterDependentCode(const Code& code) const { 7530 void Field::RegisterDependentCode(const Code& code) const {
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
7671 // Start tracking length if needed. 7675 // Start tracking length if needed.
7672 ASSERT((guarded_list_length() == Field::kUnknownFixedLength) || 7676 ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
7673 (guarded_list_length() == Field::kNoFixedLength)); 7677 (guarded_list_length() == Field::kNoFixedLength));
7674 if (needs_length_check()) { 7678 if (needs_length_check()) {
7675 ASSERT(guarded_list_length() == Field::kUnknownFixedLength); 7679 ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
7676 set_guarded_list_length(GetListLength(value)); 7680 set_guarded_list_length(GetListLength(value));
7677 InitializeGuardedListLengthInObjectOffset(); 7681 InitializeGuardedListLengthInObjectOffset();
7678 } 7682 }
7679 7683
7680 if (FLAG_trace_field_guards) { 7684 if (FLAG_trace_field_guards) {
7681 OS::Print(" => %s\n", GuardedPropertiesAsCString()); 7685 ISL_Print(" => %s\n", GuardedPropertiesAsCString());
7682 } 7686 }
7683 7687
7684 return false; 7688 return false;
7685 } 7689 }
7686 7690
7687 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) { 7691 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
7688 // Class id of the assigned value matches expected class id and nullability. 7692 // Class id of the assigned value matches expected class id and nullability.
7689 7693
7690 // If we are tracking length check if it has matches. 7694 // If we are tracking length check if it has matches.
7691 if (needs_length_check() && 7695 if (needs_length_check() &&
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
7726 return true; 7730 return true;
7727 } 7731 }
7728 7732
7729 7733
7730 void Field::RecordStore(const Object& value) const { 7734 void Field::RecordStore(const Object& value) const {
7731 if (!FLAG_use_field_guards) { 7735 if (!FLAG_use_field_guards) {
7732 return; 7736 return;
7733 } 7737 }
7734 7738
7735 if (FLAG_trace_field_guards) { 7739 if (FLAG_trace_field_guards) {
7736 OS::Print("Store %s %s <- %s\n", 7740 ISL_Print("Store %s %s <- %s\n",
7737 ToCString(), 7741 ToCString(),
7738 GuardedPropertiesAsCString(), 7742 GuardedPropertiesAsCString(),
7739 value.ToCString()); 7743 value.ToCString());
7740 } 7744 }
7741 7745
7742 if (UpdateGuardedCidAndLength(value)) { 7746 if (UpdateGuardedCidAndLength(value)) {
7743 if (FLAG_trace_field_guards) { 7747 if (FLAG_trace_field_guards) {
7744 OS::Print(" => %s\n", GuardedPropertiesAsCString()); 7748 ISL_Print(" => %s\n", GuardedPropertiesAsCString());
7745 } 7749 }
7746 7750
7747 DeoptimizeDependentCode(); 7751 DeoptimizeDependentCode();
7748 } 7752 }
7749 } 7753 }
7750 7754
7751 7755
7752 void LiteralToken::set_literal(const String& literal) const { 7756 void LiteralToken::set_literal(const String& literal) const {
7753 StorePointer(&raw_ptr()->literal_, literal.raw()); 7757 StorePointer(&raw_ptr()->literal_, literal.raw());
7754 } 7758 }
(...skipping 2693 matching lines...) Expand 10 before | Expand all | Expand 10 after
10448 virtual void ReportDeoptimization(const Code& code) { 10452 virtual void ReportDeoptimization(const Code& code) {
10449 // This gets called when the code object is on the stack 10453 // This gets called when the code object is on the stack
10450 // while nuking code that depends on a prefix. We don't expect 10454 // while nuking code that depends on a prefix. We don't expect
10451 // this to happen, so make sure we die loudly if we find 10455 // this to happen, so make sure we die loudly if we find
10452 // ourselves here. 10456 // ourselves here.
10453 UNIMPLEMENTED(); 10457 UNIMPLEMENTED();
10454 } 10458 }
10455 10459
10456 virtual void ReportSwitchingCode(const Code& code) { 10460 virtual void ReportSwitchingCode(const Code& code) {
10457 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { 10461 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
10458 OS::PrintErr("Prefix '%s': disabling %s code for %s function '%s'\n", 10462 ISL_Print("Prefix '%s': disabling %s code for %s function '%s'\n",
10459 String::Handle(prefix_.name()).ToCString(), 10463 String::Handle(prefix_.name()).ToCString(),
10460 code.is_optimized() ? "optimized" : "unoptimized", 10464 code.is_optimized() ? "optimized" : "unoptimized",
10461 CodePatcher::IsEntryPatched(code) ? "patched" : "unpatched", 10465 CodePatcher::IsEntryPatched(code) ? "patched" : "unpatched",
10462 Function::Handle(code.function()).ToCString()); 10466 Function::Handle(code.function()).ToCString());
10463 } 10467 }
10464 } 10468 }
10465 10469
10466 private: 10470 private:
10467 const LibraryPrefix& prefix_; 10471 const LibraryPrefix& prefix_;
10468 DISALLOW_COPY_AND_ASSIGN(PrefixDependentArray); 10472 DISALLOW_COPY_AND_ASSIGN(PrefixDependentArray);
10469 }; 10473 };
10470 10474
10471 10475
10472 void LibraryPrefix::RegisterDependentCode(const Code& code) const { 10476 void LibraryPrefix::RegisterDependentCode(const Code& code) const {
(...skipping 2964 matching lines...) Expand 10 before | Expand all | Expand 10 after
13437 const char* parent_str = parent_ctx.ToCString(); 13441 const char* parent_str = parent_ctx.ToCString();
13438 return zone->PrintToString( 13442 return zone->PrintToString(
13439 "Context@%p num_variables:% " Pd " parent:{ %s }", 13443 "Context@%p num_variables:% " Pd " parent:{ %s }",
13440 this->raw(), num_variables(), parent_str); 13444 this->raw(), num_variables(), parent_str);
13441 } 13445 }
13442 } 13446 }
13443 13447
13444 13448
13445 static void IndentN(int count) { 13449 static void IndentN(int count) {
13446 for (int i = 0; i < count; i++) { 13450 for (int i = 0; i < count; i++) {
13447 OS::PrintErr(" "); 13451 ISL_Print(" ");
13448 } 13452 }
13449 } 13453 }
13450 13454
13451 13455
13452 void Context::Dump(int indent) const { 13456 void Context::Dump(int indent) const {
13453 if (IsNull()) { 13457 if (IsNull()) {
13454 IndentN(indent); 13458 IndentN(indent);
13455 OS::PrintErr("Context@null\n"); 13459 ISL_Print("Context@null\n");
13456 return; 13460 return;
13457 } 13461 }
13458 13462
13459 IndentN(indent); 13463 IndentN(indent);
13460 OS::PrintErr("Context@%p vars(%" Pd ") {\n", this->raw(), num_variables()); 13464 ISL_Print("Context@%p vars(%" Pd ") {\n", this->raw(), num_variables());
13461 Object& obj = Object::Handle(); 13465 Object& obj = Object::Handle();
13462 for (intptr_t i = 0; i < num_variables(); i++) { 13466 for (intptr_t i = 0; i < num_variables(); i++) {
13463 IndentN(indent + 2); 13467 IndentN(indent + 2);
13464 obj = At(i); 13468 obj = At(i);
13465 OS::PrintErr("[%" Pd "] = %s\n", i, obj.ToCString()); 13469 ISL_Print("[%" Pd "] = %s\n", i, obj.ToCString());
13466 } 13470 }
13467 13471
13468 const Context& parent_ctx = Context::Handle(parent()); 13472 const Context& parent_ctx = Context::Handle(parent());
13469 if (!parent_ctx.IsNull()) { 13473 if (!parent_ctx.IsNull()) {
13470 parent_ctx.Dump(indent + 2); 13474 parent_ctx.Dump(indent + 2);
13471 } 13475 }
13472 IndentN(indent); 13476 IndentN(indent);
13473 OS::PrintErr("}\n"); 13477 ISL_Print("}\n");
13474 } 13478 }
13475 13479
13476 13480
13477 void Context::PrintJSONImpl(JSONStream* stream, bool ref) const { 13481 void Context::PrintJSONImpl(JSONStream* stream, bool ref) const {
13478 JSONObject jsobj(stream); 13482 JSONObject jsobj(stream);
13479 // TODO(turnidge): Should the user level type for Context be Context 13483 // TODO(turnidge): Should the user level type for Context be Context
13480 // or Object? 13484 // or Object?
13481 AddCommonObjectProperties(&jsobj, "Context", ref); 13485 AddCommonObjectProperties(&jsobj, "Context", ref);
13482 jsobj.AddServiceId(*this); 13486 jsobj.AddServiceId(*this);
13483 13487
(...skipping 7880 matching lines...) Expand 10 before | Expand all | Expand 10 after
21364 return tag_label.ToCString(); 21368 return tag_label.ToCString();
21365 } 21369 }
21366 21370
21367 21371
21368 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 21372 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
21369 Instance::PrintJSONImpl(stream, ref); 21373 Instance::PrintJSONImpl(stream, ref);
21370 } 21374 }
21371 21375
21372 21376
21373 } // namespace dart 21377 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/il_printer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698