[pypy-commit] pypy default: (fijal, cfbolz) remove some attributes from frames and put them on the
fijal
noreply at buildbot.pypy.org
Mon May 4 11:45:45 CEST 2015
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r77033:6f0ee31d6c9a
Date: 2015-05-04 11:45 +0200
http://bitbucket.org/pypy/pypy/changeset/6f0ee31d6c9a/
Log: (fijal, cfbolz) remove some attributes from frames and put them on
the debug object which is only allocated occasionally, when tracing
is involved
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1091,7 +1091,7 @@
def call_valuestack(self, w_func, nargs, frame):
from pypy.interpreter.function import Function, Method, is_builtin_code
- if frame.is_being_profiled and is_builtin_code(w_func):
+ if frame.get_is_being_profiled() and is_builtin_code(w_func):
# XXX: this code is copied&pasted :-( from the slow path below
# call_valuestack().
args = frame.make_arguments(nargs)
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -96,7 +96,7 @@
def _c_call_return_trace(self, frame, w_func, args, event):
if self.profilefunc is None:
- frame.is_being_profiled = False
+ frame.getorcreatedebug().is_being_profiled = False
else:
# undo the effect of the CALL_METHOD bytecode, which would be
# that even on a built-in method call like '[].append()',
@@ -114,7 +114,7 @@
def c_exception_trace(self, frame, w_exc):
"Profile function called upon OperationError."
if self.profilefunc is None:
- frame.is_being_profiled = False
+ frame.getorcreatedebug().is_being_profiled = False
else:
self._trace(frame, 'c_exception', w_exc)
@@ -123,7 +123,7 @@
if self.gettrace() is not None or self.profilefunc is not None:
self._trace(frame, 'call', self.space.w_None)
if self.profilefunc:
- frame.is_being_profiled = True
+ frame.getorcreatedebug().is_being_profiled = True
def return_trace(self, frame, w_retval):
"Trace the return from a function"
@@ -145,7 +145,7 @@
Like bytecode_trace() but doesn't invoke any other events besides the
trace function.
"""
- if (frame.w_f_trace is None or self.is_tracing or
+ if (frame.get_w_f_trace() is None or self.is_tracing or
self.gettrace() is None):
return
self.run_trace_func(frame)
@@ -154,8 +154,9 @@
@jit.unroll_safe
def run_trace_func(self, frame):
code = frame.pycode
- if frame.instr_lb <= frame.last_instr < frame.instr_ub:
- if frame.last_instr < frame.instr_prev_plus_one:
+ d = frame.getorcreatedebug()
+ if d.instr_lb <= frame.last_instr < d.instr_ub:
+ if frame.last_instr < d.instr_prev_plus_one:
# We jumped backwards in the same line.
self._trace(frame, 'line', self.space.w_None)
else:
@@ -170,7 +171,7 @@
break
addr += c
if c:
- frame.instr_lb = addr
+ d.instr_lb = addr
line += ord(lineno[p + 1])
p += 2
@@ -185,15 +186,15 @@
if ord(lineno[p + 1]):
break
p += 2
- frame.instr_ub = addr
+ d.instr_ub = addr
else:
- frame.instr_ub = sys.maxint
+ d.instr_ub = sys.maxint
- if frame.instr_lb == frame.last_instr: # At start of line!
- frame.f_lineno = line
+ if d.instr_lb == frame.last_instr: # At start of line!
+ d.f_lineno = line
self._trace(frame, 'line', self.space.w_None)
- frame.instr_prev_plus_one = frame.last_instr + 1
+ d.instr_prev_plus_one = frame.last_instr + 1
def bytecode_trace_after_exception(self, frame):
"Like bytecode_trace(), but without increasing the ticker."
@@ -288,7 +289,7 @@
frame = self.gettopframe_nohidden()
while frame:
if is_being_profiled:
- frame.is_being_profiled = True
+ frame.getorcreatedebug().is_being_profiled = True
frame = self.getnextframe_nohidden(frame)
def call_tracing(self, w_func, w_args):
@@ -309,7 +310,7 @@
if event == 'call':
w_callback = self.gettrace()
else:
- w_callback = frame.w_f_trace
+ w_callback = frame.get_w_f_trace()
if w_callback is not None and event != "leaveframe":
if operr is not None:
@@ -320,15 +321,16 @@
frame.fast2locals()
self.is_tracing += 1
try:
+ d = frame.getorcreatedebug()
try:
w_result = space.call_function(w_callback, space.wrap(frame), space.wrap(event), w_arg)
if space.is_w(w_result, space.w_None):
- frame.w_f_trace = None
+ d.w_f_trace = None
else:
- frame.w_f_trace = w_result
+ d.w_f_trace = w_result
except:
self.settrace(space.w_None)
- frame.w_f_trace = None
+ d.w_f_trace = None
raise
finally:
self.is_tracing -= 1
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -23,6 +23,15 @@
globals()[op] = stdlib_opcode.opmap[op]
HAVE_ARGUMENT = stdlib_opcode.HAVE_ARGUMENT
+class FrameDebugData(object):
+ """ A small object that holds debug data for tracing
+ """
+ w_f_trace = None
+ instr_lb = 0
+ instr_ub = 0
+ instr_prev_plus_one = 0
+ f_lineno = -1 # current lineno
+ is_being_profiled = False
class PyFrame(W_Root):
"""Represents a frame for a regular Python function
@@ -49,15 +58,9 @@
last_instr = -1
last_exception = None
f_backref = jit.vref_None
- # For tracing
- w_f_trace = None
- instr_lb = 0
- instr_ub = 0
- instr_prev_plus_one = 0
- # end of tracing
- is_being_profiled = False
escaped = False # see mark_as_escaped()
+ debugdata = None
w_globals = None
w_locals = None # dict containing locals, if forced or necessary
@@ -65,13 +68,12 @@
locals_stack_w = None # the list of all locals and valuestack
valuestackdepth = 0 # number of items on valuestack
lastblock = None
- # default to False
- f_lineno = 0 # current lineno
cells = None # cells
# other fields:
- # builtin - builtin cache, only if honor__builtins__ is True,
+ # builtin - builtin cache, only if honor__builtins__ is True
+ # defaults to False
# there is also self.space which is removed by the annotator
@@ -97,7 +99,26 @@
# regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
# class bodies only have CO_NEWLOCALS.
self.initialize_frame_scopes(outer_func, code)
- self.f_lineno = code.co_firstlineno
+
+ def getdebug(self):
+ return self.debugdata
+
+ def getorcreatedebug(self):
+ if self.debugdata is None:
+ self.debugdata = FrameDebugData()
+ return self.debugdata
+
+ def get_w_f_trace(self):
+ d = self.getdebug()
+ if d is None:
+ return None
+ return d.w_f_trace
+
+ def get_is_being_profiled(self):
+ d = self.getdebug()
+ if d is None:
+ return False
+ return d.is_being_profiled
def __repr__(self):
# NOT_RPYTHON: useful in tracebacks
@@ -386,10 +407,10 @@
else:
w_cells = space.newlist([space.wrap(cell) for cell in cells])
- if self.w_f_trace is None:
+ if self.get_w_f_trace() is None:
f_lineno = self.get_last_lineno()
else:
- f_lineno = self.f_lineno
+ f_lineno = self.getorcreatedebug().f_lineno
nlocals = self.pycode.co_nlocals
values_w = self.locals_stack_w[nlocals:self.valuestackdepth]
@@ -405,6 +426,7 @@
w_exc_value = self.last_exception.get_w_value(space)
w_tb = w(self.last_exception.get_traceback())
+ d = self.getorcreatedebug()
tup_state = [
w(self.f_backref()),
w(self.get_builtin()),
@@ -421,11 +443,11 @@
space.w_None, #XXX placeholder for f_locals
#f_restricted requires no additional data!
- space.w_None, ## self.w_f_trace, ignore for now
+ space.w_None,
- w(self.instr_lb), #do we need these three (that are for tracing)
- w(self.instr_ub),
- w(self.instr_prev_plus_one),
+ w(d.instr_lb),
+ w(d.instr_ub),
+ w(d.instr_prev_plus_one),
w_cells,
]
return nt(tup_state)
@@ -483,18 +505,19 @@
)
new_frame.last_instr = space.int_w(w_last_instr)
new_frame.frame_finished_execution = space.is_true(w_finished)
- new_frame.f_lineno = space.int_w(w_f_lineno)
+ d = new_frame.getorcreatedebug()
+ d.f_lineno = space.int_w(w_f_lineno)
fastlocals_w = maker.slp_from_tuple_with_nulls(space, w_fastlocals)
new_frame.locals_stack_w[:len(fastlocals_w)] = fastlocals_w
if space.is_w(w_f_trace, space.w_None):
- new_frame.w_f_trace = None
+ d.w_f_trace = None
else:
- new_frame.w_f_trace = w_f_trace
+ d.w_f_trace = w_f_trace
- new_frame.instr_lb = space.int_w(w_instr_lb) #the three for tracing
- new_frame.instr_ub = space.int_w(w_instr_ub)
- new_frame.instr_prev_plus_one = space.int_w(w_instr_prev_plus_one)
+ d.instr_lb = space.int_w(w_instr_lb) #the three for tracing
+ d.instr_ub = space.int_w(w_instr_ub)
+ d.instr_prev_plus_one = space.int_w(w_instr_prev_plus_one)
self._setcellvars(cellvars)
@@ -632,10 +655,10 @@
def fget_f_lineno(self, space):
"Returns the line number of the instruction currently being executed."
- if self.w_f_trace is None:
+ if self.get_w_f_trace() is None:
return space.wrap(self.get_last_lineno())
else:
- return space.wrap(self.f_lineno)
+ return space.wrap(self.getorcreatedebug().f_lineno)
def fset_f_lineno(self, space, w_new_lineno):
"Returns the line number of the instruction currently being executed."
@@ -645,7 +668,7 @@
raise OperationError(space.w_ValueError,
space.wrap("lineno must be an integer"))
- if self.w_f_trace is None:
+ if self.get_w_f_trace() is None:
raise OperationError(space.w_ValueError,
space.wrap("f_lineno can only be set by a trace function."))
@@ -764,7 +787,7 @@
block.cleanup(self)
f_iblock -= 1
- self.f_lineno = new_lineno
+ self.getorcreatedebug().f_lineno = new_lineno
self.last_instr = new_lasti
def get_last_lineno(self):
@@ -782,17 +805,18 @@
return self.space.wrap(self.last_instr)
def fget_f_trace(self, space):
- return self.w_f_trace
+ return self.get_w_f_trace()
def fset_f_trace(self, space, w_trace):
if space.is_w(w_trace, space.w_None):
- self.w_f_trace = None
+ self.getorcreatedebug().w_f_trace = None
else:
- self.w_f_trace = w_trace
- self.f_lineno = self.get_last_lineno()
+ d = self.getorcreatedebug()
+ d.w_f_trace = w_trace
+ d = self.get_last_lineno()
def fdel_f_trace(self, space):
- self.w_f_trace = None
+ self.getorcreatedebug().w_f_trace = None
def fget_f_exc_type(self, space):
if self.last_exception is not None:
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -109,14 +109,14 @@
# dispatch_bytecode(), causing the real exception to be
# raised after the exception handler block was popped.
try:
- trace = self.w_f_trace
+ trace = self.get_w_f_trace()
if trace is not None:
- self.w_f_trace = None
+ self.getorcreatedebug().w_f_trace = None
try:
ec.bytecode_trace_after_exception(self)
finally:
if trace is not None:
- self.w_f_trace = trace
+ self.getorcreatedebug().w_f_trace = trace
except OperationError, e:
operr = e
pytraceback.record_application_traceback(
@@ -1185,7 +1185,7 @@
args = self.argument_factory(arguments, keywords, keywords_w, w_star,
w_starstar)
w_function = self.popvalue()
- if self.is_being_profiled and function.is_builtin_code(w_function):
+ if self.get_is_being_profiled() and function.is_builtin_code(w_function):
w_result = self.space.call_args_and_c_profile(self, w_function,
args)
else:
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
@@ -35,7 +35,7 @@
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)
- rffi.setintfield(py_frame, 'c_f_lineno', frame.f_lineno)
+ rffi.setintfield(py_frame, 'c_f_lineno', frame.getorcreatedebug().f_lineno)
@cpython_api([PyObject], lltype.Void, external=False)
def frame_dealloc(space, py_obj):
@@ -58,7 +58,8 @@
w_globals = from_ref(space, py_frame.c_f_globals)
frame = space.FrameClass(space, code, w_globals, outer_func=None)
- frame.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno')
+ d = frame.getorcreatedebug()
+ d.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno')
w_obj = space.wrap(frame)
track_reference(space, py_obj, w_obj)
return w_obj
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -23,9 +23,7 @@
'cells[*]',
'last_exception',
'lastblock',
- 'is_being_profiled',
'w_globals',
- 'w_f_trace',
]
JUMP_ABSOLUTE = opmap['JUMP_ABSOLUTE']
@@ -58,7 +56,7 @@
def dispatch(self, pycode, next_instr, ec):
self = hint(self, access_directly=True)
next_instr = r_uint(next_instr)
- is_being_profiled = self.is_being_profiled
+ is_being_profiled = self.get_is_being_profiled()
try:
while True:
pypyjitdriver.jit_merge_point(ec=ec,
@@ -67,7 +65,7 @@
co_code = pycode.co_code
self.valuestackdepth = hint(self.valuestackdepth, promote=True)
next_instr = self.handle_bytecode(co_code, next_instr, ec)
- is_being_profiled = self.is_being_profiled
+ is_being_profiled = self.get_is_being_profiled()
except Yield:
self.last_exception = None
w_result = self.popvalue()
@@ -91,8 +89,8 @@
jumpto = r_uint(self.last_instr)
#
pypyjitdriver.can_enter_jit(frame=self, ec=ec, next_instr=jumpto,
- pycode=self.getcode(),
- is_being_profiled=self.is_being_profiled)
+ pycode=self.getcode(),
+ is_being_profiled=self.get_is_being_profiled())
return jumpto
def _get_adapted_tick_counter():
diff --git a/pypy/objspace/std/callmethod.py b/pypy/objspace/std/callmethod.py
--- a/pypy/objspace/std/callmethod.py
+++ b/pypy/objspace/std/callmethod.py
@@ -102,7 +102,7 @@
if w_self is None:
f.popvalue() # removes w_self, which is None
w_callable = f.popvalue()
- if f.is_being_profiled and function.is_builtin_code(w_callable):
+ if f.get_is_being_profiled() and function.is_builtin_code(w_callable):
w_result = f.space.call_args_and_c_profile(f, w_callable, args)
else:
w_result = f.space.call_args(w_callable, args)
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
@@ -237,7 +237,8 @@
frame = space.getexecutioncontext().gettopframe()
w_locals = frame.getdictscope()
pycode = frame.pycode
- filename = "<%s:%s>" %(pycode.co_filename, frame.f_lineno)
+ filename = "<%s:%s>" %(pycode.co_filename,
+ space.int_w(frame.fget_f_lineno(space)))
lines = [x + "\n" for x in expr.split("\n")]
py.std.linecache.cache[filename] = (1, None, lines, filename)
w_locals = space.call_method(w_locals, 'copy')
More information about the pypy-commit
mailing list