[pypy-svn] r79249 - in pypy/branch/jit-free/pypy/jit: backend backend/llgraph backend/test backend/x86 backend/x86/test metainterp
arigo at codespeak.net
arigo at codespeak.net
Thu Nov 18 14:55:51 CET 2010
Author: arigo
Date: Thu Nov 18 14:55:49 2010
New Revision: 79249
Modified:
pypy/branch/jit-free/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/jit-free/pypy/jit/backend/llgraph/runner.py
pypy/branch/jit-free/pypy/jit/backend/model.py
pypy/branch/jit-free/pypy/jit/backend/test/runner_test.py
pypy/branch/jit-free/pypy/jit/backend/x86/assembler.py
pypy/branch/jit-free/pypy/jit/backend/x86/test/test_runner.py
pypy/branch/jit-free/pypy/jit/metainterp/compile.py
pypy/branch/jit-free/pypy/jit/metainterp/history.py
pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py
pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py
pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py
Log:
(antocuni, arigo)
Refactoring the LoopToken class to not have a __del__ any more.
Now the __del__ is on a small class CompiledLoopToken that is
attached by the backend when compiling a new loop. Solves the
issue of weakrefs to objects that have a __del__.
Modified: pypy/branch/jit-free/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/jit-free/pypy/jit/backend/llgraph/llimpl.py Thu Nov 18 14:55:49 2010
@@ -857,13 +857,13 @@
global _last_exception
loop_token = wref_loop_token()
assert loop_token, "CALL_ASSEMBLER to a target that already died"
- if hasattr(loop_token, '_llgraph_redirected'):
- return self._do_call_assembler(loop_token._llgraph_redirected,
- *args)
+ ctl = loop_token.compiled_loop_token
+ if hasattr(ctl, 'redirected'):
+ return self._do_call_assembler(ctl.redirected, *args)
assert not self._forced
self._may_force = self.opindex
try:
- inpargs = _from_opaque(loop_token._llgraph_compiled_version).inputargs
+ inpargs = _from_opaque(ctl.compiled_version).inputargs
for i, inparg in enumerate(inpargs):
TYPE = inparg.concretetype
if TYPE is lltype.Signed:
@@ -1556,11 +1556,13 @@
do_setfield_gc_int(vable, fielddescr.ofs, 0)
def redirect_call_assembler(cpu, oldlooptoken, newlooptoken):
- OLD = _from_opaque(oldlooptoken._llgraph_compiled_version).getargtypes()
- NEW = _from_opaque(newlooptoken._llgraph_compiled_version).getargtypes()
+ oldclt = oldlooptoken.compiled_loop_token
+ newclt = newlooptoken.compiled_loop_token
+ OLD = _from_opaque(oldclt.compiled_version).getargtypes()
+ NEW = _from_opaque(newclt.compiled_version).getargtypes()
assert OLD == NEW
- assert not hasattr(oldlooptoken, '_llgraph_redirected')
- oldlooptoken._llgraph_redirected = weakref.ref(newlooptoken)
+ assert not hasattr(oldclt, 'redirected')
+ oldclt.redirected = weakref.ref(newlooptoken)
# ____________________________________________________________
Modified: pypy/branch/jit-free/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/jit-free/pypy/jit/backend/llgraph/runner.py Thu Nov 18 14:55:49 2010
@@ -120,28 +120,30 @@
def compile_bridge(self, faildescr, inputargs, operations,
original_loop_token, log=True):
c = llimpl.compile_start()
- original_loop_token._llgraph_loop_and_bridges.append(c)
+ clt = original_loop_token.compiled_loop_token
+ clt.loop_and_bridges.append(c)
+ clt.bridges_count += 1
self._compile_loop_or_bridge(c, inputargs, operations)
old, oldindex = faildescr._compiled_fail
llimpl.compile_redirect_fail(old, oldindex, c)
- def compile_loop(self, inputargs, operations, loopdescr, log=True):
+ def compile_loop(self, inputargs, operations, looptoken, log=True):
"""In a real assembler backend, this should assemble the given
list of operations. Here we just generate a similar CompiledLoop
instance. The code here is RPython, whereas the code in llimpl
is not.
"""
c = llimpl.compile_start()
- if not we_are_translated():
- assert not hasattr(loopdescr, '_llgraph_loop_and_bridges')
- loopdescr._llgraph_loop_and_bridges = [c]
- loopdescr._llgraph_compiled_version = c
+ clt = model.CompiledLoopToken(self, looptoken.number)
+ clt.loop_and_bridges = [c]
+ clt.compiled_version = c
+ looptoken.compiled_loop_token = clt
self._compile_loop_or_bridge(c, inputargs, operations)
- def free_loop_and_bridges(self, looptoken):
- for c in looptoken._llgraph_loop_and_bridges:
+ def free_loop_and_bridges(self, compiled_loop_token):
+ for c in compiled_loop_token.loop_and_bridges:
llimpl.mark_as_free(c)
- model.AbstractCPU.free_loop_and_bridges(self, looptoken)
+ model.AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
def _compile_loop_or_bridge(self, c, inputargs, operations):
var2index = {}
@@ -216,7 +218,7 @@
if op.getopnum() == rop.JUMP:
targettoken = op.getdescr()
assert isinstance(targettoken, history.LoopToken)
- compiled_version = targettoken._llgraph_compiled_version
+ compiled_version = targettoken.compiled_loop_token.compiled_version
llimpl.compile_add_jump_target(c, compiled_version)
elif op.getopnum() == rop.FINISH:
faildescr = op.getdescr()
@@ -226,7 +228,7 @@
assert False, "unknown operation"
def _execute_token(self, loop_token):
- compiled_version = loop_token._llgraph_compiled_version
+ compiled_version = loop_token.compiled_loop_token.compiled_version
frame = llimpl.new_frame(self.is_oo, self)
# setup the frame
llimpl.frame_clear(frame, compiled_version)
Modified: pypy/branch/jit-free/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/backend/model.py (original)
+++ pypy/branch/jit-free/pypy/jit/backend/model.py Thu Nov 18 14:55:49 2010
@@ -1,3 +1,4 @@
+from pypy.rlib.debug import debug_start, debug_print, debug_stop
from pypy.jit.metainterp import history, compile
@@ -41,8 +42,9 @@
def compile_loop(self, inputargs, operations, looptoken, log=True):
"""Assemble the given loop.
- Extra attributes should be put in the LoopToken to
- point to the compiled loop in assembler.
+ Should create and attach a fresh CompiledLoopToken to
+ looptoken.compiled_loop_token and stick extra attributes
+ on it to point to the compiled loop in assembler.
"""
raise NotImplementedError
@@ -120,7 +122,7 @@
oldlooptoken so that from now own they will call newlooptoken."""
raise NotImplementedError
- def free_loop_and_bridges(self, looptoken):
+ def free_loop_and_bridges(self, compiled_loop_token):
"""This method is called to free resources (machine code,
references to resume guards, etc.) allocated by the compilation
of a loop and all bridges attached to it. After this call, the
@@ -133,10 +135,10 @@
# resume descrs are the largest consumers of memory (about 3x
# more than the assembler, in the case of the x86 backend).
lst = self.fail_descr_list
- for n in looptoken.faildescr_indices:
+ for n in compiled_loop_token.faildescr_indices:
lst[n] = None
- self.fail_descr_free_list.extend(looptoken.faildescr_indices)
- # We expect 'looptoken' to be itself garbage-collected soon.
+ self.fail_descr_free_list.extend(compiled_loop_token.faildescr_indices)
+ # We expect 'compiled_loop_token' to be itself garbage-collected soon.
@staticmethod
def sizeof(S):
@@ -262,3 +264,24 @@
def force(self, force_token):
raise NotImplementedError
+
+
+class CompiledLoopToken(object):
+ def __init__(self, cpu, number):
+ self.cpu = cpu
+ self.number = number
+ self.bridges_count = 0
+ # This growing list gives the 'descr_number' of all fail descrs
+ # that belong to this loop or to a bridge attached to it.
+ # Filled by the frontend calling record_faildescr_index().
+ self.faildescr_indices = []
+
+ def record_faildescr_index(self, n):
+ self.faildescr_indices.append(n)
+
+ def __del__(self):
+ debug_start("jit-free-looptoken")
+ debug_print("Freeing loop #", self.number, 'with',
+ self.bridges_count, 'attached bridges')
+ self.cpu.free_loop_and_bridges(self)
+ debug_stop("jit-free-looptoken")
Modified: pypy/branch/jit-free/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/branch/jit-free/pypy/jit/backend/test/runner_test.py Thu Nov 18 14:55:49 2010
@@ -199,7 +199,7 @@
]
bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge)
+ self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
self.cpu.set_future_value_int(0, 2)
fail = self.cpu.execute_token(looptoken)
@@ -233,7 +233,7 @@
]
bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge)
+ self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
self.cpu.set_future_value_int(0, 2)
fail = self.cpu.execute_token(looptoken)
@@ -1050,7 +1050,7 @@
ResOperation(rop.JUMP, [f3] + fboxes2[1:], None, descr=looptoken),
]
- self.cpu.compile_bridge(faildescr1, fboxes2, bridge)
+ self.cpu.compile_bridge(faildescr1, fboxes2, bridge, looptoken)
for i in range(len(fboxes)):
self.cpu.set_future_value_float(i, 13.5 + 6.73 * i)
Modified: pypy/branch/jit-free/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/jit-free/pypy/jit/backend/x86/assembler.py Thu Nov 18 14:55:49 2010
@@ -7,6 +7,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.annlowlevel import llhelper
from pypy.tool.uid import fixid
+from pypy.jit.backend.model import CompiledLoopToken
from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
X86XMMRegisterManager, get_ebp_ofs,
_get_scale)
@@ -305,6 +306,8 @@
_x86_arglocs
_x86_debug_checksum
"""
+ looptoken.compiled_loop_token = CompiledLoopToken(self.cpu,
+ looptoken.number)
if not we_are_translated():
# Arguments should be unique
assert len(set(inputargs)) == len(inputargs)
Modified: pypy/branch/jit-free/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/backend/x86/test/test_runner.py (original)
+++ pypy/branch/jit-free/pypy/jit/backend/x86/test/test_runner.py Thu Nov 18 14:55:49 2010
@@ -338,6 +338,7 @@
faildescr1 = BasicFailDescr(1)
faildescr2 = BasicFailDescr(2)
looptoken = LoopToken()
+ looptoken.number = 17
class FakeString(object):
def __init__(self, val):
self.val = val
@@ -356,7 +357,7 @@
operations[3].setfailargs([i1])
self.cpu.compile_loop(inputargs, operations, looptoken)
name, loopaddress, loopsize = agent.functions[0]
- assert name == "Loop # 0: hello"
+ assert name == "Loop # 17: hello"
assert loopaddress <= looptoken._x86_loop_code
assert loopsize >= 40 # randomish number
Modified: pypy/branch/jit-free/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/compile.py Thu Nov 18 14:55:49 2010
@@ -42,8 +42,8 @@
name = metainterp.staticdata.stats.name_for_new_loop()
return TreeLoop(name)
-def make_loop_token(cpu, nb_args, jitdriver_sd):
- loop_token = LoopToken(cpu)
+def make_loop_token(nb_args, jitdriver_sd):
+ loop_token = LoopToken()
loop_token.specnodes = [prebuiltNotSpecNode] * nb_args
loop_token.outermost_jitdriver_sd = jitdriver_sd
return loop_token
@@ -61,8 +61,8 @@
if isinstance(descr, ResumeDescr):
descr.wref_original_loop_token = wref # stick it there
n = descr.index
- if n >= 0: # we also record the resumedescr in this list
- looptoken.faildescr_indices.append(n)
+ if n >= 0: # we also record the resumedescr number
+ looptoken.compiled_loop_token.record_faildescr_index(n)
elif isinstance(descr, LoopToken):
# for a JUMP or a CALL_ASSEMBLER: record it as a potential jump.
# (the following test is not enough to prevent more complicated
@@ -89,9 +89,8 @@
h_ops = history.operations
loop.operations = [h_ops[i].clone() for i in range(start, len(h_ops))]
metainterp_sd = metainterp.staticdata
- cpu = metainterp.cpu
jitdriver_sd = metainterp.jitdriver_sd
- loop_token = make_loop_token(cpu, len(loop.inputargs), jitdriver_sd)
+ loop_token = make_loop_token(len(loop.inputargs), jitdriver_sd)
loop.token = loop_token
loop.operations[-1].setdescr(loop_token) # patch the target of the JUMP
try:
@@ -155,7 +154,6 @@
if not we_are_translated():
show_loop(metainterp_sd)
TreeLoop.check_consistency_of(inputargs, operations)
- original_loop_token.bridges_count += 1
metainterp_sd.profiler.start_backend()
debug_start("jit-backend")
try:
@@ -512,12 +510,11 @@
# a loop at all but ends in a jump to the target loop. It starts
# with completely unoptimized arguments, as in the interpreter.
metainterp_sd = metainterp.staticdata
- cpu = metainterp.cpu
jitdriver_sd = metainterp.jitdriver_sd
redargs = new_loop.inputargs
# We make a new LoopToken for this entry bridge, and stick it
# to every guard in the loop.
- new_loop_token = make_loop_token(cpu, len(redargs), jitdriver_sd)
+ new_loop_token = make_loop_token(len(redargs), jitdriver_sd)
new_loop.token = new_loop_token
send_loop_to_backend(metainterp_sd, new_loop, "entry bridge")
# send the new_loop to warmspot.py, to be called directly the next time
@@ -601,7 +598,7 @@
"""
# 'redboxes' is only used to know the types of red arguments.
inputargs = [box.clonebox() for box in redboxes]
- loop_token = make_loop_token(cpu, len(inputargs), jitdriver_sd)
+ loop_token = make_loop_token(len(inputargs), jitdriver_sd)
# 'nb_red_args' might be smaller than len(redboxes),
# because it doesn't include the virtualizable boxes.
nb_red_args = jitdriver_sd.num_red_args
Modified: pypy/branch/jit-free/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/history.py Thu Nov 18 14:55:49 2010
@@ -5,7 +5,6 @@
from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic
from pypy.rlib.objectmodel import compute_hash, compute_unique_id
from pypy.rlib.rarithmetic import intmask, r_longlong
-from pypy.rlib.debug import debug_start, debug_print, debug_stop
from pypy.tool.uid import uid
from pypy.conftest import option
@@ -731,40 +730,28 @@
outermost_jitdriver_sd = None
# specnodes = ...
# and more data specified by the backend when the loop is compiled
- cpu = None
number = -1
generation = r_longlong(0)
- bridges_count = 0
+ # one purpose of LoopToken is to keep alive the CompiledLoopToken
+ # returned by the backend. When the LoopToken goes away, the
+ # CompiledLoopToken has its __del__ called, which frees the assembler
+ # memory and the ResumeGuards.
+ compiled_loop_token = None
- def __init__(self, cpu=None):
- self.cpu = cpu
- # See get_fail_descr_number() in backend/model.py: this growing
- # list gives the 'descr_number' of all fail descrs that belong to
- # this loop or to a bridge attached to it.
- self.faildescr_indices = []
+ def __init__(self):
# For memory management of assembled loops
self._keepalive_target_looktokens = {} # set of other LoopTokens
def record_jump_to(self, target_loop_token):
self._keepalive_target_looktokens[target_loop_token] = None
- def __del__(self):
- if self.generation > r_longlong(0):
- # MemoryManager.keep_loop_alive() has been called on this
- # loop token, which means that it has been successfully
- # compiled by the backend. Free it now.
- debug_start("jit-free-looptoken")
- debug_print("Freeing loop #", self.number, 'with',
- self.bridges_count, 'attached bridges')
- self.cpu.free_loop_and_bridges(self)
- debug_stop("jit-free-looptoken")
-
def __repr__(self):
return '<Loop %d, gen=%d>' % (self.number, self.generation)
def repr_of_descr(self):
return '<Loop%d>' % self.number
+
class TreeLoop(object):
inputargs = None
operations = None
Modified: pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py Thu Nov 18 14:55:49 2010
@@ -1,4 +1,4 @@
-import py, os, sys, weakref
+import py, os, sys
from pypy.rpython.lltypesystem import lltype, llmemory, rclass
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.unroll import unrolling_iterable
Modified: pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py Thu Nov 18 14:55:49 2010
@@ -816,10 +816,6 @@
# ____________________________________________________________
def execute_token(self, loop_token):
- self.metainterp_sd.profiler.start_running()
- debug_start("jit-running")
fail_descr = self.cpu.execute_token(loop_token)
- debug_stop("jit-running")
- self.metainterp_sd.profiler.end_running()
self.memory_manager.keep_loop_alive(loop_token)
return fail_descr
Modified: pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py (original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py Thu Nov 18 14:55:49 2010
@@ -344,7 +344,11 @@
# ---------- execute assembler ----------
while True: # until interrupted by an exception
+ metainterp_sd.profiler.start_running()
+ debug_start("jit-running")
fail_descr = warmrunnerdesc.execute_token(loop_token)
+ debug_stop("jit-running")
+ metainterp_sd.profiler.end_running()
loop_token = None # for test_memmgr
if vinfo is not None:
vinfo.reset_vable_token(virtualizable)
More information about the Pypy-commit
mailing list