Author: Armin Rigo <ar...@tunes.org> Branch: reverse-debugger Changeset: r85463:17761780c45d Date: 2016-06-29 22:30 +0200 http://bitbucket.org/pypy/pypy/changeset/17761780c45d/
Log: tweak 'next' and 'bnext' to work with opaque stack frame IDs instead of the stack depth diff --git a/rpython/rlib/revdb.py b/rpython/rlib/revdb.py --- a/rpython/rlib/revdb.py +++ b/rpython/rlib/revdb.py @@ -14,13 +14,13 @@ CMD_BACKTRACE = 2 CMD_LOCALS = 3 CMD_BREAKPOINTS = 4 -CMD_MOREINFO = 5 +CMD_STACKID = 5 CMD_ATTACHID = 6 CMD_CHECKWATCH = 7 CMD_WATCHVALUES = 8 ANSWER_LINECACHE= 19 ANSWER_TEXT = 20 -ANSWER_MOREINFO = 21 +ANSWER_STACKID = 21 ANSWER_NEXTNID = 22 ANSWER_WATCH = 23 diff --git a/rpython/translator/revdb/interact.py b/rpython/translator/revdb/interact.py --- a/rpython/translator/revdb/interact.py +++ b/rpython/translator/revdb/interact.py @@ -196,51 +196,61 @@ command_bs = command_bstep @contextmanager - def _stack_depth_break(self, range_stop): - # add temporarily a breakpoint for "stack_depth < range_stop" + def _stack_id_break(self, stack_id): + # add temporarily a breakpoint that hits when we enter/leave + # the frame identified by 'stack_id' b = self.pgroup.edit_breakpoints() - b.stack_depth = range_stop + b.stack_id = stack_id try: yield finally: - b.stack_depth = 0 + b.stack_id = 0 def command_next(self, argument): """Run forward for one step, skipping calls""" - depth1 = self.pgroup.get_stack_depth() - if self.move_forward(1): - depth2 = self.pgroup.get_stack_depth() - if depth2 > depth1: - # If, after running one step, the stack depth is greater - # than before, then continue until it is back to what it was. - # Can't do it more directly because the "breakpoint" of - # stack_depth is only checked for on function enters and - # returns (which simplifies and speeds up things for the - # RPython code). - with self._stack_depth_break(depth1 + 1): - self.command_continue('') + depth1 = self.pgroup.get_stack_id() + with self._stack_id_break(depth1): + if not self.move_forward(1): + # we either hit a regular breakpoint, or we hit the + # temporary breakpoint + return + if depth1 == 0: # we started outside any frame + return + if self.pgroup.get_stack_id() == depth1: + return # we are still in the same frame + # + # If, after running one step, the stack id is different than + # before but we didn't leave that frame, then we must have + # entered a new one. Continue until we leave that new frame. + # Can't do it more directly because the "breakpoint" of + # stack_id is only checked for on function enters and returns + # (which simplifies and speeds up things for the RPython + # code). + self.command_finish('') command_n = command_next def command_bnext(self, argument): """Run backward for one step, skipping calls""" - depth1 = self.pgroup.get_stack_depth() - if self.move_backward(1): - depth2 = self.pgroup.get_stack_depth() - if depth2 > depth1: - # If, after running one bstep, the stack depth is greater - # than before, then bcontinue until it is back to what it was. - with self._stack_depth_break(depth1 + 1): - self.command_bcontinue('') + # similar to command_next() + depth1 = self.pgroup.get_stack_id() + with self._stack_id_break(depth1): + if not self.move_backward(1): + return + if depth1 == 0: + return + if self.pgroup.get_stack_id() == depth1: + return # we are still in the same frame + self.command_bfinish('') command_bn = command_bnext def command_finish(self, argument): """Run forward until the current function finishes""" - with self._stack_depth_break(self.pgroup.get_stack_depth()): + with self._stack_id_break(self.pgroup.get_stack_id()): self.command_continue('') def command_bfinish(self, argument): """Run backward until the current function is called""" - with self._stack_depth_break(self.pgroup.get_stack_depth()): + with self._stack_id_break(self.pgroup.get_stack_id()): self.command_bcontinue('') def command_continue(self, argument): diff --git a/rpython/translator/revdb/message.py b/rpython/translator/revdb/message.py --- a/rpython/translator/revdb/message.py +++ b/rpython/translator/revdb/message.py @@ -14,9 +14,9 @@ CMD_PRINT = 1 # Message(CMD_PRINT, extra=expression) CMD_BACKTRACE = 2 # Message(CMD_BACKTRACE) CMD_LOCALS = 3 # Message(CMD_LOCALS) -CMD_BREAKPOINTS = 4 # Message(CMD_BREAKPOINTS, stack_depth, +CMD_BREAKPOINTS = 4 # Message(CMD_BREAKPOINTS, stack_id, # extra="\0-separated names") -CMD_MOREINFO = 5 # Message(CMD_MOREINFO) +CMD_STACKID = 5 # Message(CMD_STACKID, parent-flag) CMD_ATTACHID = 6 # Message(CMD_ATTACHID, small-num, unique-id) CMD_CHECKWATCH = 7 # Message(CMD_CHECKWATCH, extra=expression) CMD_WATCHVALUES = 8 # Message(CMD_WATCHVALUES, extra=texts) @@ -55,9 +55,13 @@ # Message(ANSWER_TEXT, extra=text) ANSWER_TEXT = 20 -# sent after CMD_MOREINFO: -# Message(ANSWER_MOREINFO, stack_depth) -ANSWER_MOREINFO = 21 +# CMD_STACKID returns the id of the current or parent frame (depending +# on the 'parent-flag' passed in), or 0 if not found. The id can be just +# the stack depth, or it can be the unique id of the frame object. When +# used in CMD_BREAKPOINTS, it means "break if we are entering/leaving that +# frame". +# Message(ANSWER_STACKID, stack-id) +ANSWER_STACKID = 21 # sent from CMD_PRINT to record the existence of a recallable object # Message(ANSWER_NEXTNID, unique-id) diff --git a/rpython/translator/revdb/process.py b/rpython/translator/revdb/process.py --- a/rpython/translator/revdb/process.py +++ b/rpython/translator/revdb/process.py @@ -19,16 +19,16 @@ self.num2name = {} # {small number: break/watchpoint} self.watchvalues = {} # {small number: resulting text} self.watchuids = {} # {small number: [uid...]} - self.stack_depth = 0 # breaks if the depth becomes lower than this + self.stack_id = 0 # breaks when leaving/entering this frame; 0=none def __repr__(self): return 'AllBreakpoints(%r, %r, %r, %d)' % ( self.num2name, self.watchvalues, self.watchuids, - self.stack_depth) + self.stack_id) def compare(self, other): if (self.num2name == other.num2name and - self.stack_depth == other.stack_depth): + self.stack_id == other.stack_id): if self.watchvalues == other.watchvalues: return 2 # completely equal else: @@ -37,12 +37,12 @@ return 0 # different def is_empty(self): - return len(self.num2name) == 0 and self.stack_depth == 0 + return len(self.num2name) == 0 and self.stack_id == 0 def duplicate(self): a = AllBreakpoints() a.num2name.update(self.num2name) - a.stack_depth = self.stack_depth + a.stack_id = self.stack_id return a @@ -364,7 +364,7 @@ N = (max(num2name) + 1) if num2name else 0 if cmp == 0: flat = [num2name.get(n, '') for n in range(N)] - arg1 = self.all_breakpoints.stack_depth + arg1 = self.all_breakpoints.stack_id extra = '\x00'.join(flat) self.active.send(Message(CMD_BREAKPOINTS, arg1, extra=extra)) self.active.expect_ready() @@ -536,8 +536,8 @@ def edit_breakpoints(self): return self.all_breakpoints - def get_stack_depth(self): - self.active.send(Message(CMD_MOREINFO)) - msg = self.active.expect(ANSWER_MOREINFO, Ellipsis) + def get_stack_id(self): + self.active.send(Message(CMD_STACKID)) + msg = self.active.expect(ANSWER_STACKID, Ellipsis) self.active.expect_ready() return msg.arg1 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit