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

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

Issue 1150633002: Track prologue offset of Code and use for more precise return addresses (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 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/object.h ('k') | runtime/vm/profiler.cc » ('j') | 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 12252 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698