Charles G. Waldman <cgw@fnal.gov>:
Add the EXTENDED_ARG opcode to the virtual machine, allowing 32-bit arguments to opcodes instead of being forced to stick to the 16-bit limit. This is especially useful for machine-generated code, which can be too long for the SET_LINENO parameter to fit into 16 bits. This closes the implementation portion of SourceForge patch #100893.
This commit is contained in:
parent
e266e42c9c
commit
ef8ace3a6f
|
@ -19,8 +19,8 @@ extern "C" {
|
||||||
typedef struct _node {
|
typedef struct _node {
|
||||||
short n_type;
|
short n_type;
|
||||||
char *n_str;
|
char *n_str;
|
||||||
short n_lineno;
|
int n_lineno;
|
||||||
short n_nchildren;
|
int n_nchildren;
|
||||||
struct _node *n_child;
|
struct _node *n_child;
|
||||||
} node;
|
} node;
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,9 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
#define CALL_FUNCTION_KW 141 /* #args + (#kwargs<<8) */
|
#define CALL_FUNCTION_KW 141 /* #args + (#kwargs<<8) */
|
||||||
#define CALL_FUNCTION_VAR_KW 142 /* #args + (#kwargs<<8) */
|
#define CALL_FUNCTION_VAR_KW 142 /* #args + (#kwargs<<8) */
|
||||||
|
|
||||||
|
/* Support for opargs more than 16 bits long */
|
||||||
|
#define EXTENDED_ARG 143
|
||||||
|
|
||||||
/* Comparison operator codes (argument to COMPARE_OP) */
|
/* Comparison operator codes (argument to COMPARE_OP) */
|
||||||
enum cmp_op {LT, LE, EQ, NE, GT, GE, IN, NOT_IN, IS, IS_NOT, EXC_MATCH, BAD};
|
enum cmp_op {LT, LE, EQ, NE, GT, GE, IN, NOT_IN, IS, IS_NOT, EXC_MATCH, BAD};
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ def disassemble(co, lasti=-1):
|
||||||
labels = findlabels(code)
|
labels = findlabels(code)
|
||||||
n = len(code)
|
n = len(code)
|
||||||
i = 0
|
i = 0
|
||||||
|
extended_arg = 0
|
||||||
while i < n:
|
while i < n:
|
||||||
c = code[i]
|
c = code[i]
|
||||||
op = ord(c)
|
op = ord(c)
|
||||||
|
@ -68,8 +69,11 @@ def disassemble(co, lasti=-1):
|
||||||
print string.ljust(opname[op], 20),
|
print string.ljust(opname[op], 20),
|
||||||
i = i+1
|
i = i+1
|
||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
oparg = ord(code[i]) + ord(code[i+1])*256
|
oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
|
||||||
|
extended_arg = 0
|
||||||
i = i+2
|
i = i+2
|
||||||
|
if op == EXTENDED_ARG:
|
||||||
|
extended_arg = oparg*65536L
|
||||||
print string.rjust(`oparg`, 5),
|
print string.rjust(`oparg`, 5),
|
||||||
if op in hasconst:
|
if op in hasconst:
|
||||||
print '(' + `co.co_consts[oparg]` + ')',
|
print '(' + `co.co_consts[oparg]` + ')',
|
||||||
|
@ -258,6 +262,8 @@ def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8)
|
||||||
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
|
def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
|
||||||
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
||||||
|
|
||||||
|
def_op('EXTENDED_ARG', 143)
|
||||||
|
EXTENDED_ARG = 143
|
||||||
|
|
||||||
def _test():
|
def _test():
|
||||||
"""Simple test program to disassemble a file."""
|
"""Simple test program to disassemble a file."""
|
||||||
|
|
|
@ -8,7 +8,12 @@ See the file "Misc/COPYRIGHT" for information on usage and
|
||||||
redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_LIMITS_H
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
|
#ifndef INT_MAX
|
||||||
|
#define INT_MAX 2147483647
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Parse tree node implementation */
|
/* Parse tree node implementation */
|
||||||
|
|
||||||
|
@ -39,7 +44,7 @@ PyNode_AddChild(register node *n1, int type, char *str, int lineno)
|
||||||
register int nch = n1->n_nchildren;
|
register int nch = n1->n_nchildren;
|
||||||
register int nch1 = nch+1;
|
register int nch1 = nch+1;
|
||||||
register node *n;
|
register node *n;
|
||||||
if (nch == SHRT_MAX || nch < 0)
|
if (nch == INT_MAX || nch < 0)
|
||||||
return E_OVERFLOW;
|
return E_OVERFLOW;
|
||||||
if (XXXROUNDUP(nch) < nch1) {
|
if (XXXROUNDUP(nch) < nch1) {
|
||||||
n = n1->n_child;
|
n = n1->n_child;
|
||||||
|
|
|
@ -613,6 +613,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
opcode = NEXTOP();
|
opcode = NEXTOP();
|
||||||
if (HAS_ARG(opcode))
|
if (HAS_ARG(opcode))
|
||||||
oparg = NEXTARG();
|
oparg = NEXTARG();
|
||||||
|
dispatch_opcode:
|
||||||
#ifdef DYNAMIC_EXECUTION_PROFILE
|
#ifdef DYNAMIC_EXECUTION_PROFILE
|
||||||
#ifdef DXPAIRS
|
#ifdef DXPAIRS
|
||||||
dxpairs[lastopcode][opcode]++;
|
dxpairs[lastopcode][opcode]++;
|
||||||
|
@ -1750,6 +1751,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
||||||
if (x != NULL) continue;
|
if (x != NULL) continue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EXTENDED_ARG:
|
||||||
|
opcode = NEXTOP();
|
||||||
|
oparg = oparg<<16 | NEXTARG();
|
||||||
|
goto dispatch_opcode;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|
|
@ -36,6 +36,9 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
#ifdef HAVE_LIMITS_H
|
#ifdef HAVE_LIMITS_H
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef INT_MAX
|
||||||
|
#define INT_MAX 2147483647
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Three symbols from graminit.h are also defined in Python.h, with
|
/* Three symbols from graminit.h are also defined in Python.h, with
|
||||||
Py_ prefixes to their names. Python.h can't include graminit.h
|
Py_ prefixes to their names. Python.h can't include graminit.h
|
||||||
|
@ -572,11 +575,17 @@ com_set_lineno(struct compiling *c, int lineno)
|
||||||
static void
|
static void
|
||||||
com_addoparg(struct compiling *c, int op, int arg)
|
com_addoparg(struct compiling *c, int op, int arg)
|
||||||
{
|
{
|
||||||
|
int extended_arg = arg >> 16;
|
||||||
if (op == SET_LINENO) {
|
if (op == SET_LINENO) {
|
||||||
com_set_lineno(c, arg);
|
com_set_lineno(c, arg);
|
||||||
if (Py_OptimizeFlag)
|
if (Py_OptimizeFlag)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (extended_arg){
|
||||||
|
com_addbyte(c, EXTENDED_ARG);
|
||||||
|
com_addint(c, extended_arg);
|
||||||
|
arg &= 0xffff;
|
||||||
|
}
|
||||||
com_addbyte(c, op);
|
com_addbyte(c, op);
|
||||||
com_addint(c, arg);
|
com_addint(c, arg);
|
||||||
}
|
}
|
||||||
|
@ -606,7 +615,14 @@ com_backpatch(struct compiling *c, int anchor)
|
||||||
prev = code[anchor] + (code[anchor+1] << 8);
|
prev = code[anchor] + (code[anchor+1] << 8);
|
||||||
dist = target - (anchor+2);
|
dist = target - (anchor+2);
|
||||||
code[anchor] = dist & 0xff;
|
code[anchor] = dist & 0xff;
|
||||||
code[anchor+1] = dist >> 8;
|
dist >>= 8;
|
||||||
|
code[anchor+1] = dist;
|
||||||
|
dist >>= 8;
|
||||||
|
if (dist) {
|
||||||
|
com_error(c, PyExc_SystemError,
|
||||||
|
"com_backpatch: offset too large");
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!prev)
|
if (!prev)
|
||||||
break;
|
break;
|
||||||
anchor -= prev;
|
anchor -= prev;
|
||||||
|
@ -3364,6 +3380,7 @@ optimize(struct compiling *c)
|
||||||
break;
|
break;
|
||||||
if (HAS_ARG(opcode))
|
if (HAS_ARG(opcode))
|
||||||
oparg = NEXTARG();
|
oparg = NEXTARG();
|
||||||
|
dispatch_opcode1:
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case STORE_NAME:
|
case STORE_NAME:
|
||||||
case DELETE_NAME:
|
case DELETE_NAME:
|
||||||
|
@ -3374,6 +3391,11 @@ optimize(struct compiling *c)
|
||||||
case EXEC_STMT:
|
case EXEC_STMT:
|
||||||
c->c_flags &= ~CO_OPTIMIZED;
|
c->c_flags &= ~CO_OPTIMIZED;
|
||||||
break;
|
break;
|
||||||
|
case EXTENDED_ARG:
|
||||||
|
opcode = NEXTOP();
|
||||||
|
oparg = oparg<<16 | NEXTARG();
|
||||||
|
goto dispatch_opcode1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3389,6 +3411,7 @@ optimize(struct compiling *c)
|
||||||
break;
|
break;
|
||||||
if (HAS_ARG(opcode))
|
if (HAS_ARG(opcode))
|
||||||
oparg = NEXTARG();
|
oparg = NEXTARG();
|
||||||
|
dispatch_opcode2:
|
||||||
if (opcode == LOAD_NAME ||
|
if (opcode == LOAD_NAME ||
|
||||||
opcode == STORE_NAME ||
|
opcode == STORE_NAME ||
|
||||||
opcode == DELETE_NAME) {
|
opcode == DELETE_NAME) {
|
||||||
|
@ -3403,13 +3426,20 @@ optimize(struct compiling *c)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
i = PyInt_AsLong(v);
|
i = PyInt_AsLong(v);
|
||||||
|
if (i >> 16) /* too big for 2 bytes */
|
||||||
|
continue;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case LOAD_NAME: cur_instr[0] = LOAD_FAST; break;
|
case LOAD_NAME: cur_instr[0] = LOAD_FAST; break;
|
||||||
case STORE_NAME: cur_instr[0] = STORE_FAST; break;
|
case STORE_NAME: cur_instr[0] = STORE_FAST; break;
|
||||||
case DELETE_NAME: cur_instr[0] = DELETE_FAST; break;
|
case DELETE_NAME: cur_instr[0] = DELETE_FAST; break;
|
||||||
}
|
}
|
||||||
cur_instr[1] = i & 0xff;
|
cur_instr[1] = i & 0xff;
|
||||||
cur_instr[2] = (i>>8) & 0xff;
|
cur_instr[2] = i >> 8;
|
||||||
|
}
|
||||||
|
if (opcode == EXTENDED_ARG) {
|
||||||
|
opcode = NEXTOP();
|
||||||
|
oparg = oparg<<16 | NEXTARG();
|
||||||
|
goto dispatch_opcode2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue