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/code_descriptors.h" | 5 #include "vm/code_descriptors.h" |
6 | 6 |
7 #include "vm/log.h" | 7 #include "vm/log.h" |
8 | 8 |
9 namespace dart { | 9 namespace dart { |
10 | 10 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 Zone* zone = Thread::Current()->zone(); | 121 Zone* zone = Thread::Current()->zone(); |
122 return zone->Realloc<uint8_t>(ptr, old_size, new_size); | 122 return zone->Realloc<uint8_t>(ptr, old_size, new_size); |
123 } | 123 } |
124 | 124 |
125 | 125 |
126 const TokenPosition CodeSourceMapBuilder::kInitialPosition = | 126 const TokenPosition CodeSourceMapBuilder::kInitialPosition = |
127 TokenPosition::kDartCodePrologue; | 127 TokenPosition::kDartCodePrologue; |
128 | 128 |
129 | 129 |
130 CodeSourceMapBuilder::CodeSourceMapBuilder( | 130 CodeSourceMapBuilder::CodeSourceMapBuilder( |
| 131 bool stack_traces_only, |
131 const GrowableArray<intptr_t>& caller_inline_id, | 132 const GrowableArray<intptr_t>& caller_inline_id, |
132 const GrowableArray<TokenPosition>& inline_id_to_token_pos, | 133 const GrowableArray<TokenPosition>& inline_id_to_token_pos, |
133 const GrowableArray<const Function*>& inline_id_to_function) | 134 const GrowableArray<const Function*>& inline_id_to_function) |
134 : pc_offset_(0), | 135 : buffered_pc_offset_(0), |
135 advance_pc_peephole_(0), | 136 buffered_inline_id_stack_(), |
136 inline_id_stack_(), | 137 buffered_token_pos_stack_(), |
137 token_pos_stack_(), | 138 written_pc_offset_(0), |
| 139 written_inline_id_stack_(), |
| 140 written_token_pos_stack_(), |
138 caller_inline_id_(caller_inline_id), | 141 caller_inline_id_(caller_inline_id), |
139 inline_id_to_token_pos_(inline_id_to_token_pos), | 142 inline_id_to_token_pos_(inline_id_to_token_pos), |
140 inline_id_to_function_(inline_id_to_function), | 143 inline_id_to_function_(inline_id_to_function), |
141 buffer_(NULL), | 144 buffer_(NULL), |
142 stream_(&buffer_, zone_allocator, 64) { | 145 stream_(&buffer_, zone_allocator, 64), |
143 inline_id_stack_.Add(0); | 146 stack_traces_only_(stack_traces_only) { |
144 token_pos_stack_.Add(TokenPosition::kDartCodePrologue); | 147 buffered_inline_id_stack_.Add(0); |
| 148 buffered_token_pos_stack_.Add(kInitialPosition); |
| 149 written_inline_id_stack_.Add(0); |
| 150 written_token_pos_stack_.Add(kInitialPosition); |
| 151 } |
| 152 |
| 153 |
| 154 void CodeSourceMapBuilder::FlushBuffer() { |
| 155 FlushBufferStack(); |
| 156 FlushBufferPosition(); |
| 157 FlushBufferPC(); |
| 158 } |
| 159 |
| 160 |
| 161 void CodeSourceMapBuilder::FlushBufferStack() { |
| 162 for (intptr_t i = buffered_inline_id_stack_.length() - 1; i >= 0; i--) { |
| 163 intptr_t buffered_id = buffered_inline_id_stack_[i]; |
| 164 if (i < written_inline_id_stack_.length()) { |
| 165 intptr_t written_id = written_inline_id_stack_[i]; |
| 166 if (buffered_id == written_id) { |
| 167 // i is the top-most position where the buffered and written stack |
| 168 // match. |
| 169 while (written_inline_id_stack_.length() > i + 1) { |
| 170 WritePop(); |
| 171 } |
| 172 for (intptr_t j = i + 1; j < buffered_inline_id_stack_.length(); j++) { |
| 173 TokenPosition buffered_pos = buffered_token_pos_stack_[j - 1]; |
| 174 TokenPosition written_pos = written_token_pos_stack_[j - 1]; |
| 175 if (buffered_pos != written_pos) { |
| 176 WriteChangePosition(buffered_pos); |
| 177 } |
| 178 WritePush(buffered_inline_id_stack_[j]); |
| 179 } |
| 180 return; |
| 181 } |
| 182 } |
| 183 } |
| 184 UNREACHABLE(); |
| 185 } |
| 186 |
| 187 |
| 188 void CodeSourceMapBuilder::FlushBufferPosition() { |
| 189 ASSERT(buffered_token_pos_stack_.length() == |
| 190 written_token_pos_stack_.length()); |
| 191 |
| 192 intptr_t top = buffered_token_pos_stack_.length() - 1; |
| 193 TokenPosition buffered_pos = buffered_token_pos_stack_[top]; |
| 194 TokenPosition written_pos = written_token_pos_stack_[top]; |
| 195 if (buffered_pos != written_pos) { |
| 196 WriteChangePosition(buffered_pos); |
| 197 } |
| 198 } |
| 199 |
| 200 |
| 201 void CodeSourceMapBuilder::FlushBufferPC() { |
| 202 if (buffered_pc_offset_ != written_pc_offset_) { |
| 203 WriteAdvancePC(buffered_pc_offset_ - written_pc_offset_); |
| 204 } |
145 } | 205 } |
146 | 206 |
147 | 207 |
148 void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset, | 208 void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset, |
149 intptr_t inline_id) { | 209 intptr_t inline_id) { |
150 if (inline_id_stack_.Last() == inline_id) { | 210 if (buffered_inline_id_stack_.Last() == inline_id) { |
151 // No change in function stack. | 211 // No change in function stack. |
152 return; | 212 return; |
153 } | 213 } |
154 if (inline_id == -1) { | 214 if (inline_id == -1) { |
155 // Basic blocking missing an inline_id. | 215 // Basic blocking missing an inline_id. |
156 return; | 216 return; |
157 } | 217 } |
158 | 218 |
| 219 if (!stack_traces_only_) { |
| 220 FlushBuffer(); |
| 221 } |
| 222 |
159 // Find a minimal set of pops and pushes to bring us to the new function | 223 // Find a minimal set of pops and pushes to bring us to the new function |
160 // stack. | 224 // stack. |
161 | 225 |
162 // Pop to a common ancestor. | 226 // Pop to a common ancestor. |
163 intptr_t common_parent = inline_id; | 227 intptr_t common_parent = inline_id; |
164 while (!IsOnStack(common_parent)) { | 228 while (!IsOnBufferedStack(common_parent)) { |
165 common_parent = caller_inline_id_[common_parent]; | 229 common_parent = caller_inline_id_[common_parent]; |
166 } | 230 } |
167 while (inline_id_stack_.Last() != common_parent) { | 231 while (buffered_inline_id_stack_.Last() != common_parent) { |
168 EmitPop(); | 232 BufferPop(); |
169 inline_id_stack_.RemoveLast(); | |
170 token_pos_stack_.RemoveLast(); | |
171 } | 233 } |
172 | 234 |
173 // Push to the new top-of-stack function. | 235 // Push to the new top-of-stack function. |
174 GrowableArray<intptr_t> to_push; | 236 GrowableArray<intptr_t> to_push; |
175 intptr_t id = inline_id; | 237 intptr_t id = inline_id; |
176 while (id != common_parent) { | 238 while (id != common_parent) { |
177 to_push.Add(id); | 239 to_push.Add(id); |
178 id = caller_inline_id_[id]; | 240 id = caller_inline_id_[id]; |
179 } | 241 } |
180 for (intptr_t i = to_push.length() - 1; i >= 0; i--) { | 242 for (intptr_t i = to_push.length() - 1; i >= 0; i--) { |
181 intptr_t push_id = to_push[i]; | 243 intptr_t callee_id = to_push[i]; |
182 TokenPosition call_token; | 244 TokenPosition call_token; |
183 if (push_id != 0) { | 245 if (callee_id != 0) { |
184 // TODO(rmacnak): Should make this array line up with the others. | 246 // TODO(rmacnak): Should make this array line up with the others. |
185 call_token = inline_id_to_token_pos_[push_id - 1]; | 247 call_token = inline_id_to_token_pos_[callee_id - 1]; |
| 248 } else { |
| 249 UNREACHABLE(); |
186 } | 250 } |
187 | 251 |
188 // Report caller as at the position of the call. | 252 // Report caller as at the position of the call. |
189 if (call_token != token_pos_stack_.Last()) { | 253 BufferChangePosition(call_token); |
190 EmitPosition(call_token); | |
191 token_pos_stack_[token_pos_stack_.length() - 1] = call_token; | |
192 } | |
193 | 254 |
194 // Push the callee. | 255 BufferPush(callee_id); |
195 EmitPush(push_id); | |
196 inline_id_stack_.Add(push_id); | |
197 token_pos_stack_.Add(TokenPosition::kDartCodePrologue); | |
198 } | 256 } |
199 } | 257 } |
200 | 258 |
201 | 259 |
202 void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {} | 260 void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {} |
203 | 261 |
204 | 262 |
205 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset, | 263 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset, |
206 TokenPosition pos) { | 264 TokenPosition pos) { |
207 if (pc_offset == pc_offset_) { | 265 if (pc_offset == buffered_pc_offset_) { |
208 return; // Empty intermediate instruction. | 266 return; // Empty intermediate instruction. |
209 } | 267 } |
210 if (pos != token_pos_stack_.Last()) { | 268 if (pos != buffered_token_pos_stack_.Last()) { |
211 EmitPosition(pos); | 269 if (!stack_traces_only_) { |
212 token_pos_stack_[token_pos_stack_.length() - 1] = pos; | 270 FlushBuffer(); |
| 271 } |
| 272 BufferChangePosition(pos); |
213 } | 273 } |
214 EmitAdvancePC(pc_offset - pc_offset_); | 274 BufferAdvancePC(pc_offset - buffered_pc_offset_); |
215 pc_offset_ = pc_offset; | |
216 } | 275 } |
217 | 276 |
218 | 277 |
| 278 void CodeSourceMapBuilder::NoteDescriptor(RawPcDescriptors::Kind kind, |
| 279 int32_t pc_offset, |
| 280 TokenPosition pos) { |
| 281 const uint8_t kCanThrow = |
| 282 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall | |
| 283 RawPcDescriptors::kRuntimeCall | RawPcDescriptors::kOther; |
| 284 if (stack_traces_only_ && ((kind & kCanThrow) != 0)) { |
| 285 BufferChangePosition(pos); |
| 286 BufferAdvancePC(pc_offset - buffered_pc_offset_); |
| 287 FlushBuffer(); |
| 288 } |
| 289 } |
| 290 |
| 291 |
219 RawArray* CodeSourceMapBuilder::InliningIdToFunction() { | 292 RawArray* CodeSourceMapBuilder::InliningIdToFunction() { |
220 if (inline_id_to_function_.length() <= 1) { | 293 if (inline_id_to_function_.length() <= 1) { |
221 // Not optimizing, or optimizing and nothing inlined. | 294 // Not optimizing, or optimizing and nothing inlined. |
222 return Object::empty_array().raw(); | 295 return Object::empty_array().raw(); |
223 } | 296 } |
224 const Array& res = | 297 const Array& res = |
225 Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld)); | 298 Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld)); |
226 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { | 299 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { |
227 res.SetAt(i, *inline_id_to_function_[i]); | 300 res.SetAt(i, *inline_id_to_function_[i]); |
228 } | 301 } |
229 return res.raw(); | 302 return res.raw(); |
230 } | 303 } |
231 | 304 |
232 | 305 |
233 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { | 306 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { |
234 FlushPeephole(); | 307 if (!stack_traces_only_) { |
| 308 FlushBuffer(); |
| 309 } |
235 intptr_t length = stream_.bytes_written(); | 310 intptr_t length = stream_.bytes_written(); |
236 const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length)); | 311 const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length)); |
237 NoSafepointScope no_safepoint; | 312 NoSafepointScope no_safepoint; |
238 memmove(map.Data(), buffer_, length); | 313 memmove(map.Data(), buffer_, length); |
239 return map.raw(); | 314 return map.raw(); |
240 } | 315 } |
241 | 316 |
242 | 317 |
243 void CodeSourceMapReader::GetInlinedFunctionsAt( | 318 void CodeSourceMapReader::GetInlinedFunctionsAt( |
244 int32_t pc_offset, | 319 int32_t pc_offset, |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 break; | 523 break; |
449 } | 524 } |
450 default: | 525 default: |
451 UNREACHABLE(); | 526 UNREACHABLE(); |
452 } | 527 } |
453 } | 528 } |
454 THR_Print("}\n"); | 529 THR_Print("}\n"); |
455 } | 530 } |
456 | 531 |
457 } // namespace dart | 532 } // namespace dart |
OLD | NEW |