[pypy-commit] pypy reverse-debugger: in-progress: tracking live objects
arigo
pypy.commits at gmail.com
Tue Jun 21 10:53:41 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger
Changeset: r85306:1c3f6914ae95
Date: 2016-06-21 16:54 +0200
http://bitbucket.org/pypy/pypy/changeset/1c3f6914ae95/
Log: in-progress: tracking live objects
diff --git a/rpython/rlib/revdb.py b/rpython/rlib/revdb.py
--- a/rpython/rlib/revdb.py
+++ b/rpython/rlib/revdb.py
@@ -17,6 +17,7 @@
CMD_MOREINFO = 5
ANSWER_TEXT = 20
ANSWER_MOREINFO = 21
+ANSWER_NEXTNID = 22
def stop_point():
@@ -31,6 +32,9 @@
def register_debug_command(command, lambda_func):
"""Register the extra RPython-implemented debug command."""
+def register_allocation_command(lambda_func):
+ """Register the extra RPython-implemented callback for allocation."""
+
def send_answer(cmd, arg1=0, arg2=0, arg3=0, extra=""):
"""For RPython debug commands: writes an answer block to stdout"""
llop.revdb_send_answer(lltype.Void, cmd, arg1, arg2, arg3, extra)
@@ -38,6 +42,9 @@
def send_output(text):
send_answer(ANSWER_TEXT, extra=text)
+def send_nextnid(unique_id):
+ send_answer(ANSWER_NEXTNID, unique_id)
+
def current_time():
"""For RPython debug commands: returns the current time."""
return llop.revdb_get_value(lltype.SignedLongLong, 'c')
@@ -131,7 +138,12 @@
cmds = t.revdb_commands
except AttributeError:
cmds = t.revdb_commands = []
- cmds.append((command_num, func))
+ for old_num, old_func in cmds:
+ if old_num == command_num:
+ assert old_func is func
+ break
+ else:
+ cmds.append((command_num, func))
s_func = self.bookkeeper.immutablevalue(func)
s_ptr1 = llannotation.SomePtr(ll_ptrtype=_CMDPTR)
s_str2 = annmodel.SomeString()
@@ -140,3 +152,28 @@
def specialize_call(self, hop):
hop.exception_cannot_occur()
+
+
+class RegisterAllocationCommand(ExtRegistryEntry):
+ _about_ = register_allocation_command
+
+ def compute_result_annotation(self, s_lambda_func):
+ from rpython.annotator import model as annmodel
+ from rpython.rtyper import llannotation
+
+ lambda_func = s_lambda_func.const
+ t = self.bookkeeper.annotator.translator
+ if t.config.translation.reverse_debugger:
+ func = lambda_func()
+ try:
+ assert t.revdb_allocation_cmd is func
+ except AttributeError:
+ t.revdb_allocation_cmd = func
+ s_func = self.bookkeeper.immutablevalue(func)
+ s_int1 = annmodel.SomeInteger(knowntype=r_longlong)
+ s_ref2 = llannotation.lltype_to_annotation(llmemory.GCREF)
+ self.bookkeeper.emulate_pbc_call(self.bookkeeper.position_key,
+ s_func, [s_int1, s_ref2])
+
+ def specialize_call(self, hop):
+ hop.exception_cannot_occur()
diff --git a/rpython/translator/revdb/gencsupp.py b/rpython/translator/revdb/gencsupp.py
--- a/rpython/translator/revdb/gencsupp.py
+++ b/rpython/translator/revdb/gencsupp.py
@@ -1,5 +1,5 @@
import py
-from rpython.rtyper.lltypesystem import lltype, rffi, rstr
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
from rpython.translator.c.support import cdecl
from rpython.rlib import exports, revdb
@@ -23,25 +23,31 @@
def prepare_database(db):
- FUNCPTR = lltype.Ptr(lltype.FuncType([revdb._CMDPTR,
- lltype.Ptr(rstr.STR)], lltype.Void))
+ FUNCPTR = lltype.Ptr(lltype.FuncType([revdb._CMDPTR, lltype.Ptr(rstr.STR)],
+ lltype.Void))
+ ALLOCFUNCPTR = lltype.Ptr(lltype.FuncType([rffi.LONGLONG, llmemory.GCREF],
+ lltype.Void))
bk = db.translator.annotator.bookkeeper
cmds = getattr(db.translator, 'revdb_commands', [])
- array_names = lltype.malloc(rffi.CArray(rffi.INT), len(cmds) + 1,
- flavor='raw', immortal=True, zero=True)
- array_funcs = lltype.malloc(rffi.CArray(FUNCPTR), len(cmds),
- flavor='raw', immortal=True, zero=True)
+ S = lltype.Struct('RPY_REVDB_COMMANDS',
+ ('names', lltype.FixedSizeArray(rffi.INT, len(cmds) + 1)),
+ ('funcs', lltype.FixedSizeArray(FUNCPTR, len(cmds))),
+ ('alloc', ALLOCFUNCPTR))
+ s = lltype.malloc(S, flavor='raw', immortal=True, zero=True)
for i, (name, func) in enumerate(cmds):
fnptr = lltype.getfunctionptr(bk.getdesc(func).getuniquegraph())
assert lltype.typeOf(fnptr) == FUNCPTR
assert isinstance(name, int) and name != 0
- array_names[i] = rffi.cast(rffi.INT, name)
- array_funcs[i] = fnptr
+ s.names[i] = rffi.cast(rffi.INT, name)
+ s.funcs[i] = fnptr
- exports.EXPORTS_obj2name[array_names._as_obj()] = 'rpy_revdb_command_names'
- exports.EXPORTS_obj2name[array_funcs._as_obj()] = 'rpy_revdb_command_funcs'
- db.get(array_names)
- db.get(array_funcs)
+ allocation_cmd = getattr(db.translator, 'revdb_allocation_cmd', None)
+ if allocation_cmd is not None:
+ s.alloc = lltype.getfunctionptr(
+ bk.getdesc(allocation_cmd).getuniquegraph())
+
+ exports.EXPORTS_obj2name[s._as_obj()] = 'rpy_revdb_commands'
+ db.get(s)
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
@@ -4,9 +4,11 @@
# See the corresponding answers for details about messages.
-CMD_FORK = -1 # Message(CMD_FORK)
-CMD_QUIT = -2 # Message(CMD_QUIT)
-CMD_FORWARD = -3 # Message(CMD_FORWARD, steps, breakpoint_mode)
+CMD_FORK = -1 # Message(CMD_FORK)
+CMD_QUIT = -2 # Message(CMD_QUIT)
+CMD_FORWARD = -3 # Message(CMD_FORWARD, steps, breakpoint_mode)
+CMD_FUTUREIDS = -4 # Message(CMD_FUTUREIDS, extra=list-of-8bytes-uids)
+CMD_ALLOCATING= -5 # Message(CMD_CREATING, uid, addr)
# extra commands which are not handled by revdb.c, but
# by revdb.register_debug_command()
CMD_PRINT = 1 # Message(CMD_PRINT, extra=expression)
@@ -50,6 +52,10 @@
# Message(ANSWER_MOREINFO, stack_depth)
ANSWER_MOREINFO = 21
+# sent from CMD_PRINT to record the existence of a recallable object
+# Message(ANSWER_NEXTNID, unique-id)
+ANSWER_NEXTNID = 22
+
# ____________________________________________________________
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
@@ -172,6 +172,7 @@
self.active = child
self.paused = {1: child.clone()} # {time: subprocess}
self.all_breakpoints = AllBreakpoints()
+ self.all_printed_objects = []
def get_current_time(self):
return self.active.current_time
@@ -313,7 +314,8 @@
"""Print an expression.
"""
self.active.tainted = True
- self.active.send(Message(CMD_PRINT, extra=expression))
+ next_nid = len(self.all_printed_objects)
+ self.active.send(Message(CMD_PRINT, next_nid, extra=expression))
self.active.print_text_answer()
def show_backtrace(self):
diff --git a/rpython/translator/revdb/src-revdb/revdb.c b/rpython/translator/revdb/src-revdb/revdb.c
--- a/rpython/translator/revdb/src-revdb/revdb.c
+++ b/rpython/translator/revdb/src-revdb/revdb.c
@@ -192,9 +192,10 @@
#define INIT_VERSION_NUMBER 0xd80100
-#define CMD_FORK (-1)
-#define CMD_QUIT (-2)
-#define CMD_FORWARD (-3)
+#define CMD_FORK (-1)
+#define CMD_QUIT (-2)
+#define CMD_FORWARD (-3)
+#define CMD_FUTUREIDS (-4)
#define ANSWER_INIT (-20)
#define ANSWER_READY (-21)
@@ -215,6 +216,7 @@
static uint64_t last_recorded_breakpoint_loc;
static int last_recorded_breakpoint_num;
static char breakpoint_mode;
+static uint64_t *future_ids, *future_next_id;
static void attach_gdb(void)
{
@@ -540,12 +542,33 @@
}
}
+static void command_future_ids(rpy_revdb_command_t *cmd, char *extra)
+{
+ free(future_ids);
+ if (cmd->extra_size == 0) {
+ future_ids = NULL;
+ rpy_revdb.unique_id_break = 0;
+ }
+ else {
+ assert(cmd->extra_size % sizeof(uint64_t) == 0);
+ future_ids = malloc(cmd->extra_size + sizeof(uint64_t));
+ if (future_ids == NULL) {
+ fprintf(stderr, "out of memory for a buffer of %llu chars\n",
+ (unsigned long long)cmd->extra_size);
+ exit(1);
+ }
+ memcpy(future_ids, extra, cmd->extra_size);
+ future_ids[cmd->extra_size / sizeof(uint64_t)] = 0;
+ }
+ future_next_id = future_ids;
+}
+
static void command_default(rpy_revdb_command_t *cmd, char *extra)
{
RPyString *s;
int i;
- for (i = 0; rpy_revdb_command_names[i] != cmd->cmd; i++) {
- if (rpy_revdb_command_names[i] == 0) {
+ for (i = 0; rpy_revdb_commands.rp_names[i] != cmd->cmd; i++) {
+ if (rpy_revdb_commands.rp_names[i] == 0) {
fprintf(stderr, "unknown command %d\n", cmd->cmd);
exit(1);
}
@@ -558,16 +581,29 @@
s = make_rpy_string(cmd->extra_size);
memcpy(_RPyString_AsString(s), extra, cmd->extra_size);
}
- execute_rpy_function(rpy_revdb_command_funcs[i], cmd, s);
+ execute_rpy_function(rpy_revdb_commands.rp_funcs[i], cmd, s);
+}
+
+static void save_state(void)
+{
+ stopped_time = rpy_revdb.stop_point_seen;
+ stopped_uid = rpy_revdb.unique_id_seen;
+ rpy_revdb.unique_id_seen = (-1ULL) << 63;
+}
+
+static void restore_state(void)
+{
+ rpy_revdb.stop_point_seen = stopped_time;
+ rpy_revdb.unique_id_seen = stopped_uid;
+ stopped_time = 0;
+ stopped_uid = 0;
}
RPY_EXTERN
void rpy_reverse_db_stop_point(void)
{
while (rpy_revdb.stop_point_break == rpy_revdb.stop_point_seen) {
- stopped_time = rpy_revdb.stop_point_seen;
- stopped_uid = rpy_revdb.unique_id_seen;
- rpy_revdb.unique_id_seen = (-1ULL) << 63;
+ save_state();
breakpoint_mode = 0;
if (pending_after_forward) {
@@ -599,15 +635,16 @@
command_forward(&cmd);
break;
+ case CMD_FUTUREIDS:
+ command_future_ids(&cmd, extra);
+ break;
+
default:
command_default(&cmd, extra);
break;
}
}
- rpy_revdb.stop_point_seen = stopped_time;
- rpy_revdb.unique_id_seen = stopped_uid;
- stopped_time = 0;
- stopped_uid = 0;
+ restore_state();
}
}
@@ -696,39 +733,21 @@
}
}
-static void (*unique_id_callback)(void *);
-
RPY_EXTERN
uint64_t rpy_reverse_db_unique_id_break(void *new_object)
{
- rpy_revdb_t dinfo;
- rpy_revdb.unique_id_break = 0;
- disable_io(&dinfo);
- if (setjmp(jmp_buf_cancel_execution) == 0)
- unique_id_callback(new_object);
- enable_io(&dinfo);
+ if (!new_object) {
+ fprintf(stderr, "out of memory: allocation failed, cannot continue\n");
+ exit(1);
+ }
+ if (rpy_revdb_commands.rp_alloc) {
+ save_state();
+ rpy_revdb_commands.rp_alloc(rpy_revdb.unique_id_seen, new_object);
+ restore_state();
+ }
+ rpy_revdb.unique_id_break = *future_next_id++;
return rpy_revdb.unique_id_seen;
}
-RPY_EXTERN
-void rpy_reverse_db_track_object(long long unique_id, void callback(void *))
-{
- if (stopped_uid <= 0) {
- fprintf(stderr, "stopped_uid should not be <= 0\n");
- return;
- }
- if (unique_id <= 0) {
- fprintf(stderr, "cannot track a prebuilt or debugger-created object\n");
- return;
- }
- if (unique_id < stopped_uid) {
- fprintf(stderr, "cannot track the creation of an object already created\n");
- return;
- }
- assert(callback != NULL);
- unique_id_callback = callback;
- rpy_revdb.unique_id_break = unique_id;
-}
-
/* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/src-revdb/revdb_include.h b/rpython/translator/revdb/src-revdb/revdb_include.h
--- a/rpython/translator/revdb/src-revdb/revdb_include.h
+++ b/rpython/translator/revdb/src-revdb/revdb_include.h
@@ -114,8 +114,5 @@
RPY_EXTERN void rpy_reverse_db_breakpoint(int64_t num);
RPY_EXTERN long long rpy_reverse_db_get_value(char value_id);
RPY_EXTERN uint64_t rpy_reverse_db_unique_id_break(void *new_object);
-RPY_EXTERN void rpy_reverse_db_track_object(long long unique_id,
- void callback(void *));
-
/* ------------------------------------------------------------ */
More information about the pypy-commit
mailing list