[pypy-svn] pypy jitypes2: Implement closing and reopening the stack.
arigo
commits-noreply at bitbucket.org
Mon Mar 28 15:58:48 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: jitypes2
Changeset: r42996:58a292fcefa5
Date: 2011-03-28 15:57 +0200
http://bitbucket.org/pypy/pypy/changeset/58a292fcefa5/
Log: Implement closing and reopening the stack.
diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -37,6 +37,11 @@
self.frame_depth += size
return newloc
+ def reserve_location_in_frame(self, size):
+ frame_depth = self.frame_depth
+ self.frame_depth += size
+ return frame_depth
+
# abstract methods that need to be overwritten for specific assemblers
@staticmethod
def frame_pos(loc, type):
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -15,7 +15,6 @@
from pypy.jit.backend.llsupport.descr import GcCache, get_field_descr
from pypy.jit.backend.llsupport.descr import GcPtrFieldDescr
from pypy.jit.backend.llsupport.descr import get_call_descr
-from pypy.rpython.memory.gctransform import asmgcroot
# ____________________________________________________________
@@ -309,6 +308,7 @@
@rgc.no_collect
def freeing_block(self, start, stop):
+ from pypy.rpython.memory.gctransform import asmgcroot
# if [start:stop] is a raw block of assembler, then look up the
# corresponding gcroot markers, and mark them as freed now in
# self._gcmap by setting the 2nd address of every entry to NULL.
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
@@ -126,6 +126,7 @@
self.translate_support_code = translate_support_code
# to be read/used by the assembler too
self.jump_target_descr = None
+ self.close_stack_struct = 0
def _prepare(self, inputargs, operations):
self.fm = X86FrameManager()
@@ -801,6 +802,11 @@
self._consider_call(op, guard_op)
def consider_call_release_gil(self, op, guard_op):
+ # first force the registers like eax into the stack, because of
+ # the initial call to _close_stack()
+ self.rm.before_call()
+ self.xrm.before_call()
+ #
assert guard_op is not None
self._consider_call(op, guard_op)
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
@@ -113,10 +113,11 @@
LLInterpreter.current_interpreter = prev_interpreter
return res
- @staticmethod
def cast_ptr_to_int(x):
adr = llmemory.cast_ptr_to_adr(x)
return CPU386.cast_adr_to_int(adr)
+ cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)'
+ cast_ptr_to_int = staticmethod(cast_ptr_to_int)
all_null_registers = lltype.malloc(rffi.LONGP.TO, 24,
flavor='raw', zero=True,
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -505,6 +505,7 @@
POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1))
LEA_rb = insn(rex_w, '\x8D', register(1,8), stack_bp(2))
+ LEA_rs = insn(rex_w, '\x8D', register(1,8), stack_sp(2))
LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True))
LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2))
LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2))
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
@@ -127,6 +127,8 @@
if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
self._build_malloc_fixedsize_slowpath()
self._build_stack_check_slowpath()
+ if gc_ll_descr.gcrootmap:
+ self._build_close_stack()
debug_start('jit-backend-counts')
self.set_debug(have_debug_prints())
debug_stop('jit-backend-counts')
@@ -274,6 +276,40 @@
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
self.stack_check_slowpath = rawstart
+ @staticmethod
+ def _close_stack(css):
+ # similar to trackgcroot.py:pypy_asm_stackwalk, first part
+ from pypy.rpython.memory.gctransform import asmgcroot
+ new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
+ next = asmgcroot.gcrootanchor.next
+ new.next = next
+ new.prev = asmgcroot.gcrootanchor
+ asmgcroot.gcrootanchor.next = new
+ next.prev = new
+ # XXX and now release the GIL
+
+ @staticmethod
+ def _reopen_stack(css):
+ # similar to trackgcroot.py:pypy_asm_stackwalk, second part
+ from pypy.rpython.memory.gctransform import asmgcroot
+ # XXX first reacquire the GIL
+ old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
+ prev = old.prev
+ next = old.next
+ prev.next = next
+ next.prev = prev
+
+ _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP],
+ lltype.Void))
+
+ def _build_close_stack(self):
+ closestack_func = llhelper(self._CLOSESTACK_FUNC,
+ self._close_stack)
+ reopenstack_func = llhelper(self._CLOSESTACK_FUNC,
+ self._reopen_stack)
+ self.closestack_addr = self.cpu.cast_ptr_to_int(closestack_func)
+ self.reopenstack_addr = self.cpu.cast_ptr_to_int(reopenstack_func)
+
def assemble_loop(self, inputargs, operations, looptoken, log):
'''adds the following attributes to looptoken:
_x86_loop_code (an integer giving an address)
@@ -1832,7 +1868,75 @@
self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
self.implement_guard(guard_token, 'L')
- genop_guard_call_release_gil = genop_guard_call_may_force
+ def genop_guard_call_release_gil(self, op, guard_op, guard_token,
+ arglocs, result_loc):
+ # first, close the stack in the sense of the asmgcc GC root tracker
+ gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+ if gcrootmap:
+ # note that regalloc.py used save_all_regs=True to save all
+ # registers, so we don't have to care about saving them (other
+ # than ebp) in the close_stack_struct
+ self.call_close_stack()
+ # do the call
+ faildescr = guard_op.getdescr()
+ fail_index = self.cpu.get_fail_descr_number(faildescr)
+ self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index)
+ self.genop_call(op, arglocs, result_loc)
+ # then reopen the stack
+ if gcrootmap:
+ self.call_reopen_stack(result_loc)
+ # finally, the guard_not_forced
+ self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
+ self.implement_guard(guard_token, 'L')
+
+ def call_close_stack(self):
+ from pypy.rpython.memory.gctransform import asmgcroot
+ css = self._regalloc.close_stack_struct
+ if css == 0:
+ use_words = (2 + max(asmgcroot.INDEX_OF_EBP,
+ asmgcroot.FRAME_PTR) + 1)
+ pos = self._regalloc.fm.reserve_location_in_frame(use_words)
+ css = get_ebp_ofs(pos + use_words - 1)
+ self._regalloc.close_stack_struct = css
+ # The location where the future CALL will put its return address
+ # will be [ESP-WORD], so save that as the next frame's top address
+ self.mc.LEA_rs(eax.value, -WORD) # LEA EAX, [ESP-4]
+ frame_ptr = css + WORD * (2+asmgcroot.FRAME_PTR)
+ self.mc.MOV_br(frame_ptr, eax.value) # MOV [css.frame], EAX
+ # Save ebp
+ index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
+ self.mc.MOV_br(index_of_ebp, ebp.value) # MOV [css.ebp], EBP
+ # Call the closestack() function (also releasing the GIL)
+ if IS_X86_32:
+ reg = eax
+ elif IS_X86_64:
+ reg = edi
+ self.mc.LEA_rb(reg.value, css)
+ self._emit_call(imm(self.closestack_addr), [reg])
+
+ def call_reopen_stack(self, save_loc):
+ # save the previous result (eax/xmm0) into the stack temporarily
+ if isinstance(save_loc, RegLoc):
+ self._regalloc.reserve_param(save_loc.width//WORD)
+ if save_loc.is_xmm:
+ self.mc.MOVSD_sx(0, save_loc.value)
+ else:
+ self.mc.MOV_sr(0, save_loc.value)
+ # call the reopenstack() function (also reacquiring the GIL)
+ css = self._regalloc.close_stack_struct
+ assert css != 0
+ if IS_X86_32:
+ reg = eax
+ elif IS_X86_64:
+ reg = edi
+ self.mc.LEA_rb(reg.value, css)
+ self._emit_call(imm(self.reopenstack_addr), [reg])
+ # restore the result from the stack
+ if isinstance(save_loc, RegLoc):
+ if save_loc.is_xmm:
+ self.mc.MOVSD_xs(save_loc.value, 0)
+ else:
+ self.mc.MOV_rs(save_loc.value, 0)
def genop_guard_call_assembler(self, op, guard_op, guard_token,
arglocs, result_loc):
@@ -2042,7 +2146,7 @@
# on 64-bits, 'tid' is a value that fits in 31 bits
self.mc.MOV_mi((eax.value, 0), tid)
self.mc.MOV(heap(nursery_free_adr), edx)
-
+
genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
genop_list = [Assembler386.not_implemented_op] * rop._LAST
genop_llong_list = {}
More information about the Pypy-commit
mailing list