[pypy-commit] pypy py3.5: hg merge default
arigo
pypy.commits at gmail.com
Mon Nov 28 12:34:18 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r88711:c8b4b78af01a
Date: 2016-11-28 18:33 +0100
http://bitbucket.org/pypy/pypy/changeset/c8b4b78af01a/
Log: hg merge default
diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py
--- a/lib-python/2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/2.7/distutils/sysconfig_pypy.py
@@ -74,6 +74,19 @@
g['LIBDIR'] = os.path.join(sys.prefix, 'lib')
g['VERSION'] = get_python_version()
+ if sys.platform[:6] == "darwin":
+ import platform
+ if platform.machine() == 'i386':
+ if platform.architecture()[0] == '32bit':
+ arch = 'i386'
+ else:
+ arch = 'x86_64'
+ else:
+ # just a guess
+ arch = platform.machine()
+ g['LDSHARED'] += ' -undefined dynamic_lookup'
+ g['CC'] += ' -arch %s' % (arch,)
+
global _config_vars
_config_vars = g
@@ -109,6 +122,12 @@
_config_vars['prefix'] = PREFIX
_config_vars['exec_prefix'] = EXEC_PREFIX
+ # OS X platforms require special customization to handle
+ # multi-architecture, multi-os-version installers
+ if sys.platform == 'darwin':
+ import _osx_support
+ _osx_support.customize_config_vars(_config_vars)
+
if args:
vals = []
for name in args:
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
@@ -34,3 +34,7 @@
Add jit.conditional_call_elidable(), a way to tell the JIT "conditonally
call this function" returning a result.
+
+.. branch: desc-specialize
+
+Refactor FunctionDesc.specialize() and related code (RPython annotator).
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -302,6 +302,12 @@
elif config.objspace.usemodules.pypyjit:
config.translation.jit = True
+ if config.objspace.usemodules.cpyext:
+ if config.translation.gc != 'incminimark':
+ raise Exception("The 'cpyext' module requires the 'incminimark'"
+ " GC. You need either 'targetpypystandalone.py"
+ " --withoutmod-cpyext' or '--gc=incminimark'")
+
config.translating = True
import translate
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -559,6 +559,7 @@
space.wrap(msg))
return OperationError(exc, w_error)
+ at specialize.arg(3)
def wrap_oserror2(space, e, w_filename=None, exception_name='w_OSError',
w_exception_class=None):
assert isinstance(e, OSError)
@@ -586,8 +587,8 @@
w_error = space.call_function(exc, space.wrap(errno),
space.wrap(msg))
return OperationError(exc, w_error)
-wrap_oserror2._annspecialcase_ = 'specialize:arg(3)'
+ at specialize.arg(3)
def wrap_oserror(space, e, filename=None, exception_name='w_OSError',
w_exception_class=None):
if filename is not None:
@@ -598,7 +599,6 @@
return wrap_oserror2(space, e, None,
exception_name=exception_name,
w_exception_class=w_exception_class)
-wrap_oserror._annspecialcase_ = 'specialize:arg(3)'
def exception_from_saved_errno(space, w_type):
from rpython.rlib.rposix import get_saved_errno
diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py
--- a/pypy/module/_collections/interp_deque.py
+++ b/pypy/module/_collections/interp_deque.py
@@ -1,4 +1,5 @@
import sys
+from rpython.rlib.objectmodel import specialize
from pypy.interpreter import gateway
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.typedef import TypeDef, make_weakref_descr
@@ -7,7 +8,6 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.objspace.std.sliceobject import unwrap_start_stop
from rpython.rlib.debug import check_nonneg
-from rpython.rlib.objectmodel import specialize
# A `dequeobject` is composed of a doubly-linked list of `block` nodes.
diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -124,13 +124,13 @@
assert isinstance(w_obj, FakeFloat)
return w_obj.val
+ @specialize.arg(1)
def interp_w(self, RequiredClass, w_obj, can_be_None=False):
if can_be_None and w_obj is None:
return None
if not isinstance(w_obj, RequiredClass):
raise TypeError
return w_obj
- interp_w._annspecialcase_ = 'specialize:arg(1)'
def getarg_w(self, code, w_obj): # for retrieving buffers
return FakeBuffer(w_obj)
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -35,8 +35,6 @@
from rpython.rlib.objectmodel import specialize
from pypy.module import exceptions
from pypy.module.exceptions import interp_exceptions
-# CPython 2.4 compatibility
-from py.builtin import BaseException
from rpython.tool.sourcetools import func_with_new_name
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rlib import rawrefcount
@@ -1622,9 +1620,8 @@
miniglobals = {'__name__': __name__, # for module name propagation
}
exec source.compile() in miniglobals
- call_external_function = miniglobals['cpy_call_external']
+ call_external_function = specialize.ll()(miniglobals['cpy_call_external'])
call_external_function._dont_inline_ = True
- call_external_function._annspecialcase_ = 'specialize:ll'
call_external_function._gctransformer_hint_close_stack_ = True
# don't inline, as a hack to guarantee that no GC pointer is alive
# anywhere in call_external_function
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -15,6 +15,7 @@
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rtyper.annlowlevel import llhelper
from rpython.rlib import rawrefcount
+from rpython.rlib.debug import fatalerror
#________________________________________________________
@@ -192,6 +193,8 @@
rawrefcount.create_link_pypy(w_obj, py_obj)
+w_marker_deallocating = W_Root()
+
def from_ref(space, ref):
"""
Finds the interpreter object corresponding to the given reference. If the
@@ -202,7 +205,23 @@
return None
w_obj = rawrefcount.to_obj(W_Root, ref)
if w_obj is not None:
- return w_obj
+ if w_obj is not w_marker_deallocating:
+ return w_obj
+ fatalerror(
+ "*** Invalid usage of a dying CPython object ***\n"
+ "\n"
+ "cpyext, the emulation layer, detected that while it is calling\n"
+ "an object's tp_dealloc, the C code calls back a function that\n"
+ "tries to recreate the PyPy version of the object. Usually it\n"
+ "means that tp_dealloc calls some general PyXxx() API. It is\n"
+ "a dangerous and potentially buggy thing to do: even in CPython\n"
+ "the PyXxx() function could, in theory, cause a reference to the\n"
+ "object to be taken and stored somewhere, for an amount of time\n"
+ "exceeding tp_dealloc itself. Afterwards, the object will be\n"
+ "freed, making that reference point to garbage.\n"
+ ">>> PyPy could contain some workaround to still work if\n"
+ "you are lucky, but it is not done so far; better fix the bug in\n"
+ "the CPython extension.")
# This reference is not yet a real interpreter object.
# Realize it.
@@ -233,7 +252,8 @@
INTERPLEVEL_API['as_pyobj'] = as_pyobj
def pyobj_has_w_obj(pyobj):
- return rawrefcount.to_obj(W_Root, pyobj) is not None
+ w_obj = rawrefcount.to_obj(W_Root, pyobj)
+ return w_obj is not None and w_obj is not w_marker_deallocating
INTERPLEVEL_API['pyobj_has_w_obj'] = staticmethod(pyobj_has_w_obj)
@@ -335,6 +355,7 @@
pto = obj.c_ob_type
#print >>sys.stderr, "Calling dealloc slot", pto.c_tp_dealloc, "of", obj, \
# "'s type which is", rffi.charp2str(pto.c_tp_name)
+ rawrefcount.mark_deallocating(w_marker_deallocating, obj)
generic_cpy_call(space, pto.c_tp_dealloc, obj)
@cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL)
diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -4,11 +4,11 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.unicodehelper import encode_utf8
from rpython.rlib import rgc, jit
+from rpython.rlib.objectmodel import specialize
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rtyper.tool import rffi_platform
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.translator.platform import platform
-from rpython.rlib.objectmodel import specialize
import sys
import weakref
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -208,6 +208,7 @@
def newunicode(self, x):
return w_some_obj()
+ @specialize.argtype(1)
def wrap(self, x):
if not we_are_translated():
if isinstance(x, gateway.interp2app):
@@ -221,7 +222,6 @@
return w_some_obj()
self._wrap_not_rpython(x)
return w_some_obj()
- wrap._annspecialcase_ = "specialize:argtype(1)"
def _wrap_not_rpython(self, x):
"NOT_RPYTHON"
@@ -314,10 +314,10 @@
is_root(w_complex)
return 1.1, 2.2
+ @specialize.arg(1)
def allocate_instance(self, cls, w_subtype):
is_root(w_subtype)
return instantiate(cls)
- allocate_instance._annspecialcase_ = "specialize:arg(1)"
def decode_index(self, w_index_or_slice, seqlength):
is_root(w_index_or_slice)
diff --git a/pypy/objspace/fake/test/test_checkmodule.py b/pypy/objspace/fake/test/test_checkmodule.py
--- a/pypy/objspace/fake/test/test_checkmodule.py
+++ b/pypy/objspace/fake/test/test_checkmodule.py
@@ -9,9 +9,9 @@
def make_checker():
check = []
+ @specialize.memo()
def see():
check.append(True)
- see._annspecialcase_ = 'specialize:memo'
return see, check
def test_wrap_interp2app():
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -2,12 +2,12 @@
import sys
from rpython.rlib import jit
+from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import INT_MAX
from rpython.rlib.rfloat import DTSF_ALT, formatd, isnan, isinf
from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
from rpython.rlib.unroll import unrolling_iterable
from rpython.tool.sourcetools import func_with_new_name
-from rpython.rlib.objectmodel import specialize
from pypy.interpreter.error import OperationError, oefmt
diff --git a/pypy/tool/cpyext/extbuild.py b/pypy/tool/cpyext/extbuild.py
--- a/pypy/tool/cpyext/extbuild.py
+++ b/pypy/tool/cpyext/extbuild.py
@@ -206,6 +206,10 @@
pass
from distutils.ccompiler import new_compiler
from distutils import sysconfig
+
+ # XXX for Darwin running old versions of CPython 2.7.x
+ sysconfig.get_config_vars()
+
compiler = new_compiler(force=1)
sysconfig.customize_compiler(compiler) # XXX
objects = []
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -2,6 +2,7 @@
import types
from collections import defaultdict
+from contextlib import contextmanager
from rpython.tool.ansi_print import AnsiLogger
from rpython.tool.pairtype import pair
@@ -83,22 +84,17 @@
annmodel.TLS.check_str_without_nul = (
self.translator.config.translation.check_str_without_nul)
- flowgraph, inputs_s = self.get_call_parameters(function, args_s, policy)
+ with self.using_policy(policy):
+ flowgraph, inputs_s = self.get_call_parameters(function, args_s)
if main_entry_point:
self.translator.entry_point_graph = flowgraph
return self.build_graph_types(flowgraph, inputs_s, complete_now=complete_now)
- def get_call_parameters(self, function, args_s, policy):
- desc = self.bookkeeper.getdesc(function)
- prevpolicy = self.policy
- self.policy = policy
- self.bookkeeper.enter(None)
- try:
+ def get_call_parameters(self, function, args_s):
+ with self.bookkeeper.at_position(None):
+ desc = self.bookkeeper.getdesc(function)
return desc.get_call_parameters(args_s)
- finally:
- self.bookkeeper.leave()
- self.policy = prevpolicy
def annotate_helper(self, function, args_s, policy=None):
if policy is None:
@@ -107,21 +103,29 @@
# XXX hack
annmodel.TLS.check_str_without_nul = (
self.translator.config.translation.check_str_without_nul)
- graph, inputcells = self.get_call_parameters(function, args_s, policy)
- self.build_graph_types(graph, inputcells, complete_now=False)
- self.complete_helpers(policy)
+ with self.using_policy(policy):
+ graph, inputcells = self.get_call_parameters(function, args_s)
+ self.build_graph_types(graph, inputcells, complete_now=False)
+ self.complete_helpers()
return graph
- def complete_helpers(self, policy):
- saved = self.policy, self.added_blocks
- self.policy = policy
+ def complete_helpers(self):
+ saved = self.added_blocks
+ self.added_blocks = {}
try:
- self.added_blocks = {}
self.complete()
# invoke annotation simplifications for the new blocks
self.simplify(block_subset=self.added_blocks)
finally:
- self.policy, self.added_blocks = saved
+ self.added_blocks = saved
+
+ @contextmanager
+ def using_policy(self, policy):
+ """A context manager that temporarily replaces the annotator policy"""
+ old_policy = self.policy
+ self.policy = policy
+ yield
+ self.policy = old_policy
def build_graph_types(self, flowgraph, inputcells, complete_now=True):
checkgraph(flowgraph)
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -9,6 +9,7 @@
from collections import OrderedDict
from rpython.flowspace.model import Constant
+from rpython.flowspace.bytecode import cpython_code_signature
from rpython.annotator.model import (
SomeOrderedDict, SomeString, SomeChar, SomeFloat, unionof, SomeInstance,
SomeDict, SomeBuiltin, SomePBC, SomeInteger, TLS, SomeUnicodeCodePoint,
@@ -21,6 +22,7 @@
from rpython.annotator import description
from rpython.annotator.signature import annotationoftype
from rpython.annotator.argument import simple_args
+from rpython.annotator.specialize import memo
from rpython.rlib.objectmodel import r_dict, r_ordereddict, Symbolic
from rpython.tool.algo.unionfind import UnionFind
from rpython.rtyper import extregistry
@@ -358,7 +360,7 @@
return self.descs[obj_key]
except KeyError:
if isinstance(pyobj, types.FunctionType):
- result = description.FunctionDesc(self, pyobj)
+ result = self.newfuncdesc(pyobj)
elif isinstance(pyobj, (type, types.ClassType)):
if pyobj is object:
raise Exception("ClassDesc for object not supported")
@@ -403,6 +405,23 @@
self.descs[obj_key] = result
return result
+ def newfuncdesc(self, pyfunc):
+ name = pyfunc.__name__
+ if hasattr(pyfunc, '_generator_next_method_of_'):
+ from rpython.flowspace.argument import Signature
+ signature = Signature(['entry']) # haaaaaack
+ defaults = ()
+ else:
+ signature = cpython_code_signature(pyfunc.func_code)
+ defaults = pyfunc.func_defaults
+ # get the specializer based on the tag of the 'pyobj'
+ # (if any), according to the current policy
+ tag = getattr(pyfunc, '_annspecialcase_', None)
+ specializer = self.annotator.policy.get_specializer(tag)
+ if specializer is memo:
+ return description.MemoDesc(self, pyfunc, name, signature, defaults, specializer)
+ return description.FunctionDesc(self, pyfunc, name, signature, defaults, specializer)
+
def getfrozen(self, pyobj):
return description.FrozenDesc(self, pyobj)
diff --git a/rpython/annotator/classdesc.py b/rpython/annotator/classdesc.py
--- a/rpython/annotator/classdesc.py
+++ b/rpython/annotator/classdesc.py
@@ -608,7 +608,7 @@
if mixin:
# make a new copy of the FunctionDesc for this class,
# but don't specialize further for all subclasses
- funcdesc = FunctionDesc(self.bookkeeper, value)
+ funcdesc = self.bookkeeper.newfuncdesc(value)
self.classdict[name] = funcdesc
return
# NB. if value is, say, AssertionError.__init__, then we
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -3,11 +3,10 @@
from rpython.annotator.signature import (
enforce_signature_args, enforce_signature_return, finish_type)
from rpython.flowspace.model import FunctionGraph
-from rpython.flowspace.bytecode import cpython_code_signature
from rpython.annotator.argument import rawshape, ArgErr, simple_args
from rpython.tool.sourcetools import valid_identifier
from rpython.tool.pairtype import extendabletype
-from rpython.annotator.model import AnnotatorError, s_ImpossibleValue
+from rpython.annotator.model import AnnotatorError, s_ImpossibleValue, unionof
class CallFamily(object):
"""A family of Desc objects that could be called from common call sites.
@@ -117,7 +116,6 @@
self.s_value = s_ImpossibleValue # union of possible values
def update(self, other):
- from rpython.annotator.model import unionof
self.descs.update(other.descs)
self.read_locations.update(other.read_locations)
self.s_value = unionof(self.s_value, other.s_value)
@@ -192,24 +190,12 @@
class FunctionDesc(Desc):
knowntype = types.FunctionType
- def __init__(self, bookkeeper, pyobj=None,
- name=None, signature=None, defaults=None,
+ def __init__(self, bookkeeper, pyobj, name, signature, defaults,
specializer=None):
super(FunctionDesc, self).__init__(bookkeeper, pyobj)
- if name is None:
- name = pyobj.func_name
- if signature is None:
- if hasattr(pyobj, '_generator_next_method_of_'):
- from rpython.flowspace.argument import Signature
- signature = Signature(['entry']) # haaaaaack
- defaults = ()
- else:
- signature = cpython_code_signature(pyobj.func_code)
- if defaults is None:
- defaults = pyobj.func_defaults
self.name = name
self.signature = signature
- self.defaults = defaults or ()
+ self.defaults = defaults if defaults is not None else ()
# 'specializer' is a function with the following signature:
# specializer(funcdesc, args_s) => graph
# or => s_result (overridden/memo cases)
@@ -288,12 +274,43 @@
getattr(self.bookkeeper, "position_key", None) is not None):
_, block, i = self.bookkeeper.position_key
op = block.operations[i]
- if self.specializer is None:
- # get the specializer based on the tag of the 'pyobj'
- # (if any), according to the current policy
- tag = getattr(self.pyobj, '_annspecialcase_', None)
- policy = self.bookkeeper.annotator.policy
- self.specializer = policy.get_specializer(tag)
+ self.normalize_args(inputcells)
+ if getattr(self.pyobj, '_annspecialcase_', '').endswith("call_location"):
+ return self.specializer(self, inputcells, op)
+ else:
+ return self.specializer(self, inputcells)
+
+ def pycall(self, whence, args, s_previous_result, op=None):
+ inputcells = self.parse_arguments(args)
+ graph = self.specialize(inputcells, op)
+ assert isinstance(graph, FunctionGraph)
+ # if that graph has a different signature, we need to re-parse
+ # the arguments.
+ # recreate the args object because inputcells may have been changed
+ new_args = args.unmatch_signature(self.signature, inputcells)
+ inputcells = self.parse_arguments(new_args, graph)
+ annotator = self.bookkeeper.annotator
+ result = annotator.recursivecall(graph, whence, inputcells)
+ signature = getattr(self.pyobj, '_signature_', None)
+ if signature:
+ sigresult = enforce_signature_return(self, signature[1], result)
+ if sigresult is not None:
+ 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:
+ result = unionof(result, s_previous_result)
+ return result
+
+ def normalize_args(self, inputs_s):
+ """
+ Canonicalize argument annotations into the exact parameter
+ annotations of a specific specialized graph.
+
+ Note: this method has no return value but mutates its argument instead.
+ """
enforceargs = getattr(self.pyobj, '_annenforceargs_', None)
signature = getattr(self.pyobj, '_signature_', None)
if enforceargs and signature:
@@ -304,39 +321,9 @@
from rpython.annotator.signature import Sig
enforceargs = Sig(*enforceargs)
self.pyobj._annenforceargs_ = enforceargs
- enforceargs(self, inputcells) # can modify inputcells in-place
+ enforceargs(self, inputs_s) # can modify inputs_s in-place
if signature:
- enforce_signature_args(self, signature[0], inputcells) # mutates inputcells
- if getattr(self.pyobj, '_annspecialcase_', '').endswith("call_location"):
- return self.specializer(self, inputcells, op)
- else:
- return self.specializer(self, inputcells)
-
- def pycall(self, whence, args, s_previous_result, op=None):
- inputcells = self.parse_arguments(args)
- result = self.specialize(inputcells, op)
- if isinstance(result, FunctionGraph):
- graph = result # common case
- annotator = self.bookkeeper.annotator
- # if that graph has a different signature, we need to re-parse
- # the arguments.
- # recreate the args object because inputcells may have been changed
- new_args = args.unmatch_signature(self.signature, inputcells)
- inputcells = self.parse_arguments(new_args, graph)
- result = annotator.recursivecall(graph, whence, inputcells)
- signature = getattr(self.pyobj, '_signature_', None)
- if signature:
- sigresult = enforce_signature_return(self, signature[1], result)
- if sigresult is not None:
- 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:
- from rpython.annotator.model import unionof
- result = unionof(result, s_previous_result)
- return result
+ enforce_signature_args(self, signature[0], inputs_s) # mutates inputs_s
def get_graph(self, args, op):
inputs_s = self.parse_arguments(args)
@@ -405,6 +392,16 @@
return s_sigs
+class MemoDesc(FunctionDesc):
+ def pycall(self, whence, args, s_previous_result, op=None):
+ inputcells = self.parse_arguments(args)
+ s_result = self.specialize(inputcells, op)
+ if isinstance(s_result, FunctionGraph):
+ s_result = s_result.getreturnvar().annotation
+ s_result = unionof(s_result, s_previous_result)
+ return s_result
+
+
class MethodDesc(Desc):
knowntype = types.MethodType
diff --git a/rpython/annotator/specialize.py b/rpython/annotator/specialize.py
--- a/rpython/annotator/specialize.py
+++ b/rpython/annotator/specialize.py
@@ -3,11 +3,13 @@
from rpython.tool.sourcetools import func_with_new_name
from rpython.tool.algo.unionfind import UnionFind
-from rpython.flowspace.model import Block, Link, Variable, SpaceOperation
+from rpython.flowspace.model import Block, Link, Variable
from rpython.flowspace.model import checkgraph
from rpython.flowspace.operation import op
from rpython.annotator import model as annmodel
from rpython.flowspace.argument import Signature
+from rpython.annotator.model import SomePBC, SomeImpossibleValue, SomeBool
+from rpython.annotator.model import unionof
def flatten_star_args(funcdesc, args_s):
argnames, vararg, kwarg = funcdesc.signature
@@ -127,7 +129,6 @@
def finish(self):
if self.do_not_process:
return
- from rpython.annotator.model import unionof
assert self.graph is None, "MemoTable already finished"
# list of which argument positions can take more than one value
example_args, example_value = self.table.iteritems().next()
@@ -246,34 +247,36 @@
args_s.append(unionof(*values_s))
annotator.addpendinggraph(self.graph, args_s)
+def all_values(s):
+ """Return the exhaustive list of possible values matching annotation `s`.
-def memo(funcdesc, arglist_s):
- from rpython.annotator.model import SomePBC, SomeImpossibleValue, SomeBool
- from rpython.annotator.model import unionof
+ Raises `AnnotatorError` if no such (reasonably small) finite list exists.
+ """
+ if s.is_constant():
+ return [s.const]
+ elif isinstance(s, SomePBC):
+ values = []
+ assert not s.can_be_None, "memo call: cannot mix None and PBCs"
+ for desc in s.descriptions:
+ if desc.pyobj is None:
+ raise annmodel.AnnotatorError(
+ "memo call with a class or PBC that has no "
+ "corresponding Python object (%r)" % (desc,))
+ values.append(desc.pyobj)
+ return values
+ elif isinstance(s, SomeImpossibleValue):
+ return []
+ elif isinstance(s, SomeBool):
+ return [False, True]
+ else:
+ raise annmodel.AnnotatorError("memo call: argument must be a class "
+ "or a frozen PBC, got %r" % (s,))
+
+def memo(funcdesc, args_s):
# call the function now, and collect possible results
- argvalues = []
- for s in arglist_s:
- if s.is_constant():
- values = [s.const]
- elif isinstance(s, SomePBC):
- values = []
- assert not s.can_be_None, "memo call: cannot mix None and PBCs"
- for desc in s.descriptions:
- if desc.pyobj is None:
- raise annmodel.AnnotatorError(
- "memo call with a class or PBC that has no "
- "corresponding Python object (%r)" % (desc,))
- values.append(desc.pyobj)
- elif isinstance(s, SomeImpossibleValue):
- return s # we will probably get more possible args later
- elif isinstance(s, SomeBool):
- values = [False, True]
- else:
- raise annmodel.AnnotatorError("memo call: argument must be a class "
- "or a frozen PBC, got %r" % (s,))
- argvalues.append(values)
+
# the list of all possible tuples of arguments to give to the memo function
- possiblevalues = cartesian_product(argvalues)
+ possiblevalues = cartesian_product([all_values(s_arg) for s_arg in args_s])
# a MemoTable factory -- one MemoTable per family of arguments that can
# be called together, merged via a UnionFind.
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -2936,6 +2936,12 @@
self._pyobj(pyobject).ob_pypy_link = objint
# there is no rrc_o_dict
+ def rawrefcount_mark_deallocating(self, gcobj, pyobject):
+ ll_assert(self.rrc_enabled, "rawrefcount.init not called")
+ obj = llmemory.cast_ptr_to_adr(gcobj) # should be a prebuilt obj
+ objint = llmemory.cast_adr_to_int(obj, "symbolic")
+ self._pyobj(pyobject).ob_pypy_link = objint
+
def rawrefcount_from_obj(self, gcobj):
obj = llmemory.cast_ptr_to_adr(gcobj)
if self.is_in_nursery(obj):
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -476,6 +476,10 @@
GCClass.rawrefcount_create_link_pyobj,
[s_gc, s_gcref, SomeAddress()],
annmodel.s_None)
+ self.rawrefcount_mark_deallocating = getfn(
+ GCClass.rawrefcount_mark_deallocating,
+ [s_gc, s_gcref, SomeAddress()],
+ annmodel.s_None)
self.rawrefcount_from_obj_ptr = getfn(
GCClass.rawrefcount_from_obj, [s_gc, s_gcref], SomeAddress(),
inline = True)
@@ -1281,6 +1285,14 @@
[self.rawrefcount_create_link_pyobj_ptr, self.c_const_gc,
v_gcobj, v_pyobject])
+ def gct_gc_rawrefcount_mark_deallocating(self, hop):
+ [v_gcobj, v_pyobject] = hop.spaceop.args
+ assert v_gcobj.concretetype == llmemory.GCREF
+ assert v_pyobject.concretetype == llmemory.Address
+ hop.genop("direct_call",
+ [self.rawrefcount_mark_deallocating, self.c_const_gc,
+ v_gcobj, v_pyobject])
+
def gct_gc_rawrefcount_from_obj(self, hop):
[v_gcobj] = hop.spaceop.args
assert v_gcobj.concretetype == llmemory.GCREF
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -3,7 +3,7 @@
import py
from rpython.rlib.nonconst import NonConstant
-from rpython.rlib.objectmodel import CDefinedIntSymbolic, keepalive_until_here, specialize, not_rpython
+from rpython.rlib.objectmodel import CDefinedIntSymbolic, keepalive_until_here, specialize, not_rpython, we_are_translated
from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.tool.sourcetools import rpython_wrapper
@@ -1221,7 +1221,8 @@
x = jit.conditional_call_elidable(self.cache, _compute_and_cache, ...)
"""
- if we_are_jitted():
+ if we_are_translated() and we_are_jitted():
+ #^^^ the occasional test patches we_are_jitted() to True
return _jit_conditional_call_value(value, function, *args)
else:
if isinstance(value, int):
diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py
--- a/rpython/rlib/rarithmetic.py
+++ b/rpython/rlib/rarithmetic.py
@@ -25,6 +25,10 @@
lltype.Unsigned, widen it to lltype.Signed.
Useful because the translator doesn't support
arithmetic on the smaller types.
+ovfcheck_int32_add/sub/mul(x, y)
+ perform an add/sub/mul between two regular integers,
+ but assumes that they fit inside signed 32-bit ints
+ and raises OverflowError if the result no longer does
These are meant to be erased by translation, r_uint
in the process should mark unsigned values, ovfcheck should
@@ -796,6 +800,47 @@
return longlong2float(rffi.cast(rffi.LONGLONG, res))
return rffi.cast(T, res)
+if sys.maxint == 2147483647:
+ def ovfcheck_int32_add(x, y):
+ return ovfcheck(x + y)
+ def ovfcheck_int32_sub(x, y):
+ return ovfcheck(x - y)
+ def ovfcheck_int32_mul(x, y):
+ return ovfcheck(x * y)
+else:
+ def ovfcheck_int32_add(x, y):
+ """x and y are assumed to fit inside the 32-bit rffi.INT;
+ raises OverflowError if the result doesn't fit rffi.INT"""
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ x = rffi.cast(lltype.Signed, x)
+ y = rffi.cast(lltype.Signed, y)
+ z = x + y
+ if z != rffi.cast(lltype.Signed, rffi.cast(rffi.INT, z)):
+ raise OverflowError
+ return z
+
+ def ovfcheck_int32_sub(x, y):
+ """x and y are assumed to fit inside the 32-bit rffi.INT;
+ raises OverflowError if the result doesn't fit rffi.INT"""
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ x = rffi.cast(lltype.Signed, x)
+ y = rffi.cast(lltype.Signed, y)
+ z = x - y
+ if z != rffi.cast(lltype.Signed, rffi.cast(rffi.INT, z)):
+ raise OverflowError
+ return z
+
+ def ovfcheck_int32_mul(x, y):
+ """x and y are assumed to fit inside the 32-bit rffi.INT;
+ raises OverflowError if the result doesn't fit rffi.INT"""
+ from rpython.rtyper.lltypesystem import lltype, rffi
+ x = rffi.cast(lltype.Signed, x)
+ y = rffi.cast(lltype.Signed, y)
+ z = x * y
+ if z != rffi.cast(lltype.Signed, rffi.cast(rffi.INT, z)):
+ raise OverflowError
+ return z
+
# String parsing support
# ---------------------------
diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -36,6 +36,7 @@
_pypy2ob = {}
_pypy2ob_rev = {}
_d_list = []
+ _d_marker = None
_dealloc_trigger_callback = dealloc_trigger_callback
@not_rpython
@@ -62,6 +63,14 @@
_o_list.append(ob)
@not_rpython
+def mark_deallocating(marker, ob):
+ """mark the PyObject as deallocating, by storing 'marker'
+ inside its ob_pypy_link field"""
+ assert ob._obj not in _pypy2ob_rev
+ assert not ob.c_ob_pypy_link
+ ob.c_ob_pypy_link = _build_pypy_link(marker)
+
+ at not_rpython
def from_obj(OB_PTR_TYPE, p):
ob = _pypy2ob.get(p)
if ob is None:
@@ -221,7 +230,7 @@
class Entry(ExtRegistryEntry):
- _about_ = (create_link_pypy, create_link_pyobj)
+ _about_ = (create_link_pypy, create_link_pyobj, mark_deallocating)
def compute_result_annotation(self, s_p, s_ob):
pass
@@ -231,6 +240,8 @@
name = 'gc_rawrefcount_create_link_pypy'
elif self.instance is create_link_pyobj:
name = 'gc_rawrefcount_create_link_pyobj'
+ elif self.instance is mark_deallocating:
+ name = 'gc_rawrefcount_mark_deallocating'
v_p, v_ob = hop.inputargs(*hop.args_r)
hop.exception_cannot_occur()
hop.genop(name, [_unspec_p(hop, v_p), _unspec_ob(hop, v_ob)])
diff --git a/rpython/rlib/rjitlog/rjitlog.py b/rpython/rlib/rjitlog/rjitlog.py
--- a/rpython/rlib/rjitlog/rjitlog.py
+++ b/rpython/rlib/rjitlog/rjitlog.py
@@ -13,6 +13,7 @@
from rpython.jit.metainterp.resoperation import rop
from rpython.jit.metainterp.history import ConstInt, ConstFloat
from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.rarithmetic import r_longlong
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from rpython.rlib.objectmodel import compute_unique_id, always_inline
from rpython.rlib.objectmodel import we_are_translated, specialize
@@ -113,6 +114,7 @@
@always_inline
def encode_le_64bit(val):
+ val = r_longlong(val) # force 64-bit, even on 32-bit
return ''.join([chr((val >> 0) & 0xff),
chr((val >> 8) & 0xff),
chr((val >> 16) & 0xff),
diff --git a/rpython/rlib/rurandom.py b/rpython/rlib/rurandom.py
--- a/rpython/rlib/rurandom.py
+++ b/rpython/rlib/rurandom.py
@@ -75,16 +75,6 @@
return rffi.charpsize2str(rffi.cast(rffi.CCHARP, buf), n)
-elif 0: # __VMS
- from rpython.rlib.ropenssl import libssl_RAND_pseudo_bytes
- def init_urandom():
- pass
-
- def urandom(context, n):
- with rffi.scoped_alloc_buffer(n) as buf:
- if libssl_RAND_pseudo_bytes(self.raw, n) < 0:
- raise ValueError("RAND_pseudo_bytes")
- return buf.str(n)
else: # Posix implementation
@not_rpython
def init_urandom():
diff --git a/rpython/rlib/rvmprof/src/vmprof_getpc.h b/rpython/rlib/rvmprof/src/vmprof_getpc.h
--- a/rpython/rlib/rvmprof/src/vmprof_getpc.h
+++ b/rpython/rlib/rvmprof/src/vmprof_getpc.h
@@ -126,13 +126,14 @@
// how we'd get the PC (using StackWalk64?)
// http://msdn2.microsoft.com/en-us/library/ms680650.aspx
-#include "base/logging.h" // for RAW_LOG
-#ifndef HAVE_CYGWIN_SIGNAL_H
-typedef int ucontext_t;
-#endif
+// #include "base/logging.h" // for RAW_LOG
+// #ifndef HAVE_CYGWIN_SIGNAL_H
+// typedef int ucontext_t;
+// #endif
intptr_t GetPC(ucontext_t *signal_ucontext) {
- RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n");
+ // RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n");
+ fprintf(stderr, "GetPC is not yet implemented on Windows\n");
return NULL;
}
diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py
--- a/rpython/rlib/test/test_rarithmetic.py
+++ b/rpython/rlib/test/test_rarithmetic.py
@@ -675,3 +675,11 @@
assert a ^ r_uint32(42) == "a^42"
assert r_uint32(42) ** a == "42**a"
assert a ** r_uint32(42) == "a**42"
+
+def test_ovfcheck_int32():
+ assert ovfcheck_int32_add(-2**30, -2**30) == -2**31
+ py.test.raises(OverflowError, ovfcheck_int32_add, 2**30, 2**30)
+ assert ovfcheck_int32_sub(-2**30, 2**30) == -2**31
+ py.test.raises(OverflowError, ovfcheck_int32_sub, 2**30, -2**30)
+ assert ovfcheck_int32_mul(-2**16, 2**15) == -2**31
+ py.test.raises(OverflowError, ovfcheck_int32_mul, -2**16, -2**15)
diff --git a/rpython/rlib/test/test_rawrefcount.py b/rpython/rlib/test/test_rawrefcount.py
--- a/rpython/rlib/test/test_rawrefcount.py
+++ b/rpython/rlib/test/test_rawrefcount.py
@@ -212,6 +212,15 @@
assert rawrefcount.to_obj(W_Root, ob) == p
lltype.free(ob, flavor='raw')
+ def test_mark_deallocating(self):
+ ob = lltype.malloc(PyObjectS, flavor='raw', zero=True)
+ w_marker = W_Root(42)
+ rawrefcount.mark_deallocating(w_marker, ob)
+ assert rawrefcount.to_obj(W_Root, ob) is w_marker
+ rawrefcount._collect()
+ assert rawrefcount.to_obj(W_Root, ob) is w_marker
+ lltype.free(ob, flavor='raw')
+
class TestTranslated(StandaloneTests):
@@ -222,6 +231,7 @@
state.seen = []
def dealloc_trigger():
state.seen.append(1)
+ w_marker = W_Root(-1)
def make_p():
p = W_Root(42)
@@ -257,6 +267,13 @@
if rawrefcount.next_dead(PyObject) != lltype.nullptr(PyObjectS):
print "NEXT_DEAD second time != NULL"
return 1
+ if rawrefcount.to_obj(W_Root, ob) is not None:
+ print "to_obj(dead) is not None?"
+ return 1
+ rawrefcount.mark_deallocating(w_marker, ob)
+ if rawrefcount.to_obj(W_Root, ob) is not w_marker:
+ print "to_obj(marked-dead) is not w_marker"
+ return 1
print "OK!"
lltype.free(ob, flavor='raw')
return 0
diff --git a/rpython/rtyper/annlowlevel.py b/rpython/rtyper/annlowlevel.py
--- a/rpython/rtyper/annlowlevel.py
+++ b/rpython/rtyper/annlowlevel.py
@@ -138,11 +138,12 @@
# get the graph of the mix-level helper ll_function and prepare it for
# being annotated. Annotation and RTyping should be done in a single shot
# at the end with finish().
- graph, args_s = self.rtyper.annotator.get_call_parameters(
- ll_function, args_s, policy = self.policy)
+ ann = self.rtyper.annotator
+ with ann.using_policy(self.policy):
+ graph, args_s = ann.get_call_parameters(ll_function, args_s)
for v_arg, s_arg in zip(graph.getargs(), args_s):
- self.rtyper.annotator.setbinding(v_arg, s_arg)
- self.rtyper.annotator.setbinding(graph.getreturnvar(), s_result)
+ ann.setbinding(v_arg, s_arg)
+ ann.setbinding(graph.getreturnvar(), s_result)
#self.rtyper.annotator.annotated[graph.returnblock] = graph
self.pending.append((ll_function, graph, args_s, s_result))
return graph
@@ -224,16 +225,17 @@
bk = ann.bookkeeper
translator = ann.translator
original_graph_count = len(translator.graphs)
- for ll_function, graph, args_s, s_result in self.pending:
- # mark the return block as already annotated, because the return var
- # annotation was forced in getgraph() above. This prevents temporary
- # less general values reaching the return block from crashing the
- # annotator (on the assert-that-new-binding-is-not-less-general).
- ann.annotated[graph.returnblock] = graph
- s_function = bk.immutablevalue(ll_function)
- bk.emulate_pbc_call(graph, s_function, args_s)
- self.newgraphs.add(graph)
- ann.complete_helpers(self.policy)
+ with ann.using_policy(self.policy):
+ for ll_function, graph, args_s, s_result in self.pending:
+ # mark the return block as already annotated, because the return var
+ # annotation was forced in getgraph() above. This prevents temporary
+ # less general values reaching the return block from crashing the
+ # annotator (on the assert-that-new-binding-is-not-less-general).
+ ann.annotated[graph.returnblock] = graph
+ s_function = bk.immutablevalue(ll_function)
+ bk.emulate_pbc_call(graph, s_function, args_s)
+ self.newgraphs.add(graph)
+ ann.complete_helpers()
for ll_function, graph, args_s, s_result in self.pending:
s_real_result = ann.binding(graph.getreturnvar())
if s_real_result != s_result:
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -959,6 +959,9 @@
def op_gc_rawrefcount_create_link_pypy(self, *args):
raise NotImplementedError("gc_rawrefcount_create_link_pypy")
+ def op_gc_rawrefcount_mark_deallocating(self, *args):
+ raise NotImplementedError("gc_rawrefcount_mark_deallocating")
+
def op_do_malloc_fixedsize(self):
raise NotImplementedError("do_malloc_fixedsize")
def op_do_malloc_fixedsize_clear(self):
diff --git a/rpython/rtyper/lltypesystem/llmemory.py b/rpython/rtyper/lltypesystem/llmemory.py
--- a/rpython/rtyper/lltypesystem/llmemory.py
+++ b/rpython/rtyper/lltypesystem/llmemory.py
@@ -384,7 +384,6 @@
def _sizeof_none(TYPE):
assert not TYPE._is_varsize()
return ItemOffset(TYPE)
-_sizeof_none._annspecialcase_ = 'specialize:memo'
@specialize.memo()
def _internal_array_field(TYPE):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -490,6 +490,7 @@
'gc_rawrefcount_init': LLOp(),
'gc_rawrefcount_create_link_pypy': LLOp(),
'gc_rawrefcount_create_link_pyobj': LLOp(),
+ 'gc_rawrefcount_mark_deallocating': LLOp(),
'gc_rawrefcount_from_obj': LLOp(sideeffects=False),
'gc_rawrefcount_to_obj': LLOp(sideeffects=False),
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -7,7 +7,7 @@
from rpython.rtyper.lltypesystem.llmemory import itemoffsetof
from rpython.rtyper.llannotation import lltype_to_annotation
from rpython.tool.sourcetools import func_with_new_name
-from rpython.rlib.objectmodel import Symbolic
+from rpython.rlib.objectmodel import Symbolic, specialize
from rpython.rlib.objectmodel import keepalive_until_here, enforceargs
from rpython.rlib import rarithmetic, rgc
from rpython.rtyper.extregistry import ExtRegistryEntry
@@ -74,7 +74,7 @@
def llexternal(name, args, result, _callable=None,
compilation_info=ExternalCompilationInfo(),
sandboxsafe=False, releasegil='auto',
- _nowrapper=False, calling_conv='c',
+ _nowrapper=False, calling_conv=None,
elidable_function=False, macro=None,
random_effects_on_gcobjs='auto',
save_err=RFFI_ERR_NONE):
@@ -96,7 +96,17 @@
we consider that the function is really short-running and
don't bother releasing the GIL. An explicit True or False
overrides this logic.
+
+ calling_conv: if 'unknown' or 'win', the C function is not directly seen
+ by the JIT. If 'c', it can be seen (depending on
+ releasegil=False). For tests only, or if _nowrapper,
+ it defaults to 'c'.
"""
+ if calling_conv is None:
+ if sys.platform == 'win32' and not _nowrapper:
+ calling_conv = 'unknown'
+ else:
+ calling_conv = 'c'
if _callable is not None:
assert callable(_callable)
ext_type = lltype.FuncType(args, result)
@@ -107,7 +117,8 @@
_callable = generate_macro_wrapper(
name, macro, ext_type, compilation_info)
else:
- _callable = ll2ctypes.LL2CtypesCallable(ext_type, calling_conv)
+ _callable = ll2ctypes.LL2CtypesCallable(ext_type,
+ 'c' if calling_conv == 'unknown' else calling_conv)
else:
assert macro is None, "'macro' is useless if you specify '_callable'"
if elidable_function:
@@ -205,11 +216,17 @@
else:
# if we don't have to invoke the GIL handling, we can just call
# the low-level function pointer carelessly
- if macro is None and save_err == RFFI_ERR_NONE:
+ # ...well, unless it's a macro, in which case we still have
+ # to hide it from the JIT...
+ need_wrapper = (macro is not None or save_err != RFFI_ERR_NONE)
+ # ...and unless we're on Windows and the calling convention is
+ # 'win' or 'unknown'
+ if calling_conv != 'c':
+ need_wrapper = True
+ #
+ if not need_wrapper:
call_external_function = funcptr
else:
- # ...well, unless it's a macro, in which case we still have
- # to hide it from the JIT...
argnames = ', '.join(['a%d' % i for i in range(len(args))])
source = py.code.Source("""
def call_external_function(%(argnames)s):
@@ -308,10 +325,6 @@
# for debugging, stick ll func ptr to that
wrapper._ptr = funcptr
wrapper = func_with_new_name(wrapper, name)
-
- if calling_conv != "c":
- wrapper = jit.dont_look_inside(wrapper)
-
return wrapper
@@ -1288,10 +1301,12 @@
c_memcpy = llexternal("memcpy",
[VOIDP, VOIDP, SIZE_T],
lltype.Void,
- releasegil=False
+ releasegil=False,
+ calling_conv='c',
)
c_memset = llexternal("memset",
[VOIDP, lltype.Signed, SIZE_T],
lltype.Void,
- releasegil=False
+ releasegil=False,
+ calling_conv='c',
)
diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -362,9 +362,9 @@
def get_concrete_llfn(self, s_pbc, args_s, op):
bk = self.rtyper.annotator.bookkeeper
funcdesc, = s_pbc.descriptions
- args = simple_args(args_s)
with bk.at_position(None):
- graph = funcdesc.get_graph(args, op)
+ argspec = simple_args(args_s)
+ graph = funcdesc.get_graph(argspec, op)
llfn = self.rtyper.getcallable(graph)
return inputconst(typeOf(llfn), llfn)
diff --git a/rpython/rtyper/rtyper.py b/rpython/rtyper/rtyper.py
--- a/rpython/rtyper/rtyper.py
+++ b/rpython/rtyper/rtyper.py
@@ -846,28 +846,29 @@
rtyper = self.rtyper
args_s = []
newargs_v = []
- for v in args_v:
- if v.concretetype is Void:
- s_value = rtyper.annotation(v)
- if s_value is None:
- s_value = annmodel.s_None
- if not s_value.is_constant():
- raise TyperError("non-constant variable of type Void")
- if not isinstance(s_value, (annmodel.SomePBC, annmodel.SomeNone)):
- raise TyperError("non-PBC Void argument: %r", (s_value,))
- args_s.append(s_value)
- else:
- args_s.append(lltype_to_annotation(v.concretetype))
- newargs_v.append(v)
+ with rtyper.annotator.using_policy(rtyper.lowlevel_ann_policy):
+ for v in args_v:
+ if v.concretetype is Void:
+ s_value = rtyper.annotation(v)
+ if s_value is None:
+ s_value = annmodel.s_None
+ if not s_value.is_constant():
+ raise TyperError("non-constant variable of type Void")
+ if not isinstance(s_value, (annmodel.SomePBC, annmodel.SomeNone)):
+ raise TyperError("non-PBC Void argument: %r", (s_value,))
+ args_s.append(s_value)
+ else:
+ args_s.append(lltype_to_annotation(v.concretetype))
+ newargs_v.append(v)
- self.rtyper.call_all_setups() # compute ForwardReferences now
+ self.rtyper.call_all_setups() # compute ForwardReferences now
- # hack for bound methods
- if hasattr(ll_function, 'im_func'):
- bk = rtyper.annotator.bookkeeper
- args_s.insert(0, bk.immutablevalue(ll_function.im_self))
- newargs_v.insert(0, inputconst(Void, ll_function.im_self))
- ll_function = ll_function.im_func
+ # hack for bound methods
+ if hasattr(ll_function, 'im_func'):
+ bk = rtyper.annotator.bookkeeper
+ args_s.insert(0, bk.immutablevalue(ll_function.im_self))
+ newargs_v.insert(0, inputconst(Void, ll_function.im_self))
+ ll_function = ll_function.im_func
graph = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s,
rtyper.lowlevel_ann_policy)
More information about the pypy-commit
mailing list