OLD | NEW |
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 Loading... |
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 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5221 StorePointer(&raw_ptr()->source_class_, value.raw()); | 5223 StorePointer(&raw_ptr()->source_class_, value.raw()); |
5222 } | 5224 } |
5223 | 5225 |
5224 | 5226 |
5225 bool Function::HasBreakpoint() const { | 5227 bool Function::HasBreakpoint() const { |
5226 return Isolate::Current()->debugger()->HasBreakpoint(*this); | 5228 return Isolate::Current()->debugger()->HasBreakpoint(*this); |
5227 } | 5229 } |
5228 | 5230 |
5229 | 5231 |
5230 void Function::SetInstructions(const Code& value) const { | 5232 void Function::SetInstructions(const Code& value) const { |
5231 StorePointer(&raw_ptr()->instructions_, value.instructions()); | 5233 StorePointer(&raw_ptr()->code_, value.raw()); |
5232 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint()); | 5234 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint()); |
5233 } | 5235 } |
5234 | 5236 |
5235 void Function::AttachCode(const Code& value) const { | 5237 void Function::AttachCode(const Code& value) const { |
5236 SetInstructions(value); | 5238 SetInstructions(value); |
5237 ASSERT(Function::Handle(value.function()).IsNull() || | 5239 ASSERT(Function::Handle(value.function()).IsNull() || |
5238 (value.function() == this->raw())); | 5240 (value.function() == this->raw())); |
5239 value.set_owner(*this); | 5241 value.set_owner(*this); |
5240 } | 5242 } |
5241 | 5243 |
5242 | 5244 |
5243 bool Function::HasCode() const { | 5245 bool Function::HasCode() const { |
5244 ASSERT(raw_ptr()->instructions_ != Instructions::null()); | 5246 ASSERT(raw_ptr()->code_ != Code::null()); |
5245 return raw_ptr()->instructions_ != | 5247 return raw_ptr()->code_ != StubCode::LazyCompile_entry()->code(); |
5246 StubCode::LazyCompile_entry()->code()->ptr()->instructions_; | |
5247 } | 5248 } |
5248 | 5249 |
5249 | 5250 |
5250 void Function::ClearCode() const { | 5251 void Function::ClearCode() const { |
5251 ASSERT(ic_data_array() == Array::null()); | 5252 ASSERT(ic_data_array() == Array::null()); |
5252 StorePointer(&raw_ptr()->unoptimized_code_, Code::null()); | 5253 StorePointer(&raw_ptr()->unoptimized_code_, Code::null()); |
5253 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); | 5254 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); |
5254 } | 5255 } |
5255 | 5256 |
5256 | 5257 |
5257 void Function::SwitchToUnoptimizedCode() const { | 5258 void Function::SwitchToUnoptimizedCode() const { |
5258 ASSERT(HasOptimizedCode()); | 5259 ASSERT(HasOptimizedCode()); |
5259 Thread* thread = Thread::Current(); | 5260 Thread* thread = Thread::Current(); |
5260 Isolate* isolate = thread->isolate(); | 5261 Isolate* isolate = thread->isolate(); |
5261 Zone* zone = thread->zone(); | 5262 Zone* zone = thread->zone(); |
5262 const Code& current_code = Code::Handle(zone, CurrentCode()); | 5263 const Code& current_code = Code::Handle(zone, CurrentCode()); |
5263 | 5264 |
5264 if (FLAG_trace_deoptimization_verbose) { | 5265 if (FLAG_trace_deoptimization_verbose) { |
5265 ISL_Print("Disabling optimized code: '%s' entry: %#" Px "\n", | 5266 ISL_Print("Disabling optimized code: '%s' entry: %#" Px "\n", |
5266 ToFullyQualifiedCString(), | 5267 ToFullyQualifiedCString(), |
5267 current_code.EntryPoint()); | 5268 current_code.EntryPoint()); |
5268 } | 5269 } |
5269 // Patch entry of the optimized code. | 5270 // Patch entry of the optimized code. |
5270 CodePatcher::PatchEntry(current_code); | 5271 CodePatcher::PatchEntry( |
| 5272 current_code, Code::Handle(StubCode::FixCallersTarget_entry()->code())); |
5271 const Error& error = Error::Handle(zone, | 5273 const Error& error = Error::Handle(zone, |
5272 Compiler::EnsureUnoptimizedCode(thread, *this)); | 5274 Compiler::EnsureUnoptimizedCode(thread, *this)); |
5273 if (!error.IsNull()) { | 5275 if (!error.IsNull()) { |
5274 Exceptions::PropagateError(error); | 5276 Exceptions::PropagateError(error); |
5275 } | 5277 } |
5276 const Code& unopt_code = Code::Handle(zone, unoptimized_code()); | 5278 const Code& unopt_code = Code::Handle(zone, unoptimized_code()); |
5277 AttachCode(unopt_code); | 5279 AttachCode(unopt_code); |
5278 CodePatcher::RestoreEntry(unopt_code); | 5280 CodePatcher::RestoreEntry(unopt_code); |
5279 isolate->TrackDeoptimizedCode(current_code); | 5281 isolate->TrackDeoptimizedCode(current_code); |
5280 } | 5282 } |
(...skipping 1435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6716 const Object& obj = Object::Handle(raw_ptr()->owner_); | 6718 const Object& obj = Object::Handle(raw_ptr()->owner_); |
6717 if (obj.IsClass()) { | 6719 if (obj.IsClass()) { |
6718 return Class::Cast(obj).script(); | 6720 return Class::Cast(obj).script(); |
6719 } | 6721 } |
6720 ASSERT(obj.IsPatchClass()); | 6722 ASSERT(obj.IsPatchClass()); |
6721 return PatchClass::Cast(obj).Script(); | 6723 return PatchClass::Cast(obj).Script(); |
6722 } | 6724 } |
6723 | 6725 |
6724 | 6726 |
6725 bool Function::HasOptimizedCode() const { | 6727 bool Function::HasOptimizedCode() const { |
6726 return HasCode() && Code::Handle(Instructions::Handle( | 6728 return HasCode() && Code::Handle(CurrentCode()).is_optimized(); |
6727 raw_ptr()->instructions_).code()).is_optimized(); | |
6728 } | 6729 } |
6729 | 6730 |
6730 | 6731 |
6731 RawString* Function::PrettyName() const { | 6732 RawString* Function::PrettyName() const { |
6732 const String& str = String::Handle(name()); | 6733 const String& str = String::Handle(name()); |
6733 return String::IdentifierPrettyName(str); | 6734 return String::IdentifierPrettyName(str); |
6734 } | 6735 } |
6735 | 6736 |
6736 | 6737 |
6737 const char* Function::QualifiedUserVisibleNameCString() const { | 6738 const char* Function::QualifiedUserVisibleNameCString() const { |
(...skipping 4172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10910 | 10911 |
10911 const char* Instructions::ToCString() const { | 10912 const char* Instructions::ToCString() const { |
10912 return "Instructions"; | 10913 return "Instructions"; |
10913 } | 10914 } |
10914 | 10915 |
10915 | 10916 |
10916 void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const { | 10917 void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const { |
10917 JSONObject jsobj(stream); | 10918 JSONObject jsobj(stream); |
10918 AddCommonObjectProperties(&jsobj, "Object", ref); | 10919 AddCommonObjectProperties(&jsobj, "Object", ref); |
10919 jsobj.AddServiceId(*this); | 10920 jsobj.AddServiceId(*this); |
10920 jsobj.AddProperty("_code", Code::Handle(code())); | |
10921 if (ref) { | 10921 if (ref) { |
10922 return; | 10922 return; |
10923 } | 10923 } |
10924 jsobj.AddProperty("_objectPool", ObjectPool::Handle(object_pool())); | |
10925 } | 10924 } |
10926 | 10925 |
10927 | 10926 |
10928 // Encode integer in SLEB128 format. | 10927 // Encode integer in SLEB128 format. |
10929 void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data, | 10928 void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data, |
10930 intptr_t value) { | 10929 intptr_t value) { |
10931 bool is_last_part = false; | 10930 bool is_last_part = false; |
10932 while (!is_last_part) { | 10931 while (!is_last_part) { |
10933 intptr_t part = value & 0x7f; | 10932 intptr_t part = value & 0x7f; |
10934 value >>= 7; | 10933 value >>= 7; |
(...skipping 1919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12854 } else { | 12853 } else { |
12855 ASSERT(code.IsNull() || | 12854 ASSERT(code.IsNull() || |
12856 (code.function() == array.At(i + kSCallTableFunctionEntry))); | 12855 (code.function() == array.At(i + kSCallTableFunctionEntry))); |
12857 } | 12856 } |
12858 #endif | 12857 #endif |
12859 array.SetAt(i + kSCallTableCodeEntry, code); | 12858 array.SetAt(i + kSCallTableCodeEntry, code); |
12860 } | 12859 } |
12861 | 12860 |
12862 | 12861 |
12863 void Code::Disassemble(DisassemblyFormatter* formatter) const { | 12862 void Code::Disassemble(DisassemblyFormatter* formatter) const { |
12864 const bool fix_patch = CodePatcher::CodeIsPatchable(*this) && | |
12865 CodePatcher::IsEntryPatched(*this); | |
12866 if (fix_patch) { | |
12867 // The disassembler may choke on illegal instructions if the code has been | |
12868 // patched, un-patch the code before disassembling and re-patch after. | |
12869 CodePatcher::RestoreEntry(*this); | |
12870 } | |
12871 const Instructions& instr = Instructions::Handle(instructions()); | 12863 const Instructions& instr = Instructions::Handle(instructions()); |
12872 uword start = instr.EntryPoint(); | 12864 uword start = instr.EntryPoint(); |
12873 if (formatter == NULL) { | 12865 if (formatter == NULL) { |
12874 Disassembler::Disassemble(start, start + instr.size(), *this); | 12866 Disassembler::Disassemble(start, start + instr.size(), *this); |
12875 } else { | 12867 } else { |
12876 Disassembler::Disassemble(start, start + instr.size(), formatter, *this); | 12868 Disassembler::Disassemble(start, start + instr.size(), formatter, *this); |
12877 } | 12869 } |
12878 if (fix_patch) { | |
12879 // Redo the patch. | |
12880 CodePatcher::PatchEntry(*this); | |
12881 } | |
12882 } | 12870 } |
12883 | 12871 |
12884 | 12872 |
12885 const Code::Comments& Code::comments() const { | 12873 const Code::Comments& Code::comments() const { |
12886 Comments* comments = new Code::Comments(Array::Handle(raw_ptr()->comments_)); | 12874 Comments* comments = new Code::Comments(Array::Handle(raw_ptr()->comments_)); |
12887 return *comments; | 12875 return *comments; |
12888 } | 12876 } |
12889 | 12877 |
12890 | 12878 |
12891 void Code::set_comments(const Code::Comments& comments) const { | 12879 void Code::set_comments(const Code::Comments& comments) const { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12993 { | 12981 { |
12994 uword size = Code::InstanceSize(pointer_offsets_length); | 12982 uword size = Code::InstanceSize(pointer_offsets_length); |
12995 RawObject* raw = Object::Allocate(Code::kClassId, size, Heap::kOld); | 12983 RawObject* raw = Object::Allocate(Code::kClassId, size, Heap::kOld); |
12996 NoSafepointScope no_safepoint; | 12984 NoSafepointScope no_safepoint; |
12997 result ^= raw; | 12985 result ^= raw; |
12998 result.set_pointer_offsets_length(pointer_offsets_length); | 12986 result.set_pointer_offsets_length(pointer_offsets_length); |
12999 result.set_is_optimized(false); | 12987 result.set_is_optimized(false); |
13000 result.set_is_alive(false); | 12988 result.set_is_alive(false); |
13001 result.set_comments(Comments::New(0)); | 12989 result.set_comments(Comments::New(0)); |
13002 result.set_compile_timestamp(0); | 12990 result.set_compile_timestamp(0); |
13003 result.set_entry_patch_pc_offset(kInvalidPc); | |
13004 result.set_patch_code_pc_offset(kInvalidPc); | |
13005 result.set_lazy_deopt_pc_offset(kInvalidPc); | 12991 result.set_lazy_deopt_pc_offset(kInvalidPc); |
13006 result.set_pc_descriptors(Object::empty_descriptors()); | 12992 result.set_pc_descriptors(Object::empty_descriptors()); |
13007 } | 12993 } |
13008 return result.raw(); | 12994 return result.raw(); |
13009 } | 12995 } |
13010 | 12996 |
13011 | 12997 |
13012 RawCode* Code::FinalizeCode(const char* name, | 12998 RawCode* Code::FinalizeCode(const char* name, |
13013 Assembler* assembler, | 12999 Assembler* assembler, |
13014 bool optimized) { | 13000 bool optimized) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13057 for (intptr_t i = 0; i < pointer_offsets.length(); i++) { | 13043 for (intptr_t i = 0; i < pointer_offsets.length(); i++) { |
13058 intptr_t offset_in_instrs = pointer_offsets[i]; | 13044 intptr_t offset_in_instrs = pointer_offsets[i]; |
13059 code.SetPointerOffsetAt(i, offset_in_instrs); | 13045 code.SetPointerOffsetAt(i, offset_in_instrs); |
13060 uword addr = region.start() + offset_in_instrs; | 13046 uword addr = region.start() + offset_in_instrs; |
13061 const Object* object = *reinterpret_cast<Object**>(addr); | 13047 const Object* object = *reinterpret_cast<Object**>(addr); |
13062 instrs.raw()->StorePointer(reinterpret_cast<RawObject**>(addr), | 13048 instrs.raw()->StorePointer(reinterpret_cast<RawObject**>(addr), |
13063 object->raw()); | 13049 object->raw()); |
13064 } | 13050 } |
13065 | 13051 |
13066 // Hook up Code and Instructions objects. | 13052 // Hook up Code and Instructions objects. |
13067 instrs.set_code(code.raw()); | 13053 code.set_active_instructions(instrs.raw()); |
13068 code.set_instructions(instrs.raw()); | 13054 code.set_instructions(instrs.raw()); |
13069 code.set_is_alive(true); | 13055 code.set_is_alive(true); |
13070 | 13056 |
13071 // Set object pool in Instructions object. | 13057 // Set object pool in Instructions object. |
13072 INC_STAT(Thread::Current(), | 13058 INC_STAT(Thread::Current(), |
13073 total_code_size, object_pool.Length() * sizeof(uintptr_t)); | 13059 total_code_size, object_pool.Length() * sizeof(uintptr_t)); |
13074 instrs.set_object_pool(object_pool.raw()); | 13060 code.set_object_pool(object_pool.raw()); |
13075 | 13061 |
13076 if (FLAG_write_protect_code) { | 13062 if (FLAG_write_protect_code) { |
13077 uword address = RawObject::ToAddr(instrs.raw()); | 13063 uword address = RawObject::ToAddr(instrs.raw()); |
13078 bool status = VirtualMemory::Protect( | 13064 bool status = VirtualMemory::Protect( |
13079 reinterpret_cast<void*>(address), | 13065 reinterpret_cast<void*>(address), |
13080 instrs.raw()->Size(), | 13066 instrs.raw()->Size(), |
13081 VirtualMemory::kReadExecute); | 13067 VirtualMemory::kReadExecute); |
13082 ASSERT(status); | 13068 ASSERT(status); |
13083 } | 13069 } |
13084 } | 13070 } |
(...skipping 21 matching lines...) Expand all Loading... |
13106 assembler, | 13092 assembler, |
13107 optimized); | 13093 optimized); |
13108 } else { | 13094 } else { |
13109 return FinalizeCode("", assembler); | 13095 return FinalizeCode("", assembler); |
13110 } | 13096 } |
13111 } | 13097 } |
13112 | 13098 |
13113 | 13099 |
13114 // Check if object matches find condition. | 13100 // Check if object matches find condition. |
13115 bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) const { | 13101 bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) const { |
13116 return RawInstructions::ContainsPC(obj, pc_); | 13102 return RawCode::ContainsPC(obj, pc_); |
13117 } | 13103 } |
13118 | 13104 |
13119 | 13105 |
13120 RawCode* Code::LookupCodeInIsolate(Isolate* isolate, uword pc) { | 13106 RawCode* Code::LookupCodeInIsolate(Isolate* isolate, uword pc) { |
13121 ASSERT((isolate == Isolate::Current()) || (isolate == Dart::vm_isolate())); | 13107 ASSERT((isolate == Isolate::Current()) || (isolate == Dart::vm_isolate())); |
13122 NoSafepointScope no_safepoint; | 13108 NoSafepointScope no_safepoint; |
13123 FindRawCodeVisitor visitor(pc); | 13109 FindRawCodeVisitor visitor(pc); |
13124 RawInstructions* instr; | 13110 RawObject* instr; |
13125 if (isolate->heap() == NULL) { | 13111 if (isolate->heap() == NULL) { |
13126 return Code::null(); | 13112 return Code::null(); |
13127 } | 13113 } |
13128 instr = isolate->heap()->FindObjectInCodeSpace(&visitor); | 13114 instr = isolate->heap()->FindOldObject(&visitor); |
13129 if (instr != Instructions::null()) { | 13115 if (instr != Code::null()) { |
13130 return instr->ptr()->code_; | 13116 return static_cast<RawCode*>(instr); |
13131 } | 13117 } |
13132 return Code::null(); | 13118 return Code::null(); |
13133 } | 13119 } |
13134 | 13120 |
13135 | 13121 |
13136 RawCode* Code::LookupCode(uword pc) { | 13122 RawCode* Code::LookupCode(uword pc) { |
13137 return LookupCodeInIsolate(Isolate::Current(), pc); | 13123 return LookupCodeInIsolate(Isolate::Current(), pc); |
13138 } | 13124 } |
13139 | 13125 |
13140 | 13126 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13361 while (inlining_id >= 0) { | 13347 while (inlining_id >= 0) { |
13362 inline_interval.AddValue(inlining_id); | 13348 inline_interval.AddValue(inlining_id); |
13363 inlining_id = caller_id; | 13349 inlining_id = caller_id; |
13364 caller_id = GetCallerId(inlining_id); | 13350 caller_id = GetCallerId(inlining_id); |
13365 } | 13351 } |
13366 } | 13352 } |
13367 } | 13353 } |
13368 } | 13354 } |
13369 | 13355 |
13370 | 13356 |
13371 uword Code::GetEntryPatchPc() const { | |
13372 return (entry_patch_pc_offset() != kInvalidPc) | |
13373 ? EntryPoint() + entry_patch_pc_offset() : 0; | |
13374 } | |
13375 | |
13376 | |
13377 uword Code::GetPatchCodePc() const { | |
13378 return (patch_code_pc_offset() != kInvalidPc) | |
13379 ? EntryPoint() + patch_code_pc_offset() : 0; | |
13380 } | |
13381 | |
13382 | |
13383 uword Code::GetLazyDeoptPc() const { | 13357 uword Code::GetLazyDeoptPc() const { |
13384 return (lazy_deopt_pc_offset() != kInvalidPc) | 13358 return (lazy_deopt_pc_offset() != kInvalidPc) |
13385 ? EntryPoint() + lazy_deopt_pc_offset() : 0; | 13359 ? EntryPoint() + lazy_deopt_pc_offset() : 0; |
13386 } | 13360 } |
13387 | 13361 |
13388 | 13362 |
13389 RawStackmap* Code::GetStackmap( | 13363 RawStackmap* Code::GetStackmap( |
13390 uint32_t pc_offset, Array* maps, Stackmap* map) const { | 13364 uint32_t pc_offset, Array* maps, Stackmap* map) const { |
13391 // This code is used during iterating frames during a GC and hence it | 13365 // This code is used during iterating frames during a GC and hence it |
13392 // should not in turn start a GC. | 13366 // should not in turn start a GC. |
(...skipping 8128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21521 return tag_label.ToCString(); | 21495 return tag_label.ToCString(); |
21522 } | 21496 } |
21523 | 21497 |
21524 | 21498 |
21525 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 21499 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
21526 Instance::PrintJSONImpl(stream, ref); | 21500 Instance::PrintJSONImpl(stream, ref); |
21527 } | 21501 } |
21528 | 21502 |
21529 | 21503 |
21530 } // namespace dart | 21504 } // namespace dart |
OLD | NEW |