[pypy-commit] pypy stm-thread-2: in-progress: fixing the JIT
arigo
noreply at buildbot.pypy.org
Tue Sep 11 14:35:39 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread-2
Changeset: r57274:31237d8ba2d4
Date: 2012-09-11 14:01 +0200
http://bitbucket.org/pypy/pypy/changeset/31237d8ba2d4/
Log: in-progress: fixing the JIT
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
@@ -583,9 +583,10 @@
class WriteBarrierDescr(AbstractDescr):
- def __init__(self, gc_ll_descr):
+ def __init__(self, gc_ll_descr, stmcat=None):
self.llop1 = gc_ll_descr.llop1
- self.returns_modified_object = gc_ll_descr.stm
+ self.stmcat = stmcat
+ self.returns_modified_object = (stmcat is not None)
if not self.returns_modified_object:
self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
[llmemory.Address], lltype.Void))
@@ -597,7 +598,10 @@
GCClass = gc_ll_descr.GCClass
if GCClass is None: # for tests
return
- self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG
+ if self.stmcat is None:
+ self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG
+ else:
+ self.jit_wb_if_flag, cat = self.stmcat
self.jit_wb_if_flag_byteofs, self.jit_wb_if_flag_singlebyte = (
self.extract_flag_byte(self.jit_wb_if_flag))
#
@@ -614,9 +618,21 @@
else:
self.jit_wb_cards_set = 0
+ def repr_of_descr(self):
+ if self.stmcat is None:
+ return 'wbdescr'
+ else:
+ _, cat = self.stmcat
+ return cat
+
+ def __repr__(self):
+ return '<WriteBarrierDescr %r>' % (self.repr_of_descr(),)
+
def extract_flag_byte(self, flag_word):
# if convenient for the backend, we compute the info about
# the flag as (byte-offset, single-byte-flag).
+ if flag_word == 0:
+ return (0, 0)
import struct
value = struct.pack(lltype.SignedFmt, flag_word)
assert value.count('\x00') == len(value) - 1 # only one byte is != 0
@@ -624,16 +640,20 @@
while value[i] == '\x00': i += 1
return (i, struct.unpack('b', value[i])[0])
- def get_write_barrier_fn(self, cpu, returns_modified_object=False):
- # must pass in 'self.returns_modified_object', to make sure that
+ def get_write_barrier_fn(self, cpu, stm=False):
+ # must pass in 'self.stm', to make sure that
# the callers are fixed for this case
- assert returns_modified_object == self.returns_modified_object
- if returns_modified_object:
+ assert stm == self.returns_modified_object
+ llop1 = self.llop1
+ if self.returns_modified_object:
FUNCTYPE = self.WB_FUNCPTR_MOD
+ _, cat = self.stmcat
+ assert cat(stm) == 3 and cat[1] == '2' # "x2y"
+ funcptr = llop1.get_write_barrier_failing_case(FUNCTYPE,
+ cat[0], cat[2])
else:
FUNCTYPE = self.WB_FUNCPTR
- llop1 = self.llop1
- funcptr = llop1.get_write_barrier_failing_case(FUNCTYPE)
+ funcptr = llop1.get_write_barrier_failing_case(FUNCTYPE)
funcaddr = llmemory.cast_ptr_to_adr(funcptr)
return cpu.cast_adr_to_int(funcaddr)
@@ -735,7 +755,13 @@
self.fielddescr_tid = get_field_descr(self, self.GCClass.HDR, 'tid')
def _setup_write_barrier(self):
- self.write_barrier_descr = WriteBarrierDescr(self)
+ if self.stm:
+ from pypy.rpython.memory.gc import stmgc
+ self.P2Wdescr = WriteBarrierDescr(self,
+ (stmgc.GCFLAG_NOT_WRITTEN, 'P2W'))
+ self.write_barrier_descr = "wbdescr: do not use"
+ else:
+ self.write_barrier_descr = WriteBarrierDescr(self)
def _make_functions(self, really_not_translated):
from pypy.rpython.memory.gctypelayout import check_typeid
diff --git a/pypy/jit/backend/llsupport/stm.txt b/pypy/jit/backend/llsupport/stm.txt
deleted file mode 100644
--- a/pypy/jit/backend/llsupport/stm.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-stm support
------------
-
-Any SETFIELD_GC, SETARRAYITEM_GC, SETINTERIORFIELD_GC must be done on a
-local object. The operation that forces an object p1 to be local is
-COND_CALL_GC_WB(p1, 0, descr=wbdescr). When we have stm, this
-COND_CALL_GC_WB is a bit special because if p1 is global, it *replaces*
-its value with the local copy (by changing the register's value and
-patching the stack location if any). It's still conceptually the same
-object, but the pointer is different.
-
-GETFIELD_GC & friends are more complex.
-
-The fast case is if we also see a write to the same object. In this
-case we know that the object will have a local copy anyway, even if the
-write is done after the read (we ignore the rare case that a guard may
-fail inbetween). So in this case we use the same rule as for
-SETFIELD_GC.
-
-The slow case is where we need to read the global object in-place.
-We insert STM_READ_BEFORE() before and STM_READ_AFTER() after, and
-between these two operations there can be only (one or several) reads
-from one object: GETFIELD_GC, GETARRAYITEM_GC, GETINTERIORFIELD_GC,
-COPYSTRCONTENT, COPYUNICODECONTENT. We need to be careful here because
-STM_READ_AFTER might jump back to STM_READ_BEFORE. So we must somehow
-precompute how many spills we will need to do, and do them before
-entering the STM_READ_BEFORE. As a first approximation, we can ensure
-that all registers are spilled before STM_READ_BEFORE.
-
-STM_READ_BEFORE():
-
- - if (p->flags & GCFLAG_GLOBAL == 0), ovt = p->version
-
- - else ovt = (call a helper function "ll_stm_read_before")
-
-ll_stm_read_before():
-
- - if ((p->flags & GCFLAG_WAS_COPIED) != 0 && local_copy_exists(p))
- replace p with its local copy in the caller (register and stack)
- return p->version
-
- - load the thread-local global d = thread_descriptor
-
- - ovt = p->version
-
- - if (ovt is locked or newer than d->start_time)
- call handle_spinloop_or_validation(ovt)
- jump back to reading 'ovt' above
-
- - if (!is_inevitable(d))
- oreclist_insert_if_not_already(d->reads, p)
-
- - return ovt
-
-STM_READ_AFTER():
-
- - if (p->version != ovt)
- jump back to STM_READ_BEFORE
diff --git a/pypy/jit/backend/llsupport/stmrewrite.py b/pypy/jit/backend/llsupport/stmrewrite.py
--- a/pypy/jit/backend/llsupport/stmrewrite.py
+++ b/pypy/jit/backend/llsupport/stmrewrite.py
@@ -2,6 +2,24 @@
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.metainterp.history import BoxPtr, ConstPtr, ConstInt
+#
+# STM Support
+# -----------
+#
+# Any SETFIELD_GC, SETARRAYITEM_GC, SETINTERIORFIELD_GC must be done on a
+# W object. The operation that forces an object p1 to be W is
+# COND_CALL_GC_WB(p1, 0, descr=x2Wdescr), for x in 'PGORL'. This
+# COND_CALL_GC_WB is a bit special because if p1 is not W, it *replaces*
+# its value with the W copy (by changing the register's value and
+# patching the stack location if any). It's still conceptually the same
+# object, but the pointer is different.
+#
+# The case of GETFIELD_GC & friends is similar, excepted that it goes to
+# a R or L object (at first, always a R object).
+#
+# The name "x2y" of write barriers is called the *category* or "cat".
+#
+
class GcStmRewriterAssembler(GcRewriterAssembler):
# This class performs the same rewrites as its base class,
@@ -76,12 +94,12 @@
return self.newops
- def gen_write_barrier(self, v_base):
+ def gen_write_barrier(self, v_base, cat):
v_base = self.unconstifyptr(v_base)
assert isinstance(v_base, BoxPtr)
if v_base in self.known_local:
return v_base # no write barrier needed
- write_barrier_descr = self.gc_ll_descr.write_barrier_descr
+ write_barrier_descr = getattr(self.gc_ll_descr, '%sdescr' % (cat,))
args = [v_base, self.c_zero]
self.newops.append(ResOperation(rop.COND_CALL_GC_WB, args, None,
descr=write_barrier_descr))
@@ -99,7 +117,7 @@
def handle_setfield_operations(self, op):
lst = op.getarglist()
- lst[0] = self.gen_write_barrier(lst[0])
+ lst[0] = self.gen_write_barrier(lst[0], 'P2W')
self.newops.append(op.copy_and_change(op.getopnum(), args=lst))
def handle_malloc_operation(self, op):
diff --git a/pypy/jit/backend/llsupport/test/test_stmrewrite.py b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
--- a/pypy/jit/backend/llsupport/test/test_stmrewrite.py
+++ b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
@@ -29,6 +29,7 @@
" descr=stm_try_inevitable_descr)")
frm_operations = frm_operations.replace('$INEV', inev)
to_operations = to_operations .replace('$INEV', inev)
+ namespace['P2Wdescr'] = self.gc_ll_descr.P2Wdescr
RewriteTests.check_rewrite(self, frm_operations, to_operations,
**namespace)
@@ -39,7 +40,7 @@
jump()
""", """
[p1, p2]
- cond_call_gc_wb(p1, 0, descr=wbdescr)
+ cond_call_gc_wb(p1, 0, descr=P2Wdescr)
setfield_gc(p1, p2, descr=tzdescr)
jump()
""")
diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -232,8 +232,6 @@
def JIT_minimal_size_in_nursery():
return 0
- JIT_WB_IF_FLAG = GCFLAG_GLOBAL
-
# ----------
def malloc_fixedsize_clear(self, typeid, size,
More information about the pypy-commit
mailing list