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 |