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

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

Powered by Google App Engine
This is Rietveld 408576698