Author: Carl Friedrich Bolz <[email protected]>
Branch: globals-quasiimmut
Changeset: r81747:a2af053cbe15
Date: 2016-01-13 21:31 +0100
http://bitbucket.org/pypy/pypy/changeset/a2af053cbe15/
Log: store the first w_globals that a code object is run in on the code
object. if a frame runs within that code object (which is almost
always), it does not need to store it.
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -9,8 +9,8 @@
class Code(W_Root):
"""A code is a compiled version of some source code.
Abstract base class."""
- _immutable_ = True
hidden_applevel = False
+ _immutable_fields_ = ['co_name', 'fast_natural_arity', 'hidden_applevel']
# n >= 0 : arity
# FLATPYCALL = 0x100
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -56,11 +56,13 @@
class PyCode(eval.Code):
"CPython-style code objects."
- _immutable_ = True
- _immutable_fields_ = ["co_consts_w[*]", "co_names_w[*]", "co_varnames[*]",
- "co_freevars[*]", "co_cellvars[*]",
- "_args_as_cellvars[*]"]
-
+ _immutable_fields_ = ["_signature", "co_argcount", "co_cellvars[*]",
+ "co_code", "co_consts_w[*]", "co_filename",
+ "co_firstlineno", "co_flags", "co_freevars[*]",
+ "co_lnotab", "co_names_w[*]", "co_nlocals",
+ "co_stacksize", "co_varnames[*]",
+ "_args_as_cellvars[*]", "w_globals?"]
+
def __init__(self, space, argcount, nlocals, stacksize, flags,
code, consts, names, varnames, filename,
name, firstlineno, lnotab, freevars, cellvars,
@@ -84,6 +86,10 @@
self.co_name = name
self.co_firstlineno = firstlineno
self.co_lnotab = lnotab
+ # store the first globals object that the code object is run in in
+ # here. if a frame is run in that globals object, it does not need to
+ # store it at all
+ self.w_globals = None
self.hidden_applevel = hidden_applevel
self.magic = magic
self._signature = cpython_code_signature(self)
@@ -91,6 +97,14 @@
self._init_ready()
self.new_code_hook()
+ def frame_stores_global(self, w_globals):
+ if self.w_globals is None:
+ self.w_globals = w_globals
+ return False
+ if self.w_globals is w_globals:
+ return False
+ return True
+
def new_code_hook(self):
code_hook = self.space.fromcache(CodeHookCache)._code_hook
if code_hook is not None:
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -33,9 +33,11 @@
f_lineno = 0 # current lineno for tracing
is_being_profiled = False
w_locals = None
+ w_globals = None
def __init__(self, pycode):
self.f_lineno = pycode.co_firstlineno
+ self.w_globals = pycode.w_globals
class PyFrame(W_Root):
"""Represents a frame for a regular Python function
@@ -67,7 +69,6 @@
escaped = False # see mark_as_escaped()
debugdata = None
- w_globals = None
pycode = None # code object executed by that frame
locals_cells_stack_w = None # the list of all locals, cells and the
valuestack
valuestackdepth = 0 # number of items on valuestack
@@ -90,8 +91,9 @@
self = hint(self, access_directly=True, fresh_virtualizable=True)
assert isinstance(code, pycode.PyCode)
self.space = space
- self.w_globals = w_globals
self.pycode = code
+ if code.frame_stores_global(w_globals):
+ self.getorcreatedebug().w_globals = w_globals
ncellvars = len(code.co_cellvars)
nfreevars = len(code.co_freevars)
size = code.co_nlocals + ncellvars + nfreevars + code.co_stacksize
@@ -116,6 +118,15 @@
self.debugdata = FrameDebugData(self.pycode)
return self.debugdata
+ def get_w_globals(self):
+ debugdata = self.getdebug()
+ if debugdata is not None:
+ return debugdata.w_globals
+ return jit.promote(self.pycode).w_globals
+
+ def set_w_globals(self, w_globals):
+ self.getorcreatedebug().w_globals = w_globals
+
def get_w_f_trace(self):
d = self.getdebug()
if d is None:
@@ -201,8 +212,9 @@
if flags & pycode.CO_NEWLOCALS:
self.getorcreatedebug().w_locals =
self.space.newdict(module=True)
else:
- assert self.w_globals is not None
- self.getorcreatedebug().w_locals = self.w_globals
+ w_globals = self.get_w_globals()
+ assert w_globals is not None
+ self.getorcreatedebug().w_locals = w_globals
ncellvars = len(code.co_cellvars)
nfreevars = len(code.co_freevars)
@@ -449,7 +461,7 @@
w_blockstack,
w_exc_value, # last_exception
w_tb, #
- self.w_globals,
+ self.get_w_globals(),
w(self.last_instr),
w(self.frame_finished_execution),
w(f_lineno),
@@ -658,6 +670,14 @@
def fget_getdictscope(self, space):
return self.getdictscope()
+ def fget_w_globals(self, space):
+ # bit silly, but GetSetProperty passes a space
+ return self.get_w_globals()
+
+ def fset_w_globals(self, space, w_obj):
+ # bit silly, but GetSetProperty passes a space
+ return self.set_w_globals(w_obj)
+
### line numbers ###
def fget_f_lineno(self, space):
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -837,7 +837,7 @@
w_bases = self.popvalue()
w_name = self.popvalue()
w_metaclass = find_metaclass(self.space, w_bases,
- w_methodsdict, self.w_globals,
+ w_methodsdict, self.get_w_globals(),
self.space.wrap(self.get_builtin()))
w_newclass = self.space.call_function(w_metaclass, w_name,
w_bases, w_methodsdict)
@@ -881,14 +881,14 @@
def STORE_GLOBAL(self, nameindex, next_instr):
varname = self.getname_u(nameindex)
w_newvalue = self.popvalue()
- self.space.setitem_str(self.w_globals, varname, w_newvalue)
+ self.space.setitem_str(self.get_w_globals(), varname, w_newvalue)
def DELETE_GLOBAL(self, nameindex, next_instr):
w_varname = self.getname_w(nameindex)
- self.space.delitem(self.w_globals, w_varname)
+ self.space.delitem(self.get_w_globals(), w_varname)
def LOAD_NAME(self, nameindex, next_instr):
- if self.getorcreatedebug().w_locals is not self.w_globals:
+ if self.getorcreatedebug().w_locals is not self.get_w_globals():
varname = self.getname_u(nameindex)
w_value = self.space.finditem_str(self.getorcreatedebug().w_locals,
varname)
@@ -898,7 +898,7 @@
self.LOAD_GLOBAL(nameindex, next_instr) # fall-back
def _load_global(self, varname):
- w_value = self.space.finditem_str(self.w_globals, varname)
+ w_value = self.space.finditem_str(self.get_w_globals(), varname)
if w_value is None:
# not in the globals, now look in the built-ins
w_value = self.get_builtin().getdictvalue(self.space, varname)
@@ -1029,7 +1029,7 @@
if w_locals is None: # CPython does this
w_locals = space.w_None
w_modulename = space.wrap(modulename)
- w_globals = self.w_globals
+ w_globals = self.get_w_globals()
if w_flag is None:
w_obj = space.call_function(w_import, w_modulename, w_globals,
w_locals, w_fromlist)
@@ -1237,7 +1237,7 @@
w_codeobj = self.popvalue()
codeobj = self.space.interp_w(PyCode, w_codeobj)
defaultarguments = self.popvalues(numdefaults)
- fn = function.Function(self.space, codeobj, self.w_globals,
+ fn = function.Function(self.space, codeobj, self.get_w_globals(),
defaultarguments)
self.pushvalue(self.space.wrap(fn))
@@ -1249,7 +1249,7 @@
freevars = [self.space.interp_w(Cell, cell)
for cell in self.space.fixedview(w_freevarstuple)]
defaultarguments = self.popvalues(numdefaults)
- fn = function.Function(self.space, codeobj, self.w_globals,
+ fn = function.Function(self.space, codeobj, self.get_w_globals(),
defaultarguments, freevars)
self.pushvalue(self.space.wrap(fn))
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -772,7 +772,7 @@
f_restricted = GetSetProperty(PyFrame.fget_f_restricted),
f_code = GetSetProperty(PyFrame.fget_code),
f_locals = GetSetProperty(PyFrame.fget_getdictscope),
- f_globals = interp_attrproperty_w('w_globals', cls=PyFrame),
+ f_globals = GetSetProperty(PyFrame.fget_w_globals, PyFrame.fset_w_globals),
)
assert not PyFrame.typedef.acceptable_as_base_class # no __new__
diff --git a/pypy/module/__builtin__/compiling.py
b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -93,7 +93,7 @@
if space.is_none(w_locals):
w_locals = w_globals
else:
- w_globals = caller.w_globals
+ w_globals = caller.get_w_globals()
if space.is_none(w_locals):
w_locals = caller.getdictscope()
elif space.is_none(w_locals):
diff --git a/pypy/module/__builtin__/interp_inspect.py
b/pypy/module/__builtin__/interp_inspect.py
--- a/pypy/module/__builtin__/interp_inspect.py
+++ b/pypy/module/__builtin__/interp_inspect.py
@@ -2,7 +2,7 @@
def globals(space):
"Return the dictionary containing the current scope's global variables."
ec = space.getexecutioncontext()
- return ec.gettopframe_nohidden().w_globals
+ return ec.gettopframe_nohidden().get_w_globals()
def locals(space):
"""Return a dictionary containing the current scope's local variables.
diff --git a/pypy/module/_warnings/interp_warnings.py
b/pypy/module/_warnings/interp_warnings.py
--- a/pypy/module/_warnings/interp_warnings.py
+++ b/pypy/module/_warnings/interp_warnings.py
@@ -75,7 +75,7 @@
frame = ec.getnextframe_nohidden(frame)
stacklevel -= 1
if frame:
- w_globals = frame.w_globals
+ w_globals = frame.get_w_globals()
lineno = frame.get_last_lineno()
else:
w_globals = space.sys.w_dict
diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py
--- a/pypy/module/cpyext/eval.py
+++ b/pypy/module/cpyext/eval.py
@@ -30,7 +30,7 @@
currently executing."""
caller = space.getexecutioncontext().gettopframe_nohidden()
if caller is not None:
- w_globals = caller.w_globals
+ w_globals = caller.get_w_globals()
w_builtins = space.getitem(w_globals, space.wrap('__builtins__'))
if not space.isinstance_w(w_builtins, space.w_dict):
w_builtins = w_builtins.getdict(space)
@@ -54,7 +54,7 @@
caller = space.getexecutioncontext().gettopframe_nohidden()
if caller is None:
return None
- return borrow_from(None, caller.w_globals)
+ return borrow_from(None, caller.get_w_globals())
@cpython_api([PyCodeObject, PyObject, PyObject], PyObject)
def PyEval_EvalCode(space, w_code, w_globals, w_locals):
diff --git a/pypy/module/cpyext/frameobject.py
b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -34,7 +34,7 @@
frame = space.interp_w(PyFrame, w_obj)
py_frame = rffi.cast(PyFrameObject, py_obj)
py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, frame.pycode))
- py_frame.c_f_globals = make_ref(space, frame.w_globals)
+ py_frame.c_f_globals = make_ref(space, frame.get_w_globals())
rffi.setintfield(py_frame, 'c_f_lineno', frame.getorcreatedebug().f_lineno)
@cpython_api([PyObject], lltype.Void, external=False)
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -20,7 +20,7 @@
caller = space.getexecutioncontext().gettopframe_nohidden()
# Get the builtins from current globals
if caller is not None:
- w_globals = caller.w_globals
+ w_globals = caller.get_w_globals()
w_builtin = space.getitem(w_globals, space.wrap('__builtins__'))
else:
# No globals -- use standard builtins, and fake globals
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -1139,7 +1139,7 @@
space = w_self.space
caller = space.getexecutioncontext().gettopframe_nohidden()
if caller is not None:
- w_globals = caller.w_globals
+ w_globals = caller.get_w_globals()
w_name = space.finditem(w_globals, space.wrap('__name__'))
if w_name is not None:
w_self.dict_w['__module__'] = w_name
diff --git a/pypy/tool/pytest/appsupport.py b/pypy/tool/pytest/appsupport.py
--- a/pypy/tool/pytest/appsupport.py
+++ b/pypy/tool/pytest/appsupport.py
@@ -63,7 +63,7 @@
for key, w_value in vars.items():
space.setitem(self.w_locals, space.wrap(key), w_value)
if isinstance(code, str):
- return space.eval(code, self.w_globals, self.w_locals)
+ return space.eval(code, self.get_w_globals(), self.w_locals)
pyc = pycode.PyCode._from_code(space, code)
return pyc.exec_host_bytecode(self.w_globals, self.w_locals)
exec_ = eval
@@ -248,7 +248,7 @@
#if filename.endswith("pyc"):
# filename = filename[:-1]
try:
- space.exec_(str(source), frame.w_globals, w_locals,
+ space.exec_(str(source), frame.get_w_globals(), w_locals,
filename=filename)
except OperationError, e:
if e.match(space, w_ExpectedException):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit