| 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" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 uword exit_marker = current->top_exit_frame_info(); | 208 uword exit_marker = current->top_exit_frame_info(); |
| 209 frames_.fp_ = exit_marker; | 209 frames_.fp_ = exit_marker; |
| 210 } | 210 } |
| 211 | 211 |
| 212 | 212 |
| 213 void StackFrameIterator::SetupNextExitFrameData() { | 213 void StackFrameIterator::SetupNextExitFrameData() { |
| 214 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); | 214 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); |
| 215 uword exit_marker = *reinterpret_cast<uword*>(exit_address); | 215 uword exit_marker = *reinterpret_cast<uword*>(exit_address); |
| 216 frames_.fp_ = exit_marker; | 216 frames_.fp_ = exit_marker; |
| 217 frames_.sp_ = 0; | 217 frames_.sp_ = 0; |
| 218 frames_.pc_ = 0; |
| 218 } | 219 } |
| 219 | 220 |
| 220 | 221 |
| 221 StackFrameIterator::StackFrameIterator(bool validate) | 222 StackFrameIterator::StackFrameIterator(bool validate) |
| 222 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { | 223 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { |
| 223 SetupLastExitFrameData(); // Setup data for last exit frame. | 224 SetupLastExitFrameData(); // Setup data for last exit frame. |
| 224 } | 225 } |
| 225 | 226 |
| 227 |
| 226 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate) | 228 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate) |
| 227 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { | 229 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { |
| 228 frames_.fp_ = last_fp; | 230 frames_.fp_ = last_fp; |
| 231 frames_.sp_ = 0; |
| 232 frames_.pc_ = 0; |
| 233 } |
| 234 |
| 235 |
| 236 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, |
| 237 bool validate) |
| 238 : validate_(validate), entry_(), exit_(), current_frame_(NULL) { |
| 239 frames_.fp_ = fp; |
| 240 frames_.sp_ = sp; |
| 241 frames_.pc_ = pc; |
| 229 } | 242 } |
| 230 | 243 |
| 231 | 244 |
| 232 StackFrame* StackFrameIterator::NextFrame() { | 245 StackFrame* StackFrameIterator::NextFrame() { |
| 233 // When we are at the start of iteration after having created an | 246 // When we are at the start of iteration after having created an |
| 234 // iterator object current_frame_ will be NULL as we haven't seen | 247 // iterator object, current_frame_ will be NULL as we haven't seen |
| 235 // any frames yet. At this point if NextFrame is called it tries | 248 // any frames yet (unless we start iterating in the simulator from a given |
| 249 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries |
| 236 // to set up the next exit frame by reading the top_exit_frame_info | 250 // to set up the next exit frame by reading the top_exit_frame_info |
| 237 // from the isolate. If we do not have any dart invocations yet | 251 // from the isolate. If we do not have any dart invocations yet, |
| 238 // top_exit_frame_info will be 0 and so we would return NULL. | 252 // top_exit_frame_info will be 0 and so we would return NULL. |
| 239 | 253 |
| 240 // current_frame_ will also be NULL, when we are at the end of having | 254 // current_frame_ will also be NULL, when we are at the end of having |
| 241 // iterated through all the frames. if NextFrame is called at this | 255 // iterated through all the frames. If NextFrame is called at this |
| 242 // point we will try and set up the next exit frame but since we are | 256 // point, we will try and set up the next exit frame, but since we are |
| 243 // at the end of the iteration fp_ will be 0 and we would return NULL. | 257 // at the end of the iteration, fp_ will be 0 and we would return NULL. |
| 244 if (current_frame_ == NULL) { | 258 if (current_frame_ == NULL) { |
| 245 if (!HasNextFrame()) { | 259 if (!HasNextFrame()) { |
| 246 return NULL; | 260 return NULL; |
| 247 } | 261 } |
| 248 current_frame_ = NextExitFrame(); | 262 if (frames_.pc_ == 0) { |
| 263 // Iteration starts from an exit frame given by its fp. |
| 264 current_frame_ = NextExitFrame(); |
| 265 } else if (*(reinterpret_cast<uword*>( |
| 266 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) { |
| 267 // Iteration starts from an entry frame given by its fp, sp, and pc. |
| 268 current_frame_ = NextEntryFrame(); |
| 269 } else { |
| 270 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. |
| 271 current_frame_ = frames_.NextFrame(validate_); |
| 272 } |
| 249 return current_frame_; | 273 return current_frame_; |
| 250 } | 274 } |
| 251 ASSERT((validate_ == kDontValidateFrames) || current_frame_->IsValid()); | 275 ASSERT((validate_ == kDontValidateFrames) || current_frame_->IsValid()); |
| 252 if (current_frame_->IsEntryFrame()) { | 276 if (current_frame_->IsEntryFrame()) { |
| 253 if (HasNextFrame()) { // We have another chained block. | 277 if (HasNextFrame()) { // We have another chained block. |
| 254 current_frame_ = NextExitFrame(); | 278 current_frame_ = NextExitFrame(); |
| 255 return current_frame_; | 279 return current_frame_; |
| 256 } | 280 } |
| 257 current_frame_ = NULL; // No more frames. | 281 current_frame_ = NULL; // No more frames. |
| 258 return current_frame_; | 282 return current_frame_; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 269 return current_frame_; | 293 return current_frame_; |
| 270 } | 294 } |
| 271 | 295 |
| 272 | 296 |
| 273 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { | 297 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { |
| 274 StackFrame* frame; | 298 StackFrame* frame; |
| 275 ASSERT(HasNext()); | 299 ASSERT(HasNext()); |
| 276 frame = &stack_frame_; | 300 frame = &stack_frame_; |
| 277 frame->sp_ = sp_; | 301 frame->sp_ = sp_; |
| 278 frame->fp_ = fp_; | 302 frame->fp_ = fp_; |
| 303 frame->pc_ = pc_; |
| 279 sp_ = frame->GetCallerSp(); | 304 sp_ = frame->GetCallerSp(); |
| 280 fp_ = frame->GetCallerFp(); | 305 fp_ = frame->GetCallerFp(); |
| 306 pc_ = frame->GetCallerPc(); |
| 281 ASSERT((validate == kDontValidateFrames) || frame->IsValid()); | 307 ASSERT((validate == kDontValidateFrames) || frame->IsValid()); |
| 282 return frame; | 308 return frame; |
| 283 } | 309 } |
| 284 | 310 |
| 285 | 311 |
| 286 ExitFrame* StackFrameIterator::NextExitFrame() { | 312 ExitFrame* StackFrameIterator::NextExitFrame() { |
| 287 exit_.sp_ = frames_.sp_; | 313 exit_.sp_ = frames_.sp_; |
| 288 exit_.fp_ = frames_.fp_; | 314 exit_.fp_ = frames_.fp_; |
| 315 exit_.pc_ = frames_.pc_; |
| 289 frames_.sp_ = exit_.GetCallerSp(); | 316 frames_.sp_ = exit_.GetCallerSp(); |
| 290 frames_.fp_ = exit_.GetCallerFp(); | 317 frames_.fp_ = exit_.GetCallerFp(); |
| 318 frames_.pc_ = exit_.GetCallerPc(); |
| 291 ASSERT(exit_.IsValid()); | 319 ASSERT(exit_.IsValid()); |
| 292 return &exit_; | 320 return &exit_; |
| 293 } | 321 } |
| 294 | 322 |
| 295 | 323 |
| 296 EntryFrame* StackFrameIterator::NextEntryFrame() { | 324 EntryFrame* StackFrameIterator::NextEntryFrame() { |
| 297 ASSERT(!frames_.HasNext()); | 325 ASSERT(!frames_.HasNext()); |
| 298 entry_.sp_ = frames_.sp_; | 326 entry_.sp_ = frames_.sp_; |
| 299 entry_.fp_ = frames_.fp_; | 327 entry_.fp_ = frames_.fp_; |
| 328 entry_.pc_ = frames_.pc_; |
| 300 SetupNextExitFrameData(); // Setup data for next exit frame in chain. | 329 SetupNextExitFrameData(); // Setup data for next exit frame in chain. |
| 301 ASSERT(entry_.IsValid()); | 330 ASSERT(entry_.IsValid()); |
| 302 return &entry_; | 331 return &entry_; |
| 303 } | 332 } |
| 304 | 333 |
| 305 | 334 |
| 306 InlinedFunctionsIterator::InlinedFunctionsIterator(StackFrame* frame) | 335 InlinedFunctionsIterator::InlinedFunctionsIterator(StackFrame* frame) |
| 307 : index_(0), | 336 : index_(0), |
| 308 code_(Code::Handle()), | 337 code_(Code::Handle()), |
| 309 deopt_info_(DeoptInfo::Handle()), | 338 deopt_info_(DeoptInfo::Handle()), |
| 310 function_(Function::Handle()), | 339 function_(Function::Handle()), |
| 311 pc_(0), | 340 pc_(0), |
| 312 deopt_instructions_(), | 341 deopt_instructions_(), |
| 313 object_table_(Array::Handle()) { | 342 object_table_(Array::Handle()) { |
| 314 ASSERT(frame != NULL); | 343 ASSERT(frame != NULL); |
| 315 code_ = frame->LookupDartCode(); | 344 code_ = frame->LookupDartCode(); |
| 316 ASSERT(code_.is_optimized()); | 345 ASSERT(code_.is_optimized()); |
| 317 intptr_t deopt_reason = kDeoptUnknown; | 346 intptr_t deopt_reason = kDeoptUnknown; |
| 318 deopt_info_ = code_.GetDeoptInfoAtPc(frame->pc(), &deopt_reason); | 347 deopt_info_ = code_.GetDeoptInfoAtPc(frame->pc(), &deopt_reason); |
| 319 if (deopt_info_.IsNull()) { | 348 if (deopt_info_.IsNull()) { |
| 320 // This is the case when a call without deopt info in optimzed code | 349 // This is the case when a call without deopt info in optimized code |
| 321 // throws an exception. (e.g. in the parameter copying prologue). | 350 // throws an exception. (e.g. in the parameter copying prologue). |
| 322 // In that case there won't be any inlined frames. | 351 // In that case there won't be any inlined frames. |
| 323 function_ = code_.function(); | 352 function_ = code_.function(); |
| 324 pc_ = frame->pc(); | 353 pc_ = frame->pc(); |
| 325 ASSERT(pc_ != 0); | 354 ASSERT(pc_ != 0); |
| 326 } else { | 355 } else { |
| 327 // Unpack deopt info into instructions (translate away suffixes). | 356 // Unpack deopt info into instructions (translate away suffixes). |
| 328 const Array& deopt_table = Array::Handle(code_.deopt_info_array()); | 357 const Array& deopt_table = Array::Handle(code_.deopt_info_array()); |
| 329 ASSERT(!deopt_table.IsNull()); | 358 ASSERT(!deopt_table.IsNull()); |
| 330 deopt_info_.ToInstructions(deopt_table, &deopt_instructions_); | 359 deopt_info_.ToInstructions(deopt_table, &deopt_instructions_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 352 pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &func); | 381 pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &func); |
| 353 code_ = func.unoptimized_code(); | 382 code_ = func.unoptimized_code(); |
| 354 function_ = func.raw(); | 383 function_ = func.raw(); |
| 355 return; | 384 return; |
| 356 } | 385 } |
| 357 } | 386 } |
| 358 SetDone(); | 387 SetDone(); |
| 359 } | 388 } |
| 360 | 389 |
| 361 } // namespace dart | 390 } // namespace dart |
| OLD | NEW |