File: revdb_include.h

package info (click to toggle)
pypy 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 107,216 kB
  • sloc: python: 1,201,787; ansic: 62,419; asm: 5,169; cpp: 3,017; sh: 2,534; makefile: 545; xml: 243; lisp: 45; awk: 4
file content (320 lines) | stat: -rw-r--r-- 16,103 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#include <string.h>
#include "src/thread.h"

/************************************************************
 ***  RevDB --- record and replay debugging               ***
 ************************************************************/


typedef struct {
#ifndef RPY_RDB_REPLAY
    bool_t replay;
#define RPY_RDB_REPLAY   rpy_revdb.replay
#define RPY_RDB_DYNAMIC_REPLAY
#else
# error "explicit RPY_RDB_REPLAY: not really supported"
#endif
    bool_t watch_enabled;
    int lock;
    char *buf_p;  /* NULL during recording if recording is actually disabled */
    char *buf_limit, *buf_readend;
    uint64_t stop_point_seen, stop_point_break;
    uint64_t unique_id_seen, unique_id_break;
} rpy_revdb_t;

RPY_EXTERN rpy_revdb_t rpy_revdb;
RPY_EXTERN int rpy_rev_fileno;
RPY_EXTERN __thread int rpy_active_thread;


/* ------------------------------------------------------------ */

RPY_EXTERN void rpy_reverse_db_setup(int *argc_p, char **argv_p[]);
RPY_EXTERN int rpy_reverse_db_main(Signed entry_point(Signed, char**),
                                   int argc, char **argv);

/* enable to print locations to stderr of all the EMITs */
#ifdef RPY_REVDB_PRINT_ALL
#  define _RPY_REVDB_PRINT(mode, _e)                                    \
    if (rpy_rev_fileno >= 0) {                                          \
        fprintf(stderr,                                                 \
                "%s %s:%d: %0*llx\n",                                   \
                mode, __FILE__, (int)__LINE__, (int)(2 * sizeof(_e)),   \
                ((unsigned long long)_e) & ((2ULL << (8*sizeof(_e)-1)) - 1)); \
    }
#endif

/* enable to print all mallocs to stderr */
#ifdef RPY_REVDB_PRINT_ALL
RPY_EXTERN void seeing_uid(uint64_t uid);
#  define _RPY_REVDB_PRUID()                                            \
    if (rpy_rev_fileno >= 0) {                                          \
        seeing_uid(uid);                                                \
        fprintf(stderr,                                                 \
                "[nobj] %s:%d: obj %llu\n",                             \
                __FILE__, (int)__LINE__, (unsigned long long) uid);     \
    }
#endif

#ifndef _RPY_REVDB_PRINT
#  define _RPY_REVDB_PRINT(mode, _e)  /* nothing */
#endif
#ifndef _RPY_REVDB_PRUID
#  define _RPY_REVDB_PRUID()      /* nothing */
#endif


/* Acquire/release the lock around EMIT_RECORD, because it may be
   called without holding the GIL.  Note that we're always
   single-threaded during replaying: the lock is only useful during
   recording.  

   Implementation trick: use 'a >= b' to mean 'a || !b' (the two
   variables can only take the values 0 or 1).
*/
#define _RPY_REVDB_LOCK()                                               \
    {                                                                   \
        int _lock_contention = pypy_lock_test_and_set(&rpy_revdb.lock, 1); \
        if (_lock_contention >= rpy_active_thread)                      \
            rpy_reverse_db_lock_acquire(_lock_contention);              \
    }
#define _RPY_REVDB_UNLOCK()                                             \
    pypy_lock_release(&rpy_revdb.lock)


#define _RPY_REVDB_EMIT_RECORD_L(decl_e, variable)                      \
        {                                                               \
            decl_e = variable;                                          \
            _RPY_REVDB_PRINT("[ wr ]", _e);                             \
            char *_dst = rpy_revdb.buf_p;                               \
            if (_dst) {                                                 \
                memcpy(_dst, &_e, sizeof(_e));                          \
                if ((rpy_revdb.buf_p = _dst + sizeof(_e))               \
                        > rpy_revdb.buf_limit)                          \
                    rpy_reverse_db_flush();                             \
            }                                                           \
        }

#define _RPY_REVDB_EMIT_REPLAY(decl_e, variable)                        \
        {                                                               \
            decl_e;                                                     \
            char *_src = rpy_revdb.buf_p;                               \
            char *_end1 = _src + sizeof(_e);                            \
            memcpy(&_e, _src, sizeof(_e));                              \
            rpy_revdb.buf_p = _end1;                                    \
            _RPY_REVDB_PRINT("[ rd ]", _e);                             \
            if (_end1 >= rpy_revdb.buf_limit)                           \
                rpy_reverse_db_fetch(__FILE__, __LINE__);               \
            variable = _e;                                              \
        }

#define _RPY_REVDB_EMIT_L(normal_code, decl_e, variable)                \
    if (!RPY_RDB_REPLAY) {                                              \
        normal_code                                                     \
        _RPY_REVDB_EMIT_RECORD_L(decl_e, variable)                      \
    } else                                                              \
        _RPY_REVDB_EMIT_REPLAY(decl_e, variable)

