| 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 12252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12263 return *comments; | 12263 return *comments; |
| 12264 } | 12264 } |
| 12265 | 12265 |
| 12266 | 12266 |
| 12267 void Code::set_comments(const Code::Comments& comments) const { | 12267 void Code::set_comments(const Code::Comments& comments) const { |
| 12268 ASSERT(comments.comments_.IsOld()); | 12268 ASSERT(comments.comments_.IsOld()); |
| 12269 StorePointer(&raw_ptr()->comments_, comments.comments_.raw()); | 12269 StorePointer(&raw_ptr()->comments_, comments.comments_.raw()); |
| 12270 } | 12270 } |
| 12271 | 12271 |
| 12272 | 12272 |
| 12273 void Code::set_inlined_intervals(const Array& value) const { | 12273 void Code::SetPrologueOffset(intptr_t offset) const { |
| 12274 ASSERT(value.IsOld()); | 12274 ASSERT(offset >= 0); |
| 12275 StorePointer(&raw_ptr()->inlined_intervals_, value.raw()); | 12275 StoreSmi( |
| 12276 reinterpret_cast<RawSmi* const *>(&raw_ptr()->return_address_metadata_), |
| 12277 Smi::New(offset)); |
| 12276 } | 12278 } |
| 12277 | 12279 |
| 12278 | 12280 |
| 12279 void Code::set_inlined_id_to_function(const Array& value) const { | 12281 intptr_t Code::GetPrologueOffset() const { |
| 12280 ASSERT(value.IsOld()); | 12282 const Object& object = Object::Handle(raw_ptr()->return_address_metadata_); |
| 12281 StorePointer(&raw_ptr()->inlined_id_to_function_, value.raw()); | 12283 // In the future we may put something other than a smi in |
| 12284 // |return_address_metadata_|. |
| 12285 if (object.IsNull() || !object.IsSmi()) { |
| 12286 return -1; |
| 12287 } |
| 12288 return Smi::Cast(object).Value(); |
| 12282 } | 12289 } |
| 12283 | 12290 |
| 12284 | 12291 |
| 12292 RawArray* Code::GetInlinedIntervals() const { |
| 12293 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
| 12294 if (metadata.IsNull()) { |
| 12295 return metadata.raw(); |
| 12296 } |
| 12297 return reinterpret_cast<RawArray*>( |
| 12298 metadata.At(RawCode::kInlinedIntervalsIndex)); |
| 12299 } |
| 12300 |
| 12301 |
| 12302 void Code::SetInlinedIntervals(const Array& value) const { |
| 12303 if (raw_ptr()->inlined_metadata_ == Array::null()) { |
| 12304 StorePointer(&raw_ptr()->inlined_metadata_, |
| 12305 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); |
| 12306 } |
| 12307 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
| 12308 ASSERT(!metadata.IsNull()); |
| 12309 ASSERT(metadata.IsOld()); |
| 12310 ASSERT(value.IsOld()); |
| 12311 metadata.SetAt(RawCode::kInlinedIntervalsIndex, value); |
| 12312 } |
| 12313 |
| 12314 |
| 12315 RawArray* Code::GetInlinedIdToFunction() const { |
| 12316 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
| 12317 if (metadata.IsNull()) { |
| 12318 return metadata.raw(); |
| 12319 } |
| 12320 return reinterpret_cast<RawArray*>( |
| 12321 metadata.At(RawCode::kInlinedIdToFunctionIndex)); |
| 12322 } |
| 12323 |
| 12324 |
| 12325 void Code::SetInlinedIdToFunction(const Array& value) const { |
| 12326 if (raw_ptr()->inlined_metadata_ == Array::null()) { |
| 12327 StorePointer(&raw_ptr()->inlined_metadata_, |
| 12328 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); |
| 12329 } |
| 12330 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); |
| 12331 ASSERT(!metadata.IsNull()); |
| 12332 ASSERT(metadata.IsOld()); |
| 12333 ASSERT(value.IsOld()); |
| 12334 metadata.SetAt(RawCode::kInlinedIdToFunctionIndex, value); |
| 12335 } |
| 12336 |
| 12337 |
| 12285 RawCode* Code::New(intptr_t pointer_offsets_length) { | 12338 RawCode* Code::New(intptr_t pointer_offsets_length) { |
| 12286 if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) { | 12339 if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) { |
| 12287 // This should be caught before we reach here. | 12340 // This should be caught before we reach here. |
| 12288 FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n", | 12341 FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n", |
| 12289 pointer_offsets_length); | 12342 pointer_offsets_length); |
| 12290 } | 12343 } |
| 12291 ASSERT(Object::code_class() != Class::null()); | 12344 ASSERT(Object::code_class() != Class::null()); |
| 12292 Code& result = Code::Handle(); | 12345 Code& result = Code::Handle(); |
| 12293 { | 12346 { |
| 12294 uword size = Code::InstanceSize(pointer_offsets_length); | 12347 uword size = Code::InstanceSize(pointer_offsets_length); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12377 if (FLAG_write_protect_code) { | 12430 if (FLAG_write_protect_code) { |
| 12378 uword address = RawObject::ToAddr(instrs.raw()); | 12431 uword address = RawObject::ToAddr(instrs.raw()); |
| 12379 bool status = VirtualMemory::Protect( | 12432 bool status = VirtualMemory::Protect( |
| 12380 reinterpret_cast<void*>(address), | 12433 reinterpret_cast<void*>(address), |
| 12381 instrs.raw()->Size(), | 12434 instrs.raw()->Size(), |
| 12382 VirtualMemory::kReadExecute); | 12435 VirtualMemory::kReadExecute); |
| 12383 ASSERT(status); | 12436 ASSERT(status); |
| 12384 } | 12437 } |
| 12385 } | 12438 } |
| 12386 code.set_comments(assembler->GetCodeComments()); | 12439 code.set_comments(assembler->GetCodeComments()); |
| 12440 if (assembler->prologue_offset() >= 0) { |
| 12441 code.SetPrologueOffset(assembler->prologue_offset()); |
| 12442 } else { |
| 12443 // No prologue was ever entered, optimistically assume nothing was ever |
| 12444 // pushed onto the stack. |
| 12445 code.SetPrologueOffset(assembler->CodeSize()); |
| 12446 } |
| 12387 INC_STAT(Isolate::Current(), | 12447 INC_STAT(Isolate::Current(), |
| 12388 total_code_size, code.comments().comments_.Length()); | 12448 total_code_size, code.comments().comments_.Length()); |
| 12389 return code.raw(); | 12449 return code.raw(); |
| 12390 } | 12450 } |
| 12391 | 12451 |
| 12392 | 12452 |
| 12393 RawCode* Code::FinalizeCode(const Function& function, | 12453 RawCode* Code::FinalizeCode(const Function& function, |
| 12394 Assembler* assembler, | 12454 Assembler* assembler, |
| 12395 bool optimized) { | 12455 bool optimized) { |
| 12396 // Calling ToLibNamePrefixedQualifiedCString is very expensive, | 12456 // Calling ToLibNamePrefixedQualifiedCString is very expensive, |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12608 // Only disassemble alive code objects. | 12668 // Only disassemble alive code objects. |
| 12609 DisassembleToJSONStream formatter(jsarr); | 12669 DisassembleToJSONStream formatter(jsarr); |
| 12610 Disassemble(&formatter); | 12670 Disassemble(&formatter); |
| 12611 } | 12671 } |
| 12612 } | 12672 } |
| 12613 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 12673 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
| 12614 if (!descriptors.IsNull()) { | 12674 if (!descriptors.IsNull()) { |
| 12615 JSONObject desc(&jsobj, "_descriptors"); | 12675 JSONObject desc(&jsobj, "_descriptors"); |
| 12616 descriptors.PrintToJSONObject(&desc, false); | 12676 descriptors.PrintToJSONObject(&desc, false); |
| 12617 } | 12677 } |
| 12618 const Array& inlined_function_table = Array::Handle(inlined_id_to_function()); | 12678 const Array& inlined_function_table = Array::Handle(GetInlinedIdToFunction()); |
| 12619 if (!inlined_function_table.IsNull() && | 12679 if (!inlined_function_table.IsNull() && |
| 12620 (inlined_function_table.Length() > 0)) { | 12680 (inlined_function_table.Length() > 0)) { |
| 12621 JSONArray inlined_functions(&jsobj, "_inlinedFunctions"); | 12681 JSONArray inlined_functions(&jsobj, "_inlinedFunctions"); |
| 12622 Function& function = Function::Handle(); | 12682 Function& function = Function::Handle(); |
| 12623 for (intptr_t i = 0; i < inlined_function_table.Length(); i++) { | 12683 for (intptr_t i = 0; i < inlined_function_table.Length(); i++) { |
| 12624 function ^= inlined_function_table.At(i); | 12684 function ^= inlined_function_table.At(i); |
| 12625 ASSERT(!function.IsNull()); | 12685 ASSERT(!function.IsNull()); |
| 12626 inlined_functions.AddValue(function); | 12686 inlined_functions.AddValue(function); |
| 12627 } | 12687 } |
| 12628 } | 12688 } |
| 12629 const Array& intervals = Array::Handle(inlined_intervals()); | 12689 const Array& intervals = Array::Handle(GetInlinedIntervals()); |
| 12630 if (!intervals.IsNull() && (intervals.Length() > 0)) { | 12690 if (!intervals.IsNull() && (intervals.Length() > 0)) { |
| 12631 Smi& start = Smi::Handle(); | 12691 Smi& start = Smi::Handle(); |
| 12632 Smi& end = Smi::Handle(); | 12692 Smi& end = Smi::Handle(); |
| 12633 Smi& temp_smi = Smi::Handle(); | 12693 Smi& temp_smi = Smi::Handle(); |
| 12634 JSONArray inline_intervals(&jsobj, "_inlinedIntervals"); | 12694 JSONArray inline_intervals(&jsobj, "_inlinedIntervals"); |
| 12635 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; | 12695 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; |
| 12636 i += Code::kInlIntNumEntries) { | 12696 i += Code::kInlIntNumEntries) { |
| 12637 start ^= intervals.At(i + Code::kInlIntStart); | 12697 start ^= intervals.At(i + Code::kInlIntStart); |
| 12638 if (start.IsNull()) { | 12698 if (start.IsNull()) { |
| 12639 continue; | 12699 continue; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12699 return map->raw(); // We found a stack map for this frame. | 12759 return map->raw(); // We found a stack map for this frame. |
| 12700 } | 12760 } |
| 12701 } | 12761 } |
| 12702 ASSERT(!is_optimized()); | 12762 ASSERT(!is_optimized()); |
| 12703 return Stackmap::null(); | 12763 return Stackmap::null(); |
| 12704 } | 12764 } |
| 12705 | 12765 |
| 12706 | 12766 |
| 12707 intptr_t Code::GetCallerId(intptr_t inlined_id) const { | 12767 intptr_t Code::GetCallerId(intptr_t inlined_id) const { |
| 12708 if (inlined_id < 0) return -1; | 12768 if (inlined_id < 0) return -1; |
| 12709 const Array& intervals = Array::Handle(inlined_intervals()); | 12769 const Array& intervals = Array::Handle(GetInlinedIntervals()); |
| 12710 if (intervals.IsNull() || (intervals.Length() == 0)) return -1; | 12770 if (intervals.IsNull() || (intervals.Length() == 0)) return -1; |
| 12711 Smi& temp_smi = Smi::Handle(); | 12771 Smi& temp_smi = Smi::Handle(); |
| 12712 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; | 12772 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; |
| 12713 i += Code::kInlIntNumEntries) { | 12773 i += Code::kInlIntNumEntries) { |
| 12714 temp_smi ^= intervals.At(i + Code::kInlIntInliningId); | 12774 temp_smi ^= intervals.At(i + Code::kInlIntInliningId); |
| 12715 if (temp_smi.Value() == inlined_id) { | 12775 if (temp_smi.Value() == inlined_id) { |
| 12716 temp_smi ^= intervals.At(i + Code::kInlIntCallerId); | 12776 temp_smi ^= intervals.At(i + Code::kInlIntCallerId); |
| 12717 return temp_smi.Value(); | 12777 return temp_smi.Value(); |
| 12718 } | 12778 } |
| 12719 } | 12779 } |
| 12720 return -1; | 12780 return -1; |
| 12721 } | 12781 } |
| 12722 | 12782 |
| 12723 | 12783 |
| 12724 void Code::GetInlinedFunctionsAt( | 12784 void Code::GetInlinedFunctionsAt( |
| 12725 intptr_t offset, GrowableArray<Function*>* fs) const { | 12785 intptr_t offset, GrowableArray<Function*>* fs) const { |
| 12726 fs->Clear(); | 12786 fs->Clear(); |
| 12727 const Array& intervals = Array::Handle(inlined_intervals()); | 12787 const Array& intervals = Array::Handle(GetInlinedIntervals()); |
| 12728 if (intervals.IsNull() || (intervals.Length() == 0)) { | 12788 if (intervals.IsNull() || (intervals.Length() == 0)) { |
| 12729 // E.g., for code stubs. | 12789 // E.g., for code stubs. |
| 12730 return; | 12790 return; |
| 12731 } | 12791 } |
| 12732 // First find the right interval. TODO(srdjan): use binary search since | 12792 // First find the right interval. TODO(srdjan): use binary search since |
| 12733 // intervals are sorted. | 12793 // intervals are sorted. |
| 12734 Smi& start = Smi::Handle(); | 12794 Smi& start = Smi::Handle(); |
| 12735 Smi& end = Smi::Handle(); | 12795 Smi& end = Smi::Handle(); |
| 12736 intptr_t found_interval_ix = intervals.Length() - Code::kInlIntNumEntries; | 12796 intptr_t found_interval_ix = intervals.Length() - Code::kInlIntNumEntries; |
| 12737 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; | 12797 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; |
| 12738 i += Code::kInlIntNumEntries) { | 12798 i += Code::kInlIntNumEntries) { |
| 12739 start ^= intervals.At(i + Code::kInlIntStart); | 12799 start ^= intervals.At(i + Code::kInlIntStart); |
| 12740 if (!start.IsNull()) { | 12800 if (!start.IsNull()) { |
| 12741 end ^= intervals.At(i + Code::kInlIntNumEntries + Code::kInlIntStart); | 12801 end ^= intervals.At(i + Code::kInlIntNumEntries + Code::kInlIntStart); |
| 12742 if ((start.Value() <= offset) && (offset < end.Value())) { | 12802 if ((start.Value() <= offset) && (offset < end.Value())) { |
| 12743 found_interval_ix = i; | 12803 found_interval_ix = i; |
| 12744 break; | 12804 break; |
| 12745 } | 12805 } |
| 12746 } | 12806 } |
| 12747 } | 12807 } |
| 12748 | 12808 |
| 12749 // Find all functions. | 12809 // Find all functions. |
| 12750 const Array& id_map = Array::Handle(inlined_id_to_function()); | 12810 const Array& id_map = Array::Handle(GetInlinedIdToFunction()); |
| 12751 Smi& temp_smi = Smi::Handle(); | 12811 Smi& temp_smi = Smi::Handle(); |
| 12752 temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntInliningId); | 12812 temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntInliningId); |
| 12753 intptr_t inlining_id = temp_smi.Value(); | 12813 intptr_t inlining_id = temp_smi.Value(); |
| 12754 ASSERT(inlining_id >= 0); | 12814 ASSERT(inlining_id >= 0); |
| 12755 temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntCallerId); | 12815 temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntCallerId); |
| 12756 intptr_t caller_id = temp_smi.Value(); | 12816 intptr_t caller_id = temp_smi.Value(); |
| 12757 while (inlining_id >= 0) { | 12817 while (inlining_id >= 0) { |
| 12758 Function& function = Function::ZoneHandle(); | 12818 Function& function = Function::ZoneHandle(); |
| 12759 function ^= id_map.At(inlining_id); | 12819 function ^= id_map.At(inlining_id); |
| 12760 fs->Add(&function); | 12820 fs->Add(&function); |
| 12761 inlining_id = caller_id; | 12821 inlining_id = caller_id; |
| 12762 caller_id = GetCallerId(inlining_id); | 12822 caller_id = GetCallerId(inlining_id); |
| 12763 } | 12823 } |
| 12764 } | 12824 } |
| 12765 | 12825 |
| 12766 | 12826 |
| 12767 void Code::DumpInlinedIntervals() const { | 12827 void Code::DumpInlinedIntervals() const { |
| 12768 OS::Print("Inlined intervals:\n"); | 12828 OS::Print("Inlined intervals:\n"); |
| 12769 const Array& intervals = Array::Handle(inlined_intervals()); | 12829 const Array& intervals = Array::Handle(GetInlinedIntervals()); |
| 12770 if (intervals.IsNull() || (intervals.Length() == 0)) return; | 12830 if (intervals.IsNull() || (intervals.Length() == 0)) return; |
| 12771 Smi& start = Smi::Handle(); | 12831 Smi& start = Smi::Handle(); |
| 12772 Smi& inlining_id = Smi::Handle(); | 12832 Smi& inlining_id = Smi::Handle(); |
| 12773 Smi& caller_id = Smi::Handle(); | 12833 Smi& caller_id = Smi::Handle(); |
| 12774 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { | 12834 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { |
| 12775 start ^= intervals.At(i + Code::kInlIntStart); | 12835 start ^= intervals.At(i + Code::kInlIntStart); |
| 12776 ASSERT(!start.IsNull()); | 12836 ASSERT(!start.IsNull()); |
| 12777 if (start.IsNull()) continue; | 12837 if (start.IsNull()) continue; |
| 12778 inlining_id ^= intervals.At(i + Code::kInlIntInliningId); | 12838 inlining_id ^= intervals.At(i + Code::kInlIntInliningId); |
| 12779 caller_id ^= intervals.At(i + Code::kInlIntCallerId); | 12839 caller_id ^= intervals.At(i + Code::kInlIntCallerId); |
| 12780 OS::Print(" %" Px " id: %" Pd " caller-id: %" Pd " \n", | 12840 OS::Print(" %" Px " id: %" Pd " caller-id: %" Pd " \n", |
| 12781 start.Value(), inlining_id.Value(), caller_id.Value()); | 12841 start.Value(), inlining_id.Value(), caller_id.Value()); |
| 12782 } | 12842 } |
| 12783 OS::Print("Inlined ids:\n"); | 12843 OS::Print("Inlined ids:\n"); |
| 12784 const Array& id_map = Array::Handle(inlined_id_to_function()); | 12844 const Array& id_map = Array::Handle(GetInlinedIdToFunction()); |
| 12785 Function& function = Function::Handle(); | 12845 Function& function = Function::Handle(); |
| 12786 for (intptr_t i = 0; i < id_map.Length(); i++) { | 12846 for (intptr_t i = 0; i < id_map.Length(); i++) { |
| 12787 function ^= id_map.At(i); | 12847 function ^= id_map.At(i); |
| 12788 if (!function.IsNull()) { | 12848 if (!function.IsNull()) { |
| 12789 OS::Print(" %" Pd ": %s\n", i, function.ToQualifiedCString()); | 12849 OS::Print(" %" Pd ": %s\n", i, function.ToQualifiedCString()); |
| 12790 } | 12850 } |
| 12791 } | 12851 } |
| 12792 } | 12852 } |
| 12793 | 12853 |
| 12794 | 12854 |
| (...skipping 7935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20730 return tag_label.ToCString(); | 20790 return tag_label.ToCString(); |
| 20731 } | 20791 } |
| 20732 | 20792 |
| 20733 | 20793 |
| 20734 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 20794 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| 20735 Instance::PrintJSONImpl(stream, ref); | 20795 Instance::PrintJSONImpl(stream, ref); |
| 20736 } | 20796 } |
| 20737 | 20797 |
| 20738 | 20798 |
| 20739 } // namespace dart | 20799 } // namespace dart |
| OLD | NEW |