Skip to content

Commit d076c73

Browse files
committed
Changes to support other object types besides strings
as the code string of code objects, as long as they support the (readonly) buffer interface. By Greg Stein.
1 parent 437ff86 commit d076c73

5 files changed

Lines changed: 61 additions & 16 deletions

File tree

Include/compile.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ typedef struct {
4444
int co_nlocals; /* #local variables */
4545
int co_stacksize; /* #entries needed for evaluation stack */
4646
int co_flags; /* CO_..., see below */
47-
PyStringObject *co_code; /* instruction opcodes */
47+
PyObject *co_code; /* instruction opcodes */
4848
PyObject *co_consts; /* list (constants used) */
4949
PyObject *co_names; /* list of strings (names used) */
5050
PyObject *co_varnames; /* tuple of strings (local variable names) */
@@ -75,6 +75,11 @@ PyCodeObject *PyCode_New Py_PROTO((
7575
PyObject *, PyObject *, int, PyObject *)); /* same as struct above */
7676
int PyCode_Addr2Line Py_PROTO((PyCodeObject *, int));
7777

78+
/* for internal use only */
79+
#define _PyCode_GETCODEPTR(co, pp) \
80+
((*(co)->co_code->ob_type->tp_as_buffer->bf_getreadbuffer) \
81+
((co)->co_code, 0, (void **)(pp)))
82+
7883
#ifdef __cplusplus
7984
}
8085
#endif

Modules/newmodule.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,9 @@ new_code(unused, args)
150150
PyObject* name;
151151
int firstlineno;
152152
PyObject* lnotab;
153-
154-
if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS",
153+
PyBufferProcs *pb;
154+
155+
if (!PyArg_ParseTuple(args, "iiiiOO!O!O!SSiS",
155156
&argcount, &nlocals, &stacksize, &flags,
156157
&code,
157158
&PyTuple_Type, &consts,
@@ -160,6 +161,18 @@ new_code(unused, args)
160161
&filename, &name,
161162
&firstlineno, &lnotab))
162163
return NULL;
164+
165+
pb = code->ob_type->tp_as_buffer;
166+
if (pb == NULL ||
167+
pb->bf_getreadbuffer == NULL ||
168+
pb->bf_getsegcount == NULL ||
169+
(*pb->bf_getsegcount)(code, NULL) != 1)
170+
{
171+
PyErr_SetString(PyExc_TypeError,
172+
"bytecode object must be a single-segment read-only buffer");
173+
return NULL;
174+
}
175+
163176
return (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
164177
code, consts, names, varnames,
165178
filename, name, firstlineno, lnotab);

