Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit