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
|
/***************************************************************/
/*** Global Psyco definitions ***/
/***************************************************************/
#ifndef _PSYCO_H
#define _PSYCO_H
#include <Python.h>
#include <structmember.h> /* for offsetof() */
/*****************************************************************/
/*** Various customizable parameters (use your compilers' ***/
/*** option to override them, e.g. -DXXX=value in gcc) ***/
/* set to 0 to disable all debugging checks and output */
#ifndef PSYCO_DEBUG
# define PSYCO_DEBUG 0
#endif
/* define to 1 for extra assert()'s */
#ifndef ALL_CHECKS
# define ALL_CHECKS (PSYCO_DEBUG ? 1 : 0)
#endif
/* level of debugging outputs: 0 = none, 1 = a few, 2 = more,
3 = detailled, 4 = full execution trace */
#ifndef VERBOSE_LEVEL
# define VERBOSE_LEVEL (PSYCO_DEBUG ? 0 : 0)
#endif
/* dump information about profiling and statistics */
#ifndef VERBOSE_STATS
# define VERBOSE_STATS (VERBOSE_LEVEL>=2)
#endif
/* define for *heavy* memory checking: 0 = off, 1 = reasonably heavy,
2 = unreasonably heavy */
#ifndef HEAVY_MEM_CHECK
# define HEAVY_MEM_CHECK (PSYCO_DEBUG ? 0 : 0)
#endif
#ifdef MS_WIN32
# undef HEAVY_MEM_CHECK
# define HEAVY_MEM_CHECK 0 /* not supported on Windows */
#endif
/* define to write produced blocks of code into a file; see 'xam.py'
0 = off, 1 = only manually (from a debugger or with _psyco.dumpcodebuf()),
2 = only when returning from Psyco,
3 = every time a new code block is built */
#ifndef CODE_DUMP
# define CODE_DUMP (PSYCO_DEBUG ? 1 : 0)
#endif
#if CODE_DUMP && !defined(CODE_DUMP_FILE)
# define CODE_DUMP_FILE "psyco.dump"
#endif
/* define to inline the most common functions in the produced code
(should be enabled unless you want to trade code size for speed) */
#ifndef INLINE_COMMON_FUNCTIONS
# define INLINE_COMMON_FUNCTIONS 1
#endif
#if CODE_DUMP && defined(HAVE_DLFCN_H)
/* define to locate shared symbols and write them in CODE_DUMP_FILE
requires the GNU extension dladdr() in <dlfcn.h>
Not really useful, only finds non-static symbols. */
/*# include <dlfcn.h>
# define CODE_DUMP_SYMBOLS*/
#endif
#define DEFAULT_RECURSION 10 /* default value for the 'rec' argument */
/*****************************************************************/
/* Size of buffer to allocate when emitting code.
Can be as large as you like (most OSes will not actually allocate
RAM pages before they are actually used). We no longer perform
any realloc() on this; a single allocated code region is reused
for all code buffers until it is exhausted. There are BUFFER_MARGIN
unused bytes at the end, so BIG_BUFFER_SIZE has better be large to
minimize this effect.
Linux note: I've seen in my version of glibc's malloc() that it
uses mmap for sizes >= 128k, and that it will refuse the use mmap
more than 1024 times, which means that if you allocate blocks of
128k you cannot allocate more than 128M in total.
Note that Psyco will usually allocate and fill two buffers in
parallel, by the way vcompiler.c works. However, it occasionally
needs more; codemanager.c can handle any number of parallely-growing
buffers. There is a safeguard in vcompiler.c to put an upper bound
on this number (currently should not exceed 4).
In debugging mode, we use a small size to stress the buffer-
continuation coding routines. */
#ifndef BIG_BUFFER_SIZE
# define BIG_BUFFER_SIZE (PSYCO_DEBUG ? 2*BUFFER_MARGIN : 0x100000)
#endif
/* A safety margin for occasional overflows: we might write a few
instructions too much before we realize we wrote past 'codelimit'.
XXX carefully check that it is impossible to overflow by more
We need more than 128 bytes because of the way conditional jumps
are emitted; see pycompiler.c.
The END_CODE macro triggers a silent buffer change if space is
getting very low -- less than GUARANTEED_MINIMUM */
#ifndef BUFFER_MARGIN
# define BUFFER_MARGIN 1024
#endif
/* When emitting code, all called functions can assume that they
have at least this amount of room to write their code. If they
might need more, they have to allocate new buffers and write a
jump to these from the original code (jumps can be done in less
than GUARANTEED_MINIMUM bytes). */
#ifndef GUARANTEED_MINIMUM
# define GUARANTEED_MINIMUM 64
#endif
#ifndef ALL_STATIC
# define ALL_STATIC 0 /* make all functions static; set to 1 by hack.c */
#endif
#if ALL_STATIC
# define EXTERNVAR staticforward
# define EXTERNFN static
# define DEFINEVAR statichere
# define DEFINEFN static
# define INITIALIZATIONFN PSY_INLINE
#else
# define EXTERNVAR
# define EXTERNFN
# define DEFINEVAR
# define DEFINEFN
# define INITIALIZATIONFN DEFINEFN
#endif
#if defined(_MSC_VER)
# if _MSC_VER < 1310 /* not an exact number */
# define BROKEN_CPP
# endif
#endif
#ifndef BROKEN_CPP
# define psyco_assert(x) ((void)((x) || psyco_fatal_msg(#x)))
#else
/* The VC++ preprocessor is not even able to produce from #x a C string that
is correctly escaped for the VC++ compiler !! */
# define psyco_assert(x) ((void)((x) || psyco_fatal_msg("assertion failed")))
#endif
#define psyco_fatal_msg(msg) psyco_fatal_error(msg, __FILE__, __LINE__)
EXTERNFN int psyco_fatal_error(char* msg, char* filename, int lineno);
#if ALL_CHECKS
# define MALLOC_CHECK_ 2 /* GCC malloc() checks */
# define extra_assert(x) psyco_assert(x)
#else
# define extra_assert(x) (void)0 /* nothing */
#endif
#if VERBOSE_LEVEL
# define debug_printf(level, args) do { \
if (VERBOSE_LEVEL >= (level)) { \
psyco_debug_printf args; \
} \
if (psyco_logger && (level) == 1) { \
psyco_flog args; \
} \
} while (0)
EXTERNFN void psyco_debug_printf(char* msg, ...);
#else
# define debug_printf(level, args) do { \
if (psyco_logger && (level) == 1) { \
psyco_flog args; \
} \
} while (0)
#endif
EXTERNVAR PyObject* psyco_logger;
EXTERNFN void psyco_flog(char* msg, ...);
#if (VERBOSE_LEVEL >= 4) || defined(PSYCO_TRACE)
# define TRACE_EXECUTION(msg) do { \
BEGIN_CODE EMIT_TRACE(msg, psyco_trace_execution); END_CODE } while (0)
# define TRACE_EXECUTION_NOERR(msg) do { \
BEGIN_CODE EMIT_TRACE(msg, psyco_trace_execution_noerr); END_CODE } while (0)
EXTERNFN void psyco_trace_execution(char* msg, void* code_position);
# if defined(PSYCO_TRACE)
# define psyco_trace_execution_noerr psyco_trace_execution
# else
EXTERNFN void psyco_trace_execution_noerr(char* msg, void* code_position);
# endif
#else
# define TRACE_EXECUTION(msg) do { } while (0) /* nothing */
# define TRACE_EXECUTION_NOERR(msg) do { } while (0) /* nothing */
#endif
#define RECLIMIT_SAFE_ENTER() PyThreadState_GET()->recursion_depth--
#define RECLIMIT_SAFE_LEAVE() PyThreadState_GET()->recursion_depth++
#if INLINE_COMMON_FUNCTIONS
# define PSY_INLINE __inline static
#else
# define PSY_INLINE static
#endif
#if HEAVY_MEM_CHECK
# include "linuxmemchk.h"
# if HEAVY_MEM_CHECK > 1
# define PSYCO_NO_LINKED_LISTS
# endif
#endif
#ifndef bool
typedef int bool;
#endif
#ifndef false
# define false 0
#endif
#ifndef true
# define true 1
#endif
#ifndef PyObject_TypeCheck
# define PyObject_TypeCheck(o,t) ((o)->ob_type == (t))
#endif
typedef unsigned char code_t;
typedef struct vinfo_s vinfo_t; /* defined in compiler.h */
typedef struct vinfo_array_s vinfo_array_t; /* defined in compiler.h */
typedef struct PsycoObject_s PsycoObject; /* defined in compiler.h */
typedef struct FrozenPsycoObject_s FrozenPsycoObject; /* def in dispatcher.h */
typedef struct CodeBufferObject_s CodeBufferObject; /* def in codemanager.h */
typedef struct global_entries_s global_entries_t; /* def in dispatcher.h */
typedef struct mergepoint_s mergepoint_t; /* defined in mergepoint.h */
typedef struct stack_frame_info_s stack_frame_info_t; /* def in pycompiler.h */
EXTERNVAR PyObject* PyExc_PsycoError;
EXTERNVAR long psyco_memory_usage; /* approximative */
EXTERNVAR PyObject* CPsycoModule;
/* moved here from vcompiler.h because needed by numerous header files.
See vcompiler.h for comments */
typedef bool (*compute_fn_t)(PsycoObject* po, vinfo_t* vi);
typedef PyObject* (*direct_compute_fn_t)(vinfo_t* vi, char* data);
typedef struct {
compute_fn_t compute_fn;
direct_compute_fn_t direct_compute_fn;
long pyobject_mask;
signed char nested_weight[2];
} source_virtual_t;
#if CODE_DUMP
EXTERNFN void psyco_dump_code_buffers(void);
#endif
#if CODE_DUMP >= 3
# define dump_code_buffers() psyco_dump_code_buffers()
#else
# define dump_code_buffers() do { } while (0) /* nothing */
#endif
/* to display code object names */
#define PyCodeObject_NAME(co) (co->co_name ? PyString_AS_STRING(co->co_name) \
: "<anonymous code object>")
/* defined in pycompiler.c */
#define GLOBAL_ENTRY_POINT psyco_pycompiler_mainloop
EXTERNFN code_t* psyco_pycompiler_mainloop(PsycoObject* po);
/* XXX no handling of out-of-memory conditions. We have to define precisely
what should occur in various cases, like when we run out of memory in the
middle of writing code, when the beginning is already executing. When
should we report the exception? */
EXTERNFN void psyco_out_of_memory(char *filename, int lineno);
#define OUT_OF_MEMORY() psyco_out_of_memory(__FILE__, __LINE__)
/* Thread-specific state */
EXTERNFN PyObject* psyco_thread_dict(void);
/* Getting data from the _psyco module */
EXTERNFN PyObject* need_cpsyco_obj(char* name);
/* defined in dispatcher.c */
EXTERNFN void PsycoObject_EmergencyCodeRoom(PsycoObject* po);
/* Convenience macros to start/end a code-emitting instruction block: */
#define BEGIN_CODE { code_t* code = po->code;
#define END_CODE po->code = code; \
if (code >= po->codelimit) \
PsycoObject_EmergencyCodeRoom(po); \
}
#endif /* _PSYCO_H */
|