[pypy-svn] pypy jit-shadowstack: In-progress.
arigo
commits-noreply at bitbucket.org
Thu Mar 31 13:55:52 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: jit-shadowstack
Changeset: r43042:cf2056d85fa5
Date: 2011-03-31 13:24 +0200
http://bitbucket.org/pypy/pypy/changeset/cf2056d85fa5/
Log: In-progress.
diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -75,8 +75,8 @@
num2a = ((-num2|3) >> 7) | 128
num2b = (-num2|3) & 127
shape = gcrootmap.get_basic_shape()
- gcrootmap.add_ebp_offset(shape, num1)
- gcrootmap.add_ebp_offset(shape, num2)
+ gcrootmap.add_frame_offset(shape, num1)
+ gcrootmap.add_frame_offset(shape, num2)
assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
gcrootmap.add_callee_save_reg(shape, 1)
assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
@@ -181,51 +181,74 @@
p = rffi.cast(rffi.CArrayPtr(llmemory.Address), gcmapstart)
p = rffi.ptradd(p, 2*i)
return llmemory.cast_ptr_to_adr(p)
- saved = gc.asmgcroot
- try:
- gc.asmgcroot = Asmgcroot()
- #
- gcrootmap = GcRootMap_asmgcc()
- gcrootmap._gcmap = lltype.malloc(gcrootmap.GCMAP_ARRAY,
- 1400, flavor='raw',
- immortal=True)
- for i in range(700):
- gcrootmap._gcmap[i*2] = 1200000 + i
- gcrootmap._gcmap[i*2+1] = i * 100 + 1
- assert gcrootmap._gcmap_deadentries == 0
- assert gc.asmgcroot.sort_count == 0
- gcrootmap._gcmap_maxlength = 1400
- gcrootmap._gcmap_curlength = 1400
- gcrootmap._gcmap_sorted = False
- #
- gcrootmap.freeing_block(1200000 - 100, 1200000)
- assert gcrootmap._gcmap_deadentries == 0
- assert gc.asmgcroot.sort_count == 1
- #
- gcrootmap.freeing_block(1200000 + 100, 1200000 + 200)
- assert gcrootmap._gcmap_deadentries == 100
- assert gc.asmgcroot.sort_count == 1
- for i in range(700):
- if 100 <= i < 200:
- expected = 0
- else:
- expected = i * 100 + 1
- assert gcrootmap._gcmap[i*2] == 1200000 + i
- assert gcrootmap._gcmap[i*2+1] == expected
- #
- gcrootmap.freeing_block(1200000 + 650, 1200000 + 750)
- assert gcrootmap._gcmap_deadentries == 150
- assert gc.asmgcroot.sort_count == 1
- for i in range(700):
- if 100 <= i < 200 or 650 <= i:
- expected = 0
- else:
- expected = i * 100 + 1
- assert gcrootmap._gcmap[i*2] == 1200000 + i
- assert gcrootmap._gcmap[i*2+1] == expected
+ asmgcroot = Asmgcroot()
#
- finally:
- gc.asmgcroot = saved
+ gcrootmap = GcRootMap_asmgcc()
+ gcrootmap._gcmap = lltype.malloc(gcrootmap.GCMAP_ARRAY,
+ 1400, flavor='raw',
+ immortal=True)
+ for i in range(700):
+ gcrootmap._gcmap[i*2] = 1200000 + i
+ gcrootmap._gcmap[i*2+1] = i * 100 + 1
+ assert gcrootmap._gcmap_deadentries == 0
+ assert asmgcroot.sort_count == 0
+ gcrootmap._gcmap_maxlength = 1400
+ gcrootmap._gcmap_curlength = 1400
+ gcrootmap._gcmap_sorted = False
+ #
+ gcrootmap.freeing_block(1200000 - 100, 1200000, asmgcroot=asmgcroot)
+ assert gcrootmap._gcmap_deadentries == 0
+ assert asmgcroot.sort_count == 1
+ #
+ gcrootmap.freeing_block(1200000 + 100, 1200000 + 200,
+ asmgcroot=asmgcroot)
+ assert gcrootmap._gcmap_deadentries == 100
+ assert asmgcroot.sort_count == 1
+ for i in range(700):
+ if 100 <= i < 200:
+ expected = 0
+ else:
+ expected = i * 100 + 1
+ assert gcrootmap._gcmap[i*2] == 1200000 + i
+ assert gcrootmap._gcmap[i*2+1] == expected
+ #
+ gcrootmap.freeing_block(1200000 + 650, 1200000 + 750,
+ asmgcroot=asmgcroot)
+ assert gcrootmap._gcmap_deadentries == 150
+ assert asmgcroot.sort_count == 1
+ for i in range(700):
+ if 100 <= i < 200 or 650 <= i:
+ expected = 0
+ else:
+ expected = i * 100 + 1
+ assert gcrootmap._gcmap[i*2] == 1200000 + i
+ assert gcrootmap._gcmap[i*2+1] == expected
+
+class TestGcRootMapShadowStack:
+ class FakeGcDescr:
+ force_index_ofs = 92
+
+ def test_make_shapes(self):
+ gcrootmap = GcRootMap_shadowstack(self.FakeGcDescr())
+ shape = gcrootmap.get_basic_shape()
+ gcrootmap.add_frame_offset(shape, 16)
+ gcrootmap.add_frame_offset(shape, -24)
+ assert shape == [16, -24]
+
+ def test_compress_callshape(self):
+ class FakeDataBlockWrapper:
+ def malloc_aligned(self, size, alignment):
+ assert alignment == 4 # even on 64-bits
+ assert size == 12 # 4*3, even on 64-bits
+ return rffi.cast(lltype.Signed, p)
+ datablockwrapper = FakeDataBlockWrapper()
+ p = lltype.malloc(rffi.CArray(rffi.INT), 3, immortal=True)
+ gcrootmap = GcRootMap_shadowstack(self.FakeGcDescr())
+ shape = [16, -24]
+ gcrootmap.compress_callshape(shape, datablockwrapper)
+ assert rffi.cast(lltype.Signed, p[0]) == 16
+ assert rffi.cast(lltype.Signed, p[1]) == -24
+ assert rffi.cast(lltype.Signed, p[2]) == 0
class FakeLLOp(object):
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
@@ -1,5 +1,5 @@
-from pypy.jit.metainterp.history import Const, Box
+from pypy.jit.metainterp.history import Const, Box, REF
from pypy.rlib.objectmodel import we_are_translated
class TempBox(Box):
@@ -313,11 +313,12 @@
self.assembler.regalloc_mov(reg, to)
# otherwise it's clean
- def before_call(self, force_store=[], save_all_regs=False):
+ def before_call(self, force_store=[], save_all_regs=0):
""" Spill registers before a call, as described by
'self.save_around_call_regs'. Registers are not spilled if
they don't survive past the current operation, unless they
- are listed in 'force_store'.
+ are listed in 'force_store'. 'save_all_regs' can be 0 (default),
+ 1 (save all), or 2 (save default+PTRs).
"""
for v, reg in self.reg_bindings.items():
if v not in force_store and self.longevity[v][1] <= self.position:
@@ -325,9 +326,11 @@
del self.reg_bindings[v]
self.free_regs.append(reg)
continue
- if not save_all_regs and reg not in self.save_around_call_regs:
- # we don't have to
- continue
+ if save_all_regs != 1 and reg not in self.save_around_call_regs:
+ if save_all_regs == 0:
+ continue # we don't have to
+ if v.type != REF:
+ continue # only save GC pointers
self._sync_var(v)
del self.reg_bindings[v]
self.free_regs.append(reg)
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
@@ -317,8 +317,9 @@
return j
@rgc.no_collect
- def freeing_block(self, start, stop):
- from pypy.rpython.memory.gctransform import asmgcroot
+ def freeing_block(self, start, stop, asmgcroot=None):
+ if asmgcroot is None: # always the case, except for tests
+ 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.
@@ -441,9 +442,25 @@
return WORD
else:
# case of a MARKER followed by an assembler stack frame
- self.follow_stack_frame_of_assembler(callback, gc, addr)
+ follow_stack_frame_of_assembler(callback, gc, addr)
return 2 * WORD
#
+ def follow_stack_frame_of_assembler(callback, gc, addr):
+ frame_addr = addr.signed[1]
+ addr = llmemory.cast_int_to_adr(frame_addr + self.force_index_ofs)
+ force_index = addr.signed[0]
+ if force_index < 0:
+ force_index = ~force_index
+ callshape = self._callshapes[force_index]
+ n = 0
+ while True:
+ offset = rffi.cast(lltype.Signed, callshape[n])
+ if offset == 0:
+ break
+ addr = llmemory.cast_int_to_adr(frame_addr + offset)
+ callback(gc, addr)
+ n += 1
+ #
jit2gc.update({
'rootstackhook': collect_jit_stack_root,
})
@@ -451,22 +468,6 @@
def initialize(self):
pass
- def follow_stack_frame_of_assembler(self, callback, gc, addr):
- frame_addr = addr.signed[1]
- addr = llmemory.cast_int_to_adr(frame_addr + self.force_index_ofs)
- force_index = addr.signed[0]
- if force_index < 0:
- force_index = ~force_index
- callshape = self._callshapes[force_index]
- n = 0
- while True:
- offset = rffi.cast(lltype.Signed, callshape[n])
- if offset == 0:
- break
- addr = llmemory.cast_int_to_adr(frame_addr + offset)
- callback(gc, addr)
- n += 1
-
def get_basic_shape(self, is_64_bit=False):
return []
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
@@ -738,8 +738,12 @@
def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
save_all_regs = guard_not_forced_op is not None
+ self.xrm.before_call(force_store, save_all_regs=save_all_regs)
+ if not save_all_regs:
+ gcrootmap = gc_ll_descr = self.assembler.cpu.gc_ll_descr.gcrootmap
+ if gcrootmap and gcrootmap.is_shadow_stack:
+ save_all_regs = 2
self.rm.before_call(force_store, save_all_regs=save_all_regs)
- self.xrm.before_call(force_store, save_all_regs=save_all_regs)
if op.result is not None:
if op.result.type == FLOAT:
resloc = self.xrm.after_call(op.result)
More information about the Pypy-commit
mailing list