[pypy-commit] pypy virtual-raw-mallocs: hg merge default. IN-PROGRESS: a couple of things broke because of remove-globals-in-jit, need to fix them
antocuni
noreply at buildbot.pypy.org
Thu Jan 10 11:29:38 CET 2013
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: virtual-raw-mallocs
Changeset: r59913:80b6a6da5ea0
Date: 2013-01-10 11:00 +0100
http://bitbucket.org/pypy/pypy/changeset/80b6a6da5ea0/
Log: hg merge default. IN-PROGRESS: a couple of things broke because of
remove-globals-in-jit, need to fix them
diff too long, truncating to 2000 out of 13934 lines
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -28,7 +28,7 @@
DEALINGS IN THE SOFTWARE.
-PyPy Copyright holders 2003-2012
+PyPy Copyright holders 2003-2013
-----------------------------------
Except when otherwise stated (look for LICENSE files or information at
diff --git a/lib-python/2.7/ctypes/test/test_internals.py b/lib-python/2.7/ctypes/test/test_internals.py
--- a/lib-python/2.7/ctypes/test/test_internals.py
+++ b/lib-python/2.7/ctypes/test/test_internals.py
@@ -1,7 +1,10 @@
# This tests the internal _objects attribute
import unittest
from ctypes import *
-from sys import getrefcount as grc
+try:
+ from sys import getrefcount as grc
+except ImportError:
+ grc = None # e.g. PyPy
# XXX This test must be reviewed for correctness!!!
@@ -22,6 +25,8 @@
self.assertEqual(id(a), id(b))
def test_ints(self):
+ if grc is None:
+ return unittest.skip("no sys.getrefcount()")
i = 42000123
refcnt = grc(i)
ci = c_int(i)
@@ -29,6 +34,8 @@
self.assertEqual(ci._objects, None)
def test_c_char_p(self):
+ if grc is None:
+ return unittest.skip("no sys.getrefcount()")
s = "Hello, World"
refcnt = grc(s)
cs = c_char_p(s)
diff --git a/lib-python/2.7/ctypes/test/test_memfunctions.py b/lib-python/2.7/ctypes/test/test_memfunctions.py
--- a/lib-python/2.7/ctypes/test/test_memfunctions.py
+++ b/lib-python/2.7/ctypes/test/test_memfunctions.py
@@ -53,7 +53,8 @@
s = string_at("foo bar")
# XXX The following may be wrong, depending on how Python
# manages string instances
- self.assertEqual(2, sys.getrefcount(s))
+ if hasattr(sys, 'getrefcount'):
+ self.assertEqual(2, sys.getrefcount(s))
self.assertTrue(s, "foo bar")
self.assertEqual(string_at("foo bar", 8), "foo bar\0")
diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py
--- a/lib-python/2.7/ctypes/test/test_python_api.py
+++ b/lib-python/2.7/ctypes/test/test_python_api.py
@@ -9,7 +9,10 @@
################################################################
-from sys import getrefcount as grc
+try:
+ from sys import getrefcount as grc
+except ImportError:
+ grc = None # e.g. PyPy
if sys.version_info > (2, 4):
c_py_ssize_t = c_size_t
else:
diff --git a/lib-python/2.7/ctypes/test/test_refcounts.py b/lib-python/2.7/ctypes/test/test_refcounts.py
--- a/lib-python/2.7/ctypes/test/test_refcounts.py
+++ b/lib-python/2.7/ctypes/test/test_refcounts.py
@@ -11,7 +11,10 @@
class RefcountTestCase(unittest.TestCase):
def test_1(self):
- from sys import getrefcount as grc
+ try:
+ from sys import getrefcount as grc
+ except ImportError:
+ return unittest.skip("no sys.getrefcount()")
f = dll._testfunc_callback_i_if
f.restype = ctypes.c_int
@@ -35,7 +38,10 @@
def test_refcount(self):
- from sys import getrefcount as grc
+ try:
+ from sys import getrefcount as grc
+ except ImportError:
+ return unittest.skip("no sys.getrefcount()")
def func(*args):
pass
# this is the standard refcount for func
@@ -84,6 +90,10 @@
class AnotherLeak(unittest.TestCase):
def test_callback(self):
import sys
+ try:
+ from sys import getrefcount
+ except ImportError:
+ return unittest.skip("no sys.getrefcount()")
proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
def func(a, b):
diff --git a/lib-python/2.7/sre_parse.py b/lib-python/2.7/sre_parse.py
--- a/lib-python/2.7/sre_parse.py
+++ b/lib-python/2.7/sre_parse.py
@@ -16,6 +16,12 @@
from sre_constants import *
+try:
+ from __pypy__ import newdict
+except ImportError:
+ def newdict(tp):
+ return {}
+
SPECIAL_CHARS = ".\\[{()*+?^$|"
REPEAT_CHARS = "*+?{"
@@ -68,7 +74,7 @@
self.flags = 0
self.open = []
self.groups = 1
- self.groupdict = {}
+ self.groupdict = newdict("module")
def opengroup(self, name=None):
gid = self.groups
self.groups = gid + 1
diff --git a/lib_pypy/_ctypes_test.py b/lib_pypy/_ctypes_test.py
--- a/lib_pypy/_ctypes_test.py
+++ b/lib_pypy/_ctypes_test.py
@@ -2,10 +2,6 @@
import tempfile
import gc
-# Monkeypatch & hacks to let ctypes.tests import.
-# This should be removed at some point.
-sys.getrefcount = lambda x: len(gc.get_referrers(x)) - 1
-
def compile_shared():
"""Compile '_ctypes_test.c' into an extension module, and import it
"""
diff --git a/lib_pypy/numpypy/core/arrayprint.py b/lib_pypy/numpypy/core/arrayprint.py
--- a/lib_pypy/numpypy/core/arrayprint.py
+++ b/lib_pypy/numpypy/core/arrayprint.py
@@ -248,9 +248,9 @@
'int' : IntegerFormat(data),
'float' : FloatFormat(data, precision, suppress_small),
'longfloat' : LongFloatFormat(precision),
- #'complexfloat' : ComplexFormat(data, precision,
- # suppress_small),
- #'longcomplexfloat' : LongComplexFormat(precision),
+ 'complexfloat' : ComplexFormat(data, precision,
+ suppress_small),
+ 'longcomplexfloat' : LongComplexFormat(precision),
'datetime' : DatetimeFormat(data),
'timedelta' : TimedeltaFormat(data),
'numpystr' : repr_format,
@@ -294,19 +294,19 @@
#else:
format_function = formatdict['int']
elif issubclass(dtypeobj, _nt.floating):
- #if issubclass(dtypeobj, _nt.longfloat):
- # format_function = formatdict['longfloat']
- #else:
- format_function = formatdict['float']
- #elif issubclass(dtypeobj, _nt.complexfloating):
- # if issubclass(dtypeobj, _nt.clongfloat):
- # format_function = formatdict['longcomplexfloat']
- # else:
- # format_function = formatdict['complexfloat']
+ if issubclass(dtypeobj, _nt.longfloat):
+ format_function = formatdict['longfloat']
+ else:
+ format_function = formatdict['float']
+ elif issubclass(dtypeobj, _nt.complexfloating):
+ if issubclass(dtypeobj, _nt.clongfloat):
+ format_function = formatdict['longcomplexfloat']
+ else:
+ format_function = formatdict['complexfloat']
elif issubclass(dtypeobj, (_nt.unicode_, _nt.string_)):
format_function = formatdict['numpystr']
- elif issubclass(dtypeobj, _nt.datetime64):
- format_function = formatdict['datetime']
+ #elif issubclass(dtypeobj, _nt.datetime64):
+ # format_function = formatdict['datetime']
else:
format_function = formatdict['str']
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -10,7 +10,7 @@
from pypy.annotation.model import SomeUnicodeCodePoint, SomeUnicodeString
from pypy.annotation.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator
-from pypy.annotation.model import SomePBC, SomeFloat, s_None
+from pypy.annotation.model import SomePBC, SomeFloat, s_None, SomeByteArray
from pypy.annotation.model import SomeExternalObject, SomeWeakRef
from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess
from pypy.annotation.model import SomeSingleFloat, SomeLongFloat, SomeType
@@ -415,6 +415,34 @@
result.const = str1.const + str2.const
return result
+class __extend__(pairtype(SomeByteArray, SomeByteArray)):
+ def union((b1, b2)):
+ can_be_None = b1.can_be_None or b2.can_be_None
+ return SomeByteArray(can_be_None=can_be_None)
+
+ def add((b1, b2)):
+ result = SomeByteArray()
+ if b1.is_immutable_constant() and b2.is_immutable_constant():
+ result.const = b1.const + b2.const
+ return result
+
+class __extend__(pairtype(SomeByteArray, SomeInteger)):
+ def getitem((s_b, s_i)):
+ return SomeInteger()
+
+ def setitem((s_b, s_i), s_i2):
+ assert isinstance(s_i2, SomeInteger)
+
+class __extend__(pairtype(SomeString, SomeByteArray),
+ pairtype(SomeByteArray, SomeString),
+ pairtype(SomeChar, SomeByteArray),
+ pairtype(SomeByteArray, SomeChar)):
+ def add((b1, b2)):
+ result = SomeByteArray()
+ if b1.is_immutable_constant() and b2.is_immutable_constant():
+ result.const = b1.const + b2.const
+ return result
+
class __extend__(pairtype(SomeChar, SomeChar)):
def union((chr1, chr2)):
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -13,7 +13,7 @@
SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \
SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
SomeUnicodeString, SomeList, SomeObject, HarmlesslyBlocked, \
- SomeWeakRef, lltype_to_annotation, SomeType
+ SomeWeakRef, lltype_to_annotation, SomeType, SomeByteArray
from pypy.annotation.classdef import InstanceSource, ClassDef
from pypy.annotation.listdef import ListDef, ListItem
from pypy.annotation.dictdef import DictDef
@@ -349,6 +349,8 @@
result = SomeUnicodeCodePoint()
else:
result = SomeUnicodeString()
+ elif tp is bytearray:
+ result = SomeByteArray()
elif tp is tuple:
result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x])
elif tp is float:
diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -9,7 +9,7 @@
from pypy.annotation.model import SomeFloat, unionof, SomeUnicodeString
from pypy.annotation.model import SomePBC, SomeInstance, SomeDict, SomeList
from pypy.annotation.model import SomeWeakRef, SomeIterator
-from pypy.annotation.model import SomeOOObject
+from pypy.annotation.model import SomeOOObject, SomeByteArray
from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation
from pypy.annotation.model import add_knowntypedata
from pypy.annotation.model import s_ImpossibleValue
@@ -119,6 +119,9 @@
def builtin_unicode(s_unicode):
return constpropagate(unicode, [s_unicode], SomeUnicodeString())
+def builtin_bytearray(s_str):
+ return constpropagate(bytearray, [s_str], SomeByteArray())
+
def our_issubclass(cls1, cls2):
""" we're going to try to be less silly in the face of old-style classes"""
from pypy.annotation.classdef import ClassDef
@@ -253,24 +256,6 @@
s = SomeInteger(nonneg=True, knowntype=s.knowntype)
return s
-def builtin_apply(*stuff):
- getbookkeeper().warning("ignoring apply%r" % (stuff,))
- return SomeObject()
-
-##def builtin_slice(*args):
-## bk = getbookkeeper()
-## if len(args) == 1:
-## return SomeSlice(
-## bk.immutablevalue(None), args[0], bk.immutablevalue(None))
-## elif len(args) == 2:
-## return SomeSlice(
-## args[0], args[1], bk.immutablevalue(None))
-## elif len(args) == 3:
-## return SomeSlice(
-## args[0], args[1], args[2])
-## else:
-## raise Exception, "bogus call to slice()"
-
def OSError_init(s_self, *args):
pass
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -241,6 +241,9 @@
"Stands for an object which is known to be an unicode string"
knowntype = unicode
+class SomeByteArray(SomeStringOrUnicode):
+ knowntype = bytearray
+
class SomeChar(SomeString):
"Stands for an object known to be a string of length 1."
can_be_None = False
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -3819,6 +3819,37 @@
a = self.RPythonAnnotator()
a.build_types(f, []) # assert did not explode
+ def test_bytearray(self):
+ def f():
+ return bytearray("xyz")
+
+ a = self.RPythonAnnotator()
+ assert isinstance(a.build_types(f, []), annmodel.SomeByteArray)
+
+ def test_bytearray_add(self):
+ def f(a):
+ return a + bytearray("xyz")
+
+ a = self.RPythonAnnotator()
+ assert isinstance(a.build_types(f, [annmodel.SomeByteArray()]),
+ annmodel.SomeByteArray)
+ a = self.RPythonAnnotator()
+ assert isinstance(a.build_types(f, [str]),
+ annmodel.SomeByteArray)
+ a = self.RPythonAnnotator()
+ assert isinstance(a.build_types(f, [annmodel.SomeChar()]),
+ annmodel.SomeByteArray)
+
+ def test_bytearray_setitem_getitem(self):
+ def f(b, i, c):
+ b[i] = c
+ return b[i + 1]
+
+ a = self.RPythonAnnotator()
+ assert isinstance(a.build_types(f, [annmodel.SomeByteArray(),
+ int, int]),
+ annmodel.SomeInteger)
+
def g(n):
return [0,1,2,n]
diff --git a/pypy/doc/Makefile b/pypy/doc/Makefile
--- a/pypy/doc/Makefile
+++ b/pypy/doc/Makefile
@@ -32,38 +32,38 @@
-rm -rf $(BUILDDIR)/*
html:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
pickle:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
@@ -73,7 +73,7 @@
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyPy.qhc"
latex:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@@ -81,26 +81,26 @@
"run these through (pdf)latex."
man:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man"
changes:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
- python config/generate.py
+ # python config/generate.py #readthedocs will not run this Makefile
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -38,7 +38,7 @@
# General information about the project.
project = u'PyPy'
-copyright = u'2011, The PyPy Project'
+copyright = u'2013, The PyPy Project'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
diff --git a/pypy/doc/config/translation.no__thread.txt b/pypy/doc/config/translation.no__thread.txt
--- a/pypy/doc/config/translation.no__thread.txt
+++ b/pypy/doc/config/translation.no__thread.txt
@@ -1,3 +1,3 @@
Don't use gcc __thread attribute for fast thread local storage
-implementation . Increases the chance that moving the resulting
+implementation. Increases the chance that moving the resulting
executable to another same processor Linux machine will work.
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -67,7 +67,7 @@
.. _Python: http://docs.python.org/index.html
.. _`more...`: architecture.html#mission-statement
.. _`PyPy blog`: http://morepypy.blogspot.com/
-.. _`development bug/feature tracker`: https://codespeak.net/issue/pypy-dev/
+.. _`development bug/feature tracker`: https://bugs.pypy.org
.. _here: http://tismerysoft.de/pypy/irc-logs/pypy
.. _`Mercurial commit mailing list`: http://python.org/mailman/listinfo/pypy-commit
.. _`development mailing list`: http://python.org/mailman/listinfo/pypy-dev
diff --git a/pypy/doc/pypyconfig.py b/pypy/doc/pypyconfig.py
--- a/pypy/doc/pypyconfig.py
+++ b/pypy/doc/pypyconfig.py
@@ -3,6 +3,10 @@
def setup(app):
import sys, os
sys.path.insert(0, os.path.abspath("../../"))
+
+ #Autmatically calls make_cmdlline_overview
+ from pypy.doc.config import generate
+
from pypy.config import makerestdoc
import py
role = makerestdoc.register_config_role(py.path.local())
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
@@ -5,15 +5,35 @@
.. this is a revision shortly after release-2.0-beta1
.. startrev: 0e6161a009c6
+.. branch: callback-jit
+Callbacks from C are now better JITted
+
+.. branch: remove-globals-in-jit
+
.. branch: length-hint
Implement __lenght_hint__ according to PEP 424
+.. branch: numpypy-longdouble
+Long double support for numpypy
+
+.. branch: signatures
+Improved RPython typing
+
+.. branch: rpython-bytearray
+Rudimentary support for bytearray in RPython
+
.. branches we don't care about
.. branch: autoreds
+.. branch: reflex-support
+.. branch: kill-faking
+.. branch: improved_ebnfparse_error
+.. branch: task-decorator
.. branch: release-2.0-beta1
.. branch: remove-PYPY_NOT_MAIN_FILE
+.. branch: missing-jit-operations
+
.. branch: fix-lookinside-iff-oopspec
Fixed the interaction between two internal tools for controlling the JIT.
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -56,11 +56,24 @@
----------------------------
On Windows, there is no standard place where to download, build and
-install third-party libraries. We chose to install them in the parent
+install third-party libraries. We recommend installing them in the parent
directory of the pypy checkout. For example, if you installed pypy in
``d:\pypy\trunk\`` (This directory contains a README file), the base
-directory is ``d:\pypy``. You may choose different values by setting the
-INCLUDE, LIB and PATH (for DLLs)
+directory is ``d:\pypy``. You must then set the
+INCLUDE, LIB and PATH (for DLLs) environment variables appropriately.
+
+Abridged method (for -Ojit builds using Visual Studio 2008)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Download the versions of all the external packages
+from
+https://bitbucket.org/pypy/pypy/downloads/local.zip
+Then expand it into the base directory (base_dir) and modify your environment to reflect this::
+
+ set PATH=<base_dir>\bin;%PATH%
+ set INCLUDE=<base_dir>\include;%INCLUDE%
+ set LIB=<base_dir>\lib;%LIB%
+
+Now you should be good to go. Read on for more information.
The Boehm garbage collector
~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -105,6 +105,13 @@
# typical usage (case 1 is the most common kind of app-level subclasses;
# case 2 is the memory-saving kind defined with __slots__).
#
+# +----------------------------------------------------------------+
+# | NOTE: if withmapdict is enabled, the following doesn't apply! |
+# | Map dicts can flexibly allow any slots/__dict__/__weakref__ to |
+# | show up only when needed. In particular there is no way with |
+# | mapdict to prevent some objects from being weakrefable. |
+# +----------------------------------------------------------------+
+#
# dict slots del weakrefable
#
# 1. Y N N Y UserDictWeakref
diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -1,5 +1,6 @@
from __future__ import with_statement
import os
+from pypy.jit.backend.llsupport import jitframe
from pypy.jit.backend.arm.helper.assembler import saved_registers
from pypy.jit.backend.arm import conditions as c
from pypy.jit.backend.arm import registers as r
@@ -8,7 +9,7 @@
from pypy.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
from pypy.jit.backend.arm.locations import get_fp_offset
from pypy.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
- ARMv7RegisterManager, check_imm_arg,
+ CoreRegisterManager, check_imm_arg,
operations as regalloc_operations,
operations_with_guard as regalloc_operations_with_guard)
from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
@@ -25,12 +26,12 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.jit.backend.arm.opassembler import ResOpAssembler
from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
- have_debug_prints)
+ have_debug_prints, fatalerror)
from pypy.rlib.jit import AsmInfo
from pypy.rlib.objectmodel import compute_unique_id
# XXX Move to llsupport
-from pypy.jit.backend.x86.support import values_array, memcpy_fn
+from pypy.jit.backend.x86.support import memcpy_fn
DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
('type', lltype.Char), # 'b'ridge, 'l'abel or
@@ -44,14 +45,8 @@
debug = True
- def __init__(self, cpu, failargs_limit=1000):
+ def __init__(self, cpu, translate_support_code=False):
self.cpu = cpu
- self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
- self.fail_boxes_float = values_array(longlong.FLOATSTORAGE,
- failargs_limit)
- self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit)
- self.fail_boxes_count = 0
- self.fail_force_index = 0
self.setup_failure_recovery()
self.mc = None
self.memcpy_addr = 0
@@ -68,6 +63,7 @@
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
def set_debug(self, v):
r = self._debug
@@ -112,9 +108,13 @@
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()
@@ -122,10 +122,7 @@
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)
- self._exit_code_addr = self._gen_exit_path()
- self._leave_jitted_hook_save_exc = \
- self._gen_leave_jitted_hook_code(True)
- self._leave_jitted_hook = self._gen_leave_jitted_hook_code(False)
+
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
@@ -220,36 +217,17 @@
self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func)
self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func)
- def _gen_leave_jitted_hook_code(self, save_exc):
- mc = ARMv7Builder()
- if self.cpu.supports_floats:
- floats = r.caller_vfp_resp
- else:
- floats = []
- with saved_registers(mc, r.caller_resp + [r.lr], floats):
- addr = self.cpu.get_on_leave_jitted_int(save_exception=save_exc)
- mc.BL(addr)
- assert self._exit_code_addr != 0
- mc.B(self._exit_code_addr)
- return mc.materialize(self.cpu.asmmemmgr, [],
- self.cpu.gc_ll_descr.gcrootmap)
-
def _build_propagate_exception_path(self):
if self.cpu.propagate_exception_v < 0:
return # not supported (for tests, or non-translated)
#
mc = ARMv7Builder()
- # call on_leave_jitted_save_exc()
- if self.cpu.supports_floats:
- floats = r.caller_vfp_resp
- else:
- floats = []
- with saved_registers(mc, r.caller_resp + [r.lr], floats):
- addr = self.cpu.get_on_leave_jitted_int(save_exception=True,
- default_to_memoryerror=True)
- mc.BL(addr)
- mc.gen_load_int(r.ip.value, self.cpu.propagate_exception_v)
- mc.MOV_rr(r.r0.value, r.ip.value)
+ #
+ # 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, [])
@@ -282,12 +260,12 @@
# 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)
- # call on_leave_jitted_save_exc()
- addr = self.cpu.get_on_leave_jitted_int(save_exception=True)
+ #
+ # Call the helper, which will return a dead frame object with
+ # the correct exception set, or MemoryError by default
+ addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
mc.BL(addr)
#
- mc.gen_load_int(r.r0.value, self.cpu.propagate_exception_v)
- #
# footer -- note the ADD, which skips the return address of this
# function, and will instead return to the caller's caller. Note
# also that we completely ignore the saved arguments, because we
@@ -339,39 +317,82 @@
def setup_failure_recovery(self):
- @rgc.no_collect
+ #@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.LONGLONGP, stack_pointer)
- registers = rffi.ptradd(vfp_registers, len(r.all_vfp_regs))
+ 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)
- return self.decode_registers_and_descr(mem_loc, frame_pointer,
+ bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+ return self.grab_frame_values(self.cpu, bytecode, frame_pointer,
registers, vfp_registers)
+ self.failure_recovery_code = [0, 0, 0, 0]
self.failure_recovery_func = failure_recovery_func
- recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed] * 3,
- lltype.Signed))
+ _FAILURE_RECOVERY_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP] * 3,
+ llmemory.GCREF))
- @rgc.no_collect
- def decode_registers_and_descr(self, mem_loc, frame_pointer,
+ @staticmethod
+ #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
+ def grab_frame_values(cpu, bytecode, frame_pointer,
registers, vfp_registers):
- """Decode locations encoded in memory at mem_loc and write the values
- to the failboxes. Values for spilled vars and registers are stored on
- stack at frame_loc """
- assert frame_pointer & 1 == 0
- self.fail_force_index = frame_pointer
- bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+ # no malloc allowed here!! xxx apart from one, hacking a lot
+ force_index = rffi.cast(lltype.Signed, frame_pointer)
num = 0
- value = 0
- fvalue = 0
+ deadframe = lltype.nullptr(jitframe.DEADFRAME)
+ # step 1: lots of mess just to count the final value of 'num'
+ bytecode1 = bytecode
+ while 1:
+ code = rffi.cast(lltype.Signed, bytecode1[0])
+ bytecode1 = rffi.ptradd(bytecode1, 1)
+ if code >= AssemblerARM.CODE_FROMSTACK:
+ while code > 0x7F:
+ code = rffi.cast(lltype.Signed, bytecode1[0])
+ bytecode1 = rffi.ptradd(bytecode1, 1)
+ else:
+ kind = code & 3
+ if kind == AssemblerARM.DESCR_SPECIAL:
+ if code == AssemblerARM.CODE_HOLE:
+ num += 1
+ continue
+ if code == AssemblerARM.CODE_INPUTARG:
+ continue
+ if code == AssemblerARM.CODE_FORCED:
+ # resuming from a GUARD_NOT_FORCED
+ token = force_index
+ deadframe = (
+ cpu.assembler.force_token_to_dead_frame.pop(token))
+ deadframe = lltype.cast_opaque_ptr(
+ jitframe.DEADFRAMEPTR, deadframe)
+ continue
+ assert code == AssemblerARM.CODE_STOP
+ break
+ num += 1
+
+ # allocate the deadframe
+ if not deadframe:
+ # Remove the "reserve" at the end of the nursery. This means
+ # that it is guaranteed that the following malloc() works
+ # without requiring a collect(), but it needs to be re-added
+ # as soon as possible.
+ cpu.gc_clear_extra_threshold()
+ assert num <= cpu.get_failargs_limit()
+ try:
+ deadframe = lltype.malloc(jitframe.DEADFRAME, num)
+ except MemoryError:
+ fatalerror("memory usage error in grab_frame_values")
+ # fill it
code_inputarg = False
- while True:
+ num = 0
+ value_hi = 0
+ while 1:
+ # decode the next instruction from the bytecode
code = rffi.cast(lltype.Signed, bytecode[0])
bytecode = rffi.ptradd(bytecode, 1)
- if code >= self.CODE_FROMSTACK:
+ if code >= AssemblerARM.CODE_FROMSTACK:
if code > 0x7F:
shift = 7
code &= 0x7F
@@ -384,54 +405,63 @@
break
# load the value from the stack
kind = code & 3
- code = int((code - self.CODE_FROMSTACK) >> 2)
+ code = (code - AssemblerARM.CODE_FROMSTACK) >> 2
if code_inputarg:
code = ~code
code_inputarg = False
- if kind == self.DESCR_FLOAT:
- # we use code + 1 to get the hi word of the double worded float
- stackloc = frame_pointer - get_fp_offset(int(code) + 1)
- assert stackloc & 3 == 0
- fvalue = rffi.cast(rffi.LONGLONGP, stackloc)[0]
- else:
- stackloc = frame_pointer - get_fp_offset(int(code))
- assert stackloc & 1 == 0
- value = rffi.cast(rffi.LONGP, stackloc)[0]
+ stackloc = force_index - get_fp_offset(int(code))
+ value = rffi.cast(rffi.LONGP, stackloc)[0]
+ if kind == AssemblerARM.DESCR_FLOAT:
+ assert WORD == 4
+ value_hi = value
+ value = rffi.cast(rffi.LONGP, stackloc - WORD)[0]
else:
- # 'code' identifies a register: load its value
kind = code & 3
- if kind == self.DESCR_SPECIAL:
- if code == self.CODE_HOLE:
+ if kind == AssemblerARM.DESCR_SPECIAL:
+ if code == AssemblerARM.CODE_HOLE:
num += 1
continue
- if code == self.CODE_INPUTARG:
+ if code == AssemblerARM.CODE_INPUTARG:
code_inputarg = True
continue
- assert code == self.CODE_STOP
+ if code == AssemblerARM.CODE_FORCED:
+ continue
+ assert code == AssemblerARM.CODE_STOP
break
+ # 'code' identifies a register: load its value
code >>= 2
- if kind == self.DESCR_FLOAT:
- fvalue = vfp_registers[code]
+ if kind == AssemblerARM.DESCR_FLOAT:
+ if WORD == 4:
+ value = vfp_registers[2*code]
+ value_hi = vfp_registers[2*code + 1]
+ else:
+ value = registers[code]
else:
value = registers[code]
# store the loaded value into fail_boxes_<type>
- if kind == self.DESCR_FLOAT:
- tgt = self.fail_boxes_float.get_addr_for_num(num)
- rffi.cast(rffi.LONGLONGP, tgt)[0] = fvalue
+ if kind == AssemblerARM.DESCR_INT:
+ deadframe.jf_values[num].int = value
+ elif kind == AssemblerARM.DESCR_REF:
+ deadframe.jf_values[num].ref = rffi.cast(llmemory.GCREF, value)
+ elif kind == AssemblerARM.DESCR_FLOAT:
+ assert WORD == 4
+ assert not longlong.is_64_bit
+ floatvalue = rffi.cast(lltype.SignedLongLong, value_hi)
+ floatvalue <<= 32
+ floatvalue |= rffi.cast(lltype.SignedLongLong,
+ rffi.cast(lltype.Unsigned, value))
+ deadframe.jf_values[num].float = floatvalue
else:
- if kind == self.DESCR_INT:
- tgt = self.fail_boxes_int.get_addr_for_num(num)
- elif kind == self.DESCR_REF:
- assert (value & 3) == 0, "misaligned pointer"
- tgt = self.fail_boxes_ptr.get_addr_for_num(num)
- else:
- assert 0, "bogus kind"
- rffi.cast(rffi.LONGP, tgt)[0] = value
+ assert 0, "bogus kind"
num += 1
- self.fail_boxes_count = num
+ #
+ assert num == len(deadframe.jf_values)
+ if not we_are_translated():
+ assert bytecode[4] == 0xCC
fail_index = rffi.cast(rffi.INTP, bytecode)[0]
- fail_index = rffi.cast(lltype.Signed, fail_index)
- return fail_index
+ fail_descr = cpu.get_fail_descr_from_number(fail_index)
+ deadframe.jf_descr = fail_descr.hide(cpu)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, deadframe)
def decode_inputargs(self, code):
descr_to_box_type = [REF, INT, FLOAT]
@@ -492,10 +522,10 @@
# are stored in r0 and r1.
mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value)
addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
- for reg, ofs in ARMv7RegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
+ for reg, ofs in CoreRegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
mc.STR_ri(reg.value, r.fp.value, imm=ofs)
mc.BL(addr)
- for reg, ofs in ARMv7RegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
+ for reg, ofs in CoreRegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
mc.LDR_ri(reg.value, r.fp.value, imm=ofs)
mc.CMP_ri(r.r0.value, 0)
@@ -514,12 +544,26 @@
self.mc.CMP_ri(r.r0.value, 0)
self.mc.B(self.propagate_exception_path, c=c.EQ)
- def _gen_exit_path(self):
+ def _build_failure_recovery(self, exc, withfloats=False):
mc = ARMv7Builder()
- decode_registers_addr = llhelper(self.recovery_func_sign,
+ failure_recovery = llhelper(self._FAILURE_RECOVERY_FUNC,
self.failure_recovery_func)
self._insert_checks(mc)
- with saved_registers(mc, r.all_regs, r.all_vfp_regs):
+ if withfloats:
+ f = r.all_vfp_regs
+ else:
+ f = []
+ with saved_registers(mc, r.all_regs, f):
+ if exc:
+ # We might have an exception pending. Load it into r4
+ # (this is a register saved across calls)
+ mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
+ mc.LDR_ri(r.r4.value, self.cpu.pos_exc_value())
+ # clear the exc flags
+ mc.gen_load_int(r.r6.value, 0)
+ mc.STR_ri(r.r6.value, r.r5.value)
+ mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
+ mc.STR_ri(r.r6.value, r.r5.value)
# move mem block address, to r0 to pass as
mc.MOV_rr(r.r0.value, r.lr.value)
# pass the current frame pointer as second param
@@ -527,23 +571,32 @@
# pass the current stack pointer as third param
mc.MOV_rr(r.r2.value, r.sp.value)
self._insert_checks(mc)
- mc.BL(rffi.cast(lltype.Signed, decode_registers_addr))
+ mc.BL(rffi.cast(lltype.Signed, failure_recovery))
+ if exc:
+ # save ebx into 'jf_guard_exc'
+ from pypy.jit.backend.llsupport.descr import unpack_fielddescr
+ descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+ offset, size, _ = unpack_fielddescr(descrs.jf_guard_exc)
+ mc.STR_rr(r.r4.value, r.r0.value, offset, cond=c.AL)
mc.MOV_rr(r.ip.value, r.r0.value)
mc.MOV_rr(r.r0.value, r.ip.value)
self.gen_func_epilog(mc=mc)
- return mc.materialize(self.cpu.asmmemmgr, [],
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [],
self.cpu.gc_ll_descr.gcrootmap)
+ self.failure_recovery_code[exc + 2 * withfloats] = rawstart
+ self.mc = None
DESCR_REF = 0x00
DESCR_INT = 0x01
DESCR_FLOAT = 0x02
DESCR_SPECIAL = 0x03
CODE_FROMSTACK = 64
- CODE_STOP = 0 | DESCR_SPECIAL
- CODE_HOLE = 4 | DESCR_SPECIAL
- CODE_INPUTARG = 8 | DESCR_SPECIAL
+ CODE_STOP = 0 | DESCR_SPECIAL
+ CODE_HOLE = 4 | DESCR_SPECIAL
+ CODE_INPUTARG = 8 | DESCR_SPECIAL
+ CODE_FORCED = 12 | DESCR_SPECIAL #XXX where should this be written?
- def gen_descr_encoding(self, descr, failargs, locs):
+ def write_failure_recovery_description(self, descr, failargs, locs):
assert self.mc is not None
for i in range(len(failargs)):
arg = failargs[i]
@@ -575,26 +628,33 @@
self.mc.writechar(chr(n))
self.mc.writechar(chr(self.CODE_STOP))
- fdescr = self.cpu.get_fail_descr_number(descr)
- self.mc.write32(fdescr)
+
+ def generate_quick_failure(self, guardtok, fcond=c.AL):
+ assert isinstance(guardtok.save_exc, bool)
+ fail_index = self.cpu.get_fail_descr_number(guardtok.descr)
+ startpos = self.mc.currpos()
+ withfloats = False
+ for box in guardtok.failargs:
+ if box is not None and box.type == FLOAT:
+ withfloats = True
+ break
+ exc = guardtok.save_exc
+ target = self.failure_recovery_code[exc + 2 * withfloats]
+ assert target != 0
+ self.mc.BL(target)
+ # write tight data that describes the failure recovery
+ if guardtok.is_guard_not_forced:
+ self.mc.writechar(chr(self.CODE_FORCED))
+ self.write_failure_recovery_description(guardtok.descr,
+ guardtok.failargs, guardtok.faillocs[1:])
+ self.mc.write32(fail_index)
+ # for testing the decoding, write a final byte 0xCC
+ if not we_are_translated():
+ self.mc.writechar('\xCC')
+ faillocs = [loc for loc in guardtok.faillocs if loc is not None]
+ guardtok.descr._arm_debug_faillocs = faillocs
self.align()
-
- # assert that the fail_boxes lists are big enough
- assert len(failargs) <= self.fail_boxes_int.SIZE
-
- def _gen_path_to_exit_path(self, descr, args, arglocs,
- save_exc, fcond=c.AL):
- assert isinstance(save_exc, bool)
- self.gen_exit_code(self.mc, save_exc, fcond)
- self.gen_descr_encoding(descr, args, arglocs[1:])
-
- def gen_exit_code(self, mc, save_exc, fcond=c.AL):
- assert isinstance(save_exc, bool)
- if save_exc:
- path = self._leave_jitted_hook_save_exc
- else:
- path = self._leave_jitted_hook
- mc.BL(path)
+ return startpos
def align(self):
while(self.mc.currpos() % FUNC_ALIGN != 0):
@@ -841,15 +901,10 @@
def write_pending_failure_recoveries(self):
for tok in self.pending_guards:
- descr = tok.descr
#generate the exit stub and the encoded representation
- pos = self.mc.currpos()
- tok.pos_recovery_stub = pos
-
- self._gen_path_to_exit_path(descr, tok.failargs,
- tok.faillocs, save_exc=tok.save_exc)
+ tok.pos_recovery_stub = self.generate_quick_failure(tok)
# store info on the descr
- descr._arm_current_frame_depth = tok.faillocs[0].getint()
+ tok.descr._arm_current_frame_depth = tok.faillocs[0].getint()
def process_pending_guards(self, block_start):
clt = self.current_clt
@@ -860,7 +915,7 @@
descr._arm_failure_recovery_block = failure_recovery_pos
relative_offset = tok.pos_recovery_stub - tok.offset
guard_pos = block_start + tok.offset
- if not tok.is_invalidate:
+ if not tok.is_guard_not_invalidated:
# patch the guard jumpt to the stub
# overwrite the generate NOP with a B_offs to the pos of the
# stub
@@ -1255,11 +1310,6 @@
else:
raise AssertionError('Trying to pop to an invalid location')
- def leave_jitted_hook(self):
- ptrs = self.fail_boxes_ptr.ar
- llop.gc_assume_young_pointers(lltype.Void,
- llmemory.cast_ptr_to_adr(ptrs))
-
def malloc_cond(self, nursery_free_adr, nursery_top_adr, size):
assert size & (WORD-1) == 0 # must be correctly aligned
diff --git a/pypy/jit/backend/arm/helper/regalloc.py b/pypy/jit/backend/arm/helper/regalloc.py
--- a/pypy/jit/backend/arm/helper/regalloc.py
+++ b/pypy/jit/backend/arm/helper/regalloc.py
@@ -32,14 +32,14 @@
imm_a0 = check_imm_box(a0, imm_size, allow_zero=allow_zero)
imm_a1 = check_imm_box(a1, imm_size, allow_zero=allow_zero)
if not imm_a0 and imm_a1:
- l0 = self._ensure_value_is_boxed(a0)
+ l0 = self.make_sure_var_in_reg(a0)
l1 = self.convert_to_imm(a1)
elif commutative and imm_a0 and not imm_a1:
l1 = self.convert_to_imm(a0)
- l0 = self._ensure_value_is_boxed(a1, boxes)
+ l0 = self.make_sure_var_in_reg(a1, boxes)
else:
- l0 = self._ensure_value_is_boxed(a0, boxes)
- l1 = self._ensure_value_is_boxed(a1, boxes)
+ l0 = self.make_sure_var_in_reg(a0, boxes)
+ l1 = self.make_sure_var_in_reg(a1, boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
res = self.force_allocate_reg(op.result, boxes)
@@ -52,10 +52,10 @@
if guard:
def f(self, op, guard_op, fcond):
locs = []
- loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ loc1 = self.make_sure_var_in_reg(op.getarg(0))
locs.append(loc1)
if base:
- loc2 = self._ensure_value_is_boxed(op.getarg(1))
+ loc2 = self.make_sure_var_in_reg(op.getarg(1))
locs.append(loc2)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
@@ -70,10 +70,10 @@
else:
def f(self, op, fcond):
locs = []
- loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ loc1 = self.make_sure_var_in_reg(op.getarg(0))
locs.append(loc1)
if base:
- loc2 = self._ensure_value_is_boxed(op.getarg(1))
+ loc2 = self.make_sure_var_in_reg(op.getarg(1))
locs.append(loc2)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
@@ -111,11 +111,11 @@
arg0, arg1 = boxes
imm_a1 = check_imm_box(arg1)
- l0 = self._ensure_value_is_boxed(arg0, forbidden_vars=boxes)
+ l0 = self.make_sure_var_in_reg(arg0, forbidden_vars=boxes)
if imm_a1:
l1 = self.convert_to_imm(arg1)
else:
- l1 = self._ensure_value_is_boxed(arg1, forbidden_vars=boxes)
+ l1 = self.make_sure_var_in_reg(arg1, forbidden_vars=boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
@@ -134,7 +134,7 @@
assert fcond is not None
a0 = op.getarg(0)
assert isinstance(a0, Box)
- reg = self._ensure_value_is_boxed(a0)
+ reg = self.make_sure_var_in_reg(a0)
self.possibly_free_vars_for_op(op)
if guard_op is None:
res = self.force_allocate_reg(op.result, [a0])
diff --git a/pypy/jit/backend/arm/opassembler.py b/pypy/jit/backend/arm/opassembler.py
--- a/pypy/jit/backend/arm/opassembler.py
+++ b/pypy/jit/backend/arm/opassembler.py
@@ -16,6 +16,7 @@
gen_emit_unary_float_op,
saved_registers,
count_reg_args)
+from pypy.jit.backend.arm.helper.regalloc import check_imm_arg
from pypy.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
from pypy.jit.backend.arm.jump import remap_frame_layout
from pypy.jit.backend.arm.regalloc import TempInt, TempPtr
@@ -27,18 +28,20 @@
from pypy.jit.metainterp.history import JitCellToken, TargetToken
from pypy.jit.metainterp.resoperation import rop
from pypy.rlib.objectmodel import we_are_translated
-from pypy.rpython.lltypesystem import rstr
+from pypy.rlib import rgc
+from pypy.rpython.lltypesystem import rstr, rffi, lltype, llmemory
NO_FORCE_INDEX = -1
class GuardToken(object):
- def __init__(self, descr, failargs, faillocs, offset,
- save_exc, fcond=c.AL, is_invalidate=False):
+ def __init__(self, descr, failargs, faillocs, offset, save_exc, fcond=c.AL,
+ is_guard_not_invalidated=False, is_guard_not_forced=False):
assert isinstance(save_exc, bool)
self.descr = descr
self.offset = offset
- self.is_invalidate = is_invalidate
+ self.is_guard_not_invalidated = is_guard_not_invalidated
+ self.is_guard_not_forced = is_guard_not_forced
self.failargs = failargs
self.faillocs = faillocs
self.save_exc = save_exc
@@ -190,7 +193,8 @@
return fcond
def _emit_guard(self, op, arglocs, fcond, save_exc,
- is_guard_not_invalidated=False):
+ is_guard_not_invalidated=False,
+ is_guard_not_forced=False):
assert isinstance(save_exc, bool)
assert isinstance(fcond, int)
descr = op.getdescr()
@@ -210,7 +214,8 @@
faillocs=arglocs,
offset=pos,
save_exc=save_exc,
- is_invalidate=is_guard_not_invalidated,
+ is_guard_not_invalidated=is_guard_not_invalidated,
+ is_guard_not_forced=is_guard_not_forced,
fcond=fcond))
return c.AL
@@ -312,49 +317,10 @@
return fcond
def emit_op_finish(self, op, arglocs, regalloc, fcond):
- for i in range(len(arglocs) - 1):
- loc = arglocs[i]
- box = op.getarg(i)
- if loc is None:
- continue
- if loc.is_reg():
- if box.type == REF:
- adr = self.fail_boxes_ptr.get_addr_for_num(i)
- elif box.type == INT:
- adr = self.fail_boxes_int.get_addr_for_num(i)
- else:
- assert 0
- self.mc.gen_load_int(r.ip.value, adr)
- self.mc.STR_ri(loc.value, r.ip.value)
- elif loc.is_vfp_reg():
- assert box.type == FLOAT
- adr = self.fail_boxes_float.get_addr_for_num(i)
- self.mc.gen_load_int(r.ip.value, adr)
- self.mc.VSTR(loc.value, r.ip.value)
- elif loc.is_stack() or loc.is_imm() or loc.is_imm_float():
- if box.type == FLOAT:
- adr = self.fail_boxes_float.get_addr_for_num(i)
- self.mov_loc_loc(loc, r.vfp_ip)
- self.mc.gen_load_int(r.ip.value, adr)
- self.mc.VSTR(r.vfp_ip.value, r.ip.value)
- elif box.type == REF or box.type == INT:
- if box.type == REF:
- adr = self.fail_boxes_ptr.get_addr_for_num(i)
- elif box.type == INT:
- adr = self.fail_boxes_int.get_addr_for_num(i)
- else:
- assert 0
- self.mov_loc_loc(loc, r.ip)
- self.mc.gen_load_int(r.lr.value, adr)
- self.mc.STR_ri(r.ip.value, r.lr.value)
- else:
- assert 0
- # note: no exception should currently be set in llop.get_exception_addr
- # even if this finish may be an exit_frame_with_exception (in this case
- # the exception instance is in arglocs[0]).
- addr = self.cpu.get_on_leave_jitted_int(save_exception=False)
- self.mc.BL(addr)
- self.mc.gen_load_int(r.r0.value, arglocs[-1].value)
+ [argloc] = arglocs
+ if argloc is not r.r0: #XXX verify this
+ self.mov_loc_loc(argloc, r.r0, fcond)
+ # exit function
self.gen_func_epilog()
return fcond
@@ -988,8 +954,8 @@
def _emit_copystrcontent(self, op, regalloc, fcond, is_unicode):
# compute the source address
args = op.getarglist()
- base_loc = regalloc._ensure_value_is_boxed(args[0], args)
- ofs_loc = regalloc._ensure_value_is_boxed(args[2], args)
+ base_loc = regalloc.make_sure_var_in_reg(args[0], args)
+ ofs_loc = regalloc.make_sure_var_in_reg(args[2], args)
assert args[0] is not args[1] # forbidden case of aliasing
regalloc.possibly_free_var(args[0])
regalloc.free_temp_vars()
@@ -1009,8 +975,8 @@
dstaddr_loc = regalloc.force_allocate_reg(dstaddr_box,
selected_reg=r.r0)
forbidden_vars.append(dstaddr_box)
- base_loc = regalloc._ensure_value_is_boxed(args[1], forbidden_vars)
- ofs_loc = regalloc._ensure_value_is_boxed(args[3], forbidden_vars)
+ base_loc = regalloc.make_sure_var_in_reg(args[1], forbidden_vars)
+ ofs_loc = regalloc.make_sure_var_in_reg(args[3], forbidden_vars)
assert base_loc.is_reg()
assert ofs_loc.is_reg()
regalloc.possibly_free_var(args[1])
@@ -1026,7 +992,7 @@
# need the box here
if isinstance(args[4], Box):
length_box = args[4]
- length_loc = regalloc._ensure_value_is_boxed(args[4],
+ length_loc = regalloc.make_sure_var_in_reg(args[4],
forbidden_vars)
else:
length_box = TempInt()
@@ -1152,8 +1118,26 @@
value = self.cpu.done_with_this_frame_float_v
else:
raise AssertionError(kind)
- self.mc.gen_load_int(r.ip.value, value)
- self.mc.CMP_rr(tmploc.value, r.ip.value)
+ from pypy.jit.backend.llsupport.descr import unpack_fielddescr
+ from pypy.jit.backend.llsupport.descr import unpack_interiorfielddescr
+ descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+ _offset, _size, _ = unpack_fielddescr(descrs.jf_descr)
+ fail_descr = self.cpu.get_fail_descr_from_number(value)
+ value = fail_descr.hide(self.cpu)
+ rgc._make_sure_does_not_move(value)
+ value = rffi.cast(lltype.Signed, value)
+
+ if check_imm_arg(_offset):
+ self.mc.LDR_ri(r.ip.value, tmploc.value, imm=_offset)
+ else:
+ self.mc.gen_load_int(r.ip.value, _offset)
+ self.mc.LDR_rr(r.ip.value, tmploc.value, r.ip.value)
+ if check_imm_arg(value):
+ self.mc.CMP_ri(r.ip.value, imm=value)
+ else:
+ self.mc.gen_load_int(r.lr.value, value)
+ self.mc.CMP_rr(r.lr.value, r.ip.value)
+
#if values are equal we take the fast path
# Slow path, calling helper
@@ -1180,19 +1164,31 @@
if op.result is not None:
# load the return value from fail_boxes_xxx[0]
kind = op.result.type
- if kind == INT:
- adr = self.fail_boxes_int.get_addr_for_num(0)
- elif kind == REF:
- adr = self.fail_boxes_ptr.get_addr_for_num(0)
- elif kind == FLOAT:
- adr = self.fail_boxes_float.get_addr_for_num(0)
+ if kind == FLOAT:
+ t = unpack_interiorfielddescr(descrs.as_float)[0]
+ if not check_imm_arg(t):
+ self.mc.gen_load_int(r.ip.value, t, cond=fast_path_cond)
+ self.mc.ADD_rr(r.ip.value, r.r0.value, r.ip.value,
+ cond=fast_path_cond)
+ t = 0
+ base = r.ip
+ else:
+ base = r.r0
+ self.mc.VLDR(resloc.value, base.value, imm=t,
+ cond=fast_path_cond)
else:
- raise AssertionError(kind)
- self.mc.gen_load_int(r.ip.value, adr, cond=fast_path_cond)
- if op.result.type == FLOAT:
- self.mc.VLDR(resloc.value, r.ip.value, cond=fast_path_cond)
- else:
- self.mc.LDR_ri(resloc.value, r.ip.value, cond=fast_path_cond)
+ assert resloc is r.r0
+ if kind == INT:
+ t = unpack_interiorfielddescr(descrs.as_int)[0]
+ else:
+ t = unpack_interiorfielddescr(descrs.as_ref)[0]
+ if not check_imm_arg(t):
+ self.mc.gen_load_int(r.ip.value, t, cond=fast_path_cond)
+ self.mc.LDR_rr(resloc.value, resloc.value, r.ip.value,
+ cond=fast_path_cond)
+ else:
+ self.mc.LDR_ri(resloc.value, resloc.value, imm=t,
+ cond=fast_path_cond)
# jump to merge point
jmp_pos = self.mc.currpos()
self.mc.BKPT()
@@ -1266,7 +1262,8 @@
self.mc.LDR_ri(r.ip.value, r.fp.value)
self.mc.CMP_ri(r.ip.value, 0)
- self._emit_guard(guard_op, arglocs[1 + numargs:], c.GE, save_exc=True)
+ self._emit_guard(guard_op, arglocs[1 + numargs:], c.GE,
+ save_exc=True, is_guard_not_forced=True)
return fcond
def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc,
diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py
--- a/pypy/jit/backend/arm/regalloc.py
+++ b/pypy/jit/backend/arm/regalloc.py
@@ -84,8 +84,28 @@
def void(self, op, fcond):
return []
+class ARMRegisterManager(RegisterManager):
+ def return_constant(self, v, forbidden_vars=[], selected_reg=None):
+ self._check_type(v)
+ if isinstance(v, Const):
+ if isinstance(v, ConstPtr):
+ tp = REF
+ elif isinstance(v, ConstFloat):
+ tp = FLOAT
+ else:
+ tp = INT
+ loc = self.get_scratch_reg(tp,
+ self.temp_boxes + forbidden_vars,
+ selected_reg=selected_reg)
+ immvalue = self.convert_to_imm(v)
+ self.assembler.load(loc, immvalue)
+ return loc
+ else:
+ return RegisterManager.return_constant(self, v,
+ forbidden_vars, selected_reg)
-class VFPRegisterManager(RegisterManager):
+
+class VFPRegisterManager(ARMRegisterManager):
all_regs = r.all_vfp_regs
box_types = [FLOAT]
save_around_call_regs = r.all_vfp_regs
@@ -107,20 +127,7 @@
reg = self.force_allocate_reg(v, selected_reg=r.d0)
return reg
- def ensure_value_is_boxed(self, thing, forbidden_vars=[]):
- loc = None
- if isinstance(thing, Const):
- assert isinstance(thing, ConstFloat)
- loc = self.get_scratch_reg(FLOAT, self.temp_boxes + forbidden_vars)
- immvalue = self.convert_to_imm(thing)
- self.assembler.load(loc, immvalue)
- else:
- loc = self.make_sure_var_in_reg(thing,
- forbidden_vars=self.temp_boxes + forbidden_vars)
- return loc
-
- def get_scratch_reg(self, type=FLOAT, forbidden_vars=[],
- selected_reg=None):
+ def get_scratch_reg(self, type=FLOAT, forbidden_vars=[], selected_reg=None):
assert type == FLOAT # for now
box = TempFloat()
self.temp_boxes.append(box)
@@ -129,7 +136,7 @@
return reg
-class ARMv7RegisterManager(RegisterManager):
+class CoreRegisterManager(ARMRegisterManager):
all_regs = r.all_regs
box_types = None # or a list of acceptable types
no_lower_byte_regs = all_regs
@@ -162,22 +169,6 @@
return locations.ImmLocation(rffi.cast(lltype.Signed, c.value))
assert 0
- def ensure_value_is_boxed(self, thing, forbidden_vars=None):
- loc = None
- if isinstance(thing, Const):
- if isinstance(thing, ConstPtr):
- tp = REF
- else:
- tp = INT
- loc = self.get_scratch_reg(tp, forbidden_vars=self.temp_boxes
- + forbidden_vars)
- immvalue = self.convert_to_imm(thing)
- self.assembler.load(loc, immvalue)
- else:
- loc = self.make_sure_var_in_reg(thing,
- forbidden_vars=self.temp_boxes + forbidden_vars)
- return loc
-
def get_scratch_reg(self, type=INT, forbidden_vars=[], selected_reg=None):
assert type == INT or type == REF
box = TempBox()
@@ -277,7 +268,12 @@
def make_sure_var_in_reg(self, var, forbidden_vars=[],
selected_reg=None, need_lower_byte=False):
- assert 0, 'should not be called directly'
+ if var.type == FLOAT:
+ return self.vfprm.make_sure_var_in_reg(var, forbidden_vars,
+ selected_reg, need_lower_byte)
+ else:
+ return self.rm.make_sure_var_in_reg(var, forbidden_vars,
+ selected_reg, need_lower_byte)
def convert_to_imm(self, value):
if isinstance(value, ConstInt):
@@ -294,7 +290,7 @@
fm = self.frame_manager
asm = self.assembler
self.vfprm = VFPRegisterManager(longevity, fm, asm)
- self.rm = ARMv7RegisterManager(longevity, fm, asm)
+ self.rm = CoreRegisterManager(longevity, fm, asm)
def prepare_loop(self, inputargs, operations):
self._prepare(inputargs, operations)
@@ -426,12 +422,6 @@
self.rm.before_call(force_store, save_all_regs)
self.vfprm.before_call(force_store, save_all_regs)
- def _ensure_value_is_boxed(self, thing, forbidden_vars=[]):
- if thing.type == FLOAT:
- return self.vfprm.ensure_value_is_boxed(thing, forbidden_vars)
- else:
- return self.rm.ensure_value_is_boxed(thing, forbidden_vars)
-
def _sync_var(self, v):
if v.type == FLOAT:
self.vfprm._sync_var(v)
@@ -444,14 +434,14 @@
imm_a0 = check_imm_box(a0)
imm_a1 = check_imm_box(a1)
if not imm_a0 and imm_a1:
- l0 = self._ensure_value_is_boxed(a0, boxes)
+ l0 = self.make_sure_var_in_reg(a0, boxes)
l1 = self.convert_to_imm(a1)
elif imm_a0 and not imm_a1:
l0 = self.convert_to_imm(a0)
- l1 = self._ensure_value_is_boxed(a1, boxes)
+ l1 = self.make_sure_var_in_reg(a1, boxes)
else:
- l0 = self._ensure_value_is_boxed(a0, boxes)
- l1 = self._ensure_value_is_boxed(a1, boxes)
+ l0 = self.make_sure_var_in_reg(a0, boxes)
+ l1 = self.make_sure_var_in_reg(a1, boxes)
return [l0, l1]
def prepare_op_int_add(self, op, fcond):
@@ -466,14 +456,14 @@
imm_a0 = check_imm_box(a0)
imm_a1 = check_imm_box(a1)
if not imm_a0 and imm_a1:
- l0 = self._ensure_value_is_boxed(a0, boxes)
+ l0 = self.make_sure_var_in_reg(a0, boxes)
l1 = self.convert_to_imm(a1)
elif imm_a0 and not imm_a1:
l0 = self.convert_to_imm(a0)
- l1 = self._ensure_value_is_boxed(a1, boxes)
+ l1 = self.make_sure_var_in_reg(a1, boxes)
else:
- l0 = self._ensure_value_is_boxed(a0, boxes)
- l1 = self._ensure_value_is_boxed(a1, boxes)
+ l0 = self.make_sure_var_in_reg(a0, boxes)
+ l1 = self.make_sure_var_in_reg(a1, boxes)
return [l0, l1]
def prepare_op_int_sub(self, op, fcond):
@@ -487,8 +477,8 @@
boxes = op.getarglist()
a0, a1 = boxes
- reg1 = self._ensure_value_is_boxed(a0, forbidden_vars=boxes)
- reg2 = self._ensure_value_is_boxed(a1, forbidden_vars=boxes)
+ reg1 = self.make_sure_var_in_reg(a0, forbidden_vars=boxes)
+ reg2 = self.make_sure_var_in_reg(a1, forbidden_vars=boxes)
self.possibly_free_vars(boxes)
self.possibly_free_vars_for_op(op)
@@ -497,14 +487,14 @@
return [reg1, reg2, res]
def prepare_op_int_force_ge_zero(self, op, fcond):
- argloc = self._ensure_value_is_boxed(op.getarg(0))
+ argloc = self.make_sure_var_in_reg(op.getarg(0))
resloc = self.force_allocate_reg(op.result, [op.getarg(0)])
return [argloc, resloc]
def prepare_guard_int_mul_ovf(self, op, guard, fcond):
boxes = op.getarglist()
- reg1 = self._ensure_value_is_boxed(boxes[0], forbidden_vars=boxes)
- reg2 = self._ensure_value_is_boxed(boxes[1], forbidden_vars=boxes)
+ reg1 = self.make_sure_var_in_reg(boxes[0], forbidden_vars=boxes)
+ reg2 = self.make_sure_var_in_reg(boxes[1], forbidden_vars=boxes)
res = self.force_allocate_reg(op.result)
return self._prepare_guard(guard, [reg1, reg2, res])
@@ -576,7 +566,7 @@
prepare_guard_int_is_zero = prepare_op_unary_cmp('int_is_zero')
def prepare_op_int_neg(self, op, fcond):
- l0 = self._ensure_value_is_boxed(op.getarg(0))
+ l0 = self.make_sure_var_in_reg(op.getarg(0))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
resloc = self.force_allocate_reg(op.result)
@@ -629,15 +619,15 @@
def _prepare_llong_binop_xx(self, op, fcond):
# arg 0 is the address of the function
- loc0 = self._ensure_value_is_boxed(op.getarg(1))
- loc1 = self._ensure_value_is_boxed(op.getarg(2))
+ loc0 = self.make_sure_var_in_reg(op.getarg(1))
+ loc1 = self.make_sure_var_in_reg(op.getarg(2))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
res = self.vfprm.force_allocate_reg(op.result)
return [loc0, loc1, res]
def _prepare_llong_to_int(self, op, fcond):
- loc0 = self._ensure_value_is_boxed(op.getarg(1))
+ loc0 = self.make_sure_var_in_reg(op.getarg(1))
res = self.force_allocate_reg(op.result)
return [loc0, res]
@@ -654,18 +644,12 @@
return args
def prepare_op_finish(self, op, fcond):
- args = [None] * (op.numargs() + 1)
- for i in range(op.numargs()):
- arg = op.getarg(i)
- if arg:
- args[i] = self.loc(arg)
- self.possibly_free_var(arg)
- n = self.cpu.get_fail_descr_number(op.getdescr())
- args[-1] = imm(n)
- return args
+ loc = self.loc(op.getarg(0))
+ self.possibly_free_var(op.getarg(0))
+ return [loc]
def prepare_op_guard_true(self, op, fcond):
- l0 = self._ensure_value_is_boxed(op.getarg(0))
+ l0 = self.make_sure_var_in_reg(op.getarg(0))
args = self._prepare_guard(op, [l0])
return args
@@ -677,9 +661,9 @@
boxes = op.getarglist()
a0, a1 = boxes
imm_a1 = check_imm_box(a1)
- l0 = self._ensure_value_is_boxed(a0, boxes)
+ l0 = self.make_sure_var_in_reg(a0, boxes)
if not imm_a1:
- l1 = self._ensure_value_is_boxed(a1, boxes)
+ l1 = self.make_sure_var_in_reg(a1, boxes)
else:
l1 = self.convert_to_imm(a1)
assert op.result is None
@@ -699,7 +683,7 @@
def prepare_op_guard_exception(self, op, fcond):
boxes = op.getarglist()
arg0 = ConstInt(rffi.cast(lltype.Signed, op.getarg(0).getint()))
- loc = self._ensure_value_is_boxed(arg0)
+ loc = self.make_sure_var_in_reg(arg0)
loc1 = self.get_scratch_reg(INT, boxes)
if op.result in self.longevity:
resloc = self.force_allocate_reg(op.result, boxes)
@@ -713,7 +697,7 @@
return arglocs
def prepare_op_guard_no_exception(self, op, fcond):
- loc = self._ensure_value_is_boxed(
+ loc = self.make_sure_var_in_reg(
ConstInt(self.cpu.pos_exception()))
arglocs = self._prepare_guard(op, [loc])
return arglocs
@@ -727,7 +711,7 @@
assert isinstance(op.getarg(0), Box)
boxes = op.getarglist()
- x = self._ensure_value_is_boxed(boxes[0], boxes)
+ x = self.make_sure_var_in_reg(boxes[0], boxes)
y_val = rffi.cast(lltype.Signed, op.getarg(1).getint())
arglocs = [x, None, None]
@@ -837,8 +821,8 @@
boxes = op.getarglist()
a0, a1 = boxes
ofs, size, sign = unpack_fielddescr(op.getdescr())
- base_loc = self._ensure_value_is_boxed(a0, boxes)
- value_loc = self._ensure_value_is_boxed(a1, boxes)
+ base_loc = self.make_sure_var_in_reg(a0, boxes)
+ value_loc = self.make_sure_var_in_reg(a1, boxes)
if check_imm_arg(ofs):
ofs_loc = imm(ofs)
else:
@@ -851,7 +835,7 @@
def prepare_op_getfield_gc(self, op, fcond):
a0 = op.getarg(0)
ofs, size, sign = unpack_fielddescr(op.getdescr())
- base_loc = self._ensure_value_is_boxed(a0)
+ base_loc = self.make_sure_var_in_reg(a0)
immofs = imm(ofs)
if check_imm_arg(ofs):
ofs_loc = immofs
@@ -871,8 +855,8 @@
t = unpack_interiorfielddescr(op.getdescr())
ofs, itemsize, fieldsize, sign = t
args = op.getarglist()
- base_loc = self._ensure_value_is_boxed(op.getarg(0), args)
- index_loc = self._ensure_value_is_boxed(op.getarg(1), args)
+ base_loc = self.make_sure_var_in_reg(op.getarg(0), args)
+ index_loc = self.make_sure_var_in_reg(op.getarg(1), args)
immofs = imm(ofs)
if check_imm_arg(ofs):
ofs_loc = immofs
@@ -889,9 +873,9 @@
t = unpack_interiorfielddescr(op.getdescr())
ofs, itemsize, fieldsize, sign = t
args = op.getarglist()
- base_loc = self._ensure_value_is_boxed(op.getarg(0), args)
- index_loc = self._ensure_value_is_boxed(op.getarg(1), args)
- value_loc = self._ensure_value_is_boxed(op.getarg(2), args)
+ base_loc = self.make_sure_var_in_reg(op.getarg(0), args)
+ index_loc = self.make_sure_var_in_reg(op.getarg(1), args)
+ value_loc = self.make_sure_var_in_reg(op.getarg(2), args)
immofs = imm(ofs)
if check_imm_arg(ofs):
ofs_loc = immofs
@@ -907,7 +891,7 @@
assert isinstance(arraydescr, ArrayDescr)
ofs = arraydescr.lendescr.offset
arg = op.getarg(0)
- base_loc = self._ensure_value_is_boxed(arg)
+ base_loc = self.make_sure_var_in_reg(arg)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
res = self.force_allocate_reg(op.result)
@@ -917,9 +901,9 @@
size, ofs, _ = unpack_arraydescr(op.getdescr())
scale = get_scale(size)
args = op.getarglist()
- base_loc = self._ensure_value_is_boxed(args[0], args)
- ofs_loc = self._ensure_value_is_boxed(args[1], args)
- value_loc = self._ensure_value_is_boxed(args[2], args)
+ base_loc = self.make_sure_var_in_reg(args[0], args)
+ ofs_loc = self.make_sure_var_in_reg(args[1], args)
+ value_loc = self.make_sure_var_in_reg(args[2], args)
assert check_imm_arg(ofs)
return [value_loc, base_loc, ofs_loc, imm(scale), imm(ofs)]
prepare_op_setarrayitem_raw = prepare_op_setarrayitem_gc
@@ -929,8 +913,8 @@
boxes = op.getarglist()
size, ofs, _ = unpack_arraydescr(op.getdescr())
scale = get_scale(size)
- base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
- ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
+ base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+ ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
res = self.force_allocate_reg(op.result)
@@ -944,7 +928,7 @@
def prepare_op_strlen(self, op, fcond):
args = op.getarglist()
- l0 = self._ensure_value_is_boxed(op.getarg(0))
+ l0 = self.make_sure_var_in_reg(op.getarg(0))
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
self.cpu.translate_support_code)
immofs = imm(ofs_length)
@@ -963,14 +947,14 @@
def prepare_op_strgetitem(self, op, fcond):
boxes = op.getarglist()
- base_loc = self._ensure_value_is_boxed(boxes[0])
+ base_loc = self.make_sure_var_in_reg(boxes[0])
a1 = boxes[1]
imm_a1 = check_imm_box(a1)
if imm_a1:
ofs_loc = self.convert_to_imm(a1)
else:
- ofs_loc = self._ensure_value_is_boxed(a1, boxes)
+ ofs_loc = self.make_sure_var_in_reg(a1, boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
@@ -983,9 +967,9 @@
def prepare_op_strsetitem(self, op, fcond):
boxes = op.getarglist()
- base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
- ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
- value_loc = self._ensure_value_is_boxed(boxes[2], boxes)
+ base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+ ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
+ value_loc = self.make_sure_var_in_reg(boxes[2], boxes)
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
self.cpu.translate_support_code)
assert itemsize == 1
@@ -995,7 +979,7 @@
prepare_op_copyunicodecontent = void
def prepare_op_unicodelen(self, op, fcond):
- l0 = self._ensure_value_is_boxed(op.getarg(0))
+ l0 = self.make_sure_var_in_reg(op.getarg(0))
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
self.cpu.translate_support_code)
immofs = imm(ofs_length)
@@ -1012,8 +996,8 @@
def prepare_op_unicodegetitem(self, op, fcond):
boxes = op.getarglist()
- base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
- ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
+ base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+ ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
@@ -1027,9 +1011,9 @@
def prepare_op_unicodesetitem(self, op, fcond):
boxes = op.getarglist()
- base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
- ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
- value_loc = self._ensure_value_is_boxed(boxes[2], boxes)
+ base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+ ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
+ value_loc = self.make_sure_var_in_reg(boxes[2], boxes)
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
self.cpu.translate_support_code)
scale = itemsize / 2
@@ -1042,7 +1026,7 @@
if imm_arg:
argloc = self.convert_to_imm(arg)
else:
- argloc = self._ensure_value_is_boxed(arg)
+ argloc = self.make_sure_var_in_reg(arg)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
resloc = self.force_allocate_reg(op.result)
@@ -1093,7 +1077,7 @@
# twice from the memory.
N = op.numargs()
args = op.getarglist()
- arglocs = [self._ensure_value_is_boxed(op.getarg(i), args)
+ arglocs = [self.make_sure_var_in_reg(op.getarg(i), args)
for i in range(N)]
tmp = self.get_scratch_reg(INT, args)
assert tmp not in arglocs
@@ -1215,7 +1199,7 @@
float_result=False, name='prepare_guard_float_ge')
def prepare_op_math_sqrt(self, op, fcond):
- loc = self._ensure_value_is_boxed(op.getarg(1))
+ loc = self.make_sure_var_in_reg(op.getarg(1))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
res = self.vfprm.force_allocate_reg(op.result)
@@ -1223,12 +1207,12 @@
return [loc, res]
def prepare_op_cast_float_to_int(self, op, fcond):
- loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ loc1 = self.make_sure_var_in_reg(op.getarg(0))
res = self.rm.force_allocate_reg(op.result)
return [loc1, res]
def prepare_op_cast_int_to_float(self, op, fcond):
- loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ loc1 = self.make_sure_var_in_reg(op.getarg(0))
res = self.vfprm.force_allocate_reg(op.result)
return [loc1, res]
@@ -1247,12 +1231,12 @@
return [loc, res]
def prepare_op_cast_float_to_singlefloat(self, op, fcond):
- loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ loc1 = self.make_sure_var_in_reg(op.getarg(0))
res = self.force_allocate_reg(op.result)
return [loc1, res]
-
+
def prepare_op_cast_singlefloat_to_float(self, op, fcond):
- loc1 = self._ensure_value_is_boxed(op.getarg(0))
+ loc1 = self.make_sure_var_in_reg(op.getarg(0))
res = self.force_allocate_reg(op.result)
return [loc1, res]
diff --git a/pypy/jit/backend/arm/runner.py b/pypy/jit/backend/arm/runner.py
--- a/pypy/jit/backend/arm/runner.py
+++ b/pypy/jit/backend/arm/runner.py
@@ -23,15 +23,21 @@
AbstractLLCPU.__init__(self, rtyper, stats, opts,
translate_support_code, gcdescr)
+ from pypy.jit.backend.llsupport import jitframe
+ self.deadframe_size_max = llmemory.sizeof(jitframe.DEADFRAME,
+ self.get_failargs_limit())
+
def set_debug(self, flag):
return self.assembler.set_debug(flag)
+ def get_failargs_limit(self):
+ if self.opts is not None:
+ return self.opts.failargs_limit
+ else:
+ return 1000
+
def setup(self):
- if self.opts is not None:
- failargs_limit = self.opts.failargs_limit
- else:
- failargs_limit = 1000
- self.assembler = AssemblerARM(self, failargs_limit=failargs_limit)
+ self.assembler = AssemblerARM(self, self.translate_support_code)
def setup_once(self):
self.assembler.setup_once()
@@ -51,24 +57,6 @@
return self.assembler.assemble_bridge(faildescr, inputargs, operations,
original_loop_token, log=log)
- def get_latest_value_float(self, index):
- return self.assembler.fail_boxes_float.getitem(index)
-
- def get_latest_value_int(self, index):
- return self.assembler.fail_boxes_int.getitem(index)
-
- def get_latest_value_ref(self, index):
- return self.assembler.fail_boxes_ptr.getitem(index)
-
- def get_latest_value_count(self):
- return self.assembler.fail_boxes_count
-
- def get_latest_force_token(self):
- return self.assembler.fail_force_index
-
- def get_on_leave_jitted_hook(self):
- return self.assembler.leave_jitted_hook
-
def clear_latest_values(self, count):
setitem = self.assembler.fail_boxes_ptr.setitem
null = lltype.nullptr(llmemory.GCREF.TO)
@@ -76,7 +64,7 @@
setitem(index, null)
def make_execute_token(self, *ARGS):
- FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, lltype.Signed))
+ FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, llmemory.GCREF))
def execute_token(executable_token, *args):
clt = executable_token.compiled_loop_token
@@ -91,12 +79,13 @@
prev_interpreter = LLInterpreter.current_interpreter
LLInterpreter.current_interpreter = self.debug_ll_interpreter
try:
- fail_index = func(*args)
+ deadframe = func(*args)
finally:
if not self.translate_support_code:
LLInterpreter.current_interpreter = prev_interpreter
#llop.debug_print(lltype.Void, "<<<< Back")
- return self.get_fail_descr_from_number(fail_index)
+ self.gc_set_extra_threshold()
+ return deadframe
return execute_token
def cast_ptr_to_int(x):
@@ -115,17 +104,22 @@
assert fail_index >= 0, "already forced!"
faildescr = self.get_fail_descr_from_number(fail_index)
rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
- bytecode = self.assembler._find_failure_recovery_bytecode(faildescr)
+ frb = self.assembler._find_failure_recovery_bytecode(faildescr)
+ bytecode = rffi.cast(rffi.UCHARP, frb)
addr_all_null_regsiters = rffi.cast(rffi.LONG, self.all_null_registers)
- # start of "no gc operation!" block
- fail_index_2 = self.assembler.failure_recovery_func(
- bytecode,
- addr_of_force_index,
- addr_all_null_regsiters)
- self.assembler.leave_jitted_hook()
- # end of "no gc operation!" block
- assert fail_index == fail_index_2
- return faildescr
+ #
+ assert (rffi.cast(lltype.Signed, bytecode[0]) ==
+ self.assembler.CODE_FORCED)
+ bytecode = rffi.ptradd(bytecode, 1)
+ deadframe = self.assembler.grab_frame_values(self,
+ bytecode, addr_of_force_index,
+ self.all_null_registers,
+ self.all_null_registers)
+ #
+ assert self.get_latest_descr(deadframe) is faildescr
+ self.assembler.force_token_to_dead_frame[addr_of_force_index] = (
+ deadframe)
+ return deadframe
def redirect_call_assembler(self, oldlooptoken, newlooptoken):
self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
diff --git a/pypy/jit/backend/arm/test/test_gc_integration.py b/pypy/jit/backend/arm/test/test_gc_integration.py
--- a/pypy/jit/backend/arm/test/test_gc_integration.py
+++ b/pypy/jit/backend/arm/test/test_gc_integration.py
@@ -2,25 +2,13 @@
More information about the pypy-commit
mailing list