| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/isolate.h" | 7 #include "vm/isolate.h" |
| 8 #include "vm/object.h" | 8 #include "vm/object.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 #include "vm/os.h" | 10 #include "vm/os.h" |
| 11 #include "vm/raw_object.h" | 11 #include "vm/raw_object.h" |
| 12 #include "vm/stub_code.h" | 12 #include "vm/stub_code.h" |
| 13 #include "vm/visitor.h" | 13 #include "vm/visitor.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 | 16 |
| 17 bool StackFrame::FindRawCodeVisitor::FindObject(RawObject* obj) { | 17 bool StackFrame::FindRawCodeVisitor::FindObject(RawObject* obj) { |
| 18 return RawInstructions::ContainsPC(obj, pc_); | 18 return RawInstructions::ContainsPC(obj, pc_); |
| 19 } | 19 } |
| 20 | 20 |
| 21 | 21 |
| 22 bool StackFrame::IsStubFrame() const { |
| 23 if (Dart::vm_isolate()->heap()->CodeContains(pc())) { |
| 24 return true; // Common stub code is generated in the VM heap. |
| 25 } |
| 26 // We add a no gc scope to ensure that the code below does not trigger |
| 27 // a GC as we are handling raw object references here. It is possible |
| 28 // that the code is called while a GC is in progress, that is ok. |
| 29 NoGCScope no_gc; |
| 30 Isolate* isolate = Isolate::Current(); |
| 31 RawCode* code = StackFrame::LookupCode(isolate, pc()); |
| 32 return ((code != Code::null()) && |
| 33 (code->ptr()->function_ == Function::null())); |
| 34 } |
| 35 |
| 36 |
| 22 void StackFrame::Print() const { | 37 void StackFrame::Print() const { |
| 23 OS::Print("[%-8s : sp(%p) ]\n", GetName(), sp()); | 38 OS::Print("[%-8s : sp(%p) ]\n", GetName(), sp()); |
| 24 } | 39 } |
| 25 | 40 |
| 26 | 41 |
| 27 RawCode* StackFrame::LookupCode(Isolate* isolate, uword pc) { | 42 RawCode* StackFrame::LookupCode(Isolate* isolate, uword pc) { |
| 28 // TODO(asiva): Need to add a data structure for storing a (pc, code | 43 // TODO(asiva): Need to add a data structure for storing a (pc, code |
| 29 // object) map in order to do a quick lookup and avoid having to | 44 // object) map in order to do a quick lookup and avoid having to |
| 30 // traverse the code heap. | 45 // traverse the code heap. |
| 31 ASSERT(isolate != NULL); | 46 ASSERT(isolate != NULL); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 50 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 65 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 51 // Visit objects between SP and (FP - callee_save_area). | 66 // Visit objects between SP and (FP - callee_save_area). |
| 52 ASSERT(visitor != NULL); | 67 ASSERT(visitor != NULL); |
| 53 RawObject** start = reinterpret_cast<RawObject**>(sp()); | 68 RawObject** start = reinterpret_cast<RawObject**>(sp()); |
| 54 RawObject** end = reinterpret_cast<RawObject**>( | 69 RawObject** end = reinterpret_cast<RawObject**>( |
| 55 fp() - kWordSize + ExitLinkOffset()); | 70 fp() - kWordSize + ExitLinkOffset()); |
| 56 visitor->VisitPointers(start, end); | 71 visitor->VisitPointers(start, end); |
| 57 } | 72 } |
| 58 | 73 |
| 59 | 74 |
| 60 void DartFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 75 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 61 // NOTE: This code runs while GC is in progress and runs within | 76 // NOTE: This code runs while GC is in progress and runs within |
| 62 // a NoHandleScope block. Hence it is not ok to use regular Zone or | 77 // a NoHandleScope block. Hence it is not ok to use regular Zone or |
| 63 // Scope handles. We use direct stack handles, the raw pointers in | 78 // Scope handles. We use direct stack handles, the raw pointers in |
| 64 // these handles are not traversed. The use of handles is mainly to | 79 // these handles are not traversed. The use of handles is mainly to |
| 65 // be able to reuse the handle based code and avoid having to add | 80 // be able to reuse the handle based code and avoid having to add |
| 66 // helper functions to the raw object interface. | 81 // helper functions to the raw object interface. |
| 67 NoGCScope no_gc; | 82 NoGCScope no_gc; |
| 68 Code code; | 83 Code code; |
| 69 code = LookupDartCode(); | 84 code = LookupDartCode(); |
| 70 ASSERT(!code.IsNull()); | 85 if (!code.IsNull()) { |
| 71 Array maps; | 86 Array maps; |
| 72 maps = Array::null(); | 87 maps = Array::null(); |
| 73 Stackmap map; | 88 Stackmap map; |
| 74 map = code.GetStackmap(pc(), &maps, &map); | 89 map = code.GetStackmap(pc(), &maps, &map); |
| 75 if (map.IsNull()) { | 90 if (!map.IsNull()) { |
| 76 // No stack maps are present in the code object which means this | 91 // A stack map is present in the code object, use the stack map to visit |
| 77 // frame relies on tagged pointers and hence we visit each entry | 92 // frame slots which are marked as having objects. |
| 78 // on the frame between SP and FP. | 93 intptr_t bit_offset = map.MinimumBitOffset(); |
| 79 ASSERT(visitor != NULL); | 94 intptr_t end_bit_offset = map.MaximumBitOffset(); |
| 80 visitor->VisitPointers(reinterpret_cast<RawObject**>(sp()), | 95 while (bit_offset <= end_bit_offset) { |
| 81 reinterpret_cast<RawObject**>(fp() - kWordSize)); | 96 uword addr = (fp() - ((bit_offset + 1) * kWordSize)); |
| 82 return; | 97 ASSERT(addr >= sp()); |
| 98 if (map.IsObject(bit_offset)) { |
| 99 visitor->VisitPointer(reinterpret_cast<RawObject**>(addr)); |
| 100 } |
| 101 bit_offset += 1; |
| 102 } |
| 103 return; |
| 104 } |
| 83 } | 105 } |
| 84 // A stack map is present in the code object, use the stack map to visit | 106 // No stack maps are present in the code object which means this |
| 85 // frame slots which are marked as having objects. | 107 // frame relies on tagged pointers and hence we visit each entry |
| 86 intptr_t bit_offset = map.MinimumBitOffset(); | 108 // on the frame between SP and FP. |
| 87 intptr_t end_bit_offset = map.MaximumBitOffset(); | 109 ASSERT(visitor != NULL); |
| 88 while (bit_offset <= end_bit_offset) { | 110 visitor->VisitPointers(reinterpret_cast<RawObject**>(sp()), |
| 89 uword addr = (fp() - ((bit_offset + 1) * kWordSize)); | 111 reinterpret_cast<RawObject**>(fp() - kWordSize)); |
| 90 ASSERT(addr >= sp()); | |
| 91 if (map.IsObject(bit_offset)) { | |
| 92 visitor->VisitPointer(reinterpret_cast<RawObject**>(addr)); | |
| 93 } | |
| 94 bit_offset += 1; | |
| 95 } | |
| 96 } | 112 } |
| 97 | 113 |
| 98 | 114 |
| 99 RawFunction* DartFrame::LookupDartFunction() const { | 115 RawFunction* StackFrame::LookupDartFunction() const { |
| 100 const Code& code = Code::Handle(LookupDartCode()); | 116 const Code& code = Code::Handle(LookupDartCode()); |
| 101 if (!code.IsNull()) { | 117 if (!code.IsNull()) { |
| 102 return code.function(); | 118 return code.function(); |
| 103 } | 119 } |
| 104 return Function::null(); | 120 return Function::null(); |
| 105 } | 121 } |
| 106 | 122 |
| 107 | 123 |
| 108 RawCode* DartFrame::LookupDartCode() const { | 124 RawCode* StackFrame::LookupDartCode() const { |
| 109 // We add a no gc scope to ensure that the code below does not trigger | 125 // We add a no gc scope to ensure that the code below does not trigger |
| 110 // a GC as we are handling raw object references here. It is possible | 126 // a GC as we are handling raw object references here. It is possible |
| 111 // that the code is called while a GC is in progress, that is ok. | 127 // that the code is called while a GC is in progress, that is ok. |
| 112 NoGCScope no_gc; | 128 NoGCScope no_gc; |
| 113 Isolate* isolate = Isolate::Current(); | 129 Isolate* isolate = Isolate::Current(); |
| 114 RawCode* code = StackFrame::LookupCode(isolate, pc()); | 130 RawCode* code = StackFrame::LookupCode(isolate, pc()); |
| 115 ASSERT(code != Code::null() && code->ptr()->function_ != Function::null()); | 131 if ((code != Code::null()) && (code->ptr()->function_ != Function::null())) { |
| 116 return code; | 132 return code; |
| 133 } |
| 134 return Code::null(); |
| 117 } | 135 } |
| 118 | 136 |
| 119 | 137 |
| 120 bool DartFrame::FindExceptionHandler(uword* handler_pc) const { | 138 bool StackFrame::FindExceptionHandler(uword* handler_pc) const { |
| 121 const Code& code = Code::Handle(LookupDartCode()); | 139 const Code& code = Code::Handle(LookupDartCode()); |
| 122 ASSERT(!code.IsNull()); | 140 if (code.IsNull()) { |
| 141 return false; // Stub frames do not have exception handlers. |
| 142 } |
| 123 | 143 |
| 124 // First try to find pc descriptor for the current pc. | 144 // First try to find pc descriptor for the current pc. |
| 125 intptr_t try_index = -1; | 145 intptr_t try_index = -1; |
| 126 const PcDescriptors& descriptors = | 146 const PcDescriptors& descriptors = |
| 127 PcDescriptors::Handle(code.pc_descriptors()); | 147 PcDescriptors::Handle(code.pc_descriptors()); |
| 128 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 148 for (intptr_t i = 0; i < descriptors.Length(); i++) { |
| 129 if (static_cast<uword>(descriptors.PC(i)) == pc() && | 149 if (static_cast<uword>(descriptors.PC(i)) == pc() && |
| 130 descriptors.TryIndex(i) != -1) { | 150 descriptors.TryIndex(i) != -1) { |
| 131 try_index = descriptors.TryIndex(i); | 151 try_index = descriptors.TryIndex(i); |
| 132 break; | 152 break; |
| 133 } | 153 } |
| 134 } | 154 } |
| 135 if (try_index != -1) { | 155 if (try_index != -1) { |
| 136 // We found a pc descriptor, now try to see if we have an | 156 // We found a pc descriptor, now try to see if we have an |
| 137 // exception catch handler for this try index. | 157 // exception catch handler for this try index. |
| 138 const ExceptionHandlers& handlers = | 158 const ExceptionHandlers& handlers = |
| 139 ExceptionHandlers::Handle(code.exception_handlers()); | 159 ExceptionHandlers::Handle(code.exception_handlers()); |
| 140 for (intptr_t j = 0; j < handlers.Length(); j++) { | 160 for (intptr_t j = 0; j < handlers.Length(); j++) { |
| 141 if (handlers.TryIndex(j) == try_index) { | 161 if (handlers.TryIndex(j) == try_index) { |
| 142 *handler_pc = handlers.HandlerPC(j); | 162 *handler_pc = handlers.HandlerPC(j); |
| 143 return true; | 163 return true; |
| 144 } | 164 } |
| 145 } | 165 } |
| 146 } | 166 } |
| 147 return false; | 167 return false; |
| 148 } | 168 } |
| 149 | 169 |
| 150 | 170 |
| 151 bool StubFrame::IsValid() const { | 171 bool StackFrame::IsValid() const { |
| 152 // We add a no gc scope to ensure that the code below does not trigger | 172 if (IsEntryFrame() || IsExitFrame()) { |
| 153 // a GC as we are handling raw object references here. It is possible | 173 return true; |
| 154 // that the code is called while a GC is in progress, that is ok. | 174 } |
| 155 NoGCScope no_gc; | |
| 156 Isolate* isolate = Isolate::Current(); | |
| 157 if (Dart::vm_isolate()->heap()->CodeContains(pc())) { | 175 if (Dart::vm_isolate()->heap()->CodeContains(pc())) { |
| 158 return true; // Common stub code is generated in the VM heap. | 176 return true; // Common stub code is generated in the VM heap. |
| 159 } | 177 } |
| 160 RawCode* code = StackFrame::LookupCode(isolate, pc()); | 178 return (StackFrame::LookupCode(Isolate::Current(), pc()) != Code::null()); |
| 161 return (code != Code::null() && code->ptr()->function_ == Function::null()); | |
| 162 } | |
| 163 | |
| 164 | |
| 165 void StubFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | |
| 166 // Visit objects between SP and FP. | |
| 167 ASSERT(visitor != NULL); | |
| 168 visitor->VisitPointers(reinterpret_cast<RawObject**>(sp()), | |
| 169 reinterpret_cast<RawObject**>(fp() - kWordSize)); | |
| 170 } | 179 } |
| 171 | 180 |
| 172 | 181 |
| 173 StackFrameIterator::StackFrameIterator(bool validate) | 182 StackFrameIterator::StackFrameIterator(bool validate) |
| 174 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { | 183 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { |
| 175 SetupLastExitFrameData(); // Setup data for last exit frame. | 184 SetupLastExitFrameData(); // Setup data for last exit frame. |
| 176 } | 185 } |
| 177 | 186 |
| 178 | 187 |
| 179 StackFrame* StackFrameIterator::NextFrame() { | 188 StackFrame* StackFrameIterator::NextFrame() { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 // corresponding entry frame for that set of dart/stub frames. | 222 // corresponding entry frame for that set of dart/stub frames. |
| 214 current_frame_ = | 223 current_frame_ = |
| 215 (frames_.HasNext()) ? frames_.NextFrame(validate_) : NextEntryFrame(); | 224 (frames_.HasNext()) ? frames_.NextFrame(validate_) : NextEntryFrame(); |
| 216 return current_frame_; | 225 return current_frame_; |
| 217 } | 226 } |
| 218 | 227 |
| 219 | 228 |
| 220 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { | 229 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { |
| 221 StackFrame* frame; | 230 StackFrame* frame; |
| 222 ASSERT(HasNext()); | 231 ASSERT(HasNext()); |
| 223 if (from_stub_exitframe_) { | 232 frame = &stack_frame_; |
| 224 frame = &stub_frame_; | |
| 225 } else { | |
| 226 frame = &dart_frame_; | |
| 227 } | |
| 228 frame->sp_ = sp_; | 233 frame->sp_ = sp_; |
| 229 frame->fp_ = fp_; | 234 frame->fp_ = fp_; |
| 230 sp_ = frame->GetCallerSp(); | 235 sp_ = frame->GetCallerSp(); |
| 231 fp_ = frame->GetCallerFp(); | 236 fp_ = frame->GetCallerFp(); |
| 232 from_stub_exitframe_ = false; | |
| 233 ASSERT((validate == kDontValidateFrames) || frame->IsValid()); | 237 ASSERT((validate == kDontValidateFrames) || frame->IsValid()); |
| 234 return frame; | 238 return frame; |
| 235 } | 239 } |
| 236 | 240 |
| 237 | 241 |
| 238 ExitFrame* StackFrameIterator::NextExitFrame() { | 242 ExitFrame* StackFrameIterator::NextExitFrame() { |
| 239 exit_.sp_ = frames_.sp_; | 243 exit_.sp_ = frames_.sp_; |
| 240 exit_.fp_ = frames_.fp_; | 244 exit_.fp_ = frames_.fp_; |
| 241 frames_.sp_ = exit_.GetCallerSp(); | 245 frames_.sp_ = exit_.GetCallerSp(); |
| 242 frames_.fp_ = exit_.GetCallerFp(); | 246 frames_.fp_ = exit_.GetCallerFp(); |
| 243 ASSERT(exit_.IsValid()); | 247 ASSERT(exit_.IsValid()); |
| 244 return &exit_; | 248 return &exit_; |
| 245 } | 249 } |
| 246 | 250 |
| 247 | 251 |
| 248 EntryFrame* StackFrameIterator::NextEntryFrame() { | 252 EntryFrame* StackFrameIterator::NextEntryFrame() { |
| 249 ASSERT(!frames_.HasNext()); | 253 ASSERT(!frames_.HasNext()); |
| 250 entry_.sp_ = frames_.sp_; | 254 entry_.sp_ = frames_.sp_; |
| 251 entry_.fp_ = frames_.fp_; | 255 entry_.fp_ = frames_.fp_; |
| 252 SetupNextExitFrameData(); // Setup data for next exit frame in chain. | 256 SetupNextExitFrameData(); // Setup data for next exit frame in chain. |
| 253 ASSERT(entry_.IsValid()); | 257 ASSERT(entry_.IsValid()); |
| 254 return &entry_; | 258 return &entry_; |
| 255 } | 259 } |
| 256 | 260 |
| 257 } // namespace dart | 261 } // namespace dart |
| OLD | NEW |