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/debugger.h" | 5 #include "vm/debugger.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 | 8 |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 uword fp, | 173 uword fp, |
174 uword sp, | 174 uword sp, |
175 const Code& code, | 175 const Code& code, |
176 const Array& deopt_frame, | 176 const Array& deopt_frame, |
177 intptr_t deopt_frame_offset) | 177 intptr_t deopt_frame_offset) |
178 : pc_(pc), fp_(fp), sp_(sp), | 178 : pc_(pc), fp_(fp), sp_(sp), |
179 ctx_(Context::ZoneHandle()), | 179 ctx_(Context::ZoneHandle()), |
180 code_(Code::ZoneHandle(code.raw())), | 180 code_(Code::ZoneHandle(code.raw())), |
181 function_(Function::ZoneHandle(code.function())), | 181 function_(Function::ZoneHandle(code.function())), |
182 token_pos_(-1), | 182 token_pos_(-1), |
183 desc_rec_(NULL), | 183 try_index_(-1), |
184 has_desc_rec_(false), | |
184 line_number_(-1), | 185 line_number_(-1), |
185 column_number_(-1), | 186 column_number_(-1), |
186 context_level_(-1), | 187 context_level_(-1), |
187 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 188 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
188 deopt_frame_offset_(deopt_frame_offset), | 189 deopt_frame_offset_(deopt_frame_offset), |
189 vars_initialized_(false), | 190 vars_initialized_(false), |
190 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 191 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
191 desc_indices_(8), | 192 desc_indices_(8), |
192 pc_desc_(PcDescriptors::ZoneHandle()) { | 193 pc_desc_(PcDescriptors::ZoneHandle()) { |
193 } | 194 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 void ActivationFrame::GetPcDescriptors() { | 350 void ActivationFrame::GetPcDescriptors() { |
350 if (pc_desc_.IsNull()) { | 351 if (pc_desc_.IsNull()) { |
351 pc_desc_ = code().pc_descriptors(); | 352 pc_desc_ = code().pc_descriptors(); |
352 ASSERT(!pc_desc_.IsNull()); | 353 ASSERT(!pc_desc_.IsNull()); |
353 } | 354 } |
354 } | 355 } |
355 | 356 |
356 | 357 |
357 // Compute token_pos_ and pc_desc_index_. | 358 // Compute token_pos_ and pc_desc_index_. |
358 intptr_t ActivationFrame::TokenPos() { | 359 intptr_t ActivationFrame::TokenPos() { |
359 if (token_pos_ < 0) { | 360 if (token_pos_ < 0) { |
hausner
2014/07/16 22:29:37
This should now be if (!has_desc_rec_)
srdjan
2014/07/16 23:06:13
Done.
| |
360 token_pos_ = Scanner::kNoSourcePos; | 361 token_pos_ = Scanner::kNoSourcePos; |
361 GetPcDescriptors(); | 362 GetPcDescriptors(); |
362 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 363 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
363 while (iter.HasNext()) { | 364 while (iter.HasNext()) { |
364 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 365 RawPcDescriptors::PcDescriptorRec rec; |
366 iter.NextRec(&rec); | |
hausner
2014/07/16 22:29:38
Compared to the original version that accessed the
srdjan
2014/07/16 23:06:13
Follow up CL to solve more efficient iteration.
| |
365 if (rec.pc() == pc_) { | 367 if (rec.pc() == pc_) { |
366 desc_rec_ = &rec; | 368 try_index_ = rec.try_index(); |
367 token_pos_ = rec.token_pos(); | 369 token_pos_ = rec.token_pos(); |
370 has_desc_rec_ = true; | |
hausner
2014/07/16 22:29:38
has_desc_rec_ should be set to true even if no des
srdjan
2014/07/16 23:06:13
Renamed to 'token_pos_initialized_'
| |
368 break; | 371 break; |
369 } | 372 } |
370 } | 373 } |
371 } | 374 } |
372 return token_pos_; | 375 return token_pos_; |
373 } | 376 } |
374 | 377 |
375 | 378 |
376 intptr_t ActivationFrame::TryIndex() { | 379 intptr_t ActivationFrame::TryIndex() { |
377 if (desc_rec_ == NULL) { | 380 if (!has_desc_rec_) { |
378 TokenPos(); // Side effect: compute desc_rec_ lazily. | 381 TokenPos(); // Side effect: compute has_desc_rec_, try_index_ etc. lazily. |
379 } | 382 } |
380 if (desc_rec_ == NULL) { | 383 return try_index_; |
381 return -1; | |
382 } else { | |
383 return desc_rec_->try_index(); | |
384 } | |
385 } | 384 } |
386 | 385 |
387 | 386 |
388 intptr_t ActivationFrame::LineNumber() { | 387 intptr_t ActivationFrame::LineNumber() { |
389 // Compute line number lazily since it causes scanning of the script. | 388 // Compute line number lazily since it causes scanning of the script. |
390 if ((line_number_ < 0) && (TokenPos() >= 0)) { | 389 if ((line_number_ < 0) && (TokenPos() >= 0)) { |
391 const Script& script = Script::Handle(SourceScript()); | 390 const Script& script = Script::Handle(SourceScript()); |
392 script.GetTokenLocation(TokenPos(), &line_number_, NULL); | 391 script.GetTokenLocation(TokenPos(), &line_number_, NULL); |
393 } | 392 } |
394 return line_number_; | 393 return line_number_; |
(...skipping 28 matching lines...) Expand all Loading... | |
423 | 422 |
424 | 423 |
425 // Calculate the context level at the current token index of the frame. | 424 // Calculate the context level at the current token index of the frame. |
426 intptr_t ActivationFrame::ContextLevel() { | 425 intptr_t ActivationFrame::ContextLevel() { |
427 if (context_level_ < 0 && !ctx_.IsNull()) { | 426 if (context_level_ < 0 && !ctx_.IsNull()) { |
428 ASSERT(!code_.is_optimized()); | 427 ASSERT(!code_.is_optimized()); |
429 context_level_ = 0; | 428 context_level_ = 0; |
430 // TODO(hausner): What to do if there is no descriptor entry | 429 // TODO(hausner): What to do if there is no descriptor entry |
431 // for the code position of the frame? For now say we are at context | 430 // for the code position of the frame? For now say we are at context |
432 // level 0. | 431 // level 0. |
433 if (desc_rec_ == NULL) { | 432 if (!has_desc_rec_) { |
hausner
2014/07/16 22:29:38
I think this is still a bug, similar to the one we
srdjan
2014/07/16 23:06:13
Done.
| |
434 return context_level_; | 433 return context_level_; |
435 } | 434 } |
436 ASSERT(!pc_desc_.IsNull()); | 435 ASSERT(!pc_desc_.IsNull()); |
437 intptr_t innermost_begin_pos = 0; | 436 intptr_t innermost_begin_pos = 0; |
438 intptr_t activation_token_pos = TokenPos(); | 437 intptr_t activation_token_pos = TokenPos(); |
439 ASSERT(activation_token_pos >= 0); | 438 ASSERT(activation_token_pos >= 0); |
440 GetVarDescriptors(); | 439 GetVarDescriptors(); |
441 intptr_t var_desc_len = var_descriptors_.Length(); | 440 intptr_t var_desc_len = var_descriptors_.Length(); |
442 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 441 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
443 RawLocalVarDescriptors::VarInfo var_info; | 442 RawLocalVarDescriptors::VarInfo var_info; |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1197 } | 1196 } |
1198 // Hang on to the code object before deoptimizing, in case deoptimization | 1197 // Hang on to the code object before deoptimizing, in case deoptimization |
1199 // might cause the GC to run. | 1198 // might cause the GC to run. |
1200 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); | 1199 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); |
1201 ASSERT(!code.IsNull()); | 1200 ASSERT(!code.IsNull()); |
1202 DeoptimizeWorld(); | 1201 DeoptimizeWorld(); |
1203 ASSERT(!target_function.HasOptimizedCode()); | 1202 ASSERT(!target_function.HasOptimizedCode()); |
1204 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1203 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1205 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1204 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1206 while (iter.HasNext()) { | 1205 while (iter.HasNext()) { |
1207 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1206 RawPcDescriptors::PcDescriptorRec rec; |
1207 iter.NextRec(&rec); | |
1208 if (HasTokenPos(rec)) { | 1208 if (HasTokenPos(rec)) { |
1209 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc()); | 1209 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc()); |
1210 if (bpt != NULL) { | 1210 if (bpt != NULL) { |
1211 // There is already a breakpoint for this address. Make sure | 1211 // There is already a breakpoint for this address. Make sure |
1212 // it is enabled. | 1212 // it is enabled. |
1213 bpt->Enable(); | 1213 bpt->Enable(); |
1214 continue; | 1214 continue; |
1215 } | 1215 } |
1216 bpt = new CodeBreakpoint(code, rec); | 1216 bpt = new CodeBreakpoint(code, rec); |
1217 RegisterCodeBreakpoint(bpt); | 1217 RegisterCodeBreakpoint(bpt); |
(...skipping 30 matching lines...) Expand all Loading... | |
1248 | 1248 |
1249 // Is there a closure call at the current PC? | 1249 // Is there a closure call at the current PC? |
1250 // | 1250 // |
1251 // We can't just check the callee_activation to see if it is a | 1251 // We can't just check the callee_activation to see if it is a |
1252 // closure function, because it may not be on the stack yet. | 1252 // closure function, because it may not be on the stack yet. |
1253 bool is_closure_call = false; | 1253 bool is_closure_call = false; |
1254 const PcDescriptors& pc_desc = | 1254 const PcDescriptors& pc_desc = |
1255 PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1255 PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1256 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); | 1256 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); |
1257 while (iter.HasNext()) { | 1257 while (iter.HasNext()) { |
1258 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1258 const uword rec_pc = iter.NextPc(); |
1259 if (rec.pc() == pc) { | 1259 if (rec_pc == pc) { |
1260 is_closure_call = true; | 1260 is_closure_call = true; |
1261 break; | 1261 break; |
1262 } | 1262 } |
1263 } | 1263 } |
1264 | 1264 |
1265 // Recover the context for this frame. | 1265 // Recover the context for this frame. |
1266 if (is_closure_call) { | 1266 if (is_closure_call) { |
1267 // If the callee is a closure, we should have stored the context | 1267 // If the callee is a closure, we should have stored the context |
1268 // in the current frame before making the call. | 1268 // in the current frame before making the call. |
1269 const Context& closure_call_ctx = | 1269 const Context& closure_call_ctx = |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1540 requested_token_pos = func.token_pos(); | 1540 requested_token_pos = func.token_pos(); |
1541 } | 1541 } |
1542 if (last_token_pos > func.end_token_pos()) { | 1542 if (last_token_pos > func.end_token_pos()) { |
1543 last_token_pos = func.end_token_pos(); | 1543 last_token_pos = func.end_token_pos(); |
1544 } | 1544 } |
1545 | 1545 |
1546 Code& code = Code::Handle(func.unoptimized_code()); | 1546 Code& code = Code::Handle(func.unoptimized_code()); |
1547 ASSERT(!code.IsNull()); | 1547 ASSERT(!code.IsNull()); |
1548 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1548 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1549 intptr_t best_fit_pos = INT_MAX; | 1549 intptr_t best_fit_pos = INT_MAX; |
1550 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; | |
1551 uword lowest_pc = kUwordMax; | 1550 uword lowest_pc = kUwordMax; |
1552 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; | 1551 intptr_t lowest_pc_token_pos = INT_MAX; |
1553 | |
1554 const RawPcDescriptors::PcDescriptorRec* rec = NULL; | |
1555 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1552 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1556 while (iter.HasNext()) { | 1553 while (iter.HasNext()) { |
1557 rec = &iter.Next(); | 1554 RawPcDescriptors::PcDescriptorRec rec; |
1558 intptr_t desc_token_pos = rec->token_pos(); | 1555 iter.NextRec(&rec); |
hausner
2014/07/16 22:29:38
Again, you need to copy the entire pc descriptor (
| |
1556 intptr_t desc_token_pos = rec.token_pos(); | |
1559 ASSERT(desc_token_pos >= 0); | 1557 ASSERT(desc_token_pos >= 0); |
1560 if (HasTokenPos(*rec)) { | 1558 if (HasTokenPos(rec)) { |
1561 if ((desc_token_pos < requested_token_pos) || | 1559 if ((desc_token_pos < requested_token_pos) || |
1562 (desc_token_pos > last_token_pos)) { | 1560 (desc_token_pos > last_token_pos)) { |
1563 // This descriptor is outside the desired token range. | 1561 // This descriptor is outside the desired token range. |
1564 continue; | 1562 continue; |
1565 } | 1563 } |
1566 if (desc_token_pos < best_fit_pos) { | 1564 if (desc_token_pos < best_fit_pos) { |
1567 // So far, this descriptor has the lowest token position after | 1565 // So far, this descriptor has the lowest token position after |
1568 // the first acceptable token position. | 1566 // the first acceptable token position. |
1569 best_fit_pos = desc_token_pos; | 1567 best_fit_pos = desc_token_pos; |
1570 best_fit_rec = rec; | |
1571 } | 1568 } |
1572 if (rec->pc() < lowest_pc) { | 1569 if (rec.pc() < lowest_pc) { |
1573 // This descriptor so far has the lowest code address. | 1570 // This descriptor so far has the lowest code address. |
1574 lowest_pc = rec->pc(); | 1571 lowest_pc = rec.pc(); |
1575 lowest_pc_rec = rec; | 1572 lowest_pc_token_pos = desc_token_pos; |
1576 } | 1573 } |
1577 } | 1574 } |
1578 } | 1575 } |
1579 if (lowest_pc_rec != NULL) { | 1576 if (lowest_pc_token_pos != INT_MAX) { |
1580 // We found the pc descriptor that has the lowest execution address. | 1577 // We found the pc descriptor that has the lowest execution address. |
1581 // This is the first possible breakpoint after the requested token | 1578 // This is the first possible breakpoint after the requested token |
1582 // position. We use this instead of the nearest PC descriptor | 1579 // position. We use this instead of the nearest PC descriptor |
1583 // measured in token index distance. | 1580 // measured in token index distance. |
1584 best_fit_rec = lowest_pc_rec; | 1581 return lowest_pc_token_pos; |
1585 } | 1582 } |
1586 if (best_fit_rec != NULL) { | 1583 if (best_fit_pos != INT_MAX) { |
1587 return best_fit_rec->token_pos(); | 1584 return best_fit_pos; |
1588 } | 1585 } |
1589 // We didn't find a safe point in the given token range. Try and find | 1586 // We didn't find a safe point in the given token range. Try and find |
1590 // a safe point in the remaining source code of the function. | 1587 // a safe point in the remaining source code of the function. |
1591 if (last_token_pos < func.end_token_pos()) { | 1588 if (last_token_pos < func.end_token_pos()) { |
1592 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); | 1589 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); |
1593 } | 1590 } |
1594 return -1; | 1591 return -1; |
1595 } | 1592 } |
1596 | 1593 |
1597 | 1594 |
1598 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1595 void Debugger::MakeCodeBreakpointAt(const Function& func, |
1599 SourceBreakpoint* bpt) { | 1596 SourceBreakpoint* bpt) { |
1600 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1597 ASSERT((bpt != NULL) && bpt->IsResolved()); |
1601 ASSERT(!func.HasOptimizedCode()); | 1598 ASSERT(!func.HasOptimizedCode()); |
1602 Code& code = Code::Handle(func.unoptimized_code()); | 1599 Code& code = Code::Handle(func.unoptimized_code()); |
1603 ASSERT(!code.IsNull()); | 1600 ASSERT(!code.IsNull()); |
1604 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1601 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1605 uword lowest_pc = kUwordMax; | 1602 uword lowest_pc = kUwordMax; |
1606 // Find the safe point with the lowest compiled code address | 1603 // Find the safe point with the lowest compiled code address |
1607 // that maps to the token position of the source breakpoint. | 1604 // that maps to the token position of the source breakpoint. |
1608 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1605 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1609 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; | 1606 RawPcDescriptors::PcDescriptorRec lowest_rec; |
1610 while (iter.HasNext()) { | 1607 while (iter.HasNext()) { |
1611 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1608 RawPcDescriptors::PcDescriptorRec rec; |
1609 iter.NextRec(&rec); | |
1612 intptr_t desc_token_pos = rec.token_pos(); | 1610 intptr_t desc_token_pos = rec.token_pos(); |
1613 if ((desc_token_pos == bpt->token_pos_) && HasTokenPos(rec)) { | 1611 if ((desc_token_pos == bpt->token_pos_) && HasTokenPos(rec)) { |
1614 if (rec.pc() < lowest_pc) { | 1612 if (rec.pc() < lowest_pc) { |
1615 lowest_pc = rec.pc(); | 1613 lowest_pc = rec.pc(); |
1616 lowest_rec = &rec; | 1614 lowest_rec = rec; |
1617 } | 1615 } |
1618 } | 1616 } |
1619 } | 1617 } |
1620 if (lowest_rec == NULL) { | 1618 if (lowest_pc == kUwordMax) { |
1621 return; | 1619 return; |
1622 } | 1620 } |
1623 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc()); | 1621 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec.pc()); |
1624 if (code_bpt == NULL) { | 1622 if (code_bpt == NULL) { |
1625 // No code breakpoint for this code exists; create one. | 1623 // No code breakpoint for this code exists; create one. |
1626 code_bpt = new CodeBreakpoint(code, *lowest_rec); | 1624 code_bpt = new CodeBreakpoint(code, lowest_rec); |
1627 RegisterCodeBreakpoint(code_bpt); | 1625 RegisterCodeBreakpoint(code_bpt); |
1628 } | 1626 } |
1629 code_bpt->set_src_bpt(bpt); | 1627 code_bpt->set_src_bpt(bpt); |
1630 if (bpt->IsEnabled()) { | 1628 if (bpt->IsEnabled()) { |
1631 code_bpt->Enable(); | 1629 code_bpt->Enable(); |
1632 } | 1630 } |
1633 } | 1631 } |
1634 | 1632 |
1635 | 1633 |
1636 void Debugger::FindCompiledFunctions(const Script& script, | 1634 void Debugger::FindCompiledFunctions(const Script& script, |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2578 } | 2576 } |
2579 | 2577 |
2580 | 2578 |
2581 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2579 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2582 ASSERT(bpt->next() == NULL); | 2580 ASSERT(bpt->next() == NULL); |
2583 bpt->set_next(code_breakpoints_); | 2581 bpt->set_next(code_breakpoints_); |
2584 code_breakpoints_ = bpt; | 2582 code_breakpoints_ = bpt; |
2585 } | 2583 } |
2586 | 2584 |
2587 } // namespace dart | 2585 } // namespace dart |
OLD | NEW |