[pypy-commit] pypy fast-newarray: merge default
fijal
noreply at buildbot.pypy.org
Mon Apr 15 17:52:10 CEST 2013
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: fast-newarray
Changeset: r63373:5c9cbab255ac
Date: 2013-04-15 17:51 +0200
http://bitbucket.org/pypy/pypy/changeset/5c9cbab255ac/
Log: merge default
diff too long, truncating to 2000 out of 2634 lines
diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
--- a/lib_pypy/_pypy_interact.py
+++ b/lib_pypy/_pypy_interact.py
@@ -44,7 +44,7 @@
import code
if mainmodule is None:
import __main__ as mainmodule
- console = code.InteractiveConsole(mainmodule.__dict__)
+ console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>')
# some parts of code.py are copied here because it seems to be impossible
# to start an interactive console without printing at least one line
# of banner
diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py
--- a/lib_pypy/pyrepl/python_reader.py
+++ b/lib_pypy/pyrepl/python_reader.py
@@ -171,11 +171,11 @@
def execute(self, text):
try:
- # ooh, look at the hack:
+ # ooh, look at the hack:
code = self.compile("# coding:utf8\n"+text.encode('utf-8'),
- '<input>', 'single')
+ '<stdin>', 'single')
except (OverflowError, SyntaxError, ValueError):
- self.showsyntaxerror("<input>")
+ self.showsyntaxerror('<stdin>')
else:
self.runcode(code)
if sys.stdout and not sys.stdout.closed:
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -37,13 +37,13 @@
import code
if mainmodule is None:
import __main__ as mainmodule
- console = code.InteractiveConsole(mainmodule.__dict__)
+ console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>')
def more_lines(unicodetext):
# ooh, look at the hack:
src = "#coding:utf-8\n"+unicodetext.encode('utf-8')
try:
- code = console.compile(src, '<input>', 'single')
+ code = console.compile(src, '<stdin>', 'single')
except (OverflowError, SyntaxError, ValueError):
return False
else:
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -31,6 +31,7 @@
.. _`Starting with RPython`: getting-started-dev.html
.. _`how to contribute`: how-to-contribute.html
.. _`PyPy website`: http://pypy.org
+.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE
Index of various topics:
========================
@@ -66,11 +67,9 @@
* `Sandboxing Python code`_
* `Garbage collection environment variables`_
-Status_ of the project.
-
.. _`Differences between PyPy and CPython`: cpython_differences.html
.. _`What PyPy can do for your objects`: objspace-proxies.html
-.. _`Continulets and greenlets_`: stackless.html
+.. _`Continulets and greenlets`: stackless.html
.. _`JIT Generation in PyPy`: jit/index.html
.. _`JIT hooks`: jit-hooks.html
.. _`Sandboxing Python code`: sandbox.html
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
@@ -50,6 +50,9 @@
JIT optimizations which makes cffi calls even faster, by removing the need to
allocate a temporary buffer where to store the arguments.
+.. branch: improve-docs-2
+Improve documents and straighten out links
+
.. branches we don't care about
.. branch: autoreds
.. branch: reflex-support
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -255,19 +255,7 @@
"code=%d, name=%s" %
(self.last_instr, opcode,
methodname))
- try:
- res = meth(oparg, next_instr)
- except Exception:
- if 0:
- import dis, sys
- print "*** %s at offset %d (%s)" % (sys.exc_info()[0],
- self.last_instr,
- methodname)
- try:
- dis.dis(co_code)
- except:
- pass
- raise
+ res = meth(oparg, next_instr)
if res is not None:
next_instr = res
diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py
--- a/pypy/module/__pypy__/test/test_signal.py
+++ b/pypy/module/__pypy__/test/test_signal.py
@@ -47,8 +47,9 @@
try:
done = []
interrupted = []
+ print 'starting',i
thread.start_new_thread(subthread, ())
- for i in range(10):
+ for j in range(10):
if len(done): break
print '.'
time.sleep(0.1)
diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py
--- a/pypy/module/_io/interp_bytesio.py
+++ b/pypy/module/_io/interp_bytesio.py
@@ -2,37 +2,26 @@
TypeDef, generic_new_descr, GetSetProperty)
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import OperationError, operationerrfmt
+from rpython.rlib.rStringIO import RStringIO
from rpython.rlib.rarithmetic import r_longlong
from pypy.module._io.interp_bufferedio import W_BufferedIOBase
from pypy.module._io.interp_iobase import convert_size
import sys
-def buffer2string(buffer, start, end):
- from rpython.rlib.rstring import StringBuilder
- builder = StringBuilder(end - start)
- for i in range(start, end):
- builder.append(buffer[i])
- return builder.build()
-class W_BytesIO(W_BufferedIOBase):
+class W_BytesIO(RStringIO, W_BufferedIOBase):
def __init__(self, space):
W_BufferedIOBase.__init__(self, space)
- self.pos = 0
- self.string_size = 0
- self.buf = None
+ self.init()
def descr_init(self, space, w_initial_bytes=None):
- # In case __init__ is called multiple times
- self.buf = []
- self.string_size = 0
- self.pos = 0
-
+ self.init()
if not space.is_none(w_initial_bytes):
self.write_w(space, w_initial_bytes)
- self.pos = 0
+ self.seek(0)
def _check_closed(self, space, message=None):
- if self.buf is None:
+ if self.is_closed():
if message is None:
message = "I/O operation on closed file"
raise OperationError(space.w_ValueError, space.wrap(message))
@@ -40,36 +29,12 @@
def read_w(self, space, w_size=None):
self._check_closed(space)
size = convert_size(space, w_size)
-
- # adjust invalid sizes
- available = self.string_size - self.pos
- if not 0 <= size <= available:
- size = available
- if size < 0:
- size = 0
-
- output = buffer2string(self.buf, self.pos, self.pos + size)
- self.pos += size
- return space.wrap(output)
+ return space.wrap(self.read(size))
def readline_w(self, space, w_limit=None):
self._check_closed(space)
limit = convert_size(space, w_limit)
-
- cur_pos = self.pos
- if limit < 0:
- end_pos = self.string_size
- else:
- end_pos = min(cur_pos + limit, self.string_size)
- while cur_pos != end_pos:
- if self.buf[cur_pos] == '\n':
- cur_pos += 1
- break
- cur_pos += 1
-
- output = buffer2string(self.buf, self.pos, cur_pos)
- self.pos = cur_pos
- return space.wrap(output)
+ return space.wrap(self.readline(limit))
def read1_w(self, space, w_size):
return self.read_w(space, w_size)
@@ -79,56 +44,28 @@
rwbuffer = space.rwbuffer_w(w_buffer)
size = rwbuffer.getlength()
- if self.pos + size > self.string_size:
- size = self.string_size - self.pos
-
- output = buffer2string(self.buf, self.pos, self.pos + size)
- length = len(output)
+ output = self.read(size)
rwbuffer.setslice(0, output)
- self.pos += length
- return space.wrap(length)
+ return space.wrap(len(output))
def write_w(self, space, w_data):
self._check_closed(space)
if space.isinstance_w(w_data, space.w_unicode):
raise OperationError(space.w_TypeError, space.wrap(
"bytes string of buffer expected"))
- buf = space.buffer_w(w_data)
- length = buf.getlength()
+ buf = space.bufferstr_w(w_data)
+ length = len(buf)
if length <= 0:
- return
-
- if self.pos + length > len(self.buf):
- self.buf.extend(['\0'] * (self.pos + length - len(self.buf)))
-
- if self.pos > self.string_size:
- # In case of overseek, pad with null bytes the buffer region
- # between the end of stream and the current position.
- #
- # 0 lo string_size hi
- # | |<---used--->|<----------available----------->|
- # | | <--to pad-->|<---to write---> |
- # 0 buf position
- for i in range(self.string_size, self.pos):
- self.buf[i] = '\0'
-
- # Copy the data to the internal buffer, overwriting some of the
- # existing data if self->pos < self->string_size.
- for i in range(length):
- self.buf[self.pos + i] = buf.getitem(i)
- self.pos += length
-
- # Set the new length of the internal string if it has changed
- if self.string_size < self.pos:
- self.string_size = self.pos
-
+ return space.wrap(0)
+ self.write(buf)
return space.wrap(length)
def truncate_w(self, space, w_size=None):
self._check_closed(space)
+ pos = self.tell()
if space.is_none(w_size):
- size = self.pos
+ size = pos
else:
size = space.r_longlong_w(w_size)
@@ -136,19 +73,20 @@
raise OperationError(space.w_ValueError, space.wrap(
"negative size value"))
- if size < self.string_size:
- self.string_size = size
- del self.buf[size:]
-
+ self.truncate(size)
+ if size == pos:
+ self.seek(0, 2)
+ else:
+ self.seek(pos)
return space.wrap(size)
def getvalue_w(self, space):
self._check_closed(space)
- return space.wrap(buffer2string(self.buf, 0, self.string_size))
+ return space.wrap(self.getvalue())
def tell_w(self, space):
self._check_closed(space)
- return space.wrap(self.pos)
+ return space.wrap(self.tell())
@unwrap_spec(pos=r_longlong, whence=int)
def seek_w(self, space, pos, whence=0):
@@ -159,24 +97,19 @@
raise OperationError(space.w_ValueError, space.wrap(
"negative seek value"))
elif whence == 1:
- if pos > sys.maxint - self.pos:
+ if pos > sys.maxint - self.tell():
raise OperationError(space.w_OverflowError, space.wrap(
"new position too large"))
- pos += self.pos
elif whence == 2:
- if pos > sys.maxint - self.string_size:
+ if pos > sys.maxint - self.getsize():
raise OperationError(space.w_OverflowError, space.wrap(
"new position too large"))
- pos += self.string_size
else:
raise operationerrfmt(space.w_ValueError,
"whence must be between 0 and 2, not %d", whence)
- if pos >= 0:
- self.pos = pos
- else:
- self.pos = 0
- return space.wrap(self.pos)
+ self.seek(pos, whence)
+ return space.wrap(self.tell())
def readable_w(self, space):
return space.w_True
@@ -188,17 +121,16 @@
return space.w_True
def close_w(self, space):
- self.buf = None
+ self.close()
def closed_get_w(self, space):
- return space.wrap(self.buf is None)
+ return space.wrap(self.is_closed())
def getstate_w(self, space):
self._check_closed(space)
- w_content = space.wrap(buffer2string(self.buf, 0, self.string_size))
return space.newtuple([
- w_content,
- space.wrap(self.pos),
+ space.wrap(self.getvalue()),
+ space.wrap(self.tell()),
self.getdict(space)])
def setstate_w(self, space, w_state):
@@ -211,13 +143,13 @@
space.type(w_state).getname(space)
)
w_content, w_pos, w_dict = space.unpackiterable(w_state, 3)
+ self.truncate(0)
+ self.write_w(space, w_content)
pos = space.int_w(w_pos)
- self.buf = []
- self.write_w(space, w_content)
if pos < 0:
raise OperationError(space.w_ValueError, space.wrap(
"position value cannot be negative"))
- self.pos = pos
+ self.seek(pos)
if not space.is_w(w_dict, space.w_None):
space.call_method(self.getdict(space), "update", w_dict)
diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py
--- a/pypy/module/_io/interp_stringio.py
+++ b/pypy/module/_io/interp_stringio.py
@@ -169,9 +169,9 @@
self.pos = end
return space.wrap(u''.join(self.buf[start:end]))
- @unwrap_spec(limit=int)
- def readline_w(self, space, limit=-1):
+ def readline_w(self, space, w_limit=None):
self._check_closed(space)
+ limit = convert_size(space, w_limit)
if self.pos >= len(self.buf):
return space.wrap(u"")
diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py
--- a/pypy/module/_io/test/test_bytesio.py
+++ b/pypy/module/_io/test/test_bytesio.py
@@ -4,6 +4,15 @@
def test_init(self):
import _io
raises(TypeError, _io.BytesIO, u"12345")
+ buf = "1234567890"
+ b = _io.BytesIO(buf)
+ assert b.getvalue() == buf
+ b = _io.BytesIO(None)
+ assert b.getvalue() == ""
+ b.__init__(buf * 2)
+ assert b.getvalue() == buf * 2
+ b.__init__(buf)
+ assert b.getvalue() == buf
def test_init_kwargs(self):
import _io
@@ -24,6 +33,7 @@
def test_write(self):
import _io
f = _io.BytesIO()
+ assert f.write("") == 0
assert f.write("hello") == 5
import gc; gc.collect()
assert f.getvalue() == "hello"
@@ -47,10 +57,17 @@
def test_truncate(self):
import _io
- f = _io.BytesIO("hello")
+ f = _io.BytesIO()
+ f.write("hello")
+ assert f.truncate(0) == 0
+ assert f.tell() == 5
+ f.seek(0)
+ f.write("hello")
f.seek(3)
assert f.truncate() == 3
assert f.getvalue() == "hel"
+ assert f.truncate(2) == 2
+ assert f.tell() == 3
def test_setstate(self):
# state is (content, position, __dict__)
@@ -73,7 +90,13 @@
import _io
b = _io.BytesIO("hello")
+ a1 = bytearray('t')
+ a2 = bytearray('testing')
+ assert b.readinto(a1) == 1
+ assert b.readinto(a2) == 4
b.close()
+ assert a1 == "h"
+ assert a2 == "elloing"
raises(ValueError, b.readinto, bytearray("hello"))
def test_readline(self):
diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py
--- a/pypy/module/_io/test/test_stringio.py
+++ b/pypy/module/_io/test/test_stringio.py
@@ -32,7 +32,7 @@
raises(ValueError, sio.read, 1)
raises(ValueError, sio.write, u"text")
- def testRead(self):
+ def test_read(self):
import io
buf = u"1234567890"
sio = io.StringIO(buf)
@@ -42,6 +42,13 @@
assert buf[5:] == sio.read(900)
assert u"" == sio.read()
+ def test_readline(self):
+ import io
+ sio = io.StringIO(u'123\n456')
+ assert sio.readline(2) == '12'
+ assert sio.readline(None) == '3\n'
+ assert sio.readline() == '456'
+
def test_seek(self):
import io
diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_io/test/test_ztranslation.py
@@ -0,0 +1,4 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_checkmodule():
+ checkmodule('_io')
diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py
--- a/pypy/module/_minimal_curses/__init__.py
+++ b/pypy/module/_minimal_curses/__init__.py
@@ -2,10 +2,12 @@
import _curses
except ImportError:
try:
- import _minimal_curses as _curses # when running on top of pypy-c
+ # when running on top of pypy before it had _curses, settle for minimal
+ # we prefer _curses so any constants added make it into _minimal_curses
+ import _minimal_curses as _curses
except ImportError:
import py
- py.test.skip("no _curses or _minimal_curses module") #no _curses at all
+ py.test.skip("no _curses or _minimal_curses module") # no _curses at all
from pypy.interpreter.mixedmodule import MixedModule
from pypy.module._minimal_curses import fficurses # for side effects
diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py
--- a/pypy/module/cStringIO/interp_stringio.py
+++ b/pypy/module/cStringIO/interp_stringio.py
@@ -146,7 +146,7 @@
class W_OutputType(RStringIO, W_InputOutputType):
def __init__(self, space):
- RStringIO.__init__(self)
+ self.init()
self.space = space
def descr_truncate(self, w_size=None):
@@ -159,6 +159,7 @@
if size < 0:
raise OperationError(space.w_IOError, space.wrap("negative size"))
self.truncate(size)
+ self.seek(0, 2)
@unwrap_spec(buffer='bufferstr')
def descr_write(self, buffer):
diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py
--- a/pypy/module/cStringIO/test/test_interp_stringio.py
+++ b/pypy/module/cStringIO/test/test_interp_stringio.py
@@ -142,8 +142,11 @@
f.write(' world')
f.truncate(30)
assert f.getvalue() == '\x00' * 20 + 'hello worl'
+ assert f.tell() == 30
+ f.seek(0)
f.truncate(25)
assert f.getvalue() == '\x00' * 20 + 'hello'
+ assert f.tell() == 25
f.write('baz')
f.write('egg')
f.truncate(3)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -1,6 +1,6 @@
import sys
import weakref
-import os.path
+import os
import py
@@ -19,6 +19,21 @@
from rpython.tool.identity_dict import identity_dict
from rpython.tool import leakfinder
+def setup_module(module):
+ if os.name == 'nt':
+ # Do not open dreaded dialog box on segfault
+ import ctypes
+ SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN
+ old_err_mode = ctypes.windll.kernel32.GetErrorMode()
+ new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX
+ ctypes.windll.kernel32.SetErrorMode(new_err_mode)
+ module.old_err_mode = old_err_mode
+
+def teardown_module(module):
+ if os.name == 'nt':
+ import ctypes
+ ctypes.windll.kernel32.SetErrorMode(module.old_err_mode)
+
@api.cpython_api([], api.PyObject)
def PyPy_Crash1(space):
1/0
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -282,7 +282,10 @@
return dtype
if w_dtype is dtype.w_box_type:
return dtype
- raise OperationError(space.w_TypeError, space.wrap("data type %r not understood" % w_dtype))
+ typename = space.type(w_dtype).getname(space)
+ raise OperationError(space.w_TypeError, space.wrap(
+ "data type not understood (value of type " +
+ "%s not expected here)" % typename))
W_Dtype.typedef = TypeDef("dtype",
__module__ = "numpypy",
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -32,7 +32,8 @@
assert dtype(None) is dtype(float)
- raises(TypeError, dtype, 1042)
+ exc = raises(TypeError, dtype, (1, 2))
+ assert 'data type not understood' in str(exc.value)
raises(KeyError, 'dtype(int)["asdasd"]')
def test_dtype_eq(self):
diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -132,7 +132,7 @@
if not e.match(space, space.w_SystemExit):
ident = rthread.get_ident()
where = 'thread %d started by ' % ident
- e.write_unraisable(space, where, w_callable)
+ e.write_unraisable(space, where, w_callable, with_traceback=True)
e.clear(space)
# clean up space.threadlocals to remove the ExecutionContext
# entry corresponding to the current thread
diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py
--- a/pypy/module/thread/test/test_thread.py
+++ b/pypy/module/thread/test/test_thread.py
@@ -129,10 +129,10 @@
sys.stderr = StringIO.StringIO()
thread.start_new_thread(fn3, ())
self.waitfor(lambda: "ValueError" in sys.stderr.getvalue())
- result = sys.stderr.getvalue()
- assert "ValueError" in result
- assert "hello world" in result
- assert len(result.splitlines()) == 1
+ result = sys.stderr.getvalue().splitlines()
+ #assert result[0].startswith("Unhandled exception in thread ")
+ assert result[1].startswith("Traceback ")
+ assert result[-1] == "ValueError: hello world"
finally:
sys.stderr = prev
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -58,6 +58,10 @@
class W_MyType(W_MyObject):
def __init__(self):
self.mro_w = [w_some_obj(), w_some_obj()]
+ self.dict_w = {'__str__': w_some_obj()}
+
+ def get_module(self):
+ return w_some_obj()
def w_some_obj():
if NonConstant(False):
@@ -318,7 +322,7 @@
ObjSpace.ExceptionTable +
['int', 'str', 'float', 'long', 'tuple', 'list',
'dict', 'unicode', 'complex', 'slice', 'bool',
- 'basestring', 'object']):
+ 'basestring', 'object', 'bytearray']):
setattr(FakeObjSpace, 'w_' + name, w_some_obj())
FakeObjSpace.w_type = w_some_type()
#
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -1109,7 +1109,7 @@
self.i = i
def __eq__(self, other):
if self.i == 9:
- del l[i - 1]
+ del l[self.i - 1]
return True
else:
return False
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -74,29 +74,6 @@
def setup_failure_recovery(self):
self.failure_recovery_code = [0, 0, 0, 0]
- @staticmethod
- def _release_gil_shadowstack():
- before = rffi.aroundstate.before
- if before:
- before()
-
- @staticmethod
- def _reacquire_gil_shadowstack():
- after = rffi.aroundstate.after
- if after:
- after()
-
- _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
-
- def _build_release_gil(self, gcrootmap):
- assert gcrootmap.is_shadow_stack
- releasegil_func = llhelper(self._NOARG_FUNC,
- self._release_gil_shadowstack)
- reacqgil_func = llhelper(self._NOARG_FUNC,
- self._reacquire_gil_shadowstack)
- self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func)
- self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func)
-
def _build_propagate_exception_path(self):
if not self.cpu.propagate_exception_descr:
return # not supported (for tests, or non-translated)
@@ -537,7 +514,7 @@
clt.allgcrefs = []
clt.frame_info.clear() # for now
- if False and log:
+ if log:
operations = self._inject_debugging_code(looptoken, operations,
'e', looptoken.number)
@@ -787,13 +764,13 @@
# restore registers
self._pop_all_regs_from_jitframe(mc, [], self.cpu.supports_floats)
- mc.POP([r.ip.value, r.pc.value]) # return
+ mc.POP([r.ip.value, r.pc.value]) # return
self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, [])
def _load_shadowstack_top(self, mc, reg, gcrootmap):
rst = gcrootmap.get_root_stack_top_addr()
mc.gen_load_int(reg.value, rst)
- mc.gen_load_int(reg.value, reg.value)
+ self.load_reg(mc, reg, reg)
return rst
def fixup_target_tokens(self, rawstart):
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -352,7 +352,8 @@
def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None,
result_info=(-1, -1),
- can_collect=1):
+ can_collect=1,
+ reload_frame=False):
if self.cpu.hf_abi:
stack_args, adr = self._setup_call_hf(adr, arglocs, fcond,
resloc, result_info)
@@ -365,7 +366,6 @@
gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs)
self.push_gcmap(self.mc, gcmap, store=True)
#the actual call
- #self.mc.BKPT()
if adr.is_imm():
self.mc.BL(adr.value)
elif adr.is_stack():
@@ -388,6 +388,8 @@
if can_collect:
self._reload_frame_if_necessary(self.mc, can_collect=can_collect)
self.pop_gcmap(self.mc)
+ elif reload_frame:
+ self._reload_frame_if_necessary(self.mc)
return fcond
def _restore_sp(self, stack_args, fcond):
@@ -630,7 +632,9 @@
# argument the address of the structure we are writing into
# (the first argument to COND_CALL_GC_WB).
helper_num = card_marking
- if self._regalloc is not None and self._regalloc.vfprm.reg_bindings:
+ if is_frame:
+ helper_num = 4
+ elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings:
helper_num += 2
if self.wb_slowpath[helper_num] == 0: # tests only
assert not we_are_translated()
@@ -1264,7 +1268,11 @@
resloc = arglocs[0]
if gcrootmap:
- self.call_release_gil(gcrootmap, arglocs, fcond)
+ noregs = self.cpu.gc_ll_descr.is_shadow_stack()
+ assert noregs
+ gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs)
+ self.push_gcmap(self.mc, gcmap, store=True)
+ self.call_release_gil(gcrootmap, arglocs, regalloc, fcond)
# do the call
self._store_force_index(guard_op)
#
@@ -1273,42 +1281,40 @@
signed = descr.is_result_signed()
#
self._emit_call(adr, callargs, fcond,
- resloc, (size, signed))
+ resloc, (size, signed),
+ can_collect=0)
# then reopen the stack
if gcrootmap:
- self.call_reacquire_gil(gcrootmap, resloc, fcond)
+ self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond)
self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs)
return fcond
- def call_release_gil(self, gcrootmap, save_registers, fcond):
- # First, we need to save away the registers listed in
- # 'save_registers' that are not callee-save.
+ def call_release_gil(self, gcrootmap, save_registers, regalloc, fcond):
+ # Save caller saved registers and do the call
# NOTE: We assume that the floating point registers won't be modified.
- regs_to_save = []
- for reg in self._regalloc.rm.save_around_call_regs:
- if reg in save_registers:
- regs_to_save.append(reg)
assert gcrootmap.is_shadow_stack
- with saved_registers(self.mc, regs_to_save):
- self._emit_call(imm(self.releasegil_addr), [], fcond)
+ with saved_registers(self.mc, regalloc.rm.save_around_call_regs):
+ self._emit_call(imm(self.releasegil_addr), [],
+ fcond, can_collect=False)
- def call_reacquire_gil(self, gcrootmap, save_loc, fcond):
- # save the previous result into the stack temporarily.
+ def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond):
+ # save the previous result into the stack temporarily, in case it is in
+ # a caller saved register.
# NOTE: like with call_release_gil(), we assume that we don't need to
# save vfp regs in this case. Besides the result location
regs_to_save = []
vfp_regs_to_save = []
- if save_loc.is_reg():
+ if save_loc and save_loc in regalloc.rm.save_around_call_regs:
regs_to_save.append(save_loc)
- if save_loc.is_vfp_reg():
+ regs_to_save.append(r.ip) # for alingment
+ elif save_loc and save_loc in regalloc.vfprm.save_around_call_regs:
vfp_regs_to_save.append(save_loc)
+ assert gcrootmap.is_shadow_stack
# call the reopenstack() function (also reacquiring the GIL)
- if len(regs_to_save) % 2 != 1:
- regs_to_save.append(r.ip) # for alingment
- assert gcrootmap.is_shadow_stack
with saved_registers(self.mc, regs_to_save, vfp_regs_to_save):
- self._emit_call(imm(self.reacqgil_addr), [], fcond)
+ self._emit_call(imm(self.reacqgil_addr), [], fcond,
+ can_collect=False, reload_frame=True)
def _store_force_index(self, guard_op):
faildescr = guard_op.getdescr()
diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -554,10 +554,9 @@
return self._prepare_call(op)
def _prepare_call(self, op, force_store=[], save_all_regs=False):
- args = []
- args.append(None)
+ args = [None] * (op.numargs() + 1)
for i in range(op.numargs()):
- args.append(self.loc(op.getarg(i)))
+ args[i + 1] = self.loc(op.getarg(i))
# spill variables that need to be saved around calls
self.vfprm.before_call(save_all_regs=save_all_regs)
if not save_all_regs:
diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc.py b/rpython/jit/backend/arm/test/test_zrpy_gc.py
--- a/rpython/jit/backend/arm/test/test_zrpy_gc.py
+++ b/rpython/jit/backend/arm/test/test_zrpy_gc.py
@@ -1,4 +1,8 @@
from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests
skip_unless_run_slow_tests()
-from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack
+from rpython.jit.backend.llsupport.test.zrpy_gc_test import CompileFrameworkTests
+
+
+class TestShadowStack(CompileFrameworkTests):
+ gcrootfinder = "shadowstack"
diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py
--- a/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py
+++ b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py
@@ -1,3 +1,3 @@
from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests
skip_unless_run_slow_tests()
-from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm
+from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import compile_boehm_test as test_compile_boehm
diff --git a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py
--- a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py
+++ b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py
@@ -1,4 +1,10 @@
from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests
skip_unless_run_slow_tests()
-from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack
+from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import ReleaseGILTests
+
+
+class TestShadowStack(ReleaseGILTests):
+ gcrootfinder = "shadowstack"
+
+
diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -9,7 +9,7 @@
debug_print)
from rpython.rlib.rarithmetic import r_uint
from rpython.rlib.objectmodel import specialize, compute_unique_id
-from rpython.rtyper.annlowlevel import cast_instance_to_gcref
+from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper
from rpython.rtyper.lltypesystem import rffi, lltype
@@ -283,6 +283,69 @@
debug_print(prefix + ':' + str(struct.i))
debug_stop('jit-backend-counts')
+ @staticmethod
+ @rgc.no_collect
+ def _release_gil_asmgcc(css):
+ # similar to trackgcroot.py:pypy_asm_stackwalk, first part
+ from rpython.memory.gctransform import asmgcroot
+ new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
+ next = asmgcroot.gcrootanchor.next
+ new.next = next
+ new.prev = asmgcroot.gcrootanchor
+ asmgcroot.gcrootanchor.next = new
+ next.prev = new
+ # and now release the GIL
+ before = rffi.aroundstate.before
+ if before:
+ before()
+
+ @staticmethod
+ @rgc.no_collect
+ def _reacquire_gil_asmgcc(css):
+ # first reacquire the GIL
+ after = rffi.aroundstate.after
+ if after:
+ after()
+ # similar to trackgcroot.py:pypy_asm_stackwalk, second part
+ from rpython.memory.gctransform import asmgcroot
+ old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
+ prev = old.prev
+ next = old.next
+ prev.next = next
+ next.prev = prev
+
+ @staticmethod
+ @rgc.no_collect
+ def _release_gil_shadowstack():
+ before = rffi.aroundstate.before
+ if before:
+ before()
+
+ @staticmethod
+ @rgc.no_collect
+ def _reacquire_gil_shadowstack():
+ after = rffi.aroundstate.after
+ if after:
+ after()
+
+ _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
+ _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP],
+ lltype.Void))
+
+ def _build_release_gil(self, gcrootmap):
+ if gcrootmap.is_shadow_stack:
+ releasegil_func = llhelper(self._NOARG_FUNC,
+ self._release_gil_shadowstack)
+ reacqgil_func = llhelper(self._NOARG_FUNC,
+ self._reacquire_gil_shadowstack)
+ else:
+ releasegil_func = llhelper(self._CLOSESTACK_FUNC,
+ self._release_gil_asmgcc)
+ reacqgil_func = llhelper(self._CLOSESTACK_FUNC,
+ self._reacquire_gil_asmgcc)
+ self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func)
+ self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func)
+
def debug_bridge(descr_number, rawstart, codeendpos):
diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
@@ -719,18 +719,24 @@
# people actually wreck xmm registers
cpu = self.cpu
l = []
+ copied_stack = [None]
def before():
+ # put nonsense on the top of shadowstack
+ frame = rffi.cast(JITFRAMEPTR, cpu.gc_ll_descr.gcrootmap.stack[0])
+ assert getmap(frame).count('1') == 7 #
+ copied_stack[0] = cpu.gc_ll_descr.gcrootmap.stack[0]
+ cpu.gc_ll_descr.gcrootmap.stack[0] = 0
l.append("before")
def after():
+ cpu.gc_ll_descr.gcrootmap.stack[0] = copied_stack[0]
l.append("after")
invoke_around_extcall(before, after)
def f(frame, x):
# all the gc pointers are alive p1 -> p7 (but not p0)
- assert getmap(frame).count('1') == 7 #
assert x == 1
return 2
diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py
--- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py
+++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py
@@ -32,7 +32,7 @@
g._dont_inline_ = True
return g
-def test_compile_boehm(monkeypatch):
+def compile_boehm_test(monkeypatch):
fix_annotator_for_vrawbuffer(monkeypatch)
myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
@dont_look_inside
diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py
--- a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py
+++ b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py
@@ -770,6 +770,3 @@
def test_compile_framework_call_assembler(self):
self.run('compile_framework_call_assembler')
-
-class TestShadowStack(CompileFrameworkTests):
- gcrootfinder = "shadowstack"
diff --git a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py
--- a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py
+++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py
@@ -95,10 +95,3 @@
def test_close_stack(self):
self.run('close_stack')
assert 'call_release_gil' in udir.join('TestCompileFramework.log').read()
-
-
-class TestShadowStack(ReleaseGILTests):
- gcrootfinder = "shadowstack"
-
-class TestAsmGcc(ReleaseGILTests):
- gcrootfinder = "asmgcc"
diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -348,7 +348,7 @@
i0 = BoxInt()
class UntouchableFailDescr(AbstractFailDescr):
final_descr = True
-
+
def __setattr__(self, name, value):
if (name == 'index' or name == '_carry_around_for_tests'
or name == '_TYPE' or name == '_cpu'):
@@ -2455,12 +2455,12 @@
lltype.free(raw, flavor='raw')
def test_call_to_winapi_function(self):
- from rpython.rlib.clibffi import _WIN32, FUNCFLAG_STDCALL
+ from rpython.rlib.clibffi import _WIN32
if not _WIN32:
py.test.skip("Windows test only")
- from rpython.rlib.libffi import CDLL, types, ArgChain
+ from rpython.rlib.libffi import WinDLL, types, ArgChain
from rpython.rlib.rwin32 import DWORD
- libc = CDLL('KERNEL32')
+ libc = WinDLL('KERNEL32')
c_GetCurrentDir = libc.getpointer('GetCurrentDirectoryA',
[types.ulong, types.pointer],
types.ulong)
@@ -2831,6 +2831,56 @@
assert self.cpu.get_int_value(deadframe, 0) == 97
assert not called
+ def test_assembler_call_propagate_exc(self):
+ from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
+
+ if not isinstance(self.cpu, AbstractLLCPU):
+ py.test.skip("llgraph can't fake exceptions well enough, give up")
+
+ excdescr = BasicFailDescr(666)
+ self.cpu.propagate_exception_descr = excdescr
+ self.cpu.setup_once() # xxx redo it, because we added
+ # propagate_exception
+
+ def assembler_helper(deadframe, virtualizable):
+ assert self.cpu.get_latest_descr(deadframe) is excdescr
+ # let's assume we handled that
+ return 3
+
+ FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF,
+ llmemory.GCREF],
+ lltype.Signed))
+ class FakeJitDriverSD:
+ index_of_virtualizable = -1
+ _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
+ assembler_helper_adr = llmemory.cast_ptr_to_adr(
+ _assembler_helper_ptr)
+
+ ops = '''
+ [i0]
+ p0 = newunicode(i0)
+ finish(p0)'''
+ loop = parse(ops)
+ looptoken = JitCellToken()
+ looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
+ self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+ ARGS = [lltype.Signed] * 10
+ RES = lltype.Signed
+ FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
+ lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
+ EffectInfo.MOST_GENERAL)
+ ops = '''
+ [i0]
+ i11 = call_assembler(i0, descr=looptoken)
+ guard_not_forced()[]
+ finish(i11)
+ '''
+ loop = parse(ops, namespace=locals())
+ othertoken = JitCellToken()
+ self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
+ deadframe = self.cpu.execute_token(othertoken, sys.maxint - 1)
+ assert self.cpu.get_int_value(deadframe, 0) == 3
+
def test_assembler_call_float(self):
if not self.cpu.supports_floats:
py.test.skip("requires floats")
@@ -3341,7 +3391,7 @@
excdescr = BasicFailDescr(666)
self.cpu.propagate_exception_descr = excdescr
self.cpu.setup_once() # xxx redo it, because we added
- # propagate_exception_v
+ # propagate_exception
i0 = BoxInt()
p0 = BoxPtr()
operations = [
@@ -3375,7 +3425,7 @@
calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, effectinfo)
testcases = [(4.0, 2.0), (6.25, 2.5)]
for arg, expected in testcases:
- res = self.execute_operation(rop.CALL,
+ res = self.execute_operation(rop.CALL,
[funcbox, boxfloat(arg)],
'float', descr=calldescr)
assert res.getfloat() == expected
@@ -3731,7 +3781,7 @@
# memory
assert values[0] == 0
- def test_compile_bridge_while_running(self):
+ def test_compile_bridge_while_running(self):
def func():
bridge = parse("""
[i1, i2, px]
@@ -3778,9 +3828,9 @@
func2_ptr = llhelper(FPTR2, func2)
calldescr2 = cpu.calldescrof(FUNC2, FUNC2.ARGS, FUNC2.RESULT,
EffectInfo.MOST_GENERAL)
-
+
faildescr = BasicFailDescr(0)
-
+
looptoken = JitCellToken()
loop = parse("""
[i0, i1, i2]
@@ -3796,7 +3846,7 @@
if not isinstance(self.cpu, AbstractLLCPU):
py.test.skip("pointless test on non-asm")
-
+
frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, frame)
assert len(frame.jf_frame) == frame.jf_frame_info.jfi_frame_depth
ref = self.cpu.get_ref_value(frame, 9)
@@ -3858,7 +3908,7 @@
'calldescr': calldescr,
'faildescr': faildescr,
'finaldescr2': BasicFinalDescr(1)})
-
+
self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
frame = self.cpu.execute_token(looptoken, 1, 2, 3)
descr = self.cpu.get_latest_descr(frame)
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -371,69 +371,6 @@
else:
self.wb_slowpath[withcards + 2 * withfloats] = rawstart
- @staticmethod
- @rgc.no_collect
- def _release_gil_asmgcc(css):
- # similar to trackgcroot.py:pypy_asm_stackwalk, first part
- from rpython.memory.gctransform import asmgcroot
- new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
- next = asmgcroot.gcrootanchor.next
- new.next = next
- new.prev = asmgcroot.gcrootanchor
- asmgcroot.gcrootanchor.next = new
- next.prev = new
- # and now release the GIL
- before = rffi.aroundstate.before
- if before:
- before()
-
- @staticmethod
- @rgc.no_collect
- def _reacquire_gil_asmgcc(css):
- # first reacquire the GIL
- after = rffi.aroundstate.after
- if after:
- after()
- # similar to trackgcroot.py:pypy_asm_stackwalk, second part
- from rpython.memory.gctransform import asmgcroot
- old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
- prev = old.prev
- next = old.next
- prev.next = next
- next.prev = prev
-
- @staticmethod
- @rgc.no_collect
- def _release_gil_shadowstack():
- before = rffi.aroundstate.before
- if before:
- before()
-
- @staticmethod
- @rgc.no_collect
- def _reacquire_gil_shadowstack():
- after = rffi.aroundstate.after
- if after:
- after()
-
- _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
- _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP],
- lltype.Void))
-
- def _build_release_gil(self, gcrootmap):
- if gcrootmap.is_shadow_stack:
- releasegil_func = llhelper(self._NOARG_FUNC,
- self._release_gil_shadowstack)
- reacqgil_func = llhelper(self._NOARG_FUNC,
- self._reacquire_gil_shadowstack)
- else:
- releasegil_func = llhelper(self._CLOSESTACK_FUNC,
- self._release_gil_asmgcc)
- reacqgil_func = llhelper(self._CLOSESTACK_FUNC,
- self._reacquire_gil_asmgcc)
- self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func)
- self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func)
-
def assemble_loop(self, loopname, inputargs, operations, looptoken, log):
'''adds the following attributes to looptoken:
_ll_function_addr (address of the generated func, as an int)
@@ -1041,12 +978,13 @@
def _emit_call(self, x, arglocs, start=0, tmp=eax,
argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1,
- stack_max=PASS_ON_MY_FRAME):
+ stack_max=PASS_ON_MY_FRAME, reload_frame=False):
if can_collect == 1 and not self._is_asmgcc():
can_collect = 2 # don't bother with jf_extra_stack_depth
if IS_X86_64:
return self._emit_call_64(x, arglocs, start, argtypes,
- can_collect, stack_max)
+ can_collect, stack_max,
+ reload_frame=reload_frame)
stack_depth = 0
n = len(arglocs)
for i in range(start, n):
@@ -1096,6 +1034,8 @@
ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
self.mc.MOV_bi(ofs, 0)
self.pop_gcmap(self.mc)
+ elif reload_frame:
+ self._reload_frame_if_necessary(self.mc)
#
def _fix_stdcall(self, callconv, p):
@@ -1106,7 +1046,7 @@
self.mc.SUB_ri(esp.value, p)
def _emit_call_64(self, x, arglocs, start, argtypes,
- can_collect, stack_max):
+ can_collect, stack_max, reload_frame=False):
src_locs = []
dst_locs = []
xmm_src_locs = []
@@ -1196,6 +1136,8 @@
if align and can_collect == 1:
ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
self.mc.MOV_bi(ofs, 0)
+ elif reload_frame:
+ self._reload_frame_if_necessary(self.mc)
if align:
self.mc.ADD_ri(esp.value, align * WORD)
if can_collect:
@@ -1988,6 +1930,9 @@
self.pending_guard_tokens.append(guard_token)
def genop_call(self, op, arglocs, resloc):
+ return self._genop_call(op, arglocs, resloc)
+
+ def _genop_call(self, op, arglocs, resloc, is_call_release_gil=False):
from rpython.jit.backend.llsupport.descr import CallDescr
sizeloc = arglocs[0]
@@ -2005,11 +1950,14 @@
assert isinstance(descr, CallDescr)
stack_max = PASS_ON_MY_FRAME
- if self._is_asmgcc() and op.getopnum() == rop.CALL_RELEASE_GIL:
- from rpython.memory.gctransform import asmgcroot
- stack_max -= asmgcroot.JIT_USE_WORDS
- can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth,
- # and reload ebp from the css
+ if is_call_release_gil:
+ if self._is_asmgcc():
+ from rpython.memory.gctransform import asmgcroot
+ stack_max -= asmgcroot.JIT_USE_WORDS
+ can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth,
+ # and reload ebp from the css
+ else:
+ can_collect = 0
else:
can_collect = 1
@@ -2074,13 +2022,16 @@
def genop_guard_call_release_gil(self, op, guard_op, guard_token,
arglocs, result_loc):
+ self._store_force_index(guard_op)
# first, close the stack in the sense of the asmgcc GC root tracker
gcrootmap = self.cpu.gc_ll_descr.gcrootmap
if gcrootmap:
+ noregs = self.cpu.gc_ll_descr.is_shadow_stack()
+ gcmap = self._regalloc.get_gcmap([eax], noregs=noregs)
+ self.push_gcmap(self.mc, gcmap, store=True)
self.call_release_gil(gcrootmap, arglocs)
# do the call
- self._store_force_index(guard_op)
- self.genop_call(op, arglocs, result_loc)
+ self._genop_call(op, arglocs, result_loc, is_call_release_gil=True)
# then reopen the stack
if gcrootmap:
self.call_reacquire_gil(gcrootmap, result_loc)
@@ -2139,7 +2090,8 @@
reg = edi
self.mc.LEA_rs(reg.value, css)
args = [reg]
- self._emit_call(imm(self.reacqgil_addr), args, can_collect=False)
+ self._emit_call(imm(self.reacqgil_addr), args, can_collect=False,
+ reload_frame=True)
# restore the result from the stack
if isinstance(save_loc, RegLoc) and not save_loc.is_xmm:
self.mc.MOV_rs(save_loc.value, WORD)
diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/x86/test/test_zrpy_gc.py
--- a/rpython/jit/backend/x86/test/test_zrpy_gc.py
+++ b/rpython/jit/backend/x86/test/test_zrpy_gc.py
@@ -1,1 +1,5 @@
-from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack
+from rpython.jit.backend.llsupport.test.zrpy_gc_test import CompileFrameworkTests
+
+
+class TestShadowStack(CompileFrameworkTests):
+ gcrootfinder = "shadowstack"
diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py
--- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py
+++ b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py
@@ -1,1 +1,1 @@
-from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm
+from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import compile_boehm_test as test_compile_boehm
diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py
--- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py
+++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py
@@ -1,1 +1,9 @@
-from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack, TestAsmGcc
+from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import ReleaseGILTests
+
+
+class TestShadowStack(ReleaseGILTests):
+ gcrootfinder = "shadowstack"
+
+
+class TestAsmGcc(ReleaseGILTests):
+ gcrootfinder = "asmgcc"
diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1755,11 +1755,15 @@
return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None)
def rewrite_op_jit_force_virtual(self, op):
- return self._do_builtin_call(op)
+ op0 = SpaceOperation('-live-', [], None)
+ op1 = self._do_builtin_call(op)
+ if isinstance(op1, list):
+ return [op0] + op1
+ else:
+ return [op0, op1]
def rewrite_op_jit_is_virtual(self, op):
- raise Exception, (
- "'vref.virtual' should not be used from jit-visible code")
+ raise Exception("'vref.virtual' should not be used from jit-visible code")
def rewrite_op_jit_force_virtualizable(self, op):
# this one is for virtualizables
diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -689,6 +689,7 @@
self.encoding_test(f, [], """
new_with_vtable <Descr> -> %r0
virtual_ref %r0 -> %r1
+ -live-
residual_call_r_r $<* fn jit_force_virtual>, R[%r1], <Descr> -> %r2
ref_return %r2
""", transform=True, cc=FakeCallControlWithVRefInfo())
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -1747,9 +1747,9 @@
ops = """
[i1]
i2 = call('malloc', 10, descr=raw_malloc_descr)
- setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
- setarrayitem_raw(i2, 2, 456, descr=rawarraydescr)
- setarrayitem_raw(i2, 1, 123, descr=rawarraydescr)
+ setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char)
+ setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char)
+ setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char)
label('foo') # we expect the buffer to be forced *after* the label
escape(i2)
call('free', i2, descr=raw_free_descr)
@@ -1759,11 +1759,11 @@
[i1]
label('foo')
i2 = call('malloc', 10, descr=raw_malloc_descr)
- setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
- i3 = int_add(i2, 8)
- setarrayitem_raw(i3, 0, 123, descr=rawarraydescr)
- i4 = int_add(i2, 16)
- setarrayitem_raw(i4, 0, 456, descr=rawarraydescr)
+ setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char)
+ i3 = int_add(i2, 1)
+ setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char)
+ i4 = int_add(i2, 2)
+ setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char)
escape(i2)
call('free', i2, descr=raw_free_descr)
jump(i1)
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1,25 +1,27 @@
-import py, sys
+import sys
+
+import py
+
+from rpython.jit.codewriter import heaptracker
+from rpython.jit.codewriter.effectinfo import EffectInfo
+from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr
+from rpython.jit.metainterp import history, compile, resume, executor
+from rpython.jit.metainterp.heapcache import HeapCache
+from rpython.jit.metainterp.history import (Const, ConstInt, ConstPtr,
+ ConstFloat, Box, TargetToken)
+from rpython.jit.metainterp.jitexc import JitException, get_llexception
+from rpython.jit.metainterp.jitprof import EmptyProfiler
+from rpython.jit.metainterp.logger import Logger
+from rpython.jit.metainterp.optimizeopt.util import args_dict_box
+from rpython.jit.metainterp.resoperation import rop
+from rpython.rlib import nonconst, rstack
+from rpython.rlib.debug import debug_start, debug_stop, debug_print, make_sure_not_resized
+from rpython.rlib.jit import Counters
+from rpython.rlib.objectmodel import we_are_translated, specialize
+from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper.lltypesystem import lltype, rclass
-from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.debug import debug_start, debug_stop, debug_print
-from rpython.rlib.debug import make_sure_not_resized
-from rpython.rlib import nonconst, rstack
-from rpython.jit.metainterp import history, compile, resume
-from rpython.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
-from rpython.jit.metainterp.history import Box, TargetToken
-from rpython.jit.metainterp.resoperation import rop
-from rpython.jit.metainterp import executor
-from rpython.jit.metainterp.logger import Logger
-from rpython.jit.metainterp.jitprof import EmptyProfiler
-from rpython.rlib.jit import Counters
-from rpython.jit.metainterp.jitexc import JitException, get_llexception
-from rpython.jit.metainterp.heapcache import HeapCache
-from rpython.rlib.objectmodel import specialize
-from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr
-from rpython.jit.codewriter import heaptracker
-from rpython.jit.metainterp.optimizeopt.util import args_dict_box
+
# ____________________________________________________________
@@ -831,15 +833,17 @@
opimpl_inline_call_irf_f = _opimpl_inline_call3
opimpl_inline_call_irf_v = _opimpl_inline_call3
- @arguments("box", "boxes", "descr")
- def _opimpl_residual_call1(self, funcbox, argboxes, calldescr):
- return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
- @arguments("box", "boxes2", "descr")
- def _opimpl_residual_call2(self, funcbox, argboxes, calldescr):
- return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
- @arguments("box", "boxes3", "descr")
- def _opimpl_residual_call3(self, funcbox, argboxes, calldescr):
- return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
+ @arguments("box", "boxes", "descr", "orgpc")
+ def _opimpl_residual_call1(self, funcbox, argboxes, calldescr, pc):
+ return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc)
+
+ @arguments("box", "boxes2", "descr", "orgpc")
+ def _opimpl_residual_call2(self, funcbox, argboxes, calldescr, pc):
+ return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc)
+
+ @arguments("box", "boxes3", "descr", "orgpc")
+ def _opimpl_residual_call3(self, funcbox, argboxes, calldescr, pc):
+ return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc)
opimpl_residual_call_r_i = _opimpl_residual_call1
opimpl_residual_call_r_r = _opimpl_residual_call1
@@ -852,8 +856,8 @@
opimpl_residual_call_irf_f = _opimpl_residual_call3
opimpl_residual_call_irf_v = _opimpl_residual_call3
- @arguments("int", "boxes3", "boxes3")
- def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes):
+ @arguments("int", "boxes3", "boxes3", "orgpc")
+ def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes, pc):
targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
allboxes = greenboxes + redboxes
warmrunnerstate = targetjitdriver_sd.warmstate
@@ -868,15 +872,15 @@
# that assembler that we call is still correct
self.verify_green_args(targetjitdriver_sd, greenboxes)
#
- return self.do_recursive_call(targetjitdriver_sd, allboxes,
+ return self.do_recursive_call(targetjitdriver_sd, allboxes, pc,
assembler_call)
- def do_recursive_call(self, targetjitdriver_sd, allboxes,
+ def do_recursive_call(self, targetjitdriver_sd, allboxes, pc,
assembler_call=False):
portal_code = targetjitdriver_sd.mainjitcode
k = targetjitdriver_sd.portal_runner_adr
funcbox = ConstInt(heaptracker.adr2int(k))
- return self.do_residual_call(funcbox, allboxes, portal_code.calldescr,
+ return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, pc,
assembler_call=assembler_call,
assembler_call_jd=targetjitdriver_sd)
@@ -935,7 +939,7 @@
return box # no promotion needed, already a Const
else:
constbox = box.constbox()
- resbox = self.do_residual_call(funcbox, [box, constbox], descr)
+ resbox = self.do_residual_call(funcbox, [box, constbox], descr, orgpc)
promoted_box = resbox.constbox()
# This is GUARD_VALUE because GUARD_TRUE assumes the existance
# of a label when computing resumepc
@@ -1027,7 +1031,7 @@
except ChangeFrame:
pass
frame = self.metainterp.framestack[-1]
- frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes,
+ frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, orgpc,
assembler_call=True)
raise ChangeFrame
@@ -1329,7 +1333,7 @@
self.metainterp.assert_no_exception()
return resbox
- def do_residual_call(self, funcbox, argboxes, descr,
+ def do_residual_call(self, funcbox, argboxes, descr, pc,
assembler_call=False,
assembler_call_jd=None):
# First build allboxes: it may need some reordering from the
@@ -1369,6 +1373,10 @@
effectinfo.check_forces_virtual_or_virtualizable()):
# residual calls require attention to keep virtualizables in-sync
self.metainterp.clear_exception()
+ if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL:
+ resbox = self._do_jit_force_virtual(allboxes, descr, pc)
+ if resbox is not None:
+ return resbox
self.metainterp.vable_and_vrefs_before_residual_call()
resbox = self.metainterp.execute_and_record_varargs(
rop.CALL_MAY_FORCE, allboxes, descr=descr)
@@ -1399,7 +1407,27 @@
pure = effectinfo.check_is_elidable()
return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure)
- def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr):
+ def _do_jit_force_virtual(self, allboxes, descr, pc):
+ assert len(allboxes) == 2
+ if (self.metainterp.jitdriver_sd.virtualizable_info is None and
+ self.metainterp.jitdriver_sd.greenfield_info is None):
+ # can occur in case of multiple JITs
+ return None
+ vref_box = allboxes[1]
+ standard_box = self.metainterp.virtualizable_boxes[-1]
+ if standard_box is vref_box:
+ return vref_box
+ if self.metainterp.heapcache.is_nonstandard_virtualizable(vref_box):
+ return None
+ eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, vref_box, standard_box)
+ eqbox = self.implement_guard_value(eqbox, pc)
+ isstandard = eqbox.getint()
+ if isstandard:
+ return standard_box
+ else:
+ return None
+
+ def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr, pc):
"""The 'residual_call' operation is emitted in two cases:
when we have to generate a residual CALL operation, but also
to handle an indirect_call that may need to be inlined."""
@@ -1411,7 +1439,7 @@
# we should follow calls to this graph
return self.metainterp.perform_call(jitcode, argboxes)
# but we should not follow calls to that graph
- return self.do_residual_call(funcbox, argboxes, calldescr)
+ return self.do_residual_call(funcbox, argboxes, calldescr, pc)
# ____________________________________________________________
diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py
--- a/rpython/jit/metainterp/test/test_virtualizable.py
+++ b/rpython/jit/metainterp/test/test_virtualizable.py
@@ -1,20 +1,22 @@
import py
+
+from rpython.jit.codewriter import heaptracker
+from rpython.jit.codewriter.policy import StopAtXPolicy
+from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
+from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin
+from rpython.jit.metainterp.warmspot import get_translator
+from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote, virtual_ref
+from rpython.rlib.rarithmetic import intmask
+from rpython.rtyper.annlowlevel import hlstr
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rtyper.lltypesystem import lltype, lloperation, rclass, llmemory
-from rpython.rtyper.annlowlevel import llhelper
-from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY
-from rpython.jit.codewriter.policy import StopAtXPolicy
-from rpython.jit.codewriter import heaptracker
-from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote
-from rpython.rlib.rarithmetic import intmask
-from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin
-from rpython.rtyper.rclass import FieldListAccessor
-from rpython.jit.metainterp.warmspot import get_stats, get_translator
-from rpython.jit.metainterp import history
-from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
+from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY, FieldListAccessor
+
def promote_virtualizable(*args):
pass
+
+
class Entry(ExtRegistryEntry):
"Annotation and rtyping of LLOp instances, which are callable."
_about_ = promote_virtualizable
@@ -46,7 +48,7 @@
('inst_node', lltype.Ptr(LLtypeMixin.NODE)),
hints = {'virtualizable2_accessor': FieldListAccessor()})
XY._hints['virtualizable2_accessor'].initialize(
- XY, {'inst_x' : IR_IMMUTABLE, 'inst_node' : IR_IMMUTABLE})
+ XY, {'inst_x': IR_IMMUTABLE, 'inst_node': IR_IMMUTABLE})
xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable, 'XY')
@@ -73,7 +75,7 @@
x = xy.inst_x
xy.inst_x = x + 1
n -= 1
- promote_virtualizable(xy, 'inst_x')
+ promote_virtualizable(xy, 'inst_x')
return xy.inst_x
res = self.meta_interp(f, [20])
assert res == 30
@@ -97,7 +99,7 @@
x = xy.inst_x
xy.inst_x = x + 10
n -= 1
- promote_virtualizable(xy, 'inst_x')
+ promote_virtualizable(xy, 'inst_x')
return xy.inst_x
assert f(5) == 185
res = self.meta_interp(f, [5])
@@ -118,10 +120,10 @@
x = xy.inst_x
if n <= 10:
x += 1000
- promote_virtualizable(xy, 'inst_x')
+ promote_virtualizable(xy, 'inst_x')
xy.inst_x = x + 1
n -= 1
- promote_virtualizable(xy, 'inst_x')
+ promote_virtualizable(xy, 'inst_x')
return xy.inst_x
res = self.meta_interp(f, [18])
assert res == 10118
@@ -164,7 +166,7 @@
xy.inst_x = x + 1
m = (m+1) & 3 # the loop gets unrolled 4 times
n -= 1
- promote_virtualizable(xy, 'inst_x')
+ promote_virtualizable(xy, 'inst_x')
return xy.inst_x
def f(n):
res = 0
@@ -194,7 +196,7 @@
promote_virtualizable(xy, 'inst_x')
xy.inst_x = value + 100 # virtualized away
n -= 1
- promote_virtualizable(xy, 'inst_x')
+ promote_virtualizable(xy, 'inst_x')
return xy.inst_x
res = self.meta_interp(f, [20])
assert res == 134
@@ -212,8 +214,8 @@
('inst_l2', lltype.Ptr(lltype.GcArray(lltype.Signed))),
hints = {'virtualizable2_accessor': FieldListAccessor()})
XY2._hints['virtualizable2_accessor'].initialize(
- XY2, {'inst_x' : IR_IMMUTABLE,
- 'inst_l1' : IR_IMMUTABLE_ARRAY, 'inst_l2' : IR_IMMUTABLE_ARRAY})
+ XY2, {'inst_x': IR_IMMUTABLE,
+ 'inst_l1': IR_IMMUTABLE_ARRAY, 'inst_l2': IR_IMMUTABLE_ARRAY})
xy2_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
heaptracker.set_testing_vtable_for_gcstruct(XY2, xy2_vtable, 'XY2')
@@ -241,11 +243,11 @@
while n > 0:
myjitdriver.can_enter_jit(xy2=xy2, n=n)
myjitdriver.jit_merge_point(xy2=xy2, n=n)
- promote_virtualizable(xy2, 'inst_l1')
+ promote_virtualizable(xy2, 'inst_l1')
promote_virtualizable(xy2, 'inst_l2')
xy2.inst_l1[2] += xy2.inst_l2[0]
n -= 1
- promote_virtualizable(xy2, 'inst_l1')
+ promote_virtualizable(xy2, 'inst_l1')
return xy2.inst_l1[2]
res = self.meta_interp(f, [16])
assert res == 3001 + 16 * 80
@@ -292,7 +294,7 @@
myjitdriver.can_enter_jit(xy2=xy2, n=n)
myjitdriver.jit_merge_point(xy2=xy2, n=n)
promote_virtualizable(xy2, 'inst_l1')
- promote_virtualizable(xy2, 'inst_l2')
+ promote_virtualizable(xy2, 'inst_l2')
xy2.inst_l1[1] += len(xy2.inst_l2)
n -= 1
def f(n):
@@ -373,7 +375,7 @@
promote_virtualizable(xy2, 'inst_l2')
xy2.inst_l2[0] = value + 100 # virtualized away
n -= 1
- promote_virtualizable(xy2, 'inst_l2')
+ promote_virtualizable(xy2, 'inst_l2')
return xy2.inst_l2[0]
expected = f(20)
res = self.meta_interp(f, [20], enable_opts='')
@@ -406,8 +408,8 @@
myjitdriver.can_enter_jit(xy2=xy2, n=n)
myjitdriver.jit_merge_point(xy2=xy2, n=n)
parent = xy2.parent
- promote_virtualizable(parent, 'inst_x')
- promote_virtualizable(parent, 'inst_l2')
+ promote_virtualizable(parent, 'inst_x')
+ promote_virtualizable(parent, 'inst_l2')
parent.inst_l2[0] += parent.inst_x
n -= 1
def f(n):
@@ -432,8 +434,7 @@
# ------------------------------
-class ImplicitVirtualizableTests:
-
+class ImplicitVirtualizableTests(object):
def test_simple_implicit(self):
myjitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
@@ -473,9 +474,9 @@
def __init__(self, l, s):
self.l = l
self.s = s
-
+
def f(n, a):
- frame = Frame([a,a+1,a+2,a+3], 0)
+ frame = Frame([a, a+1, a+2, a+3], 0)
x = 0
while n > 0:
myjitdriver.can_enter_jit(frame=frame, n=n, x=x)
@@ -544,7 +545,7 @@
def f(n):
BaseFrame([]) # hack to force 'x' to be in BaseFrame
- frame = Frame([1,2,3])
+ frame = Frame([1, 2, 3])
z = 0
while n > 0:
jitdriver.can_enter_jit(frame=frame, n=n, z=z)
@@ -560,9 +561,10 @@
def test_external_read(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -592,9 +594,10 @@
def test_external_read_with_exception(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -634,6 +637,7 @@
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -663,9 +667,10 @@
def test_external_read_sometimes(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -699,11 +704,13 @@
def test_external_read_sometimes_with_virtuals(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class Y:
pass
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -742,11 +749,13 @@
def test_external_read_sometimes_changing_virtuals(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class Y:
pass
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -790,11 +799,13 @@
def test_external_read_sometimes_with_exception(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class FooBarError(Exception):
pass
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -832,9 +843,10 @@
def test_external_read_sometimes_dont_compile_guard(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -868,9 +880,10 @@
def test_external_read_sometimes_recursive(self):
jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -919,9 +932,10 @@
def test_external_write_sometimes(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -955,9 +969,10 @@
def test_bridge_forces(self):
jitdriver = JitDriver(greens = [], reds = ['frame'],
virtualizables = ['frame'])
-
+
class Frame(object):
_virtualizable2_ = ['x', 'y']
+
class SomewhereElse:
pass
somewhere_else = SomewhereElse()
@@ -988,6 +1003,7 @@
def test_promote_index_in_virtualizable_list(self):
jitdriver = JitDriver(greens = [], reds = ['n', 'frame'],
virtualizables = ['frame'])
+
class Frame(object):
_virtualizable2_ = ['stackpos', 'stack[*]']
@@ -1063,8 +1079,8 @@
assert direct_calls(f_graph) == ['__init__',
'force_virtualizable_if_necessary',
'll_portal_runner']
- assert direct_calls(portal_graph)==['force_virtualizable_if_necessary',
- 'maybe_enter_jit']
+ assert direct_calls(portal_graph) == ['force_virtualizable_if_necessary',
+ 'maybe_enter_jit']
assert direct_calls(init_graph) == []
def test_virtual_child_frame(self):
@@ -1262,7 +1278,7 @@
somewhere_else = SomewhereElse()
def jump_back(frame, fail):
- myjitdriver.can_enter_jit(frame=frame, fail=fail)
+ myjitdriver.can_enter_jit(frame=frame, fail=fail)
def f(n, fail):
frame = Frame(n, 0)
@@ -1315,8 +1331,10 @@
f.x -= 1
result += indirection(f)
return result
+
def indirection(arg):
return interp(arg)
+
def run_interp(n):
f = hint(Frame(n), access_directly=True)
return interp(f)
@@ -1325,7 +1343,7 @@
assert res == run_interp(4)
def test_guard_failure_in_inlined_function(self):
- from rpython.rtyper.annlowlevel import hlstr
+
class Frame(object):
_virtualizable2_ = ['n', 'next']
@@ -1368,11 +1386,12 @@
assert 0
pc += 1
return frame.n
+
def main(n):
frame = Frame(n)
return f("c-l", frame)
More information about the pypy-commit
mailing list