#define RPY_REVDB_EMIT(normal_code, decl_e, variable)                   \
    if (!RPY_RDB_REPLAY) {                                              \
        normal_code                                                     \
        _RPY_REVDB_LOCK();                                              \
        _RPY_REVDB_EMIT_RECORD_L(decl_e, variable)                      \
        _RPY_REVDB_UNLOCK();                                            \
    } else                                                              \
        _RPY_REVDB_EMIT_REPLAY(decl_e, variable)

#define RPY_REVDB_EMIT_VOID(normal_code)                                \
    if (!RPY_RDB_REPLAY) { normal_code } else { }

#define RPY_REVDB_CALL(call_code, decl_e, variable)                     \
    if (!RPY_RDB_REPLAY) {                                              \
        call_code                                                       \
        _RPY_REVDB_LOCK();                                              \
        _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFC)                \
        _RPY_REVDB_EMIT_RECORD_L(decl_e, variable)                      \
        _RPY_REVDB_UNLOCK();                                            \
    } else {                                                            \
        unsigned char _re;                                              \
        _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re)                   \
        if (_re != 0xFC)                                                \
            rpy_reverse_db_invoke_callback(_re);                        \
        _RPY_REVDB_EMIT_REPLAY(decl_e, variable)                        \
    }

#define RPY_REVDB_CALL_VOID(call_code)                                  \
    if (!RPY_RDB_REPLAY) {                                              \
        call_code                                                       \
        _RPY_REVDB_LOCK();                                              \
        _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFC)                \
        _RPY_REVDB_UNLOCK();                                            \
    }                                                                   \
    else {                                                              \
        unsigned char _re;                                              \
        _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re)                   \
        if (_re != 0xFC)                                                \
            rpy_reverse_db_invoke_callback(_re);                        \
    }

#define RPY_REVDB_CALL_GIL_ACQUIRE()                                    \
    if (!RPY_RDB_REPLAY) {                                              \
        RPyGilAcquire();                                                \
        _RPY_REVDB_LOCK();                                              \
        _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFD)                \
        _RPY_REVDB_UNLOCK();                                            \
    }                                                                   \
    else {                                                              \
        unsigned char _re;                                              \
        _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re)                   \
        if (_re != 0xFD)                                                \
            rpy_reverse_db_bad_acquire_gil("acquire");                  \
    }

#define RPY_REVDB_CALL_GIL_RELEASE()                                    \
    if (!RPY_RDB_REPLAY) {                                              \
        _RPY_REVDB_LOCK();                                              \
        _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFE)                \
        _RPY_REVDB_UNLOCK();                                            \
        RPyGilRelease();                                                \
    }                                                                   \
    else {                                                              \
        unsigned char _re;                                              \
        _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re)                   \
        if (_re != 0xFE)                                                \
            rpy_reverse_db_bad_acquire_gil("release");                  \
    }

#define RPY_REVDB_C_ONLY_ENTER                                          \
    char *saved_bufp = rpy_revdb.buf_p;                                 \
    rpy_revdb.buf_p = NULL;

#define RPY_REVDB_C_ONLY_LEAVE                                          \
    rpy_revdb.buf_p = saved_bufp;

#define RPY_REVDB_CALLBACKLOC(locnum)                                   \
    rpy_reverse_db_callback_loc(locnum)

#define RPY_REVDB_REC_UID(expr)                                         \
    do {                                                                \
        uint64_t uid = rpy_revdb.unique_id_seen;                        \
        if (uid == rpy_revdb.unique_id_break || !expr)                  \
            uid = rpy_reverse_db_unique_id_break(expr);                 \
        rpy_revdb.unique_id_seen = uid + 1;                             \
        ((struct pypy_header0 *)expr)->h_uid = uid;                     \
        _RPY_REVDB_PRUID();                                             \
    } while (0)

#define OP_REVDB_STOP_POINT(place, r)                                   \
    if (++rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break)      \
        rpy_reverse_db_stop_point(place)

#define OP_REVDB_SEND_ANSWER(cmd, arg1, arg2, arg3, ll_string, r)       \
    rpy_reverse_db_send_answer(cmd, arg1, arg2, arg3, ll_string)

#define OP_REVDB_BREAKPOINT(num, r)                                     \
    rpy_reverse_db_breakpoint(num)

#define OP_REVDB_GET_VALUE(value_id, r)                                 \
    r = rpy_reverse_db_get_value(value_id)

#define OP_REVDB_IDENTITYHASH(obj, r)                                   \
    r = rpy_reverse_db_identityhash((struct pypy_header0 *)(obj))

#define OP_REVDB_GET_UNIQUE_ID(x, r)                                    \
    r = ((struct pypy_header0 *)x)->h_uid

#define OP_REVDB_TRACK_OBJECT(uid, callback, r)                         \
    rpy_reverse_db_track_object(uid, callback)

