rather than passing locals to the class body, just execute the class body in the proper environment

This commit is contained in:
Benjamin Peterson 2013-05-16 14:37:25 -05:00
parent e914123d1f
commit e8e14591eb
10 changed files with 3143 additions and 3175 deletions

View file

@ -596,12 +596,6 @@ the stack so that it is available for further iterations of the loop.
.. XXX explain the WHY stuff! .. XXX explain the WHY stuff!
.. opcode:: STORE_LOCALS
Pops TOS from the stack and stores it as the current frame's ``f_locals``.
This is used in class construction.
All of the following opcodes expect arguments. An argument is two bytes, with All of the following opcodes expect arguments. An argument is two bytes, with
the more significant byte last. the more significant byte last.

View file

@ -49,7 +49,6 @@ extern "C" {
#define BINARY_OR 66 #define BINARY_OR 66
#define INPLACE_POWER 67 #define INPLACE_POWER 67
#define GET_ITER 68 #define GET_ITER 68
#define STORE_LOCALS 69
#define PRINT_EXPR 70 #define PRINT_EXPR 70
#define LOAD_BUILD_CLASS 71 #define LOAD_BUILD_CLASS 71
#define YIELD_FROM 72 #define YIELD_FROM 72

View file

@ -391,12 +391,13 @@ def _call_with_frames_removed(f, *args, **kwds):
# Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override # Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override
# free vars) # free vars)
# Python 3.4a1 3270 (various tweaks to the __class_ closure) # Python 3.4a1 3270 (various tweaks to the __class_ closure)
# Python 3.4a1 3280 (remove implicit class argument)
# #
# MAGIC must change whenever the bytecode emitted by the compiler may no # MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually # longer be understood by older implementations of the eval loop (usually
# due to the addition of new opcodes). # due to the addition of new opcodes).
_MAGIC_BYTES = (3270).to_bytes(2, 'little') + b'\r\n' _MAGIC_BYTES = (3280).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(_MAGIC_BYTES, 'little') _RAW_MAGIC_NUMBER = int.from_bytes(_MAGIC_BYTES, 'little')
_PYCACHE = '__pycache__' _PYCACHE = '__pycache__'

View file

@ -84,7 +84,6 @@ def_op('BINARY_XOR', 65)
def_op('BINARY_OR', 66) def_op('BINARY_OR', 66)
def_op('INPLACE_POWER', 67) def_op('INPLACE_POWER', 67)
def_op('GET_ITER', 68) def_op('GET_ITER', 68)
def_op('STORE_LOCALS', 69)
def_op('PRINT_EXPR', 70) def_op('PRINT_EXPR', 70)
def_op('LOAD_BUILD_CLASS', 71) def_op('LOAD_BUILD_CLASS', 71)

View file

@ -57,6 +57,11 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ func = PyTuple_GET_ITEM(args, 0); /* Better be callable */
if (!PyFunction_Check(func)) {
PyErr_SetString(PyExc_TypeError,
"__build__class__: func must be a function");
return NULL;
}
name = PyTuple_GET_ITEM(args, 1); name = PyTuple_GET_ITEM(args, 1);
if (!PyUnicode_Check(name)) { if (!PyUnicode_Check(name)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
@ -155,7 +160,9 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds)
Py_DECREF(bases); Py_DECREF(bases);
return NULL; return NULL;
} }
cell = PyObject_CallFunctionObjArgs(func, ns, NULL); cell = PyEval_EvalCodeEx(PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), ns,
NULL, 0, NULL, 0, NULL, 0, NULL,
PyFunction_GET_CLOSURE(func));
if (cell != NULL) { if (cell != NULL) {
PyObject *margs; PyObject *margs;
margs = PyTuple_Pack(3, name, bases, ns); margs = PyTuple_Pack(3, name, bases, ns);

View file

@ -1873,14 +1873,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
goto error; goto error;
} }
TARGET(STORE_LOCALS) {
PyObject *locals = POP();
PyObject *old = f->f_locals;
Py_XDECREF(old);
f->f_locals = locals;
DISPATCH();
}
TARGET(RETURN_VALUE) { TARGET(RETURN_VALUE) {
retval = POP(); retval = POP();
why = WHY_RETURN; why = WHY_RETURN;

View file

@ -893,8 +893,6 @@ opcode_stack_effect(int opcode, int oparg)
return 7; return 7;
case WITH_CLEANUP: case WITH_CLEANUP:
return -1; /* XXX Sometimes more */ return -1; /* XXX Sometimes more */
case STORE_LOCALS:
return -1;
case RETURN_VALUE: case RETURN_VALUE:
return -1; return -1;
case IMPORT_STAR: case IMPORT_STAR:
@ -1696,12 +1694,6 @@ compiler_class(struct compiler *c, stmt_ty s)
Py_INCREF(s->v.ClassDef.name); Py_INCREF(s->v.ClassDef.name);
Py_XDECREF(c->u->u_private); Py_XDECREF(c->u->u_private);
c->u->u_private = s->v.ClassDef.name; c->u->u_private = s->v.ClassDef.name;
/* force it to have one mandatory argument */
c->u->u_argcount = 1;
/* load the first argument (__locals__) ... */
ADDOP_I(c, LOAD_FAST, 0);
/* ... and store it into f_locals */
ADDOP_IN_SCOPE(c, STORE_LOCALS);
/* load (global) __name__ ... */ /* load (global) __name__ ... */
str = PyUnicode_InternFromString("__name__"); str = PyUnicode_InternFromString("__name__");
if (!str || !compiler_nameop(c, str, Load)) { if (!str || !compiler_nameop(c, str, Load)) {
@ -4110,9 +4102,8 @@ compute_code_flags(struct compiler *c)
{ {
PySTEntryObject *ste = c->u->u_ste; PySTEntryObject *ste = c->u->u_ste;
int flags = 0, n; int flags = 0, n;
if (ste->ste_type != ModuleBlock)
flags |= CO_NEWLOCALS;
if (ste->ste_type == FunctionBlock) { if (ste->ste_type == FunctionBlock) {
flags |= CO_NEWLOCALS;
if (!ste->ste_unoptimized) if (!ste->ste_unoptimized)
flags |= CO_OPTIMIZED; flags |= CO_OPTIMIZED;
if (ste->ste_nested) if (ste->ste_nested)

File diff suppressed because it is too large Load diff

View file

@ -68,7 +68,7 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_OR, &&TARGET_BINARY_OR,
&&TARGET_INPLACE_POWER, &&TARGET_INPLACE_POWER,
&&TARGET_GET_ITER, &&TARGET_GET_ITER,
&&TARGET_STORE_LOCALS, &&_unknown_opcode,
&&TARGET_PRINT_EXPR, &&TARGET_PRINT_EXPR,
&&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_BUILD_CLASS,
&&TARGET_YIELD_FROM, &&TARGET_YIELD_FROM,

View file

@ -192,7 +192,7 @@ static int symtable_visit_withitem(struct symtable *st, withitem_ty item);
static identifier top = NULL, lambda = NULL, genexpr = NULL, static identifier top = NULL, lambda = NULL, genexpr = NULL,
listcomp = NULL, setcomp = NULL, dictcomp = NULL, listcomp = NULL, setcomp = NULL, dictcomp = NULL,
__class__ = NULL, __locals__ = NULL; __class__ = NULL;
#define GET_IDENTIFIER(VAR) \ #define GET_IDENTIFIER(VAR) \
((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR)))
@ -1185,11 +1185,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
(void *)s, s->lineno, s->col_offset)) (void *)s, s->lineno, s->col_offset))
VISIT_QUIT(st, 0); VISIT_QUIT(st, 0);
if (!GET_IDENTIFIER(__locals__) ||
!symtable_add_def(st, __locals__, DEF_PARAM)) {
symtable_exit_block(st, s);
VISIT_QUIT(st, 0);
}
tmp = st->st_private; tmp = st->st_private;
st->st_private = s->v.ClassDef.name; st->st_private = s->v.ClassDef.name;
VISIT_SEQ(st, stmt, s->v.ClassDef.body); VISIT_SEQ(st, stmt, s->v.ClassDef.body);