Python/ceval.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ eval_code2(co, globals, locals,
366366
register PyObject **fastlocals = NULL;
367367
PyObject *retval = NULL; /* Return value */
368368
PyThreadState *tstate = PyThreadState_Get();
369+
unsigned char *first_instr;
369370
#ifdef LLTRACE
370371
int lltrace;
371372
#endif
@@ -379,11 +380,10 @@ eval_code2(co, globals, locals,
379380
#define GETCONST(i) Getconst(f, i)
380381
#define GETNAME(i) Getname(f, i)
381382
#define GETNAMEV(i) Getnamev(f, i)
382-
#define FIRST_INSTR() (GETUSTRINGVALUE(co->co_code))
383-
#define INSTR_OFFSET() (next_instr - FIRST_INSTR())
383+
#define INSTR_OFFSET() (next_instr - first_instr)
384384
#define NEXTOP() (*next_instr++)
385385
#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
386-
#define JUMPTO(x) (next_instr = FIRST_INSTR() + (x))
386+
#define JUMPTO(x) (next_instr = first_instr + (x))
387387
#define JUMPBY(x) (next_instr += (x))
388388

389389
/* Stack manipulation macros */
@@ -580,7 +580,8 @@ eval_code2(co, globals, locals,
580580
return NULL;
581581
}
582582

583-
next_instr = GETUSTRINGVALUE(co->co_code);
583+
_PyCode_GETCODEPTR(co, &first_instr);
584+
next_instr = first_instr;
584585
stack_pointer = f->f_valuestack;
585586

586587
why = WHY_NOT;
@@ -2801,7 +2802,9 @@ find_from_args(f, nexti)
28012802
PyObject *list, *name;
28022803
unsigned char *next_instr;
28032804

2804-
next_instr = GETUSTRINGVALUE(f->f_code->co_code) + nexti;
2805+
_PyCode_GETCODEPTR(f->f_code, &next_instr);
2806+
next_instr += nexti;
2807+
28052808
opcode = (*next_instr++);
28062809
if (opcode != IMPORT_FROM) {
28072810
Py_INCREF(Py_None);

Python/compile.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,11 @@ code_repr(co)
121121
{
122122
char buf[500];
123123
int lineno = -1;
124-
char *p = PyString_AS_STRING(co->co_code);
124+
unsigned char *p;
125125
char *filename = "???";
126126
char *name = "???";
127+
128+
_PyCode_GETCODEPTR(co, &p);
127129
if (*p == SET_LINENO)
128130
lineno = (p[1] & 0xff) | ((p[2] & 0xff) << 8);
129131
if (co->co_filename && PyString_Check(co->co_filename))
@@ -146,8 +148,7 @@ code_compare(co, cp)
146148
if (cmp) return cmp;
147149
cmp = co->co_flags - cp->co_flags;
148150
if (cmp) return cmp;
149-
cmp = PyObject_Compare((PyObject *)co->co_code,
150-
(PyObject *)cp->co_code);
151+
cmp = PyObject_Compare(co->co_code, cp->co_code);
151152
if (cmp) return cmp;
152153
cmp = PyObject_Compare(co->co_consts, cp->co_consts);
153154
if (cmp) return cmp;
@@ -162,7 +163,7 @@ code_hash(co)
162163
PyCodeObject *co;
163164
{
164165
long h, h1, h2, h3, h4;
165-
h1 = PyObject_Hash((PyObject *)co->co_code);
166+
h1 = PyObject_Hash(co->co_code);
166167
if (h1 == -1) return -1;
167168
h2 = PyObject_Hash(co->co_consts);
168169
if (h2 == -1) return -1;
@@ -216,9 +217,10 @@ PyCode_New(argcount, nlocals, stacksize, flags,
216217
{
217218
PyCodeObject *co;
218219
int i;
220+
PyBufferProcs *pb;
219221
/* Check argument types */
220222
if (argcount < 0 || nlocals < 0 ||
221-
code == NULL || !PyString_Check(code) ||
223+
code == NULL ||
222224
consts == NULL || !PyTuple_Check(consts) ||
223225
names == NULL || !PyTuple_Check(names) ||
224226
varnames == NULL || !PyTuple_Check(varnames) ||
@@ -228,6 +230,15 @@ PyCode_New(argcount, nlocals, stacksize, flags,
228230
PyErr_BadInternalCall();
229231
return NULL;
230232
}
233+
pb = code->ob_type->tp_as_buffer;
234+
if (pb == NULL ||
235+
pb->bf_getreadbuffer == NULL ||
236+
pb->bf_getsegcount == NULL ||
237+
(*pb->bf_getsegcount)(code, NULL) != 1)
238+
{
239+
PyErr_BadInternalCall();
240+
return NULL;
241+
}
231242
/* Make sure names and varnames are all strings, & intern them */
232243
for (i = PyTuple_Size(names); --i >= 0; ) {
233244
PyObject *v = PyTuple_GetItem(names, i);
@@ -264,7 +275,7 @@ PyCode_New(argcount, nlocals, stacksize, flags,
264275
co->co_stacksize = stacksize;
265276
co->co_flags = flags;
266277
Py_INCREF(code);
267-
co->co_code = (PyStringObject *)code;
278+
co->co_code = code;
268279
Py_INCREF(consts);
269280
co->co_consts = consts;
270281
Py_INCREF(names);

Python/marshal.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ w_object(v, p)
142142
WFILE *p;
143143
{
144144
int i, n;
145+
PyBufferProcs *pb;
145146

146147
if (v == NULL) {
147148
w_byte(TYPE_NULL, p);
@@ -251,7 +252,7 @@ w_object(v, p)
251252
w_short(co->co_nlocals, p);
252253
w_short(co->co_stacksize, p);
253254
w_short(co->co_flags, p);
254-
w_object((PyObject *)co->co_code, p);
255+
w_object(co->co_code, p);
255256
w_object(co->co_consts, p);
256257
w_object(co->co_names, p);
257258
w_object(co->co_varnames, p);
@@ -260,6 +261,18 @@ w_object(v, p)
260261
w_short(co->co_firstlineno, p);
261262
w_object(co->co_lnotab, p);
262263
}
264+
else if ((pb = v->ob_type->tp_as_buffer) != NULL &&
265+
pb->bf_getsegcount != NULL &&
266+
pb->bf_getreadbuffer != NULL &&
267+
(*pb->bf_getsegcount)(v, NULL) == 1)
268+
{
269+
/* Write unknown buffer-style objects as a string */
270+
char *s;
271+
w_byte(TYPE_STRING, p);
272+
n = (*pb->bf_getreadbuffer)(v, 0, (void **)&s);
273+
w_long((long)n, p);
274+
w_string(s, n, p);
275+
}
263276
else {
264277
w_byte(TYPE_UNKNOWN, p);
265278
p->error = 1;
@@ -730,7 +743,7 @@ marshal_loads(self, args)
730743
PyObject *v;
731744
char *s;
732745
int n;
733-
if (!PyArg_Parse(args, "s#", &s, &n))
746+
if (!PyArg_Parse(args, "r#", &s, &n))
734747
return NULL;
735748
rf.fp = NULL;
736749
rf.str = args;

0 commit comments

Comments
 (0)