Author: Armin Rigo <[email protected]>
Branch: stmgc-c7
Changeset: r75427:dd8bd6ba13a9
Date: 2015-01-18 16:03 +0100
http://bitbucket.org/pypy/pypy/changeset/dd8bd6ba13a9/
Log: Try harder to preserve the stm_location
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -143,6 +143,8 @@
------------------------------------------------------------
+stm_read(p125)
+cond_call_gc_wb_array(p125...) # don't need the stm_read maybe?
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
@@ -145,8 +145,9 @@
if op.is_guard() or op.getopnum() == rop.FINISH:
# the only ops with descrs that get recorded in a trace
llref = cast_instance_to_gcref(op.getdescr())
- assert rgc._make_sure_does_not_move(llref)
- gcrefs_output_list.append(llref)
+ if llref:
+ assert rgc._make_sure_does_not_move(llref)
+ gcrefs_output_list.append(llref)
#
if len(ops_with_movable_const_ptr[op]) == 0:
del ops_with_movable_const_ptr[op]
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
@@ -38,6 +38,7 @@
_previous_size = -1
_op_malloc_nursery = None
_v_last_malloced_nursery = None
+ stm_location = None
# does_any_alloc tells us if we did any allocation since the last LABEL
does_any_allocation = False
@@ -63,6 +64,8 @@
#
for i in range(len(operations)):
op = operations[i]
+ if op.stm_location is not None:
+ self.stm_location = op.stm_location
if op.getopnum() == rop.DEBUG_MERGE_POINT:
continue
# ---------- turn NEWxxx into CALL_MALLOC_xxx ----------
@@ -110,6 +113,10 @@
return self.newops
def other_operation(self, op):
+ self.newop(op)
+
+ def newop(self, op):
+ op.stm_location = self.stm_location
self.newops.append(op)
def could_merge_with_next_guard(self, op, i, operations):
@@ -142,7 +149,7 @@
op = ResOperation(rop.SETFIELD_GC,
[op.result, ConstInt(classint)], None,
descr=self.gc_ll_descr.fielddescr_vtable)
- self.newops.append(op)
+ self.newop(op)
elif opnum == rop.NEW_ARRAY or opnum == rop.NEW_ARRAY_CLEAR:
descr = op.getdescr()
assert isinstance(descr, ArrayDescr)
@@ -202,7 +209,7 @@
return
op = ResOperation(rop.SETFIELD_GC, [result, self.c_zero], None,
descr=hash_descr)
- self.newops.append(op)
+ self.newop(op)
def handle_new_fixedsize(self, descr, op):
assert isinstance(descr, SizeDescr)
@@ -264,7 +271,7 @@
# See emit_pending_zeros().
o = ResOperation(rop.ZERO_ARRAY, [v_arr, self.c_zero, v_length], None,
descr=arraydescr)
- self.newops.append(o)
+ self.newop(o)
if isinstance(v_length, ConstInt):
self.last_zero_arrays.append(o)
@@ -276,7 +283,7 @@
op0 = ResOperation(rop.GETFIELD_RAW,
[history.ConstInt(frame_info)],
size_box,
descr=descrs.jfi_frame_depth)
- self.newops.append(op0)
+ self.newop(op0)
op1 = ResOperation(rop.NEW_ARRAY, [size_box], frame,
descr=descrs.arraydescr)
self.handle_new_array(descrs.arraydescr, op1)
@@ -286,7 +293,7 @@
op0 = ResOperation(rop.GETFIELD_RAW,
[history.ConstInt(frame_info)],
size_box,
descr=descrs.jfi_frame_size)
- self.newops.append(op0)
+ self.newop(op0)
self.gen_malloc_nursery_varsize_frame(size_box, frame)
self.gen_initialize_tid(frame, descrs.arraydescr.tid)
length_box = history.BoxInt()
@@ -308,7 +315,8 @@
ResOperation(rop.SETFIELD_GC, [frame, self.c_null],
None, descr=descrs.jf_forward),
]
- self.newops += extra_ops
+ for extra_op in extra_ops:
+ self.newop(extra_op)
self.gen_initialize_len(frame, length_box,
descrs.arraydescr.lendescr)
else:
@@ -317,7 +325,7 @@
op0 = ResOperation(rop.GETFIELD_RAW,[history.ConstInt(frame_info)],
length_box,
descr=descrs.jfi_frame_depth)
- self.newops.append(op0)
+ self.newop(op0)
self.gen_malloc_nursery_varsize_frame(length_box, frame)
self.gen_initialize_tid(frame, descrs.arraydescr.tid)
self.gen_initialize_len(frame, length_box,
@@ -333,7 +341,7 @@
self.gen_malloc_frame(llfi, frame)
op2 = ResOperation(rop.SETFIELD_GC, [frame, history.ConstInt(llfi)],
None, descr=descrs.jf_frame_info)
- self.newops.append(op2)
+ self.newop(op2)
arglist = op.getarglist()
index_list = loop_token.compiled_loop_token._ll_initial_locs
for i, arg in enumerate(arglist):
@@ -341,7 +349,7 @@
assert self.cpu.JITFRAME_FIXED_SIZE & 1 == 0
_, itemsize, _ = self.cpu.unpack_arraydescr_size(descr)
index = index_list[i] // itemsize # index is in bytes
- self.newops.append(ResOperation(rop.SETARRAYITEM_GC,
+ self.newop(ResOperation(rop.SETARRAYITEM_GC,
[frame, ConstInt(index),
arg],
None, descr))
@@ -355,8 +363,7 @@
args = [frame]
op1 = ResOperation(rop.CALL_ASSEMBLER, args,
op.result, op.getdescr())
- op1.stm_location = op.stm_location
- self.newops.append(op1)
+ self.newop(op1)
# ----------
@@ -399,14 +406,14 @@
for v, d in self.delayed_zero_setfields.iteritems():
for ofs in d.iterkeys():
op = ResOperation(rop.ZERO_PTR_FIELD, [v, ConstInt(ofs)], None)
- self.newops.append(op)
+ self.newop(op)
self.delayed_zero_setfields.clear()
def _gen_call_malloc_gc(self, args, v_result, descr):
"""Generate a CALL_MALLOC_GC with the given args."""
self.emitting_an_operation_that_can_collect()
op = ResOperation(rop.CALL_MALLOC_GC, args, v_result, descr)
- self.newops.append(op)
+ self.newop(op)
# In general, don't add v_result to write_barrier_applied:
# v_result might be a large young array.
@@ -493,7 +500,7 @@
op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE,
[ConstInt(kind), ConstInt(itemsize), v_length],
v_result, descr=arraydescr)
- self.newops.append(op)
+ self.newop(op)
# don't record v_result into self.write_barrier_applied:
# it can be a large, young array with card marking, and then
# the GC relies on the write barrier being called
@@ -507,7 +514,7 @@
[sizebox], # if STM, this is actually lengthbox!
v_result)
- self.newops.append(op)
+ self.newop(op)
self.write_barrier_applied[v_result] = None
def gen_malloc_nursery(self, size, v_result):
@@ -539,7 +546,7 @@
v_result)
self._op_malloc_nursery = op
#
- self.newops.append(op)
+ self.newop(op)
self._previous_size = size
self._v_last_malloced_nursery = v_result
self.write_barrier_applied[v_result] = None
@@ -551,14 +558,14 @@
op = ResOperation(rop.SETFIELD_GC,
[v_newgcobj, ConstInt(tid)], None,
descr=self.gc_ll_descr.fielddescr_tid)
- self.newops.append(op)
+ self.newop(op)
def gen_initialize_len(self, v_newgcobj, v_length, arraylen_descr):
# produce a SETFIELD to initialize the array length
op = ResOperation(rop.SETFIELD_GC,
[v_newgcobj, v_length], None,
descr=arraylen_descr)
- self.newops.append(op)
+ self.newop(op)
# ----------
@@ -572,27 +579,26 @@
def handle_write_barrier_setfield(self, op):
val = op.getarg(0)
if self.must_apply_write_barrier(val, op.getarg(1)):
- self.gen_write_barrier(val, op.stm_location)
- self.newops.append(op)
+ self.gen_write_barrier(val)
+ self.newop(op)
def handle_write_barrier_setarrayitem(self, op):
val = op.getarg(0)
if self.must_apply_write_barrier(val, op.getarg(2)):
- self.gen_write_barrier_array(val, op.getarg(1), op.stm_location)
- self.newops.append(op)
+ self.gen_write_barrier_array(val, op.getarg(1))
+ self.newop(op)
handle_write_barrier_setinteriorfield = handle_write_barrier_setarrayitem
- def gen_write_barrier(self, v_base, stm_location):
+ def gen_write_barrier(self, v_base):
write_barrier_descr = self.gc_ll_descr.write_barrier_descr
args = [v_base]
op = ResOperation(rop.COND_CALL_GC_WB, args, None,
descr=write_barrier_descr)
- op.stm_location = stm_location
- self.newops.append(op)
+ self.newop(op)
self.write_barrier_applied[v_base] = None
- def gen_write_barrier_array(self, v_base, v_index, stm_location):
+ 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_write_barrier_from_array(self.cpu):
# If we know statically the length of 'v', and it is not too
@@ -605,13 +611,12 @@
args = [v_base, v_index]
op = ResOperation(rop.COND_CALL_GC_WB_ARRAY, args, None,
descr=write_barrier_descr)
- op.stm_location = stm_location
- self.newops.append(op)
+ self.newop(op)
# a WB_ARRAY is not enough to prevent any future write
# barriers, so don't add to 'write_barrier_applied'!
return
# fall-back case: produce a write_barrier
- self.gen_write_barrier(v_base, stm_location)
+ self.gen_write_barrier(v_base)
def round_up_for_allocation(self, size):
if not self.gc_ll_descr.round_up:
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
@@ -20,22 +20,21 @@
def other_operation(self, op):
opnum = op.getopnum()
if opnum == rop.INCREMENT_DEBUG_COUNTER:
- self.newops.append(op)
+ self.newop(op)
return
# ---------- transaction breaks ----------
if opnum == rop.STM_HINT_COMMIT_SOON:
- self._do_stm_call('stm_hint_commit_soon', [], None,
- op.stm_location)
+ self._do_stm_call('stm_hint_commit_soon', [], None)
return
# ---------- jump, finish, guard_not_forced_2 ----------
if (opnum == rop.JUMP or opnum == rop.FINISH
or opnum == rop.GUARD_NOT_FORCED_2):
self.add_dummy_allocation()
- self.newops.append(op)
+ self.newop(op)
return
# ---------- pure operations, guards ----------
if op.is_always_pure() or op.is_guard() or op.is_ovf():
- self.newops.append(op)
+ self.newop(op)
return
# ---------- non-pure getfields ----------
if opnum in (rop.GETFIELD_GC, rop.GETARRAYITEM_GC,
@@ -49,7 +48,7 @@
if opnum == rop.CALL_RELEASE_GIL:
# self.fallback_inevitable(op)
# is done by assembler._release_gil_shadowstack()
- self.newops.append(op)
+ self.newop(op)
elif opnum == rop.CALL_ASSEMBLER:
assert 0 # case handled by the parent class
else:
@@ -62,7 +61,7 @@
or descr.get_extra_info().call_needs_inevitable():
self.fallback_inevitable(op)
else:
- self.newops.append(op)
+ self.newop(op)
return
# ---------- setters for pure fields ----------
if opnum in (rop.STRSETITEM, rop.UNICODESETITEM):
@@ -80,7 +79,7 @@
if opnum == rop.LABEL:
# note that the parent class also clears some things on a LABEL
self.next_op_may_be_in_new_transaction()
- self.newops.append(op)
+ self.newop(op)
return
# ---------- other ignored ops ----------
if opnum in (rop.STM_SHOULD_BREAK_TRANSACTION, rop.FORCE_TOKEN,
@@ -88,7 +87,7 @@
rop.JIT_DEBUG, rop.KEEPALIVE,
rop.QUASIIMMUT_FIELD, rop.RECORD_KNOWN_CLASS,
):
- self.newops.append(op)
+ self.newop(op)
return
# ---------- fall-back ----------
# Check that none of the ops handled here can collect.
@@ -112,12 +111,12 @@
# group together several stm_reads then we can save one
# instruction; if delayed over a cond_call_gc_wb then we can
# omit the stm_read completely; ...
- self.newops.append(op)
+ self.newop(op)
v_ptr = op.getarg(0)
if (v_ptr not in self.read_barrier_applied and
v_ptr not in self.write_barrier_applied):
op1 = ResOperation(rop.STM_READ, [v_ptr], None)
- self.newops.append(op1)
+ self.newop(op1)
self.read_barrier_applied[v_ptr] = None
def add_dummy_allocation(self):
@@ -137,33 +136,31 @@
@specialize.arg(1)
- def _do_stm_call(self, funcname, args, result, stm_location):
+ def _do_stm_call(self, funcname, args, result):
addr = self.gc_ll_descr.get_malloc_fn_addr(funcname)
descr = getattr(self.gc_ll_descr, funcname + '_descr')
op1 = ResOperation(rop.CALL, [ConstInt(addr)] + args,
result, descr=descr)
- op1.stm_location = stm_location
- self.newops.append(op1)
+ self.newop(op1)
def fallback_inevitable(self, op):
if not self.always_inevitable:
self.emitting_an_operation_that_can_collect()
- self._do_stm_call('stm_try_inevitable', [], None,
- op.stm_location)
+ self._do_stm_call('stm_try_inevitable', [], None)
self.always_inevitable = True
- self.newops.append(op)
+ self.newop(op)
debug_print("fallback for", op.repr())
def maybe_handle_raw_accesses(self, op):
descr = op.getdescr()
assert isinstance(descr, FieldDescr)
if descr.stm_dont_track_raw_accesses:
- self.newops.append(op)
+ self.newop(op)
return True
return False
def handle_setters_for_pure_fields(self, op, targetindex):
val = op.getarg(targetindex)
if self.must_apply_write_barrier(val):
- self.gen_write_barrier(val, op.stm_location)
- self.newops.append(op)
+ self.gen_write_barrier(val)
+ self.newop(op)
diff --git a/rpython/jit/backend/llsupport/test/test_stmrewrite.py
b/rpython/jit/backend/llsupport/test/test_stmrewrite.py
--- a/rpython/jit/backend/llsupport/test/test_stmrewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_stmrewrite.py
@@ -1256,17 +1256,30 @@
guard_not_forced() [] {55}
""", """
[i0, f0]
- i1 = getfield_raw(ConstClass(frame_info), descr=jfi_frame_depth)
- p1 = call_malloc_nursery_varsize_frame(i1)
- setfield_gc(p1, 0, descr=tiddescr)
- setfield_gc(p1, i1, descr=framelendescr)
- setfield_gc(p1, ConstClass(frame_info), descr=jf_frame_info)
- setarrayitem_gc(p1, 0, i0, descr=signedframedescr)
- setarrayitem_gc(p1, 1, f0, descr=floatframedescr)
+ i1 = getfield_raw(ConstClass(frame_info), descr=jfi_frame_depth) {54}
+ p1 = call_malloc_nursery_varsize_frame(i1) {54}
+ setfield_gc(p1, 0, descr=tiddescr) {54}
+ setfield_gc(p1, i1, descr=framelendescr) {54}
+ setfield_gc(p1, ConstClass(frame_info), descr=jf_frame_info) {54}
+ setarrayitem_gc(p1, 0, i0, descr=signedframedescr) {54}
+ setarrayitem_gc(p1, 1, f0, descr=floatframedescr) {54}
i3 = call_assembler(p1, descr=casmdescr) {54}
guard_not_forced() [] {55}
""")
+ def test_stm_location_4(self):
+ self.check_rewrite("""
+ [p1, i2, p3]
+ debug_merge_point() {81}
+ i3 = int_add(i2, 5)
+ setarrayitem_gc(p1, i3, p3, descr=cdescr)
+ """, """
+ [p1, i2, p3]
+ i3 = int_add(i2, 5) {81}
+ cond_call_gc_wb_array(p1, i3, descr=wbdescr) {81}
+ setarrayitem_gc(p1, i3, p3, descr=cdescr) {81}
+ """)
+
def test_stm_should_break_transaction_no_malloc(self):
self.check_rewrite("""
[]
diff --git a/rpython/jit/metainterp/pyjitpl.py
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1159,8 +1159,6 @@
loc = jitdriver_sd.warmstate.get_location_str(greenkey)
debug_print(loc)
args = [ConstInt(jd_index), ConstInt(portal_call_depth),
ConstInt(current_call_id)] + greenkey
- self.metainterp.history.record(rop.DEBUG_MERGE_POINT, args, None)
- #
if self.metainterp.staticdata.config.translation.stm:
report_location = jitdriver_sd.stm_report_location
if report_location is not None:
@@ -1169,6 +1167,8 @@
ref = greenkey[idx_ref].getref_base()
location = StmLocation(num, ref)
self.metainterp.history.stm_location = location
+ #
+ self.metainterp.history.record(rop.DEBUG_MERGE_POINT, args, None)
@arguments("box", "label")
def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit