[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Sun Nov 30 23:12:42 CET 2014
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r74767:e01964ac6c50
Date: 2014-11-30 11:51 -0800
http://bitbucket.org/pypy/pypy/changeset/e01964ac6c50/
Log: merge default
diff too long, truncating to 2000 out of 3374 lines
diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -655,6 +655,21 @@
"""Create new Popen instance."""
_cleanup()
+ # --- PyPy hack, see _pypy_install_libs_after_virtualenv() ---
+ # match arguments passed by different versions of virtualenv
+ if args[1:] in (
+ ['-c', 'import sys; print(sys.prefix)'], # 1.6 10ba3f3c
+ ['-c', "\nimport sys\nprefix = sys.prefix\n" # 1.7 0e9342ce
+ "if sys.version_info[0] == 3:\n"
+ " prefix = prefix.encode('utf8')\n"
+ "if hasattr(sys.stdout, 'detach'):\n"
+ " sys.stdout = sys.stdout.detach()\n"
+ "elif hasattr(sys.stdout, 'buffer'):\n"
+ " sys.stdout = sys.stdout.buffer\nsys.stdout.write(prefix)\n"],
+ ['-c', 'import sys;out=sys.stdout;getattr(out, "buffer"'
+ ', out).write(sys.prefix.encode("utf-8"))']): # 1.7.2 a9454bce
+ _pypy_install_libs_after_virtualenv(args[0])
+
if not isinstance(bufsize, (int, long)):
raise TypeError("bufsize must be an integer")
@@ -1560,6 +1575,27 @@
self.send_signal(signal.SIGKILL)
+def _pypy_install_libs_after_virtualenv(target_executable):
+ # https://bitbucket.org/pypy/pypy/issue/1922/future-proofing-virtualenv
+ #
+ # PyPy 2.4.1 turned --shared on by default. This means the pypy binary
+ # depends on the 'libpypy-c.so' shared library to be able to run.
+ # The virtualenv code existing at the time did not account for this
+ # and would break. Try to detect that we're running under such a
+ # virtualenv in the "Testing executable with" phase and copy the
+ # library ourselves.
+ caller = sys._getframe(2)
+ if ('virtualenv_version' in caller.f_globals and
+ 'copyfile' in caller.f_globals):
+ dest_dir = sys.pypy_resolvedirof(target_executable)
+ src_dir = sys.pypy_resolvedirof(sys.executable)
+ for libname in ['libpypy-c.so']:
+ dest_library = os.path.join(dest_dir, libname)
+ src_library = os.path.join(src_dir, libname)
+ if os.path.exists(src_library):
+ caller.f_globals['copyfile'](src_library, dest_library)
+
+
def _demo_posix():
#
# Example 1: Simple redirection: Get process list
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -205,23 +205,28 @@
The above is true both in CPython and in PyPy. Differences
can occur about whether a built-in function or method will
call an overridden method of *another* object than ``self``.
-In PyPy, they are generally always called, whereas not in
-CPython. For example, in PyPy, ``dict1.update(dict2)``
-considers that ``dict2`` is just a general mapping object, and
-will thus call overridden ``keys()`` and ``__getitem__()``
-methods on it. So the following code prints ``42`` on PyPy
-but ``foo`` on CPython::
+In PyPy, they are often called in cases where CPython would not.
+Two examples::
- >>>> class D(dict):
- .... def __getitem__(self, key):
- .... return 42
- ....
- >>>>
- >>>> d1 = {}
- >>>> d2 = D(a='foo')
- >>>> d1.update(d2)
- >>>> print d1['a']
- 42
+ class D(dict):
+ def __getitem__(self, key):
+ return "%r from D" % (key,)
+
+ class A(object):
+ pass
+
+ a = A()
+ a.__dict__ = D()
+ a.foo = "a's own foo"
+ print a.foo
+ # CPython => a's own foo
+ # PyPy => 'foo' from D
+
+ glob = D(foo="base item")
+ loc = {}
+ exec "print foo" in glob, loc
+ # CPython => base item
+ # PyPy => 'foo' from D
Mutating classes of objects which are already used as dictionary keys
@@ -292,6 +297,9 @@
above types will return a value that is computed from the argument, and can
thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
+Notably missing from the list above are ``str`` and ``unicode``. If your
+code relies on comparing strings with ``is``, then it might break in PyPy.
+
Miscellaneous
-------------
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -1,15 +1,13 @@
-"""
-Python control flow graph generation and bytecode assembly.
-"""
+"""Python control flow graph generation and bytecode assembly."""
-from pypy.interpreter.astcompiler import ast, consts, symtable
-from pypy.interpreter import pycode
+from rpython.rlib import rfloat
+from rpython.rlib.objectmodel import specialize, we_are_translated
+
+from pypy.interpreter.astcompiler import ast, consts, misc, symtable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.pycode import PyCode
from pypy.tool import stdlib_opcode as ops
-from pypy.interpreter.error import OperationError
-from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib import rfloat
-
class Instruction(object):
"""Represents a single opcode."""
@@ -21,14 +19,12 @@
self.has_jump = False
def size(self):
- """Return the size of bytes of this instruction when it is encoded."""
+ """Return the size of bytes of this instruction when it is
+ encoded.
+ """
if self.opcode >= ops.HAVE_ARGUMENT:
- if self.arg > 0xFFFF:
- return 6
- else:
- return 3
- else:
- return 1
+ return (6 if self.arg > 0xFFFF else 3)
+ return 1
def jump_to(self, target, absolute=False):
"""Indicate the target this jump instruction.
@@ -54,9 +50,9 @@
class Block(object):
"""A basic control flow block.
- It has one entry point and several possible exit points. Its instructions
- may be jumps to other blocks, or if control flow reaches the end of the
- block, it continues to next_block.
+ It has one entry point and several possible exit points. Its
+ instructions may be jumps to other blocks, or if control flow
+ reaches the end of the block, it continues to next_block.
"""
def __init__(self):
@@ -71,10 +67,10 @@
stack.append(nextblock)
def post_order(self):
- """Return this block and its children in post order.
- This means that the graph of blocks is first cleaned up to
- ignore back-edges, thus turning it into a DAG. Then the DAG
- is linearized. For example:
+ """Return this block and its children in post order. This means
+ that the graph of blocks is first cleaned up to ignore
+ back-edges, thus turning it into a DAG. Then the DAG is
+ linearized. For example:
A --> B -\ => [A, D, B, C]
\-> D ---> C
@@ -105,7 +101,9 @@
return resultblocks
def code_size(self):
- """Return the encoded size of all the instructions in this block."""
+ """Return the encoded size of all the instructions in this
+ block.
+ """
i = 0
for instr in self.instructions:
i += instr.size()
@@ -141,6 +139,7 @@
i += 1
return result
+
@specialize.argtype(0)
def _iter_to_dict(iterable, offset=0):
result = {}
@@ -302,11 +301,11 @@
def _resolve_block_targets(self, blocks):
"""Compute the arguments of jump instructions."""
last_extended_arg_count = 0
- # The reason for this loop is extended jumps. EXTENDED_ARG extends the
- # bytecode size, so it might invalidate the offsets we've already given.
- # Thus we have to loop until the number of extended args is stable. Any
- # extended jump at all is extremely rare, so performance is not too
- # concerning.
+ # The reason for this loop is extended jumps. EXTENDED_ARG
+ # extends the bytecode size, so it might invalidate the offsets
+ # we've already given. Thus we have to loop until the number of
+ # extended args is stable. Any extended jump at all is
+ # extremely rare, so performance is not too concerning.
while True:
extended_arg_count = 0
offset = 0
@@ -332,7 +331,8 @@
instr.opcode = ops.JUMP_ABSOLUTE
absolute = True
elif target_op == ops.RETURN_VALUE:
- # Replace JUMP_* to a RETURN into just a RETURN
+ # Replace JUMP_* to a RETURN into
+ # just a RETURN
instr.opcode = ops.RETURN_VALUE
instr.arg = 0
instr.has_jump = False
@@ -347,7 +347,8 @@
instr.arg = jump_arg
if jump_arg > 0xFFFF:
extended_arg_count += 1
- if extended_arg_count == last_extended_arg_count and not force_redo:
+ if (extended_arg_count == last_extended_arg_count and
+ not force_redo):
break
else:
last_extended_arg_count = extended_arg_count
@@ -362,12 +363,14 @@
while True:
try:
w_key = space.next(w_iter)
- except OperationError, e:
+ except OperationError as e:
if not e.match(space, space.w_StopIteration):
raise
break
w_index = space.getitem(w_consts, w_key)
- consts_w[space.int_w(w_index)] = space.getitem(w_key, first)
+ w_constant = space.getitem(w_key, first)
+ w_constant = misc.intern_if_common_string(space, w_constant)
+ consts_w[space.int_w(w_index)] = w_constant
return consts_w
def _get_code_flags(self):
@@ -435,15 +438,16 @@
continue
addr = offset - current_off
# Python assumes that lineno always increases with
- # increasing bytecode address (lnotab is unsigned char).
- # Depending on when SET_LINENO instructions are emitted this
- # is not always true. Consider the code:
+ # increasing bytecode address (lnotab is unsigned
+ # char). Depending on when SET_LINENO instructions
+ # are emitted this is not always true. Consider the
+ # code:
# a = (1,
# b)
- # In the bytecode stream, the assignment to "a" occurs after
- # the loading of "b". This works with the C Python compiler
- # because it only generates a SET_LINENO instruction for the
- # assignment.
+ # In the bytecode stream, the assignment to "a"
+ # occurs after the loading of "b". This works with
+ # the C Python compiler because it only generates a
+ # SET_LINENO instruction for the assignment.
if line or addr:
while addr > 255:
push(chr(255))
@@ -488,23 +492,23 @@
# (Only) inherit compilerflags in PyCF_MASK
flags |= (self.compile_info.flags & consts.PyCF_MASK)
bytecode = ''.join([block.get_code() for block in blocks])
- return pycode.PyCode(self.space,
- self.argcount,
- self.kwonlyargcount,
- len(self.var_names),
- stack_depth,
- flags,
- bytecode,
- list(consts_w),
- names,
- var_names,
- self.compile_info.filename,
- self.name,
- self.first_lineno,
- lnotab,
- free_names,
- cell_names,
- self.compile_info.hidden_applevel)
+ return PyCode(self.space,
+ self.argcount,
+ self.kwonlyargcount,
+ len(self.var_names),
+ stack_depth,
+ flags,
+ bytecode,
+ list(consts_w),
+ names,
+ var_names,
+ self.compile_info.filename,
+ self.name,
+ self.first_lineno,
+ lnotab,
+ free_names,
+ cell_names,
+ self.compile_info.hidden_applevel)
def _list_from_dict(d, offset=0):
@@ -515,116 +519,116 @@
_static_opcode_stack_effects = {
- ops.NOP : 0,
- ops.STOP_CODE : 0,
+ ops.NOP: 0,
+ ops.STOP_CODE: 0,
- ops.POP_TOP : -1,
- ops.ROT_TWO : 0,
- ops.ROT_THREE : 0,
- ops.DUP_TOP : 1,
- ops.DUP_TOP_TWO : 2,
+ ops.POP_TOP: -1,
+ ops.ROT_TWO: 0,
+ ops.ROT_THREE: 0,
+ ops.DUP_TOP: 1,
+ ops.DUP_TOP_TWO: 2,
- ops.UNARY_POSITIVE : 0,
- ops.UNARY_NEGATIVE : 0,
- ops.UNARY_NOT : 0,
- ops.UNARY_INVERT : 0,
+ ops.UNARY_POSITIVE: 0,
+ ops.UNARY_NEGATIVE: 0,
+ ops.UNARY_NOT: 0,
+ ops.UNARY_INVERT: 0,
- ops.LIST_APPEND : -1,
- ops.SET_ADD : -1,
- ops.MAP_ADD : -2,
- ops.STORE_MAP : -2,
+ ops.LIST_APPEND: -1,
+ ops.SET_ADD: -1,
+ ops.MAP_ADD: -2,
+ ops.STORE_MAP: -2,
- ops.BINARY_POWER : -1,
- ops.BINARY_MULTIPLY : -1,
- ops.BINARY_MODULO : -1,
- ops.BINARY_ADD : -1,
- ops.BINARY_SUBTRACT : -1,
- ops.BINARY_SUBSCR : -1,
- ops.BINARY_FLOOR_DIVIDE : -1,
- ops.BINARY_TRUE_DIVIDE : -1,
- ops.BINARY_LSHIFT : -1,
- ops.BINARY_RSHIFT : -1,
- ops.BINARY_AND : -1,
- ops.BINARY_OR : -1,
- ops.BINARY_XOR : -1,
+ ops.BINARY_POWER: -1,
+ ops.BINARY_MULTIPLY: -1,
+ ops.BINARY_MODULO: -1,
+ ops.BINARY_ADD: -1,
+ ops.BINARY_SUBTRACT: -1,
+ ops.BINARY_SUBSCR: -1,
+ ops.BINARY_FLOOR_DIVIDE: -1,
+ ops.BINARY_TRUE_DIVIDE: -1,
+ ops.BINARY_LSHIFT: -1,
+ ops.BINARY_RSHIFT: -1,
+ ops.BINARY_AND: -1,
+ ops.BINARY_OR: -1,
+ ops.BINARY_XOR: -1,
- ops.INPLACE_FLOOR_DIVIDE : -1,
- ops.INPLACE_TRUE_DIVIDE : -1,
- ops.INPLACE_ADD : -1,
- ops.INPLACE_SUBTRACT : -1,
- ops.INPLACE_MULTIPLY : -1,
- ops.INPLACE_MODULO : -1,
- ops.INPLACE_POWER : -1,
- ops.INPLACE_LSHIFT : -1,
- ops.INPLACE_RSHIFT : -1,
- ops.INPLACE_AND : -1,
- ops.INPLACE_OR : -1,
- ops.INPLACE_XOR : -1,
+ ops.INPLACE_FLOOR_DIVIDE: -1,
+ ops.INPLACE_TRUE_DIVIDE: -1,
+ ops.INPLACE_ADD: -1,
+ ops.INPLACE_SUBTRACT: -1,
+ ops.INPLACE_MULTIPLY: -1,
+ ops.INPLACE_MODULO: -1,
+ ops.INPLACE_POWER: -1,
+ ops.INPLACE_LSHIFT: -1,
+ ops.INPLACE_RSHIFT: -1,
+ ops.INPLACE_AND: -1,
+ ops.INPLACE_OR: -1,
+ ops.INPLACE_XOR: -1,
- ops.STORE_SUBSCR : -2,
- ops.DELETE_SUBSCR : -2,
+ ops.STORE_SUBSCR: -2,
+ ops.DELETE_SUBSCR: -2,
- ops.GET_ITER : 0,
- ops.FOR_ITER : 1,
- ops.BREAK_LOOP : 0,
- ops.CONTINUE_LOOP : 0,
- ops.SETUP_LOOP : 0,
+ ops.GET_ITER: 0,
+ ops.FOR_ITER: 1,
+ ops.BREAK_LOOP: 0,
+ ops.CONTINUE_LOOP: 0,
+ ops.SETUP_LOOP: 0,
- ops.PRINT_EXPR : -1,
+ ops.PRINT_EXPR: -1,
- ops.WITH_CLEANUP : -1,
- ops.LOAD_BUILD_CLASS : 1,
- ops.STORE_LOCALS : -1,
- ops.POP_BLOCK : 0,
- ops.POP_EXCEPT : 0,
- ops.END_FINALLY : -1,
- ops.SETUP_WITH : 1,
- ops.SETUP_FINALLY : 0,
- ops.SETUP_EXCEPT : 4,
+ ops.WITH_CLEANUP: -1,
+ ops.LOAD_BUILD_CLASS: 1,
+ ops.STORE_LOCALS: -1,
+ ops.POP_BLOCK: 0,
+ ops.POP_EXCEPT: 0,
+ ops.END_FINALLY: -1,
+ ops.SETUP_WITH: 1,
+ ops.SETUP_FINALLY: 0,
+ ops.SETUP_EXCEPT: 4,
- ops.RETURN_VALUE : -1,
- ops.YIELD_VALUE : 0,
- ops.BUILD_MAP : 1,
- ops.BUILD_SET : 1,
- ops.COMPARE_OP : -1,
+ ops.RETURN_VALUE: -1,
+ ops.YIELD_VALUE: 0,
+ ops.BUILD_MAP: 1,
+ ops.BUILD_SET: 1,
+ ops.COMPARE_OP: -1,
- ops.LOOKUP_METHOD : 1,
+ ops.LOOKUP_METHOD: 1,
- ops.LOAD_NAME : 1,
- ops.STORE_NAME : -1,
- ops.DELETE_NAME : 0,
+ ops.LOAD_NAME: 1,
+ ops.STORE_NAME: -1,
+ ops.DELETE_NAME: 0,
- ops.LOAD_FAST : 1,
- ops.STORE_FAST : -1,
- ops.DELETE_FAST : 0,
+ ops.LOAD_FAST: 1,
+ ops.STORE_FAST: -1,
+ ops.DELETE_FAST: 0,
- ops.LOAD_ATTR : 0,
- ops.STORE_ATTR : -2,
- ops.DELETE_ATTR : -1,
+ ops.LOAD_ATTR: 0,
+ ops.STORE_ATTR: -2,
+ ops.DELETE_ATTR: -1,
- ops.LOAD_GLOBAL : 1,
- ops.STORE_GLOBAL : -1,
- ops.DELETE_GLOBAL : 0,
- ops.DELETE_DEREF : 0,
-
- ops.LOAD_CLOSURE : 1,
- ops.LOAD_DEREF : 1,
- ops.STORE_DEREF : -1,
+ ops.LOAD_GLOBAL: 1,
+ ops.STORE_GLOBAL: -1,
+ ops.DELETE_GLOBAL: 0,
ops.DELETE_DEREF: 0,
- ops.LOAD_CONST : 1,
+ ops.LOAD_CLOSURE: 1,
+ ops.LOAD_DEREF: 1,
+ ops.STORE_DEREF: -1,
+ ops.DELETE_DEREF: 0,
- ops.IMPORT_STAR : -1,
- ops.IMPORT_NAME : -1,
- ops.IMPORT_FROM : 1,
+ ops.LOAD_CONST: 1,
- ops.JUMP_FORWARD : 0,
- ops.JUMP_ABSOLUTE : 0,
- ops.JUMP_IF_TRUE_OR_POP : 0,
- ops.JUMP_IF_FALSE_OR_POP : 0,
- ops.POP_JUMP_IF_TRUE : -1,
- ops.POP_JUMP_IF_FALSE : -1,
- ops.JUMP_IF_NOT_DEBUG : 0,
+ ops.IMPORT_STAR: -1,
+ ops.IMPORT_NAME: -1,
+ ops.IMPORT_FROM: 1,
+
+ ops.JUMP_FORWARD: 0,
+ ops.JUMP_ABSOLUTE: 0,
+ ops.JUMP_IF_TRUE_OR_POP: 0,
+ ops.JUMP_IF_FALSE_OR_POP: 0,
+ ops.POP_JUMP_IF_TRUE: -1,
+ ops.POP_JUMP_IF_FALSE: -1,
+ ops.JUMP_IF_NOT_DEBUG: 0,
ops.BUILD_LIST_FROM_ARG: 1,
}
diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py
--- a/pypy/interpreter/astcompiler/misc.py
+++ b/pypy/interpreter/astcompiler/misc.py
@@ -108,6 +108,16 @@
return "_%s%s" % (klass[i:], name)
+def intern_if_common_string(space, w_const):
+ # only intern identifier-like strings
+ if not space.is_w(space.type(w_const), space.w_str):
+ return w_const
+ for c in space.str_w(w_const):
+ if not (c.isalnum() or c == '_'):
+ return w_const
+ return space.new_interned_w_str(w_const)
+
+
def new_identifier(space, name):
# Check whether there are non-ASCII characters in the identifier; if
# so, normalize to NFKC
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -279,6 +279,11 @@
if w_const is None:
return tup
consts_w[i] = w_const
+ # intern the string constants packed into the tuple here,
+ # because assemble.py will see the result as just a tuple constant
+ for i in range(len(consts_w)):
+ consts_w[i] = misc.intern_if_common_string(
+ self.space, consts_w[i])
else:
consts_w = []
w_consts = self.space.newtuple(consts_w)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -15,7 +15,7 @@
UserDelAction)
from pypy.interpreter.error import OperationError, new_exception_class, oefmt
from pypy.interpreter.argument import Arguments
-from pypy.interpreter.miscutils import ThreadLocals
+from pypy.interpreter.miscutils import ThreadLocals, make_weak_value_dictionary
__all__ = ['ObjSpace', 'OperationError', 'W_Root']
@@ -362,7 +362,7 @@
self.builtin_modules = {}
self.reloading_modules = {}
- self.interned_strings = {}
+ self.interned_strings = make_weak_value_dictionary(self, str, W_Root)
self.actionflag = ActionFlag() # changed by the signal module
self.check_signal_action = None # changed by the signal module
self.user_del_action = UserDelAction(self)
@@ -766,25 +766,30 @@
return self.w_False
def new_interned_w_str(self, w_s):
+ assert isinstance(w_s, W_Root) # and is not None
s = self.str_w(w_s)
if not we_are_translated():
assert type(s) is str
- try:
- return self.interned_strings[s]
- except KeyError:
- pass
- self.interned_strings[s] = w_s
- return w_s
+ w_s1 = self.interned_strings.get(s)
+ if w_s1 is None:
+ w_s1 = w_s
+ self.interned_strings.set(s, w_s1)
+ return w_s1
def new_interned_str(self, s):
if not we_are_translated():
assert type(s) is str
- try:
- return self.interned_strings[s]
- except KeyError:
- pass
- w_s = self.interned_strings[s] = self.wrap(s)
- return w_s
+ w_s1 = self.interned_strings.get(s)
+ if w_s1 is None:
+ w_s1 = self.wrap(s)
+ self.interned_strings.set(s, w_s1)
+ return w_s1
+
+ def is_interned_str(self, s):
+ # interface for marshal_impl
+ if not we_are_translated():
+ assert type(s) is str
+ return self.interned_strings.get(s) is not None
def descr_self_interp_w(self, RequiredClass, w_obj):
if not isinstance(w_obj, RequiredClass):
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -31,3 +31,19 @@
def getallvalues(self):
return {0: self._value}
+
+
+def make_weak_value_dictionary(space, keytype, valuetype):
+ "NOT_RPYTHON"
+ if space.config.translation.rweakref:
+ from rpython.rlib.rweakref import RWeakValueDictionary
+ return RWeakValueDictionary(keytype, valuetype)
+ else:
+ class FakeWeakValueDict(object):
+ def __init__(self):
+ self._dict = {}
+ def get(self, key):
+ return self._dict.get(key, None)
+ def set(self, key, value):
+ self._dict[key] = value
+ return FakeWeakValueDict()
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -131,7 +131,6 @@
# class bodies only have CO_NEWLOCALS.
# CO_NEWLOCALS: make a locals dict unless optimized is also set
# CO_OPTIMIZED: no locals dict needed at all
- # NB: this method is overridden in nestedscope.py
flags = code.co_flags
if not (flags & pycode.CO_OPTIMIZED):
if flags & pycode.CO_NEWLOCALS:
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -1094,7 +1094,12 @@
sys.stdout = out
output = s.getvalue()
assert "CALL_METHOD" in output
-
+
+ def test_interned_strings(self):
+ source = """x = ('foo_bar42', 5); y = 'foo_bar42'; z = x[0]"""
+ exec source
+ assert y is z
+
class AppTestExceptions:
def test_indentation_error(self):
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -378,3 +378,41 @@
assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
space.startup()
assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
+
+ def test_interned_strings_are_weak(self):
+ import weakref, gc, random
+ space = self.space
+ assert space.config.translation.rweakref
+ w1 = space.new_interned_str("abcdef")
+ w2 = space.new_interned_str("abcdef")
+ assert w2 is w1
+ #
+ # check that 'w1' goes away if we don't hold a reference to it
+ rw1 = weakref.ref(w1)
+ del w1, w2
+ i = 10
+ while rw1() is not None:
+ i -= 1
+ assert i >= 0
+ gc.collect()
+ #
+ s = "foobar%r" % random.random()
+ w0 = space.wrap(s)
+ w1 = space.new_interned_w_str(w0)
+ assert w1 is w0
+ w2 = space.new_interned_w_str(w0)
+ assert w2 is w0
+ w3 = space.wrap(s)
+ assert w3 is not w0
+ w4 = space.new_interned_w_str(w3)
+ assert w4 is w0
+ #
+ # check that 'w0' goes away if we don't hold a reference to it
+ # (even if we hold a reference to 'w3')
+ rw0 = weakref.ref(w0)
+ del w0, w1, w2, w4
+ i = 10
+ while rw0() is not None:
+ i -= 1
+ assert i >= 0
+ gc.collect()
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -147,7 +147,6 @@
atom_int(tc, int) puts code and int
atom_int64(tc, int64) puts code and int64
atom_str(tc, str) puts code, len and string
- atom_strlist(tc, strlist) puts code, len and list of strings
building blocks for compound types:
@@ -201,15 +200,6 @@
self.atom_int(typecode, len(x))
self.put(x)
- def atom_strlist(self, typecode, tc2, x):
- self.atom_int(typecode, len(x))
- atom_str = self.atom_str
- for item in x:
- # type(str) seems to be forbidden
- #if type(item) is not str:
- # self.raise_exc('object with wrong type in strlist')
- atom_str(tc2, item)
-
def start(self, typecode):
# type(char) not supported
self.put(typecode)
@@ -382,16 +372,6 @@
self.start(typecode)
return self.get_lng()
- def atom_strlist(self, typecode, tc2):
- self.start(typecode)
- lng = self.get_lng()
- res = [None] * lng
- idx = 0
- while idx < lng:
- res[idx] = self.atom_str(tc2)
- idx += 1
- return res
-
def start(self, typecode):
tc = self.get1()
if tc != typecode:
@@ -439,7 +419,6 @@
def get_w_obj(self, allow_null=False):
space = self.space
- w_ret = space.w_None # something not None
tc = self.get1()
w_ret = self._dispatch[ord(tc)](space, self, tc)
if w_ret is None and not allow_null:
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -275,9 +275,19 @@
@classmethod
def parse_op(cls, line):
- # strip comment
+ # strip comment after '#', but not if it appears inside parentheses
if '#' in line:
- line = line[:line.index('#')]
+ nested = 0
+ for i, c in enumerate(line):
+ if c == '(':
+ nested += 1
+ elif c == ')':
+ assert nested > 0, "more ')' than '(' in %r" % (line,)
+ nested -= 1
+ elif c == '#' and nested == 0:
+ line = line[:i]
+ break
+ #
if line.strip() == 'guard_not_invalidated?':
return 'guard_not_invalidated', None, [], '...', False
# find the resvar, if any
@@ -314,7 +324,7 @@
# to repeat it every time
ticker_check = """
guard_not_invalidated?
- ticker0 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value .*>)
+ ticker0 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value .*>)
ticker_cond0 = int_lt(ticker0, 0)
guard_false(ticker_cond0, descr=...)
"""
@@ -323,9 +333,9 @@
# this is the ticker check generated if we have threads
thread_ticker_check = """
guard_not_invalidated?
- ticker0 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value .*>)
- ticker1 = int_sub(ticker0, _)
- setfield_raw(ticker_address, ticker1, descr=<FieldS pypysig_long_struct.c_value .*>)
+ ticker0 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value .*>)
+ ticker1 = int_sub(ticker0, #)
+ setfield_raw(#, ticker1, descr=<FieldS pypysig_long_struct.c_value .*>)
ticker_cond0 = int_lt(ticker1, 0)
guard_false(ticker_cond0, descr=...)
"""
@@ -333,7 +343,7 @@
#
# this is the ticker check generated in PyFrame.handle_operation_error
exc_ticker_check = """
- ticker2 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value .*>)
+ ticker2 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value .*>)
ticker_cond1 = int_lt(ticker2, 0)
guard_false(ticker_cond1, descr=...)
"""
@@ -351,18 +361,31 @@
@staticmethod
def as_numeric_const(v1):
+ # returns one of: ('int', value) ('float', value) None
try:
- return int(v1)
- except (ValueError, TypeError):
- return None
+ return ('int', int(v1))
+ except ValueError:
+ pass
+ if '.' in v1:
+ try:
+ return ('float', float(v1))
+ except ValueError:
+ pass
+ return None
def match_var(self, v1, exp_v2):
assert v1 != '_'
- if exp_v2 == '_':
+ if exp_v2 == '_': # accept anything
return True
+ if exp_v2 is None:
+ return v1 is None
+ assert exp_v2 != '...' # bogus use of '...' in the expected code
n1 = self.as_numeric_const(v1)
+ if exp_v2 == '#': # accept any (integer or float) number
+ return n1 is not None
n2 = self.as_numeric_const(exp_v2)
- if n1 is not None and n2 is not None:
+ if n1 is not None or n2 is not None:
+ # at least one is a number; check that both are, and are equal
return n1 == n2
if self.is_const(v1) or self.is_const(exp_v2):
return v1[:-1].startswith(exp_v2[:-1])
@@ -382,10 +405,13 @@
def match_op(self, op, (exp_opname, exp_res, exp_args, exp_descr, _)):
self._assert(op.name == exp_opname, "operation mismatch")
self.match_var(op.res, exp_res)
- if exp_args != ['...']:
+ if exp_args[-1:] == ['...']: # exp_args ends with '...'
+ exp_args = exp_args[:-1]
+ self._assert(len(op.args) >= len(exp_args), "not enough arguments")
+ else:
self._assert(len(op.args) == len(exp_args), "wrong number of arguments")
- for arg, exp_arg in zip(op.args, exp_args):
- self._assert(self.match_var(arg, exp_arg), "variable mismatch: %r instead of %r" % (arg, exp_arg))
+ for arg, exp_arg in zip(op.args, exp_args):
+ self._assert(self.match_var(arg, exp_arg), "variable mismatch: %r instead of %r" % (arg, exp_arg))
self.match_descr(op.descr, exp_descr)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -158,6 +158,24 @@
assert match_var('v0', 'V0')
assert match_var('ConstPtr(ptr0)', '_')
py.test.raises(AssertionError, "match_var('_', 'v0')")
+ #
+ # numerics
+ assert match_var('1234', '1234')
+ assert not match_var('1234', '1235')
+ assert not match_var('v0', '1234')
+ assert not match_var('1234', 'v0')
+ assert match_var('1234', '#') # the '#' char matches any number
+ assert not match_var('v0', '#')
+ assert match_var('1234', '_') # the '_' char matches anything
+ #
+ # float numerics
+ assert match_var('0.000000', '0.0')
+ assert not match_var('0.000000', '0')
+ assert not match_var('0', '0.0')
+ assert not match_var('v0', '0.0')
+ assert not match_var('0.0', 'v0')
+ assert match_var('0.0', '#')
+ assert match_var('0.0', '_')
def test_parse_op(self):
res = OpMatcher.parse_op(" a = int_add( b, 3 ) # foo")
@@ -210,6 +228,19 @@
"""
assert not self.match(loop, expected)
+ def test_dotdotdot_in_operation(self):
+ loop = """
+ [i0, i1]
+ jit_debug(i0, 1, ConstClass(myclass), i1)
+ """
+ assert self.match(loop, "jit_debug(...)")
+ assert self.match(loop, "jit_debug(i0, ...)")
+ assert self.match(loop, "jit_debug(i0, 1, ...)")
+ assert self.match(loop, "jit_debug(i0, 1, _, ...)")
+ assert self.match(loop, "jit_debug(i0, 1, _, i1, ...)")
+ py.test.raises(AssertionError, self.match,
+ loop, "jit_debug(i0, 1, ..., i1)")
+
def test_match_descr(self):
loop = """
[p0]
@@ -232,7 +263,7 @@
jump(i4)
"""
expected = """
- i1 = int_add(0, 1)
+ i1 = int_add(i0, 1)
...
i4 = int_mul(i1, 1000)
jump(i4, descr=...)
@@ -249,7 +280,7 @@
jump(i4, descr=...)
"""
expected = """
- i1 = int_add(0, 1)
+ i1 = int_add(i0, 1)
...
_ = int_mul(_, 1000)
jump(i4, descr=...)
@@ -268,7 +299,7 @@
jump(i4)
"""
expected = """
- i1 = int_add(0, 1)
+ i1 = int_add(i0, 1)
...
"""
assert self.match(loop, expected)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_buffers.py b/pypy/module/pypyjit/test_pypy_c/test_buffers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_buffers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_buffers.py
@@ -21,7 +21,7 @@
i65 = getfield_gc(p18, descr=...)
i67 = int_gt(0, i65)
guard_false(i67, descr=...)
- i69 = int_gt(., i65)
+ i69 = int_gt(#, i65)
guard_true(i69, descr=...)
--TICK--
""")
@@ -56,7 +56,7 @@
guard_false(i99, descr=...)
i100 = int_lshift(i98, 24)
i101 = int_or(i97, i100)
- i102 = getfield_raw(\d+, descr=<FieldS pypysig_long_struct.c_value 0>)
+ i102 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
i103 = int_lt(i102, 0)
guard_false(i103, descr=...)
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -395,7 +395,7 @@
setarrayitem_gc(p24, 0, p26, descr=<ArrayP .>)
setfield_gc(p22, p24, descr=<FieldP .*Arguments.inst_arguments_w .*>)
}}}
- p32 = call_may_force(..., p18, p22, descr=<Callr . rr EF=6>)
+ p32 = call_may_force(_, p18, p22, descr=<Callr . rr EF=6>)
...
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -82,7 +82,7 @@
guard_no_exception(descr=...)
i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, descr=<Calli . rri EF=4 OS=4>)
guard_no_exception(descr=...)
- i26 = int_and(i23, .*)
+ i26 = int_and(i23, #)
i27 = int_is_true(i26)
guard_false(i27, descr=...)
p28 = getfield_gc(p13, descr=<FieldP dicttable.entries .*>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_math.py b/pypy/module/pypyjit/test_pypy_c/test_math.py
--- a/pypy/module/pypyjit/test_pypy_c/test_math.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_math.py
@@ -21,7 +21,7 @@
guard_true(i2, descr=...)
guard_not_invalidated(descr=...)
f1 = cast_int_to_float(i0)
- i3 = float_le(f1, 0)
+ i3 = float_le(f1, 0.0)
guard_false(i3, descr=...)
f2 = call(ConstClass(log), f1, descr=<Callf . f EF=2>)
f3 = call(ConstClass(log10), f1, descr=<Callf . f EF=2>)
@@ -56,7 +56,7 @@
f3 = call(ConstClass(cos), f1, descr=<Callf . f EF=0>)
f4 = float_sub(f2, f3)
f5 = float_add(f0, f4)
- i7 = int_add(i0, f1)
+ i7 = int_add(i0, 1)
--TICK--
jump(..., descr=)
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -104,7 +104,7 @@
setarrayitem_gc(p150, 1, 0, descr=<ArrayS .+>)
setarrayitem_gc(p150, 0, 0, descr=<ArrayS .+>)
guard_not_invalidated(descr=...)
- i154 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+ i154 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
i155 = int_lt(i154, 0)
guard_false(i155, descr=...)
p156 = new_with_vtable(...)
@@ -142,7 +142,7 @@
raw_store(i103, i132, 42.000000, descr=<ArrayF 8>)
p152 = getfield_gc_pure(p126, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices .+>)
i153 = int_add(i120, 1)
- i154 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+ i154 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
setarrayitem_gc(p152, 1, 0, descr=<ArrayS .+>)
setarrayitem_gc(p152, 0, 0, descr=<ArrayS .+>)
i157 = int_lt(i154, 0)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -67,15 +67,15 @@
i11 = int_lt(i6, i7)
guard_true(i11, descr=...)
guard_not_invalidated(descr=...)
- i13 = int_eq(i6, %d)
+ i13 = int_eq(i6, %d) # value provided below
guard_false(i13, descr=...)
- i15 = int_mod(i6, i8)
- i17 = int_rshift(i15, %d)
- i18 = int_and(i8, i17)
+ i15 = int_mod(i6, 10)
+ i17 = int_rshift(i15, %d) # value provided below
+ i18 = int_and(10, i17)
i19 = int_add(i15, i18)
i21 = int_lt(i19, 0)
guard_false(i21, descr=...)
- i22 = int_ge(i19, i8)
+ i22 = int_ge(i19, 10)
guard_false(i22, descr=...)
i23 = strgetitem(p10, i19)
p25 = newstr(1)
@@ -83,7 +83,7 @@
p93 = call(ConstClass(fromstr), p25, 16, descr=<Callr . ri EF=3>)
guard_no_exception(descr=...)
i95 = getfield_gc_pure(p93, descr=<FieldS rpython.rlib.rbigint.rbigint.inst_size .*>)
- i96 = int_gt(i95, .*)
+ i96 = int_gt(i95, #)
guard_false(i96, descr=...)
i94 = call(ConstClass(rbigint._toint_helper), p93, descr=<Calli . r EF=3>)
guard_no_exception(descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -64,7 +64,7 @@
guard_true(i56, descr=...)
p57 = force_token()
setfield_gc(p0, p57, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
- i58 = call_release_gil(..., i37, 1, descr=<Calli 4 ii EF=6>)
+ i58 = call_release_gil(_, i37, 1, descr=<Calli 4 ii EF=6>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
i59 = int_is_true(i58)
@@ -72,14 +72,14 @@
i60 = int_sub(i44, 1)
p62 = force_token()
setfield_gc(p0, p62, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
- i63 = call_release_gil(..., i37, 0, descr=<Calli 4 ii EF=6>)
+ i63 = call_release_gil(_, i37, 0, descr=<Calli 4 ii EF=6>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
i64 = int_is_true(i63)
guard_false(i64, descr=...)
p65 = force_token()
setfield_gc(p0, p65, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
- call_release_gil(..., i37, descr=<Callv 0 i EF=6>)
+ call_release_gil(_, i37, descr=<Callv 0 i EF=6>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
guard_not_invalidated(descr=...)
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -322,8 +322,8 @@
m.put_int(x.co_stacksize)
m.put_int(x.co_flags)
m.atom_str(TYPE_STRING, x.co_code)
- m.put_tuple_w(TYPE_TUPLE, x.co_consts_w[:])
- m.atom_strlist(TYPE_TUPLE, TYPE_STRING, [space.str_w(w_name) for w_name in x.co_names_w])
+ m.put_tuple_w(TYPE_TUPLE, x.co_consts_w)
+ m.put_tuple_w(TYPE_TUPLE, x.co_names_w)
m.atom_strlist(TYPE_TUPLE, TYPE_STRING, x.co_varnames)
m.atom_strlist(TYPE_TUPLE, TYPE_STRING, x.co_freevars)
m.atom_strlist(TYPE_TUPLE, TYPE_STRING, x.co_cellvars)
@@ -332,9 +332,8 @@
m.put_int(x.co_firstlineno)
m.atom_str(TYPE_STRING, x.co_lnotab)
-# helper for unmarshalling string lists of code objects.
-# unfortunately they now can be interned or referenced,
-# so we no longer can handle it in interp_marshal.atom_strlist
+# helper for unmarshalling "tuple of string" objects
+# into rpython-level lists of strings. Only for code objects.
def unmarshal_str(u):
w_obj = u.get_w_obj()
diff --git a/rpython/flowspace/bytecode.py b/rpython/flowspace/bytecode.py
--- a/rpython/flowspace/bytecode.py
+++ b/rpython/flowspace/bytecode.py
@@ -81,37 +81,37 @@
and **varkwarg, if they exist."""
return self.signature.scope_length()
- def read(self, pos):
+ def read(self, offset):
"""
- Decode the instruction starting at position ``next_instr``.
+ Decode the instruction starting at position ``offset``.
- Returns (next_instr, opname, oparg).
+ Returns (next_offset, opname, oparg).
"""
co_code = self.co_code
- opnum = ord(co_code[pos])
- next_instr = pos + 1
+ opnum = ord(co_code[offset])
+ next_offset = offset + 1
if opnum >= HAVE_ARGUMENT:
- lo = ord(co_code[next_instr])
- hi = ord(co_code[next_instr+1])
- next_instr += 2
+ lo = ord(co_code[next_offset])
+ hi = ord(co_code[next_offset + 1])
+ next_offset += 2
oparg = (hi * 256) | lo
else:
oparg = 0
while opnum == EXTENDED_ARG:
- opnum = ord(co_code[next_instr])
+ opnum = ord(co_code[next_offset])
if opnum < HAVE_ARGUMENT:
raise BytecodeCorruption
- lo = ord(co_code[next_instr+1])
- hi = ord(co_code[next_instr+2])
- next_instr += 3
+ lo = ord(co_code[next_offset + 1])
+ hi = ord(co_code[next_offset + 2])
+ next_offset += 3
oparg = (oparg * 65536) | (hi * 256) | lo
if opnum in opcode.hasjrel:
- oparg += next_instr
+ oparg += next_offset
opname = self.opnames[opnum]
- return next_instr, opname, oparg
+ return next_offset, opname, oparg
@property
def is_generator(self):
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -29,7 +29,7 @@
msg = ["\n"]
msg += map(str, self.args)
msg += [""]
- msg += source_lines(self.ctx.graph, None, offset=self.ctx.last_instr)
+ msg += source_lines(self.ctx.graph, None, offset=self.ctx.last_offset)
return "\n".join(msg)
@@ -288,7 +288,7 @@
self.init_closure(func.func_closure)
self.f_lineno = code.co_firstlineno
- self.last_instr = 0
+ self.last_offset = 0
self.init_locals_stack(code)
@@ -359,7 +359,7 @@
self.locals_stack_w[:len(items_w)] = items_w
self.dropvaluesuntil(len(items_w))
- def getstate(self, next_pos):
+ def getstate(self, next_offset):
# getfastscope() can return real None, for undefined locals
data = self.save_locals_stack()
if self.last_exception is None:
@@ -369,7 +369,7 @@
data.append(self.last_exception.w_type)
data.append(self.last_exception.w_value)
recursively_flatten(data)
- return FrameState(data, self.blockstack[:], next_pos)
+ return FrameState(data, self.blockstack[:], next_offset)
def setstate(self, state):
""" Reset the context to the given frame state. """
@@ -393,7 +393,7 @@
if getattr(recorder, 'final_state', None) is not None:
self.mergeblock(recorder.crnt_block, recorder.final_state)
raise StopFlowing
- spaceop.offset = self.last_instr
+ spaceop.offset = self.last_offset
recorder.append(spaceop)
def do_op(self, op):
@@ -424,12 +424,12 @@
def record_block(self, block):
self.setstate(block.framestate)
- next_pos = block.framestate.next_instr
+ next_offset = block.framestate.next_offset
self.recorder = block.make_recorder()
try:
while True:
- next_pos = self.handle_bytecode(next_pos)
- self.recorder.final_state = self.getstate(next_pos)
+ next_offset = self.handle_bytecode(next_offset)
+ self.recorder.final_state = self.getstate(next_offset)
except RaiseImplicit as e:
w_exc = e.w_exc
@@ -467,10 +467,10 @@
self.recorder = None
def mergeblock(self, currentblock, currentstate):
- next_instr = currentstate.next_instr
+ next_offset = currentstate.next_offset
# can 'currentstate' be merged with one of the blocks that
# already exist for this bytecode position?
- candidates = self.joinpoints.setdefault(next_instr, [])
+ candidates = self.joinpoints.setdefault(next_offset, [])
for block in candidates:
newstate = block.framestate.union(currentstate)
if newstate is not None:
@@ -526,12 +526,12 @@
stack_items_w[i] = w_new
break
- def handle_bytecode(self, next_instr):
- self.last_instr = next_instr
- next_instr, methodname, oparg = self.pycode.read(next_instr)
+ def handle_bytecode(self, next_offset):
+ self.last_offset = next_offset
+ next_offset, methodname, oparg = self.pycode.read(next_offset)
try:
- res = getattr(self, methodname)(oparg)
- return res if res is not None else next_instr
+ offset = getattr(self, methodname)(oparg)
+ return offset if offset is not None else next_offset
except FlowSignal as signal:
return self.unroll(signal)
@@ -856,14 +856,9 @@
def WITH_CLEANUP(self, oparg):
# Note: RPython context managers receive None in lieu of tracebacks
# and cannot suppress the exception.
- # This opcode changed a lot between CPython versions
- if sys.version_info >= (2, 6):
- unroller = self.popvalue()
- w_exitfunc = self.popvalue()
- self.pushvalue(unroller)
- else:
- w_exitfunc = self.popvalue()
- unroller = self.peekvalue(0)
+ unroller = self.popvalue()
+ w_exitfunc = self.popvalue()
+ self.pushvalue(unroller)
if isinstance(unroller, Raise):
w_exc = unroller.w_exc
diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py
--- a/rpython/flowspace/framestate.py
+++ b/rpython/flowspace/framestate.py
@@ -3,10 +3,10 @@
class FrameState(object):
- def __init__(self, mergeable, blocklist, next_instr):
+ def __init__(self, mergeable, blocklist, next_offset):
self.mergeable = mergeable
self.blocklist = blocklist
- self.next_instr = next_instr
+ self.next_offset = next_offset
def copy(self):
"Make a copy of this state in which all Variables are fresh."
@@ -15,7 +15,7 @@
if isinstance(w, Variable):
w = Variable(w)
newstate.append(w)
- return FrameState(newstate, self.blocklist, self.next_instr)
+ return FrameState(newstate, self.blocklist, self.next_offset)
def getvariables(self):
return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -26,7 +26,7 @@
# safety check, don't try to compare states with different
# nonmergeable states
assert self.blocklist == other.blocklist
- assert self.next_instr == other.next_instr
+ assert self.next_offset == other.next_offset
for w1, w2 in zip(self.mergeable, other.mergeable):
if not (w1 == w2 or (isinstance(w1, Variable) and
isinstance(w2, Variable))):
@@ -44,7 +44,7 @@
newstate.append(union(w1, w2))
except UnionError:
return None
- return FrameState(newstate, self.blocklist, self.next_instr)
+ return FrameState(newstate, self.blocklist, self.next_offset)
def getoutputargs(self, targetstate):
"Return the output arguments needed to link self to targetstate."
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1832,15 +1832,17 @@
offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
mc.MOV_br(offset, ebx.value)
- # now we return from the complete frame, which starts from
- # _call_header_with_stack_check(). The LEA in _call_footer below
- # throws away most of the frame, including all the PUSHes that we
- # did just above.
+ # fill in the jf_descr and jf_gcmap fields of the frame according
+ # to which failure we are resuming from. These are constants
+ # pushed on the stack just before we jump to the current helper,
+ # in generate_quick_failure().
ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
mc.POP_b(ofs2)
mc.POP_b(ofs)
+ # now we return from the complete frame, which starts from
+ # _call_header_with_stack_check(). The _call_footer below does it.
self._call_footer()
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
self.failure_recovery_code[exc + 2 * withfloats] = rawstart
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
@@ -216,8 +216,8 @@
# fall-back number.
"nursery_size": 896*1024,
- # The system page size. Like obmalloc.c, we assume that it is 4K
- # for 32-bit systems; unlike obmalloc.c, we assume that it is 8K
+ # The system page size. Like malloc, we assume that it is 4K
+ # for 32-bit systems; unlike malloc, we assume that it is 8K
# for 64-bit systems, for consistent results.
"page_size": 1024*WORD,
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -174,8 +174,8 @@
# fall-back number.
"nursery_size": 896*1024,
- # The system page size. Like obmalloc.c, we assume that it is 4K
- # for 32-bit systems; unlike obmalloc.c, we assume that it is 8K
+ # The system page size. Like malloc, we assume that it is 4K
+ # for 32-bit systems; unlike malloc, we assume that it is 8K
# for 64-bit systems, for consistent results.
"page_size": 1024*WORD,
diff --git a/rpython/memory/gc/minimarktest.py b/rpython/memory/gc/minimarktest.py
--- a/rpython/memory/gc/minimarktest.py
+++ b/rpython/memory/gc/minimarktest.py
@@ -5,7 +5,7 @@
from rpython.rlib.rarithmetic import LONG_BIT
# For testing, a simple implementation of ArenaCollection.
-# This version could be used together with obmalloc.c, but
+# This version could be used together with malloc, but
# it requires an extra word per object in the 'all_objects'
# list.
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
@@ -461,17 +461,18 @@
annmodel.SomeInteger(nonneg=True)],
annmodel.s_None)
- self.pin_ptr = getfn(GCClass.pin,
- [s_gc, SomeAddress()],
- annmodel.SomeBool())
+ if GCClass.can_usually_pin_objects:
+ self.pin_ptr = getfn(GCClass.pin,
+ [s_gc, SomeAddress()],
+ annmodel.SomeBool())
- self.unpin_ptr = getfn(GCClass.unpin,
- [s_gc, SomeAddress()],
- annmodel.s_None)
+ self.unpin_ptr = getfn(GCClass.unpin,
+ [s_gc, SomeAddress()],
+ annmodel.s_None)
- self._is_pinned_ptr = getfn(GCClass._is_pinned,
- [s_gc, SomeAddress()],
- annmodel.SomeBool())
+ self._is_pinned_ptr = getfn(GCClass._is_pinned,
+ [s_gc, SomeAddress()],
+ annmodel.SomeBool())
self.write_barrier_ptr = None
self.write_barrier_from_array_ptr = None
@@ -1042,6 +1043,10 @@
v_size])
def gct_gc_pin(self, hop):
+ if not hasattr(self, 'pin_ptr'):
+ c_false = rmodel.inputconst(lltype.Bool, False)
+ hop.genop("same_as", [c_false], resultvar=hop.spaceop.result)
+ return
op = hop.spaceop
v_addr = hop.genop('cast_ptr_to_adr', [op.args[0]],
resulttype=llmemory.Address)
@@ -1049,6 +1054,8 @@
resultvar=op.result)
def gct_gc_unpin(self, hop):
+ if not hasattr(self, 'unpin_ptr'):
+ return
op = hop.spaceop
v_addr = hop.genop('cast_ptr_to_adr', [op.args[0]],
resulttype=llmemory.Address)
@@ -1056,6 +1063,10 @@
resultvar=op.result)
def gct_gc__is_pinned(self, hop):
+ if not hasattr(self, '_is_pinned_ptr'):
+ c_false = rmodel.inputconst(lltype.Bool, False)
+ hop.genop("same_as", [c_false], resultvar=hop.spaceop.result)
+ return
op = hop.spaceop
v_addr = hop.genop('cast_ptr_to_adr', [op.args[0]],
resulttype=llmemory.Address)
diff --git a/rpython/rlib/rweakref.py b/rpython/rlib/rweakref.py
--- a/rpython/rlib/rweakref.py
+++ b/rpython/rlib/rweakref.py
@@ -105,7 +105,7 @@
rtyper.getrepr(self.s_key))
def rtyper_makekey(self):
- return self.__class__,
+ return self.__class__, self.s_key.rtyper_makekey(), self.valueclassdef
def method_get(self, s_key):
return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
@@ -165,7 +165,7 @@
return _rweakkeydict.WeakKeyDictRepr(rtyper)
def rtyper_makekey(self):
- return self.__class__,
+ return self.__class__, self.keyclassdef, self.valueclassdef
def method_get(self, s_key):
assert isinstance(s_key, annmodel.SomeInstance)
diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -311,7 +311,7 @@
assert isinstance(lst, list)
found = False
for family, socktype, protocol, canonname, addr in lst:
- if addr.get_host() == '140.211.10.69':
+ if addr.get_host() == '104.130.43.121':
found = True
result[i] += found
diff --git a/rpython/rlib/test/test_rweakvaldict.py b/rpython/rlib/test/test_rweakvaldict.py
--- a/rpython/rlib/test/test_rweakvaldict.py
+++ b/rpython/rlib/test/test_rweakvaldict.py
@@ -144,3 +144,13 @@
d = RWeakValueDictionary(str, Y)
d.set("x", X())
py.test.raises(Exception, interpret, g, [1])
+
+
+def test_bogus_makekey():
+ class X: pass
+ class Y: pass
+ def g():
+ X(); Y()
+ RWeakValueDictionary(str, X).get("foobar")
+ RWeakValueDictionary(int, Y).get(42)
+ interpret(g, [])
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -100,7 +100,6 @@
def test_string_reverse(self):
c_source = py.code.Source("""
#include <string.h>
- #include <src/allocator.h>
#include <src/mem.h>
char *f(char* arg)
diff --git a/rpython/rtyper/normalizecalls.py b/rpython/rtyper/normalizecalls.py
--- a/rpython/rtyper/normalizecalls.py
+++ b/rpython/rtyper/normalizecalls.py
@@ -298,12 +298,16 @@
# ____________________________________________________________
+class TooLateForNewSubclass(Exception):
+ pass
+
class TotalOrderSymbolic(ComputedIntSymbolic):
def __init__(self, orderwitness, peers):
self.orderwitness = orderwitness
self.peers = peers
self.value = None
+ self._with_subclasses = None # unknown
peers.append(self)
def __cmp__(self, other):
@@ -320,12 +324,34 @@
def __rsub__(self, other):
return other - self.compute_fn()
+ def check_any_subclass_in_peer_list(self, i):
+ # check if the next peer, in order, is or not the end
+ # marker for this start marker
+ assert self.peers[i] is self
+ return self.peers[i + 1].orderwitness != self.orderwitness + [MAX]
+
+ def number_with_subclasses(self):
+ # Return True or False depending on whether this is the
+ # subclassrange_min corresponding to a class which has subclasses
+ # or not. If this is called and returns False, then adding later
+ # new subclasses will crash in compute_fn().
+ if self._with_subclasses is None: # unknown so far
+ self.peers.sort()
+ i = self.peers.index(self)
+ self._with_subclasses = self.check_any_subclass_in_peer_list(i)
+ return self._with_subclasses
+
def compute_fn(self):
if self.value is None:
self.peers.sort()
for i, peer in enumerate(self.peers):
assert peer.value is None or peer.value == i
peer.value = i
+ #
+ if peer._with_subclasses is False:
+ if peer.check_any_subclass_in_peer_list(i):
+ raise TooLateForNewSubclass
+ #
assert self.value is not None
return self.value
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -1007,14 +1007,11 @@
v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
if isinstance(v_cls, Constant):
cls = v_cls.value
- # XXX re-implement the following optimization
- #if cls.subclassrange_max == cls.subclassrange_min:
- # # a class with no subclass
- # return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls)
- #else:
- minid = hop.inputconst(Signed, cls.subclassrange_min)
- maxid = hop.inputconst(Signed, cls.subclassrange_max)
- return hop.gendirectcall(ll_isinstance_const, v_obj, minid, maxid)
+ llf, llf_nonnull = make_ll_isinstance(self.rtyper, cls)
+ if hop.args_s[0].can_be_None:
+ return hop.gendirectcall(llf, v_obj)
+ else:
+ return hop.gendirectcall(llf_nonnull, v_obj)
else:
return hop.gendirectcall(ll_isinstance, v_obj, v_cls)
@@ -1128,16 +1125,26 @@
obj_cls = obj.typeptr
return ll_issubclass(obj_cls, cls)
-def ll_isinstance_const(obj, minid, maxid):
- if not obj:
- return False
- return ll_issubclass_const(obj.typeptr, minid, maxid)
-
-def ll_isinstance_exact(obj, cls):
- if not obj:
- return False
- obj_cls = obj.typeptr
- return obj_cls == cls
+def make_ll_isinstance(rtyper, cls):
+ try:
+ return rtyper.isinstance_helpers[cls._obj]
+ except KeyError:
+ minid = cls.subclassrange_min
+ maxid = cls.subclassrange_max
+ if minid.number_with_subclasses():
+ def ll_isinstance_const_nonnull(obj):
+ objid = obj.typeptr.subclassrange_min
+ return llop.int_between(Bool, minid, objid, maxid)
+ else:
+ def ll_isinstance_const_nonnull(obj):
+ return obj.typeptr == cls
+ def ll_isinstance_const(obj):
+ if not obj:
+ return False
+ return ll_isinstance_const_nonnull(obj)
+ result = (ll_isinstance_const, ll_isinstance_const_nonnull)
+ rtyper.isinstance_helpers[cls._obj] = result
+ return result
def ll_runtime_type_info(obj):
return obj.typeptr.rtti
diff --git a/rpython/rtyper/rtyper.py b/rpython/rtyper/rtyper.py
--- a/rpython/rtyper/rtyper.py
+++ b/rpython/rtyper/rtyper.py
@@ -59,6 +59,7 @@
self.typererror_count = 0
# make the primitive_to_repr constant mapping
self.primitive_to_repr = {}
+ self.isinstance_helpers = {}
self.exceptiondata = ExceptionData(self)
self.custom_trace_funcs = []
diff --git a/rpython/rtyper/test/test_normalizecalls.py b/rpython/rtyper/test/test_normalizecalls.py
--- a/rpython/rtyper/test/test_normalizecalls.py
+++ b/rpython/rtyper/test/test_normalizecalls.py
@@ -6,6 +6,7 @@
from rpython.rtyper.test.test_llinterp import interpret
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.normalizecalls import TotalOrderSymbolic, MAX
+from rpython.rtyper.normalizecalls import TooLateForNewSubclass
def test_TotalOrderSymbolic():
@@ -21,6 +22,49 @@
assert t1 <= 5
assert t1.value == 0
+def test_TotalOrderSymbolic_with_subclasses():
+ lst = []
+ t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst)
+ t1 = TotalOrderSymbolic([3, 4], lst)
+ t2 = TotalOrderSymbolic([3, 4, 2], lst)
+ t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+ assert t1.number_with_subclasses()
+ assert not t2.number_with_subclasses()
+ assert [t.compute_fn() for t in [t1, t2, t3, t4]] == range(4)
+ #
+ lst = []
+ t1 = TotalOrderSymbolic([3, 4], lst)
+ t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst)
+ t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+ t2 = TotalOrderSymbolic([3, 4, 2], lst)
+ assert not t2.number_with_subclasses()
+ assert t1.number_with_subclasses()
+ assert [t.compute_fn() for t in [t1, t2, t3, t4]] == range(4)
+ #
+ lst = []
+ t1 = TotalOrderSymbolic([3, 4], lst)
+ t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+ assert not t1.number_with_subclasses()
+ t2 = TotalOrderSymbolic([3, 4, 2], lst)
+ t3 = TotalOrderSymbolic([3, 4, 2, MAX], lst)
+ py.test.raises(TooLateForNewSubclass, t2.compute_fn)
+ #
+ lst = []
+ t1 = TotalOrderSymbolic([3, 4], lst)
+ t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+ assert not t1.number_with_subclasses()
+ t2 = TotalOrderSymbolic([1], lst)
+ t3 = TotalOrderSymbolic([1, MAX], lst)
+ assert [t.compute_fn() for t in [t2, t3, t1, t4]] == range(4)
+ #
+ lst = []
+ t1 = TotalOrderSymbolic([3, 4], lst)
+ t4 = TotalOrderSymbolic([3, 4, MAX], lst)
+ assert not t1.number_with_subclasses()
+ t2 = TotalOrderSymbolic([6], lst)
+ t3 = TotalOrderSymbolic([6, MAX], lst)
+ assert [t.compute_fn() for t in [t1, t4, t2, t3]] == range(4)
+
# ____________________________________________________________
class TestNormalize(object):
diff --git a/rpython/tool/jitlogparser/parser.py b/rpython/tool/jitlogparser/parser.py
--- a/rpython/tool/jitlogparser/parser.py
+++ b/rpython/tool/jitlogparser/parser.py
@@ -216,7 +216,7 @@
line_starts_here = property(getline_starts_here)
def __repr__(self):
- return "[%s]" % ", ".join([repr(op) for op in self.operations])
+ return "[%s\n]" % "\n ".join([repr(op) for op in self.operations])
def pretty_print(self, out):
pass
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -405,8 +405,6 @@
('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" debug_target'),
('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" debug_target'),
('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DPYPY_USE_TRIVIAL_MALLOC" debug_target'),
- ('no_obmalloc', '', '$(MAKE) CFLAGS="-g -O2 -DRPY_ASSERT -DPYPY_NO_OBMALLOC" $(TARGET)'),
- ('linuxmemchk', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DPYPY_USE_LINUXMEMCHK" debug_target'),
('llsafer', '', '$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(TARGET)'),
('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
('lldebug0','', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -O0 -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
@@ -762,7 +760,6 @@
srcdir = py.path.local(__file__).join('..', 'src')
files = [
srcdir / 'entrypoint.c', # ifdef PYPY_STANDALONE
- srcdir / 'allocator.c', # ifdef PYPY_STANDALONE
srcdir / 'mem.c',
srcdir / 'exception.c',
srcdir / 'rtyper.c', # ifdef HAVE_RTYPER
diff --git a/rpython/translator/c/src/allocator.c b/rpython/translator/c/src/allocator.c
deleted file mode 100644
--- a/rpython/translator/c/src/allocator.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* allocation functions */
-#include "common_header.h"
-#ifdef PYPY_STANDALONE
-#include <stdlib.h>
-
-#if defined(PYPY_USE_TRIVIAL_MALLOC)
- void *PyObject_Malloc(size_t n) { return malloc(n); }
- void *PyObject_Realloc(void *p, size_t n) { return realloc(p, n); }
- void PyObject_Free(void *p) { if (p) { *((int*)p) = 0xDDDDDDDD; } free(p); }
-
-#elif defined(PYPY_USE_LINUXMEMCHK)
-# include "linuxmemchk.c"
-
-#elif defined(PYPY_NO_OBMALLOC)
- void *PyObject_Malloc(size_t n) { return malloc(n); }
- void *PyObject_Realloc(void *p, size_t n) { return realloc(p, n); }
- void PyObject_Free(void *p) { free(p); }
-
-#else
-# ifndef WITH_PYMALLOC
-# define WITH_PYMALLOC
-# endif
-/* The same obmalloc as CPython */
-# include "src/obmalloc.c"
-
-#endif
-#elif defined _MSC_VER
-/* link will fail without some kind of definition for the functions */
- void *PyObject_Malloc(size_t n) { return NULL; }
- void *PyObject_Realloc(void *p, size_t n) { return NULL; }
- void PyObject_Free(void *p) { }
-
-#endif /* PYPY_STANDALONE */
diff --git a/rpython/translator/c/src/allocator.h b/rpython/translator/c/src/allocator.h
deleted file mode 100644
--- a/rpython/translator/c/src/allocator.h
+++ /dev/null
@@ -1,4 +0,0 @@
-/* allocation functions prototypes */
-RPY_EXTERN void *PyObject_Malloc(size_t n);
-RPY_EXTERN void *PyObject_Realloc(void *p, size_t n);
-RPY_EXTERN void PyObject_Free(void *p);
diff --git a/rpython/translator/c/src/g_include.h b/rpython/translator/c/src/g_include.h
--- a/rpython/translator/c/src/g_include.h
+++ b/rpython/translator/c/src/g_include.h
@@ -33,7 +33,6 @@
# include "src/debug_traceback.h"
#endif
-# include "src/allocator.h"
#ifdef PYPY_STANDALONE
# include "src/entrypoint.h"
#endif
diff --git a/rpython/translator/c/src/linuxmemchk.c b/rpython/translator/c/src/linuxmemchk.c
deleted file mode 100644
--- a/rpython/translator/c/src/linuxmemchk.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* custom checking allocators a la Electric Fence */
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define PAGESIZE 4096
-#ifndef MALLOC_BIGBUFFER
-# define MALLOC_BIGBUFFER (PAGESIZE*32768) /* 128MB */
-#endif
-
-
-struct _alloc_s {
- void* ptr;
- int npages;
-};
-static void* _na_start = NULL;
-static char* _na_cur;
-
-static void _na_assert(int x, char* msg)
-{
- if (!x)
- {
- fprintf(stderr, "linuxmemchk: failed assertion: %s\n", msg);
- abort();
- }
-}
-
-static struct _alloc_s* _na_find(void* data)
-{
- int err;
- long data1;
- struct _alloc_s* s;
- _na_assert(_na_start+PAGESIZE <= data &&
- data < _na_start+MALLOC_BIGBUFFER-PAGESIZE,
- "corrupted na_start");
- data1 = (long) data;
- data1 &= ~(PAGESIZE-1);
- data1 -= PAGESIZE;
- err = mprotect((void*) data1, PAGESIZE, PROT_READ|PROT_WRITE);
- _na_assert(!err, "mprotect[1] failed");
- s = (struct _alloc_s*) data1;
- _na_assert(s->npages > 0, "corrupted s->npages");
- return s;
-}
-
-void* PyObject_Malloc(size_t size)
-{
- int err, npages = (size + PAGESIZE-1) / PAGESIZE + 1;
- struct _alloc_s* s;
- char* data;
- if (_na_start == NULL)
- {
- _na_start = mmap(NULL, MALLOC_BIGBUFFER, PROT_NONE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- _na_assert(_na_start != MAP_FAILED, "initial mmap failed");
- _na_cur = (char*) _na_start;
- }
- s = (struct _alloc_s*) _na_cur;
- _na_cur += npages * PAGESIZE;
- if (_na_cur >= ((char*) _na_start) + MALLOC_BIGBUFFER)
- {
- fprintf(stderr, "linuxmemchk.c: Nothing wrong so far, but we are running out\nlinuxmemchk.c: of mmap'ed memory. Increase MALLOC_BIGBUFFER.\n");
- abort();
- }
- err = mprotect(s, npages * PAGESIZE, PROT_READ|PROT_WRITE|PROT_EXEC);
- _na_assert(!err, "mprotect[2] failed");
- s->ptr = data = _na_cur - /*((size+3)&~3)*/ size;
- s->npages = npages;
- err = mprotect(s, PAGESIZE, PROT_NONE);
- _na_assert(!err, "mprotect[3] failed");
- return data;
-}
-
-void PyObject_Free(void* data)
-{
- int err, npages;
- struct _alloc_s* s;
- if (data == NULL)
- return;
- s = _na_find(data);
- _na_assert(s->ptr == data, "free got a pointer not returned by malloc");
- npages = s->npages;
- s->npages = 0;
- err = mprotect(s, npages * PAGESIZE, PROT_NONE);
- _na_assert(!err, "mprotect[4] failed");
-}
-
-void* PyObject_Realloc(void* data, size_t nsize)
-{
- size_t size;
- struct _alloc_s* s = _na_find(data);
- void* ndata = PyObject_Malloc(nsize);
-
- _na_assert(s->ptr == data, "realloc got a pointer not returned by malloc");
- size = ((char*)s) + s->npages * PAGESIZE - (char*)data;
- memcpy(ndata, data, size<nsize ? size : nsize);
- PyObject_Free(data);
- return ndata;
-}
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -9,13 +9,13 @@
#define OP_RAW_MALLOC(size, r, restype) { \
- r = (restype) PyObject_Malloc(size); \
+ r = (restype) malloc(size); \
if (r != NULL) { \
COUNT_MALLOC; \
} \
}
-#define OP_RAW_FREE(p, r) PyObject_Free(p); COUNT_FREE;
+#define OP_RAW_FREE(p, r) free(p); COUNT_FREE;
#define OP_RAW_MEMCLEAR(p, size, r) memset((void*)p, 0, size)
#define OP_RAW_MEMSET(p, byte, size, r) memset((void*)p, byte, size)
diff --git a/rpython/translator/c/src/obmalloc.c b/rpython/translator/c/src/obmalloc.c
deleted file mode 100644
--- a/rpython/translator/c/src/obmalloc.c
+++ /dev/null
@@ -1,1418 +0,0 @@
-
-#ifdef WITH_PYMALLOC
-
-#include <string.h>
-#include <assert.h>
-
-/* An object allocator for Python.
-
- Here is an introduction to the layers of the Python memory architecture,
- showing where the object allocator is actually used (layer +2), It is
- called for every object allocation and deallocation (PyObject_New/Del),
- unless the object-specific allocators implement a proprietary allocation
- scheme (ex.: ints use a simple free list). This is also the place where
- the cyclic garbage collector operates selectively on container objects.
-
-
- Object-specific allocators
- _____ ______ ______ ________
- [ int ] [ dict ] [ list ] ... [ string ] Python core |
-+3 | <----- Object-specific memory -----> | <-- Non-object memory --> |
- _______________________________ | |
- [ Python's object allocator ] | |
-+2 | ####### Object memory ####### | <------ Internal buffers ------> |
- ______________________________________________________________ |
- [ Python's raw memory allocator (PyMem_ API) ] |
-+1 | <----- Python memory (under PyMem manager's control) ------> | |
- __________________________________________________________________
- [ Underlying general-purpose allocator (ex: C library malloc) ]
- 0 | <------ Virtual memory allocated for the python process -------> |
-
- =========================================================================
- _______________________________________________________________________
- [ OS-specific Virtual Memory Manager (VMM) ]
--1 | <--- Kernel dynamic storage allocation & management (page-based) ---> |
- __________________________________ __________________________________
- [ ] [ ]
--2 | <-- Physical memory: ROM/RAM --> | | <-- Secondary storage (swap) --> |
-
-*/
-/*==========================================================================*/
-
-/* A fast, special-purpose memory allocator for small blocks, to be used
- on top of a general-purpose malloc -- heavily based on previous art. */
-
-/* Vladimir Marangozov -- August 2000 */
-
-/*
- * "Memory management is where the rubber meets the road -- if we do the wrong
- * thing at any level, the results will not be good. And if we don't make the
- * levels work well together, we are in serious trouble." (1)
- *
- * (1) Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,
- * "Dynamic Storage Allocation: A Survey and Critical Review",
- * in Proc. 1995 Int'l. Workshop on Memory Management, September 1995.
- */
-
More information about the pypy-commit
mailing list