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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: preserve CODE_REG in ARM Integer_shl intrinsic. Created 5 years, 3 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
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 3689 matching lines...) Expand 10 before | Expand all | Expand 10 after
3700 } 3700 }
3701 3701
3702 3702
3703 void Class::DisableAllocationStub() const { 3703 void Class::DisableAllocationStub() const {
3704 const Code& existing_stub = Code::Handle(allocation_stub()); 3704 const Code& existing_stub = Code::Handle(allocation_stub());
3705 if (existing_stub.IsNull()) { 3705 if (existing_stub.IsNull()) {
3706 return; 3706 return;
3707 } 3707 }
3708 ASSERT(!CodePatcher::IsEntryPatched(existing_stub)); 3708 ASSERT(!CodePatcher::IsEntryPatched(existing_stub));
3709 // Patch the stub so that the next caller will regenerate the stub. 3709 // Patch the stub so that the next caller will regenerate the stub.
3710 CodePatcher::PatchEntry(existing_stub); 3710 CodePatcher::PatchEntry(
3711 existing_stub,
3712 Code::Handle(StubCode::FixAllocationStubTarget_entry()->code()));
3711 // Disassociate the existing stub from class. 3713 // Disassociate the existing stub from class.
3712 StorePointer(&raw_ptr()->allocation_stub_, Code::null()); 3714 StorePointer(&raw_ptr()->allocation_stub_, Code::null());
3713 } 3715 }
3714 3716
3715 3717
3716 bool Class::IsFunctionClass() const { 3718 bool Class::IsFunctionClass() const {
3717 return raw() == Type::Handle(Type::Function()).type_class(); 3719 return raw() == Type::Handle(Type::Function()).type_class();
3718 } 3720 }
3719 3721
3720 3722
(...skipping 1497 matching lines...) Expand 10 before | Expand all | Expand 10 after
5218 StorePointer(&raw_ptr()->source_class_, value.raw()); 5220 StorePointer(&raw_ptr()->source_class_, value.raw());
5219 } 5221 }
5220 5222
5221 5223
5222 bool Function::HasBreakpoint() const { 5224 bool Function::HasBreakpoint() const {
5223 return Isolate::Current()->debugger()->HasBreakpoint(*this); 5225 return Isolate::Current()->debugger()->HasBreakpoint(*this);
5224 } 5226 }
5225 5227
5226 5228
5227 void Function::SetInstructions(const Code& value) const { 5229 void Function::SetInstructions(const Code& value) const {
5228 StorePointer(&raw_ptr()->instructions_, value.instructions()); 5230 StorePointer(&raw_ptr()->code_, value.raw());
5229 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint()); 5231 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint());
5230 } 5232 }
5231 5233
5232 void Function::AttachCode(const Code& value) const { 5234 void Function::AttachCode(const Code& value) const {
5233 SetInstructions(value); 5235 SetInstructions(value);
5234 ASSERT(Function::Handle(value.function()).IsNull() || 5236 ASSERT(Function::Handle(value.function()).IsNull() ||
5235 (value.function() == this->raw())); 5237 (value.function() == this->raw()));
5236 value.set_owner(*this); 5238 value.set_owner(*this);
5237 } 5239 }
5238 5240
5239 5241
5240 bool Function::HasCode() const { 5242 bool Function::HasCode() const {
5241 ASSERT(raw_ptr()->instructions_ != Instructions::null()); 5243 ASSERT(raw_ptr()->code_ != Code::null());
5242 return raw_ptr()->instructions_ != 5244 return raw_ptr()->code_ != StubCode::LazyCompile_entry()->code();
5243 StubCode::LazyCompile_entry()->code()->ptr()->instructions_;
5244 } 5245 }
5245 5246
5246 5247
5247 void Function::ClearCode() const { 5248 void Function::ClearCode() const {
5248 ASSERT(ic_data_array() == Array::null()); 5249 ASSERT(ic_data_array() == Array::null());
5249 StorePointer(&raw_ptr()->unoptimized_code_, Code::null()); 5250 StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
5250 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); 5251 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
5251 } 5252 }
5252 5253
5253 5254
5254 void Function::SwitchToUnoptimizedCode() const { 5255 void Function::SwitchToUnoptimizedCode() const {
5255 ASSERT(HasOptimizedCode()); 5256 ASSERT(HasOptimizedCode());
5256 Thread* thread = Thread::Current(); 5257 Thread* thread = Thread::Current();
5257 Isolate* isolate = thread->isolate(); 5258 Isolate* isolate = thread->isolate();
5258 Zone* zone = thread->zone(); 5259 Zone* zone = thread->zone();
5259 const Code& current_code = Code::Handle(zone, CurrentCode()); 5260 const Code& current_code = Code::Handle(zone, CurrentCode());
5260 5261
5261 if (FLAG_trace_deoptimization_verbose) { 5262 if (FLAG_trace_deoptimization_verbose) {
5262 THR_Print("Disabling optimized code: '%s' entry: %#" Px "\n", 5263 THR_Print("Disabling optimized code: '%s' entry: %#" Px "\n",
5263 ToFullyQualifiedCString(), 5264 ToFullyQualifiedCString(),
5264 current_code.EntryPoint()); 5265 current_code.EntryPoint());
5265 } 5266 }
5266 // Patch entry of the optimized code. 5267 // Patch entry of the optimized code.
5267 CodePatcher::PatchEntry(current_code); 5268 CodePatcher::PatchEntry(
5269 current_code, Code::Handle(StubCode::FixCallersTarget_entry()->code()));
5268 const Error& error = Error::Handle(zone, 5270 const Error& error = Error::Handle(zone,
5269 Compiler::EnsureUnoptimizedCode(thread, *this)); 5271 Compiler::EnsureUnoptimizedCode(thread, *this));
5270 if (!error.IsNull()) { 5272 if (!error.IsNull()) {
5271 Exceptions::PropagateError(error); 5273 Exceptions::PropagateError(error);
5272 } 5274 }
5273 const Code& unopt_code = Code::Handle(zone, unoptimized_code()); 5275 const Code& unopt_code = Code::Handle(zone, unoptimized_code());
5274 AttachCode(unopt_code); 5276 AttachCode(unopt_code);
5275 CodePatcher::RestoreEntry(unopt_code); 5277 CodePatcher::RestoreEntry(unopt_code);
5276 isolate->TrackDeoptimizedCode(current_code); 5278 isolate->TrackDeoptimizedCode(current_code);
5277 } 5279 }
(...skipping 1443 matching lines...) Expand 10 before | Expand all | Expand 10 after
6721 const Object& obj = Object::Handle(raw_ptr()->owner_); 6723 const Object& obj = Object::Handle(raw_ptr()->owner_);
6722 if (obj.IsClass()) { 6724 if (obj.IsClass()) {
6723 return Class::Cast(obj).script(); 6725 return Class::Cast(obj).script();
6724 } 6726 }
6725 ASSERT(obj.IsPatchClass()); 6727 ASSERT(obj.IsPatchClass());
6726 return PatchClass::Cast(obj).Script(); 6728 return PatchClass::Cast(obj).Script();
6727 } 6729 }
6728 6730
6729 6731
6730 bool Function::HasOptimizedCode() const { 6732 bool Function::HasOptimizedCode() const {
6731 return HasCode() && Code::Handle(Instructions::Handle( 6733 return HasCode() && Code::Handle(CurrentCode()).is_optimized();
6732 raw_ptr()->instructions_).code()).is_optimized();
6733 } 6734 }
6734 6735
6735 6736
6736 RawString* Function::PrettyName() const { 6737 RawString* Function::PrettyName() const {
6737 const String& str = String::Handle(name()); 6738 const String& str = String::Handle(name());
6738 return String::IdentifierPrettyName(str); 6739 return String::IdentifierPrettyName(str);
6739 } 6740 }
6740 6741
6741 6742
6742 const char* Function::QualifiedUserVisibleNameCString() const { 6743 const char* Function::QualifiedUserVisibleNameCString() const {
(...skipping 4168 matching lines...) Expand 10 before | Expand all | Expand 10 after
10911 10912
10912 const char* Instructions::ToCString() const { 10913 const char* Instructions::ToCString() const {
10913 return "Instructions"; 10914 return "Instructions";
10914 } 10915 }
10915 10916
10916 10917
10917 void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const { 10918 void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const {
10918 JSONObject jsobj(stream); 10919 JSONObject jsobj(stream);
10919 AddCommonObjectProperties(&jsobj, "Object", ref); 10920 AddCommonObjectProperties(&jsobj, "Object", ref);
10920 jsobj.AddServiceId(*this); 10921 jsobj.AddServiceId(*this);
10921 jsobj.AddProperty("_code", Code::Handle(code()));
10922 if (ref) { 10922 if (ref) {
10923 return; 10923 return;
10924 } 10924 }
10925 jsobj.AddProperty("_objectPool", ObjectPool::Handle(object_pool()));
10926 } 10925 }
10927 10926
10928 10927
10929 // Encode integer in SLEB128 format. 10928 // Encode integer in SLEB128 format.
10930 void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data, 10929 void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data,
10931 intptr_t value) { 10930 intptr_t value) {
10932 bool is_last_part = false; 10931 bool is_last_part = false;
10933 while (!is_last_part) { 10932 while (!is_last_part) {
10934 intptr_t part = value & 0x7f; 10933 intptr_t part = value & 0x7f;
10935 value >>= 7; 10934 value >>= 7;
(...skipping 1913 matching lines...) Expand 10 before | Expand all | Expand 10 after
12849 } else { 12848 } else {
12850 ASSERT(code.IsNull() || 12849 ASSERT(code.IsNull() ||
12851 (code.function() == array.At(i + kSCallTableFunctionEntry))); 12850 (code.function() == array.At(i + kSCallTableFunctionEntry)));
12852 } 12851 }
12853 #endif 12852 #endif
12854 array.SetAt(i + kSCallTableCodeEntry, code); 12853 array.SetAt(i + kSCallTableCodeEntry, code);
12855 } 12854 }
12856 12855
12857 12856
12858 void Code::Disassemble(DisassemblyFormatter* formatter) const { 12857 void Code::Disassemble(DisassemblyFormatter* formatter) const {
12859 const bool fix_patch = CodePatcher::CodeIsPatchable(*this) &&
12860 CodePatcher::IsEntryPatched(*this);
12861 if (fix_patch) {
12862 // The disassembler may choke on illegal instructions if the code has been
12863 // patched, un-patch the code before disassembling and re-patch after.
12864 CodePatcher::RestoreEntry(*this);
12865 }
12866 const Instructions& instr = Instructions::Handle(instructions()); 12858 const Instructions& instr = Instructions::Handle(instructions());
12867 uword start = instr.EntryPoint(); 12859 uword start = instr.EntryPoint();
12868 if (formatter == NULL) { 12860 if (formatter == NULL) {
12869 Disassembler::Disassemble(start, start + instr.size(), *this); 12861 Disassembler::Disassemble(start, start + instr.size(), *this);
12870 } else { 12862 } else {
12871 Disassembler::Disassemble(start, start + instr.size(), formatter, *this); 12863 Disassembler::Disassemble(start, start + instr.size(), formatter, *this);
12872 } 12864 }
12873 if (fix_patch) {
12874 // Redo the patch.
12875 CodePatcher::PatchEntry(*this);
12876 }
12877 } 12865 }
12878 12866
12879 12867
12880 const Code::Comments& Code::comments() const { 12868 const Code::Comments& Code::comments() const {
12881 Comments* comments = new Code::Comments(Array::Handle(raw_ptr()->comments_)); 12869 Comments* comments = new Code::Comments(Array::Handle(raw_ptr()->comments_));
12882 return *comments; 12870 return *comments;
12883 } 12871 }
12884 12872
12885 12873
12886 void Code::set_comments(const Code::Comments& comments) const { 12874 void Code::set_comments(const Code::Comments& comments) const {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
12988 { 12976 {
12989 uword size = Code::InstanceSize(pointer_offsets_length); 12977 uword size = Code::InstanceSize(pointer_offsets_length);
12990 RawObject* raw = Object::Allocate(Code::kClassId, size, Heap::kOld); 12978 RawObject* raw = Object::Allocate(Code::kClassId, size, Heap::kOld);
12991 NoSafepointScope no_safepoint; 12979 NoSafepointScope no_safepoint;
12992 result ^= raw; 12980 result ^= raw;
12993 result.set_pointer_offsets_length(pointer_offsets_length); 12981 result.set_pointer_offsets_length(pointer_offsets_length);
12994 result.set_is_optimized(false); 12982 result.set_is_optimized(false);
12995 result.set_is_alive(false); 12983 result.set_is_alive(false);
12996 result.set_comments(Comments::New(0)); 12984 result.set_comments(Comments::New(0));
12997 result.set_compile_timestamp(0); 12985 result.set_compile_timestamp(0);
12998 result.set_entry_patch_pc_offset(kInvalidPc);
12999 result.set_patch_code_pc_offset(kInvalidPc);
13000 result.set_lazy_deopt_pc_offset(kInvalidPc); 12986 result.set_lazy_deopt_pc_offset(kInvalidPc);
13001 result.set_pc_descriptors(Object::empty_descriptors()); 12987 result.set_pc_descriptors(Object::empty_descriptors());
13002 } 12988 }
13003 return result.raw(); 12989 return result.raw();
13004 } 12990 }
13005 12991
13006 12992
13007 RawCode* Code::FinalizeCode(const char* name, 12993 RawCode* Code::FinalizeCode(const char* name,
13008 Assembler* assembler, 12994 Assembler* assembler,
13009 bool optimized) { 12995 bool optimized) {
13010 Isolate* isolate = Isolate::Current(); 12996 Isolate* isolate = Isolate::Current();
13011 if (!isolate->compilation_allowed()) { 12997 if (!isolate->compilation_allowed()) {
13012 FATAL1("Precompilation missed code %s\n", name); 12998 FATAL1("Precompilation missed code %s\n", name);
13013 } 12999 }
13014 13000
13015 ASSERT(assembler != NULL); 13001 ASSERT(assembler != NULL);
13016 const ObjectPool& object_pool = 13002 const ObjectPool& object_pool =
13017 ObjectPool::Handle(assembler->object_pool_wrapper().MakeObjectPool()); 13003 ObjectPool::Handle(assembler->object_pool_wrapper().MakeObjectPool());
13018 13004
13019 // Allocate the Code and Instructions objects. Code is allocated first 13005 // Allocate the Code and Instructions objects. Code is allocated first
13020 // because a GC during allocation of the code will leave the instruction 13006 // because a GC during allocation of the code will leave the instruction
13021 // pages read-only. 13007 // pages read-only.
13022 intptr_t pointer_offset_count = assembler->CountPointerOffsets(); 13008 intptr_t pointer_offset_count = assembler->CountPointerOffsets();
13023 Code& code = Code::ZoneHandle(Code::New(pointer_offset_count)); 13009 Code& code = Code::ZoneHandle(Code::New(pointer_offset_count));
13010 #ifdef TARGET_ARCH_IA32
13011 assembler->set_code_object(code);
13012 #endif
13024 Instructions& instrs = 13013 Instructions& instrs =
13025 Instructions::ZoneHandle(Instructions::New(assembler->CodeSize())); 13014 Instructions::ZoneHandle(Instructions::New(assembler->CodeSize()));
13026 INC_STAT(Thread::Current(), total_instr_size, assembler->CodeSize()); 13015 INC_STAT(Thread::Current(), total_instr_size, assembler->CodeSize());
13027 INC_STAT(Thread::Current(), total_code_size, assembler->CodeSize()); 13016 INC_STAT(Thread::Current(), total_code_size, assembler->CodeSize());
13028 13017
13029 // Copy the instructions into the instruction area and apply all fixups. 13018 // Copy the instructions into the instruction area and apply all fixups.
13030 // Embedded pointers are still in handles at this point. 13019 // Embedded pointers are still in handles at this point.
13031 MemoryRegion region(reinterpret_cast<void*>(instrs.EntryPoint()), 13020 MemoryRegion region(reinterpret_cast<void*>(instrs.EntryPoint()),
13032 instrs.size()); 13021 instrs.size());
13033 assembler->FinalizeInstructions(region); 13022 assembler->FinalizeInstructions(region);
(...skipping 18 matching lines...) Expand all
13052 for (intptr_t i = 0; i < pointer_offsets.length(); i++) { 13041 for (intptr_t i = 0; i < pointer_offsets.length(); i++) {
13053 intptr_t offset_in_instrs = pointer_offsets[i]; 13042 intptr_t offset_in_instrs = pointer_offsets[i];
13054 code.SetPointerOffsetAt(i, offset_in_instrs); 13043 code.SetPointerOffsetAt(i, offset_in_instrs);
13055 uword addr = region.start() + offset_in_instrs; 13044 uword addr = region.start() + offset_in_instrs;
13056 const Object* object = *reinterpret_cast<Object**>(addr); 13045 const Object* object = *reinterpret_cast<Object**>(addr);
13057 instrs.raw()->StorePointer(reinterpret_cast<RawObject**>(addr), 13046 instrs.raw()->StorePointer(reinterpret_cast<RawObject**>(addr),
13058 object->raw()); 13047 object->raw());
13059 } 13048 }
13060 13049
13061 // Hook up Code and Instructions objects. 13050 // Hook up Code and Instructions objects.
13062 instrs.set_code(code.raw()); 13051 code.set_active_instructions(instrs.raw());
13063 code.set_instructions(instrs.raw()); 13052 code.set_instructions(instrs.raw());
13064 code.set_is_alive(true); 13053 code.set_is_alive(true);
13065 13054
13066 // Set object pool in Instructions object. 13055 // Set object pool in Instructions object.
13067 INC_STAT(Thread::Current(), 13056 INC_STAT(Thread::Current(),
13068 total_code_size, object_pool.Length() * sizeof(uintptr_t)); 13057 total_code_size, object_pool.Length() * sizeof(uintptr_t));
13069 instrs.set_object_pool(object_pool.raw()); 13058 code.set_object_pool(object_pool.raw());
13070 13059
13071 if (FLAG_write_protect_code) { 13060 if (FLAG_write_protect_code) {
13072 uword address = RawObject::ToAddr(instrs.raw()); 13061 uword address = RawObject::ToAddr(instrs.raw());
13073 bool status = VirtualMemory::Protect( 13062 bool status = VirtualMemory::Protect(
13074 reinterpret_cast<void*>(address), 13063 reinterpret_cast<void*>(address),
13075 instrs.raw()->Size(), 13064 instrs.raw()->Size(),
13076 VirtualMemory::kReadExecute); 13065 VirtualMemory::kReadExecute);
13077 ASSERT(status); 13066 ASSERT(status);
13078 } 13067 }
13079 } 13068 }
(...skipping 21 matching lines...) Expand all
13101 assembler, 13090 assembler,
13102 optimized); 13091 optimized);
13103 } else { 13092 } else {
13104 return FinalizeCode("", assembler); 13093 return FinalizeCode("", assembler);
13105 } 13094 }
13106 } 13095 }
13107 13096
13108 13097
13109 // Check if object matches find condition. 13098 // Check if object matches find condition.
13110 bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) const { 13099 bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) const {
13111 return RawInstructions::ContainsPC(obj, pc_); 13100 return RawCode::ContainsPC(obj, pc_);
13112 } 13101 }
13113 13102
13114 13103
13115 RawCode* Code::LookupCodeInIsolate(Isolate* isolate, uword pc) { 13104 RawCode* Code::LookupCodeInIsolate(Isolate* isolate, uword pc) {
13116 ASSERT((isolate == Isolate::Current()) || (isolate == Dart::vm_isolate())); 13105 ASSERT((isolate == Isolate::Current()) || (isolate == Dart::vm_isolate()));
13117 NoSafepointScope no_safepoint; 13106 NoSafepointScope no_safepoint;
13118 FindRawCodeVisitor visitor(pc); 13107 FindRawCodeVisitor visitor(pc);
13119 RawInstructions* instr; 13108 RawObject* instr;
13120 if (isolate->heap() == NULL) { 13109 if (isolate->heap() == NULL) {
13121 return Code::null(); 13110 return Code::null();
13122 } 13111 }
13123 instr = isolate->heap()->FindObjectInCodeSpace(&visitor); 13112 instr = isolate->heap()->FindOldObject(&visitor);
13124 if (instr != Instructions::null()) { 13113 if (instr != Code::null()) {
13125 return instr->ptr()->code_; 13114 return static_cast<RawCode*>(instr);
13126 } 13115 }
13127 return Code::null(); 13116 return Code::null();
13128 } 13117 }
13129 13118
13130 13119
13131 RawCode* Code::LookupCode(uword pc) { 13120 RawCode* Code::LookupCode(uword pc) {
13132 return LookupCodeInIsolate(Isolate::Current(), pc); 13121 return LookupCodeInIsolate(Isolate::Current(), pc);
13133 } 13122 }
13134 13123
13135 13124
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
13356 while (inlining_id >= 0) { 13345 while (inlining_id >= 0) {
13357 inline_interval.AddValue(inlining_id); 13346 inline_interval.AddValue(inlining_id);
13358 inlining_id = caller_id; 13347 inlining_id = caller_id;
13359 caller_id = GetCallerId(inlining_id); 13348 caller_id = GetCallerId(inlining_id);
13360 } 13349 }
13361 } 13350 }
13362 } 13351 }
13363 } 13352 }
13364 13353
13365 13354
13366 uword Code::GetEntryPatchPc() const {
13367 return (entry_patch_pc_offset() != kInvalidPc)
13368 ? EntryPoint() + entry_patch_pc_offset() : 0;
13369 }
13370
13371
13372 uword Code::GetPatchCodePc() const {
13373 return (patch_code_pc_offset() != kInvalidPc)
13374 ? EntryPoint() + patch_code_pc_offset() : 0;
13375 }
13376
13377
13378 uword Code::GetLazyDeoptPc() const { 13355 uword Code::GetLazyDeoptPc() const {
13379 return (lazy_deopt_pc_offset() != kInvalidPc) 13356 return (lazy_deopt_pc_offset() != kInvalidPc)
13380 ? EntryPoint() + lazy_deopt_pc_offset() : 0; 13357 ? EntryPoint() + lazy_deopt_pc_offset() : 0;
13381 } 13358 }
13382 13359
13383 13360
13384 RawStackmap* Code::GetStackmap( 13361 RawStackmap* Code::GetStackmap(
13385 uint32_t pc_offset, Array* maps, Stackmap* map) const { 13362 uint32_t pc_offset, Array* maps, Stackmap* map) const {
13386 // This code is used during iterating frames during a GC and hence it 13363 // This code is used during iterating frames during a GC and hence it
13387 // should not in turn start a GC. 13364 // should not in turn start a GC.
(...skipping 8047 matching lines...) Expand 10 before | Expand all | Expand 10 after
21435 return tag_label.ToCString(); 21412 return tag_label.ToCString();
21436 } 21413 }
21437 21414
21438 21415
21439 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 21416 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
21440 Instance::PrintJSONImpl(stream, ref); 21417 Instance::PrintJSONImpl(stream, ref);
21441 } 21418 }
21442 21419
21443 21420
21444 } // namespace dart 21421 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698