[pypy-commit] pypy py3.6: merge default
cfbolz
pypy.commits at gmail.com
Wed Jun 5 05:32:05 EDT 2019
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: py3.6
Changeset: r96747:0ffff10dd2bc
Date: 2019-06-05 11:31 +0200
http://bitbucket.org/pypy/pypy/changeset/0ffff10dd2bc/
Log: merge default
diff too long, truncating to 2000 out of 7324 lines
diff --git a/extra_tests/cffi_tests/cffi0/test_parsing.py b/extra_tests/cffi_tests/cffi0/test_parsing.py
--- a/extra_tests/cffi_tests/cffi0/test_parsing.py
+++ b/extra_tests/cffi_tests/cffi0/test_parsing.py
@@ -410,7 +410,17 @@
def test_enum():
ffi = FFI()
ffi.cdef("""
- enum Enum { POS = +1, TWO = 2, NIL = 0, NEG = -1, OP = (POS+TWO)-1};
+ enum Enum {
+ POS = +1,
+ TWO = 2,
+ NIL = 0,
+ NEG = -1,
+ ADDSUB = (POS+TWO)-1,
+ DIVMULINT = (3 * 3) / 2,
+ SHIFT = (1 << 3) >> 1,
+ BINOPS = (0x7 & 0x1) | 0x8,
+ XOR = 0xf ^ 0xa
+ };
""")
needs_dlopen_none()
C = ffi.dlopen(None)
@@ -418,7 +428,11 @@
assert C.TWO == 2
assert C.NIL == 0
assert C.NEG == -1
- assert C.OP == 2
+ assert C.ADDSUB == 2
+ assert C.DIVMULINT == 4
+ assert C.SHIFT == 4
+ assert C.BINOPS == 0b1001
+ assert C.XOR == 0b0101
def test_stdcall():
ffi = FFI()
diff --git a/extra_tests/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py
--- a/extra_tests/cffi_tests/cffi0/test_verify.py
+++ b/extra_tests/cffi_tests/cffi0/test_verify.py
@@ -2535,3 +2535,29 @@
x.p = p
x.cyclic = x
del p, x
+
+def test_arithmetic_in_cdef():
+ for a in [0, 11, 15]:
+ ffi = FFI()
+ ffi.cdef("""
+ enum FOO {
+ DIVNN = ((-?) / (-3)),
+ DIVNP = ((-?) / (+3)),
+ DIVPN = ((+?) / (-3)),
+ MODNN = ((-?) % (-3)),
+ MODNP = ((-?) % (+3)),
+ MODPN = ((+?) % (-3)),
+ };
+ """.replace('?', str(a)))
+ lib = ffi.verify("""
+ enum FOO {
+ DIVNN = ((-?) / (-3)),
+ DIVNP = ((-?) / (+3)),
+ DIVPN = ((+?) / (-3)),
+ MODNN = ((-?) % (-3)),
+ MODNP = ((-?) % (+3)),
+ MODPN = ((+?) % (-3)),
+ };
+ """.replace('?', str(a)))
+ # the verify() crashes if the values in the enum are different from
+ # the values we computed ourselves from the cdef()
diff --git a/extra_tests/cffi_tests/cffi0/test_zintegration.py b/extra_tests/cffi_tests/cffi0/test_zintegration.py
--- a/extra_tests/cffi_tests/cffi0/test_zintegration.py
+++ b/extra_tests/cffi_tests/cffi0/test_zintegration.py
@@ -2,11 +2,13 @@
import py, os, sys, shutil
import subprocess
from extra_tests.cffi_tests.udir import udir
+import pytest
if sys.platform == 'win32':
- py.test.skip('snippets do not run on win32')
+ pytestmark = pytest.mark.skip('snippets do not run on win32')
if sys.version_info < (2, 7):
- py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
+ pytestmark = pytest.mark.skip(
+ 'fails e.g. on a Debian/Ubuntu which patches virtualenv'
' in a non-2.6-friendly way')
def create_venv(name):
diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py
--- a/extra_tests/cffi_tests/cffi1/test_recompiler.py
+++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py
@@ -2339,3 +2339,24 @@
typedef int foo_t; struct foo_s { void (*x)(foo_t); };
""")
py.test.raises(TypeError, ffi.new, "struct foo_s *")
+
+def test_from_buffer_struct():
+ ffi = FFI()
+ ffi.cdef("""struct foo_s { int a, b; };""")
+ lib = verify(ffi, "test_from_buffer_struct_p", """
+ struct foo_s { int a, b; };
+ """)
+ p = ffi.new("struct foo_s *", [-219239, 58974983])
+ q = ffi.from_buffer("struct foo_s[]", ffi.buffer(p))
+ assert ffi.typeof(q) == ffi.typeof("struct foo_s[]")
+ assert len(q) == 1
+ assert q[0].a == p.a
+ assert q[0].b == p.b
+ assert q == p
+ q = ffi.from_buffer("struct foo_s *", ffi.buffer(p))
+ assert ffi.typeof(q) == ffi.typeof("struct foo_s *")
+ assert q.a == p.a
+ assert q.b == p.b
+ assert q[0].a == p.a
+ assert q[0].b == p.b
+ assert q == p
diff --git a/extra_tests/cffi_tests/embedding/test_basic.py b/extra_tests/cffi_tests/embedding/test_basic.py
--- a/extra_tests/cffi_tests/embedding/test_basic.py
+++ b/extra_tests/cffi_tests/embedding/test_basic.py
@@ -64,8 +64,8 @@
output = popen.stdout.read()
err = popen.wait()
if err:
- raise OSError("popen failed with exit code %r: %r" % (
- err, args))
+ raise OSError(("popen failed with exit code %r: %r\n\n%s" % (
+ err, args, output)).rstrip())
print(output.rstrip())
return output
diff --git a/extra_tests/cffi_tests/embedding/test_performance.py b/extra_tests/cffi_tests/embedding/test_performance.py
--- a/extra_tests/cffi_tests/embedding/test_performance.py
+++ b/extra_tests/cffi_tests/embedding/test_performance.py
@@ -3,8 +3,8 @@
from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests
if sys.platform == 'win32':
- import py
- py.test.skip("written with POSIX functions")
+ import pytest
+ pytestmark = pytest.mark.skip("written with POSIX functions")
class TestPerformance(EmbeddingTests):
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.12.3
+Version: 1.13.0
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -5,8 +5,8 @@
from .error import CDefError, FFIError, VerificationError, VerificationMissing
from .error import PkgConfigError
-__version__ = "1.12.3"
-__version_info__ = (1, 12, 3)
+__version__ = "1.13.0"
+__version_info__ = (1, 13, 0)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -145,6 +145,7 @@
int result;
PyGILState_STATE state;
PyObject *pycode=NULL, *global_dict=NULL, *x;
+ PyObject *builtins;
state = PyGILState_Ensure();
@@ -169,7 +170,7 @@
global_dict = PyDict_New();
if (global_dict == NULL)
goto error;
- PyObject *builtins = PyEval_GetBuiltins();
+ builtins = PyEval_GetBuiltins();
if (builtins == NULL)
goto error;
if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0)
@@ -223,7 +224,7 @@
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.12.3"
+ "\ncompiled with cffi version: 1.13.0"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -858,19 +858,39 @@
"the actual array length in this context"
% exprnode.coord.line)
#
- if (isinstance(exprnode, pycparser.c_ast.BinaryOp) and
- exprnode.op == '+'):
- return (self._parse_constant(exprnode.left) +
- self._parse_constant(exprnode.right))
- #
- if (isinstance(exprnode, pycparser.c_ast.BinaryOp) and
- exprnode.op == '-'):
- return (self._parse_constant(exprnode.left) -
- self._parse_constant(exprnode.right))
+ if isinstance(exprnode, pycparser.c_ast.BinaryOp):
+ left = self._parse_constant(exprnode.left)
+ right = self._parse_constant(exprnode.right)
+ if exprnode.op == '+':
+ return left + right
+ elif exprnode.op == '-':
+ return left - right
+ elif exprnode.op == '*':
+ return left * right
+ elif exprnode.op == '/':
+ return self._c_div(left, right)
+ elif exprnode.op == '%':
+ return left - self._c_div(left, right) * right
+ elif exprnode.op == '<<':
+ return left << right
+ elif exprnode.op == '>>':
+ return left >> right
+ elif exprnode.op == '&':
+ return left & right
+ elif exprnode.op == '|':
+ return left | right
+ elif exprnode.op == '^':
+ return left ^ right
#
raise FFIError(":%d: unsupported expression: expected a "
"simple numeric constant" % exprnode.coord.line)
+ def _c_div(self, a, b):
+ result = a // b
+ if ((a < 0) ^ (b < 0)) and (a % b) != 0:
+ result += 1
+ return result
+
def _build_enum_type(self, explicit_name, decls):
if decls is not None:
partial = False
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
@@ -38,3 +38,7 @@
.. branch: fix-vmprof-memory-tracking
Fix a bug that prevent memory-tracking in vmprof working on PyPy.
+
+.. branch: optimizeopt-cleanup
+
+Cleanup optimizeopt
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
from rpython.rlib import rdynload, clibffi
from rpython.rtyper.lltypesystem import rffi
-VERSION = "1.12.3"
+VERSION = "1.13.0"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -670,11 +670,14 @@
return self.length
def _repr_extra(self):
- if self.w_keepalive is not None:
- name = self.space.type(self.w_keepalive).name
+ from pypy.module._cffi_backend import ctypearray
+ if self.w_keepalive is None:
+ return "buffer RELEASED"
+ obj_tp_name = self.space.type(self.w_keepalive).name
+ if isinstance(self.ctype, ctypearray.W_CTypeArray):
+ return "buffer len %d from '%s' object" % (self.length, obj_tp_name)
else:
- name = "(released)"
- return "buffer len %d from '%s' object" % (self.length, name)
+ return "buffer from '%s' object" % (obj_tp_name,)
def enter_exit(self, exit_now):
# for now, limited effect on PyPy
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -112,9 +112,10 @@
@unwrap_spec(w_ctype=ctypeobj.W_CType, require_writable=int)
def from_buffer(space, w_ctype, w_x, require_writable=0):
- from pypy.module._cffi_backend import ctypearray
- if not isinstance(w_ctype, ctypearray.W_CTypeArray):
- raise oefmt(space.w_TypeError, "expected an array ctype, got '%s'",
+ from pypy.module._cffi_backend import ctypeptr, ctypearray
+ if not isinstance(w_ctype, ctypeptr.W_CTypePtrOrArray):
+ raise oefmt(space.w_TypeError,
+ "expected a poiunter or array ctype, got '%s'",
w_ctype.name)
if space.isinstance_w(w_x, space.w_unicode):
raise oefmt(space.w_TypeError,
@@ -135,33 +136,36 @@
"raw address on PyPy", w_x)
#
buffersize = buf.getlength()
- arraylength = w_ctype.length
- if arraylength >= 0:
- # it's an array with a fixed length; make sure that the
- # buffer contains enough bytes.
- if buffersize < w_ctype.size:
- raise oefmt(space.w_ValueError,
- "buffer is too small (%d bytes) for '%s' (%d bytes)",
- buffersize, w_ctype.name, w_ctype.size)
+ if not isinstance(w_ctype, ctypearray.W_CTypeArray):
+ arraylength = buffersize # number of bytes, not used so far
else:
- # it's an open 'array[]'
- itemsize = w_ctype.ctitem.size
- if itemsize == 1:
- # fast path, performance only
- arraylength = buffersize
- elif itemsize > 0:
- # give it as many items as fit the buffer. Ignore a
- # partial last element.
- arraylength = buffersize / itemsize
+ arraylength = w_ctype.length
+ if arraylength >= 0:
+ # it's an array with a fixed length; make sure that the
+ # buffer contains enough bytes.
+ if buffersize < w_ctype.size:
+ raise oefmt(space.w_ValueError,
+ "buffer is too small (%d bytes) for '%s' (%d bytes)",
+ buffersize, w_ctype.name, w_ctype.size)
else:
- # it's an array 'empty[]'. Unsupported obscure case:
- # the problem is that setting the length of the result
- # to anything large (like SSIZE_T_MAX) is dangerous,
- # because if someone tries to loop over it, it will
- # turn effectively into an infinite loop.
- raise oefmt(space.w_ZeroDivisionError,
- "from_buffer('%s', ..): the actual length of the array "
- "cannot be computed", w_ctype.name)
+ # it's an open 'array[]'
+ itemsize = w_ctype.ctitem.size
+ if itemsize == 1:
+ # fast path, performance only
+ arraylength = buffersize
+ elif itemsize > 0:
+ # give it as many items as fit the buffer. Ignore a
+ # partial last element.
+ arraylength = buffersize / itemsize
+ else:
+ # it's an array 'empty[]'. Unsupported obscure case:
+ # the problem is that setting the length of the result
+ # to anything large (like SSIZE_T_MAX) is dangerous,
+ # because if someone tries to loop over it, it will
+ # turn effectively into an infinite loop.
+ raise oefmt(space.w_ZeroDivisionError,
+ "from_buffer('%s', ..): the actual length of the array "
+ "cannot be computed", w_ctype.name)
#
return cdataobj.W_CDataFromBuffer(space, _cdata, arraylength,
w_ctype, buf, w_x)
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.12.3", ("This test_c.py file is for testing a version"
+assert __version__ == "1.13.0", ("This test_c.py file is for testing a version"
" of cffi that differs from the one that we"
" get from 'import _cffi_backend'")
if sys.version_info < (3,):
@@ -3830,7 +3830,9 @@
BIntP = new_pointer_type(BInt)
BIntA = new_array_type(BIntP, None)
lst = [-12345678, 87654321, 489148]
- bytestring = buffer(newp(BIntA, lst))[:] + b'XYZ'
+ bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
+ lst2 = lst + [42, -999999999]
+ bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ')
#
p1 = from_buffer(BIntA, bytestring) # int[]
assert typeof(p1) is BIntA
@@ -3844,7 +3846,19 @@
p1[-1]
#
py.test.raises(TypeError, from_buffer, BInt, bytestring)
- py.test.raises(TypeError, from_buffer, BIntP, bytestring)
+ #
+ p2 = from_buffer(BIntP, bytestring) # int *
+ assert p2 == p1 or 'PY_DOT_PY' in globals()
+ # note: on py.py ^^^, bytearray buffers are not emulated well enough
+ assert typeof(p2) is BIntP
+ assert p2[0] == lst[0]
+ assert p2[1] == lst[1]
+ assert p2[2] == lst[2]
+ # hopefully does not crash, but doesn't raise an exception:
+ p2[3]
+ p2[-1]
+ # not enough data even for one, but this is not enforced:
+ from_buffer(BIntP, b"")
#
BIntA2 = new_array_type(BIntP, 2)
p2 = from_buffer(BIntA2, bytestring) # int[2]
@@ -3856,7 +3870,7 @@
p2[2]
with pytest.raises(IndexError):
p2[-1]
- assert p2 == p1
+ assert p2 == p1 or 'PY_DOT_PY' in globals()
#
BIntA4 = new_array_type(BIntP, 4) # int[4]: too big
py.test.raises(ValueError, from_buffer, BIntA4, bytestring)
@@ -3866,13 +3880,37 @@
('a2', BInt, -1)])
BStructP = new_pointer_type(BStruct)
BStructA = new_array_type(BStructP, None)
- p1 = from_buffer(BStructA, bytestring) # struct[]
- assert len(p1) == 1
+ p1 = from_buffer(BStructA, bytestring2) # struct[]
+ assert len(p1) == 2
assert typeof(p1) is BStructA
- assert p1[0].a1 == lst[0]
- assert p1[0].a2 == lst[1]
+ assert p1[0].a1 == lst2[0]
+ assert p1[0].a2 == lst2[1]
+ assert p1[1].a1 == lst2[2]
+ assert p1[1].a2 == lst2[3]
with pytest.raises(IndexError):
- p1[1]
+ p1[2]
+ with pytest.raises(IndexError):
+ p1[-1]
+ assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>"
+ #
+ p2 = from_buffer(BStructP, bytestring2) # 'struct *'
+ assert p2 == p1 or 'PY_DOT_PY' in globals()
+ assert typeof(p2) is BStructP
+ assert p2.a1 == lst2[0]
+ assert p2.a2 == lst2[1]
+ assert p2[0].a1 == lst2[0]
+ assert p2[0].a2 == lst2[1]
+ assert p2[1].a1 == lst2[2]
+ assert p2[1].a2 == lst2[3]
+ # does not crash:
+ p2[2]
+ p2[-1]
+ # not enough data even for one, but this is not enforced:
+ from_buffer(BStructP, b"")
+ from_buffer(BStructP, b"1234567")
+ #
+ release(p1)
+ assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>"
#
BEmptyStruct = new_struct_type("empty")
complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
@@ -3886,7 +3924,37 @@
p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5]
assert typeof(p1) is BEmptyStructA5
assert len(p1) == 5
- assert cast(BIntP, p1) == from_buffer(BIntA, bytestring)
+ assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring)
+ or 'PY_DOT_PY' in globals())
+ #
+ BVarStruct = new_struct_type("varfoo")
+ BVarStructP = new_pointer_type(BVarStruct)
+ complete_struct_or_union(BVarStruct, [('a1', BInt, -1),
+ ('va', BIntA, -1)])
+ with pytest.raises(TypeError):
+ from_buffer(BVarStruct, bytestring)
+ pv = from_buffer(BVarStructP, bytestring) # varfoo *
+ assert pv.a1 == lst[0]
+ assert pv.va[0] == lst[1]
+ assert pv.va[1] == lst[2]
+ assert sizeof(pv[0]) == 1 * size_of_int()
+ with pytest.raises(TypeError):
+ len(pv.va)
+ # hopefully does not crash, but doesn't raise an exception:
+ pv.va[2]
+ pv.va[-1]
+ # not enough data even for one, but this is not enforced:
+ from_buffer(BVarStructP, b"")
+ assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>"
+ assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
+ #
+ release(pv)
+ assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>"
+ assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
+ #
+ pv = from_buffer(BVarStructP, bytestring) # make a fresh one
+ with pytest.raises(ValueError):
+ release(pv[0])
def test_memmove():
Short = new_primitive_type("short")
@@ -4312,8 +4380,10 @@
BCharA = new_array_type(BCharP, None)
p = from_buffer(BCharA, a)
assert p[2] == b"z"
+ assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
release(p)
assert p[2] == b"z" # true so far, but might change to raise RuntimeError
+ assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
release(p) # no effect
def test_explicit_release_from_buffer_contextmgr():
@@ -4325,6 +4395,7 @@
with p:
assert p[2] == b"z"
assert p[2] == b"z" # true so far, but might change to raise RuntimeError
+ assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
release(p) # no effect
def test_explicit_release_bytearray_on_cpython():
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -2,6 +2,8 @@
import sys
+import sys
+
from rpython.rlib.objectmodel import (
compute_hash, compute_unique_id, import_from_mixin, always_inline,
enforceargs, newlist_hint, specialize, we_are_translated)
diff --git a/rpython/doc/jit/optimizer.rst b/rpython/doc/jit/optimizer.rst
--- a/rpython/doc/jit/optimizer.rst
+++ b/rpython/doc/jit/optimizer.rst
@@ -13,7 +13,7 @@
Before some optimizations are explained in more detail, it is essential to
understand how traces look like.
-The optimizer comes with a test suit. It contains many trace
+The optimizer comes with a test suite. It contains many trace
examples and you might want to take a look at it
(in `rpython/jit/metainterp/optimizeopt/test/*.py`).
The allowed operations can be found in `rpython/jit/metainterp/resoperation.py`.
@@ -21,7 +21,7 @@
[p0,i0,i1]
label(p0, i0, i1)
- i2 = getarray_item_raw(p0, i0, descr=<Array Signed>)
+ i2 = getarrayitem_raw(p0, i0, descr=<Array Signed>)
i3 = int_add(i1,i2)
i4 = int_add(i0,1)
i5 = int_le(i4, 100) # lower-or-equal
@@ -32,7 +32,7 @@
to compare the Python code that constructed the trace::
from array import array
- a = array('i',range(101))
+ a = array('i', range(101))
sum = 0; i = 0
while i <= 100: # can be seen as label
sum += a[i]
@@ -131,20 +131,16 @@
Whenever such an operation is encountered (e.g. ``y = x & 0``), no operation is
emitted. Instead the variable y is made equal to 0
-(= ``make_equal_to(op.result, 0)``). The variables found in a trace are
-instances of Box classes that can be found in
-`rpython/jit/metainterp/history.py`. `OptValue` wraps those variables again
-and maps the boxes to the optimization values in the optimizer. When a
-value is made equal, the two variable's boxes are made to point to the same
-`OptValue` instance.
+(= ``make_constant_int(op, 0)``). The variables found in a trace are instances
+of classes that can be found in `rpython/jit/metainterp/history.py`. When a
+value is made equal to another, its box is made to point to the other one.
-**NOTE: this OptValue organization is currently being refactored in a branch.**
Pure optimization
-----------------
-Is interwoven into the basic optimizer. It saves operations, results,
-arguments to be known to have pure semantics.
+The 'pure' optimizations interwoven into the basic optimizer. It saves
+operations, results, arguments to be known to have pure semantics.
"Pure" here means the same as the ``jit.elidable`` decorator:
free of "observable" side effects and referentially transparent
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -3,23 +3,22 @@
from rpython.rtyper.annlowlevel import (
cast_instance_to_gcref, cast_gcref_to_instance)
from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.debug import debug_start, debug_stop, debug_print, have_debug_prints
+from rpython.rlib.debug import (
+ debug_start, debug_stop, debug_print, have_debug_prints)
from rpython.rlib.rarithmetic import r_uint, intmask
from rpython.rlib import rstack
from rpython.rlib.jit import JitDebugInfo, Counters, dont_look_inside
from rpython.rlib.rjitlog import rjitlog as jl
-from rpython.rlib.objectmodel import compute_unique_id
-from rpython.conftest import option
-from rpython.jit.metainterp.resoperation import ResOperation, rop,\
- get_deep_immutable_oplist, OpHelpers, InputArgInt, InputArgRef,\
- InputArgFloat
-from rpython.jit.metainterp.history import (TreeLoop, Const, JitCellToken,
+from rpython.jit.metainterp.resoperation import (
+ ResOperation, rop, get_deep_immutable_oplist, OpHelpers, InputArgInt,
+ InputArgRef, InputArgFloat)
+from rpython.jit.metainterp.history import (TreeLoop, JitCellToken,
TargetToken, AbstractFailDescr, ConstInt)
from rpython.jit.metainterp import history, jitexc
from rpython.jit.metainterp.optimize import InvalidLoop
-from rpython.jit.metainterp.resume import (PENDINGFIELDSP,
- ResumeDataDirectReader, AccumInfo)
+from rpython.jit.metainterp.resume import (
+ PENDINGFIELDSP, ResumeDataDirectReader)
from rpython.jit.metainterp.resumecode import NUMBERING
from rpython.jit.metainterp.support import adr2int
from rpython.jit.codewriter import longlong
@@ -30,6 +29,9 @@
raise SwitchToBlackhole(Counters.ABORT_BRIDGE)
class CompileData(object):
+ """ An object that accumulates all of the necessary info for
+ the optimization phase, but does not actually have any other state
+ """
memo = None
log_noopt = True
@@ -37,10 +39,28 @@
for arg in self.trace.inputargs:
arg.set_forwarded(None)
-class LoopCompileData(CompileData):
- """ An object that accumulates all of the necessary info for
- the optimization phase, but does not actually have any other state
+ def optimize_trace(self, metainterp_sd, jitdriver_sd, memo):
+ """Optimize loop.operations to remove internal overheadish operations.
+ """
+ from rpython.jit.metainterp.optimizeopt import build_opt_chain
+ # mark that a new trace has been started
+ log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE, metainterp_sd, None)
+ log.write_trace(self.trace)
+ if self.log_noopt:
+ metainterp_sd.logger_noopt.log_loop_from_trace(self.trace, memo=memo)
+ self.box_names_memo = memo
+ optimizations = build_opt_chain(self.enable_opts)
+ debug_start("jit-optimize")
+ try:
+ return self.optimize(metainterp_sd, jitdriver_sd, optimizations)
+ finally:
+ self.forget_optimization_info()
+ debug_stop("jit-optimize")
+
+
+class PreambleCompileData(CompileData):
+ """
This is the case of label() ops label()
"""
def __init__(self, trace, runtime_boxes, call_pure_results=None,
@@ -51,19 +71,12 @@
assert runtime_boxes is not None
self.runtime_boxes = runtime_boxes
- def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
- from rpython.jit.metainterp.optimizeopt.unroll import (UnrollOptimizer,
- Optimizer)
-
- if unroll:
- opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
- return opt.optimize_preamble(self.trace,
- self.runtime_boxes,
- self.call_pure_results,
- self.box_names_memo)
- else:
- opt = Optimizer(metainterp_sd, jitdriver_sd, optimizations)
- return opt.propagate_all_forward(self.trace, self.call_pure_results)
+ def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
+ from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
+ opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
+ return opt.optimize_preamble(
+ self.trace, self.runtime_boxes, self.call_pure_results,
+ self.box_names_memo)
class SimpleCompileData(CompileData):
""" This represents label() ops jump with no extra info associated with
@@ -76,26 +89,19 @@
self.call_pure_results = call_pure_results
self.enable_opts = enable_opts
- def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+ def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
- from rpython.jit.metainterp.optimizeopt.bridgeopt import deserialize_optimizer_knowledge
-
- #assert not unroll
opt = Optimizer(metainterp_sd, jitdriver_sd, optimizations)
- traceiter = self.trace.get_iter()
- if self.resumestorage:
- frontend_inputargs = self.trace.inputargs
- deserialize_optimizer_knowledge(opt, self.resumestorage,
- frontend_inputargs,
- traceiter.inputargs)
- return opt.propagate_all_forward(traceiter, self.call_pure_results)
+ return opt.optimize_loop(
+ self.trace, self.resumestorage, self.call_pure_results)
class BridgeCompileData(CompileData):
""" This represents ops() with a jump at the end that goes to some
loop, we need to deal with virtual state and inlining of short preamble
"""
- def __init__(self, trace, runtime_boxes, resumestorage=None, call_pure_results=None,
- enable_opts=None, inline_short_preamble=False):
+ def __init__(self, trace, runtime_boxes, resumestorage=None,
+ call_pure_results=None, enable_opts=None,
+ inline_short_preamble=False):
self.trace = trace
self.runtime_boxes = runtime_boxes
self.call_pure_results = call_pure_results
@@ -103,7 +109,7 @@
self.inline_short_preamble = inline_short_preamble
self.resumestorage = resumestorage
- def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+ def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
@@ -115,29 +121,26 @@
class UnrolledLoopData(CompileData):
""" This represents label() ops jump with extra info that's from the
- run of LoopCompileData. Jump goes to the same label
+ run of PreambleCompileData. Jump goes to the same label
"""
log_noopt = False
def __init__(self, trace, celltoken, state,
- call_pure_results=None, enable_opts=None,
- inline_short_preamble=True):
+ call_pure_results=None, enable_opts=None):
self.trace = trace
self.celltoken = celltoken
self.enable_opts = enable_opts
self.state = state
self.call_pure_results = call_pure_results
- self.inline_short_preamble = inline_short_preamble
- def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+ def optimize(self, metainterp_sd, jitdriver_sd, optimizations):
from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
-
- assert unroll # we should not be here if it's disabled
opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
- return opt.optimize_peeled_loop(self.trace, self.celltoken, self.state,
- self.call_pure_results, self.inline_short_preamble)
+ return opt.optimize_peeled_loop(
+ self.trace, self.celltoken, self.state, self.call_pure_results)
def show_procedures(metainterp_sd, procedure=None, error=None):
+ from rpython.conftest import option
# debugging
if option and (option.view or option.viewloops):
if error:
@@ -173,19 +176,14 @@
original_jitcell_token = loop.original_jitcell_token
assert original_jitcell_token is not None
if metainterp_sd.warmrunnerdesc is not None: # for tests
- assert original_jitcell_token.generation > 0 # has been registered with memmgr
+ assert original_jitcell_token.generation > 0 # has been registered with memmgr
wref = weakref.ref(original_jitcell_token)
clt = original_jitcell_token.compiled_loop_token
clt.loop_token_wref = wref
for op in loop.operations:
descr = op.getdescr()
- # not sure what descr.index is about
if isinstance(descr, ResumeDescr):
descr.rd_loop_token = clt # stick it there
- #n = descr.index
- #if n >= 0: # we also record the resumedescr number
- # original_jitcell_token.compiled_loop_token.record_faildescr_index(n)
- # pass
if isinstance(descr, JitCellToken):
# for a CALL_ASSEMBLER: record it as a potential jump.
if descr is not original_jitcell_token:
@@ -215,11 +213,8 @@
# ____________________________________________________________
-
def compile_simple_loop(metainterp, greenkey, trace, runtime_args, enable_opts,
cut_at):
- from rpython.jit.metainterp.optimizeopt import optimize_trace
-
jitdriver_sd = metainterp.jitdriver_sd
metainterp_sd = metainterp.staticdata
jitcell_token = make_jitcell_token(jitdriver_sd)
@@ -227,8 +222,8 @@
data = SimpleCompileData(trace, call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
- loop_info, ops = optimize_trace(metainterp_sd, jitdriver_sd,
- data, metainterp.box_names_memo)
+ loop_info, ops = data.optimize_trace(
+ metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
except InvalidLoop:
metainterp_sd.jitlog.trace_aborted()
trace.cut_at(cut_at)
@@ -253,12 +248,10 @@
return target_token
def compile_loop(metainterp, greenkey, start, inputargs, jumpargs,
- full_preamble_needed=True, try_disabling_unroll=False):
+ use_unroll=True):
"""Try to compile a new procedure by closing the current history back
to the first operation.
"""
- from rpython.jit.metainterp.optimizeopt import optimize_trace
-
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
history = metainterp.history
@@ -269,28 +262,21 @@
faildescr=None, entry_bridge=False)
#
enable_opts = jitdriver_sd.warmstate.enable_opts
- if try_disabling_unroll:
- if 'unroll' not in enable_opts:
- return None
- enable_opts = enable_opts.copy()
- del enable_opts['unroll']
-
jitcell_token = make_jitcell_token(jitdriver_sd)
cut_at = history.get_trace_position()
history.record(rop.JUMP, jumpargs, None, descr=jitcell_token)
if start != (0, 0, 0):
trace = trace.cut_trace_from(start, inputargs)
- if 'unroll' not in enable_opts or not metainterp.cpu.supports_guard_gc_type:
+ if not use_unroll:
return compile_simple_loop(metainterp, greenkey, trace, jumpargs,
enable_opts, cut_at)
call_pure_results = metainterp.call_pure_results
- preamble_data = LoopCompileData(trace, jumpargs,
+ preamble_data = PreambleCompileData(trace, jumpargs,
call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
- start_state, preamble_ops = optimize_trace(metainterp_sd, jitdriver_sd,
- preamble_data,
- metainterp.box_names_memo)
+ start_state, preamble_ops = preamble_data.optimize_trace(
+ metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
except InvalidLoop:
metainterp_sd.jitlog.trace_aborted()
history.cut(cut_at)
@@ -305,9 +291,8 @@
call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
- loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd,
- loop_data,
- metainterp.box_names_memo)
+ loop_info, loop_ops = loop_data.optimize_trace(
+ metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
except InvalidLoop:
metainterp_sd.jitlog.trace_aborted()
history.cut(cut_at)
@@ -354,8 +339,6 @@
"""Try to compile a new procedure by closing the current history back
to the first operation.
"""
- from rpython.jit.metainterp.optimizeopt import optimize_trace
-
trace = metainterp.history.trace.cut_trace_from(start, inputargs)
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
@@ -375,29 +358,14 @@
call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
- loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd,
- loop_data,
- metainterp.box_names_memo)
+ loop_info, loop_ops = loop_data.optimize_trace(
+ metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
except InvalidLoop:
- # Fall back on jumping directly to preamble
+ metainterp_sd.jitlog.trace_aborted()
history.cut(cut)
- history.record(rop.JUMP, jumpargs[:], None, descr=loop_jitcell_token)
- loop_data = UnrolledLoopData(trace, loop_jitcell_token, start_state,
- call_pure_results=call_pure_results,
- enable_opts=enable_opts,
- inline_short_preamble=False)
- try:
- loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd,
- loop_data,
- metainterp.box_names_memo)
- except InvalidLoop:
- metainterp_sd.jitlog.trace_aborted()
- history.cut(cut)
- return None
+ return None
label_op = loop_info.label_op
- if label_op is None:
- assert False, "unreachable code" # hint for some strange tests
label_token = label_op.getdescr()
assert isinstance(label_token, TargetToken)
if label_token.short_preamble:
@@ -405,9 +373,8 @@
label_token.short_preamble, metainterp.box_names_memo)
loop = partial_trace
loop.original_jitcell_token = loop_jitcell_token
- loop.operations = (loop.operations + loop_info.extra_same_as +
- [loop_info.label_op]
- + loop_ops)
+ loop.operations = (
+ loop.operations + loop_info.extra_same_as + [label_op] + loop_ops)
quasi_immutable_deps = {}
if loop_info.quasi_immutable_deps:
@@ -419,8 +386,6 @@
target_token = loop.operations[-1].getdescr()
resumekey.compile_and_attach(metainterp, loop, inputargs)
-
- record_loop_or_bridge(metainterp_sd, loop)
return target_token
def get_box_replacement(op, allow_none=False):
@@ -828,6 +793,7 @@
self, inputargs, new_loop.operations,
new_loop.original_jitcell_token,
metainterp.box_names_memo)
+ record_loop_or_bridge(metainterp.staticdata, new_loop)
def make_a_counter_per_value(self, guard_value_op, index):
assert guard_value_op.getopnum() == rop.GUARD_VALUE
@@ -1038,18 +1004,16 @@
jitdriver_sd.warmstate.attach_procedure_to_interp(
self.original_greenkey, jitcell_token)
metainterp_sd.stats.add_jitcell_token(jitcell_token)
+ record_loop_or_bridge(metainterp_sd, new_loop)
def get_resumestorage(self):
return None
-def compile_trace(metainterp, resumekey, runtime_boxes):
+def compile_trace(metainterp, resumekey, runtime_boxes, ends_with_jump=False):
"""Try to compile a new bridge leading from the beginning of the history
to some existing place.
"""
-
- from rpython.jit.metainterp.optimizeopt import optimize_trace
-
# The history contains new operations to attach as the code for the
# failure of 'resumekey.guard_op'.
#
@@ -1058,11 +1022,6 @@
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
- #
- jd_name = jitdriver_sd.jitdriver.name
- metainterp_sd.jitlog.start_new_trace(metainterp_sd,
- faildescr=resumekey, entry_bridge=False, jd_name=jd_name)
- #
if isinstance(resumekey, ResumeAtPositionDescr):
inline_short_preamble = False
else:
@@ -1071,11 +1030,15 @@
trace = metainterp.history.trace
jitdriver_sd = metainterp.jitdriver_sd
enable_opts = jitdriver_sd.warmstate.enable_opts
-
call_pure_results = metainterp.call_pure_results
resumestorage = resumekey.get_resumestorage()
- if metainterp.history.ends_with_jump:
+ trace.tracing_done()
+ metainterp_sd.jitlog.start_new_trace(metainterp_sd,
+ faildescr=resumekey, entry_bridge=False,
+ jd_name=jitdriver_sd.jitdriver.name)
+
+ if ends_with_jump:
data = BridgeCompileData(trace, runtime_boxes, resumestorage,
call_pure_results=call_pure_results,
enable_opts=enable_opts,
@@ -1085,12 +1048,10 @@
call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
- info, newops = optimize_trace(metainterp_sd, jitdriver_sd,
- data, metainterp.box_names_memo)
+ info, newops = data.optimize_trace(
+ metainterp_sd, jitdriver_sd, metainterp.box_names_memo)
except InvalidLoop:
metainterp_sd.jitlog.trace_aborted()
- #pdb.post_mortem(sys.exc_info()[2])
- debug_print("compile_new_bridge: got an InvalidLoop")
# XXX I am fairly convinced that optimize_bridge cannot actually raise
# InvalidLoop
debug_print('InvalidLoop in compile_new_bridge')
@@ -1104,7 +1065,6 @@
new_trace.inputargs = info.inputargs
target_token = new_trace.operations[-1].getdescr()
resumekey.compile_and_attach(metainterp, new_trace, inputargs)
- record_loop_or_bridge(metainterp_sd, new_trace)
return target_token
new_trace.inputargs = info.renamed_inputargs
metainterp.retrace_needed(new_trace, info)
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -689,7 +689,6 @@
class History(object):
- ends_with_jump = False
trace = None
def __init__(self):
diff --git a/rpython/jit/metainterp/opencoder.py b/rpython/jit/metainterp/opencoder.py
--- a/rpython/jit/metainterp/opencoder.py
+++ b/rpython/jit/metainterp/opencoder.py
@@ -7,12 +7,13 @@
"""
from rpython.jit.metainterp.history import (
- ConstInt, Const, ConstFloat, ConstPtr, new_ref_dict)
+ ConstInt, Const, ConstFloat, ConstPtr, new_ref_dict, SwitchToBlackhole)
from rpython.jit.metainterp.resoperation import AbstractResOp, AbstractInputArg,\
ResOperation, oparity, rop, opwithdescr, GuardResOp, IntOp, FloatOp, RefOp,\
opclasses
from rpython.rlib.rarithmetic import intmask, r_uint
from rpython.rlib.objectmodel import we_are_translated, specialize
+from rpython.rlib.jit import Counters
from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
TAGINT, TAGCONSTPTR, TAGCONSTOTHER, TAGBOX = range(4)
@@ -301,7 +302,8 @@
def tracing_done(self):
from rpython.rlib.debug import debug_start, debug_stop, debug_print
- assert not self.tag_overflow
+ if self.tag_overflow:
+ raise SwitchToBlackhole(Counters.ABORT_TOO_LONG)
self._bigints_dict = {}
self._refs_dict = new_ref_dict()
diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py
--- a/rpython/jit/metainterp/optimizeopt/__init__.py
+++ b/rpython/jit/metainterp/optimizeopt/__init__.py
@@ -1,4 +1,3 @@
-from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
from rpython.jit.metainterp.optimizeopt.rewrite import OptRewrite
from rpython.jit.metainterp.optimizeopt.intbounds import OptIntBounds
from rpython.jit.metainterp.optimizeopt.virtualize import OptVirtualize
@@ -7,10 +6,8 @@
from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify
from rpython.jit.metainterp.optimizeopt.pure import OptPure
from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce
-from rpython.rlib.rjitlog import rjitlog as jl
from rpython.rlib.jit import PARAMETERS, ENABLE_ALL_OPTS
from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.debug import debug_start, debug_stop, debug_print
ALL_OPTS = [('intbounds', OptIntBounds),
@@ -31,45 +28,17 @@
assert ENABLE_ALL_OPTS == ALL_OPTS_NAMES, (
'please fix rlib/jit.py to say ENABLE_ALL_OPTS = %r' % (ALL_OPTS_NAMES,))
-def build_opt_chain(metainterp_sd, enable_opts):
+def build_opt_chain(enable_opts):
optimizations = []
- unroll = 'unroll' in enable_opts # 'enable_opts' is normally a dict
- if (metainterp_sd.cpu is not None and
- not metainterp_sd.cpu.supports_guard_gc_type):
- unroll = False
for name, opt in unroll_all_opts:
if name in enable_opts:
if opt is not None:
o = opt()
optimizations.append(o)
-
- if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts
- or 'heap' not in enable_opts or 'pure' not in enable_opts):
- optimizations.append(OptSimplify(unroll))
-
- return optimizations, unroll
-
-def optimize_trace(metainterp_sd, jitdriver_sd, compile_data, memo=None):
- """Optimize loop.operations to remove internal overheadish operations.
- """
- debug_start("jit-optimize")
- try:
- # mark that a new trace has been started
- log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE, metainterp_sd, None)
- log.write_trace(compile_data.trace)
- if compile_data.log_noopt:
- metainterp_sd.logger_noopt.log_loop_from_trace(compile_data.trace, memo=memo)
- if memo is None:
- memo = {}
- compile_data.box_names_memo = memo
- optimizations, unroll = build_opt_chain(metainterp_sd,
- compile_data.enable_opts)
- return compile_data.optimize(metainterp_sd, jitdriver_sd,
- optimizations, unroll)
- finally:
- compile_data.forget_optimization_info()
- debug_stop("jit-optimize")
+ if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts or
+ 'heap' not in enable_opts or 'pure' not in enable_opts):
+ optimizations.append(OptSimplify())
+ return optimizations
if __name__ == '__main__':
print ALL_OPTS_NAMES
-
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
@@ -3,6 +3,7 @@
from rpython.jit.metainterp import resumecode
from rpython.jit.metainterp.history import Const, ConstInt, CONST_NULL
+from .info import getptrinfo
# adds the following sections at the end of the resume code:
@@ -75,7 +76,7 @@
for box in liveboxes:
if box is None or box.type != "r":
continue
- info = optimizer.getptrinfo(box)
+ info = getptrinfo(box)
known_class = info is not None and info.get_known_class(optimizer.cpu) is not None
bitfield <<= 1
bitfield |= known_class
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
@@ -1,26 +1,19 @@
-import os
from collections import OrderedDict
from rpython.jit.codewriter.effectinfo import EffectInfo
from rpython.jit.metainterp.optimizeopt.util import args_dict
-from rpython.jit.metainterp.history import Const, ConstInt, new_ref_dict
-from rpython.jit.metainterp.jitexc import JitException
+from rpython.jit.metainterp.history import new_ref_dict
from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.optimizeopt.util import (
+ make_dispatcher_method, get_box_replacement)
from rpython.jit.metainterp.optimizeopt.intutils import IntBound
from rpython.jit.metainterp.optimizeopt.shortpreamble import PreambleOp
from rpython.jit.metainterp.optimize import InvalidLoop
-from rpython.jit.metainterp.resoperation import rop, ResOperation, OpHelpers,\
- GuardResOp
+from rpython.jit.metainterp.resoperation import rop
from rpython.rlib.objectmodel import we_are_translated
from rpython.jit.metainterp.optimizeopt import info
-
-class BogusImmutableField(JitException):
- pass
-
-
class AbstractCachedEntry(object):
""" abstract base class abstracting over the difference between caching
struct fields and array items. """
@@ -56,40 +49,32 @@
descr, index=-1):
assert self._lazy_set is None
for i, info in enumerate(self.cached_infos):
- structbox = optimizer.get_box_replacement(self.cached_structs[i])
+ structbox = get_box_replacement(self.cached_structs[i])
info.produce_short_preamble_ops(structbox, descr, index, optimizer,
shortboxes)
- def possible_aliasing(self, optheap, opinfo):
+ def possible_aliasing(self, opinfo):
# If lazy_set is set and contains a setfield on a different
# structvalue, then we are annoyed, because it may point to either
# the same or a different structure at runtime.
# XXX constants?
return (self._lazy_set is not None
- and (not optheap.getptrinfo(
- self._lazy_set.getarg(0)).same_info(opinfo)))
+ and not info.getptrinfo(self._lazy_set.getarg(0)).same_info(opinfo))
def do_setfield(self, optheap, op):
# Update the state with the SETFIELD_GC/SETARRAYITEM_GC operation 'op'.
structinfo = optheap.ensure_ptr_info_arg0(op)
- arg1 = optheap.get_box_replacement(self._get_rhs_from_set_op(op))
- if self.possible_aliasing(optheap, structinfo):
+ arg1 = get_box_replacement(self._get_rhs_from_set_op(op))
+ if self.possible_aliasing(structinfo):
self.force_lazy_set(optheap, op.getdescr())
- assert not self.possible_aliasing(optheap, structinfo)
+ assert not self.possible_aliasing(structinfo)
cached_field = self._getfield(structinfo, op.getdescr(), optheap, False)
if cached_field is not None:
- cached_field = optheap.get_box_replacement(cached_field)
-
- # Hack to ensure constants are imported from the preamble
- # XXX no longer necessary?
- #if cached_fieldvalue and fieldvalue.is_constant():
- # optheap.optimizer.ensure_imported(cached_fieldvalue)
- # cached_fieldvalue = self._cached_fields.get(structvalue, None)
+ cached_field = cached_field.get_box_replacement()
if not cached_field or not cached_field.same_box(arg1):
# common case: store the 'op' as lazy_set
self._lazy_set = op
-
else:
# this is the case where the pending setfield ends up
# storing precisely the value that is already there,
@@ -104,11 +89,11 @@
def getfield_from_cache(self, optheap, opinfo, descr):
# Returns the up-to-date field's value, or None if not cached.
- if self.possible_aliasing(optheap, opinfo):
+ if self.possible_aliasing(opinfo):
self.force_lazy_set(optheap, descr)
if self._lazy_set is not None:
op = self._lazy_set
- return optheap.get_box_replacement(self._get_rhs_from_set_op(op))
+ return get_box_replacement(self._get_rhs_from_set_op(op))
else:
res = self._getfield(opinfo, descr, optheap)
if res is not None:
@@ -140,7 +125,6 @@
elif not can_cache:
self.invalidate(descr)
-
# abstract methods
def _get_rhs_from_set_op(self, op):
@@ -167,8 +151,8 @@
return op.getarg(1)
def put_field_back_to_info(self, op, opinfo, optheap):
- arg = optheap.get_box_replacement(op.getarg(1))
- struct = optheap.get_box_replacement(op.getarg(0))
+ arg = get_box_replacement(op.getarg(1))
+ struct = get_box_replacement(op.getarg(0))
opinfo.setfield(op.getdescr(), struct, arg, optheap=optheap, cf=self)
def _getfield(self, opinfo, descr, optheap, true_force=True):
@@ -216,8 +200,8 @@
return res
def put_field_back_to_info(self, op, opinfo, optheap):
- arg = optheap.get_box_replacement(op.getarg(2))
- struct = optheap.get_box_replacement(op.getarg(0))
+ arg = get_box_replacement(op.getarg(2))
+ struct = get_box_replacement(op.getarg(0))
opinfo.setitem(op.getdescr(), self.index, struct, arg, optheap=optheap, cf=self)
def invalidate(self, descr):
@@ -412,8 +396,8 @@
d = self.cached_dict_reads[descr1] = args_dict()
self.corresponding_array_descrs[descrs[1]] = descr1
#
- key = [self.optimizer.get_box_replacement(op.getarg(1)), # dict
- self.optimizer.get_box_replacement(op.getarg(2))] # key
+ key = [get_box_replacement(op.getarg(1)), # dict
+ get_box_replacement(op.getarg(2))] # key
# other args can be ignored here (hash, store_flag)
try:
res_v = d[key]
@@ -525,7 +509,7 @@
# guards' resume data is that of a virtual object that is stored
# into a field of a non-virtual object. Here, 'op' in either
# SETFIELD_GC or SETARRAYITEM_GC.
- opinfo = self.getptrinfo(op.getarg(0))
+ opinfo = info.getptrinfo(op.getarg(0))
assert not opinfo.is_virtual() # it must be a non-virtual
if self.optimizer.is_virtual(op.getarg(2)):
pendingfields.append(op)
@@ -564,13 +548,6 @@
def optimize_SETFIELD_GC(self, op):
self.setfield(op)
- #opnum = OpHelpers.getfield_pure_for_descr(op.getdescr())
- #if self.has_pure_result(opnum, [op.getarg(0)],
- # op.getdescr()):
- # os.write(2, '[bogus _immutable_field_ declaration: %s]\n' %
- # (op.getdescr().repr_of_descr()))
- # raise BogusImmutableField
- #
def setfield(self, op):
cf = self.field_cache(op.getdescr())
@@ -606,8 +583,8 @@
index = indexb.getint()
cf = self.arrayitem_cache(op.getdescr(), index)
arrayinfo.setitem(op.getdescr(), indexb.getint(),
- self.get_box_replacement(op.getarg(0)),
- self.get_box_replacement(op), optheap=self,
+ get_box_replacement(op.getarg(0)),
+ get_box_replacement(op), optheap=self,
cf=cf)
optimize_GETARRAYITEM_GC_R = optimize_GETARRAYITEM_GC_I
optimize_GETARRAYITEM_GC_F = optimize_GETARRAYITEM_GC_I
@@ -639,13 +616,6 @@
optimize_GETARRAYITEM_GC_PURE_F = optimize_GETARRAYITEM_GC_PURE_I
def optimize_SETARRAYITEM_GC(self, op):
- #opnum = OpHelpers.getarrayitem_pure_for_descr(op.getdescr())
- #if self.has_pure_result(opnum, [op.getarg(0), op.getarg(1)],
- # op.getdescr()):
- # os.write(2, '[bogus immutable array declaration: %s]\n' %
- # (op.getdescr().repr_of_descr()))
- # raise BogusImmutableField
- #
indexb = self.getintbound(op.getarg(1))
if indexb.is_constant():
arrayinfo = self.ensure_ptr_info_arg0(op)
@@ -680,8 +650,7 @@
# check that the value is still correct; it could have changed
# already between the tracing and now. In this case, we mark the loop
# as invalid
- if not qmutdescr.is_still_valid_for(
- self.get_box_replacement(op.getarg(0))):
+ if not qmutdescr.is_still_valid_for(get_box_replacement(op.getarg(0))):
raise InvalidLoop('quasi immutable field changed during tracing')
# record as an out-of-line guard
if self.optimizer.quasi_immutable_deps is None:
@@ -701,10 +670,10 @@
result_getfield = []
for descr, cf in self.cached_fields.iteritems():
if cf._lazy_set:
- continue # XXX safe default for now
+ continue # XXX safe default for now
parent_descr = descr.get_parent_descr()
if not parent_descr.is_object():
- continue # XXX could be extended to non-instance objects
+ continue # XXX could be extended to non-instance objects
for i, box1 in enumerate(cf.cached_structs):
if not box1.is_constant() and box1 not in available_boxes:
continue
@@ -721,7 +690,7 @@
for descr, indexdict in self.cached_arrayitems.iteritems():
for index, cf in indexdict.iteritems():
if cf._lazy_set:
- continue # XXX safe default for now
+ 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
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -1,13 +1,14 @@
-from rpython.rlib.objectmodel import specialize, we_are_translated, compute_hash
-from rpython.jit.metainterp.resoperation import AbstractValue, ResOperation,\
- rop, OpHelpers
-from rpython.jit.metainterp.history import ConstInt, Const
-from rpython.rtyper.lltypesystem import lltype, llmemory
-from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation
+from rpython.rlib.objectmodel import specialize, compute_hash
+from rpython.jit.metainterp.resoperation import (
+ AbstractValue, ResOperation, rop, OpHelpers)
+from rpython.jit.metainterp.history import ConstInt, ConstPtr, Const
+from rpython.rtyper.lltypesystem import lltype
+from rpython.jit.metainterp.optimizeopt.rawbuffer import (
+ RawBuffer, InvalidRawOperation)
from rpython.jit.metainterp.executor import execute
from rpython.jit.metainterp.optimize import InvalidLoop
-
+from .util import get_box_replacement
INFO_NULL = 0
INFO_NONNULL = 1
@@ -51,7 +52,7 @@
def force_at_the_end_of_preamble(self, op, optforce, rec):
if not self.is_virtual():
- return optforce.get_box_replacement(op)
+ return get_box_replacement(op)
return self._force_at_the_end_of_preamble(op, optforce, rec)
def get_known_class(self, cpu):
@@ -84,7 +85,7 @@
@specialize.arg(2)
def get_constant_string_spec(self, string_optimizer, mode):
- return None # can't be constant
+ return None # can't be constant
class NonNullPtrInfo(PtrInfo):
_attrs_ = ('last_guard_pos',)
@@ -109,7 +110,7 @@
def mark_last_guard(self, optimizer):
if (optimizer.getlastop() is None or
- not optimizer.getlastop().is_guard()):
+ not optimizer.getlastop().is_guard()):
# there can be a really emitted operation that's not a guard
# e.g. a setfield, ignore those
return
@@ -140,12 +141,12 @@
constptr = optforce.optimizer.constant_fold(op)
op.set_forwarded(constptr)
self._is_virtual = False
- self._force_elements_immutable(self.descr, constptr, optforce)
+ self._force_elements_immutable(self.descr, constptr, optforce.optimizer)
return constptr
#
op.set_forwarded(None)
optforce.emit_extra(op)
- newop = optforce.getlastop()
+ newop = optforce.optimizer.getlastop()
if newop is not op:
op.set_forwarded(newop)
newop.set_forwarded(self)
@@ -161,14 +162,14 @@
def is_virtual(self):
return self._is_virtual
- def _visitor_walk_recursive(self, op, visitor, optimizer):
+ def _visitor_walk_recursive(self, op, visitor):
raise NotImplementedError("abstract")
- def visitor_walk_recursive(self, instbox, visitor, optimizer):
+ def visitor_walk_recursive(self, instbox, visitor):
instbox = instbox.get_box_replacement()
if visitor.already_seen_virtual(instbox):
return
- return self._visitor_walk_recursive(instbox, visitor, optimizer)
+ return self._visitor_walk_recursive(instbox, visitor)
class AbstractStructPtrInfo(AbstractVirtualPtrInfo):
@@ -181,7 +182,7 @@
self.descr = descr
self._fields = [None] * len(descr.get_all_fielddescrs())
if index >= len(self._fields):
- self.descr = descr # a more precise descr
+ self.descr = descr # a more precise descr
# we found out a subclass with more fields
extra_len = len(descr.get_all_fielddescrs()) - len(self._fields)
self._fields = self._fields + [None] * extra_len
@@ -218,7 +219,7 @@
for i, fielddescr in enumerate(descr.get_all_fielddescrs()):
fld = self._fields[i]
if fld is not None:
- subbox = optforce.force_box(fld)
+ subbox = optforce.optimizer.force_box(fld)
setfieldop = ResOperation(rop.SETFIELD_GC, [op, subbox],
descr=fielddescr)
self._fields[i] = None
@@ -226,31 +227,30 @@
def _force_at_the_end_of_preamble(self, op, optforce, rec):
if self._fields is None:
- return optforce.get_box_replacement(op)
+ return get_box_replacement(op)
if self in rec:
- return optforce.get_box_replacement(op)
+ return get_box_replacement(op)
rec[self] = None
for i, fldbox in enumerate(self._fields):
if fldbox is not None:
- info = optforce.getptrinfo(fldbox)
+ info = getptrinfo(fldbox)
if info is not None:
fldbox = info.force_at_the_end_of_preamble(fldbox, optforce,
rec)
self._fields[i] = fldbox
return op
- def _visitor_walk_recursive(self, instbox, visitor, optimizer):
+ def _visitor_walk_recursive(self, instbox, visitor):
lst = self.descr.get_all_fielddescrs()
assert self.is_virtual()
- visitor.register_virtual_fields(instbox,
- [optimizer.get_box_replacement(box)
- for box in self._fields])
+ visitor.register_virtual_fields(
+ instbox, [get_box_replacement(box) for box in self._fields])
for i in range(len(lst)):
op = self._fields[i]
if op:
- fieldinfo = optimizer.getptrinfo(op)
+ fieldinfo = getptrinfo(op)
if fieldinfo and fieldinfo.is_virtual():
- fieldinfo.visitor_walk_recursive(op, visitor, optimizer)
+ fieldinfo.visitor_walk_recursive(op, visitor)
def produce_short_preamble_ops(self, structbox, fielddescr, index, optimizer,
shortboxes):
@@ -259,7 +259,7 @@
if fielddescr.get_index() >= len(self._fields):
# we don't know about this item
return
- op = optimizer.get_box_replacement(self._fields[fielddescr.get_index()])
+ op = get_box_replacement(self._fields[fielddescr.get_index()])
if op is None:
# XXX same bug as in serialize_opt:
# op should never be None, because that's an invariant violation in
@@ -290,7 +290,7 @@
if op.is_constant():
pass # it is a constant value: ok
else:
- fieldinfo = optimizer.getptrinfo(op)
+ fieldinfo = getptrinfo(op)
if fieldinfo and fieldinfo.is_virtual():
# recursive check
if memo is None:
@@ -302,12 +302,12 @@
return False # not a constant at all
return True
- def _force_elements_immutable(self, descr, constptr, optforce):
+ def _force_elements_immutable(self, descr, constptr, optimizer):
for i, fielddescr in enumerate(descr.get_all_fielddescrs()):
fld = self._fields[i]
- subbox = optforce.force_box(fld)
+ subbox = optimizer.force_box(fld)
assert isinstance(subbox, Const)
- execute(optforce.optimizer.cpu, None, rop.SETFIELD_GC,
+ execute(optimizer.cpu, None, rop.SETFIELD_GC,
fielddescr, constptr, subbox)
class InstancePtrInfo(AbstractStructPtrInfo):
@@ -435,8 +435,8 @@
[op, ConstInt(offset), itembox], descr=descr)
optforce.emit_extra(setfield_op)
- def _visitor_walk_recursive(self, op, visitor, optimizer):
- itemboxes = [optimizer.get_box_replacement(box)
+ def _visitor_walk_recursive(self, op, visitor):
+ itemboxes = [get_box_replacement(box)
for box in self._get_buffer().values]
visitor.register_virtual_fields(op, itemboxes)
# there can be no virtuals stored in raw buffer
@@ -465,21 +465,21 @@
return self.parent is not None
def getitem_raw(self, offset, itemsize, descr):
- return self.parent.getitem_raw(self.offset+offset, itemsize, descr)
+ return self.parent.getitem_raw(self.offset + offset, itemsize, descr)
def setitem_raw(self, offset, itemsize, descr, itemop):
- self.parent.setitem_raw(self.offset+offset, itemsize, descr, itemop)
+ self.parent.setitem_raw(self.offset + offset, itemsize, descr, itemop)
def _force_elements(self, op, optforce, descr):
if self.parent.is_virtual():
self.parent._force_elements(op, optforce, descr)
self.parent = None
- def _visitor_walk_recursive(self, op, visitor, optimizer):
- source_op = optimizer.get_box_replacement(op.getarg(0))
+ def _visitor_walk_recursive(self, op, visitor):
+ source_op = get_box_replacement(op.getarg(0))
visitor.register_virtual_fields(op, [source_op])
if self.parent.is_virtual():
- self.parent.visitor_walk_recursive(source_op, visitor, optimizer)
+ self.parent.visitor_walk_recursive(source_op, visitor)
@specialize.argtype(1)
def visitor_dispatch_virtual_type(self, visitor):
@@ -534,7 +534,7 @@
def _force_elements(self, op, optforce, descr):
# XXX
descr = op.getdescr()
- const = optforce.new_const_item(self.descr)
+ const = optforce.optimizer.new_const_item(self.descr)
for i in range(self.length):
item = self._items[i]
if item is None:
@@ -543,7 +543,7 @@
# clear the item so we don't know what's there
self._items[i] = None
continue
- subbox = optforce.force_box(item)
+ subbox = optforce.optimizer.force_box(item)
setop = ResOperation(rop.SETARRAYITEM_GC,
[op, ConstInt(i), subbox],
descr=descr)
@@ -570,17 +570,15 @@
def getlength(self):
return self.length
- def _visitor_walk_recursive(self, instbox, visitor, optimizer):
- itemops = [optimizer.get_box_replacement(item)
- for item in self._items]
+ def _visitor_walk_recursive(self, instbox, visitor):
+ itemops = [get_box_replacement(item) for item in self._items]
visitor.register_virtual_fields(instbox, itemops)
for i in range(self.getlength()):
itemop = self._items[i]
- if (itemop is not None and
- not isinstance(itemop, Const)):
- ptrinfo = optimizer.getptrinfo(itemop)
+ if (itemop is not None and not isinstance(itemop, Const)):
+ ptrinfo = getptrinfo(itemop)
if ptrinfo and ptrinfo.is_virtual():
- ptrinfo.visitor_walk_recursive(itemop, visitor, optimizer)
+ ptrinfo.visitor_walk_recursive(itemop, visitor)
@specialize.argtype(1)
def visitor_dispatch_virtual_type(self, visitor):
@@ -596,7 +594,7 @@
item = self._items[index]
if item is not None:
# see comment in AbstractStructPtrInfo.produce_short_preamble_ops
- op = optimizer.get_box_replacement(item)
+ op = get_box_replacement(item)
opnum = OpHelpers.getarrayitem_for_descr(descr)
getarrayitem_op = ResOperation(opnum, [structbox, ConstInt(index)],
descr=descr)
@@ -604,13 +602,13 @@
def _force_at_the_end_of_preamble(self, op, optforce, rec):
if self._items is None:
- return optforce.get_box_replacement(op)
+ return get_box_replacement(op)
if self in rec:
- return optforce.get_box_replacement(op)
+ return get_box_replacement(op)
rec[self] = None
for i, fldbox in enumerate(self._items):
if fldbox is not None:
- info = optforce.getptrinfo(fldbox)
+ info = getptrinfo(fldbox)
if info is not None:
fldbox = info.force_at_the_end_of_preamble(fldbox, optforce,
rec)
@@ -640,7 +638,7 @@
def _compute_index(self, index, fielddescr):
all_fdescrs = fielddescr.get_arraydescr().get_all_fielddescrs()
if all_fdescrs is None:
- return 0 # annotation hack
+ return 0 # annotation hack
one_size = len(all_fdescrs)
return index * one_size + fielddescr.get_field_descr().get_index()
@@ -659,7 +657,7 @@
for fielddescr in fielddescrs:
fld = self._items[i]
if fld is not None:
- subbox = optforce.force_box(fld)
+ subbox = optforce.optimizer.force_box(fld)
setfieldop = ResOperation(rop.SETINTERIORFIELD_GC,
[op, ConstInt(index), subbox],
descr=fielddescr)
@@ -668,21 +666,18 @@
# if it does, we would need a fix here
i += 1
- def _visitor_walk_recursive(self, instbox, visitor, optimizer):
- itemops = [optimizer.get_box_replacement(item)
- for item in self._items]
+ def _visitor_walk_recursive(self, instbox, visitor):
+ itemops = [get_box_replacement(item) for item in self._items]
visitor.register_virtual_fields(instbox, itemops)
fielddescrs = self.descr.get_all_fielddescrs()
i = 0
for index in range(self.getlength()):
for fielddescr in fielddescrs:
itemop = self._items[i]
- if (itemop is not None and
- not isinstance(itemop, Const)):
- ptrinfo = optimizer.getptrinfo(itemop)
+ if (itemop is not None and not isinstance(itemop, Const)):
+ ptrinfo = getptrinfo(itemop)
if ptrinfo and ptrinfo.is_virtual():
- ptrinfo.visitor_walk_recursive(itemop, visitor,
- optimizer)
+ ptrinfo.visitor_walk_recursive(itemop, visitor)
i += 1
@specialize.argtype(1)
@@ -705,7 +700,8 @@
def _get_info(self, descr, optheap):
ref = self._const.getref_base()
- if not ref: raise InvalidLoop # null protection
+ if not ref:
+ raise InvalidLoop # null protection
info = optheap.const_infos.get(ref, None)
if info is None:
info = StructPtrInfo(descr)
@@ -714,7 +710,8 @@
def _get_array_info(self, descr, optheap):
ref = self._const.getref_base()
- if not ref: raise InvalidLoop # null protection
+ if not ref:
+ raise InvalidLoop # null protection
info = optheap.const_infos.get(ref, None)
if info is None:
info = ArrayPtrInfo(descr)
@@ -780,8 +777,8 @@
return self._unpack_str(mode)
def getlenbound(self, mode):
- from rpython.jit.metainterp.optimizeopt.intutils import ConstIntBound,\
- IntLowerBound
+ from rpython.jit.metainterp.optimizeopt.intutils import (
+ ConstIntBound, IntLowerBound)
length = self.getstrlen1(mode)
if length < 0:
@@ -848,3 +845,36 @@
def make_guards(self, op, short, optimizer):
short.append(ResOperation(rop.GUARD_VALUE, [op, self._const]))
+
+
+def getrawptrinfo(op):
+ from rpython.jit.metainterp.optimizeopt.intutils import IntBound
+ assert op.type == 'i'
+ op = op.get_box_replacement()
+ assert op.type == 'i'
+ if isinstance(op, ConstInt):
+ return ConstPtrInfo(op)
+ fw = op.get_forwarded()
+ if isinstance(fw, IntBound):
+ return None
+ if fw is not None:
+ assert isinstance(fw, AbstractRawPtrInfo)
+ return fw
+ return None
+
+def getptrinfo(op):
+ if op.type == 'i':
+ return getrawptrinfo(op)
+ elif op.type == 'f':
+ return None
+ assert op.type == 'r'
+ op = get_box_replacement(op)
+ assert op.type == 'r'
+ if isinstance(op, ConstPtr):
+ return ConstPtrInfo(op)
+ fw = op.get_forwarded()
+ if fw is not None:
+ assert isinstance(fw, PtrInfo)
+ return fw
+ return None
+
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -5,7 +5,9 @@
IntLowerBound, IntUpperBound, ConstIntBound)
from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, CONST_1,
CONST_0)
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.optimizeopt.util import (
+ make_dispatcher_method, get_box_replacement)
+from .info import getptrinfo
from rpython.jit.metainterp.resoperation import rop
from rpython.jit.metainterp.optimizeopt import vstring
from rpython.jit.codewriter.effectinfo import EffectInfo
@@ -64,8 +66,8 @@
postprocess_GUARD_VALUE = _postprocess_guard_true_false_value
def optimize_INT_OR_or_XOR(self, op):
- v1 = self.get_box_replacement(op.getarg(0))
- v2 = self.get_box_replacement(op.getarg(1))
+ v1 = get_box_replacement(op.getarg(0))
+ v2 = get_box_replacement(op.getarg(1))
if v1 is v2:
if op.getopnum() == rop.INT_OR:
self.make_equal_to(op, v1)
@@ -75,9 +77,9 @@
return self.emit(op)
def postprocess_INT_OR_or_XOR(self, op):
- v1 = self.get_box_replacement(op.getarg(0))
+ v1 = get_box_replacement(op.getarg(0))
b1 = self.getintbound(v1)
- v2 = self.get_box_replacement(op.getarg(1))
+ v2 = get_box_replacement(op.getarg(1))
b2 = self.getintbound(v2)
b = b1.or_bound(b2)
self.getintbound(op).intersect(b)
@@ -108,8 +110,8 @@
self.getintbound(op).intersect(b)
def optimize_INT_ADD(self, op):
- arg1 = self.get_box_replacement(op.getarg(0))
- arg2 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(0))
+ arg2 = get_box_replacement(op.getarg(1))
if self.is_raw_ptr(arg1) or self.is_raw_ptr(arg2):
return self.emit(op)
v1 = self.getintbound(arg1)
@@ -130,8 +132,8 @@
arg1 = self.optimizer.as_operation(arg1)
if arg1 is not None:
if arg1.getopnum() == rop.INT_ADD:
- prod_arg1 = self.get_box_replacement(arg1.getarg(0))
- prod_arg2 = self.get_box_replacement(arg1.getarg(1))
+ prod_arg1 = get_box_replacement(arg1.getarg(0))
+ prod_arg2 = get_box_replacement(arg1.getarg(1))
prod_v1 = self.getintbound(prod_arg1)
prod_v2 = self.getintbound(prod_arg2)
@@ -196,9 +198,9 @@
return self.emit(op)
def postprocess_INT_LSHIFT(self, op):
- arg0 = self.get_box_replacement(op.getarg(0))
+ arg0 = get_box_replacement(op.getarg(0))
b1 = self.getintbound(arg0)
- arg1 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(1))
b2 = self.getintbound(arg1)
r = self.getintbound(op)
b = b1.lshift_bound(b2)
@@ -290,8 +292,8 @@
r.intersect(resbound)
def optimize_INT_SUB_OVF(self, op):
- arg0 = self.get_box_replacement(op.getarg(0))
- arg1 = self.get_box_replacement(op.getarg(1))
+ arg0 = get_box_replacement(op.getarg(0))
+ arg1 = get_box_replacement(op.getarg(1))
b0 = self.getintbound(arg0)
b1 = self.getintbound(arg1)
if arg0.same_box(arg1):
@@ -304,8 +306,8 @@
return self.emit(op)
def postprocess_INT_SUB_OVF(self, op):
- arg0 = self.get_box_replacement(op.getarg(0))
- arg1 = self.get_box_replacement(op.getarg(1))
+ arg0 = get_box_replacement(op.getarg(0))
+ arg1 = get_box_replacement(op.getarg(1))
b0 = self.getintbound(arg0)
b1 = self.getintbound(arg1)
resbound = b0.sub_bound(b1)
@@ -329,8 +331,8 @@
r.intersect(resbound)
def optimize_INT_LT(self, op):
- arg1 = self.get_box_replacement(op.getarg(0))
- arg2 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(0))
+ arg2 = get_box_replacement(op.getarg(1))
b1 = self.getintbound(arg1)
b2 = self.getintbound(arg2)
if b1.known_lt(b2):
@@ -341,8 +343,8 @@
return self.emit(op)
def optimize_INT_GT(self, op):
- arg1 = self.get_box_replacement(op.getarg(0))
- arg2 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(0))
+ arg2 = get_box_replacement(op.getarg(1))
b1 = self.getintbound(arg1)
b2 = self.getintbound(arg2)
if b1.known_gt(b2):
@@ -353,8 +355,8 @@
return self.emit(op)
def optimize_INT_LE(self, op):
- arg1 = self.get_box_replacement(op.getarg(0))
- arg2 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(0))
+ arg2 = get_box_replacement(op.getarg(1))
b1 = self.getintbound(arg1)
b2 = self.getintbound(arg2)
if b1.known_le(b2) or arg1 is arg2:
@@ -365,8 +367,8 @@
return self.emit(op)
def optimize_INT_GE(self, op):
- arg1 = self.get_box_replacement(op.getarg(0))
- arg2 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(0))
+ arg2 = get_box_replacement(op.getarg(1))
b1 = self.getintbound(arg1)
b2 = self.getintbound(arg2)
if b1.known_ge(b2) or arg1 is arg2:
@@ -377,9 +379,9 @@
return self.emit(op)
def optimize_INT_EQ(self, op):
- arg0 = self.get_box_replacement(op.getarg(0))
+ arg0 = get_box_replacement(op.getarg(0))
b1 = self.getintbound(arg0)
- arg1 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(1))
b2 = self.getintbound(arg1)
if b1.known_gt(b2):
self.make_constant_int(op, 0)
@@ -391,9 +393,9 @@
return self.emit(op)
def optimize_INT_NE(self, op):
- arg0 = self.get_box_replacement(op.getarg(0))
+ arg0 = get_box_replacement(op.getarg(0))
b1 = self.getintbound(arg0)
- arg1 = self.get_box_replacement(op.getarg(1))
+ arg1 = get_box_replacement(op.getarg(1))
b2 = self.getintbound(arg1)
if b1.known_gt(b2):
self.make_constant_int(op, 1)
@@ -442,7 +444,7 @@
def postprocess_STRLEN(self, op):
self.make_nonnull_str(op.getarg(0), vstring.mode_string)
- array = self.getptrinfo(op.getarg(0))
+ array = getptrinfo(op.getarg(0))
self.optimizer.setintbound(op, array.getlenbound(vstring.mode_string))
def optimize_UNICODELEN(self, op):
@@ -450,7 +452,7 @@
def postprocess_UNICODELEN(self, op):
self.make_nonnull_str(op.getarg(0), vstring.mode_unicode)
- array = self.getptrinfo(op.getarg(0))
+ array = getptrinfo(op.getarg(0))
self.optimizer.setintbound(op, array.getlenbound(vstring.mode_unicode))
def optimize_STRGETITEM(self, op):
@@ -458,7 +460,7 @@
def postprocess_STRGETITEM(self, op):
v1 = self.getintbound(op)
- v2 = self.getptrinfo(op.getarg(0))
+ v2 = getptrinfo(op.getarg(0))
intbound = self.getintbound(op.getarg(1))
if (intbound.has_lower and v2 is not None and
v2.getlenbound(vstring.mode_string) is not None):
@@ -523,7 +525,7 @@
def postprocess_UNICODEGETITEM(self, op):
b1 = self.getintbound(op)
b1.make_ge(IntLowerBound(0))
- v2 = self.getptrinfo(op.getarg(0))
+ v2 = getptrinfo(op.getarg(0))
intbound = self.getintbound(op.getarg(1))
if (intbound.has_lower and v2 is not None and
v2.getlenbound(vstring.mode_unicode) is not None):
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -1,16 +1,19 @@
from rpython.jit.metainterp import jitprof, resume, compile
from rpython.jit.metainterp.executor import execute_nonspec_const
from rpython.jit.metainterp.history import (
- Const, ConstInt, ConstPtr, CONST_NULL, new_ref_dict)
-from rpython.jit.metainterp.optimizeopt.intutils import IntBound,\
- ConstIntBound, MININT, MAXINT, IntUnbounded
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from rpython.jit.metainterp.resoperation import rop, AbstractResOp, GuardResOp,\
- OpHelpers
+ Const, ConstInt, CONST_NULL, new_ref_dict)
+from rpython.jit.metainterp.optimizeopt.intutils import (
+ IntBound, ConstIntBound, MININT, MAXINT, IntUnbounded)
+from rpython.jit.metainterp.optimizeopt.util import (
+ make_dispatcher_method, get_box_replacement)
+from rpython.jit.metainterp.optimizeopt.bridgeopt import (
+ deserialize_optimizer_knowledge)
+from rpython.jit.metainterp.resoperation import (
+ rop, AbstractResOp, GuardResOp, OpHelpers)
+from .info import getrawptrinfo, getptrinfo
from rpython.jit.metainterp.optimizeopt import info
from rpython.jit.metainterp.optimize import InvalidLoop
from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib.debug import debug_print
from rpython.rtyper import rclass
from rpython.rtyper.lltypesystem import llmemory
from rpython.jit.metainterp.optimize import SpeculativeError
@@ -57,9 +60,6 @@
def __init__(self):
pass # make rpython happy
- def send_extra_operation(self, op, opt=None):
- self.optimizer.send_extra_operation(op, opt)
-
More information about the pypy-commit
mailing list