[pypy-svn] r65264 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test
arigo at codespeak.net
arigo at codespeak.net
Thu May 14 19:03:27 CEST 2009
Author: arigo
Date: Thu May 14 19:03:25 2009
New Revision: 65264
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py
pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py
pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py
pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py
Log:
Yay! GC roots finding seems to work.
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Thu May 14 19:03:25 2009
@@ -155,6 +155,9 @@
self.single_gcref_descr = ConstDescr3(0, WORD, True)
else:
self.gcrefs = None
+ self.gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+ if self.gcrootmap:
+ self.gcrootmap.initialize()
def eventually_log_operations(self, inputargs, operations, memo=None,
myid=0):
@@ -240,8 +243,7 @@
self.eventually_log_operations(tree.inputargs, tree.operations, None,
compute_unique_id(tree))
regalloc = RegAlloc(self, tree, self.cpu.translate_support_code)
- if not we_are_translated():
- self._regalloc = regalloc # for debugging
+ self._regalloc = regalloc
regalloc.walk_operations(tree)
self.sanitize_tree(tree.operations)
self.mc.done()
@@ -257,6 +259,8 @@
tl = op.jump_target
self.patch_jump(pos, tl._x86_compiled, tl.arglocs, tl.arglocs,
tree._x86_stack_depth, tl._x86_stack_depth)
+ if we_are_translated():
+ self._regalloc = None # else keep it around for debugging
def sanitize_tree(self, operations):
""" Cleans up all attributes attached by regalloc and backend
@@ -270,6 +274,9 @@
def assemble_bootstrap_code(self, jumpaddr, arglocs, framesize):
self.make_sure_mc_exists()
addr = self.mc.tell()
+ if self.gcrootmap:
+ self.mc.PUSH(ebp)
+ self.mc.MOV(ebp, esp)
self.mc.SUB(esp, imm(framesize * WORD))
# This uses XCHG to put zeroes in fail_boxes after reading them,
# just in case they are pointers.
@@ -390,6 +397,7 @@
assert not isinstance(arg, MODRM)
self.mc.PUSH(arg)
self.mc.CALL(rel32(addr))
+ self.mark_gc_roots(len(args))
self.mc.ADD(esp, imm(len(args) * WORD))
assert res is eax
@@ -814,6 +822,8 @@
self.mc.ADD(esp, imm32(0))
guard_index = self.cpu.make_guard_index(op)
self.mc.MOV(eax, imm(guard_index))
+ if self.gcrootmap:
+ self.mc.POP(ebp)
self.mc.RET()
def generate_ovf_set(self):
@@ -860,6 +870,7 @@
if isinstance(x, MODRM):
x = stack_pos(x.position + extra_on_stack)
self.mc.CALL(x)
+ self.mark_gc_roots(extra_on_stack)
self.mc.ADD(esp, imm(WORD * extra_on_stack))
if size == 1:
self.mc.AND(eax, imm(0xff))
@@ -889,6 +900,18 @@
# self.gen_call(op, arglocs, resloc)
# self.mc.MOVZX(eax, eax)
+ def mark_gc_roots(self, extra_on_stack):
+ if self.gcrootmap:
+ gclocs = []
+ regalloc = self._regalloc
+ for v, val in regalloc.stack_bindings.items():
+ if (isinstance(v, BoxPtr) and
+ regalloc.longevity[v][1] > regalloc.position):
+ gclocs.append(val)
+ shape = self.gcrootmap.encode_callshape(gclocs)
+ self.gcrootmap.put(rffi.cast(llmemory.Address, self.mc.tell()),
+ shape)
+
genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
genop_list = [Assembler386.not_implemented_op] * rop._LAST
genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/gc.py Thu May 14 19:03:25 2009
@@ -19,6 +19,7 @@
class GcLLDescr_boehm(GcLLDescription):
moving_gc = False
+ gcrootmap = None
def __init__(self, gcdescr, mixlevelann):
# grab a pointer to the Boehm 'malloc' function
@@ -135,16 +136,22 @@
CALLSHAPE_ARRAY = rffi.CArray(rffi.UCHAR)
def __init__(self):
- self._gcmap = lltype.malloc(self.GCMAP_ARRAY, 0, flavor='raw')
+ self._gcmap = lltype.nullptr(self.GCMAP_ARRAY)
self._gcmap_curlength = 0
self._gcmap_maxlength = 0
+ def initialize(self):
+ # hack hack hack. Remove these lines and see MissingRTypeAttribute
+ # when the rtyper tries to annotate these methods only when GC-ing...
+ self.gcmapstart()
+ self.gcmapend()
+
def gcmapstart(self):
return llmemory.cast_ptr_to_adr(self._gcmap)
def gcmapend(self):
start = self.gcmapstart()
- return start + llmemory.sizeof(lltype.Signed) * self._gcmap_curlength
+ return start + llmemory.sizeof(llmemory.Address)*self._gcmap_curlength
def put(self, retaddr, callshapeaddr):
"""'retaddr' is the address just after the CALL.
@@ -157,31 +164,31 @@
self._gcmap_curlength = index + 2
def _enlarge_gcmap(self):
- newlength = 128 + self._gcmap_maxlength // 4
+ newlength = 128 + self._gcmap_maxlength * 5 // 4
newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw')
oldgcmap = self._gcmap
for i in range(self._gcmap_curlength):
newgcmap[i] = oldgcmap[i]
self._gcmap = newgcmap
self._gcmap_maxlength = newlength
- lltype.free(oldgcmap, flavor='raw')
+ if oldgcmap:
+ lltype.free(oldgcmap, flavor='raw')
- def encode_callshape(self, gclocs, framesize):
+ def encode_callshape(self, gclocs):
"""Encode a callshape from the list of locations containing GC
- pointers and from the frame size of the current (caller) frame.
- The framesize gives the offset from %esp to the return address
- of the current frame."""
- shape = self._get_callshape(gclocs, framesize)
+ pointers."""
+ shape = self._get_callshape(gclocs)
return self._compress_callshape(shape)
- def _get_callshape(self, gclocs, framesize):
- # the four registers %ebx, %esi, %edi, %ebp are not used at all
+ def _get_callshape(self, gclocs):
+ # The return address is always found at 4(%ebp); and
+ # the three registers %ebx, %esi, %edi are not used at all
# so far, so their value always comes from the caller.
- shape = [self.LOC_ESP_BASED | framesize,
+ shape = [self.LOC_EBP_BASED | 4,
self.LOC_REG | 0,
self.LOC_REG | 4,
self.LOC_REG | 8,
- self.LOC_REG | 12,
+ self.LOC_EBP_BASED | 0,
0]
for loc in gclocs:
assert isinstance(loc, MODRM)
@@ -225,15 +232,16 @@
except KeyError:
raise NotImplementedError("--gcrootfinder=%s not implemented"
" with the JIT" % (name,))
- self.gcrootmap = cls()
+ gcrootmap = cls()
+ self.gcrootmap = gcrootmap
# make a TransformerLayoutBuilder and save it on the translator
# where it can be fished and reused by the FrameworkGCTransformer
self.layoutbuilder = framework.TransformerLayoutBuilder()
self.translator._jit2gc = {
'layoutbuilder': self.layoutbuilder,
- 'gcmapstart': self.gcrootmap.gcmapstart,
- 'gcmapend': self.gcrootmap.gcmapend,
+ 'gcmapstart': lambda: gcrootmap.gcmapstart(),
+ 'gcmapend': lambda: gcrootmap.gcmapend(),
}
GCClass, _ = choose_gc_from_config(gcdescr.config)
self.moving_gc = GCClass.moving_gc
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Thu May 14 19:03:25 2009
@@ -951,7 +951,8 @@
loc = self.make_sure_var_in_reg(v, [v])
self.sync_var(v)
if size != 0:
- # XXX lshift?
+ # XXX lshift? no, better yet, use 'LEA' somehow (it can be
+ # combined with the following INT_ADD)
self.Perform(ResOperation(rop.INT_MUL, [], None),
[loc, imm(1 << size)], loc)
self.Perform(ResOperation(rop.INT_ADD, [], None),
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_zrpy_gc.py Thu May 14 19:03:25 2009
@@ -7,7 +7,7 @@
import weakref, random
import py
from pypy.rlib import rgc
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.jit import JitDriver
from pypy.jit.backend.x86.runner import CPU386
@@ -112,17 +112,34 @@
def test_GcRootMap_asmgcc():
gcrootmap = GcRootMap_asmgcc()
- shape = gcrootmap._get_callshape([stack_pos(1), stack_pos(55)], 236)
- assert shape == [236|3, 1, 5, 9, 13, 0, 4|3, 220|3]
+ shape = gcrootmap._get_callshape([stack_pos(1), stack_pos(55)])
+ assert shape == [6, 1, 5, 9, 2, 0, 4|3, 220|3]
#
- addr = gcrootmap.encode_callshape([stack_pos(1), stack_pos(55)], 236)
+ shapeaddr = gcrootmap.encode_callshape([stack_pos(1), stack_pos(55)])
PCALLSHAPE = lltype.Ptr(GcRootMap_asmgcc.CALLSHAPE_ARRAY)
- p = llmemory.cast_adr_to_ptr(addr, PCALLSHAPE)
- for i, expected in enumerate([131, 62, 14, 0, 26, 18, 10, 2, 131, 94]):
+ p = llmemory.cast_adr_to_ptr(shapeaddr, PCALLSHAPE)
+ for i, expected in enumerate([131, 62, 14, 0, 4, 18, 10, 2, 12]):
assert p[i] == expected
+ #
+ retaddr = rffi.cast(llmemory.Address, 1234567890)
+ gcrootmap.put(retaddr, shapeaddr)
+ assert gcrootmap._gcmap[0] == retaddr
+ assert gcrootmap._gcmap[1] == shapeaddr
+ assert gcrootmap.gcmapstart().address[0] == retaddr
+ #
+ # the same as before, but enough times to trigger a few resizes
+ expected_shapeaddr = {}
+ for i in range(1, 600):
+ shapeaddr = gcrootmap.encode_callshape([stack_pos(i)])
+ expected_shapeaddr[i] = shapeaddr
+ retaddr = rffi.cast(llmemory.Address, 123456789 + i)
+ gcrootmap.put(retaddr, shapeaddr)
+ for i in range(1, 600):
+ expected_retaddr = rffi.cast(llmemory.Address, 123456789 + i)
+ assert gcrootmap._gcmap[i*2+0] == expected_retaddr
+ assert gcrootmap._gcmap[i*2+1] == expected_shapeaddr[i]
def test_compile_hybrid_2():
- py.test.skip("in-progress")
# a moving GC. Supports malloc_varsize_nonmovable. More complex test,
# requires root stack enumeration but not write_barriers.
myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
More information about the Pypy-commit
mailing list