| 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/stack_frame.h" | 5 #include "vm/stack_frame.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/deopt_instructions.h" | 8 #include "vm/deopt_instructions.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
| 12 #include "vm/os.h" | 12 #include "vm/os.h" |
| 13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
| 14 #include "vm/raw_object.h" | 14 #include "vm/raw_object.h" |
| 15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 16 #include "vm/visitor.h" | 16 #include "vm/visitor.h" |
| 17 | 17 |
| 18 namespace dart { | 18 namespace dart { |
| 19 | 19 |
| 20 | 20 |
| 21 bool StackFrame::IsStubFrame() const { | 21 bool StackFrame::IsStubFrame() const { |
| 22 ASSERT(!(IsEntryFrame() || IsExitFrame())); | 22 ASSERT(!(IsEntryFrame() || IsExitFrame())); |
| 23 uword saved_pc = | 23 uword saved_pc = |
| 24 *(reinterpret_cast<uword*>(fp() + EntrypointMarkerOffsetFromFp())); | 24 *(reinterpret_cast<uword*>(fp() + (kPcMarkerSlotFromFp * kWordSize))); |
| 25 return (saved_pc == 0); | 25 return (saved_pc == 0); |
| 26 } | 26 } |
| 27 | 27 |
| 28 | 28 |
| 29 void StackFrame::Print() const { | 29 void StackFrame::Print() const { |
| 30 OS::Print("[%-8s : sp(%#"Px") ]\n", GetName(), sp()); | 30 OS::Print("[%-8s : sp(%#"Px") ]\n", GetName(), sp()); |
| 31 } | 31 } |
| 32 | 32 |
| 33 | 33 |
| 34 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 34 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 35 // There are no objects to visit in this frame. | 35 // There are no objects to visit in this frame. |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 RawContext* EntryFrame::SavedContext() const { | 39 RawContext* EntryFrame::SavedContext() const { |
| 40 return *(reinterpret_cast<RawContext**>(fp() + SavedContextOffset())); | 40 return *(reinterpret_cast<RawContext**>( |
| 41 fp() + (kSavedContextSlotFromEntryFp * kWordSize))); |
| 41 } | 42 } |
| 42 | 43 |
| 43 | 44 |
| 44 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 45 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 45 // Visit objects between SP and (FP - callee_save_area). | 46 // Visit objects between SP and (FP - callee_save_area). |
| 46 ASSERT(visitor != NULL); | 47 ASSERT(visitor != NULL); |
| 47 RawObject** start = reinterpret_cast<RawObject**>(sp()); | 48 RawObject** first = reinterpret_cast<RawObject**>(sp()); |
| 48 RawObject** end = reinterpret_cast<RawObject**>( | 49 RawObject** last = reinterpret_cast<RawObject**>( |
| 49 fp() - kWordSize + ExitLinkOffset()); | 50 fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize); |
| 50 visitor->VisitPointers(start, end); | 51 visitor->VisitPointers(first, last); |
| 51 } | 52 } |
| 52 | 53 |
| 53 | 54 |
| 54 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 55 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 55 // NOTE: This code runs while GC is in progress and runs within | 56 // NOTE: This code runs while GC is in progress and runs within |
| 56 // a NoHandleScope block. Hence it is not ok to use regular Zone or | 57 // a NoHandleScope block. Hence it is not ok to use regular Zone or |
| 57 // Scope handles. We use direct stack handles, the raw pointers in | 58 // Scope handles. We use direct stack handles, the raw pointers in |
| 58 // these handles are not traversed. The use of handles is mainly to | 59 // these handles are not traversed. The use of handles is mainly to |
| 59 // be able to reuse the handle based code and avoid having to add | 60 // be able to reuse the handle based code and avoid having to add |
| 60 // helper functions to the raw object interface. | 61 // helper functions to the raw object interface. |
| 61 ASSERT(visitor != NULL); | 62 ASSERT(visitor != NULL); |
| 62 NoGCScope no_gc; | 63 NoGCScope no_gc; |
| 63 RawObject** start_addr = reinterpret_cast<RawObject**>(sp()); | 64 RawObject** first = reinterpret_cast<RawObject**>(sp()); |
| 64 RawObject** end_addr = | 65 RawObject** last = reinterpret_cast<RawObject**>( |
| 65 reinterpret_cast<RawObject**>(fp()) + kFirstLocalSlotIndex; | 66 fp() + (kFirstLocalSlotFromFp * kWordSize)); |
| 66 Code code; | 67 Code code; |
| 67 code = LookupDartCode(); | 68 code = LookupDartCode(); |
| 68 if (!code.IsNull()) { | 69 if (!code.IsNull()) { |
| 69 // Visit the code object. | 70 // Visit the code object. |
| 70 RawObject* raw_code = code.raw(); | 71 RawObject* raw_code = code.raw(); |
| 71 visitor->VisitPointer(&raw_code); | 72 visitor->VisitPointer(&raw_code); |
| 72 // Visit stack based on stack maps. | 73 // Visit stack based on stack maps. |
| 73 Array maps; | 74 Array maps; |
| 74 maps = Array::null(); | 75 maps = Array::null(); |
| 75 Stackmap map; | 76 Stackmap map; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 86 // map. The outgoing arguments are assumed to be tagged; the number | 87 // map. The outgoing arguments are assumed to be tagged; the number |
| 87 // of outgoing arguments is not explicitly tracked. | 88 // of outgoing arguments is not explicitly tracked. |
| 88 // | 89 // |
| 89 // TODO(kmillikin): This does not handle slow path calls with | 90 // TODO(kmillikin): This does not handle slow path calls with |
| 90 // arguments, where the arguments are pushed after the live registers. | 91 // arguments, where the arguments are pushed after the live registers. |
| 91 // Enable such calls. | 92 // Enable such calls. |
| 92 intptr_t length = map.Length(); | 93 intptr_t length = map.Length(); |
| 93 // Spill slots are at the 'bottom' of the frame. | 94 // Spill slots are at the 'bottom' of the frame. |
| 94 intptr_t spill_slot_count = length - map.RegisterBitCount(); | 95 intptr_t spill_slot_count = length - map.RegisterBitCount(); |
| 95 for (intptr_t bit = 0; bit < spill_slot_count; ++bit) { | 96 for (intptr_t bit = 0; bit < spill_slot_count; ++bit) { |
| 96 if (map.IsObject(bit)) visitor->VisitPointer(end_addr); | 97 if (map.IsObject(bit)) visitor->VisitPointer(last); |
| 97 --end_addr; | 98 --last; |
| 98 } | 99 } |
| 99 | 100 |
| 100 // The live registers at the 'top' of the frame comprise the rest of the | 101 // The live registers at the 'top' of the frame comprise the rest of the |
| 101 // stack map. | 102 // stack map. |
| 102 for (intptr_t bit = length - 1; bit >= spill_slot_count; --bit) { | 103 for (intptr_t bit = length - 1; bit >= spill_slot_count; --bit) { |
| 103 if (map.IsObject(bit)) visitor->VisitPointer(start_addr); | 104 if (map.IsObject(bit)) visitor->VisitPointer(first); |
| 104 ++start_addr; | 105 ++first; |
| 105 } | 106 } |
| 106 | 107 |
| 107 // The end address can be one slot (but not more) past the start | 108 // The last slot can be one slot (but not more) past the last slot |
| 108 // address in the case that all slots were covered by the stack map. | 109 // in the case that all slots were covered by the stack map. |
| 109 ASSERT((end_addr + 1) >= start_addr); | 110 ASSERT((last + 1) >= first); |
| 110 } | 111 } |
| 111 } | 112 } |
| 112 // Each slot between the start and end address are tagged objects. | 113 // Each slot between the first and last included are tagged objects. |
| 113 visitor->VisitPointers(start_addr, end_addr); | 114 visitor->VisitPointers(first, last); |
| 114 } | 115 } |
| 115 | 116 |
| 116 | 117 |
| 117 RawFunction* StackFrame::LookupDartFunction() const { | 118 RawFunction* StackFrame::LookupDartFunction() const { |
| 118 const Code& code = Code::Handle(LookupDartCode()); | 119 const Code& code = Code::Handle(LookupDartCode()); |
| 119 if (!code.IsNull()) { | 120 if (!code.IsNull()) { |
| 120 return code.function(); | 121 return code.function(); |
| 121 } | 122 } |
| 122 return Function::null(); | 123 return Function::null(); |
| 123 } | 124 } |
| 124 | 125 |
| 125 | 126 |
| 126 RawCode* StackFrame::LookupDartCode() const { | 127 RawCode* StackFrame::LookupDartCode() const { |
| 127 // We add a no gc scope to ensure that the code below does not trigger | 128 // We add a no gc scope to ensure that the code below does not trigger |
| 128 // a GC as we are handling raw object references here. It is possible | 129 // a GC as we are handling raw object references here. It is possible |
| 129 // that the code is called while a GC is in progress, that is ok. | 130 // that the code is called while a GC is in progress, that is ok. |
| 130 NoGCScope no_gc; | 131 NoGCScope no_gc; |
| 131 RawCode* code = GetCodeObject(); | 132 RawCode* code = GetCodeObject(); |
| 132 ASSERT(code == Code::null() || code->ptr()->function_ != Function::null()); | 133 ASSERT(code == Code::null() || code->ptr()->function_ != Function::null()); |
| 133 return code; | 134 return code; |
| 134 } | 135 } |
| 135 | 136 |
| 136 | 137 |
| 137 RawCode* StackFrame::GetCodeObject() const { | 138 RawCode* StackFrame::GetCodeObject() const { |
| 138 // We add a no gc scope to ensure that the code below does not trigger | 139 // We add a no gc scope to ensure that the code below does not trigger |
| 139 // a GC as we are handling raw object references here. It is possible | 140 // a GC as we are handling raw object references here. It is possible |
| 140 // that the code is called while a GC is in progress, that is ok. | 141 // that the code is called while a GC is in progress, that is ok. |
| 141 NoGCScope no_gc; | 142 NoGCScope no_gc; |
| 142 uword saved_pc = | 143 const uword pc_marker = |
| 143 *(reinterpret_cast<uword*>(fp() + EntrypointMarkerOffsetFromFp())); | 144 *(reinterpret_cast<uword*>(fp() + (kPcMarkerSlotFromFp * kWordSize))); |
| 144 if (saved_pc != 0) { | 145 if (pc_marker != 0) { |
| 145 uword entry_point = | 146 const uword entry_point = |
| 146 (saved_pc - Assembler::kOffsetOfSavedPCfromEntrypoint); | 147 (pc_marker - Assembler::kEntryPointToPcMarkerOffset); |
| 147 RawInstructions* instr = Instructions::FromEntryPoint(entry_point); | 148 RawInstructions* instr = Instructions::FromEntryPoint(entry_point); |
| 148 if (instr != Instructions::null()) { | 149 if (instr != Instructions::null()) { |
| 149 return instr->ptr()->code_; | 150 return instr->ptr()->code_; |
| 150 } | 151 } |
| 151 } | 152 } |
| 152 return Code::null(); | 153 return Code::null(); |
| 153 } | 154 } |
| 154 | 155 |
| 155 | 156 |
| 156 bool StackFrame::FindExceptionHandler(uword* handler_pc) const { | 157 bool StackFrame::FindExceptionHandler(uword* handler_pc) const { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 | 196 |
| 196 | 197 |
| 197 bool StackFrame::IsValid() const { | 198 bool StackFrame::IsValid() const { |
| 198 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { | 199 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { |
| 199 return true; | 200 return true; |
| 200 } | 201 } |
| 201 return (LookupDartCode() != Code::null()); | 202 return (LookupDartCode() != Code::null()); |
| 202 } | 203 } |
| 203 | 204 |
| 204 | 205 |
| 206 void StackFrameIterator::SetupLastExitFrameData() { |
| 207 Isolate* current = Isolate::Current(); |
| 208 uword exit_marker = current->top_exit_frame_info(); |
| 209 frames_.fp_ = exit_marker; |
| 210 } |
| 211 |
| 212 |
| 213 void StackFrameIterator::SetupNextExitFrameData() { |
| 214 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); |
| 215 uword exit_marker = *reinterpret_cast<uword*>(exit_address); |
| 216 frames_.fp_ = exit_marker; |
| 217 frames_.sp_ = 0; |
| 218 } |
| 219 |
| 220 |
| 205 StackFrameIterator::StackFrameIterator(bool validate) | 221 StackFrameIterator::StackFrameIterator(bool validate) |
| 206 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { | 222 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { |
| 207 SetupLastExitFrameData(); // Setup data for last exit frame. | 223 SetupLastExitFrameData(); // Setup data for last exit frame. |
| 208 } | 224 } |
| 209 | 225 |
| 210 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate) | 226 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate) |
| 211 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { | 227 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { |
| 212 frames_.fp_ = last_fp; | 228 frames_.fp_ = last_fp; |
| 213 } | 229 } |
| 214 | 230 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &func); | 352 pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &func); |
| 337 code_ = func.unoptimized_code(); | 353 code_ = func.unoptimized_code(); |
| 338 function_ = func.raw(); | 354 function_ = func.raw(); |
| 339 return; | 355 return; |
| 340 } | 356 } |
| 341 } | 357 } |
| 342 SetDone(); | 358 SetDone(); |
| 343 } | 359 } |
| 344 | 360 |
| 345 } // namespace dart | 361 } // namespace dart |
| OLD | NEW |