@@ -247,7 +247,8 @@ ActivationFrame::ActivationFrame(uword pc,
247
247
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
248
248
desc_indices_(8 ),
249
249
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.
251
252
}
252
253
#endif // !defined(DART_PRECOMPILED_RUNTIME)
253
254
@@ -676,7 +677,8 @@ void ActivationFrame::GetVarDescriptors() {
676
677
}
677
678
678
679
bool ActivationFrame::IsDebuggable () const {
679
- return Debugger::IsDebuggable (function ());
680
+ // When stepping in bytecode stub, function is null.
681
+ return !function ().IsNull () && Debugger::IsDebuggable (function ());
680
682
}
681
683
682
684
void ActivationFrame::PrintDescriptorsError (const char * message) {
@@ -996,8 +998,9 @@ void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
996
998
if (yield_point_index == await_jump_var) {
997
999
token_pos_ = iter.TokenPos ();
998
1000
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);
1001
1004
return ;
1002
1005
}
1003
1006
++yield_point_index;
@@ -1561,15 +1564,18 @@ const char* ActivationFrame::ToCString() {
1561
1564
intptr_t line = LineNumber ();
1562
1565
const char * func_name = Debugger::QualifiedFunctionName (function ());
1563
1566
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
1565
1568
" )\n "
1566
1569
" \t function = %s\n "
1567
1570
" \t url = %s\n "
1568
1571
" \t line = %" Pd
1569
1572
" \n "
1570
1573
" \t context = %s\n "
1571
1574
" \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 (),
1573
1579
ContextLevel ());
1574
1580
}
1575
1581
@@ -2580,9 +2586,11 @@ ActivationFrame* Debugger::TopDartFrame() const {
2580
2586
#if !defined(DART_PRECOMPILED_RUNTIME)
2581
2587
if (frame->is_interpreted ()) {
2582
2588
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.
2586
2594
ActivationFrame* activation =
2587
2595
new ActivationFrame (frame->pc (), frame->fp (), frame->sp (), bytecode);
2588
2596
return activation;
@@ -3053,19 +3061,20 @@ TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
3053
3061
3054
3062
#if !defined(DART_PRECOMPILED_RUNTIME)
3055
3063
// 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) )) {
3060
3068
pc = KernelBytecode::Next (pc);
3061
3069
}
3062
3070
if (pc < end_pc) {
3063
- ASSERT (KernelBytecode::IsDebugBreakCheckedOpcode (pc));
3071
+ ASSERT (KernelBytecode::IsDebugBreakCheckedOpcode (
3072
+ reinterpret_cast <const KBCInstr*>(pc)));
3064
3073
// The checked debug break pc must point to the next bytecode.
3065
3074
return KernelBytecode::Next (pc);
3066
3075
}
3067
3076
// No 'debug break checked' bytecode in the range.
3068
- return nullptr ;
3077
+ return 0 ;
3069
3078
}
3070
3079
#endif // !defined(DART_PRECOMPILED_RUNTIME)
3071
3080
@@ -3079,45 +3088,40 @@ void Debugger::MakeCodeBreakpointAt(const Function& func,
3079
3088
if (func.HasBytecode ()) {
3080
3089
Bytecode& bytecode = Bytecode::Handle (func.bytecode ());
3081
3090
ASSERT (!bytecode.IsNull ());
3082
- const KBCInstr* pc = nullptr ;
3091
+ uword pc = 0 ;
3083
3092
if (bytecode.HasSourcePositions ()) {
3084
3093
kernel::BytecodeSourcePositionsIterator iter (Thread::Current ()->zone (),
3085
3094
bytecode);
3086
3095
bool check_range = false ;
3087
3096
while (iter.MoveNext ()) {
3088
3097
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 ();
3092
3099
check_range = false ;
3093
3100
// Find a 'debug break checked' bytecode in the range [pc..end_pc[.
3094
3101
pc = FindBreakpointCheckedInstr (pc, end_pc);
3095
- if (pc != nullptr ) {
3102
+ if (pc != 0 ) {
3096
3103
// TODO(regis): We may want to find all PCs for a token position,
3097
3104
// e.g. in the case of duplicated bytecode in finally clauses.
3098
3105
break ;
3099
3106
}
3100
3107
}
3101
3108
if (iter.TokenPos () == loc->token_pos_ ) {
3102
- pc = reinterpret_cast <const KBCInstr*>(bytecode.PayloadStart ()) +
3103
- iter.PcOffset ();
3109
+ pc = bytecode.PayloadStart () + iter.PcOffset ();
3104
3110
check_range = true ;
3105
3111
}
3106
3112
}
3107
3113
if (check_range) {
3108
- ASSERT (pc != nullptr );
3114
+ ASSERT (pc != 0 );
3109
3115
// Use the end of the bytecode as the end of the range to check.
3110
3116
pc = FindBreakpointCheckedInstr (
3111
- pc, reinterpret_cast <const KBCInstr*>(bytecode.PayloadStart ()) +
3112
- bytecode.Size ());
3117
+ pc, bytecode.PayloadStart () + bytecode.Size ());
3113
3118
}
3114
3119
}
3115
- if (pc != nullptr ) {
3116
- CodeBreakpoint* code_bpt = GetCodeBreakpoint (reinterpret_cast <uword>(pc) );
3120
+ if (pc != 0 ) {
3121
+ CodeBreakpoint* code_bpt = GetCodeBreakpoint (pc );
3117
3122
if (code_bpt == NULL ) {
3118
3123
// 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);
3121
3125
RegisterCodeBreakpoint (code_bpt);
3122
3126
}
3123
3127
code_bpt->set_bpt_location (loc);
0 commit comments