[pypy-svn] pypy out-of-line-guards: * X86 support for invalidating call assembler
fijal
commits-noreply at bitbucket.org
Sun Jan 2 15:08:18 CET 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: out-of-line-guards
Changeset: r40324:c34c158d2b2f
Date: 2011-01-02 15:54 +0200
http://bitbucket.org/pypy/pypy/changeset/c34c158d2b2f/
Log: * X86 support for invalidating call assembler
* Clean up invalidating to support both jumps (that invalidate
everything) and call_assemblers (that patch back to tmp_token)
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -69,7 +69,8 @@
# cases of cycles, but at least it helps in simple tests of
# test_memgr.py)
if descr is not looptoken:
- looptoken.record_jump_to(descr)
+ looptoken.record_jump_to(descr,
+ op.getopnum() == rop.CALL_ASSEMBLER)
op.setdescr(None) # clear reference, mostly for tests
# mostly for tests: make sure we don't keep a reference to the LoopToken
loop.token = None
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -491,22 +491,29 @@
def get_invalidate_asm(self, TP, fieldname):
def invalidate_asm(arg):
next = getattr(arg, fieldname)
+ all = []
while next:
- prev = next
- llx = llmemory.weakref_deref(ropaque.ROPAQUE, prev.address)
+ llx = llmemory.weakref_deref(ropaque.ROPAQUE, next.address)
if llx:
- x = ropaque.cast_ropaque_to_obj(history.LoopToken, llx)
- x.invalidated = True
- compiled = x.compiled_loop_token.compiled_version
- llimpl.mark_as_invalid(compiled)
- for elem in x._back_looptokens:
- token = elem()
- if token:
- tk = token.compiled_loop_token.compiled_version
- llimpl.invalidate_call_asm(tk,
- x.compiled_loop_token)
-
+ all.append(ropaque.cast_ropaque_to_obj(history.LoopToken,
+ llx))
next = next.next
+
+ while all:
+ next = all.pop()
+ next.invalidated = True
+ compiled = next.compiled_loop_token.compiled_version
+ llimpl.mark_as_invalid(compiled)
+ for elem in next._back_looptokens_call_asm:
+ token = elem()
+ if token:
+ tk = token.compiled_loop_token.compiled_version
+ llimpl.invalidate_call_asm(tk,
+ next.compiled_loop_token)
+ for elem in next._back_looptokens:
+ elem = elem()
+ if elem:
+ all.append(elem)
return invalidate_asm
class OOtypeCPU_xxx_disabled(BaseCPU):
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -749,11 +749,15 @@
# For memory management of assembled loops
self._keepalive_target_looktokens = {} # set of other LoopTokens
self._back_looptokens = []
+ self._back_looptokens_call_asm = []
# the reverse of the _keepalive_target_looktokens dict
- def record_jump_to(self, target_loop_token):
+ def record_jump_to(self, target_loop_token, is_call_asm=False):
self._keepalive_target_looktokens[target_loop_token] = None
- target_loop_token._back_looptokens.append(weakref.ref(self))
+ if is_call_asm:
+ target_loop_token._back_looptokens_call_asm.append(weakref.ref(self))
+ else:
+ target_loop_token._back_looptokens.append(weakref.ref(self))
def __repr__(self):
return '<Loop %d, gen=%d>' % (self.number, self.generation)
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -435,6 +435,9 @@
def consider_guard_no_exception(self, op):
self.perform_guard(op, [], None)
+ def consider_guard_not_invalidated(self, op):
+ self.perform_guard(op, [], None)
+
def consider_guard_exception(self, op):
loc = self.rm.make_sure_var_in_reg(op.getarg(0))
box = TempBox()
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -2,6 +2,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.llinterp import LLInterpreter
from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib import ropaque
from pypy.jit.metainterp import history, compile
from pypy.jit.backend.x86.assembler import Assembler386
from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -267,7 +267,7 @@
# entry_loop_token is also kept alive by any loop that used
# to point to old_token. Actually freeing old_token early
# is a pointless optimization (it is tiny).
- old_token.record_jump_to(entry_loop_token)
+ old_token.record_jump_to(entry_loop_token, False)
# ----------
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -311,17 +311,10 @@
def _invalidate_call_asm(from_loop, ctl):
for op in from_loop.operations:
- if op.opnum == rop.CALL_ASSEMBLER or op.opnum == rop.JUMP:
- if op.descr is None:
- continue
+ if op.opnum == rop.CALL_ASSEMBLER:
call_target = op.descr().compiled_loop_token
if call_target is ctl:
- tmp = op.descr()._tmp_token.compiled_loop_token
- if hasattr(call_target, 'redirected'):
- import pdb
- pdb.set_trace()
- _redirect_call_assembler(call_target, tmp,
- op.descr()._tmp_token)
+ op.descr = weakref.ref(op.descr()._tmp_token)
if op.is_guard() and op.jump_target is not None:
_invalidate_call_asm(op.jump_target, to_loop)
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -130,6 +130,8 @@
assert self.memcpy_addr != 0, "setup_once() not called?"
self.pending_guard_tokens = []
self.mc = codebuf.MachineCodeBlockWrapper()
+ self.invalidate_adr = rffi.cast(lltype.Signed,
+ looptoken._x86_asm_invalidated)
if self.datablockwrapper is None:
allblocks = self.get_asmmemmgr_blocks(looptoken)
self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
@@ -140,6 +142,7 @@
self.mc = None
self.looppos = -1
self.currently_compiling_loop = None
+ self.invalidate_adr = 0
def finish_once(self):
if self._debug:
@@ -216,6 +219,10 @@
# Arguments should be unique
assert len(set(inputargs)) == len(inputargs)
+ looptoken._x86_asm_invalidated = lltype.malloc(rffi.CArray(
+ lltype.Signed), 1, flavor='raw', track_allocation=False)
+ # XXX wrong, free it one day
+ looptoken._x86_asm_invalidated[0] = 0
self.setup(looptoken)
self.currently_compiling_loop = looptoken
funcname = self._find_debug_merge_point(operations)
@@ -254,10 +261,6 @@
looptoken._x86_bootstrap_code = rawstart + bootstrappos
looptoken._x86_loop_code = rawstart + self.looppos
looptoken._x86_direct_bootstrap_code = rawstart + directbootstrappos
- looptoken._x86_asm_invalidated = lltype.malloc(rffi.CArray(
- lltype.Signed), 1, flavor='raw', track_allocation=False)
- # XXX wrong, free it one day
- looptoken._x86_asm_invalidated[0] = 0
self.teardown()
# oprofile support
if self.cpu.profile_agent is not None:
@@ -486,7 +489,7 @@
if IS_X86_64:
return self._assemble_bootstrap_direct_call_64(arglocs, jmppos, stackdepth)
# XXX pushing ebx esi and edi is a bit pointless, since we store
- # all regsiters anyway, for the case of guard_not_forced
+ # all registers anyway, for the case of guard_not_forced
# XXX this can be improved greatly. Right now it'll behave like
# a normal call
nonfloatlocs, floatlocs = arglocs
@@ -1275,6 +1278,11 @@
#
self.implement_guard(guard_token, 'NE')
+ def genop_guard_guard_not_invalidated(self, ign_1, guard_op, guard_token,
+ locs, ign_2):
+ self.mc.CMP(heap(self.invalidate_adr), imm0)
+ self.implement_guard(guard_token, 'NZ')
+
def implement_guard_recovery(self, guard_opnum, faildescr, failargs,
fail_locs):
exc = (guard_opnum == rop.GUARD_EXCEPTION or
More information about the Pypy-commit
mailing list