#define OP_REVDB_WATCH_SAVE_STATE(force, r)   do {                      \
        r = rpy_revdb.watch_enabled;                                    \
        if ((force) || r) rpy_reverse_db_watch_save_state();            \
    } while (0)

#define OP_REVDB_WATCH_RESTORE_STATE(any_watch_point, r)                \
    rpy_reverse_db_watch_restore_state(any_watch_point)

#define OP_REVDB_WEAKREF_CREATE(target, r)                              \
    r = rpy_reverse_db_weakref_create(target)

#define OP_REVDB_WEAKREF_DEREF(weakref, r)                              \
    r = rpy_reverse_db_weakref_deref(weakref)

#define OP_REVDB_CALL_DESTRUCTOR(obj, r)                                \
    rpy_reverse_db_call_destructor(obj)

#define RPY_REVDB_CAST_PTR_TO_INT(obj)                                  \
    rpy_reverse_db_cast_ptr_to_int((struct pypy_header0 *)(obj))

#define OP_REVDB_SET_THREAD_BREAKPOINT(tnum, r)                         \
    rpy_reverse_db_set_thread_breakpoint(tnum)

#define OP_REVDB_STRTOD(s, r)                                           \
    r = rpy_reverse_db_strtod(s)

#define OP_REVDB_DTOA(d, r)                                             \
    r = rpy_reverse_db_dtoa(d)

#define OP_REVDB_MODF(x, index, r)                                      \
    do {                                                                \
        double _r0, _r1;                                                \
        _r0 = modf(x, &_r1);                                            \
        r = (index == 0) ? _r0 : _r1;                                   \
    } while (0)

#define OP_REVDB_FREXP(x, index, r)                                     \
    do {                                                                \
        double _r0; int _r1;                                            \
        _r0 = frexp(x, &_r1);                                           \
        r = (index == 0) ? _r0 : _r1;                                   \
    } while (0)


#define OP_GC_RAWREFCOUNT_CREATE_LINK_PYPY(gcobj, pyobj, r)   \
    rpy_reverse_db_rawrefcount_create_link_pypy(gcobj, pyobj)

#define OP_GC_RAWREFCOUNT_CREATE_LINK_PYOBJ(gcobj, pyobj, r)   \
    rpy_reverse_db_rawrefcount_create_link_pypy(gcobj, pyobj)

#define OP_GC_RAWREFCOUNT_FROM_OBJ(gcobj, r)   \
    r = rpy_reverse_db_rawrefcount_from_obj(gcobj)

#define OP_GC_RAWREFCOUNT_TO_OBJ(pyobj, r)   \
    r = rpy_reverse_db_rawrefcount_to_obj(pyobj)

#define OP_GC_RAWREFCOUNT_NEXT_DEAD(r)   \
    r = rpy_reverse_db_rawrefcount_next_dead()


RPY_EXTERN void rpy_reverse_db_flush(void);  /* must be called with the lock */
RPY_EXTERN void rpy_reverse_db_fetch(const char *file, int line);
RPY_EXTERN void rpy_reverse_db_stop_point(long place);
RPY_EXTERN void rpy_reverse_db_send_answer(int cmd, int64_t arg1, int64_t arg2,
                                           int64_t arg3, RPyString *extra);
RPY_EXTERN Signed rpy_reverse_db_identityhash(struct pypy_header0 *obj);
RPY_EXTERN Signed rpy_reverse_db_cast_ptr_to_int(struct pypy_header0 *obj);
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_watch_save_state(void);
RPY_EXTERN void rpy_reverse_db_watch_restore_state(bool_t any_watch_point);
RPY_EXTERN void *rpy_reverse_db_weakref_create(void *target);
RPY_EXTERN void *rpy_reverse_db_weakref_deref(void *weakref);
RPY_EXTERN int rpy_reverse_db_fq_register(void *obj);
RPY_EXTERN void *rpy_reverse_db_next_dead(void *result);
RPY_EXTERN void rpy_reverse_db_register_destructor(void *obj, void(*)(void *));
RPY_EXTERN void rpy_reverse_db_call_destructor(void *obj);
RPY_EXTERN void rpy_reverse_db_invoke_callback(unsigned char);
RPY_EXTERN void rpy_reverse_db_callback_loc(int);
RPY_EXTERN void rpy_reverse_db_lock_acquire(bool_t lock_contention);
RPY_EXTERN void rpy_reverse_db_bad_acquire_gil(const char *name);
RPY_EXTERN void rpy_reverse_db_set_thread_breakpoint(int64_t tnum);
RPY_EXTERN double rpy_reverse_db_strtod(RPyString *s);
RPY_EXTERN RPyString *rpy_reverse_db_dtoa(double d);
RPY_EXTERN void rpy_reverse_db_rawrefcount_create_link_pypy(void *gcobj, 
                                                            void *pyobj);
RPY_EXTERN void *rpy_reverse_db_rawrefcount_from_obj(void *gcobj);
RPY_EXTERN void *rpy_reverse_db_rawrefcount_to_obj(void *pyobj);
RPY_EXTERN void *rpy_reverse_db_rawrefcount_next_dead(void);

/* ------------------------------------------------------------ */