[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Mon Mar 18 23:08:39 CET 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r62411:7d3b2666f8b2
Date: 2013-03-18 15:08 -0700
http://bitbucket.org/pypy/pypy/changeset/7d3b2666f8b2/
Log: merge default
diff too long, truncating to 2000 out of 23512 lines
diff --git a/lib-python/2/distutils/sysconfig_pypy.py b/lib-python/2/distutils/sysconfig_pypy.py
--- a/lib-python/2/distutils/sysconfig_pypy.py
+++ b/lib-python/2/distutils/sysconfig_pypy.py
@@ -43,7 +43,7 @@
if prefix is None:
prefix = PREFIX
if standard_lib:
- return os.path.join(prefix, "lib-python", get_python_version())
+ return os.path.join(prefix, "lib-python", sys.version[0])
return os.path.join(prefix, 'site-packages')
@@ -61,6 +61,7 @@
g['SO'] = _get_so_extension() or ".so"
g['SOABI'] = g['SO'].rsplit('.')[0]
g['LIBDIR'] = os.path.join(sys.prefix, 'lib')
+ g['CC'] = "gcc -pthread" # -pthread might not be valid on OS/X, check
global _config_vars
_config_vars = g
diff --git a/lib-python/2/pickle.py b/lib-python/2/pickle.py
--- a/lib-python/2/pickle.py
+++ b/lib-python/2/pickle.py
@@ -34,6 +34,8 @@
import struct
import re
+from __pypy__.builders import StringBuilder
+
__all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler",
"Unpickler", "dump", "dumps", "load", "loads"]
@@ -1409,11 +1411,24 @@
except ImportError:
from StringIO import StringIO
+
+class StringBuilderFile(object):
+ ''' pickle uses only file.write - provide this method,
+ use StringBuilder for speed
+ '''
+ def __init__(self):
+ self.builder = StringBuilder()
+ self.write = self.builder.append
+
+ def getvalue(self):
+ return self.builder.build()
+
+
def dump(obj, file, protocol=None):
Pickler(file, protocol).dump(obj)
def dumps(obj, protocol=None):
- file = StringIO()
+ file = StringBuilderFile()
Pickler(file, protocol).dump(obj)
return file.getvalue()
diff --git a/lib-python/2/sysconfig.py b/lib-python/2/sysconfig.py
--- a/lib-python/2/sysconfig.py
+++ b/lib-python/2/sysconfig.py
@@ -27,10 +27,10 @@
'data' : '{base}',
},
'pypy': {
- 'stdlib': '{base}/lib-python/{py_version_short}',
- 'platstdlib': '{base}/lib-python/{py_version_short}',
- 'purelib': '{base}/lib-python/{py_version_short}',
- 'platlib': '{base}/lib-python/{py_version_short}',
+ 'stdlib': '{base}/lib-python/{py_version}',
+ 'platstdlib': '{base}/lib-python/{py_version}',
+ 'purelib': '{base}/lib-python/{py_version}',
+ 'platlib': '{base}/lib-python/{py_version}',
'include': '{base}/include',
'platinclude': '{base}/include',
'scripts': '{base}/bin',
diff --git a/lib_pypy/_marshal.py b/lib_pypy/_marshal.py
--- a/lib_pypy/_marshal.py
+++ b/lib_pypy/_marshal.py
@@ -7,7 +7,6 @@
# the "sandboxed" process. It must work for Python2 as well.
import types
-from _codecs import utf_8_decode, utf_8_encode
try:
intern
@@ -166,9 +165,8 @@
def dump_unicode(self, x):
self._write(TYPE_UNICODE)
- #s = x.encode('utf8')
- s, len_s = utf_8_encode(x)
- self.w_long(len_s)
+ s = x.encode('utf8')
+ self.w_long(len(s))
self._write(s)
try:
unicode
@@ -386,8 +384,7 @@
def load_unicode(self):
n = self.r_long()
s = self._read(n)
- #ret = s.decode('utf8')
- ret, len_ret = utf_8_decode(s)
+ ret = s.decode('utf8')
return ret
dispatch[TYPE_UNICODE] = load_unicode
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -364,9 +364,10 @@
self._in_transaction = False
self.isolation_level = isolation_level
- self._cursors = []
+ self.__cursors = []
+ self.__cursors_counter = 0
self.__statements = []
- self.__statement_counter = 0
+ self.__statements_counter = 0
self._statement_cache = _StatementCache(self, cached_statements)
self.__func_cache = {}
@@ -394,10 +395,7 @@
def close(self):
self._check_thread()
- for statement in self.__statements:
- obj = statement()
- if obj is not None:
- obj._finalize()
+ self.__do_all_statements(Statement._finalize, True)
if self._db:
ret = _lib.sqlite3_close(self._db)
@@ -469,13 +467,33 @@
exc.error_code = error_code
return exc
+ def _remember_cursor(self, cursor):
+ self.__cursors.append(weakref.ref(cursor))
+ self.__cursors_counter += 1
+ if self.__cursors_counter < 200:
+ return
+ self.__cursors_counter = 0
+ self.__cursors = [r for r in self.__cursors if r() is not None]
+
def _remember_statement(self, statement):
self.__statements.append(weakref.ref(statement))
- self.__statement_counter += 1
+ self.__statements_counter += 1
+ if self.__statements_counter < 200:
+ return
+ self.__statements_counter = 0
+ self.__statements = [r for r in self.__statements if r() is not None]
- if self.__statement_counter % 100 == 0:
- self.__statements = [ref for ref in self.__statements
- if ref() is not None]
+ def __do_all_statements(self, action, reset_cursors):
+ for weakref in self.__statements:
+ statement = weakref()
+ if statement is not None:
+ action(statement)
+
+ if reset_cursors:
+ for weakref in self.__cursors:
+ cursor = weakref()
+ if cursor is not None:
+ cursor._reset = True
@_check_thread_wrap
@_check_closed_wrap
@@ -528,10 +546,7 @@
if not self._in_transaction:
return
- for statement in self.__statements:
- obj = statement()
- if obj is not None:
- obj._reset()
+ self.__do_all_statements(Statement._reset, False)
statement = c_void_p()
ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1,
@@ -552,15 +567,7 @@
if not self._in_transaction:
return
- for statement in self.__statements:
- obj = statement()
- if obj is not None:
- obj._reset()
-
- for cursor_ref in self._cursors:
- cursor = cursor_ref()
- if cursor:
- cursor._reset = True
+ self.__do_all_statements(Statement._reset, True)
statement = c_void_p()
ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1,
@@ -787,14 +794,9 @@
__statement = None
def __init__(self, con):
- self.__initialized = True
- self.__connection = con
-
if not isinstance(con, Connection):
raise TypeError
- con._check_thread()
- con._check_closed()
- con._cursors.append(weakref.ref(self))
+ self.__connection = con
self.arraysize = 1
self.row_factory = None
@@ -804,11 +806,12 @@
self.__description = None
self.__rowcount = -1
+ con._check_thread()
+ con._remember_cursor(self)
+
+ self.__initialized = True
+
def __del__(self):
- try:
- self.__connection._cursors.remove(weakref.ref(self))
- except (AttributeError, ValueError):
- pass
if self.__statement:
self.__statement._reset()
@@ -876,9 +879,6 @@
if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW:
self.__statement._build_row_cast_map()
self.__statement._readahead(self)
- else:
- self.__statement._item = None
- self.__statement._exhausted = True
if self.__statement._kind == Statement._DML:
if self.__rowcount == -1:
@@ -886,7 +886,6 @@
self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
finally:
self.__locked = False
-
return self
@__check_cursor_wrap
@@ -924,9 +923,10 @@
if rc != _lib.SQLITE_DONE:
_lib.sqlite3_finalize(statement)
if rc == _lib.SQLITE_OK:
- return self
+ break
else:
raise self.__connection._get_exception(rc)
+
rc = _lib.sqlite3_finalize(statement)
if rc != _lib.SQLITE_OK:
raise self.__connection._get_exception(rc)
@@ -1003,6 +1003,7 @@
def __init__(self, connection, sql):
self.__con = connection
+ self.__con._remember_statement(self)
if not isinstance(sql, basestring):
raise Warning("SQL is of wrong type. Must be string or unicode.")
@@ -1015,7 +1016,6 @@
self._kind = Statement._DDL
self._in_use = False
- self._exhausted = False
self._row_factory = None
if isinstance(sql, unicode):
@@ -1031,10 +1031,9 @@
ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1,
byref(self._statement), byref(sql))
self._kind = Statement._DQL
-
if ret != _lib.SQLITE_OK:
raise self.__con._get_exception(ret)
- self.__con._remember_statement(self)
+
sql = sql.value.decode('utf-8')
if _check_remaining_sql(sql):
raise Warning("You can only execute one statement at a time.")
@@ -1053,7 +1052,6 @@
if self._in_use and self._statement:
_lib.sqlite3_reset(self._statement)
self._in_use = False
- self._exhausted = False
if sys.version_info[0] < 3:
def __check_decodable(self, param):
@@ -1218,20 +1216,19 @@
self._item = row
def _next(self, cursor):
- if self._exhausted:
+ try:
+ item = self._item
+ except AttributeError:
raise StopIteration
- item = self._item
+ del self._item
ret = _lib.sqlite3_step(self._statement)
- if ret == _lib.SQLITE_DONE:
- self._exhausted = True
- self._item = None
- elif ret != _lib.SQLITE_ROW:
- exc = self.__con._get_exception(ret)
+ if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW):
_lib.sqlite3_reset(self._statement)
- raise exc
+ raise self.__con._get_exception(ret)
+ elif ret == _lib.SQLITE_ROW:
+ self._readahead(cursor)
- self._readahead(cursor)
return item
def _get_description(self):
diff --git a/lib_pypy/numpypy/core/numeric.py b/lib_pypy/numpypy/core/numeric.py
--- a/lib_pypy/numpypy/core/numeric.py
+++ b/lib_pypy/numpypy/core/numeric.py
@@ -4,6 +4,7 @@
'array_repr', 'array_str', 'set_string_function',
'array_equal', 'outer', 'vdot', 'identity', 'little_endian',
'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN', 'False_', 'True_',
+ 'seterr',
]
import sys
diff --git a/pypy/TODO b/pypy/TODO
new file mode 100644
--- /dev/null
+++ b/pypy/TODO
@@ -0,0 +1,2 @@
+
+* ARM
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
@@ -42,6 +42,7 @@
.. branch: numpy-unify-methods
.. branch: fix-version-tool
.. branch: popen2-removal
+.. branch: pickle-dumps
.. branch: release-2.0-beta1
@@ -85,3 +86,8 @@
.. branch: vendor-rename
Remove minor verison number from lib-python dirs to simplify stdlib upgrades.
+
+.. branch: jitframe-on-heap
+Moves optimized JIT frames from stack to heap. As a side effect it enables
+stackless to work well with the JIT on PyPy. Also removes a bunch of code from
+the GC which fixes cannot find gc roots.
diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py
new file mode 100755
--- /dev/null
+++ b/pypy/goal/getnightly.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import py
+
+if sys.platform.startswith('linux'):
+ arch = 'linux'
+else:
+ print 'Cannot determine the platform, please update this scrip'
+ sys.exit(1)
+
+if sys.maxint == 2**63 - 1:
+ arch += '64'
+
+filename = 'pypy-c-jit-latest-%s.tar.bz2' % arch
+url = 'http://buildbot.pypy.org/nightly/trunk/%s' % filename
+tmp = py.path.local.mkdtemp()
+mydir = tmp.chdir()
+print 'Downloading pypy to', tmp
+if os.system('wget "%s"' % url) != 0:
+ sys.exit(1)
+
+print 'Extracting pypy binary'
+mydir.chdir()
+os.system("tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy'" % tmp.join(filename))
+
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -1,8 +1,15 @@
-import os, sys
+import cStringIO
import itertools
+import os
+import sys
+import traceback
+from errno import EINTR
+
from rpython.rlib import jit
from rpython.rlib.objectmodel import we_are_translated
-from errno import EINTR
+
+from pypy.interpreter import debug
+
AUTO_DEBUG = os.getenv('PYPY_DEBUG')
RECORD_INTERPLEVEL_TRACEBACK = True
@@ -94,7 +101,7 @@
if space is None:
# this part NOT_RPYTHON
exc_typename = str(self.w_type)
- exc_value = str(w_value)
+ exc_value = str(w_value)
else:
w = space.wrap
if space.is_w(space.type(self.w_type), space.w_text):
@@ -128,7 +135,8 @@
def print_application_traceback(self, space, file=None):
"NOT_RPYTHON: Dump a standard application-level traceback."
- if file is None: file = sys.stderr
+ if file is None:
+ file = sys.stderr
self.print_app_tb_only(file)
print >> file, self.errorstr(space)
@@ -163,8 +171,8 @@
def print_detailed_traceback(self, space=None, file=None):
"""NOT_RPYTHON: Dump a nice detailed interpreter- and
application-level traceback, useful to debug the interpreter."""
- import traceback, cStringIO
- if file is None: file = sys.stderr
+ if file is None:
+ file = sys.stderr
f = cStringIO.StringIO()
for i in range(len(self.debug_excs)-1, -1, -1):
print >> f, "Traceback (interpreter-level):"
@@ -177,7 +185,6 @@
self.print_app_tb_only(file)
print >> file, '(application-level)', self.errorstr(space)
if AUTO_DEBUG:
- import debug
debug.fire(self)
@jit.unroll_safe
@@ -202,7 +209,7 @@
# (Class, x) (Class, Class(x)) no
# (inst, None) (inst.__class__, inst) no
#
- w_type = self.w_type
+ w_type = self.w_type
w_value = self.get_w_value(space)
if space.exception_is_valid_obj_as_class_w(w_type):
@@ -252,7 +259,7 @@
w_value = w_inst
w_type = w_instclass
- self.w_type = w_type
+ self.w_type = w_type
self._w_value = w_value
def _exception_getclass(self, space, w_inst, what="exceptions"):
@@ -372,7 +379,7 @@
from rpython.rlib.unroll import unrolling_iterable
attrs = ['x%d' % i for i in range(len(formats))]
entries = unrolling_iterable(zip(itertools.count(), formats, attrs))
- #
+
class OpErrFmt(OperationError):
def __init__(self, w_type, strings, *args):
assert len(args) == len(strings) - 1
@@ -381,6 +388,7 @@
setattr(self, attr, args[i])
assert w_type is not None
self.setup(w_type)
+
def _compute_value(self):
lst = [None] * (len(formats) + len(formats) + 1)
for i, fmt, attr in entries:
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -1,11 +1,13 @@
-from pypy.interpreter.error import OperationError
-from pypy.interpreter import function, pycode, pyframe
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.mixedmodule import MixedModule
-from pypy.interpreter.astcompiler import consts
from rpython.rlib import jit
from rpython.tool.uid import uid
+from pypy.interpreter import function, pycode, pyframe
+from pypy.interpreter.astcompiler import consts
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.mixedmodule import MixedModule
+
+
class Cell(Wrappable):
"A simple container for a wrapped value."
@@ -20,7 +22,7 @@
def get(self):
if self.w_value is None:
- raise ValueError, "get() from an empty cell"
+ raise ValueError("get() from an empty cell")
return self.w_value
def set(self, w_value):
@@ -28,7 +30,7 @@
def delete(self):
if self.w_value is None:
- raise ValueError, "delete() on an empty cell"
+ raise ValueError("delete() on an empty cell")
self.w_value = None
def descr__lt__(self, space, w_other):
@@ -53,10 +55,10 @@
return space.eq(self.w_value, other.w_value)
def descr__reduce__(self, space):
- w_mod = space.getbuiltinmodule('_pickle_support')
- mod = space.interp_w(MixedModule, w_mod)
+ w_mod = space.getbuiltinmodule('_pickle_support')
+ mod = space.interp_w(MixedModule, w_mod)
new_inst = mod.get('cell_new')
- if self.w_value is None: #when would this happen?
+ if self.w_value is None: # when would this happen?
return space.newtuple([new_inst, space.newtuple([])])
tup = [self.w_value]
return space.newtuple([new_inst, space.newtuple([]),
@@ -64,7 +66,7 @@
def descr__setstate__(self, space, w_state):
self.w_value = space.getitem(w_state, space.wrap(0))
-
+
def __repr__(self):
""" representation for debugging purposes """
if self.w_value is None:
@@ -81,10 +83,9 @@
raise OperationError(space.w_ValueError, space.wrap("Cell is empty"))
-
super_initialize_frame_scopes = pyframe.PyFrame.initialize_frame_scopes
-super_fast2locals = pyframe.PyFrame.fast2locals
-super_locals2fast = pyframe.PyFrame.locals2fast
+super_fast2locals = pyframe.PyFrame.fast2locals
+super_locals2fast = pyframe.PyFrame.locals2fast
class __extend__(pyframe.PyFrame):
@@ -139,7 +140,7 @@
def fast2locals(self):
super_fast2locals(self)
# cellvars are values exported to inner scopes
- # freevars are values coming from outer scopes
+ # freevars are values coming from outer scopes
freevarnames = list(self.pycode.co_cellvars)
if self.pycode.co_flags & consts.CO_OPTIMIZED:
freevarnames.extend(self.pycode.co_freevars)
diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -19,11 +19,6 @@
# - normal: self.sthread != None, not is_empty_handle(self.h)
# - finished: self.sthread != None, is_empty_handle(self.h)
- def __del__(self):
- sthread = self.sthread
- if sthread is not None and not sthread.is_empty_handle(self.h):
- sthread.destroy(self.h)
-
def check_sthread(self):
ec = self.space.getexecutioncontext()
if ec.stacklet_thread is not self.sthread:
@@ -34,7 +29,6 @@
if self.sthread is not None:
raise geterror(self.space, "continulet already __init__ialized")
sthread = build_sthread(self.space)
- workaround_disable_jit(sthread)
#
# hackish: build the frame "by hand", passing it the correct arguments
space = self.space
@@ -77,8 +71,7 @@
global_state.clear()
raise geterror(self.space, "continulet already finished")
self.check_sthread()
- workaround_disable_jit(self.sthread)
- #
+
global_state.origin = self
if to is None:
# simple switch: going to self.h
@@ -271,16 +264,6 @@
sthread = ec.stacklet_thread = SThread(space, ec)
return sthread
-def workaround_disable_jit(sthread):
- # A bad workaround to kill the JIT anywhere in this thread.
- # This forces all the frames. It's a bad workaround because
- # it takes O(depth) time, and it will cause some "abort:
- # vable escape" in the JIT. The goal is to prevent any frame
- # from being still virtuals, because the JIT generates code
- # to un-virtualizable them "on demand" by loading values based
- # on FORCE_TOKEN, which is an address in the stack.
- sthread.ec.force_all_frames()
-
# ____________________________________________________________
def permute(space, args_w):
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -391,7 +391,11 @@
def remove(self, w_iobase):
holder = w_iobase.streamholder
if holder is not None:
- del self.streams[holder]
+ try:
+ del self.streams[holder]
+ except KeyError:
+ # this can happen in daemon threads
+ pass
def flush_all(self, space):
while self.streams:
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ b/pypy/module/cppyy/capi/reflex_capi.py
@@ -9,18 +9,23 @@
srcpath = pkgpath.join("src")
incpath = pkgpath.join("include")
+import commands
+(config_stat, incdir) = commands.getstatusoutput("root-config --incdir")
+
if os.environ.get("ROOTSYS"):
- import commands
- (stat, incdir) = commands.getstatusoutput("root-config --incdir")
- if stat != 0: # presumably Reflex-only
+ if config_stat != 0: # presumably Reflex-only
rootincpath = [os.path.join(os.environ["ROOTSYS"], "include")]
rootlibpath = [os.path.join(os.environ["ROOTSYS"], "lib64"), os.path.join(os.environ["ROOTSYS"], "lib")]
else:
rootincpath = [incdir]
rootlibpath = commands.getoutput("root-config --libdir").split()
else:
- rootincpath = []
- rootlibpath = []
+ if config_stat == 0:
+ rootincpath = [incdir]
+ rootlibpath = commands.getoutput("root-config --libdir").split()
+ else:
+ rootincpath = []
+ rootlibpath = []
def identify():
return 'Reflex'
diff --git a/pypy/module/cppyy/test/Makefile b/pypy/module/cppyy/test/Makefile
--- a/pypy/module/cppyy/test/Makefile
+++ b/pypy/module/cppyy/test/Makefile
@@ -7,7 +7,7 @@
ifeq ($(ROOTSYS),)
genreflex=genreflex
- cppflags=
+ cppflags=-I$(shell root-config --incdir) -L$(shell root-config --libdir)
else
genreflex=$(ROOTSYS)/bin/genreflex
ifeq ($(wildcard $(ROOTSYS)/include),) # standard locations used?
diff --git a/pypy/module/cppyy/test/test_crossing.py b/pypy/module/cppyy/test/test_crossing.py
--- a/pypy/module/cppyy/test/test_crossing.py
+++ b/pypy/module/cppyy/test/test_crossing.py
@@ -1,6 +1,16 @@
import py, os, sys
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.translator import platform
+from rpython.translator.gensupp import uniquemodulename
+from rpython.tool.udir import udir
+
+from pypy.module.cpyext import api
+from pypy.module.cpyext.state import State
+
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
currpath = py.path.local(__file__).dirpath()
test_dct = str(currpath.join("crossingDict.so"))
@@ -11,27 +21,90 @@
if err:
raise OSError("'make' failed (see stderr)")
+# from pypy/module/cpyext/test/test_cpyext.py; modified to accept more external
+# symbols and called directly instead of import_module
+def compile_extension_module(space, modname, symbols, **kwds):
+ """
+ Build an extension module and return the filename of the resulting native
+ code file.
+
+ modname is the name of the module, possibly including dots if it is a module
+ inside a package.
+
+ Any extra keyword arguments are passed on to ExternalCompilationInfo to
+ build the module (so specify your source with one of those).
+ """
+ state = space.fromcache(State)
+ api_library = state.api_lib
+ if sys.platform == 'win32':
+ kwds["libraries"] = [api_library]
+ # '%s' undefined; assuming extern returning int
+ kwds["compile_extra"] = ["/we4013"]
+ elif sys.platform == 'darwin':
+ kwds["link_files"] = [str(api_library + '.dylib')]
+ else:
+ kwds["link_files"] = [str(api_library + '.so')]
+ if sys.platform.startswith('linux'):
+ kwds["compile_extra"]=["-Werror=implicit-function-declaration"]
+
+ modname = modname.split('.')[-1]
+ eci = ExternalCompilationInfo(
+ export_symbols=['init%s' % (modname,)]+symbols,
+ include_dirs=api.include_dirs,
+ **kwds
+ )
+ eci = eci.convert_sources_to_files()
+ dirname = (udir/uniquemodulename('module')).ensure(dir=1)
+ soname = platform.platform.compile(
+ [], eci,
+ outputfilename=str(dirname/modname),
+ standalone=False)
+ from pypy.module.imp.importing import get_so_extension
+ pydname = soname.new(purebasename=modname, ext=get_so_extension(space))
+ soname.rename(pydname)
+ return str(pydname)
class AppTestCrossing(AppTestCpythonExtensionBase):
spaceconfig = dict(usemodules=['cpyext', 'cppyy', 'thread', '_rawffi', '_ffi',
'array', 'itertools', 'rctime', 'binascii'])
def setup_class(cls):
- # following from AppTestCpythonExtensionBase, with cppyy added
- cls.space.getbuiltinmodule("cpyext")
- from pypy.module.imp.importing import importhook
- importhook(cls.space, "os") # warm up reference counts
- from pypy.module.cpyext.pyobject import RefcountState
- state = cls.space.fromcache(RefcountState)
- state.non_heaptypes_w[:] = []
-
- # cppyy specific additions (not that the test_dct is loaded late
+ AppTestCpythonExtensionBase.setup_class.im_func(cls)
+ # cppyy specific additions (note that test_dct is loaded late
# to allow the generated extension module be loaded first)
cls.w_test_dct = cls.space.wrap(test_dct)
cls.w_pre_imports = cls.space.appexec([], """():
import cppyy, ctypes""") # prevents leak-checking complaints on ctypes
- from pypy.module.imp.importing import get_so_extension
- cls.w_soext = cls.space.wrap(get_so_extension(cls.space))
+
+ def setup_method(self, func):
+ AppTestCpythonExtensionBase.setup_method.im_func(self, func)
+
+ @unwrap_spec(name=str, init=str, body=str)
+ def load_cdll(space, name, init, body, w_symbols):
+ # the following is loosely from test_cpyext.py import_module; it
+ # is copied here to be able to tweak the call to
+ # compile_extension_module and to get a different return result
+ # than in that function
+ code = """
+ #include <Python.h>
+ %(body)s
+
+ void init%(name)s(void) {
+ %(init)s
+ }
+ """ % dict(name=name, init=init, body=body)
+ kwds = dict(separate_module_sources=[code])
+ symbols = [space.str_w(w_item) for w_item in space.fixedview(w_symbols)]
+ mod = compile_extension_module(space, name, symbols, **kwds)
+
+ # explicitly load the module as a CDLL rather than as a module
+ import ctypes
+ from pypy.module.imp.importing import get_so_extension
+ fullmodname = os.path.join(
+ os.path.dirname(mod), name + get_so_extension(space))
+ return ctypes.CDLL(fullmodname, ctypes.RTLD_GLOBAL)
+
+ self.w_load_cdll = self.space.wrap(interp2app(load_cdll))
def test00_base_class(self):
"""Test from cpyext; only here to see whether the imported class works"""
@@ -49,10 +122,13 @@
import os, ctypes
+ name = 'bar'
+
init = """
if (Py_IsInitialized())
Py_InitModule("bar", methods);
"""
+
# note: only the symbols are needed for C, none for python
body = """
long bar_unwrap(PyObject* arg)
@@ -67,10 +143,12 @@
{ NULL }
};
"""
+ # explicitly load the module as a CDLL rather than as a module
+# dirname = space.wrap(os.path.dirname(mod))
- dirname = self.import_module(name='bar', init=init, body=body, load_it=False)
- fullmodname = os.path.join(dirname, 'bar' + self.soext)
- self.cmodule = ctypes.CDLL(fullmodname, ctypes.RTLD_GLOBAL)
+# dirname = self.import_module(name='bar', init=init, body=body, load_it=False)
+# fullmodname = os.path.join(dirname, name + self.soext)
+ self.cmodule = self.load_cdll(name, init, body, ['bar_unwrap', 'bar_wrap'])#ctypes.CDLL(fullmodname, ctypes.RTLD_GLOBAL)
def test02_crossing_dict(self):
"""Test availability of all needed classes in the dict"""
diff --git a/pypy/module/cppyy/test/test_pythonify.py b/pypy/module/cppyy/test/test_pythonify.py
--- a/pypy/module/cppyy/test/test_pythonify.py
+++ b/pypy/module/cppyy/test/test_pythonify.py
@@ -6,6 +6,9 @@
test_dct = str(currpath.join("example01Dict.so"))
def setup_module(mod):
+ # force removal of ROOTSYS for this one test, which serves as a test itself
+ if os.getenv("ROOTSYS"):
+ os.unsetenv("ROOTSYS")
if sys.platform == 'win32':
py.test.skip("win32 not supported so far")
err = os.system("cd '%s' && make example01Dict.so" % currpath)
diff --git a/pypy/module/micronumpy/interp_arrayops.py b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -109,19 +109,19 @@
_axis = axis
if axis < 0:
_axis = len(shape) + axis
- if _axis < 0 or len(shape) <= _axis:
- raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
for arr in args_w[1:]:
- dtype = interp_ufuncs.find_binop_result_dtype(space, dtype,
- arr.get_dtype())
- if _axis < 0 or len(arr.get_shape()) <= _axis:
- raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
for i, axis_size in enumerate(arr.get_shape()):
if len(arr.get_shape()) != len(shape) or (i != _axis and axis_size != shape[i]):
raise OperationError(space.w_ValueError, space.wrap(
"all the input arrays must have same number of dimensions"))
elif i == _axis:
shape[i] += axis_size
+ dtype = interp_ufuncs.find_binop_result_dtype(space, dtype,
+ arr.get_dtype())
+ if _axis < 0 or len(arr.get_shape()) <= _axis:
+ raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
+ if _axis < 0 or len(shape) <= _axis:
+ raise operationerrfmt(space.w_IndexError, "axis %d out of bounds [0, %d)", axis, len(shape))
res = W_NDimArray.from_shape(shape, dtype, 'C')
chunks = [Chunk(0, i, 1, i) for i in shape]
axis_start = 0
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -136,6 +136,10 @@
def getitem_array_int(self, space, w_index):
prefix, res_shape, iter_shape, indexes = \
self._prepare_array_index(space, w_index)
+ if iter_shape is None:
+ # w_index is a list of slices, return a view
+ chunks = self.implementation._prepare_slice_args(space, w_index)
+ return chunks.apply(self)
shape = res_shape + self.get_shape()[len(indexes):]
res = W_NDimArray.from_shape(shape, self.get_dtype(), self.get_order())
if not res.get_size():
@@ -147,8 +151,15 @@
val_arr = convert_to_array(space, w_value)
prefix, _, iter_shape, indexes = \
self._prepare_array_index(space, w_index)
- return loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
- prefix)
+ if iter_shape is None:
+ # w_index is a list of slices
+ w_value = convert_to_array(space, w_value)
+ chunks = self.implementation._prepare_slice_args(space, w_index)
+ view = chunks.apply(self)
+ view.implementation.setslice(space, w_value)
+ return
+ loop.setitem_array_int(space, self, iter_shape, indexes, val_arr,
+ prefix)
def descr_getitem(self, space, w_idx):
if (isinstance(w_idx, W_NDimArray) and
@@ -169,9 +180,9 @@
def descr_setitem(self, space, w_idx, w_value):
if (isinstance(w_idx, W_NDimArray) and
- w_idx.get_dtype().is_bool_type()):
- return self.setitem_filter(space, w_idx,
- convert_to_array(space, w_value))
+ w_idx.get_dtype().is_bool_type()):
+ self.setitem_filter(space, w_idx, convert_to_array(space, w_value))
+ return
try:
self.implementation.descr_setitem(space, self, w_idx, w_value)
except ArrayArgumentException:
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1470,12 +1470,11 @@
assert str(exc.value) == \
"all the input arrays must have same number of dimensions"
- if 0: # XXX too pedantic
- g1 = array([0,1,2])
- g2 = array([[3,4,5]])
- exc = raises(ValueError, concatenate, (g1, g2), axis=2)
- assert str(exc.value) == \
- "all the input arrays must have same number of dimensions"
+ g1 = array([0,1,2])
+ g2 = array([[3,4,5]])
+ exc = raises(ValueError, concatenate, (g1, g2), axis=2)
+ assert str(exc.value) == \
+ "all the input arrays must have same number of dimensions"
a = array([1, 2, 3, 4, 5, 6])
a = (a + a)[::2]
@@ -2204,6 +2203,20 @@
a[array([0, 2]), slice(0, 2)] = [[10, 11], [12, 13]]
assert (a == [[10, 11], [3, 4], [12, 13]]).all()
+ def test_slice_vector_index(self):
+ from numpypy import arange
+ b = arange(145)
+ a = b[slice(25, 125, None)]
+ assert (a == range(25, 125)).all()
+ a = b[[slice(25, 125, None)]]
+ assert a.shape == (100,)
+ # a is a view into b
+ a[10] = 200
+ assert b[35] == 200
+ b[[slice(25, 30)]] = range(5)
+ assert all(a[:5] == range(5))
+ raises(TypeError, 'b[[[slice(25, 125)]]]')
+
def test_cumsum(self):
from numpypy import arange
a = arange(6).reshape(3, 2)
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -22,6 +22,7 @@
'lastblock',
'is_being_profiled',
'w_globals',
+ 'w_f_trace',
]
JUMP_ABSOLUTE = opmap['JUMP_ABSOLUTE']
@@ -39,9 +40,6 @@
def set_jitcell_at(newcell, next_instr, is_being_profiled, bytecode):
bytecode.jit_cells[next_instr, is_being_profiled] = newcell
-def confirm_enter_jit(next_instr, is_being_profiled, bytecode, frame, ec):
- return (frame.w_f_trace is None and
- ec.w_tracefunc is None)
def can_never_inline(next_instr, is_being_profiled, bytecode):
return False
@@ -57,7 +55,6 @@
pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location,
get_jitcell_at = get_jitcell_at,
set_jitcell_at = set_jitcell_at,
- confirm_enter_jit = confirm_enter_jit,
can_never_inline = can_never_inline,
should_unroll_one_iteration =
should_unroll_one_iteration,
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -5,14 +5,14 @@
from pypy.interpreter.gateway import unwrap_spec, interp2app
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.error import OperationError
-from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance, hlstr
from rpython.rtyper.lltypesystem.rclass import OBJECT
-from rpython.jit.metainterp.resoperation import rop, AbstractResOp
+from rpython.jit.metainterp.resoperation import rop
from rpython.rlib.nonconst import NonConstant
from rpython.rlib import jit_hooks
from rpython.rlib.jit import Counters
-from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib.objectmodel import compute_unique_id
from pypy.module.pypyjit.interp_jit import pypyjitdriver
class Cache(object):
@@ -270,7 +270,8 @@
self.jd_name = debug_info.get_jitdriver().name
self.type = debug_info.type
if is_bridge:
- self.bridge_no = debug_info.fail_descr_no
+ self.bridge_no = compute_unique_id(debug_info.fail_descr)
+ #self.bridge_no = debug_info.fail_descr_no
self.w_green_key = space.w_None
else:
self.w_green_key = wrap_greenkey(space,
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -106,7 +106,7 @@
'posix', '_socket', '_sre', '_lsprof', '_weakref',
'__pypy__', 'cStringIO', '_collections', 'struct',
'mmap', 'marshal', '_codecs', 'rctime', 'cppyy',
- '_cffi_backend', 'pyexpat']:
+ '_cffi_backend', 'pyexpat', '_continuation']:
if modname == 'pypyjit' and 'interp_resop' in rest:
return False
return True
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py
--- a/pypy/module/pypyjit/test/test_jit_hook.py
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -2,7 +2,8 @@
import py
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.pycode import PyCode
-from rpython.jit.metainterp.history import JitCellToken, ConstInt, ConstPtr
+from rpython.jit.metainterp.history import JitCellToken, ConstInt, ConstPtr,\
+ BasicFailDescr
from rpython.jit.metainterp.resoperation import rop
from rpython.jit.metainterp.logger import Logger
from rpython.rtyper.annlowlevel import (cast_instance_to_base_ptr,
@@ -69,7 +70,7 @@
oplist, 'loop', greenkey)
di_loop.asminfo = AsmInfo(offset, 0, 0)
di_bridge = JitDebugInfo(MockJitDriverSD, logger, JitCellToken(),
- oplist, 'bridge', fail_descr_no=0)
+ oplist, 'bridge', fail_descr=BasicFailDescr())
di_bridge.asminfo = AsmInfo(offset, 0, 0)
def interp_on_compile():
diff --git a/pypy/module/test_lib_pypy/test_marshal_extra.py b/pypy/module/test_lib_pypy/test_marshal_extra.py
--- a/pypy/module/test_lib_pypy/test_marshal_extra.py
+++ b/pypy/module/test_lib_pypy/test_marshal_extra.py
@@ -144,3 +144,8 @@
def test_load_truncated_string():
s = '(\x02\x00\x00\x00i\x03\x00\x00\x00sB\xf9\x00\x00\nabcd'
py.test.raises(EOFError, marshal.loads, s)
+
+def test_dump_unicode_length():
+ s = b'123\xe9'.decode('latin-1')
+ r = marshal.dumps(s)
+ assert r == b'u\x05\x00\x00\x00123\xc3\xa9'
diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
--- a/pypy/module/test_lib_pypy/test_sqlite3.py
+++ b/pypy/module/test_lib_pypy/test_sqlite3.py
@@ -57,11 +57,34 @@
cur = con.cursor()
with pytest.raises(StopIteration):
next(cur)
- cur = con.execute('select 1')
+
+ cur.execute('select 1')
next(cur)
with pytest.raises(StopIteration):
next(cur)
+ cur.execute('select 1')
+ con.commit()
+ next(cur)
+ with pytest.raises(StopIteration):
+ next(cur)
+
+ with pytest.raises(_sqlite3.ProgrammingError):
+ cur.executemany('select 1', [])
+ with pytest.raises(StopIteration):
+ next(cur)
+
+ cur.execute('select 1')
+ cur.execute('create table test(ing)')
+ with pytest.raises(StopIteration):
+ next(cur)
+
+ cur.execute('select 1')
+ cur.execute('insert into test values(1)')
+ con.commit()
+ with pytest.raises(StopIteration):
+ next(cur)
+
def test_cursor_after_close():
con = _sqlite3.connect(':memory:')
cur = con.execute('select 1')
@@ -136,6 +159,7 @@
con.commit()
except _sqlite3.OperationalError:
pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
+ con.close()
def test_statement_arg_checking():
con = _sqlite3.connect(':memory:')
@@ -171,3 +195,4 @@
with pytest.raises(ValueError) as e:
con.execute('insert into foo(x) values (?)', 2)
assert str(e.value) == 'parameters are of unsupported type'
+ con.close()
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -107,15 +107,13 @@
for w_k, w_v in list_pairs_w:
w_self.setitem(w_k, w_v)
- def view_as_kwargs(self):
- return self.strategy.view_as_kwargs(self)
-
def _add_indirections():
dict_methods = "setitem setitem_str getitem \
getitem_str delitem length \
clear w_keys values \
items iterkeys itervalues iteritems setdefault \
- popitem listview_str listview_unicode listview_int".split()
+ popitem listview_str listview_unicode listview_int \
+ view_as_kwargs".split()
def make_method(method):
def f(self, *args):
@@ -123,9 +121,6 @@
f.func_name = method
return f
- def view_as_kwargs(self):
- return self.strategy.view_as_kwargs(self)
-
for method in dict_methods:
setattr(W_DictMultiObject, method, make_method(method))
@@ -573,6 +568,12 @@
def w_keys(self, w_dict):
return self.space.newlist(self.unerase(w_dict.dstorage).keys())
+ def setitem_str(self, w_dict, s, w_value):
+ self.setitem(w_dict, self.space.wrap(s), w_value)
+
+ def switch_to_object_strategy(self, w_dict):
+ assert 0, "should be unreachable"
+
create_iterator_classes(ObjectDictStrategy)
class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -34,7 +34,7 @@
self.descr = descr
self._is_guard = name.startswith('guard_')
if self._is_guard:
- self.guard_no = int(self.descr[len('<Guard'):-1])
+ self.guard_no = int(self.descr[len('<Guard'):-1], 16)
def setfailargs(self, failargs):
self.failargs = failargs
@@ -350,7 +350,7 @@
i = 0
while i < len(ops):
op = ops[i]
- if op.is_guard() and bridges.get('loop-' + str(op.guard_no), None):
+ if op.is_guard() and bridges.get('loop-' + hex(op.guard_no)[2:], None):
res.append(op)
i = 0
if hasattr(op.bridge, 'force_asm'):
@@ -372,7 +372,7 @@
m = re.search('has address ([-\da-f]+)', entry)
addr = int(m.group(1), 16)
entry = entry.lower()
- m = re.search('guard \d+', entry)
+ m = re.search('guard [\da-f]+', entry)
name = m.group(0)
else:
name = entry[:entry.find('(') - 1].lower()
@@ -395,8 +395,8 @@
comm = loop.comment
comm = comm.lower()
if comm.startswith('# bridge'):
- m = re.search('guard \d+', comm)
- name = m.group(0)
+ m = re.search('guard (\d+)', comm)
+ name = 'guard ' + hex(int(m.group(1)))[2:]
elif "(" in comm:
name = comm[2:comm.find('(')-1]
else:
@@ -414,7 +414,7 @@
def split_trace(trace):
labels = [0]
if trace.comment and 'Guard' in trace.comment:
- descrs = ['bridge ' + re.search('Guard (\d+)', trace.comment).group(1)]
+ descrs = ['bridge ' + re.search('Guard ([\da-f]+)', trace.comment).group(1)]
else:
descrs = ['entry ' + re.search('Loop (\d+)', trace.comment).group(1)]
for i, op in enumerate(trace.operations):
@@ -444,3 +444,7 @@
if line:
num, count = line.split(':', 2)
mapping[num].count = int(count)
+
+if __name__ == '__main__':
+ import_log(sys.argv[1])
+
diff --git a/pypy/tool/jitlogparser/storage.py b/pypy/tool/jitlogparser/storage.py
--- a/pypy/tool/jitlogparser/storage.py
+++ b/pypy/tool/jitlogparser/storage.py
@@ -63,14 +63,14 @@
for loop_no, loop in enumerate(loops):
for op in loop.operations:
if op.name.startswith('guard_'):
- guard_dict[int(op.descr[len('<Guard'):-1])] = (op, loop)
+ guard_dict[int(op.descr[len('<Guard'):-1], 16)] = (op, loop)
for loop in loops:
if loop.comment:
comment = loop.comment.strip()
if 'entry bridge' in comment:
pass
elif comment.startswith('# bridge out of'):
- no = int(comment[len('# bridge out of Guard '):].split(' ', 1)[0])
+ no = int(comment[len('# bridge out of Guard '):].split(' ', 1)[0], 16)
op, parent = guard_dict[no]
op.bridge = loop
op.percentage = ((getattr(loop, 'count', 1) * 100) /
diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -162,23 +162,23 @@
loops = LoopStorage().reconnect_loops([main, bridge, entry_bridge])
assert len(loops) == 2
assert len(loops[0].operations[0].bridge.operations) == 1
- assert loops[0].operations[0].bridge.no == 18
+ assert loops[0].operations[0].bridge.no == 0x18
assert loops[0].operations[0].percentage == 30
def test_adjust_bridges():
main = parse('''
[v0]
- guard_false(v0, descr=<Guard13>)
+ guard_false(v0, descr=<Guard1a>)
guard_true(v0, descr=<Guard5>)
''')
bridge = parse('''
- # bridge out of Guard 13
+ # bridge out of Guard 1a
[]
int_add(0, 1)
''')
LoopStorage().reconnect_loops([main, bridge])
assert adjust_bridges(main, {})[1].name == 'guard_true'
- assert adjust_bridges(main, {'loop-13': True})[1].name == 'int_add'
+ assert adjust_bridges(main, {'loop-1a': True})[1].name == 'int_add'
def test_parsing_strliteral():
loop = parse("""
@@ -259,7 +259,7 @@
+348: i32 = int_is_true(i31)
+360: i33 = int_or(i27, i32)
+364: i34 = int_is_true(i33)
-guard_false(i34, descr=<Guard89>) [i1, i22, p2]
+guard_false(i34, descr=<Guard8a>) [i1, i22, p2]
+372: i35 = int_add(i22, 1)
debug_merge_point(0, 're StrMatchIn at 92 [17. 4. 0. 20. 393237. 21. 0. 29. 9. 1. 65535. 15. 4. 9. 3. 0. 1. 21. 1. 29. 9. 1. 65535. 15. 4. 9. 2. 0. 1. 1...')
+376: jump(i35, i1, p2, p4, descr=TargetToken(1081858656))
@@ -323,7 +323,7 @@
[i7]
i9 = int_lt(i7, 1003)
label(i9, descr=grrr)
- guard_true(i9, descr=<Guard2>) []
+ guard_true(i9, descr=<Guardaf>) []
i13 = getfield_raw(151937600, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
label(i13, descr=asb)
i19 = int_lt(i13, 1003)
@@ -336,10 +336,10 @@
i0 = int_lt(1, 2)
finish(i0)
''')
- bridge.comment = 'bridge out of Guard 2 with 1 ops'
+ bridge.comment = 'bridge out of Guard af with 1 ops'
loop.comment = 'Loop 0'
loops = split_trace(loop) + split_trace(bridge)
- input = ['grrr:123\nasb:12\nbridge 2:1234']
+ input = ['grrr:123\nasb:12\nbridge af:1234']
parse_log_counts(input, loops)
assert loops[-1].count == 1234
assert loops[1].count == 123
diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -143,13 +143,9 @@
# XXX HACK HACK HACK
bk = getbookkeeper()
if bk is not None: # for testing
+ op = bk._find_current_op("is_", 2)
knowntypedata = {}
- fn, block, i = bk.position_key
-
annotator = bk.annotator
- op = block.operations[i]
- assert op.opname == "is_"
- assert len(op.args) == 2
def bind(src_obj, tgt_obj, tgt_arg):
if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant():
@@ -319,11 +315,7 @@
rarithmetic.signedtype(int2.knowntype)):
return r
knowntypedata = {}
- # XXX HACK HACK HACK
- fn, block, i = getbookkeeper().position_key
- op = block.operations[i]
- assert op.opname == opname
- assert len(op.args) == 2
+ op = getbookkeeper()._find_current_op(opname=opname, arity=2)
def tointtype(int0):
if int0.knowntype is bool:
return int
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -693,6 +693,20 @@
if emulate_enter:
self.leave()
+ def _find_current_op(self, opname=None, arity=None, pos=None, s_type=None):
+ """ Find operation that is currently being annotated. Do some
+ sanity checks to see whether the correct op was found."""
+ # XXX XXX HACK HACK HACK
+ fn, block, i = self.position_key
+ op = block.operations[i]
+ if opname is not None:
+ assert op.opname == opname or op.opname in opname
+ if arity is not None:
+ assert len(op.args) == arity
+ if pos is not None:
+ assert self.annotator.binding(op.args[pos]) == s_type
+ return op
+
def build_args(self, op, args_s):
space = RPythonCallsSpace()
if op == "simple_call":
diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py
--- a/rpython/annotator/builtin.py
+++ b/rpython/annotator/builtin.py
@@ -178,15 +178,9 @@
# from bool to int, notice that isinstance( , bool|int)
# is quite border case for RPython
r.const = False
- # XXX HACK HACK HACK
- # XXX HACK HACK HACK
- # XXX HACK HACK HACK
bk = getbookkeeper()
if variables is None:
- fn, block, i = bk.position_key
- op = block.operations[i]
- assert op.opname == "simple_call"
- assert len(op.args) == 3
+ op = bk._find_current_op("simple_call", 3)
assert op.args[0] == Constant(isinstance)
variables = [op.args[1]]
for variable in variables:
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -306,8 +306,10 @@
result = schedule(graph, inputcells)
signature = getattr(self.pyobj, '_signature_', None)
if signature:
- result = enforce_signature_return(self, signature[1], result)
- self.bookkeeper.annotator.addpendingblock(graph, graph.returnblock, [result])
+ sigresult = enforce_signature_return(self, signature[1], result)
+ if sigresult is not None:
+ self.bookkeeper.annotator.addpendingblock(graph, graph.returnblock, [sigresult])
+ result = sigresult
# Some specializations may break the invariant of returning
# annotations that are always more general than the previous time.
# We restore it here:
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -233,6 +233,9 @@
def nonnoneify(self):
return self.__class__(can_be_None=False, no_nul=self.no_nul)
+ def nonnulify(self):
+ return self.__class__(can_be_None=self.can_be_None, no_nul=True)
+
class SomeString(SomeStringOrUnicode):
"Stands for an object which is known to be a string."
knowntype = str
diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py
--- a/rpython/annotator/signature.py
+++ b/rpython/annotator/signature.py
@@ -132,11 +132,13 @@
inputcells[:] = args_s
def finish_type(paramtype, bookkeeper, func):
- from rpython.rlib.types import SelfTypeMarker
+ from rpython.rlib.types import SelfTypeMarker, AnyTypeMarker
if isinstance(paramtype, SomeObject):
return paramtype
elif isinstance(paramtype, SelfTypeMarker):
raise Exception("%r argument declared as annotation.types.self(); class needs decorator rlib.signature.finishsigs()" % (func,))
+ elif isinstance(paramtype, AnyTypeMarker):
+ return None
else:
return paramtype(bookkeeper)
@@ -144,15 +146,20 @@
assert len(paramtypes) == len(actualtypes)
params_s = [finish_type(paramtype, funcdesc.bookkeeper, funcdesc.pyobj) for paramtype in paramtypes]
for i, (s_param, s_actual) in enumerate(zip(params_s, actualtypes)):
+ if s_param is None: # can be anything
+ continue
if not s_param.contains(s_actual):
raise Exception("%r argument %d:\n"
"expected %s,\n"
" got %s" % (funcdesc, i+1, s_param, s_actual))
- actualtypes[:] = params_s
+ for i, s_param in enumerate(params_s):
+ if s_param is None:
+ continue
+ actualtypes[i] = s_param
def enforce_signature_return(funcdesc, sigtype, inferredtype):
s_sigret = finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
- if not s_sigret.contains(inferredtype):
+ if s_sigret is not None and not s_sigret.contains(inferredtype):
raise Exception("%r return value:\n"
"expected %s,\n"
" got %s" % (funcdesc, s_sigret, inferredtype))
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -446,6 +446,25 @@
s_item = s.listdef.listitem.s_value
assert s_item.no_nul
+ def test_str_split_nul(self):
+ def f(n):
+ return n.split('\0')[0]
+ a = self.RPythonAnnotator()
+ a.translator.config.translation.check_str_without_nul = True
+ s = a.build_types(f, [annmodel.SomeString(no_nul=False, can_be_None=False)])
+ assert isinstance(s, annmodel.SomeString)
+ assert not s.can_be_None
+ assert s.no_nul
+
+ def g(n):
+ return n.split('\0', 1)[0]
+ a = self.RPythonAnnotator()
+ a.translator.config.translation.check_str_without_nul = True
+ s = a.build_types(g, [annmodel.SomeString(no_nul=False, can_be_None=False)])
+ assert isinstance(s, annmodel.SomeString)
+ assert not s.can_be_None
+ assert not s.no_nul
+
def test_str_splitlines(self):
a = self.RPythonAnnotator()
def f(a_str):
@@ -3762,6 +3781,19 @@
assert isinstance(s, annmodel.SomeString)
assert not s.can_be_None
+ def test_contains_no_nul(self):
+ def f(i):
+ if "\0" in i:
+ return None
+ else:
+ return i
+ a = self.RPythonAnnotator()
+ a.translator.config.translation.check_str_without_nul = True
+ s = a.build_types(f, [annmodel.SomeString(no_nul=False)])
+ assert isinstance(s, annmodel.SomeString)
+ assert s.can_be_None
+ assert s.no_nul
+
def test_no___call__(self):
class X(object):
def __call__(self):
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -43,12 +43,7 @@
raise Exception, 'type() called with more than one argument'
r = SomeType()
bk = getbookkeeper()
- fn, block, i = bk.position_key
- annotator = bk.annotator
- op = block.operations[i]
- assert op.opname == "type"
- assert len(op.args) == 1
- assert annotator.binding(op.args[0]) == obj
+ op = bk._find_current_op(opname="type", arity=1, pos=0, s_type=obj)
r.is_type_of = [op.args[0]]
return r
@@ -79,10 +74,7 @@
bk = getbookkeeper()
knowntypedata = {}
- fn, block, i = bk.position_key
- op = block.operations[i]
- assert op.opname == "is_true" or op.opname == "nonzero"
- assert len(op.args) == 1
+ op = bk._find_current_op(opname=("is_true", "nonzero"), arity=1)
arg = op.args[0]
s_nonnone_obj = s_obj
if s_obj.can_be_none():
@@ -504,7 +496,11 @@
def method_split(str, patt, max=-1):
getbookkeeper().count("str_split", str, patt)
- s_item = str.basestringclass(no_nul=str.no_nul)
+ if max == -1 and patt.is_constant() and patt.const == "\0":
+ no_nul = True
+ else:
+ no_nul = str.no_nul
+ s_item = str.basestringclass(no_nul=no_nul)
return getbookkeeper().newlist(s_item)
def method_rsplit(str, patt, max=-1):
@@ -520,6 +516,20 @@
result = str.basestringclass(no_nul=str.no_nul)
return result
+ def op_contains(str, s_element):
+ if s_element.is_constant() and s_element.const == "\0":
+ r = SomeBool()
+ bk = getbookkeeper()
+ op = bk._find_current_op(opname="contains", arity=2, pos=0, s_type=str)
+ knowntypedata = {}
+ add_knowntypedata(knowntypedata, False, [op.args[0]], str.nonnulify())
+ r.set_knowntypedata(knowntypedata)
+ return r
+ else:
+ return SomeObject.op_contains(str, s_element)
+ op_contains.can_only_throw = []
+
+
class __extend__(SomeUnicodeString):
def method_encode(uni, s_enc):
if not s_enc.is_constant():
diff --git a/rpython/jit/backend/arm/arch.py b/rpython/jit/backend/arm/arch.py
--- a/rpython/jit/backend/arm/arch.py
+++ b/rpython/jit/backend/arm/arch.py
@@ -1,7 +1,3 @@
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rlib.rarithmetic import r_uint
-
-
FUNC_ALIGN = 8
WORD = 4
DOUBLE_WORD = 8
@@ -14,54 +10,12 @@
PC_OFFSET = 8
FORCE_INDEX_OFS = 0
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-eci = ExternalCompilationInfo(post_include_bits=["""
-static int pypy__arm_int_div(int a, int b) {
- return a/b;
-}
-static unsigned int pypy__arm_uint_div(unsigned int a, unsigned int b) {
- return a/b;
-}
-static int pypy__arm_int_mod(int a, int b) {
- return a % b;
-}
-"""])
-
-
-def arm_int_div_emulator(a, b):
- return int(a / float(b))
-arm_int_div_sign = lltype.Ptr(
- lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
-arm_int_div = rffi.llexternal(
- "pypy__arm_int_div", [lltype.Signed, lltype.Signed], lltype.Signed,
- _callable=arm_int_div_emulator,
- compilation_info=eci,
- _nowrapper=True, elidable_function=True)
-
-
-def arm_uint_div_emulator(a, b):
- return r_uint(a) / r_uint(b)
-arm_uint_div_sign = lltype.Ptr(
- lltype.FuncType([lltype.Unsigned, lltype.Unsigned], lltype.Unsigned))
-arm_uint_div = rffi.llexternal(
- "pypy__arm_uint_div", [lltype.Unsigned, lltype.Unsigned], lltype.Unsigned,
- _callable=arm_uint_div_emulator,
- compilation_info=eci,
- _nowrapper=True, elidable_function=True)
-
-
-def arm_int_mod_emulator(a, b):
- sign = 1
- if a < 0:
- a = -1 * a
- sign = -1
- if b < 0:
- b = -1 * b
- res = a % b
- return sign * res
-arm_int_mod_sign = arm_int_div_sign
-arm_int_mod = rffi.llexternal(
- "pypy__arm_int_mod", [lltype.Signed, lltype.Signed], lltype.Signed,
- _callable=arm_int_mod_emulator,
- compilation_info=eci,
- _nowrapper=True, elidable_function=True)
+# The stack contains the force_index and the, callee saved registers and
+# ABI required information
+# All the rest of the data is in a GC-managed variable-size "frame".
+# This jitframe object's address is always stored in the register FP
+# A jitframe is a jit.backend.llsupport.llmodel.jitframe.JITFRAME
+# Stack frame fixed area
+# Currently only the force_index
+JITFRAME_FIXED_SIZE = 11 + 16 * 2 + 1
+# 11 GPR + 16 VFP Regs (64bit) + 1 word for alignment
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
@@ -1,91 +1,64 @@
from __future__ import with_statement
+
import os
+
+from rpython.jit.backend.arm import conditions as c, registers as r
+from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD, FUNC_ALIGN,
+ JITFRAME_FIXED_SIZE)
+from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
+from rpython.jit.backend.arm.locations import imm, StackLocation
+from rpython.jit.backend.arm.opassembler import ResOpAssembler
+from rpython.jit.backend.arm.regalloc import (Regalloc,
+ CoreRegisterManager, check_imm_arg, VFPRegisterManager,
+ operations as regalloc_operations,
+ operations_with_guard as regalloc_operations_with_guard)
from rpython.jit.backend.llsupport import jitframe
-from rpython.jit.backend.arm.helper.assembler import saved_registers
-from rpython.jit.backend.arm import conditions as c
-from rpython.jit.backend.arm import registers as r
-from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, FUNC_ALIGN, \
- N_REGISTERS_SAVED_BY_MALLOC
-from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
-from rpython.jit.backend.arm.locations import get_fp_offset
-from rpython.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
- CoreRegisterManager, check_imm_arg,
- operations as regalloc_operations,
- operations_with_guard as regalloc_operations_with_guard)
+from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER
from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
from rpython.jit.backend.model import CompiledLoopToken
-from rpython.jit.codewriter import longlong
from rpython.jit.codewriter.effectinfo import EffectInfo
-from rpython.jit.metainterp.history import AbstractFailDescr, INT, REF, FLOAT
-from rpython.jit.metainterp.history import BoxInt, ConstInt
-from rpython.jit.metainterp.resoperation import rop, ResOperation
-from rpython.rlib import rgc
-from rpython.rlib.objectmodel import we_are_translated, specialize
-from rpython.rtyper.annlowlevel import llhelper
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.jit.backend.arm.opassembler import ResOpAssembler
-from rpython.rlib.debug import (debug_print, debug_start, debug_stop,
- have_debug_prints, fatalerror)
+from rpython.jit.metainterp.history import AbstractFailDescr, FLOAT
+from rpython.jit.metainterp.resoperation import rop
+from rpython.rlib.debug import debug_print, debug_start, debug_stop
from rpython.rlib.jit import AsmInfo
-from rpython.rlib.objectmodel import compute_unique_id
-
-# XXX Move to llsupport
-from rpython.jit.backend.x86.support import memcpy_fn
-
-DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
- ('type', lltype.Char), # 'b'ridge, 'l'abel or
- # 'e'ntry point
- ('number', lltype.Signed))
+from rpython.rlib.objectmodel import we_are_translated, specialize, compute_unique_id
+from rpython.rlib.rarithmetic import r_uint
+from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref
+from rpython.rtyper.lltypesystem import lltype, rffi
class AssemblerARM(ResOpAssembler):
- STACK_FIXED_AREA = -1
-
- debug = True
+ debug = False
def __init__(self, cpu, translate_support_code=False):
- self.cpu = cpu
+ ResOpAssembler.__init__(self, cpu, translate_support_code)
self.setup_failure_recovery()
self.mc = None
- self.memcpy_addr = 0
self.pending_guards = None
self._exit_code_addr = 0
self.current_clt = None
self.malloc_slowpath = 0
- self.wb_slowpath = [0, 0, 0, 0]
+ self.wb_slowpath = [0, 0, 0, 0, 0]
self._regalloc = None
self.datablockwrapper = None
self.propagate_exception_path = 0
self.stack_check_slowpath = 0
- self._compute_stack_size()
self._debug = False
self.loop_run_counters = []
self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
- self.force_token_to_dead_frame = {} # XXX temporary hack
+ self.gcrootmap_retaddr_forced = 0
def set_debug(self, v):
r = self._debug
self._debug = v
return r
- def _compute_stack_size(self):
- self.STACK_FIXED_AREA = len(r.callee_saved_registers) * WORD
- self.STACK_FIXED_AREA += WORD # FORCE_TOKEN
- self.STACK_FIXED_AREA += N_REGISTERS_SAVED_BY_MALLOC * WORD
- if self.cpu.supports_floats:
- self.STACK_FIXED_AREA += (len(r.callee_saved_vfp_registers)
- * DOUBLE_WORD)
- if self.STACK_FIXED_AREA % 8 != 0:
- self.STACK_FIXED_AREA += WORD # Stack alignment
- assert self.STACK_FIXED_AREA % 8 == 0
-
- def setup(self, looptoken, operations):
+ def setup(self, looptoken):
+ assert self.memcpy_addr != 0, 'setup_once() not called?'
+ if we_are_translated():
+ self.debug = False
self.current_clt = looptoken.compiled_loop_token
- operations = self.cpu.gc_ll_descr.rewrite_assembler(self.cpu,
- operations, self.current_clt.allgcrefs)
- assert self.memcpy_addr != 0, 'setup_once() not called?'
self.mc = ARMv7Builder()
self.pending_guards = []
assert self.datablockwrapper is None
@@ -93,7 +66,6 @@
self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
allblocks)
self.target_tokens_currently_compiling = {}
- return operations
def teardown(self):
self.current_clt = None
@@ -102,34 +74,8 @@
self.pending_guards = None
assert self.datablockwrapper is None
- def setup_once(self):
- # Addresses of functions called by new_xxx operations
- gc_ll_descr = self.cpu.gc_ll_descr
- gc_ll_descr.initialize()
- self._build_wb_slowpath(False)
- self._build_wb_slowpath(True)
- self._build_failure_recovery(exc=True, withfloats=False)
- self._build_failure_recovery(exc=False, withfloats=False)
- if self.cpu.supports_floats:
- self._build_wb_slowpath(False, withfloats=True)
- self._build_wb_slowpath(True, withfloats=True)
- self._build_failure_recovery(exc=True, withfloats=True)
- self._build_failure_recovery(exc=False, withfloats=True)
- self._build_propagate_exception_path()
- if gc_ll_descr.get_malloc_slowpath_addr is not None:
- self._build_malloc_slowpath()
- self._build_stack_check_slowpath()
- if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
- self._build_release_gil(gc_ll_descr.gcrootmap)
- self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
-
- if not self._debug:
- # if self._debug is already set it means that someone called
- # set_debug by hand before initializing the assembler. Leave it
- # as it is
- debug_start('jit-backend-counts')
- self.set_debug(have_debug_prints())
- debug_stop('jit-backend-counts')
+ def setup_failure_recovery(self):
+ self.failure_recovery_code = [0, 0, 0, 0]
def finish_once(self):
if self._debug:
@@ -162,18 +108,6 @@
self.loop_run_counters.append(struct)
return struct
- def _append_debugging_code(self, operations, tp, number, token):
- counter = self._register_counter(tp, number, token)
- c_adr = ConstInt(rffi.cast(lltype.Signed, counter))
- box = BoxInt()
- box2 = BoxInt()
- ops = [ResOperation(rop.GETFIELD_RAW, [c_adr],
- box, descr=self.debug_counter_descr),
- ResOperation(rop.INT_ADD, [box, ConstInt(1)], box2),
- ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
- None, descr=self.debug_counter_descr)]
- operations.extend(ops)
-
@specialize.argtype(1)
def _inject_debugging_code(self, looptoken, operations, tp, number):
if self._debug:
@@ -218,22 +152,84 @@
self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func)
def _build_propagate_exception_path(self):
- if self.cpu.propagate_exception_v < 0:
+ if not self.cpu.propagate_exception_descr:
return # not supported (for tests, or non-translated)
#
mc = ARMv7Builder()
- #
- # Call the helper, which will return a dead frame object with
- # the correct exception set, or MemoryError by default
- # XXX make sure we return the correct value here
- addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
- mc.BL(addr)
- self.gen_func_epilog(mc=mc)
- self.propagate_exception_path = mc.materialize(self.cpu.asmmemmgr, [])
+ self._store_and_reset_exception(mc, r.r0)
+ ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+ # make sure ofs fits into a register
+ assert check_imm_arg(ofs)
+ mc.LDR_ri(r.r0.value, r.fp.value, imm=ofs)
+ propagate_exception_descr = rffi.cast(lltype.Signed,
+ cast_instance_to_gcref(self.cpu.propagate_exception_descr))
+ # put propagate_exception_descr into frame
+ ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+ # make sure ofs fits into a register
+ assert check_imm_arg(ofs)
+ mc.gen_load_int(r.r0.value, propagate_exception_descr)
+ mc.STR_ri(r.r0.value, r.fp.value, imm=ofs)
+ mc.MOV_rr(r.r0.value, r.fp.value)
+ self.gen_func_epilog(mc)
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+ self.propagate_exception_path = rawstart
+
+ def _store_and_reset_exception(self, mc, excvalloc=None, exctploc=None,
+ on_frame=False):
+ """ Resest the exception. If excvalloc is None, then store it on the
+ frame in jf_guard_exc
+ """
+ assert excvalloc is not r.ip
+ assert exctploc is not r.ip
+ tmpreg = r.lr
+ mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value())
+ if excvalloc is not None: # store
+ assert excvalloc.is_reg()
+ self.load_reg(mc, excvalloc, r.ip)
+ if on_frame:
+ # store exc_value in JITFRAME
+ ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+ assert check_imm_arg(ofs)
+ self.store_reg(mc, r.ip, r.fp, ofs)
+ if exctploc is not None:
+ # store pos_exception in exctploc
+ assert exctploc.is_reg()
+ mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
+ self.load_reg(mc, exctploc, r.ip)
+
+ # reset exception
+ mc.gen_load_int(tmpreg.value, 0)
+
+ self.store_reg(mc, tmpreg, r.ip, 0)
+
+ mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
+ self.store_reg(mc, tmpreg, r.ip, 0)
+
+ def _restore_exception(self, mc, excvalloc, exctploc):
+ assert excvalloc is not r.ip
+ assert exctploc is not r.ip
+ tmpreg = r.lr # use lr as a second temporary reg
+ mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value())
+ if excvalloc is not None:
+ assert excvalloc.is_reg()
+ self.store_reg(mc, excvalloc, r.ip)
+ else:
+ assert exctploc is not r.fp
+ # load exc_value from JITFRAME and put it in pos_exc_value
+ ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
+ self.load_reg(mc, tmpreg, r.fp, ofs)
+ self.store_reg(mc, tmpreg, r.ip)
+ # reset exc_value in the JITFRAME
+ mc.gen_load_int(tmpreg.value, 0)
+ self.store_reg(mc, tmpreg, r.fp, ofs)
+
+ # restore pos_exception from exctploc register
+ mc.gen_load_int(r.ip.value, self.cpu.pos_exception())
+ self.store_reg(mc, exctploc, r.ip)
def _build_stack_check_slowpath(self):
_, _, slowpathaddr = self.cpu.insert_stack_check()
- if slowpathaddr == 0 or self.cpu.propagate_exception_v < 0:
+ if slowpathaddr == 0 or not self.cpu.propagate_exception_descr:
return # no stack check (for tests, or non-translated)
#
# make a "function" that is called immediately at the start of
@@ -257,7 +253,7 @@
mc.gen_load_int(r.r0.value, self.cpu.pos_exception())
mc.LDR_ri(r.r0.value, r.r0.value)
mc.TST_rr(r.r0.value, r.r0.value)
- # restore registers and return
+ # restore registers and return
# We check for c.EQ here, meaning all bits zero in this case
mc.POP([reg.value for reg in r.argument_regs] + [r.pc.value], cond=c.EQ)
#
@@ -276,7 +272,7 @@
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
self.stack_check_slowpath = rawstart
- def _build_wb_slowpath(self, withcards, withfloats=False):
+ def _build_wb_slowpath(self, withcards, withfloats=False, for_frame=False):
descr = self.cpu.gc_ll_descr.write_barrier_descr
if descr is None:
return
@@ -295,12 +291,28 @@
# It must keep stack alignment accordingly.
mc = ARMv7Builder()
#
- if withfloats:
- floats = r.caller_vfp_resp
+ exc0 = exc1 = None
+ mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment
+ if not for_frame:
+ self._push_all_regs_to_jitframe(mc, [], withfloats, callee_only=True)
else:
- floats = []
- with saved_registers(mc, r.caller_resp + [r.ip, r.lr], floats):
- mc.BL(func)
+ # we're possibly called from the slowpath of malloc
+ # save the caller saved registers
+ # assuming we do not collect here
+ exc0, exc1 = r.r4, r.r5
+ mc.PUSH([gpr.value for gpr in r.caller_resp] + [exc0.value, exc1.value])
+ mc.VPUSH([vfpr.value for vfpr in r.caller_vfp_resp])
+
+ self._store_and_reset_exception(mc, exc0, exc1)
+ mc.BL(func)
+ #
+ if not for_frame:
+ self._pop_all_regs_from_jitframe(mc, [], withfloats, callee_only=True)
+ else:
+ self._restore_exception(mc, exc0, exc1)
+ mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp])
+ mc.POP([gpr.value for gpr in r.caller_resp] +
+ [exc0.value, exc1.value])
#
if withcards:
# A final TEST8 before the RET, for the caller. Careful to
@@ -310,350 +322,174 @@
imm=descr.jit_wb_if_flag_byteofs)
mc.TST_ri(r.ip.value, imm=0x80)
#
- mc.MOV_rr(r.pc.value, r.lr.value)
+ mc.POP([r.ip.value, r.pc.value])
#
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
- self.wb_slowpath[withcards + 2 * withfloats] = rawstart
-
- def setup_failure_recovery(self):
-
- #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
- def failure_recovery_func(mem_loc, frame_pointer, stack_pointer):
- """mem_loc is a structure in memory describing where the values for
- the failargs are stored. frame loc is the address of the frame
- pointer for the frame to be decoded frame """
- vfp_registers = rffi.cast(rffi.LONGP, stack_pointer)
- registers = rffi.ptradd(vfp_registers, 2*len(r.all_vfp_regs))
- registers = rffi.cast(rffi.LONGP, registers)
More information about the pypy-commit
mailing list