[pypy-commit] pypy default: merge getarrayitem-into-bridges:
cfbolz
pypy.commits at gmail.com
Fri Aug 4 11:26:14 EDT 2017
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch:
Changeset: r92076:43ff4a9015e3
Date: 2017-08-04 16:54 +0200
http://bitbucket.org/pypy/pypy/changeset/43ff4a9015e3/
Log: merge getarrayitem-into-bridges:
improvement on what information is retained into a bridge: in
particular, knowledge about the content of arrays (at fixed indices)
is stored in guards (and thus available at the beginning of
bridges). also, some better handling of constants.
diff --git a/rpython/jit/metainterp/optimizeopt/bridgeopt.py b/rpython/jit/metainterp/optimizeopt/bridgeopt.py
--- a/rpython/jit/metainterp/optimizeopt/bridgeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/bridgeopt.py
@@ -18,6 +18,10 @@
# (<box1> <descr> <box2>) length times, if getfield(box1, descr) == box2
# both boxes should be in the liveboxes
#
+# <length>
+# (<box1> <index> <descr> <box2>) length times, if getarrayitem_gc(box1, index, descr) == box2
+# both boxes should be in the liveboxes
+#
# ----
@@ -82,18 +86,26 @@
# structs
# XXX could be extended to arrays
if optimizer.optheap:
- triples = optimizer.optheap.serialize_optheap(available_boxes)
+ triples_struct, triples_array = optimizer.optheap.serialize_optheap(available_boxes)
# can only encode descrs that have a known index into
# metainterp_sd.all_descrs
- triples = [triple for triple in triples if triple[1].descr_index != -1]
- numb_state.append_int(len(triples))
- for box1, descr, box2 in triples:
- index = descr.descr_index
+ triples_struct = [triple for triple in triples_struct if triple[1].descr_index != -1]
+ numb_state.append_int(len(triples_struct))
+ for box1, descr, box2 in triples_struct:
+ descr_index = descr.descr_index
+ numb_state.append_short(tag_box(box1, liveboxes_from_env, memo))
+ numb_state.append_int(descr_index)
+ numb_state.append_short(tag_box(box2, liveboxes_from_env, memo))
+ numb_state.append_int(len(triples_array))
+ for box1, index, descr, box2 in triples_array:
+ descr_index = descr.descr_index
numb_state.append_short(tag_box(box1, liveboxes_from_env, memo))
numb_state.append_int(index)
+ numb_state.append_int(descr_index)
numb_state.append_short(tag_box(box2, liveboxes_from_env, memo))
else:
numb_state.append_int(0)
+ numb_state.append_int(0)
def deserialize_optimizer_knowledge(optimizer, resumestorage, frontend_boxes, liveboxes):
reader = resumecode.Reader(resumestorage.rd_numb)
@@ -123,13 +135,24 @@
if not optimizer.optheap:
return
length = reader.next_item()
- result = []
+ result_struct = []
+ for i in range(length):
+ tagged = reader.next_item()
+ box1 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu)
+ descr_index = reader.next_item()
+ descr = metainterp_sd.all_descrs[descr_index]
+ tagged = reader.next_item()
+ box2 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu)
+ result_struct.append((box1, descr, box2))
+ length = reader.next_item()
+ result_array = []
for i in range(length):
tagged = reader.next_item()
box1 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu)
index = reader.next_item()
- descr = metainterp_sd.all_descrs[index]
+ descr_index = reader.next_item()
+ descr = metainterp_sd.all_descrs[descr_index]
tagged = reader.next_item()
box2 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu)
- result.append((box1, descr, box2))
- optimizer.optheap.deserialize_optheap(result)
+ result_array.append((box1, index, descr, box2))
+ optimizer.optheap.deserialize_optheap(result_struct, result_array)
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -698,7 +698,7 @@
return self.emit(op)
def serialize_optheap(self, available_boxes):
- result = []
+ result_getfield = []
for descr, cf in self.cached_fields.iteritems():
if cf._lazy_set:
continue # XXX safe default for now
@@ -706,27 +706,62 @@
if not parent_descr.is_object():
continue # XXX could be extended to non-instance objects
for i, box1 in enumerate(cf.cached_structs):
- if box1 not in available_boxes:
+ if not box1.is_constant() and box1 not in available_boxes:
continue
structinfo = cf.cached_infos[i]
- box2 = structinfo.getfield(descr).get_box_replacement()
- if isinstance(box2, Const) or box2 in available_boxes:
- result.append((box1, descr, box2))
- return result
+ box2 = structinfo.getfield(descr)
+ if box2 is None:
+ # XXX this should not happen, as it is an invariant
+ # violation! yet it does if box1 is a constant
+ continue
+ box2 = box2.get_box_replacement()
+ if box2.is_constant() or box2 in available_boxes:
+ result_getfield.append((box1, descr, box2))
+ result_array = []
+ for descr, indexdict in self.cached_arrayitems.iteritems():
+ for index, cf in indexdict.iteritems():
+ if cf._lazy_set:
+ continue # XXX safe default for now
+ for i, box1 in enumerate(cf.cached_structs):
+ if not box1.is_constant() and box1 not in available_boxes:
+ continue
+ arrayinfo = cf.cached_infos[i]
+ box2 = arrayinfo.getitem(descr, index)
+ if box2 is None:
+ # XXX this should not happen, as it is an invariant
+ # violation! yet it does if box1 is a constant
+ continue
+ box2 = box2.get_box_replacement()
+ if box2.is_constant() or box2 in available_boxes:
+ result_array.append((box1, index, descr, box2))
+ return result_getfield, result_array
- def deserialize_optheap(self, triples):
- for box1, descr, box2 in triples:
+ def deserialize_optheap(self, triples_struct, triples_array):
+ for box1, descr, box2 in triples_struct:
parent_descr = descr.get_parent_descr()
assert parent_descr.is_object()
- structinfo = box1.get_forwarded()
- if not isinstance(structinfo, info.AbstractVirtualPtrInfo):
- structinfo = info.InstancePtrInfo(parent_descr)
- structinfo.init_fields(parent_descr, descr.get_index())
- box1.set_forwarded(structinfo)
-
+ if box1.is_constant():
+ structinfo = info.ConstPtrInfo(box1)
+ else:
+ structinfo = box1.get_forwarded()
+ if not isinstance(structinfo, info.AbstractVirtualPtrInfo):
+ structinfo = info.InstancePtrInfo(parent_descr)
+ structinfo.init_fields(parent_descr, descr.get_index())
+ box1.set_forwarded(structinfo)
cf = self.field_cache(descr)
structinfo.setfield(descr, box1, box2, optheap=self, cf=cf)
+ for box1, index, descr, box2 in triples_array:
+ if box1.is_constant():
+ arrayinfo = info.ConstPtrInfo(box1)
+ else:
+ arrayinfo = box1.get_forwarded()
+ if not isinstance(arrayinfo, info.AbstractVirtualPtrInfo):
+ arrayinfo = info.ArrayPtrInfo(descr)
+ box1.set_forwarded(arrayinfo)
+ cf = self.arrayitem_cache(descr, index)
+ arrayinfo.setitem(descr, index, box1, box2, optheap=self, cf=cf)
+
dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_',
default=OptHeap.emit)
diff --git a/rpython/jit/metainterp/test/test_bridgeopt.py b/rpython/jit/metainterp/test/test_bridgeopt.py
--- a/rpython/jit/metainterp/test/test_bridgeopt.py
+++ b/rpython/jit/metainterp/test/test_bridgeopt.py
@@ -61,7 +61,7 @@
serialize_optimizer_knowledge(optimizer, numb_state, liveboxes, {}, None)
- assert unpack_numbering(numb_state.create_numbering()) == [1, 0b010000, 0]
+ assert unpack_numbering(numb_state.create_numbering()) == [1, 0b010000, 0, 0]
rbox1 = InputArgRef()
rbox2 = InputArgRef()
@@ -97,7 +97,7 @@
serialize_optimizer_knowledge(optimizer, numb_state, liveboxes, {}, None)
- assert len(numb_state.create_numbering().code) == 2 + math.ceil(len(refboxes) / 6.0)
+ assert len(numb_state.create_numbering().code) == 3 + math.ceil(len(refboxes) / 6.0)
dct = {box: cls
for box, known_class in boxes_known_classes
@@ -143,11 +143,7 @@
def test_bridge_field_read(self):
myjitdriver = jit.JitDriver(greens=[], reds=['y', 'res', 'n', 'a'])
class A(object):
- def f(self):
- return 1
- class B(A):
- def f(self):
- return 2
+ pass
class M(object):
_immutable_fields_ = ['x']
def __init__(self, x):
@@ -156,14 +152,12 @@
m1 = M(1)
m2 = M(2)
def f(x, y, n):
+ a = A()
+ a.n = n
if x:
- a = A()
a.m = m1
- a.n = n
else:
- a = B()
a.m = m2
- a.n = n
a.x = 0
res = 0
while y > 0:
@@ -186,3 +180,105 @@
self.check_resops(getfield_gc_i=4) # 3x a.x, 1x a.n
self.check_resops(getfield_gc_r=1) # in main loop
+ def test_bridge_field_read_constants(self):
+ myjitdriver = jit.JitDriver(greens=[], reds=['y', 'res', 'n'])
+ class A(object):
+ pass
+ class M(object):
+ _immutable_fields_ = ['x']
+ def __init__(self, x):
+ self.x = x
+
+ m1 = M(1)
+ m2 = M(2)
+ a = A()
+ a.m = m1
+ a.n = 0
+ def f(x, y, n):
+ if x:
+ a.m = m1
+ a.n = n
+ else:
+ a.m = m2
+ a.n = n
+ a.x = 0
+ res = 0
+ while y > 0:
+ myjitdriver.jit_merge_point(y=y, n=n, res=res)
+ n1 = a.n
+ m = jit.promote(a.m)
+ res += m.x
+ a.x += 1
+ if y > n:
+ res += 1
+ m = jit.promote(a.m)
+ res += m.x
+ res += n1 + a.n
+ y -= 1
+ return res
+ res = self.meta_interp(f, [6, 32, 16])
+ assert res == f(6, 32, 16)
+ self.check_trace_count(3)
+ self.check_resops(guard_value=1)
+ self.check_resops(getfield_gc_i=4) # 3x a.x, 1x a.n
+ self.check_resops(getfield_gc_r=1) # in main loop
+
+ def test_bridge_array_read(self):
+ myjitdriver = jit.JitDriver(greens=[], reds=['y', 'res', 'n', 'a'])
+ def f(x, y, n):
+ if x:
+ a = [1, n, 0]
+ else:
+ a = [2, n, 0]
+ res = 0
+ while y > 0:
+ myjitdriver.jit_merge_point(y=y, n=n, res=res, a=a)
+ n1 = a[1]
+ m = jit.promote(a[0])
+ res += m
+ a[2] += 1
+ if y > n:
+ res += 1
+ m = jit.promote(a[0])
+ res += m
+ res += n1 + a[1]
+ y -= 1
+ return res
+ res = self.meta_interp(f, [6, 32, 16])
+ assert res == f(6, 32, 16)
+ self.check_trace_count(3)
+ self.check_resops(guard_value=1)
+ self.check_resops(getarrayitem_gc_i=4)
+
+ def test_bridge_array_read_constant(self):
+ myjitdriver = jit.JitDriver(greens=[], reds=['y', 'res', 'n'])
+ class A(object):
+ pass
+ a = A()
+ a.l = [1, -65, 0]
+ def f(x, y, n):
+ if x:
+ a.l[0] = 1
+ else:
+ a.l[0] = 2
+ a.l[1] = n
+ a.l[2] = 0
+ res = 0
+ while y > 0:
+ myjitdriver.jit_merge_point(y=y, n=n, res=res)
+ n1 = a.l[1]
+ m = jit.promote(a.l[0])
+ res += m
+ a.l[2] += 1
+ if y > n:
+ res += 1
+ m = jit.promote(a.l[0])
+ res += m
+ res += n1 + a.l[1]
+ y -= 1
+ return res
+ res = self.meta_interp(f, [6, 32, 16])
+ assert res == f(6, 32, 16)
+ self.check_trace_count(3)
+ self.check_resops(guard_value=1)
+ self.check_resops(getarrayitem_gc_i=5)
More information about the pypy-commit
mailing list