[pypy-commit] pypy stmgc-c7: in-progress
arigo
noreply at buildbot.pypy.org
Sat Mar 22 11:20:53 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r70158:005b73ce47d4
Date: 2014-03-22 11:20 +0100
http://bitbucket.org/pypy/pypy/changeset/005b73ce47d4/
Log: in-progress
diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -107,7 +107,8 @@
def rewrite_assembler(self, cpu, operations, gcrefs_output_list):
if not self.stm:
- from rpython.jit.backend.llsupport.rewrite import GcRewriterAssembler
+ from rpython.jit.backend.llsupport import rewrite
+ GcRewriterAssembler = rewrite.GcRewriterAssembler
else:
from rpython.jit.backend.llsupport import stmrewrite
GcRewriterAssembler = stmrewrite.GcStmRewriterAssembler
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -52,7 +52,6 @@
# barriers. We do this on each "basic block" of operations, which in
# this case means between CALLs or unknown-size mallocs.
#
- # SYNC with stmrewrite.py!
for op in operations:
if op.getopnum() == rop.DEBUG_MERGE_POINT:
continue
@@ -60,7 +59,7 @@
if op.is_malloc():
self.handle_malloc_operation(op)
continue
- elif op.is_call():
+ elif op.can_malloc():
self.emitting_an_operation_that_can_collect()
elif op.getopnum() == rop.LABEL:
self.emitting_an_operation_that_can_collect()
@@ -80,10 +79,13 @@
if op.getopnum() == rop.CALL_ASSEMBLER:
self.handle_call_assembler(op)
continue
- #
- self.newops.append(op)
+ # ---------- fallback case (overwritten in stmrewrite) -----------
+ self.other_operation(op)
return self.newops
+ def other_operation(self, op):
+ self.newops.append(op)
+
# ----------
def handle_malloc_operation(self, op):
@@ -158,8 +160,7 @@
else:
raise NotImplementedError(op.getopname())
- def gen_malloc_frame(self, frame_info, frame):
- size_box = history.BoxInt()
+ def gen_malloc_frame(self, frame_info, frame, size_box):
descrs = self.gc_ll_descr.getframedescrs(self.cpu)
if self.gc_ll_descr.kind == 'boehm' or self.gc_ll_descr.stm:
op0 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)],
@@ -176,8 +177,8 @@
size_box,
descr=descrs.jfi_frame_size)
self.newops.append(op0)
- self.gen_malloc_nursery_varsize_frame(size_box, frame,
- descrs.arraydescr.tid)
+ self.gen_malloc_nursery_varsize_frame(size_box, frame)
+ self.gen_initialize_tid(frame, descrs.arraydescr.tid)
length_box = history.BoxInt()
op1 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)],
length_box,
@@ -192,8 +193,9 @@
assert isinstance(loop_token, history.JitCellToken)
jfi = loop_token.compiled_loop_token.frame_info
llfi = heaptracker.adr2int(llmemory.cast_ptr_to_adr(jfi))
+ size_box = history.BoxInt()
frame = history.BoxPtr()
- self.gen_malloc_frame(llfi, frame)
+ self.gen_malloc_frame(llfi, frame, size_box)
op2 = ResOperation(rop.SETFIELD_GC, [frame, history.ConstInt(llfi)],
None, descr=descrs.jf_frame_info)
self.newops.append(op2)
@@ -322,7 +324,7 @@
self.write_barrier_applied[v_result] = None
return True
- def gen_malloc_nursery_varsize_frame(self, sizebox, v_result, tid):
+ def gen_malloc_nursery_varsize_frame(self, sizebox, v_result):
""" Generate CALL_MALLOC_NURSERY_VARSIZE_FRAME
"""
self.emitting_an_operation_that_can_collect()
@@ -333,8 +335,6 @@
self.newops.append(op)
self.write_barrier_applied[v_result] = None
- self.gen_initialize_tid(v_result, tid)
-
def gen_malloc_nursery(self, size, v_result):
"""Try to generate or update a CALL_MALLOC_NURSERY.
If that fails, generate a plain CALL_MALLOC_GC instead.
@@ -392,8 +392,8 @@
v = op.getarg(1)
if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
bool(v.value)): # store a non-NULL
- op = self.prepare_write_barrier(op, rop.SETFIELD_RAW)
- self.gen_write_barrier(op.getarg(0))
+ self.gen_write_barrier(val)
+ #op = op.copy_and_change(rop.SETFIELD_RAW)
self.newops.append(op)
def handle_write_barrier_setinteriorfield(self, op):
@@ -402,8 +402,8 @@
v = op.getarg(2)
if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
bool(v.value)): # store a non-NULL
- op = self.prepare_write_barrier(op, rop.SETINTERIORFIELD_RAW)
- self.gen_write_barrier(op.getarg(0))
+ self.gen_write_barrier(val)
+ #op = op.copy_and_change(rop.SETINTERIORFIELD_RAW)
self.newops.append(op)
def handle_write_barrier_setarrayitem(self, op):
@@ -412,22 +412,10 @@
v = op.getarg(2)
if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
bool(v.value)): # store a non-NULL
- op = self.prepare_write_barrier(op, rop.SETARRAYITEM_RAW)
- self.gen_write_barrier_array(op.getarg(0),
- op.getarg(1))
+ self.gen_write_barrier_array(val, op.getarg(1))
+ #op = op.copy_and_change(rop.SETARRAYITEM_RAW)
self.newops.append(op)
- def prepare_write_barrier(self, op, newopnum):
- write_barrier_descr = self.gc_ll_descr.write_barrier_descr
- if (write_barrier_descr.returns_modified_object and
- isinstance(op.getarg(0), ConstPtr)):
- args = op.getarglist()
- v_box = BoxPtr()
- self.newops.append(ResOperation(rop.SAME_AS, [args[0]], v_box))
- args[0] = v_box
- return op.copy_and_change(opnum=newopnum, args=args)
- return op
-
def gen_write_barrier(self, v_base):
write_barrier_descr = self.gc_ll_descr.write_barrier_descr
args = [v_base]
@@ -437,11 +425,10 @@
def gen_write_barrier_array(self, v_base, v_index):
write_barrier_descr = self.gc_ll_descr.write_barrier_descr
- if write_barrier_descr.has_barrier_from_array(self.cpu):
+ if write_barrier_descr.has_write_barrier_from_array(self.cpu):
# If we know statically the length of 'v', and it is not too
# big, then produce a regular write_barrier. If it's unknown or
# too big, produce instead a write_barrier_from_array.
- assert not write_barrier_descr.returns_modified_object
LARGE = 130
length = self.known_lengths.get(v_base, LARGE)
if length >= LARGE:
diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py
--- a/rpython/jit/backend/llsupport/stmrewrite.py
+++ b/rpython/jit/backend/llsupport/stmrewrite.py
@@ -9,32 +9,6 @@
debug_print)
from rpython.jit.codewriter.effectinfo import EffectInfo
-### XXX:
-### we changed some 'x2I' barriers to 'x2R' since
-### obj initialization may happen in 2 different transactions.
-### check and fix this assumption
-
-
-#
-# 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_STM_B(p1, descr=x2Wdescr), for x in 'AIQRVWZ'. This
-# COND_CALL_STM_B 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,
@@ -42,143 +16,83 @@
def __init__(self, *args):
GcRewriterAssembler.__init__(self, *args)
- self.known_category = {} # variable: letter (R, W, ...)
self.always_inevitable = False
-
- def rewrite(self, operations):
- debug_start("jit-stmrewrite-ops")
- # overridden method from parent class
- #
- for op in operations:
- opnum = op.getopnum()
- if not we_are_translated():
- # only possible in tests:
- if opnum in (rop.COND_CALL_STM_B,
- -124): # FORCE_SPILL
+ def other_operation(self, op):
+ opnum = op.getopnum()
+ if opnum == rop.INCREMENT_DEBUG_COUNTER:
+ self.newops.append(op)
+ return
+ # ---------- transaction breaks ----------
+ if opnum == rop.STM_TRANSACTION_BREAK:
+ # XXX redo!
+ #self.emitting_an_operation_that_can_collect()
+ #self.next_op_may_be_in_new_transaction()
+ #self.newops.append(op)
+ return
+ # ---------- pure operations, guards ----------
+ if op.is_always_pure() or op.is_guard() or op.is_ovf():
+ self.newops.append(op)
+ return
+ # ---------- non-pure getfields ----------
+ if opnum in (rop.GETFIELD_GC, rop.GETARRAYITEM_GC,
+ rop.GETINTERIORFIELD_GC):
+ self.handle_getfields(op)
+ return
+ # ---------- calls ----------
+ if op.is_call():
+ if opnum == rop.CALL_RELEASE_GIL:
+ # self.fallback_inevitable(op)
+ # is done by assembler._release_gil_shadowstack()
+ self.newops.append(op)
+ elif opnum == rop.CALL_ASSEMBLER:
+ assert 0 # case handled by the parent class
+ else:
+ # only insert become_inevitable if calling a
+ # non-transactionsafe and non-releasegil function
+ descr = op.getdescr()
+ assert not descr or isinstance(descr, CallDescr)
+
+ if not descr or not descr.get_extra_info() \
+ or descr.get_extra_info().call_needs_inevitable():
+ self.fallback_inevitable(op)
+ else:
self.newops.append(op)
- continue
- if opnum in (rop.INCREMENT_DEBUG_COUNTER,
- rop.DEBUG_MERGE_POINT):
- self.newops.append(op)
+ return
+ # ---------- copystrcontent ----------
+ if opnum in (rop.COPYSTRCONTENT, rop.COPYUNICODECONTENT):
+ self.handle_copystrcontent(op)
+ continue
+ XXX
+ # ---------- raw getfields and setfields ----------
+ if opnum in (rop.GETFIELD_RAW, rop.SETFIELD_RAW):
+ if self.maybe_handle_raw_accesses(op):
continue
- # ---------- transaction breaks ----------
- if opnum == rop.STM_TRANSACTION_BREAK:
- self.emitting_an_operation_that_can_collect()
- self.next_op_may_be_in_new_transaction()
- self.newops.append(op)
- continue
- # ---------- ptr_eq ----------
- if opnum in (rop.PTR_EQ, rop.INSTANCE_PTR_EQ,
- rop.PTR_NE, rop.INSTANCE_PTR_NE):
- self.newops.append(op)
- continue
- # ---------- guard_class ----------
- if opnum == rop.GUARD_CLASS:
- assert self.cpu.vtable_offset is None
- # requires gcremovetypeptr translation option
- # uses h_tid which doesn't need a read-barrier
- self.newops.append(op)
- continue
- # ---------- pure operations needing read-barrier ----------
- if opnum in (rop.GETFIELD_GC_PURE,
- rop.GETARRAYITEM_GC_PURE,
- rop.ARRAYLEN_GC, rop.STRGETITEM,
- rop.UNICODEGETITEM, rop.STRLEN,
- rop.UNICODELEN):
- # e.g. getting inst_intval of a W_IntObject that is
- # currently only a stub needs to first resolve to a
- # real object
- # XXX: 'I' enough?
- self.handle_category_operations(op, 'R')
- continue
- # ---------- pure operations, guards ----------
- if op.is_always_pure() or op.is_guard() or op.is_ovf():
- self.newops.append(op)
- continue
- # ---------- getfields ----------
- if opnum in (rop.GETFIELD_GC, rop.GETARRAYITEM_GC,
- rop.GETINTERIORFIELD_GC):
- self.handle_getfields(op)
- continue
- # ---------- setfields ----------
- if opnum in (rop.SETFIELD_GC, rop.SETINTERIORFIELD_GC,
- rop.SETARRAYITEM_GC, rop.STRSETITEM,
- rop.UNICODESETITEM):
- self.handle_setfields(op)
- continue
- # ---------- mallocs ----------
- if op.is_malloc():
- self.handle_malloc_operation(op)
- continue
- # ---------- calls ----------
- if op.is_call():
- if opnum == rop.CALL and op.getdescr():
- d = op.getdescr()
- assert isinstance(d, CallDescr)
- ei = d.get_extra_info()
- if ei and ei.oopspecindex == EffectInfo.OS_JIT_STM_SHOULD_BREAK_TRANSACTION:
- self.newops.append(op)
- continue
-
- self.emitting_an_operation_that_can_collect()
- self.next_op_may_be_in_new_transaction()
-
- if opnum == rop.CALL_RELEASE_GIL:
- # self.fallback_inevitable(op)
- # is done by assembler._release_gil_shadowstack()
- self.newops.append(op)
- elif opnum == rop.CALL_ASSEMBLER:
- self.handle_call_assembler(op)
- else:
- # only insert become_inevitable if calling a
- # non-transactionsafe and non-releasegil function
- descr = op.getdescr()
- assert not descr or isinstance(descr, CallDescr)
-
- if not descr or not descr.get_extra_info() \
- or descr.get_extra_info().call_needs_inevitable():
- self.fallback_inevitable(op)
- else:
- self.newops.append(op)
- continue
- # ---------- copystrcontent ----------
- if opnum in (rop.COPYSTRCONTENT, rop.COPYUNICODECONTENT):
- self.handle_copystrcontent(op)
- continue
- # ---------- raw getfields and setfields ----------
- if opnum in (rop.GETFIELD_RAW, rop.SETFIELD_RAW):
- if self.maybe_handle_raw_accesses(op):
- continue
- # ---------- labels ----------
- if opnum == rop.LABEL:
- self.emitting_an_operation_that_can_collect()
- self.next_op_may_be_in_new_transaction()
-
- self.newops.append(op)
- continue
- # ---------- jumps ----------
- if opnum == rop.JUMP:
- self.newops.append(op)
- continue
- # ---------- finish, other ignored ops ----------
- if opnum in (rop.FINISH, rop.FORCE_TOKEN,
- rop.READ_TIMESTAMP, rop.MARK_OPAQUE_PTR,
- rop.JIT_DEBUG, rop.KEEPALIVE,
- rop.QUASIIMMUT_FIELD, rop.RECORD_KNOWN_CLASS,
- ):
- self.newops.append(op)
- continue
- # ---------- fall-back ----------
- # Check that none of the ops handled here can_collect
- # or cause a transaction break. This is not done by
- # the fallback here
- self.fallback_inevitable(op)
- debug_print("fallback for", op.repr())
- #
-
- debug_stop("jit-stmrewrite-ops")
- return self.newops
+ # ---------- labels ----------
+ if opnum == rop.LABEL:
+ self.emitting_an_operation_that_can_collect()
+ self.next_op_may_be_in_new_transaction()
+
+ self.newops.append(op)
+ continue
+ # ---------- jumps ----------
+ if opnum == rop.JUMP:
+ self.newops.append(op)
+ continue
+ # ---------- finish, other ignored ops ----------
+ if opnum in (rop.FINISH, rop.FORCE_TOKEN,
+ rop.READ_TIMESTAMP, rop.MARK_OPAQUE_PTR,
+ rop.JIT_DEBUG, rop.KEEPALIVE,
+ rop.QUASIIMMUT_FIELD, rop.RECORD_KNOWN_CLASS,
+ ):
+ self.newops.append(op)
+ continue
+ # ---------- fall-back ----------
+ # Check that none of the ops handled here can_collect
+ # or cause a transaction break. This is not done by
+ # the fallback here
+ self.fallback_inevitable(op)
+ debug_print("fallback for", op.repr())
def emitting_an_operation_that_can_collect(self):
GcRewriterAssembler.emitting_an_operation_that_can_collect(self)
More information about the pypy-commit
mailing list