[pypy-commit] pypy py3.5: hg merge default
mjacob
pypy.commits at gmail.com
Mon Mar 19 12:07:25 EDT 2018
Author: Manuel Jacob <me at manueljacob.de>
Branch: py3.5
Changeset: r94004:fcbdf6d13402
Date: 2018-03-19 16:55 +0100
http://bitbucket.org/pypy/pypy/changeset/fcbdf6d13402/
Log: hg merge default
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -52,3 +52,13 @@
.. branch: refactor-slots
Refactor cpyext slots.
+
+
+.. branch: call-loopinvariant-into-bridges
+
+Speed up branchy code that does a lot of function inlining by saving one call
+to read the TLS in most bridges.
+
+.. branch: rpython-sprint
+
+Refactor in rpython signatures
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -1403,6 +1403,7 @@
if len(e.value.args) > 2:
assert e.value.args[2] == "\\foo\\bar\\baz"
+ @py.test.mark.skipif("sys.platform != 'win32'")
def test_rename(self):
os = self.posix
fname = self.path2 + 'rename.txt'
diff --git a/pypy/module/unicodedata/test/test_hyp.py b/pypy/module/unicodedata/test/test_hyp.py
--- a/pypy/module/unicodedata/test/test_hyp.py
+++ b/pypy/module/unicodedata/test/test_hyp.py
@@ -1,6 +1,7 @@
+import sys
import pytest
try:
- from hypothesis import given, strategies as st, example, settings
+ from hypothesis import given, strategies as st, example, settings, assume
except ImportError:
pytest.skip("hypothesis required")
@@ -40,9 +41,14 @@
@pytest.mark.parametrize('NF1, NF2, NF3', compositions)
@example(s=u'---\uafb8\u11a7---') # issue 2289
- at example(s=u'\ufacf')
@settings(max_examples=1000)
@given(s=st.text())
def test_composition(s, space, NF1, NF2, NF3):
+ # 'chr(0xfacf) normalizes to chr(0x2284a), which is too big')
+ assume(not (s == u'\ufacf' and sys.maxunicode == 65535))
norm1, norm2, norm3 = [make_normalization(space, form) for form in [NF1, NF2, NF3]]
assert norm2(norm1(s)) == norm3(s)
+
+if sys.maxunicode != 65535:
+ # conditionally generate the example via an unwrapped decorator
+ test_composition = example(s=u'\ufacf')(test_composition)
diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py
--- a/rpython/annotator/signature.py
+++ b/rpython/annotator/signature.py
@@ -14,16 +14,16 @@
def _annotation_key(t):
from rpython.rtyper import extregistry
- if type(t) is list:
+ if isinstance(t, list):
assert len(t) == 1
return ('list', _annotation_key(t[0]))
- elif type(t) is dict:
+ elif isinstance(t, dict):
assert len(t.keys()) == 1
return ('dict', _annotation_key(t.items()[0]))
elif isinstance(t, tuple):
return tuple([_annotation_key(i) for i in t])
elif extregistry.is_registered(t):
- # XXX should it really be always different?
+ # XXX do we want to do something in this case?
return t
return t
@@ -38,24 +38,36 @@
return t
return _compute_annotation(t, bookkeeper)
+
+def _validate_annotation_size(t):
+ try:
+ _ = iter(t)
+ except TypeError: # if it's not an iterable, just return
+ return t # (size does not matter)
+ if isinstance(t, tuple): # we accept tuples with any length, because
+ return t # their in-memory representation is predictable
+ if len(t) > 1:
+ raise TypeError("Cannot specify multiple types in a %s (try using tuple)", type(t))
+
+
def _compute_annotation(t, bookkeeper=None):
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.llannotation import lltype_to_annotation
+ _validate_annotation_size(t)
if isinstance(t, SomeObject):
return t
elif isinstance(t, lltype.LowLevelType):
return lltype_to_annotation(t)
elif isinstance(t, list):
- assert len(t) == 1, "We do not support type joining in list"
- listdef = ListDef(bookkeeper, annotation(t[0]), mutated=True, resized=True)
- return SomeList(listdef)
+ return SomeList(
+ ListDef(bookkeeper, annotation(t[0]),
+ mutated=True, resized=True))
elif isinstance(t, tuple):
return SomeTuple(tuple([annotation(i) for i in t]))
elif isinstance(t, dict):
- assert len(t) == 1, "We do not support type joining in dict"
- result = SomeDict(DictDef(bookkeeper, annotation(t.keys()[0]),
- annotation(t.values()[0])))
- return result
+ return SomeDict(
+ DictDef(bookkeeper,
+ annotation(t.keys()[0]), annotation(t.values()[0])))
elif type(t) is types.NoneType:
return s_None
elif extregistry.is_registered(t):
@@ -84,13 +96,12 @@
elif t is types.NoneType:
return s_None
elif bookkeeper and extregistry.is_registered_type(t):
- entry = extregistry.lookup_type(t)
- return entry.compute_annotation_bk(bookkeeper)
+ return (extregistry.lookup_type(t)
+ .compute_annotation_bk(bookkeeper))
elif t is type:
return SomeType()
elif bookkeeper and not hasattr(t, '_freeze_'):
- classdef = bookkeeper.getuniqueclassdef(t)
- return SomeInstance(classdef)
+ return SomeInstance(bookkeeper.getuniqueclassdef(t))
else:
raise AssertionError("annotationoftype(%r)" % (t,))
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
@@ -17,11 +17,17 @@
# <length>
# (<box1> <descr> <box2>) length times, if getfield(box1, descr) == box2
# both boxes should be in the liveboxes
+# (or constants)
#
# <length>
# (<box1> <index> <descr> <box2>) length times, if getarrayitem_gc(box1, index, descr) == box2
# both boxes should be in the liveboxes
+# (or constants)
#
+# ---- call_loopinvariant knowledge
+# <length>
+# (<const> <box2>) length times, if call_loopinvariant(const) == box2
+# box2 should be in liveboxes
# ----
@@ -55,11 +61,11 @@
return box
def serialize_optimizer_knowledge(optimizer, numb_state, liveboxes, liveboxes_from_env, memo):
+ from rpython.jit.metainterp.history import ConstInt
available_boxes = {}
for box in liveboxes:
if box is not None and box in liveboxes_from_env:
available_boxes[box] = None
- metainterp_sd = optimizer.metainterp_sd
# class knowledge is stored as bits, true meaning the class is known, false
# means unknown. on deserializing we look at the bits, and read the runtime
@@ -106,7 +112,19 @@
numb_state.append_int(0)
numb_state.append_int(0)
+ if optimizer.optrewrite:
+ tuples_loopinvariant = optimizer.optrewrite.serialize_optrewrite(
+ available_boxes)
+ numb_state.append_int(len(tuples_loopinvariant))
+ for constarg0, box in tuples_loopinvariant:
+ numb_state.append_short(
+ tag_box(ConstInt(constarg0), liveboxes_from_env, memo))
+ numb_state.append_short(tag_box(box, liveboxes_from_env, memo))
+ else:
+ numb_state.append_int(0)
+
def deserialize_optimizer_knowledge(optimizer, resumestorage, frontend_boxes, liveboxes):
+ from rpython.jit.metainterp.history import ConstInt
reader = resumecode.Reader(resumestorage.rd_numb)
assert len(frontend_boxes) == len(liveboxes)
metainterp_sd = optimizer.metainterp_sd
@@ -131,8 +149,6 @@
optimizer.make_constant_class(box, cls)
# heap knowledge
- if not optimizer.optheap:
- return
length = reader.next_item()
result_struct = []
for i in range(length):
@@ -154,4 +170,19 @@
tagged = reader.next_item()
box2 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu)
result_array.append((box1, index, descr, box2))
- optimizer.optheap.deserialize_optheap(result_struct, result_array)
+ if optimizer.optheap:
+ optimizer.optheap.deserialize_optheap(result_struct, result_array)
+
+ # call_loopinvariant knowledge
+ length = reader.next_item()
+ result_loopinvariant = []
+ for i in range(length):
+ tagged1 = reader.next_item()
+ const = decode_box(resumestorage, tagged1, liveboxes, metainterp_sd.cpu)
+ assert isinstance(const, ConstInt)
+ i = const.getint()
+ tagged2 = reader.next_item()
+ box = decode_box(resumestorage, tagged2, liveboxes, metainterp_sd.cpu)
+ result_loopinvariant.append((i, box))
+ if optimizer.optrewrite:
+ optimizer.optrewrite.deserialize_optrewrite(result_loopinvariant)
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -877,6 +877,18 @@
optimize_SAME_AS_R = optimize_SAME_AS_I
optimize_SAME_AS_F = optimize_SAME_AS_I
+ def serialize_optrewrite(self, available_boxes):
+ res = []
+ for i, box in self.loop_invariant_results.iteritems():
+ box = self.get_box_replacement(box)
+ if box in available_boxes:
+ res.append((i, box))
+ return res
+
+ def deserialize_optrewrite(self, tups):
+ for i, box in tups:
+ self.loop_invariant_results[i] = box
+
dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
default=OptRewrite.emit)
optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
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
@@ -1,6 +1,9 @@
# tests that check that information is fed from the optimizer into the bridges
+import pytest
+
import math
+
from rpython.rlib import jit
from rpython.jit.metainterp.test.support import LLJitMixin
from rpython.jit.metainterp.optimizeopt.bridgeopt import serialize_optimizer_knowledge
@@ -27,6 +30,7 @@
class FakeOptimizer(object):
metainterp_sd = None
optheap = None
+ optrewrite = None
def __init__(self, dct={}, cpu=None):
self.dct = dct
@@ -61,7 +65,8 @@
serialize_optimizer_knowledge(optimizer, numb_state, liveboxes, {}, None)
- assert unpack_numbering(numb_state.create_numbering()) == [1, 0b010000, 0, 0]
+ assert unpack_numbering(numb_state.create_numbering()) == [
+ 1, 0b010000, 0, 0, 0]
rbox1 = InputArgRef()
rbox2 = InputArgRef()
@@ -100,7 +105,7 @@
serialize_optimizer_knowledge(optimizer, numb_state, liveboxes, {}, None)
- assert len(numb_state.create_numbering().code) == 3 + math.ceil(len(refboxes) / 6.0)
+ assert len(numb_state.create_numbering().code) == 4 + math.ceil(len(refboxes) / 6.0)
dct = {box: cls
for box, known_class in boxes_known_classes
@@ -321,3 +326,74 @@
self.check_trace_count(3)
self.check_resops(guard_value=1)
self.check_resops(getarrayitem_gc_i=5)
+
+ def test_bridge_call_loopinvariant(self):
+ class A(object):
+ pass
+ class B(object):
+ pass
+
+ aholder = B()
+ aholder.a = A()
+
+ @jit.loop_invariant
+ def get():
+ return aholder.a
+
+ myjitdriver = jit.JitDriver(greens=[], reds=['y', 'res', 'n'])
+ def f(x, y, n):
+ if x == 10001121:
+ aholder.a = A()
+ if x:
+ get().x = 1
+ else:
+ get().x = 2
+ res = 0
+ while y > 0:
+ myjitdriver.jit_merge_point(y=y, n=n, res=res)
+ a = get()
+ a = get()
+ res += a.x
+ if y > n:
+ res += 1
+ res += get().x + a.x
+ y -= 1
+ return res
+ res = self.meta_interp(f, [6, 32, 16])
+ self.check_trace_count(3)
+ self.check_resops(call_r=1)
+
+ @pytest.mark.xfail()
+ def test_bridge_call_loopinvariant_2(self):
+ class A(object):
+ pass
+ class B(object):
+ pass
+
+ aholder = B()
+ aholder.a = A()
+
+ @jit.loop_invariant
+ def get():
+ return aholder.a
+
+ myjitdriver = jit.JitDriver(greens=[], reds=['y', 'res', 'n'])
+ def f(x, y, n):
+ if x == 10001121:
+ aholder.a = A()
+ if x:
+ get().x = 1
+ else:
+ get().x = 2
+ res = 0
+ while y > 0:
+ myjitdriver.jit_merge_point(y=y, n=n, res=res)
+ if y > n:
+ res += get().x
+ res += 1
+ res += get().x
+ y -= 1
+ return res
+ res = self.meta_interp(f, [6, 32, 16])
+ self.check_trace_count(3)
+ self.check_resops(call_r=1)
diff --git a/rpython/jit/metainterp/test/test_resume.py b/rpython/jit/metainterp/test/test_resume.py
--- a/rpython/jit/metainterp/test/test_resume.py
+++ b/rpython/jit/metainterp/test/test_resume.py
@@ -40,7 +40,7 @@
class FakeOptimizer(object):
metainterp_sd = None
- optheap = None
+ optheap = optrewrite = None
def __init__(self, trace=None):
self.trace = trace
diff --git a/rpython/rlib/rstruct/nativefmttable.py b/rpython/rlib/rstruct/nativefmttable.py
--- a/rpython/rlib/rstruct/nativefmttable.py
+++ b/rpython/rlib/rstruct/nativefmttable.py
@@ -130,6 +130,13 @@
sizeof_double = native_fmttable['d']['size']
sizeof_float = native_fmttable['f']['size']
+# Copy CPython's behavior of using short's size and alignment for half-floats.
+native_fmttable['e'] = {'size': native_fmttable['h']['size'],
+ 'alignment': native_fmttable['h']['alignment'],
+ 'pack': std.pack_halffloat,
+ 'unpack': std.unpack_halffloat,
+ }
+
# ____________________________________________________________
#
# A PyPy extension: accepts the 'u' format character in native mode,
diff --git a/rpython/rlib/rstruct/test/test_pack.py b/rpython/rlib/rstruct/test/test_pack.py
--- a/rpython/rlib/rstruct/test/test_pack.py
+++ b/rpython/rlib/rstruct/test/test_pack.py
@@ -139,9 +139,6 @@
self.check('d', 123.456789)
def test_pack_halffloat(self):
- if self.fmttable is nativefmttable.native_fmttable:
- # Host Python cannot handle half floats.
- return
size = 2
wbuf = MutableStringBuffer(size)
self.mypack_into('e', wbuf, 6.5e+04)
More information about the pypy-commit
mailing list