@@ -247,7 +247,8 @@ ActivationFrame::ActivationFrame(uword pc,
247247 var_descriptors_(LocalVarDescriptors::ZoneHandle()),
248248 desc_indices_(8 ),
249249 pc_desc_(PcDescriptors::ZoneHandle()) {
250- ASSERT (!function_.IsNull ()); // Frames with bytecode stubs should be skipped.
250+ // The frame of a bytecode stub has a null function. It may be encountered
251+ // when single stepping.
251252}
252253#endif // !defined(DART_PRECOMPILED_RUNTIME)
253254
@@ -676,7 +677,8 @@ void ActivationFrame::GetVarDescriptors() {
676677}
677678
678679bool ActivationFrame::IsDebuggable () const {
679- return Debugger::IsDebuggable (function ());
680+ // When stepping in bytecode stub, function is null.
681+ return !function ().IsNull () && Debugger::IsDebuggable (function ());
680682}
681683
682684void ActivationFrame::PrintDescriptorsError (const char * message) {
@@ -996,8 +998,9 @@ void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
996998 if (yield_point_index == await_jump_var) {
997999 token_pos_ = iter.TokenPos ();
9981000 token_pos_initialized_ = true ;
999- try_index_ = bytecode.GetTryIndexAtPc (bytecode.PayloadStart () +
1000- iter.PcOffset ());
1001+ const uword return_address =
1002+ KernelBytecode::Next (bytecode.PayloadStart () + iter.PcOffset ());
1003+ try_index_ = bytecode.GetTryIndexAtPc (return_address);
10011004 return ;
10021005 }
10031006 ++yield_point_index;
@@ -1561,15 +1564,18 @@ const char* ActivationFrame::ToCString() {
15611564 intptr_t line = LineNumber ();
15621565 const char * func_name = Debugger::QualifiedFunctionName (function ());
15631566 return Thread::Current ()->zone ()->PrintToString (
1564- " [ Frame pc(0x%" Px " ) fp(0x%" Px " ) sp(0x%" Px
1567+ " [ Frame pc(0x%" Px " offset:0x% " Px " ) fp(0x%" Px " ) sp(0x%" Px
15651568 " )\n "
15661569 " \t function = %s\n "
15671570 " \t url = %s\n "
15681571 " \t line = %" Pd
15691572 " \n "
15701573 " \t context = %s\n "
15711574 " \t context level = %" Pd " ]\n " ,
1572- pc (), fp (), sp (), func_name, url.ToCString (), line, ctx_.ToCString (),
1575+ pc (),
1576+ pc () -
1577+ (IsInterpreted () ? bytecode ().PayloadStart () : code ().PayloadStart ()),
1578+ fp (), sp (), func_name, url.ToCString (), line, ctx_.ToCString (),
15731579 ContextLevel ());
15741580}
15751581
@@ -2580,9 +2586,11 @@ ActivationFrame* Debugger::TopDartFrame() const {
25802586#if !defined(DART_PRECOMPILED_RUNTIME)
25812587 if (frame->is_interpreted ()) {
25822588 Bytecode& bytecode = Bytecode::Handle (frame->LookupDartBytecode ());
2583- if (bytecode.function () == Function::null ()) {
2584- continue ; // Skip bytecode stub frame.
2585- }
2589+ // Note that we do not skip bytecode stub frame (with a null function),
2590+ // so that we can ignore a single stepping breakpoint in such a frame.
2591+ // A bytecode stub contains a VM internal bytecode followed by a
2592+ // ReturnTOS bytecode. The single step on the ReturnTOS bytecode
2593+ // needs to be skipped.
25862594 ActivationFrame* activation =
25872595 new ActivationFrame (frame->pc (), frame->fp (), frame->sp (), bytecode);
25882596 return activation;
@@ -3053,19 +3061,20 @@ TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
30533061
30543062#if !defined(DART_PRECOMPILED_RUNTIME)
30553063// Find a 'debug break checked' bytecode in the range [pc..end_pc[ and return
3056- // the pc after it or nullptr .
3057- static const KBCInstr* FindBreakpointCheckedInstr (const KBCInstr* pc,
3058- const KBCInstr* end_pc) {
3059- while ((pc < end_pc) && ! KernelBytecode::IsDebugBreakCheckedOpcode (pc)) {
3064+ // the pc after it or 0 if not found .
3065+ static uword FindBreakpointCheckedInstr (uword pc, uword end_pc) {
3066+ while ((pc < end_pc) && ! KernelBytecode::IsDebugBreakCheckedOpcode (
3067+ reinterpret_cast < const KBCInstr*> (pc) )) {
30603068 pc = KernelBytecode::Next (pc);
30613069 }
30623070 if (pc < end_pc) {
3063- ASSERT (KernelBytecode::IsDebugBreakCheckedOpcode (pc));
3071+ ASSERT (KernelBytecode::IsDebugBreakCheckedOpcode (
3072+ reinterpret_cast <const KBCInstr*>(pc)));
30643073 // The checked debug break pc must point to the next bytecode.
30653074 return KernelBytecode::Next (pc);
30663075 }
30673076 // No 'debug break checked' bytecode in the range.
3068- return nullptr ;
3077+ return 0 ;
30693078}
30703079#endif // !defined(DART_PRECOMPILED_RUNTIME)
30713080
@@ -3079,45 +3088,40 @@ void Debugger::MakeCodeBreakpointAt(const Function& func,
30793088 if (func.HasBytecode ()) {
30803089 Bytecode& bytecode = Bytecode::Handle (func.bytecode ());
30813090 ASSERT (!bytecode.IsNull ());
3082- const KBCInstr* pc = nullptr ;
3091+ uword pc = 0 ;
30833092 if (bytecode.HasSourcePositions ()) {
30843093 kernel::BytecodeSourcePositionsIterator iter (Thread::Current ()->zone (),
30853094 bytecode);
30863095 bool check_range = false ;
30873096 while (iter.MoveNext ()) {
30883097 if (check_range) {
3089- const KBCInstr* end_pc =
3090- reinterpret_cast <const KBCInstr*>(bytecode.PayloadStart ()) +
3091- iter.PcOffset ();
3098+ uword end_pc = bytecode.PayloadStart () + iter.PcOffset ();
30923099 check_range = false ;
30933100 // Find a 'debug break checked' bytecode in the range [pc..end_pc[.
30943101 pc = FindBreakpointCheckedInstr (pc, end_pc);
3095- if (pc != nullptr ) {
3102+ if (pc != 0 ) {
30963103 // TODO(regis): We may want to find all PCs for a token position,
30973104 // e.g. in the case of duplicated bytecode in finally clauses.
30983105 break ;
30993106 }
31003107 }
31013108 if (iter.TokenPos () == loc->token_pos_ ) {
3102- pc = reinterpret_cast <const KBCInstr*>(bytecode.PayloadStart ()) +
3103- iter.PcOffset ();
3109+ pc = bytecode.PayloadStart () + iter.PcOffset ();
31043110 check_range = true ;
31053111 }
31063112 }
31073113 if (check_range) {
3108- ASSERT (pc != nullptr );
3114+ ASSERT (pc != 0 );
31093115 // Use the end of the bytecode as the end of the range to check.
31103116 pc = FindBreakpointCheckedInstr (
3111- pc, reinterpret_cast <const KBCInstr*>(bytecode.PayloadStart ()) +
3112- bytecode.Size ());
3117+ pc, bytecode.PayloadStart () + bytecode.Size ());
31133118 }
31143119 }
3115- if (pc != nullptr ) {
3116- CodeBreakpoint* code_bpt = GetCodeBreakpoint (reinterpret_cast <uword>(pc) );
3120+ if (pc != 0 ) {
3121+ CodeBreakpoint* code_bpt = GetCodeBreakpoint (pc );
31173122 if (code_bpt == NULL ) {
31183123 // No code breakpoint for this code exists; create one.
3119- code_bpt = new CodeBreakpoint (bytecode, loc->token_pos_ ,
3120- reinterpret_cast <uword>(pc));
3124+ code_bpt = new CodeBreakpoint (bytecode, loc->token_pos_ , pc);
31213125 RegisterCodeBreakpoint (code_bpt);
31223126 }
31233127 code_bpt->set_bpt_location (loc);
0 commit comments