[pypy-commit] pypy jit-targets: hg merge default
hakanardo
noreply at buildbot.pypy.org
Sun Dec 4 20:10:03 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r50141:a18379234939
Date: 2011-12-04 20:08 +0100
http://bitbucket.org/pypy/pypy/changeset/a18379234939/
Log: hg merge default
diff --git a/lib_pypy/_sha.py b/lib_pypy/_sha.py
--- a/lib_pypy/_sha.py
+++ b/lib_pypy/_sha.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# -*- coding: iso-8859-1
+# -*- coding: iso-8859-1 -*-
# Note that PyPy contains also a built-in module 'sha' which will hide
# this one if compiled in.
diff --git a/lib_pypy/itertools.py b/lib_pypy/itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/itertools.py
@@ -25,7 +25,7 @@
__all__ = ['chain', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter',
'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
- 'takewhile', 'tee']
+ 'takewhile', 'tee', 'compress', 'product']
try: from __pypy__ import builtinify
except ImportError: builtinify = lambda f: f
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -252,7 +252,26 @@
# unsignedness is considered a rare and contagious disease
def union((int1, int2)):
- knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+ if int1.unsigned == int2.unsigned:
+ knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+ else:
+ t1 = int1.knowntype
+ if t1 is bool:
+ t1 = int
+ t2 = int2.knowntype
+ if t2 is bool:
+ t2 = int
+
+ if t2 is int:
+ if int2.nonneg == False:
+ raise UnionError, "Merging %s and a possibly negative int is not allowed" % t1
+ knowntype = t1
+ elif t1 is int:
+ if int1.nonneg == False:
+ raise UnionError, "Merging %s and a possibly negative int is not allowed" % t2
+ knowntype = t2
+ else:
+ raise UnionError, "Merging these types (%s, %s) is not supported" % (t1, t2)
return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
knowntype=knowntype)
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -591,13 +591,11 @@
immutable = True
def __init__(self, method):
self.method = method
-
-NUMBER = object()
+
annotation_to_ll_map = [
(SomeSingleFloat(), lltype.SingleFloat),
(s_None, lltype.Void), # also matches SomeImpossibleValue()
(s_Bool, lltype.Bool),
- (SomeInteger(knowntype=r_ulonglong), NUMBER),
(SomeFloat(), lltype.Float),
(SomeLongFloat(), lltype.LongFloat),
(SomeChar(), lltype.Char),
@@ -623,10 +621,11 @@
return lltype.Ptr(p.PARENTTYPE)
if isinstance(s_val, SomePtr):
return s_val.ll_ptrtype
+ if type(s_val) is SomeInteger:
+ return lltype.build_number(None, s_val.knowntype)
+
for witness, T in annotation_to_ll_map:
if witness.contains(s_val):
- if T is NUMBER:
- return lltype.build_number(None, s_val.knowntype)
return T
if info is None:
info = ''
@@ -635,7 +634,7 @@
raise ValueError("%sshould return a low-level type,\ngot instead %r" % (
info, s_val))
-ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map if ll is not NUMBER])
+ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map])
def lltype_to_annotation(T):
try:
diff --git a/pypy/annotation/specialize.py b/pypy/annotation/specialize.py
--- a/pypy/annotation/specialize.py
+++ b/pypy/annotation/specialize.py
@@ -36,9 +36,7 @@
newtup = SpaceOperation('newtuple', starargs, argscopy[-1])
newstartblock.operations.append(newtup)
newstartblock.closeblock(Link(argscopy, graph.startblock))
- graph.startblock.isstartblock = False
graph.startblock = newstartblock
- newstartblock.isstartblock = True
argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
graph.signature = Signature(argnames)
# note that we can mostly ignore defaults: if nb_extra_args > 0,
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -856,6 +856,46 @@
py.test.raises(Exception, a.build_types, f, [])
# if you want to get a r_uint, you have to be explicit about it
+ def test_add_different_ints(self):
+ def f(a, b):
+ return a + b
+ a = self.RPythonAnnotator()
+ py.test.raises(Exception, a.build_types, f, [r_uint, int])
+
+ def test_merge_different_ints(self):
+ def f(a, b):
+ if a:
+ c = a
+ else:
+ c = b
+ return c
+ a = self.RPythonAnnotator()
+ py.test.raises(Exception, a.build_types, f, [r_uint, int])
+
+ def test_merge_ruint_zero(self):
+ def f(a):
+ if a:
+ c = a
+ else:
+ c = 0
+ return c
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [r_uint])
+ assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
+
+ def test_merge_ruint_nonneg_signed(self):
+ def f(a, b):
+ if a:
+ c = a
+ else:
+ assert b >= 0
+ c = b
+ return c
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [r_uint, int])
+ assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
+
+
def test_prebuilt_long_that_is_not_too_long(self):
small_constant = 12L
def f():
@@ -3029,7 +3069,7 @@
if g(x, y):
g(x, r_uint(y))
a = self.RPythonAnnotator()
- a.build_types(f, [int, int])
+ py.test.raises(Exception, a.build_types, f, [int, int])
def test_compare_with_zero(self):
def g():
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -69,8 +69,8 @@
"statistics": [("translation.gctransformer", "framework")],
"generation": [("translation.gctransformer", "framework")],
"hybrid": [("translation.gctransformer", "framework")],
- "boehm": [("translation.gctransformer", "boehm"),
- ("translation.continuation", False)], # breaks
+ "boehm": [("translation.continuation", False), # breaks
+ ("translation.gctransformer", "boehm")],
"markcompact": [("translation.gctransformer", "framework")],
"minimark": [("translation.gctransformer", "framework")],
},
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
@@ -304,5 +304,14 @@
never a dictionary as it sometimes is in CPython. Assigning to
``__builtins__`` has no effect.
+* directly calling the internal magic methods of a few built-in types
+ with invalid arguments may have a slightly different result. For
+ example, ``[].__add__(None)`` and ``(2).__add__(None)`` both return
+ ``NotImplemented`` on PyPy; on CPython, only the later does, and the
+ former raises ``TypeError``. (Of course, ``[]+None`` and ``2+None``
+ both raise ``TypeError`` everywhere.) This difference is an
+ implementation detail that shows up because of internal C-level slots
+ that PyPy does not have.
+
.. include:: _ref.txt
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -15,7 +15,7 @@
* `FAQ`_: some frequently asked questions.
-* `Release 1.6`_: the latest official release
+* `Release 1.7`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -75,7 +75,7 @@
.. _`Getting Started`: getting-started.html
.. _`Papers`: extradoc.html
.. _`Videos`: video-index.html
-.. _`Release 1.6`: http://pypy.org/download.html
+.. _`Release 1.7`: http://pypy.org/download.html
.. _`speed.pypy.org`: http://speed.pypy.org
.. _`RPython toolchain`: translation.html
.. _`potential project ideas`: project-ideas.html
@@ -120,9 +120,9 @@
Windows, on top of .NET, and on top of Java.
To dig into PyPy it is recommended to try out the current
Mercurial default branch, which is always working or mostly working,
-instead of the latest release, which is `1.6`__.
+instead of the latest release, which is `1.7`__.
-.. __: release-1.6.0.html
+.. __: release-1.7.0.html
PyPy is mainly developed on Linux and Mac OS X. Windows is supported,
but platform-specific bugs tend to take longer before we notice and fix
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -10,7 +10,7 @@
from pypy.rlib.objectmodel import we_are_translated, instantiate
from pypy.rlib.jit import hint
from pypy.rlib.debug import make_sure_not_resized, check_nonneg
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
from pypy.rlib import jit
from pypy.tool import stdlib_opcode
from pypy.tool.stdlib_opcode import host_bytecode_spec
@@ -167,7 +167,7 @@
# Execution starts just after the last_instr. Initially,
# last_instr is -1. After a generator suspends it points to
# the YIELD_VALUE instruction.
- next_instr = self.last_instr + 1
+ next_instr = r_uint(self.last_instr + 1)
if next_instr != 0:
self.pushvalue(w_inputvalue)
#
@@ -691,6 +691,7 @@
handlerposition = space.int_w(w_handlerposition)
valuestackdepth = space.int_w(w_valuestackdepth)
assert valuestackdepth >= 0
+ assert handlerposition >= 0
blk = instantiate(get_block_class(opname))
blk.handlerposition = handlerposition
blk.valuestackdepth = valuestackdepth
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -837,6 +837,7 @@
raise Yield
def jump_absolute(self, jumpto, next_instr, ec):
+ check_nonneg(jumpto)
return jumpto
def JUMP_FORWARD(self, jumpby, next_instr):
@@ -1278,7 +1279,7 @@
def handle(self, frame, unroller):
next_instr = self.really_handle(frame, unroller) # JIT hack
- return next_instr
+ return r_uint(next_instr)
def really_handle(self, frame, unroller):
""" Purely abstract method
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -21,7 +21,7 @@
from pypy.jit.backend.llgraph import symbolic
from pypy.jit.codewriter import longlong
-from pypy.rlib import libffi
+from pypy.rlib import libffi, clibffi
from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
@@ -1464,6 +1464,10 @@
res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
return res
+def do_getinteriorfield_raw_float(array, index, width, ofs):
+ res = _getinteriorfield_raw(libffi.types.double, array, index, width, ofs)
+ return res
+
def _getfield_raw(struct, fieldnum):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1542,12 +1546,17 @@
do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
-def new_setinteriorfield_raw(ffitype):
+def new_setinteriorfield_raw(cast_func, ffitype):
def do_setinteriorfield_raw(array, index, newvalue, width, ofs):
addr = rffi.cast(rffi.VOIDP, array)
+ for TYPE, ffitype2 in clibffi.ffitype_map:
+ if ffitype2 is ffitype:
+ newvalue = cast_func(TYPE, newvalue)
+ break
return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
return do_setinteriorfield_raw
-do_setinteriorfield_raw_int = new_setinteriorfield_raw(libffi.types.slong)
+do_setinteriorfield_raw_int = new_setinteriorfield_raw(cast_from_int, libffi.types.slong)
+do_setinteriorfield_raw_float = new_setinteriorfield_raw(cast_from_floatstorage, libffi.types.double)
def do_setfield_raw_int(struct, fieldnum, newvalue):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
diff --git a/pypy/jit/backend/llsupport/asmmemmgr.py b/pypy/jit/backend/llsupport/asmmemmgr.py
--- a/pypy/jit/backend/llsupport/asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/asmmemmgr.py
@@ -37,25 +37,25 @@
self._add_free_block(smaller_stop, stop)
stop = smaller_stop
result = (start, stop)
- self.total_mallocs += stop - start
+ self.total_mallocs += r_uint(stop - start)
return result # pair (start, stop)
def free(self, start, stop):
"""Free a block (start, stop) returned by a previous malloc()."""
- self.total_mallocs -= (stop - start)
+ self.total_mallocs -= r_uint(stop - start)
self._add_free_block(start, stop)
def open_malloc(self, minsize):
"""Allocate at least minsize bytes. Returns (start, stop)."""
result = self._allocate_block(minsize)
(start, stop) = result
- self.total_mallocs += stop - start
+ self.total_mallocs += r_uint(stop - start)
return result
def open_free(self, middle, stop):
"""Used for freeing the end of an open-allocated block of memory."""
if stop - middle >= self.min_fragment:
- self.total_mallocs -= (stop - middle)
+ self.total_mallocs -= r_uint(stop - middle)
self._add_free_block(middle, stop)
return True
else:
@@ -77,7 +77,7 @@
# Hack to make sure that mcs are not within 32-bits of one
# another for testing purposes
rmmap.hint.pos += 0x80000000 - size
- self.total_memory_allocated += size
+ self.total_memory_allocated += r_uint(size)
data = rffi.cast(lltype.Signed, data)
return self._add_free_block(data, data + size)
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -648,14 +648,10 @@
# make a malloc function, with two arguments
def malloc_basic(size, tid):
type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
- has_finalizer = bool(tid & (1<<llgroup.HALFSHIFT))
- has_light_finalizer = bool(tid & (1<<(llgroup.HALFSHIFT + 1)))
check_typeid(type_id)
res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
type_id, size,
- has_finalizer,
- has_light_finalizer,
- False)
+ False, False, False)
# In case the operation above failed, we are returning NULL
# from this function to assembler. There is also an RPython
# exception set, typically MemoryError; but it's easier and
@@ -749,11 +745,8 @@
def init_size_descr(self, S, descr):
type_id = self.layoutbuilder.get_type_id(S)
assert not self.layoutbuilder.is_weakref_type(S)
- has_finalizer = bool(self.layoutbuilder.has_finalizer(S))
- has_light_finalizer = bool(self.layoutbuilder.has_light_finalizer(S))
- flags = (int(has_finalizer) << llgroup.HALFSHIFT |
- int(has_light_finalizer) << (llgroup.HALFSHIFT + 1))
- descr.tid = llop.combine_ushort(lltype.Signed, type_id, flags)
+ assert not self.layoutbuilder.has_finalizer(S)
+ descr.tid = llop.combine_ushort(lltype.Signed, type_id, 0)
def init_array_descr(self, A, descr):
type_id = self.layoutbuilder.get_type_id(A)
diff --git a/pypy/jit/backend/llsupport/test/test_regalloc.py b/pypy/jit/backend/llsupport/test/test_regalloc.py
--- a/pypy/jit/backend/llsupport/test/test_regalloc.py
+++ b/pypy/jit/backend/llsupport/test/test_regalloc.py
@@ -2,6 +2,8 @@
from pypy.jit.metainterp.history import BoxInt, ConstInt, BoxFloat, INT, FLOAT
from pypy.jit.backend.llsupport.regalloc import FrameManager
from pypy.jit.backend.llsupport.regalloc import RegisterManager as BaseRegMan
+from pypy.jit.tool.oparser import parse
+from pypy.jit.backend.detect_cpu import getcpuclass
def newboxes(*values):
return [BoxInt(v) for v in values]
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -168,26 +168,22 @@
operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
allgcrefs)
# compute longevity of variables
- longevity = self._compute_vars_longevity(inputargs, operations)
+ longevity, useful = self._compute_vars_longevity(inputargs, operations)
self.longevity = longevity
self.rm = gpr_reg_mgr_cls(longevity,
frame_manager = self.fm,
assembler = self.assembler)
self.xrm = xmm_reg_mgr_cls(longevity, frame_manager = self.fm,
assembler = self.assembler)
- return operations
+ return operations, useful
def prepare_loop(self, inputargs, operations, looptoken, allgcrefs):
- operations = self._prepare(inputargs, operations, allgcrefs)
- jump = operations[-1]
- loop_consts = self._compute_loop_consts(inputargs, jump, looptoken)
- self.loop_consts = loop_consts
- return self._process_inputargs(inputargs), operations
+ operations, useful = self._prepare(inputargs, operations, allgcrefs)
+ return self._process_inputargs(inputargs, useful), operations
def prepare_bridge(self, prev_depths, inputargs, arglocs, operations,
allgcrefs):
- operations = self._prepare(inputargs, operations, allgcrefs)
- self.loop_consts = {}
+ operations, _ = self._prepare(inputargs, operations, allgcrefs)
self._update_bindings(arglocs, inputargs)
self.fm.frame_depth = prev_depths[0]
self.param_depth = prev_depths[1]
@@ -196,7 +192,7 @@
def reserve_param(self, n):
self.param_depth = max(self.param_depth, n)
- def _process_inputargs(self, inputargs):
+ def _process_inputargs(self, inputargs, useful):
# XXX we can sort out here by longevity if we need something
# more optimal
floatlocs = [None] * len(inputargs)
@@ -212,7 +208,7 @@
arg = inputargs[i]
assert not isinstance(arg, Const)
reg = None
- if arg not in self.loop_consts and self.longevity[arg][1] > -1:
+ if self.longevity[arg][1] > -1 and arg in useful:
if arg.type == FLOAT:
# xxx is it really a good idea? at the first CALL they
# will all be flushed anyway
@@ -288,15 +284,15 @@
else:
return self.xrm.make_sure_var_in_reg(var, forbidden_vars)
- def _compute_loop_consts(self, inputargs, jump, looptoken):
- if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
- loop_consts = {}
- else:
- loop_consts = {}
- for i in range(len(inputargs)):
- if inputargs[i] is jump.getarg(i):
- loop_consts[inputargs[i]] = i
- return loop_consts
+ #def _compute_loop_consts(self, inputargs, jump, looptoken):
+ # if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
+ # loop_consts = {}
+ # else:
+ # loop_consts = {}
+ # for i in range(len(inputargs)):
+ # if inputargs[i] is jump.getarg(i):
+ # loop_consts[inputargs[i]] = i
+ # return loop_consts
def _update_bindings(self, locs, inputargs):
# XXX this should probably go to llsupport/regalloc.py
@@ -451,8 +447,14 @@
def _compute_vars_longevity(self, inputargs, operations):
# compute a dictionary that maps variables to index in
# operations that is a "last-time-seen"
+
+ # returns a pair longevity/useful. Non-useful variables are ones that
+ # never appear in the assembler or it does not matter if they appear on
+ # stack or in registers. Main example is loop arguments that go
+ # only to guard operations or to jump or to finish
produced = {}
last_used = {}
+ useful = {}
for i in range(len(operations)-1, -1, -1):
op = operations[i]
if op.result:
@@ -460,8 +462,11 @@
continue
assert op.result not in produced
produced[op.result] = i
+ opnum = op.getopnum()
for j in range(op.numargs()):
arg = op.getarg(j)
+ if opnum != rop.JUMP and opnum != rop.FINISH:
+ useful[arg] = None
if isinstance(arg, Box) and arg not in last_used:
last_used[arg] = i
if op.is_guard():
@@ -487,7 +492,7 @@
longevity[arg] = (0, last_used[arg])
del last_used[arg]
assert len(last_used) == 0
- return longevity
+ return longevity, useful
def loc(self, v):
if v is None: # xxx kludgy
diff --git a/pypy/jit/backend/x86/test/test_regalloc.py b/pypy/jit/backend/x86/test/test_regalloc.py
--- a/pypy/jit/backend/x86/test/test_regalloc.py
+++ b/pypy/jit/backend/x86/test/test_regalloc.py
@@ -153,6 +153,13 @@
self.cpu.execute_token(looptoken)
return loop
+ def prepare_loop(self, ops):
+ loop = self.parse(ops)
+ regalloc = RegAlloc(self.cpu.assembler, False)
+ regalloc.prepare_loop(loop.inputargs, loop.operations,
+ loop.token, [])
+ return regalloc
+
def getint(self, index):
return self.cpu.get_latest_value_int(index)
@@ -434,6 +441,35 @@
self.run(loop)
assert self.getints(9) == range(9)
+ def test_loopargs(self):
+ ops = """
+ [i0, i1, i2, i3]
+ i4 = int_add(i0, i1)
+ jump(i4, i1, i2, i3)
+ """
+ regalloc = self.prepare_loop(ops)
+ assert len(regalloc.rm.reg_bindings) == 2
+
+ def test_loopargs_2(self):
+ ops = """
+ [i0, i1, i2, i3]
+ i4 = int_add(i0, i1)
+ finish(i4, i1, i2, i3)
+ """
+ regalloc = self.prepare_loop(ops)
+ assert len(regalloc.rm.reg_bindings) == 2
+
+ def test_loopargs_3(self):
+ ops = """
+ [i0, i1, i2, i3]
+ i4 = int_add(i0, i1)
+ guard_true(i4) [i0, i1, i2, i3, i4]
+ jump(i4, i1, i2, i3)
+ """
+ regalloc = self.prepare_loop(ops)
+ assert len(regalloc.rm.reg_bindings) == 2
+
+
class TestRegallocCompOps(BaseTestRegalloc):
def test_cmp_op_0(self):
diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -457,6 +457,46 @@
def test_compile_framework_7(self):
self.run('compile_framework_7')
+ def define_compile_framework_7_interior(cls):
+ # Array of structs containing pointers (test the write barrier
+ # for setinteriorfield_gc)
+ S = lltype.GcStruct('S', ('i', lltype.Signed))
+ A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)),
+ ('y', lltype.Ptr(S)),
+ ('z', lltype.Ptr(S))))
+ class Glob:
+ a = lltype.nullptr(A)
+ glob = Glob()
+ #
+ def make_s(i):
+ s = lltype.malloc(S)
+ s.i = i
+ return s
+ #
+ @unroll_safe
+ def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+ a = glob.a
+ if not a:
+ a = glob.a = lltype.malloc(A, 10)
+ i = 0
+ while i < 10:
+ a[i].x = make_s(n + i * 100 + 1)
+ a[i].y = make_s(n + i * 100 + 2)
+ a[i].z = make_s(n + i * 100 + 3)
+ i += 1
+ i = 0
+ while i < 10:
+ check(a[i].x.i == n + i * 100 + 1)
+ check(a[i].y.i == n + i * 100 + 2)
+ check(a[i].z.i == n + i * 100 + 3)
+ i += 1
+ return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+ f(123, *[None]*11) # check that the check() are ok
+ return None, f, None
+
+ def test_compile_framework_7_interior(self):
+ self.run('compile_framework_7_interior')
+
def define_compile_framework_8(cls):
# Array of pointers, of unknown length (test write_barrier_from_array)
def before(n, x):
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -241,12 +241,15 @@
return op.opname == 'jit_force_quasi_immutable'
class RandomEffectsAnalyzer(BoolGraphAnalyzer):
- def analyze_direct_call(self, graph, seen=None):
- if hasattr(graph, "func") and hasattr(graph.func, "_ptr"):
- if graph.func._ptr._obj.random_effects_on_gcobjs:
+ def analyze_external_call(self, op, seen=None):
+ try:
+ funcobj = op.args[0].value._obj
+ if funcobj.random_effects_on_gcobjs:
return True
- return super(RandomEffectsAnalyzer, self).analyze_direct_call(graph,
- seen)
+ except (AttributeError, lltype.DelayedPointer):
+ return True # better safe than sorry
+ return super(RandomEffectsAnalyzer, self).analyze_external_call(
+ op, seen)
def analyze_simple_operation(self, op, graphinfo):
return False
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -15,6 +15,8 @@
from pypy.translator.simplify import get_funcobj
from pypy.translator.unsimplify import varoftype
+class UnsupportedMallocFlags(Exception):
+ pass
def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None):
"""Transform a control flow graph to make it suitable for
@@ -205,7 +207,24 @@
if op.args[0] in self.vable_array_vars:
self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
- rewrite_op_cast_pointer = rewrite_op_same_as
+ def rewrite_op_cast_pointer(self, op):
+ newop = self.rewrite_op_same_as(op)
+ assert newop is None
+ return
+ # disabled for now
+ if (self._is_rclass_instance(op.args[0]) and
+ self._is_rclass_instance(op.result)):
+ FROM = op.args[0].concretetype.TO
+ TO = op.result.concretetype.TO
+ if lltype._castdepth(TO, FROM) > 0:
+ vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, TO)
+ const_vtable = Constant(vtable, lltype.typeOf(vtable))
+ return [None, # hack, do the right renaming from op.args[0] to op.result
+ SpaceOperation("record_known_class", [op.args[0], const_vtable], None)]
+
+ def rewrite_op_jit_record_known_class(self, op):
+ return SpaceOperation("record_known_class", [op.args[0], op.args[1]], None)
+
def rewrite_op_cast_bool_to_int(self, op): pass
def rewrite_op_cast_bool_to_uint(self, op): pass
def rewrite_op_cast_char_to_int(self, op): pass
@@ -481,8 +500,22 @@
def rewrite_op_malloc_varsize(self, op):
if op.args[1].value['flavor'] == 'raw':
+ d = op.args[1].value.copy()
+ d.pop('flavor')
+ add_memory_pressure = d.pop('add_memory_pressure', False)
+ zero = d.pop('zero', False)
+ track_allocation = d.pop('track_allocation', True)
+ if d:
+ raise UnsupportedMallocFlags(d)
ARRAY = op.args[0].value
- return self._do_builtin_call(op, 'raw_malloc',
+ name = 'raw_malloc'
+ if zero:
+ name += '_zero'
+ if add_memory_pressure:
+ name += '_add_memory_pressure'
+ if not track_allocation:
+ name += '_no_track_allocation'
+ return self._do_builtin_call(op, name,
[op.args[2]],
extra = (ARRAY,),
extrakey = ARRAY)
@@ -1053,35 +1086,20 @@
# jit.codewriter.support.
for _op, _oopspec in [('llong_invert', 'INVERT'),
- ('ullong_invert', 'INVERT'),
('llong_lt', 'LT'),
('llong_le', 'LE'),
('llong_eq', 'EQ'),
('llong_ne', 'NE'),
('llong_gt', 'GT'),
('llong_ge', 'GE'),
- ('ullong_lt', 'ULT'),
- ('ullong_le', 'ULE'),
- ('ullong_eq', 'EQ'),
- ('ullong_ne', 'NE'),
- ('ullong_gt', 'UGT'),
- ('ullong_ge', 'UGE'),
('llong_add', 'ADD'),
('llong_sub', 'SUB'),
('llong_mul', 'MUL'),
('llong_and', 'AND'),
('llong_or', 'OR'),
('llong_xor', 'XOR'),
- ('ullong_add', 'ADD'),
- ('ullong_sub', 'SUB'),
- ('ullong_mul', 'MUL'),
- ('ullong_and', 'AND'),
- ('ullong_or', 'OR'),
- ('ullong_xor', 'XOR'),
('llong_lshift', 'LSHIFT'),
('llong_rshift', 'RSHIFT'),
- ('ullong_lshift', 'LSHIFT'),
- ('ullong_rshift', 'URSHIFT'),
('cast_int_to_longlong', 'FROM_INT'),
('truncate_longlong_to_int', 'TO_INT'),
('cast_float_to_longlong', 'FROM_FLOAT'),
@@ -1104,6 +1122,21 @@
('cast_uint_to_ulonglong', 'FROM_UINT'),
('cast_float_to_ulonglong', 'FROM_FLOAT'),
('cast_ulonglong_to_float', 'U_TO_FLOAT'),
+ ('ullong_invert', 'INVERT'),
+ ('ullong_lt', 'ULT'),
+ ('ullong_le', 'ULE'),
+ ('ullong_eq', 'EQ'),
+ ('ullong_ne', 'NE'),
+ ('ullong_gt', 'UGT'),
+ ('ullong_ge', 'UGE'),
+ ('ullong_add', 'ADD'),
+ ('ullong_sub', 'SUB'),
+ ('ullong_mul', 'MUL'),
+ ('ullong_and', 'AND'),
+ ('ullong_or', 'OR'),
+ ('ullong_xor', 'XOR'),
+ ('ullong_lshift', 'LSHIFT'),
+ ('ullong_rshift', 'URSHIFT'),
]:
exec py.code.Source('''
def rewrite_op_%s(self, op):
@@ -1134,7 +1167,7 @@
def rewrite_op_llong_is_true(self, op):
v = varoftype(op.args[0].concretetype)
- op0 = SpaceOperation('cast_int_to_longlong',
+ op0 = SpaceOperation('cast_primitive',
[Constant(0, lltype.Signed)],
v)
args = [op.args[0], v]
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -258,6 +258,9 @@
y = ~r_ulonglong(xll)
return u_to_longlong(y)
+def _ll_1_ullong_invert(xull):
+ return ~xull
+
def _ll_2_llong_lt(xll, yll):
return xll < yll
@@ -276,16 +279,22 @@
def _ll_2_llong_ge(xll, yll):
return xll >= yll
-def _ll_2_llong_ult(xull, yull):
+def _ll_2_ullong_eq(xull, yull):
+ return xull == yull
+
+def _ll_2_ullong_ne(xull, yull):
+ return xull != yull
+
+def _ll_2_ullong_ult(xull, yull):
return xull < yull
-def _ll_2_llong_ule(xull, yull):
+def _ll_2_ullong_ule(xull, yull):
return xull <= yull
-def _ll_2_llong_ugt(xull, yull):
+def _ll_2_ullong_ugt(xull, yull):
return xull > yull
-def _ll_2_llong_uge(xull, yull):
+def _ll_2_ullong_uge(xull, yull):
return xull >= yull
def _ll_2_llong_add(xll, yll):
@@ -312,14 +321,41 @@
z = r_ulonglong(xll) ^ r_ulonglong(yll)
return u_to_longlong(z)
+def _ll_2_ullong_add(xull, yull):
+ z = (xull) + (yull)
+ return (z)
+
+def _ll_2_ullong_sub(xull, yull):
+ z = (xull) - (yull)
+ return (z)
+
+def _ll_2_ullong_mul(xull, yull):
+ z = (xull) * (yull)
+ return (z)
+
+def _ll_2_ullong_and(xull, yull):
+ z = (xull) & (yull)
+ return (z)
+
+def _ll_2_ullong_or(xull, yull):
+ z = (xull) | (yull)
+ return (z)
+
+def _ll_2_ullong_xor(xull, yull):
+ z = (xull) ^ (yull)
+ return (z)
+
def _ll_2_llong_lshift(xll, y):
z = r_ulonglong(xll) << y
return u_to_longlong(z)
+def _ll_2_ullong_lshift(xull, y):
+ return xull << y
+
def _ll_2_llong_rshift(xll, y):
return xll >> y
-def _ll_2_llong_urshift(xull, y):
+def _ll_2_ullong_urshift(xull, y):
return xull >> y
def _ll_1_llong_from_int(x):
@@ -563,10 +599,21 @@
return p
return _ll_0_alloc_with_del
- def build_ll_1_raw_malloc(ARRAY):
- def _ll_1_raw_malloc(n):
- return lltype.malloc(ARRAY, n, flavor='raw')
- return _ll_1_raw_malloc
+ def build_raw_malloc_builder(zero=False, add_memory_pressure=False, track_allocation=True):
+ def build_ll_1_raw_malloc(ARRAY):
+ def _ll_1_raw_malloc(n):
+ return lltype.malloc(ARRAY, n, flavor='raw', zero=zero, add_memory_pressure=add_memory_pressure)
+ return _ll_1_raw_malloc
+ return build_ll_1_raw_malloc
+
+ build_ll_1_raw_malloc = build_raw_malloc_builder()
+ build_ll_1_raw_malloc_zero = build_raw_malloc_builder(zero=True)
+ build_ll_1_raw_malloc_zero_add_memory_pressure = build_raw_malloc_builder(zero=True, add_memory_pressure=True)
+ build_ll_1_raw_malloc_add_memory_pressure = build_raw_malloc_builder(add_memory_pressure=True)
+ build_ll_1_raw_malloc_no_track_allocation = build_raw_malloc_builder(track_allocation=False)
+ build_ll_1_raw_malloc_zero_no_track_allocation = build_raw_malloc_builder(zero=True, track_allocation=False)
+ build_ll_1_raw_malloc_zero_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(zero=True, add_memory_pressure=True, track_allocation=False)
+ build_ll_1_raw_malloc_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(add_memory_pressure=True, track_allocation=False)
def build_ll_1_raw_free(ARRAY):
def _ll_1_raw_free(p):
diff --git a/pypy/jit/codewriter/test/test_call.py b/pypy/jit/codewriter/test/test_call.py
--- a/pypy/jit/codewriter/test/test_call.py
+++ b/pypy/jit/codewriter/test/test_call.py
@@ -192,3 +192,21 @@
[op] = block.operations
call_descr = cc.getcalldescr(op)
assert call_descr.extrainfo.has_random_effects()
+
+def test_random_effects_on_stacklet_switch():
+ from pypy.jit.backend.llgraph.runner import LLtypeCPU
+ from pypy.rlib._rffi_stacklet import switch, thread_handle, handle
+ @jit.dont_look_inside
+ def f():
+ switch(rffi.cast(thread_handle, 0), rffi.cast(handle, 0))
+
+ rtyper = support.annotate(f, [])
+ jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
+ cc = CallControl(LLtypeCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
+ res = cc.find_all_graphs(FakePolicy())
+
+ [f_graph] = [x for x in res if x.func is f]
+ [block, _] = list(f_graph.iterblocks())
+ op = block.operations[-1]
+ call_descr = cc.getcalldescr(op)
+ assert call_descr.extrainfo.has_random_effects()
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1,3 +1,5 @@
+
+import py
import random
try:
from itertools import product
@@ -15,12 +17,12 @@
from pypy.objspace.flow.model import FunctionGraph, Block, Link
from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
from pypy.rpython.lltypesystem.module import ll_math
from pypy.translator.unsimplify import varoftype
from pypy.jit.codewriter import heaptracker, effectinfo
from pypy.jit.codewriter.flatten import ListOfKind
-from pypy.jit.codewriter.jtransform import Transformer
+from pypy.jit.codewriter.jtransform import Transformer, UnsupportedMallocFlags
from pypy.jit.metainterp.history import getkind
def const(x):
@@ -538,6 +540,44 @@
assert op1.opname == '-live-'
assert op1.args == []
+def test_raw_malloc():
+ S = rffi.CArray(lltype.Signed)
+ v1 = varoftype(lltype.Signed)
+ v = varoftype(lltype.Ptr(S))
+ flags = Constant({'flavor': 'raw'}, lltype.Void)
+ op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+ v1], v)
+ tr = Transformer(FakeCPU(), FakeResidualCallControl())
+ op0, op1 = tr.rewrite_operation(op)
+ assert op0.opname == 'residual_call_ir_i'
+ assert op0.args[0].value == 'raw_malloc' # pseudo-function as a str
+ assert op1.opname == '-live-'
+ assert op1.args == []
+
+def test_raw_malloc_zero():
+ S = rffi.CArray(lltype.Signed)
+ v1 = varoftype(lltype.Signed)
+ v = varoftype(lltype.Ptr(S))
+ flags = Constant({'flavor': 'raw', 'zero': True}, lltype.Void)
+ op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+ v1], v)
+ tr = Transformer(FakeCPU(), FakeResidualCallControl())
+ op0, op1 = tr.rewrite_operation(op)
+ assert op0.opname == 'residual_call_ir_i'
+ assert op0.args[0].value == 'raw_malloc_zero' # pseudo-function as a str
+ assert op1.opname == '-live-'
+ assert op1.args == []
+
+def test_raw_malloc_unsupported_flag():
+ S = rffi.CArray(lltype.Signed)
+ v1 = varoftype(lltype.Signed)
+ v = varoftype(lltype.Ptr(S))
+ flags = Constant({'flavor': 'raw', 'unsupported_flag': True}, lltype.Void)
+ op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+ v1], v)
+ tr = Transformer(FakeCPU(), FakeResidualCallControl())
+ py.test.raises(UnsupportedMallocFlags, tr.rewrite_operation, op)
+
def test_rename_on_links():
v1 = Variable()
v2 = Variable(); v2.concretetype = llmemory.Address
@@ -1140,4 +1180,4 @@
assert op1.opname == 'mark_opaque_ptr'
assert op1.args == [v1]
assert op1.result is None
- assert op2 is None
\ No newline at end of file
+ assert op2 is None
diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py
--- a/pypy/jit/codewriter/test/test_longlong.py
+++ b/pypy/jit/codewriter/test/test_longlong.py
@@ -78,7 +78,7 @@
oplist = tr.rewrite_operation(op)
assert len(oplist) == 2
assert oplist[0].opname == 'residual_call_irf_f'
- assert oplist[0].args[0].value == 'llong_from_int'
+ assert oplist[0].args[0].value == opname.split('_')[0]+'_from_int'
assert oplist[0].args[1] == 'calldescr-84'
assert list(oplist[0].args[2]) == [const(0)]
assert list(oplist[0].args[3]) == []
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -518,6 +518,9 @@
@arguments("r")
def bhimpl_mark_opaque_ptr(a):
pass
+ @arguments("r", "i")
+ def bhimpl_record_known_class(a, b):
+ pass
@arguments("i", returns="i")
def bhimpl_int_copy(a):
diff --git a/pypy/jit/metainterp/gc.py b/pypy/jit/metainterp/gc.py
--- a/pypy/jit/metainterp/gc.py
+++ b/pypy/jit/metainterp/gc.py
@@ -7,6 +7,9 @@
self.config = config
+class GC_none(GcDescription):
+ malloc_zero_filled = True
+
class GC_boehm(GcDescription):
malloc_zero_filled = True
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -1071,6 +1071,25 @@
# a jump back to itself and possibly a few bridges ending with finnish.
# Only the operations within the loop formed by that single jump will
# be counted.
+
+ # XXX hacked version, ignore and remove me when jit-targets is merged.
+ loops = self.get_all_loops()
+ loops = [loop for loop in loops if 'Preamble' not in repr(loop)] #XXX
+ assert len(loops) == 1
+ loop, = loops
+ jumpop = loop.operations[-1]
+ assert jumpop.getopnum() == rop.JUMP
+ insns = {}
+ for op in loop.operations:
+ opname = op.getopname()
+ insns[opname] = insns.get(opname, 0) + 1
+ return self._check_insns(insns, expected, check)
+
+ def check_simple_loop(self, expected=None, **check):
+ # Usefull in the simplest case when we have only one trace ending with
+ # a jump back to itself and possibly a few bridges ending with finnish.
+ # Only the operations within the loop formed by that single jump will
+ # be counted.
loops = self.get_all_loops()
assert len(loops) == 1
loop = loops[0]
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -7,7 +7,7 @@
from pypy.rlib.libffi import Func
from pypy.rlib.objectmodel import we_are_translated
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rpython.lltypesystem import llmemory
+from pypy.rpython.lltypesystem import llmemory, rffi
class FuncInfo(object):
@@ -237,7 +237,7 @@
else:
assert False, "unsupported ffitype or kind"
#
- fieldsize = ffitype.c_size
+ fieldsize = rffi.getintfield(ffitype, 'c_size')
return self.optimizer.cpu.interiorfielddescrof_dynamic(
offset, width, fieldsize, is_pointer, is_float, is_signed
)
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -565,9 +565,12 @@
descr = op.getdescr()
assert isinstance(descr, compile.ResumeGuardDescr)
modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
- newboxes = modifier.finish(self.values, self.pendingfields)
- if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
- compile.giveup()
+ try:
+ newboxes = modifier.finish(self.values, self.pendingfields)
+ if len(newboxes) > self.metainterp_sd.options.failargs_limit:
+ raise resume.TagOverflow
+ except resume.TagOverflow:
+ raise compile.giveup()
descr.store_final_boxes(op, newboxes)
#
if op.getopnum() == rop.GUARD_VALUE:
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -260,6 +260,16 @@
def optimize_GUARD_FALSE(self, op):
self.optimize_guard(op, CONST_0)
+ def optimize_RECORD_KNOWN_CLASS(self, op):
+ value = self.getvalue(op.getarg(0))
+ expectedclassbox = op.getarg(1)
+ assert isinstance(expectedclassbox, Const)
+ realclassbox = value.get_constant_class(self.optimizer.cpu)
+ if realclassbox is not None:
+ assert realclassbox.same_constant(expectedclassbox)
+ return
+ value.make_constant_class(expectedclassbox, None)
+
def optimize_GUARD_CLASS(self, op):
value = self.getvalue(op.getarg(0))
expectedclassbox = op.getarg(1)
@@ -481,6 +491,9 @@
self.pure(rop.CAST_PTR_TO_INT, [op.result], op.getarg(0))
self.emit_operation(op)
+ def optimize_SAME_AS(self, op):
+ self.make_equal_to(op.result, self.getvalue(op.getarg(0)))
+
dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
default=OptRewrite.emit_operation)
optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -31,6 +31,9 @@
def optimize_MARK_OPAQUE_PTR(self, op):
pass
+ def optimize_RECORD_KNOWN_CLASS(self, op):
+ pass
+
def optimize_LABEL(self, op):
self.last_label_descr = op.getdescr()
self.emit_operation(op)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -6508,6 +6508,21 @@
# not obvious, because of the exception UnicodeDecodeError that
# can be raised by ll_str2unicode()
+ def test_record_known_class(self):
+ ops = """
+ [p0]
+ p1 = getfield_gc(p0, descr=nextdescr)
+ record_known_class(p1, ConstClass(node_vtable))
+ guard_class(p1, ConstClass(node_vtable)) []
+ jump(p1)
+ """
+ expected = """
+ [p0]
+ p1 = getfield_gc(p0, descr=nextdescr)
+ jump(p1)
+ """
+ self.optimize_loop(ops, expected)
+
def test_quasi_immut(self):
ops = """
[p0, p1, i0]
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -242,6 +242,18 @@
def opimpl_mark_opaque_ptr(self, box):
return self.execute(rop.MARK_OPAQUE_PTR, box)
+ @arguments("box", "box")
+ def opimpl_record_known_class(self, box, clsbox):
+ from pypy.rpython.lltypesystem import llmemory
+ if self.metainterp.heapcache.is_class_known(box):
+ return
+ adr = clsbox.getaddr()
+ bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE)
+ if bounding_class.subclassrange_max - bounding_class.subclassrange_min == 1:
+ # precise class knowledge, this can be used
+ self.execute(rop.RECORD_KNOWN_CLASS, box, clsbox)
+ self.metainterp.heapcache.class_now_known(box)
+
@arguments("box")
def _opimpl_any_return(self, box):
self.metainterp.finishframe(box)
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -496,6 +496,7 @@
'COPYSTRCONTENT/5', # src, dst, srcstart, dststart, length
'COPYUNICODECONTENT/5',
'QUASIIMMUT_FIELD/1d', # [objptr], descr=SlowMutateDescr
+ 'RECORD_KNOWN_CLASS/2', # [objptr, clsptr]
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
'_CALL_FIRST',
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -93,12 +93,14 @@
TAGMASK = 3
+class TagOverflow(Exception):
+ pass
+
def tag(value, tagbits):
- if tagbits >> 2:
- raise ValueError
+ assert 0 <= tagbits <= 3
sx = value >> 13
if sx != 0 and sx != -1:
- raise ValueError
+ raise TagOverflow
return rffi.r_short(value<<2|tagbits)
def untag(value):
@@ -153,7 +155,7 @@
return self._newconst(const)
try:
return tag(val, TAGINT)
- except ValueError:
+ except TagOverflow:
pass
tagged = self.large_ints.get(val, UNASSIGNED)
if not tagged_eq(tagged, UNASSIGNED):
@@ -429,8 +431,7 @@
fieldnum = self._gettagged(fieldbox)
# the index is limited to 2147483647 (64-bit machines only)
if itemindex > 2147483647:
- from pypy.jit.metainterp import compile
- compile.giveup()
+ raise TagOverflow
itemindex = rffi.cast(rffi.INT, itemindex)
#
rd_pendingfields[i].lldescr = lldescr
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -14,7 +14,7 @@
from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
loop_invariant, elidable, promote, jit_debug, assert_green,
AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
- isconstant, isvirtual, promote_string, set_param)
+ isconstant, isvirtual, promote_string, set_param, record_known_class)
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rpython.ootypesystem import ootype
@@ -3537,6 +3537,132 @@
self.interp_operations(f, [5], translationoptions=translationoptions)
+ def test_annotation_gives_class_knowledge_to_tracer(self):
+ py.test.skip("disabled")
+ class Base(object):
+ pass
+ class A(Base):
+ def f(self):
+ return self.a
+ def g(self):
+ return self.a + 1
+ class B(Base):
+ def f(self):
+ return self.b
+ def g(self):
+ return self.b + 1
+ class C(B):
+ def f(self):
+ self.c += 1
+ return self.c
+ def g(self):
+ return self.c + 1
+ @dont_look_inside
+ def make(x):
+ if x > 0:
+ a = A()
+ a.a = x + 1
+ elif x < 0:
+ a = B()
+ a.b = -x
+ else:
+ a = C()
+ a.c = 10
+ return a
+ def f(x):
+ a = make(x)
+ if x > 0:
+ assert isinstance(a, A)
+ z = a.f()
+ elif x < 0:
+ assert isinstance(a, B)
+ z = a.f()
+ else:
+ assert isinstance(a, C)
+ z = a.f()
+ return z + a.g()
+ res1 = f(6)
+ res2 = self.interp_operations(f, [6])
+ assert res1 == res2
+ self.check_operations_history(guard_class=0, record_known_class=1)
+
+ res1 = f(-6)
+ res2 = self.interp_operations(f, [-6])
+ assert res1 == res2
+ # cannot use record_known_class here, because B has a subclass
+ self.check_operations_history(guard_class=1)
+
+ res1 = f(0)
+ res2 = self.interp_operations(f, [0])
+ assert res1 == res2
+ # here it works again
+ self.check_operations_history(guard_class=0, record_known_class=1)
+
+ def test_give_class_knowledge_to_tracer_explicitly(self):
+ from pypy.rpython.lltypesystem.lloperation import llop
+ class Base(object):
+ def f(self):
+ raise NotImplementedError
+ def g(self):
+ raise NotImplementedError
+ class A(Base):
+ def f(self):
+ return self.a
+ def g(self):
+ return self.a + 1
+ class B(Base):
+ def f(self):
+ return self.b
+ def g(self):
+ return self.b + 1
+ class C(B):
+ def f(self):
+ self.c += 1
+ return self.c
+ def g(self):
+ return self.c + 1
+ @dont_look_inside
+ def make(x):
+ if x > 0:
+ a = A()
+ a.a = x + 1
+ elif x < 0:
+ a = B()
+ a.b = -x
+ else:
+ a = C()
+ a.c = 10
+ return a
+ def f(x):
+ a = make(x)
+ if x > 0:
+ record_known_class(a, A)
+ z = a.f()
+ elif x < 0:
+ record_known_class(a, B)
+ z = a.f()
+ else:
+ record_known_class(a, C)
+ z = a.f()
+ return z + a.g()
+ res1 = f(6)
+ res2 = self.interp_operations(f, [6])
+ assert res1 == res2
+ self.check_operations_history(guard_class=0, record_known_class=1)
+
+ res1 = f(-6)
+ res2 = self.interp_operations(f, [-6])
+ assert res1 == res2
+ # cannot use record_known_class here, because B has a subclass
+ self.check_operations_history(guard_class=1)
+
+ res1 = f(0)
+ res2 = self.interp_operations(f, [0])
+ assert res1 == res2
+ # here it works again
+ self.check_operations_history(guard_class=0, record_known_class=1)
+
+
class TestLLtype(BaseLLtypeTests, LLJitMixin):
def test_tagged(self):
from pypy.rlib.objectmodel import UnboxedValue
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -23,11 +23,11 @@
assert tag(-3, 2) == rffi.r_short(-3<<2|2)
assert tag((1<<13)-1, 3) == rffi.r_short(((1<<15)-1)|3)
assert tag(-1<<13, 3) == rffi.r_short((-1<<15)|3)
- py.test.raises(ValueError, tag, 3, 5)
- py.test.raises(ValueError, tag, 1<<13, 0)
- py.test.raises(ValueError, tag, (1<<13)+1, 0)
- py.test.raises(ValueError, tag, (-1<<13)-1, 0)
- py.test.raises(ValueError, tag, (-1<<13)-5, 0)
+ py.test.raises(AssertionError, tag, 3, 5)
+ py.test.raises(TagOverflow, tag, 1<<13, 0)
+ py.test.raises(TagOverflow, tag, (1<<13)+1, 0)
+ py.test.raises(TagOverflow, tag, (-1<<13)-1, 0)
+ py.test.raises(TagOverflow, tag, (-1<<13)-5, 0)
def test_untag():
assert untag(tag(3, 1)) == (3, 1)
@@ -1318,8 +1318,7 @@
assert rffi.cast(lltype.Signed, pf[1].fieldnum) == 1062
assert rffi.cast(lltype.Signed, pf[1].itemindex) == 2147483647
#
- from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole
- py.test.raises(SwitchToBlackhole, modifier._add_pending_fields,
+ py.test.raises(TagOverflow, modifier._add_pending_fields,
[(array_a, 42, 63, 2147483648)])
def test_resume_reader_fields_and_arrayitems():
diff --git a/pypy/jit/metainterp/test/test_virtual.py b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -615,7 +615,7 @@
return node.value
res = self.meta_interp(f, [48, 3], policy=StopAtXPolicy(externfn))
assert res == f(48, 3)
- self.check_trace_count(3)
+ self.check_trace_count(4)
res = self.meta_interp(f, [40, 3], policy=StopAtXPolicy(externfn))
assert res == f(40, 3)
self.check_trace_count(3)
@@ -764,6 +764,27 @@
res = self.meta_interp(f, [0x1F, 0x11])
assert res == f(0x1F, 0x11)
+ def test_duplicated_virtual(self):
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'node1', 'node2'])
+ def f(n):
+ node1 = self._new()
+ node1.value = 0
+ node2 = self._new()
+ node2.value = 1
+ while n > 0:
+ myjitdriver.jit_merge_point(n=n, node1=node1, node2=node2)
+ next = self._new()
+ next.value = node1.value + node2.value + n
+ node1 = next
+ node2 = next
+ n -= 1
+ return node1.value
+ res = self.meta_interp(f, [10])
+ assert res == f(10)
+ self.check_resops(new_with_vtable=0, new=0)
+
+
+
def test_retrace_not_matching_bridge(self):
@dont_look_inside
def external(node):
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -255,10 +255,8 @@
s_binding = self.translator.annotator.binding
jd._portal_args_s = [s_binding(v) for v in args]
graph = copygraph(graph)
- graph.startblock.isstartblock = False
[jmpp] = find_jit_merge_points([graph])
graph.startblock = support.split_before_jit_merge_point(*jmpp)
- graph.startblock.isstartblock = True
# a crash in the following checkgraph() means that you forgot
# to list some variable in greens=[] or reds=[] in JitDriver,
# or that a jit_merge_point() takes a constant as an argument.
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -27,6 +27,7 @@
'builtinify' : 'interp_magic.builtinify',
'lookup_special' : 'interp_magic.lookup_special',
'do_what_I_mean' : 'interp_magic.do_what_I_mean',
+ 'list_strategy' : 'interp_magic.list_strategy',
}
submodules = {
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -5,7 +5,6 @@
from pypy.objspace.std.typeobject import MethodCache
from pypy.objspace.std.mapdict import IndexCache
-
def internal_repr(space, w_object):
return space.wrap('%r' % (w_object,))
@@ -73,3 +72,11 @@
def do_what_I_mean(space):
return space.wrap(42)
+
+def list_strategy(space, w_list):
+ from pypy.objspace.std.listobject import W_ListObject
+ if isinstance(w_list, W_ListObject):
+ return space.wrap(w_list.strategy._applevel_repr)
+ else:
+ w_msg = space.wrap("Can only get the list strategy of a list")
+ raise OperationError(space.w_TypeError, w_msg)
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -5,7 +5,7 @@
def setup_class(cls):
if option.runappdirect:
py.test.skip("does not make sense on pypy-c")
- cls.space = gettestobjspace(**{"objspace.usemodules.select": False})
+ cls.space = gettestobjspace(**{"objspace.usemodules.select": False, "objspace.std.withrangelist": True})
def test__isfake(self):
from __pypy__ import isfake
@@ -54,3 +54,21 @@
from __pypy__ import do_what_I_mean
x = do_what_I_mean()
assert x == 42
+
+ def test_list_strategy(self):
+ from __pypy__ import list_strategy
+
+ l = [1, 2, 3]
+ assert list_strategy(l) == "int"
+ l = ["a", "b", "c"]
+ assert list_strategy(l) == "str"
+ l = [1.1, 2.2, 3.3]
+ assert list_strategy(l) == "float"
+ l = range(3)
+ assert list_strategy(l) == "range"
+ l = [1, "b", 3]
+ assert list_strategy(l) == "object"
+ l = []
+ assert list_strategy(l) == "empty"
+ o = 5
+ raises(TypeError, list_strategy, 5)
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -67,10 +67,7 @@
if self.unicodedata_handler:
return self.unicodedata_handler
try:
- w_builtin = space.getbuiltinmodule('__builtin__')
- w_import = space.getattr(w_builtin, space.wrap("__import__"))
- w_unicodedata = space.call_function(w_import,
- space.wrap("unicodedata"))
+ w_unicodedata = space.getbuiltinmodule("unicodedata")
w_getcode = space.getattr(w_unicodedata, space.wrap("_get_code"))
except OperationError:
return None
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -100,7 +100,6 @@
res, newbuf = self.do_recv_string(
space, self.BUFFER_SIZE, maxlength)
- res = intmask(res) # XXX why?
try:
if newbuf:
return space.wrap(rffi.charpsize2str(newbuf, res))
@@ -117,7 +116,6 @@
res, newbuf = self.do_recv_string(
space, length - offset, PY_SSIZE_T_MAX)
- res = intmask(res) # XXX why?
try:
if newbuf:
raise BufferTooShort(space, space.wrap(
@@ -148,7 +146,6 @@
res, newbuf = self.do_recv_string(
space, self.BUFFER_SIZE, PY_SSIZE_T_MAX)
- res = intmask(res) # XXX why?
try:
if newbuf:
w_received = space.wrap(rffi.charpsize2str(newbuf, res))
@@ -413,7 +410,7 @@
self.buffer, min(self.BUFFER_SIZE, buflength),
read_ptr, rffi.NULL)
if result:
- return read_ptr[0], lltype.nullptr(rffi.CCHARP.TO)
+ return intmask(read_ptr[0]), lltype.nullptr(rffi.CCHARP.TO)
err = rwin32.GetLastError()
if err == ERROR_BROKEN_PIPE:
@@ -476,7 +473,7 @@
block = timeout < 0
if not block:
# XXX does not check for overflow
- deadline = _GetTickCount() + int(1000 * timeout + 0.5)
+ deadline = intmask(_GetTickCount()) + int(1000 * timeout + 0.5)
else:
deadline = 0
@@ -500,7 +497,7 @@
return True
if not block:
- now = _GetTickCount()
+ now = intmask(_GetTickCount())
if now > deadline:
return False
diff = deadline - now
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -235,7 +235,7 @@
elif timeout >= 0.5 * rwin32.INFINITE: # 25 days
raise OperationError(space.w_OverflowError,
space.wrap("timeout is too large"))
- full_msecs = int(timeout + 0.5)
+ full_msecs = r_uint(int(timeout + 0.5))
# check whether we can acquire without blocking
res = rwin32.WaitForSingleObject(self.handle, 0)
@@ -243,7 +243,7 @@
if res != rwin32.WAIT_TIMEOUT:
return True
- msecs = r_uint(full_msecs)
+ msecs = full_msecs
start = _GetTickCount()
while True:
@@ -269,7 +269,7 @@
ticks = _GetTickCount()
if r_uint(ticks - start) >= full_msecs:
return False
- msecs = r_uint(full_msecs - (ticks - start))
+ msecs = full_msecs - r_uint(ticks - start)
# handle result
if res != rwin32.WAIT_TIMEOUT:
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -543,6 +543,7 @@
from pypy.rlib.rwin32 import GetLastError
return space.wrap(GetLastError())
-def set_last_error(space, w_error):
+ at unwrap_spec(error=int)
+def set_last_error(space, error):
from pypy.rlib.rwin32 import SetLastError
- SetLastError(space.uint_w(w_error))
+ SetLastError(error)
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -5,17 +5,34 @@
applevel_name = 'numpypy'
interpleveldefs = {
- 'array': 'interp_numarray.NDimArray',
+ 'ndarray': 'interp_numarray.W_NDimArray',
'dtype': 'interp_dtype.W_Dtype',
'ufunc': 'interp_ufuncs.W_Ufunc',
+ 'array': 'interp_numarray.array',
'zeros': 'interp_numarray.zeros',
'empty': 'interp_numarray.zeros',
'ones': 'interp_numarray.ones',
+ 'dot': 'interp_numarray.dot',
'fromstring': 'interp_support.fromstring',
+ 'flatiter': 'interp_numarray.W_FlatIterator',
- 'True_': 'space.w_True',
- 'False_': 'space.w_False',
+ 'True_': 'types.Bool.True',
+ 'False_': 'types.Bool.False',
+
+ 'generic': 'interp_boxes.W_GenericBox',
+ 'number': 'interp_boxes.W_NumberBox',
+ 'integer': 'interp_boxes.W_IntegerBox',
+ 'signedinteger': 'interp_boxes.W_SignedIntegerBox',
+ 'bool_': 'interp_boxes.W_BoolBox',
+ 'int8': 'interp_boxes.W_Int8Box',
+ 'int16': 'interp_boxes.W_Int16Box',
+ 'int32': 'interp_boxes.W_Int32Box',
+ 'int64': 'interp_boxes.W_Int64Box',
+ 'int_': 'interp_boxes.W_LongBox',
+ 'inexact': 'interp_boxes.W_InexactBox',
+ 'floating': 'interp_boxes.W_FloatingBox',
+ 'float64': 'interp_boxes.W_Float64Box',
}
# ufuncs
@@ -48,6 +65,7 @@
("sign", "sign"),
("sin", "sin"),
("subtract", "subtract"),
+ ('sqrt', 'sqrt'),
("tan", "tan"),
]:
interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
@@ -57,4 +75,5 @@
'mean': 'app_numpy.mean',
'inf': 'app_numpy.inf',
'e': 'app_numpy.e',
+ 'arange': 'app_numpy.arange',
}
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -6,12 +6,33 @@
inf = float("inf")
e = math.e
+
def average(a):
# This implements a weighted average, for now we don't implement the
# weighting, just the average part!
return mean(a)
+
def mean(a):
if not hasattr(a, "mean"):
a = numpypy.array(a)
return a.mean()
+
+
+def arange(start, stop=None, step=1, dtype=None):
+ '''arange([start], stop[, step], dtype=None)
+ Generate values in the half-interval [start, stop).
+ '''
+ if stop is None:
+ stop = start
+ start = 0
+ if dtype is None:
+ test = numpypy.array([start, stop, step, 0])
+ dtype = test.dtype
+ arr = numpypy.zeros(int(math.ceil((stop - start) / step)), dtype=dtype)
+ i = start
+ for j in range(arr.size):
+ arr[j] = i
+ j += 1
+ i += step
+ return arr
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,13 +3,16 @@
It should not be imported by the module itself
"""
+import re
+
from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype, W_BoolDtype
+from pypy.module.micronumpy import interp_boxes
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
- descr_new_array, scalar_w, NDimArray)
+ scalar_w, W_NDimArray, array)
from pypy.module.micronumpy import interp_ufuncs
-from pypy.rlib.objectmodel import specialize
-import re
+from pypy.rlib.objectmodel import specialize, instantiate
+
class BogusBytecode(Exception):
pass
@@ -48,15 +51,12 @@
def __init__(self):
"""NOT_RPYTHON"""
self.fromcache = InternalSpaceCache(self).getorbuild
- self.w_float64dtype = W_Float64Dtype(self)
def issequence_w(self, w_obj):
- return isinstance(w_obj, ListObject) or isinstance(w_obj, NDimArray)
+ return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
def isinstance_w(self, w_obj, w_tp):
- if w_obj.tp == w_tp:
- return True
- return False
+ return w_obj.tp == w_tp
def decode_index4(self, w_idx, size):
if isinstance(w_idx, IntObject):
@@ -69,8 +69,12 @@
if start < 0:
start += size
if stop < 0:
- stop += size
- return (start, stop, step, size//step)
+ stop += size + 1
+ if step < 0:
+ lgt = (stop - start + 1) / step + 1
+ else:
+ lgt = (stop - start - 1) / step + 1
+ return (start, stop, step, lgt)
@specialize.argtype(1)
def wrap(self, obj):
@@ -93,11 +97,13 @@
fixedview = listview
def float(self, w_obj):
- assert isinstance(w_obj, FloatObject)
- return w_obj
+ if isinstance(w_obj, FloatObject):
+ return w_obj
+ assert isinstance(w_obj, interp_boxes.W_GenericBox)
+ return self.float(w_obj.descr_float(self))
def float_w(self, w_obj):
- assert isinstance(w_obj, FloatObject)
+ assert isinstance(w_obj, FloatObject)
return w_obj.floatval
def int_w(self, w_obj):
@@ -108,7 +114,10 @@
raise NotImplementedError
def int(self, w_obj):
- return w_obj
+ if isinstance(w_obj, IntObject):
+ return w_obj
+ assert isinstance(w_obj, interp_boxes.W_GenericBox)
+ return self.int(w_obj.descr_int(self))
def is_true(self, w_obj):
assert isinstance(w_obj, BoolObject)
@@ -131,6 +140,9 @@
assert isinstance(what, tp)
return what
+ def allocate_instance(self, klass, w_subtype):
+ return instantiate(klass)
+
def len_w(self, w_obj):
if isinstance(w_obj, ListObject):
return len(w_obj.items)
@@ -208,11 +220,12 @@
def execute(self, interp):
arr = interp.variables[self.name]
- w_index = self.index.execute(interp).eval(arr.start_iter()).wrap(interp.space)
+ w_index = self.index.execute(interp)
# cast to int
if isinstance(w_index, FloatObject):
w_index = IntObject(int(w_index.floatval))
- w_val = self.expr.execute(interp).eval(arr.start_iter()).wrap(interp.space)
+ w_val = self.expr.execute(interp)
+ assert isinstance(arr, BaseArray)
arr.descr_setitem(interp.space, w_index, w_val)
def __repr__(self):
@@ -240,23 +253,28 @@
w_rhs = self.rhs.wrap(interp.space)
else:
w_rhs = self.rhs.execute(interp)
+ if not isinstance(w_lhs, BaseArray):
+ # scalar
+ dtype = get_dtype_cache(interp.space).w_float64dtype
+ w_lhs = scalar_w(interp.space, dtype, w_lhs)
assert isinstance(w_lhs, BaseArray)
if self.name == '+':
w_res = w_lhs.descr_add(interp.space, w_rhs)
elif self.name == '*':
w_res = w_lhs.descr_mul(interp.space, w_rhs)
elif self.name == '-':
- w_res = w_lhs.descr_sub(interp.space, w_rhs)
+ w_res = w_lhs.descr_sub(interp.space, w_rhs)
elif self.name == '->':
- if isinstance(w_rhs, Scalar):
- w_rhs = w_rhs.eval(w_rhs.start_iter()).wrap(interp.space)
- assert isinstance(w_rhs, FloatObject)
+ assert not isinstance(w_rhs, Scalar)
+ if isinstance(w_rhs, FloatObject):
w_rhs = IntObject(int(w_rhs.floatval))
+ assert isinstance(w_lhs, BaseArray)
w_res = w_lhs.descr_getitem(interp.space, w_rhs)
else:
raise NotImplementedError
- if not isinstance(w_res, BaseArray):
- dtype = interp.space.fromcache(W_Float64Dtype)
+ if (not isinstance(w_res, BaseArray) and
+ not isinstance(w_res, interp_boxes.W_GenericBox)):
+ dtype = get_dtype_cache(interp.space).w_float64dtype
w_res = scalar_w(interp.space, dtype, w_res)
return w_res
@@ -274,9 +292,7 @@
return space.wrap(self.v)
def execute(self, interp):
- dtype = interp.space.fromcache(W_Float64Dtype)
- assert isinstance(dtype, W_Float64Dtype)
- return Scalar(dtype, dtype.box(self.v))
+ return interp.space.wrap(self.v)
class RangeConstant(Node):
def __init__(self, v):
@@ -284,10 +300,10 @@
def execute(self, interp):
w_list = interp.space.newlist(
- [interp.space.wrap(float(i)) for i in range(self.v)])
- dtype = interp.space.fromcache(W_Float64Dtype)
- return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
- w_order=None)
+ [interp.space.wrap(float(i)) for i in range(self.v)]
+ )
+ dtype = get_dtype_cache(interp.space).w_float64dtype
+ return array(interp.space, w_list, w_dtype=dtype, w_order=None)
def __repr__(self):
return 'Range(%s)' % self.v
@@ -308,9 +324,8 @@
def execute(self, interp):
w_list = self.wrap(interp.space)
- dtype = interp.space.fromcache(W_Float64Dtype)
- return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
- w_order=None)
+ dtype = get_dtype_cache(interp.space).w_float64dtype
+ return array(interp.space, w_list, w_dtype=dtype, w_order=None)
def __repr__(self):
return "[" + ", ".join([repr(item) for item in self.items]) + "]"
@@ -325,6 +340,9 @@
def wrap(self, space):
return SliceObject(self.start, self.stop, self.step)
+ def execute(self, interp):
+ return SliceObject(self.start, self.stop, self.step)
+
def __repr__(self):
return 'slice(%s,%s,%s)' % (self.start, self.stop, self.step)
@@ -374,9 +392,11 @@
if isinstance(w_res, BaseArray):
return w_res
if isinstance(w_res, FloatObject):
- dtype = interp.space.fromcache(W_Float64Dtype)
+ dtype = get_dtype_cache(interp.space).w_float64dtype
elif isinstance(w_res, BoolObject):
- dtype = interp.space.fromcache(W_BoolDtype)
+ dtype = get_dtype_cache(interp.space).w_booldtype
+ elif isinstance(w_res, interp_boxes.W_GenericBox):
+ dtype = w_res.get_dtype(interp.space)
else:
dtype = None
return scalar_w(interp.space, dtype, w_res)
@@ -477,8 +497,8 @@
else:
step = 1
return SliceConstant(start, stop, step)
-
-
+
+
def parse_expression(self, tokens):
stack = []
while tokens.remaining():
@@ -532,7 +552,7 @@
if token.name == 'array_right':
return elems
assert token.name == 'coma'
-
+
def parse_statement(self, tokens):
if (tokens.get(0).name == 'identifier' and
tokens.get(1).name == 'assign'):
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -0,0 +1,267 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.objspace.std.floattype import float_typedef
+from pypy.objspace.std.inttype import int_typedef
+from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.rlib.rarithmetic import LONG_BIT
+from pypy.tool.sourcetools import func_with_new_name
+
+
+MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
+
+def new_dtype_getter(name):
+ def get_dtype(space):
+ from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+ return getattr(get_dtype_cache(space), "w_%sdtype" % name)
+ def new(space, w_subtype, w_value):
+ dtype = get_dtype(space)
+ return dtype.itemtype.coerce_subtype(space, w_subtype, w_value)
+ return func_with_new_name(new, name + "_box_new"), staticmethod(get_dtype)
+
+class PrimitiveBox(object):
+ _mixin_ = True
+
+ def __init__(self, value):
+ self.value = value
+
+ def convert_to(self, dtype):
+ return dtype.box(self.value)
+
+class W_GenericBox(Wrappable):
+ _attrs_ = ()
+
+ def descr__new__(space, w_subtype, __args__):
+ assert isinstance(w_subtype, W_TypeObject)
+ raise operationerrfmt(space.w_TypeError, "cannot create '%s' instances",
+ w_subtype.get_module_type_name()
+ )
+
+ def descr_str(self, space):
+ return self.descr_repr(space)
+
+ def descr_repr(self, space):
+ return space.wrap(self.get_dtype(space).itemtype.str_format(self))
+
+ def descr_int(self, space):
+ box = self.convert_to(W_LongBox.get_dtype(space))
+ assert isinstance(box, W_LongBox)
+ return space.wrap(box.value)
+
+ def descr_float(self, space):
+ box = self.convert_to(W_Float64Box.get_dtype(space))
+ assert isinstance(box, W_Float64Box)
+ return space.wrap(box.value)
+
+ def descr_nonzero(self, space):
+ dtype = self.get_dtype(space)
+ return space.wrap(dtype.itemtype.bool(self))
+
+ def _binop_impl(ufunc_name):
+ def impl(self, space, w_other):
+ from pypy.module.micronumpy import interp_ufuncs
+ return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+ return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
+
+ def _binop_right_impl(ufunc_name):
+ def impl(self, space, w_other):
+ from pypy.module.micronumpy import interp_ufuncs
+ return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+ return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
+
+ def _unaryop_impl(ufunc_name):
+ def impl(self, space):
+ from pypy.module.micronumpy import interp_ufuncs
+ return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+ return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
+
+ descr_add = _binop_impl("add")
+ descr_sub = _binop_impl("subtract")
+ descr_mul = _binop_impl("multiply")
+ descr_div = _binop_impl("divide")
+ descr_eq = _binop_impl("equal")
+ descr_ne = _binop_impl("not_equal")
+ descr_lt = _binop_impl("less")
+ descr_le = _binop_impl("less_equal")
+ descr_gt = _binop_impl("greater")
+ descr_ge = _binop_impl("greater_equal")
+
+ descr_radd = _binop_right_impl("add")
+ descr_rmul = _binop_right_impl("multiply")
+
+ descr_neg = _unaryop_impl("negative")
+ descr_abs = _unaryop_impl("absolute")
+
+
+class W_BoolBox(W_GenericBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("bool")
+
+class W_NumberBox(W_GenericBox):
+ _attrs_ = ()
+
+class W_IntegerBox(W_NumberBox):
+ pass
+
+class W_SignedIntegerBox(W_IntegerBox):
+ pass
+
+class W_UnsignedIntgerBox(W_IntegerBox):
+ pass
+
+class W_Int8Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int8")
+
+class W_UInt8Box(W_UnsignedIntgerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("uint8")
+
+class W_Int16Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int16")
+
+class W_UInt16Box(W_UnsignedIntgerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("uint16")
+
+class W_Int32Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int32")
+
+class W_UInt32Box(W_UnsignedIntgerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("uint32")
+
+class W_LongBox(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("long")
+
+class W_ULongBox(W_UnsignedIntgerBox, PrimitiveBox):
+ pass
+
+class W_Int64Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int64")
+
+class W_UInt64Box(W_UnsignedIntgerBox, PrimitiveBox):
+ pass
+
+class W_InexactBox(W_NumberBox):
+ _attrs_ = ()
+
+class W_FloatingBox(W_InexactBox):
+ _attrs_ = ()
+
+class W_Float32Box(W_FloatingBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("float32")
+
+class W_Float64Box(W_FloatingBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("float64")
+
+
+
+W_GenericBox.typedef = TypeDef("generic",
+ __module__ = "numpypy",
+
+ __new__ = interp2app(W_GenericBox.descr__new__.im_func),
+
+ __str__ = interp2app(W_GenericBox.descr_str),
+ __repr__ = interp2app(W_GenericBox.descr_repr),
+ __int__ = interp2app(W_GenericBox.descr_int),
+ __float__ = interp2app(W_GenericBox.descr_float),
+ __nonzero__ = interp2app(W_GenericBox.descr_nonzero),
+
+ __add__ = interp2app(W_GenericBox.descr_add),
+ __sub__ = interp2app(W_GenericBox.descr_sub),
+ __mul__ = interp2app(W_GenericBox.descr_mul),
+ __div__ = interp2app(W_GenericBox.descr_div),
+
+ __radd__ = interp2app(W_GenericBox.descr_add),
+ __rmul__ = interp2app(W_GenericBox.descr_rmul),
+
+ __eq__ = interp2app(W_GenericBox.descr_eq),
+ __ne__ = interp2app(W_GenericBox.descr_ne),
+ __lt__ = interp2app(W_GenericBox.descr_lt),
+ __le__ = interp2app(W_GenericBox.descr_le),
+ __gt__ = interp2app(W_GenericBox.descr_gt),
+ __ge__ = interp2app(W_GenericBox.descr_ge),
+
+ __neg__ = interp2app(W_GenericBox.descr_neg),
+ __abs__ = interp2app(W_GenericBox.descr_abs),
+)
+
+W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_BoolBox.descr__new__.im_func),
+)
+
+W_NumberBox.typedef = TypeDef("number", W_GenericBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_IntegerBox.typedef = TypeDef("integer", W_NumberBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_SignedIntegerBox.typedef = TypeDef("signedinteger", W_IntegerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int8Box.typedef = TypeDef("int8", W_SignedIntegerBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int8Box.descr__new__.im_func),
+)
+
+W_UInt8Box.typedef = TypeDef("uint8", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int16Box.typedef = TypeDef("int16", W_SignedIntegerBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int16Box.descr__new__.im_func),
+)
+
+W_UInt16Box.typedef = TypeDef("uint16", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int32Box.typedef = TypeDef("int32", W_SignedIntegerBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int32Box.descr__new__.im_func),
+)
+
+W_UInt32Box.typedef = TypeDef("uint32", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+if LONG_BIT == 32:
+ long_name = "int32"
+elif LONG_BIT == 64:
+ long_name = "int64"
+W_LongBox.typedef = TypeDef(long_name, (W_SignedIntegerBox.typedef, int_typedef,),
+ __module__ = "numpypy",
+)
+
+W_ULongBox.typedef = TypeDef("u" + long_name, W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int64Box.descr__new__.im_func),
+)
+
+W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_InexactBox.typedef = TypeDef("inexact", W_NumberBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_FloatingBox.typedef = TypeDef("floating", W_InexactBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Float32Box.typedef = TypeDef("float32", W_FloatingBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Float64Box.typedef = TypeDef("float64", (W_FloatingBox.typedef, float_typedef),
+ __module__ = "numpypy",
+
+ __new__ = interp2app(W_Float64Box.descr__new__.im_func),
+)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -1,16 +1,11 @@
-import functools
-import math
-
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty
-from pypy.module.micronumpy import signature
-from pypy.objspace.std.floatobject import float2string
-from pypy.rlib import rarithmetic, rfloat
-from pypy.rlib.rarithmetic import LONG_BIT, widen
-from pypy.rlib.objectmodel import specialize, enforceargs
-from pypy.rlib.unroll import unrolling_iterable
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
+ interp_attrproperty, interp_attrproperty_w)
+from pypy.module.micronumpy import types, signature, interp_boxes
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT
from pypy.rpython.lltypesystem import lltype, rffi
@@ -19,501 +14,218 @@
BOOLLTR = "b"
FLOATINGLTR = "f"
+
+VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True})
+
class W_Dtype(Wrappable):
- def __init__(self, space):
- pass
+ _immuable_fields_ = ["itemtype", "num", "kind"]
+
+ def __init__(self, itemtype, num, kind, name, char, w_box_type, alternate_constructors=[]):
+ self.signature = signature.BaseSignature()
+ self.itemtype = itemtype
+ self.num = num
+ self.kind = kind
+ self.name = name
+ self.char = char
+ self.w_box_type = w_box_type
+ self.alternate_constructors = alternate_constructors
+
+ def malloc(self, length):
+ # XXX find out why test_zjit explodes with tracking of allocations
+ return lltype.malloc(VOID_STORAGE, self.itemtype.get_element_size() * length,
+ zero=True, flavor="raw",
+ track_allocation=False, add_memory_pressure=True
+ )
+
+ @specialize.argtype(1)
+ def box(self, value):
+ return self.itemtype.box(value)
+
+ def coerce(self, space, w_item):
+ return self.itemtype.coerce(space, w_item)
+
+ def getitem(self, storage, i):
+ return self.itemtype.read(storage, self.itemtype.get_element_size(), i, 0)
+
+ def setitem(self, storage, i, box):
+ self.itemtype.store(storage, self.itemtype.get_element_size(), i, 0, box)
+
+ def fill(self, storage, box, start, stop):
+ self.itemtype.fill(storage, self.itemtype.get_element_size(), box, start, stop, 0)
def descr__new__(space, w_subtype, w_dtype):
+ cache = get_dtype_cache(space)
+
if space.is_w(w_dtype, space.w_None):
- return space.fromcache(W_Float64Dtype)
+ return cache.w_float64dtype
+ elif space.isinstance_w(w_dtype, w_subtype):
+ return w_dtype
elif space.isinstance_w(w_dtype, space.w_str):
- dtype = space.str_w(w_dtype)
- for alias, dtype_class in dtypes_by_alias:
- if alias == dtype:
- return space.fromcache(dtype_class)
- elif isinstance(space.interpclass_w(w_dtype), W_Dtype):
- return w_dtype
- elif space.isinstance_w(w_dtype, space.w_type):
- for typename, dtype_class in dtypes_by_apptype:
- if space.is_w(getattr(space, "w_%s" % typename), w_dtype):
- return space.fromcache(dtype_class)
+ name = space.str_w(w_dtype)
+ for dtype in cache.builtin_dtypes:
+ if dtype.name == name or dtype.char == name:
+ return dtype
+ else:
+ for dtype in cache.builtin_dtypes:
+ if w_dtype in dtype.alternate_constructors:
+ return dtype
+ if w_dtype is dtype.w_box_type:
+ return dtype
raise OperationError(space.w_TypeError, space.wrap("data type not understood"))
+ def descr_str(self, space):
+ return space.wrap(self.name)
+
def descr_repr(self, space):
return space.wrap("dtype('%s')" % self.name)
- def descr_str(self, space):
- return space.wrap(self.name)
+ def descr_get_itemsize(self, space):
+ return space.wrap(self.itemtype.get_element_size())
def descr_get_shape(self, space):
return space.newtuple([])
-
-class BaseBox(object):
- pass
-
-VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True, "uncast_on_llgraph": True}))
-
-def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype,
- expected_size=None):
-
- class Box(BaseBox):
- def __init__(self, val):
- self.val = val
-
- def wrap(self, space):
- val = self.val
- if valtype is rarithmetic.r_singlefloat:
- val = float(val)
- return space.wrap(val)
-
- def convert_to(self, dtype):
- return dtype.adapt_val(self.val)
- Box.__name__ = "%sBox" % T._name
-
- TP = lltype.Ptr(lltype.Array(T, hints={'nolength': True}))
- class W_LowLevelDtype(W_Dtype):
- signature = signature.BaseSignature()
-
- def erase(self, storage):
- return rffi.cast(VOID_TP, storage)
-
- def unerase(self, storage):
- return rffi.cast(TP, storage)
-
- @enforceargs(None, valtype)
- def box(self, value):
- return Box(value)
-
- def unbox(self, box):
- assert isinstance(box, Box)
- return box.val
-
- def unwrap(self, space, w_item):
- raise NotImplementedError
-
- def malloc(self, size):
- # XXX find out why test_zjit explodes with tracking of allocations
- return self.erase(lltype.malloc(TP.TO, size,
- zero=True, flavor="raw",
- track_allocation=False, add_memory_pressure=True
- ))
-
- def getitem(self, storage, i):
- return Box(self.unerase(storage)[i])
-
- def setitem(self, storage, i, item):
- self.unerase(storage)[i] = self.unbox(item)
-
- def setitem_w(self, space, storage, i, w_item):
- self.setitem(storage, i, self.unwrap(space, w_item))
-
- def fill(self, storage, item, start, stop):
- storage = self.unerase(storage)
- item = self.unbox(item)
- for i in xrange(start, stop):
- storage[i] = item
-
- @specialize.argtype(1)
- def adapt_val(self, val):
- return self.box(rffi.cast(TP.TO.OF, val))
-
- W_LowLevelDtype.__name__ = "W_%sDtype" % name.capitalize()
- W_LowLevelDtype.num = num
- W_LowLevelDtype.kind = kind
- W_LowLevelDtype.name = name
- W_LowLevelDtype.aliases = aliases
- W_LowLevelDtype.applevel_types = applevel_types
- W_LowLevelDtype.num_bytes = rffi.sizeof(T)
- if expected_size is not None:
- assert W_LowLevelDtype.num_bytes == expected_size
- return W_LowLevelDtype
-
-
-def binop(func):
- @functools.wraps(func)
- def impl(self, v1, v2):
- return self.adapt_val(func(self,
- self.for_computation(self.unbox(v1)),
- self.for_computation(self.unbox(v2)),
- ))
- return impl
-
-def raw_binop(func):
- # Returns the result unwrapped.
- @functools.wraps(func)
- def impl(self, v1, v2):
- return func(self,
- self.for_computation(self.unbox(v1)),
- self.for_computation(self.unbox(v2))
- )
- return impl
-
-def unaryop(func):
- @functools.wraps(func)
- def impl(self, v):
- return self.adapt_val(func(self, self.for_computation(self.unbox(v))))
- return impl
-
-class ArithmeticTypeMixin(object):
- _mixin_ = True
-
- @binop
- def add(self, v1, v2):
- return v1 + v2
- @binop
- def sub(self, v1, v2):
- return v1 - v2
- @binop
- def mul(self, v1, v2):
- return v1 * v2
-
- @unaryop
- def pos(self, v):
- return +v
- @unaryop
- def neg(self, v):
- return -v
- @unaryop
- def abs(self, v):
- return abs(v)
-
- @binop
- def max(self, v1, v2):
- return max(v1, v2)
- @binop
- def min(self, v1, v2):
- return min(v1, v2)
-
- def bool(self, v):
- return bool(self.for_computation(self.unbox(v)))
- @raw_binop
- def eq(self, v1, v2):
- return v1 == v2
- @raw_binop
- def ne(self, v1, v2):
- return v1 != v2
- @raw_binop
- def lt(self, v1, v2):
- return v1 < v2
- @raw_binop
- def le(self, v1, v2):
- return v1 <= v2
- @raw_binop
- def gt(self, v1, v2):
- return v1 > v2
- @raw_binop
- def ge(self, v1, v2):
- return v1 >= v2
-
-
-class FloatArithmeticDtype(ArithmeticTypeMixin):
- _mixin_ = True
-
- def unwrap(self, space, w_item):
- return self.adapt_val(space.float_w(space.float(w_item)))
-
- def for_computation(self, v):
- return float(v)
-
- def str_format(self, item):
- return float2string(self.for_computation(self.unbox(item)), 'g', rfloat.DTSF_STR_PRECISION)
-
- @binop
- def div(self, v1, v2):
- try:
- return v1 / v2
- except ZeroDivisionError:
- if v1 == v2 == 0.0:
- return rfloat.NAN
- return rfloat.copysign(rfloat.INFINITY, v1 * v2)
- @binop
- def mod(self, v1, v2):
- return math.fmod(v1, v2)
- @binop
- def pow(self, v1, v2):
- return math.pow(v1, v2)
-
- @unaryop
- def sign(self, v):
- if v == 0.0:
- return 0.0
- return rfloat.copysign(1.0, v)
- @unaryop
- def reciprocal(self, v):
- if v == 0.0:
- return rfloat.copysign(rfloat.INFINITY, v)
- return 1.0 / v
- @unaryop
- def fabs(self, v):
- return math.fabs(v)
- @unaryop
- def floor(self, v):
- return math.floor(v)
-
- @binop
- def copysign(self, v1, v2):
- return math.copysign(v1, v2)
- @unaryop
- def exp(self, v):
- try:
- return math.exp(v)
- except OverflowError:
- return rfloat.INFINITY
- @unaryop
- def sin(self, v):
- return math.sin(v)
- @unaryop
- def cos(self, v):
- return math.cos(v)
- @unaryop
- def tan(self, v):
- return math.tan(v)
- @unaryop
- def arcsin(self, v):
- if not -1.0 <= v <= 1.0:
- return rfloat.NAN
- return math.asin(v)
- @unaryop
- def arccos(self, v):
- if not -1.0 <= v <= 1.0:
- return rfloat.NAN
- return math.acos(v)
- @unaryop
- def arctan(self, v):
- return math.atan(v)
- @unaryop
- def arcsinh(self, v):
- return math.asinh(v)
- @unaryop
- def arctanh(self, v):
- if v == 1.0 or v == -1.0:
- return math.copysign(rfloat.INFINITY, v)
- if not -1.0 < v < 1.0:
- return rfloat.NAN
- return math.atanh(v)
-
-class IntegerArithmeticDtype(ArithmeticTypeMixin):
- _mixin_ = True
-
- def unwrap(self, space, w_item):
- return self.adapt_val(space.int_w(space.int(w_item)))
-
- def for_computation(self, v):
- return widen(v)
-
- def str_format(self, item):
- return str(widen(self.unbox(item)))
-
- @binop
- def div(self, v1, v2):
- if v2 == 0:
- return 0
- return v1 / v2
- @binop
- def mod(self, v1, v2):
- return v1 % v2
-
-class SignedIntegerArithmeticDtype(IntegerArithmeticDtype):
- _mixin_ = True
-
- @unaryop
- def sign(self, v):
- if v > 0:
- return 1
- elif v < 0:
- return -1
- else:
- assert v == 0
- return 0
-
-class UnsignedIntegerArithmeticDtype(IntegerArithmeticDtype):
- _mixin_ = True
-
- @unaryop
- def sign(self, v):
- return int(v != 0)
-
-
-W_BoolDtype = create_low_level_dtype(
- num = 0, kind = BOOLLTR, name = "bool",
- aliases = ["?", "bool", "bool8"],
- applevel_types = ["bool"],
- T = lltype.Bool,
- valtype = bool,
-)
-class W_BoolDtype(SignedIntegerArithmeticDtype, W_BoolDtype):
- def unwrap(self, space, w_item):
- return self.adapt_val(space.is_true(w_item))
-
- def str_format(self, item):
- v = self.unbox(item)
- return "True" if v else "False"
-
- def for_computation(self, v):
- return int(v)
-
-W_Int8Dtype = create_low_level_dtype(
- num = 1, kind = SIGNEDLTR, name = "int8",
- aliases = ["b", "int8", "i1"],
- applevel_types = [],
- T = rffi.SIGNEDCHAR,
- valtype = rffi.SIGNEDCHAR._type,
- expected_size = 1,
-)
-class W_Int8Dtype(SignedIntegerArithmeticDtype, W_Int8Dtype):
- pass
-
-W_UInt8Dtype = create_low_level_dtype(
- num = 2, kind = UNSIGNEDLTR, name = "uint8",
- aliases = ["B", "uint8", "I1"],
- applevel_types = [],
- T = rffi.UCHAR,
- valtype = rffi.UCHAR._type,
- expected_size = 1,
-)
-class W_UInt8Dtype(UnsignedIntegerArithmeticDtype, W_UInt8Dtype):
- pass
-
-W_Int16Dtype = create_low_level_dtype(
- num = 3, kind = SIGNEDLTR, name = "int16",
- aliases = ["h", "int16", "i2"],
- applevel_types = [],
- T = rffi.SHORT,
- valtype = rffi.SHORT._type,
- expected_size = 2,
-)
-class W_Int16Dtype(SignedIntegerArithmeticDtype, W_Int16Dtype):
- pass
-
-W_UInt16Dtype = create_low_level_dtype(
- num = 4, kind = UNSIGNEDLTR, name = "uint16",
- aliases = ["H", "uint16", "I2"],
- applevel_types = [],
- T = rffi.USHORT,
- valtype = rffi.USHORT._type,
- expected_size = 2,
-)
-class W_UInt16Dtype(UnsignedIntegerArithmeticDtype, W_UInt16Dtype):
- pass
-
-W_Int32Dtype = create_low_level_dtype(
- num = 5, kind = SIGNEDLTR, name = "int32",
- aliases = ["i", "int32", "i4"],
- applevel_types = [],
- T = rffi.INT,
- valtype = rffi.INT._type,
- expected_size = 4,
-)
-class W_Int32Dtype(SignedIntegerArithmeticDtype, W_Int32Dtype):
- pass
-
-W_UInt32Dtype = create_low_level_dtype(
- num = 6, kind = UNSIGNEDLTR, name = "uint32",
- aliases = ["I", "uint32", "I4"],
- applevel_types = [],
- T = rffi.UINT,
- valtype = rffi.UINT._type,
- expected_size = 4,
-)
-class W_UInt32Dtype(UnsignedIntegerArithmeticDtype, W_UInt32Dtype):
- pass
-
-W_Int64Dtype = create_low_level_dtype(
- num = 9, kind = SIGNEDLTR, name = "int64",
- aliases = ["q", "int64", "i8"],
- applevel_types = ["long"],
- T = rffi.LONGLONG,
- valtype = rffi.LONGLONG._type,
- expected_size = 8,
-)
-class W_Int64Dtype(SignedIntegerArithmeticDtype, W_Int64Dtype):
- pass
-
-W_UInt64Dtype = create_low_level_dtype(
- num = 10, kind = UNSIGNEDLTR, name = "uint64",
- aliases = ["Q", "uint64", "I8"],
- applevel_types = [],
- T = rffi.ULONGLONG,
- valtype = rffi.ULONGLONG._type,
- expected_size = 8,
-)
-class W_UInt64Dtype(UnsignedIntegerArithmeticDtype, W_UInt64Dtype):
- pass
-
-if LONG_BIT == 32:
- long_dtype = W_Int32Dtype
- ulong_dtype = W_UInt32Dtype
-elif LONG_BIT == 64:
- long_dtype = W_Int64Dtype
- ulong_dtype = W_UInt64Dtype
-else:
- assert False
-
-class W_LongDtype(long_dtype):
- num = 7
- aliases = ["l"]
- applevel_types = ["int"]
-
-class W_ULongDtype(ulong_dtype):
- num = 8
- aliases = ["L"]
-
-W_Float32Dtype = create_low_level_dtype(
- num = 11, kind = FLOATINGLTR, name = "float32",
- aliases = ["f", "float32", "f4"],
- applevel_types = [],
- T = lltype.SingleFloat,
- valtype = rarithmetic.r_singlefloat,
- expected_size = 4,
-)
-class W_Float32Dtype(FloatArithmeticDtype, W_Float32Dtype):
- pass
-
-W_Float64Dtype = create_low_level_dtype(
- num = 12, kind = FLOATINGLTR, name = "float64",
- aliases = ["d", "float64", "f8"],
- applevel_types = ["float"],
- T = lltype.Float,
- valtype = float,
- expected_size = 8,
-)
-class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype):
- pass
-
-ALL_DTYPES = [
- W_BoolDtype,
- W_Int8Dtype, W_UInt8Dtype, W_Int16Dtype, W_UInt16Dtype,
- W_Int32Dtype, W_UInt32Dtype, W_LongDtype, W_ULongDtype,
- W_Int64Dtype, W_UInt64Dtype,
- W_Float32Dtype, W_Float64Dtype,
-]
-
-dtypes_by_alias = unrolling_iterable([
- (alias, dtype)
- for dtype in ALL_DTYPES
- for alias in dtype.aliases
-])
-dtypes_by_apptype = unrolling_iterable([
- (apptype, dtype)
- for dtype in ALL_DTYPES
- for apptype in dtype.applevel_types
-])
-dtypes_by_num_bytes = unrolling_iterable(sorted([
- (dtype.num_bytes, dtype)
- for dtype in ALL_DTYPES
-]))
-
W_Dtype.typedef = TypeDef("dtype",
- __module__ = "numpy",
+ __module__ = "numpypy",
__new__ = interp2app(W_Dtype.descr__new__.im_func),
+ __str__= interp2app(W_Dtype.descr_str),
__repr__ = interp2app(W_Dtype.descr_repr),
- __str__ = interp2app(W_Dtype.descr_str),
num = interp_attrproperty("num", cls=W_Dtype),
kind = interp_attrproperty("kind", cls=W_Dtype),
- itemsize = interp_attrproperty("num_bytes", cls=W_Dtype),
+ type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
+ itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
shape = GetSetProperty(W_Dtype.descr_get_shape),
)
W_Dtype.typedef.acceptable_as_base_class = False
+
+class DtypeCache(object):
+ def __init__(self, space):
+ self.w_booldtype = W_Dtype(
+ types.Bool(),
+ num=0,
+ kind=BOOLLTR,
+ name="bool",
+ char="?",
+ w_box_type = space.gettypefor(interp_boxes.W_BoolBox),
+ alternate_constructors=[space.w_bool],
+ )
+ self.w_int8dtype = W_Dtype(
+ types.Int8(),
+ num=1,
+ kind=SIGNEDLTR,
+ name="int8",
+ char="b",
+ w_box_type = space.gettypefor(interp_boxes.W_Int8Box)
+ )
+ self.w_uint8dtype = W_Dtype(
+ types.UInt8(),
+ num=2,
+ kind=UNSIGNEDLTR,
+ name="uint8",
+ char="B",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt8Box),
+ )
+ self.w_int16dtype = W_Dtype(
+ types.Int16(),
+ num=3,
+ kind=SIGNEDLTR,
+ name="int16",
+ char="h",
+ w_box_type = space.gettypefor(interp_boxes.W_Int16Box),
+ )
+ self.w_uint16dtype = W_Dtype(
+ types.UInt16(),
+ num=4,
+ kind=UNSIGNEDLTR,
+ name="uint16",
+ char="H",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt16Box),
+ )
+ self.w_int32dtype = W_Dtype(
+ types.Int32(),
+ num=5,
+ kind=SIGNEDLTR,
+ name="int32",
+ char="i",
+ w_box_type = space.gettypefor(interp_boxes.W_Int32Box),
+ )
+ self.w_uint32dtype = W_Dtype(
+ types.UInt32(),
+ num=6,
+ kind=UNSIGNEDLTR,
+ name="uint32",
+ char="I",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt32Box),
+ )
+ if LONG_BIT == 32:
+ name = "int32"
+ elif LONG_BIT == 64:
+ name = "int64"
+ self.w_longdtype = W_Dtype(
+ types.Long(),
+ num=7,
+ kind=SIGNEDLTR,
+ name=name,
+ char="l",
+ w_box_type = space.gettypefor(interp_boxes.W_LongBox),
+ alternate_constructors=[space.w_int],
+ )
+ self.w_ulongdtype = W_Dtype(
+ types.ULong(),
+ num=8,
+ kind=UNSIGNEDLTR,
+ name="u" + name,
+ char="L",
+ w_box_type = space.gettypefor(interp_boxes.W_ULongBox),
+ )
+ self.w_int64dtype = W_Dtype(
+ types.Int64(),
+ num=9,
+ kind=SIGNEDLTR,
+ name="int64",
+ char="q",
+ w_box_type = space.gettypefor(interp_boxes.W_Int64Box),
+ alternate_constructors=[space.w_long],
+ )
+ self.w_uint64dtype = W_Dtype(
+ types.UInt64(),
+ num=10,
+ kind=UNSIGNEDLTR,
+ name="uint64",
+ char="Q",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt64Box),
+ )
+ self.w_float32dtype = W_Dtype(
+ types.Float32(),
+ num=11,
+ kind=FLOATINGLTR,
+ name="float32",
+ char="f",
+ w_box_type = space.gettypefor(interp_boxes.W_Float32Box),
+ )
+ self.w_float64dtype = W_Dtype(
+ types.Float64(),
+ num=12,
+ kind=FLOATINGLTR,
+ name="float64",
+ char="d",
+ w_box_type = space.gettypefor(interp_boxes.W_Float64Box),
+ alternate_constructors=[space.w_float],
+ )
+
+ self.builtin_dtypes = [
+ self.w_booldtype, self.w_int8dtype, self.w_uint8dtype,
+ self.w_int16dtype, self.w_uint16dtype, self.w_int32dtype,
+ self.w_uint32dtype, self.w_longdtype, self.w_ulongdtype,
+ self.w_int64dtype, self.w_uint64dtype, self.w_float32dtype,
+ self.w_float64dtype
+ ]
+ self.dtypes_by_num_bytes = sorted(
+ (dtype.itemtype.get_element_size(), dtype)
+ for dtype in self.builtin_dtypes
+ )
+
+def get_dtype_cache(space):
+ return space.fromcache(DtypeCache)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -4,7 +4,7 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.module.micronumpy import interp_ufuncs, interp_dtype, signature
from pypy.rlib import jit
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
from pypy.tool.sourcetools import func_with_new_name
from pypy.rlib.rstring import StringBuilder
from pypy.rlib.objectmodel import instantiate
@@ -98,46 +98,6 @@
endshape[i] = remainder[i]
return endshape
-def descr_new_array(space, w_subtype, w_item_or_iterable, w_dtype=None,
- w_order=NoneNotWrapped):
- # find scalar
- if not space.issequence_w(w_item_or_iterable):
- w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
- w_item_or_iterable,
- w_dtype)
- dtype = space.interp_w(interp_dtype.W_Dtype,
- space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
- return scalar_w(space, dtype, w_item_or_iterable)
- if w_order is None:
- order = 'C'
- else:
- order = space.str_w(w_order)
- if order != 'C': # or order != 'F':
- raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
- order)
- shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
- # they come back in C order
- size = len(elems_w)
- if space.is_w(w_dtype, space.w_None):
- w_dtype = None
- for w_elem in elems_w:
- w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
- w_dtype)
- if w_dtype is space.fromcache(interp_dtype.W_Float64Dtype):
- break
- if w_dtype is None:
- w_dtype = space.w_None
- dtype = space.interp_w(interp_dtype.W_Dtype,
- space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
- )
- arr = NDimArray(size, shape[:], dtype=dtype, order=order)
- shapelen = len(shape)
- arr_iter = arr.start_iter(arr.shape)
- for i in range(len(elems_w)):
- w_elem = elems_w[i]
- dtype.setitem_w(space, arr.storage, arr_iter.offset, w_elem)
- arr_iter = arr_iter.next(shapelen)
- return arr
# Iterators for arrays
# --------------------
@@ -178,6 +138,25 @@
def get_offset(self):
return self.offset
+class OneDimIterator(BaseIterator):
+ def __init__(self, start, step, stop):
+ self.offset = start
+ self.step = step
+ self.size = stop * step + start
+
+ def next(self, shapelen):
+ arr = instantiate(OneDimIterator)
+ arr.size = self.size
+ arr.step = self.step
+ arr.offset = self.offset + self.step
+ return arr
+
+ def done(self):
+ return self.offset == self.size
+
+ def get_offset(self):
+ return self.offset
+
class ViewIterator(BaseIterator):
def __init__(self, arr):
self.indices = [0] * len(arr.shape)
@@ -227,7 +206,7 @@
self.strides = []
self.backstrides = []
for i in range(len(arr.shape)):
- if arr.shape[i]==1:
+ if arr.shape[i] == 1:
self.strides.append(0)
self.backstrides.append(0)
else:
@@ -312,12 +291,12 @@
def get_offset(self):
return 0
+
class BaseArray(Wrappable):
_attrs_ = ["invalidates", "signature", "shape", "strides", "backstrides",
"start", 'order']
- _immutable_fields_ = ['shape[*]', "strides[*]", "backstrides[*]", 'start',
- "order"]
+ _immutable_fields_ = ['start', "order"]
strides = None
start = 0
@@ -327,21 +306,24 @@
self.shape = shape
self.order = order
if self.strides is None:
- strides = []
- backstrides = []
- s = 1
- shape_rev = shape[:]
- if order == 'C':
- shape_rev.reverse()
- for sh in shape_rev:
- strides.append(s)
- backstrides.append(s * (sh - 1))
- s *= sh
- if order == 'C':
- strides.reverse()
- backstrides.reverse()
- self.strides = strides[:]
- self.backstrides = backstrides[:]
+ self.calc_strides(shape)
+
+ def calc_strides(self, shape):
+ strides = []
+ backstrides = []
+ s = 1
+ shape_rev = shape[:]
+ if self.order == 'C':
+ shape_rev.reverse()
+ for sh in shape_rev:
+ strides.append(s)
+ backstrides.append(s * (sh - 1))
+ s *= sh
+ if self.order == 'C':
+ strides.reverse()
+ backstrides.reverse()
+ self.strides = strides[:]
+ self.backstrides = backstrides[:]
def invalidated(self):
if self.invalidates:
@@ -355,6 +337,13 @@
def add_invalidates(self, other):
self.invalidates.append(other)
+ def descr__new__(space, w_subtype, w_size, w_dtype=None):
+ dtype = space.interp_w(interp_dtype.W_Dtype,
+ space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+ )
+ size, shape = _find_size_and_shape(space, w_size)
+ return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
+
def _unaryop_impl(ufunc_name):
def impl(self, space):
return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
@@ -428,8 +417,8 @@
self=self, dtype=dtype,
i=i, result=result, idx=idx,
cur_best=cur_best)
- new_best = getattr(dtype, op_name)(cur_best, self.eval(i))
- if dtype.ne(new_best, cur_best):
+ new_best = getattr(dtype.itemtype, op_name)(cur_best, self.eval(i))
+ if dtype.itemtype.ne(new_best, cur_best):
result = idx
cur_best = new_best
i = i.next(shapelen)
@@ -439,8 +428,7 @@
size = self.find_size()
if size == 0:
raise OperationError(space.w_ValueError,
- space.wrap("Can't call %s on zero-size arrays" \
- % op_name))
+ space.wrap("Can't call %s on zero-size arrays" % op_name))
return space.wrap(loop(self))
return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
@@ -452,7 +440,7 @@
all_driver.jit_merge_point(signature=self.signature,
shapelen=shapelen, self=self,
dtype=dtype, i=i)
- if not dtype.bool(self.eval(i)):
+ if not dtype.itemtype.bool(self.eval(i)):
return False
i = i.next(shapelen)
return True
@@ -467,7 +455,7 @@
any_driver.jit_merge_point(signature=self.signature,
shapelen=shapelen, self=self,
dtype=dtype, i=i)
- if dtype.bool(self.eval(i)):
+ if dtype.itemtype.bool(self.eval(i)):
return True
i = i.next(shapelen)
return False
@@ -499,7 +487,7 @@
return space.wrap(self.find_size())
def descr_copy(self, space):
- return space.call_function(space.gettypefor(BaseArray), self, self.find_dtype())
+ return self.get_concrete().copy()
def descr_len(self, space):
return self.get_concrete().descr_len(space)
@@ -519,8 +507,8 @@
res.append(')')
else:
concrete.to_str(space, 1, res, indent=' ')
- if (dtype is not space.fromcache(interp_dtype.W_Float64Dtype) and
- dtype is not space.fromcache(interp_dtype.W_Int64Dtype)) or \
+ if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
+ dtype is not interp_dtype.get_dtype_cache(space).w_int64dtype) or \
not self.find_size():
res.append(", dtype=" + dtype.name)
res.append(")")
@@ -589,7 +577,7 @@
start = False
else:
builder.append(spacer)
- builder.append(dtype.str_format(self.getitem(item)))
+ builder.append(dtype.itemtype.str_format(self.getitem(item)))
item += self.strides[0]
# Add a comma only if comma is False - this prevents adding two
# commas
@@ -602,7 +590,7 @@
start = False
else:
builder.append(spacer)
- builder.append(dtype.str_format(self.getitem(item)))
+ builder.append(dtype.itemtype.str_format(self.getitem(item)))
item += self.strides[0]
i += 1
else:
@@ -674,6 +662,7 @@
return False
return True
+ @jit.unroll_safe
def _prepare_slice_args(self, space, w_idx):
if (space.isinstance_w(w_idx, space.w_int) or
space.isinstance_w(w_idx, space.w_slice)):
@@ -684,31 +673,31 @@
def descr_getitem(self, space, w_idx):
if self._single_item_result(space, w_idx):
concrete = self.get_concrete()
+ if len(concrete.shape) < 1:
+ raise OperationError(space.w_IndexError, space.wrap(
+ "0-d arrays can't be indexed"))
item = concrete._index_of_single_item(space, w_idx)
- return concrete.getitem(item).wrap(space)
+ return concrete.getitem(item)
chunks = self._prepare_slice_args(space, w_idx)
return space.wrap(self.create_slice(space, chunks))
def descr_setitem(self, space, w_idx, w_value):
self.invalidated()
- concrete = self.get_concrete()
if self._single_item_result(space, w_idx):
+ concrete = self.get_concrete()
+ if len(concrete.shape) < 1:
+ raise OperationError(space.w_IndexError, space.wrap(
+ "0-d arrays can't be indexed"))
item = concrete._index_of_single_item(space, w_idx)
concrete.setitem_w(space, item, w_value)
return
- if isinstance(w_value, BaseArray):
- # for now we just copy if setting part of an array from
- # part of itself. can be improved.
- if (concrete.get_root_storage() ==
- w_value.get_concrete().get_root_storage()):
- w_value = space.call_function(space.gettypefor(BaseArray), w_value)
- assert isinstance(w_value, BaseArray)
- else:
+ if not isinstance(w_value, BaseArray):
w_value = convert_to_array(space, w_value)
chunks = self._prepare_slice_args(space, w_idx)
view = self.create_slice(space, chunks)
view.setslice(space, w_value)
+ @jit.unroll_safe
def create_slice(self, space, chunks):
if len(chunks) == 1:
start, stop, step, lgt = chunks[0]
@@ -747,17 +736,35 @@
shape[:])
def descr_mean(self, space):
- return space.wrap(space.float_w(self.descr_sum(space)) / self.find_size())
+ return space.div(self.descr_sum(space), space.wrap(self.find_size()))
def descr_nonzero(self, space):
- try:
- if self.find_size() > 1:
- raise OperationError(space.w_ValueError, space.wrap(
- "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
- except ValueError:
- pass
- return space.wrap(space.is_true(self.get_concrete().eval(
- self.start_iter(self.shape)).wrap(space)))
+ if self.find_size() > 1:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
+ return space.wrap(space.is_true(
+ self.get_concrete().eval(self.start_iter(self.shape))
+ ))
+
+ def descr_get_transpose(self, space):
+ concrete = self.get_concrete()
+ if len(concrete.shape) < 2:
+ return space.wrap(self)
+ new_sig = signature.Signature.find_sig([
+ NDimSlice.signature, self.signature
+ ])
+ strides = []
+ backstrides = []
+ shape = []
+ for i in range(len(concrete.shape) - 1, -1, -1):
+ strides.append(concrete.strides[i])
+ backstrides.append(concrete.backstrides[i])
+ shape.append(concrete.shape[i])
+ return space.wrap(NDimSlice(concrete, new_sig, self.start, strides[:],
+ backstrides[:], shape[:]))
+
+ def descr_get_flatiter(self, space):
+ return space.wrap(W_FlatIterator(self))
def getitem(self, item):
raise NotImplementedError
@@ -765,22 +772,22 @@
def start_iter(self, res_shape=None):
raise NotImplementedError
+ def descr_debug_repr(self, space):
+ return space.wrap(self.debug_repr())
+
def convert_to_array(space, w_obj):
if isinstance(w_obj, BaseArray):
return w_obj
elif space.issequence_w(w_obj):
# Convert to array.
- w_obj = space.call_function(space.gettypefor(BaseArray), w_obj)
- assert isinstance(w_obj, BaseArray)
- return w_obj
+ return array(space, w_obj, w_order=None)
else:
# If it's a scalar
dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
return scalar_w(space, dtype, w_obj)
def scalar_w(space, dtype, w_obj):
- assert isinstance(dtype, interp_dtype.W_Dtype)
- return Scalar(dtype, dtype.unwrap(space, w_obj))
+ return Scalar(dtype, dtype.coerce(space, w_obj))
class Scalar(BaseArray):
"""
@@ -791,12 +798,13 @@
_attrs_ = ["dtype", "value", "shape"]
def __init__(self, dtype, value):
+ self.shape = self.strides = []
BaseArray.__init__(self, [], 'C')
self.dtype = dtype
self.value = value
def find_size(self):
- raise ValueError
+ return 1
def get_concrete(self):
return self
@@ -805,7 +813,7 @@
return self.dtype
def getitem(self, item):
- return self.value
+ raise NotImplementedError
def eval(self, iter):
return self.value
@@ -814,7 +822,13 @@
return ConstantIterator()
def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
- builder.append(self.dtype.str_format(self.value))
+ builder.append(self.dtype.itemtype.str_format(self.value))
+
+ def copy(self):
+ return Scalar(self.dtype, self.value)
+
+ def debug_repr(self):
+ return 'Scalar'
class VirtualArray(BaseArray):
"""
@@ -834,7 +848,7 @@
i = 0
signature = self.signature
result_size = self.find_size()
- result = NDimArray(result_size, self.shape, self.find_dtype())
+ result = W_NDimArray(result_size, self.shape, self.find_dtype())
shapelen = len(self.shape)
i = self.start_iter()
ri = result.start_iter()
@@ -907,6 +921,17 @@
return self.forced_result.start_iter(res_shape)
return Call1Iterator(self.values.start_iter(res_shape))
+ def debug_repr(self):
+ sig = self.signature
+ assert isinstance(sig, signature.Signature)
+ call_sig = sig.components[0]
+ assert isinstance(call_sig, signature.Call1)
+ if self.forced_result is not None:
+ return 'Call1(%s, forced=%s)' % (call_sig.name,
+ self.forced_result.debug_repr())
+ return 'Call1(%s, %s)' % (call_sig.name,
+ self.values.debug_repr())
+
class Call2(VirtualArray):
"""
Intermediate class for performing binary operations.
@@ -946,6 +971,18 @@
assert isinstance(call_sig, signature.Call2)
return call_sig.func(self.calc_dtype, lhs, rhs)
+ def debug_repr(self):
+ sig = self.signature
+ assert isinstance(sig, signature.Signature)
+ call_sig = sig.components[0]
+ assert isinstance(call_sig, signature.Call2)
+ if self.forced_result is not None:
+ return 'Call2(%s, forced=%s)' % (call_sig.name,
+ self.forced_result.debug_repr())
+ return 'Call2(%s, %s, %s)' % (call_sig.name,
+ self.left.debug_repr(),
+ self.right.debug_repr())
+
class ViewArray(BaseArray):
"""
Class for representing views of arrays, they will reflect changes of parent
@@ -985,8 +1022,6 @@
return space.wrap(self.shape[0])
return space.wrap(1)
-class VirtualView(VirtualArray):
- pass
class NDimSlice(ViewArray):
signature = signature.BaseSignature()
@@ -1001,9 +1036,6 @@
for sh in shape:
self.size *= sh
- def get_root_storage(self):
- return self.parent.get_concrete().get_root_storage()
-
def find_size(self):
return self.size
@@ -1032,14 +1064,25 @@
def start_iter(self, res_shape=None):
if res_shape is not None and res_shape != self.shape:
return BroadcastIterator(self, res_shape)
- # XXX there is a possible optimization here with SingleDimViewIterator
- # ignore for now
+ if len(self.shape) == 1:
+ return OneDimIterator(self.start, self.strides[0], self.shape[0])
return ViewIterator(self)
def setitem(self, item, value):
self.parent.setitem(item, value)
-class NDimArray(BaseArray):
+ def debug_repr(self):
+ return 'Slice(%s)' % self.parent.debug_repr()
+
+ def copy(self):
+ array = W_NDimArray(self.size, self.shape[:], self.find_dtype())
+ iter = self.start_iter()
+ while not iter.done():
+ array.setitem(iter.offset, self.getitem(iter.offset))
+ iter = iter.next(len(self.shape))
+ return array
+
+class W_NDimArray(BaseArray):
""" A class representing contiguous array. We know that each iteration
by say ufunc will increase the data index by one
"""
@@ -1053,9 +1096,6 @@
def get_concrete(self):
return self
- def get_root_storage(self):
- return self.storage
-
def find_size(self):
return self.size
@@ -1068,6 +1108,15 @@
def eval(self, iter):
return self.dtype.getitem(self.storage, iter.get_offset())
+ def copy(self):
+ array = W_NDimArray(self.size, self.shape[:], self.dtype, self.order)
+ rffi.c_memcpy(
+ array.storage,
+ self.storage,
+ self.size * self.dtype.itemtype.get_element_size()
+ )
+ return array
+
def descr_len(self, space):
if len(self.shape):
return space.wrap(self.shape[0])
@@ -1075,8 +1124,7 @@
"len() of unsized object"))
def setitem_w(self, space, item, w_value):
- self.invalidated()
- self.dtype.setitem_w(space, self.storage, item, w_value)
+ return self.setitem(item, self.dtype.coerce(space, w_value))
def setitem(self, item, value):
self.invalidated()
@@ -1089,6 +1137,9 @@
return ArrayIterator(self.size)
raise NotImplementedError # use ViewIterator simply, test it
+ def debug_repr(self):
+ return 'Array'
+
def __del__(self):
lltype.free(self.storage, flavor='raw', track_allocation=False)
@@ -1105,27 +1156,75 @@
shape.append(item)
return size, shape
+def array(space, w_item_or_iterable, w_dtype=None, w_order=NoneNotWrapped):
+ # find scalar
+ if not space.issequence_w(w_item_or_iterable):
+ if space.is_w(w_dtype, space.w_None):
+ w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
+ w_item_or_iterable)
+ dtype = space.interp_w(interp_dtype.W_Dtype,
+ space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+ )
+ return scalar_w(space, dtype, w_item_or_iterable)
+ if w_order is None:
+ order = 'C'
+ else:
+ order = space.str_w(w_order)
+ if order != 'C': # or order != 'F':
+ raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
+ order)
+ shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
+ # they come back in C order
+ size = len(elems_w)
+ if space.is_w(w_dtype, space.w_None):
+ w_dtype = None
+ for w_elem in elems_w:
+ w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
+ w_dtype)
+ if w_dtype is interp_dtype.get_dtype_cache(space).w_float64dtype:
+ break
+ if w_dtype is None:
+ w_dtype = space.w_None
+ dtype = space.interp_w(interp_dtype.W_Dtype,
+ space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+ )
+ arr = W_NDimArray(size, shape[:], dtype=dtype, order=order)
+ shapelen = len(shape)
+ arr_iter = arr.start_iter(arr.shape)
+ for i in range(len(elems_w)):
+ w_elem = elems_w[i]
+ dtype.setitem(arr.storage, arr_iter.offset, dtype.coerce(space, w_elem))
+ arr_iter = arr_iter.next(shapelen)
+ return arr
+
def zeros(space, w_size, w_dtype=None):
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
size, shape = _find_size_and_shape(space, w_size)
- return space.wrap(NDimArray(size, shape[:], dtype=dtype))
+ return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
def ones(space, w_size, w_dtype=None):
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
+
size, shape = _find_size_and_shape(space, w_size)
- arr = NDimArray(size, shape[:], dtype=dtype)
- one = dtype.adapt_val(1)
+ arr = W_NDimArray(size, shape[:], dtype=dtype)
+ one = dtype.box(1)
arr.dtype.fill(arr.storage, one, 0, size)
return space.wrap(arr)
+def dot(space, w_obj, w_obj2):
+ w_arr = convert_to_array(space, w_obj)
+ if isinstance(w_arr, Scalar):
+ return convert_to_array(space, w_obj2).descr_dot(space, w_arr)
+ return w_arr.descr_dot(space, w_obj2)
+
BaseArray.typedef = TypeDef(
- 'numarray',
- __new__ = interp2app(descr_new_array),
-
+ 'ndarray',
+ __module__ = "numpypy",
+ __new__ = interp2app(BaseArray.descr__new__.im_func),
__len__ = interp2app(BaseArray.descr_len),
__getitem__ = interp2app(BaseArray.descr_getitem),
@@ -1159,11 +1258,15 @@
__repr__ = interp2app(BaseArray.descr_repr),
__str__ = interp2app(BaseArray.descr_str),
+ __debug_repr__ = interp2app(BaseArray.descr_debug_repr),
dtype = GetSetProperty(BaseArray.descr_get_dtype),
shape = GetSetProperty(BaseArray.descr_get_shape),
size = GetSetProperty(BaseArray.descr_get_size),
+ T = GetSetProperty(BaseArray.descr_get_transpose),
+ flat = GetSetProperty(BaseArray.descr_get_flatiter),
+
mean = interp2app(BaseArray.descr_mean),
sum = interp2app(BaseArray.descr_sum),
prod = interp2app(BaseArray.descr_prod),
@@ -1177,3 +1280,54 @@
copy = interp2app(BaseArray.descr_copy),
)
+
+
+class W_FlatIterator(ViewArray):
+ signature = signature.BaseSignature()
+
+ @jit.unroll_safe
+ def __init__(self, arr):
+ size = 1
+ for sh in arr.shape:
+ size *= sh
+ new_sig = signature.Signature.find_sig([
+ W_FlatIterator.signature, arr.signature
+ ])
+ ViewArray.__init__(self, arr, new_sig, [arr.strides[-1]],
+ [arr.backstrides[-1]], [size])
+ self.shapelen = len(arr.shape)
+ self.arr = arr
+ self.iter = self.start_iter()
+
+ def start_iter(self, res_shape=None):
+ if res_shape is not None and res_shape != self.shape:
+ return BroadcastIterator(self, res_shape)
+ return OneDimIterator(self.arr.start, self.strides[0],
+ self.shape[0])
+
+ def find_dtype(self):
+ return self.arr.find_dtype()
+
+ def find_size(self):
+ return self.shape[0]
+
+ def descr_next(self, space):
+ if self.iter.done():
+ raise OperationError(space.w_StopIteration, space.w_None)
+ result = self.eval(self.iter)
+ self.iter = self.iter.next(self.shapelen)
+ return result
+
+ def descr_iter(self):
+ return self
+
+ def debug_repr(self):
+ return 'FlatIter(%s)' % self.arr.debug_repr()
+
+
+W_FlatIterator.typedef = TypeDef(
+ 'flatiter',
+ next = interp2app(W_FlatIterator.descr_next),
+ __iter__ = interp2app(W_FlatIterator.descr_iter),
+)
+W_FlatIterator.acceptable_as_base_class = False
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -1,6 +1,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
from pypy.rlib.rstruct.runpack import runpack
from pypy.rpython.lltypesystem import lltype, rffi
@@ -9,7 +9,7 @@
@unwrap_spec(s=str)
def fromstring(space, s):
- from pypy.module.micronumpy.interp_numarray import NDimArray
+ from pypy.module.micronumpy.interp_numarray import W_NDimArray
length = len(s)
if length % FLOAT_SIZE == 0:
@@ -18,8 +18,8 @@
raise OperationError(space.w_ValueError, space.wrap(
"string length %d not divisable by %d" % (length, FLOAT_SIZE)))
- dtype = space.fromcache(W_Float64Dtype)
- a = NDimArray(number, [number], dtype=dtype)
+ dtype = get_dtype_cache(space).w_float64dtype
+ a = W_NDimArray(number, [number], dtype=dtype)
start = 0
end = FLOAT_SIZE
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -2,7 +2,7 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_dtype, signature
+from pypy.module.micronumpy import interp_boxes, interp_dtype, signature, types
from pypy.rlib import jit
from pypy.rlib.rarithmetic import LONG_BIT
from pypy.tool.sourcetools import func_with_new_name
@@ -15,6 +15,7 @@
class W_Ufunc(Wrappable):
_attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
+ _immutable_fields_ = ["promote_to_float", "promote_bools"]
def __init__(self, name, promote_to_float, promote_bools, identity):
self.name = name
@@ -29,7 +30,7 @@
def descr_get_identity(self, space):
if self.identity is None:
return space.w_None
- return self.identity.wrap(space)
+ return self.identity
def descr_call(self, space, __args__):
if __args__.keywords or len(__args__.arguments_w) < self.argcount:
@@ -80,8 +81,7 @@
new_sig = signature.Signature.find_sig([
self.reduce_signature, obj.signature
])
- return self.reduce_loop(new_sig, shapelen, start, value, obj,
- dtype).wrap(space)
+ return self.reduce_loop(new_sig, shapelen, start, value, obj, dtype)
def reduce_loop(self, signature, shapelen, i, value, obj, dtype):
while not i.done():
@@ -115,7 +115,7 @@
promote_bools=self.promote_bools,
)
if isinstance(w_obj, Scalar):
- return self.func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space)
+ return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
new_sig = signature.Signature.find_sig([self.signature, w_obj.signature])
w_res = Call1(new_sig, w_obj.shape, res_dtype, w_obj, w_obj.order)
@@ -124,6 +124,7 @@
class W_Ufunc2(W_Ufunc):
+ _immutable_fields_ = ["comparison_func", "func"]
argcount = 2
def __init__(self, func, name, promote_to_float=False, promote_bools=False,
@@ -148,14 +149,14 @@
promote_bools=self.promote_bools,
)
if self.comparison_func:
- res_dtype = space.fromcache(interp_dtype.W_BoolDtype)
+ res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
else:
res_dtype = calc_dtype
if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
return self.func(calc_dtype,
w_lhs.value.convert_to(calc_dtype),
w_rhs.value.convert_to(calc_dtype)
- ).wrap(space)
+ )
new_sig = signature.Signature.find_sig([
self.signature, w_lhs.signature, w_rhs.signature
@@ -169,7 +170,7 @@
W_Ufunc.typedef = TypeDef("ufunc",
- __module__ = "numpy",
+ __module__ = "numpypy",
__call__ = interp2app(W_Ufunc.descr_call),
__repr__ = interp2app(W_Ufunc.descr_repr),
@@ -187,7 +188,7 @@
dt1, dt2 = dt2, dt1
# Some operations promote op(bool, bool) to return int8, rather than bool
if promote_bools and (dt1.kind == dt2.kind == interp_dtype.BOOLLTR):
- return space.fromcache(interp_dtype.W_Int8Dtype)
+ return interp_dtype.get_dtype_cache(space).w_int8dtype
if promote_to_float:
return find_unaryop_result_dtype(space, dt2, promote_to_float=True)
# If they're the same kind, choose the greater one.
@@ -197,14 +198,14 @@
# Everything promotes to float, and bool promotes to everything.
if dt2.kind == interp_dtype.FLOATINGLTR or dt1.kind == interp_dtype.BOOLLTR:
# Float32 + 8-bit int = Float64
- if dt2.num == 11 and dt1.num_bytes >= 4:
- return space.fromcache(interp_dtype.W_Float64Dtype)
+ if dt2.num == 11 and dt1.itemtype.get_element_size() >= 4:
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
return dt2
# for now this means mixing signed and unsigned
if dt2.kind == interp_dtype.SIGNEDLTR:
# if dt2 has a greater number of bytes, then just go with it
- if dt1.num_bytes < dt2.num_bytes:
+ if dt1.itemtype.get_element_size() < dt2.itemtype.get_element_size():
return dt2
# we need to promote both dtypes
dtypenum = dt2.num + 2
@@ -214,10 +215,11 @@
# UInt64 + signed = Float64
if dt2.num == 10:
dtypenum += 1
- newdtype = interp_dtype.ALL_DTYPES[dtypenum]
+ newdtype = interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
- if newdtype.num_bytes > dt2.num_bytes or newdtype.kind == interp_dtype.FLOATINGLTR:
- return space.fromcache(newdtype)
+ if (newdtype.itemtype.get_element_size() > dt2.itemtype.get_element_size() or
+ newdtype.kind == interp_dtype.FLOATINGLTR):
+ return newdtype
else:
# we only promoted to long on 32-bit or to longlong on 64-bit
# this is really for dealing with the Long and Ulong dtypes
@@ -225,35 +227,42 @@
dtypenum += 2
else:
dtypenum += 3
- return space.fromcache(interp_dtype.ALL_DTYPES[dtypenum])
+ return interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
def find_unaryop_result_dtype(space, dt, promote_to_float=False,
promote_bools=False, promote_to_largest=False):
if promote_bools and (dt.kind == interp_dtype.BOOLLTR):
- return space.fromcache(interp_dtype.W_Int8Dtype)
+ return interp_dtype.get_dtype_cache(space).w_int8dtype
if promote_to_float:
if dt.kind == interp_dtype.FLOATINGLTR:
return dt
if dt.num >= 5:
- return space.fromcache(interp_dtype.W_Float64Dtype)
- for bytes, dtype in interp_dtype.dtypes_by_num_bytes:
- if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes > dt.num_bytes:
- return space.fromcache(dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
+ for bytes, dtype in interp_dtype.get_dtype_cache(space).dtypes_by_num_bytes:
+ if (dtype.kind == interp_dtype.FLOATINGLTR and
+ dtype.itemtype.get_element_size() > dt.itemtype.get_element_size()):
+ return dtype
if promote_to_largest:
if dt.kind == interp_dtype.BOOLLTR or dt.kind == interp_dtype.SIGNEDLTR:
- return space.fromcache(interp_dtype.W_Int64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
elif dt.kind == interp_dtype.FLOATINGLTR:
- return space.fromcache(interp_dtype.W_Float64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
elif dt.kind == interp_dtype.UNSIGNEDLTR:
- return space.fromcache(interp_dtype.W_UInt64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_uint64dtype
else:
assert False
return dt
def find_dtype_for_scalar(space, w_obj, current_guess=None):
- bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
- long_dtype = space.fromcache(interp_dtype.W_LongDtype)
- int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
+ bool_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+ long_dtype = interp_dtype.get_dtype_cache(space).w_longdtype
+ int64_dtype = interp_dtype.get_dtype_cache(space).w_int64dtype
+
+ if isinstance(w_obj, interp_boxes.W_GenericBox):
+ dtype = w_obj.get_dtype(space)
+ if current_guess is None:
+ return dtype
+ return find_binop_result_dtype(space, dtype, current_guess)
if space.isinstance_w(w_obj, space.w_bool):
if current_guess is None or current_guess is bool_dtype:
@@ -269,20 +278,19 @@
current_guess is long_dtype or current_guess is int64_dtype):
return int64_dtype
return current_guess
- return space.fromcache(interp_dtype.W_Float64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
if argcount == 1:
def impl(res_dtype, value):
- return getattr(res_dtype, op_name)(value)
+ return getattr(res_dtype.itemtype, op_name)(value)
elif argcount == 2:
+ dtype_cache = interp_dtype.get_dtype_cache(space)
def impl(res_dtype, lvalue, rvalue):
- res = getattr(res_dtype, op_name)(lvalue, rvalue)
+ res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue)
if comparison_func:
- booldtype = space.fromcache(interp_dtype.W_BoolDtype)
- assert isinstance(booldtype, interp_dtype.W_BoolDtype)
- res = booldtype.box(res)
+ return dtype_cache.w_booldtype.box(res)
return res
return func_with_new_name(impl, ufunc_name)
@@ -319,6 +327,8 @@
("floor", "floor", 1, {"promote_to_float": True}),
("exp", "exp", 1, {"promote_to_float": True}),
+ ('sqrt', 'sqrt', 1, {'promote_to_float': True}),
+
("sin", "sin", 1, {"promote_to_float": True}),
("cos", "cos", 1, {"promote_to_float": True}),
("tan", "tan", 1, {"promote_to_float": True}),
@@ -336,7 +346,7 @@
identity = extra_kwargs.get("identity")
if identity is not None:
- identity = space.fromcache(interp_dtype.W_LongDtype).adapt_val(identity)
+ identity = interp_dtype.get_dtype_cache(space).w_longdtype.box(identity)
extra_kwargs["identity"] = identity
func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -40,13 +40,15 @@
return Signature._known_sigs.setdefault(components, Signature(components))
class Call1(BaseSignature):
- _immutable_fields_ = ["func"]
+ _immutable_fields_ = ["func", "name"]
def __init__(self, func):
self.func = func
+ self.name = func.func_name
class Call2(BaseSignature):
- _immutable_fields_ = ["func"]
+ _immutable_fields_ = ["func", "name"]
def __init__(self, func):
self.func = func
+ self.name = func.func_name
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -1,6 +1,6 @@
from pypy.conftest import gettestobjspace
-from pypy.module.micronumpy import interp_dtype
-from pypy.module.micronumpy.interp_numarray import NDimArray, Scalar
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, Scalar
from pypy.module.micronumpy.interp_ufuncs import (find_binop_result_dtype,
find_unaryop_result_dtype)
@@ -11,9 +11,10 @@
class TestSignature(object):
def test_binop_signature(self, space):
- float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+ float64_dtype = get_dtype_cache(space).w_float64dtype
+ bool_dtype = get_dtype_cache(space).w_booldtype
- ar = NDimArray(10, [10], dtype=float64_dtype)
+ ar = W_NDimArray(10, [10], dtype=float64_dtype)
v1 = ar.descr_add(space, ar)
v2 = ar.descr_add(space, Scalar(float64_dtype, 2.0))
assert v1.signature is not v2.signature
@@ -22,7 +23,7 @@
v4 = ar.descr_add(space, ar)
assert v1.signature is v4.signature
- bool_ar = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_BoolDtype))
+ bool_ar = W_NDimArray(10, [10], dtype=bool_dtype)
v5 = ar.descr_add(space, bool_ar)
assert v5.signature is not v1.signature
assert v5.signature is not v2.signature
@@ -30,7 +31,9 @@
assert v5.signature is v6.signature
def test_slice_signature(self, space):
- ar = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_Float64Dtype))
+ float64_dtype = get_dtype_cache(space).w_float64dtype
+
+ ar = W_NDimArray(10, [10], dtype=float64_dtype)
v1 = ar.descr_getitem(space, space.wrap(slice(1, 3, 1)))
v2 = ar.descr_getitem(space, space.wrap(slice(4, 6, 1)))
assert v1.signature is v2.signature
@@ -41,10 +44,10 @@
class TestUfuncCoerscion(object):
def test_binops(self, space):
- bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
- int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype)
- int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype)
- float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+ bool_dtype = get_dtype_cache(space).w_booldtype
+ int8_dtype = get_dtype_cache(space).w_int8dtype
+ int32_dtype = get_dtype_cache(space).w_int32dtype
+ float64_dtype = get_dtype_cache(space).w_float64dtype
# Basic pairing
assert find_binop_result_dtype(space, bool_dtype, bool_dtype) is bool_dtype
@@ -62,19 +65,19 @@
assert find_binop_result_dtype(space, bool_dtype, float64_dtype, promote_to_float=True) is float64_dtype
def test_unaryops(self, space):
- bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
- int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype)
- uint8_dtype = space.fromcache(interp_dtype.W_UInt8Dtype)
- int16_dtype = space.fromcache(interp_dtype.W_Int16Dtype)
- uint16_dtype = space.fromcache(interp_dtype.W_UInt16Dtype)
- int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype)
- uint32_dtype = space.fromcache(interp_dtype.W_UInt32Dtype)
- long_dtype = space.fromcache(interp_dtype.W_LongDtype)
- ulong_dtype = space.fromcache(interp_dtype.W_ULongDtype)
- int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
- uint64_dtype = space.fromcache(interp_dtype.W_UInt64Dtype)
- float32_dtype = space.fromcache(interp_dtype.W_Float32Dtype)
- float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+ bool_dtype = get_dtype_cache(space).w_booldtype
+ int8_dtype = get_dtype_cache(space).w_int8dtype
+ uint8_dtype = get_dtype_cache(space).w_uint8dtype
+ int16_dtype = get_dtype_cache(space).w_int16dtype
+ uint16_dtype = get_dtype_cache(space).w_uint16dtype
+ int32_dtype = get_dtype_cache(space).w_int32dtype
+ uint32_dtype = get_dtype_cache(space).w_uint32dtype
+ long_dtype = get_dtype_cache(space).w_longdtype
+ ulong_dtype = get_dtype_cache(space).w_ulongdtype
+ int64_dtype = get_dtype_cache(space).w_int64dtype
+ uint64_dtype = get_dtype_cache(space).w_uint64dtype
+ float32_dtype = get_dtype_cache(space).w_float32dtype
+ float64_dtype = get_dtype_cache(space).w_float64dtype
# Normal rules, everything returns itself
assert find_unaryop_result_dtype(space, bool_dtype) is bool_dtype
diff --git a/pypy/module/micronumpy/test/test_compile.py b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -1,6 +1,9 @@
+import py
-import py
-from pypy.module.micronumpy.compile import *
+from pypy.module.micronumpy.compile import (numpy_compile, Assignment,
+ ArrayConstant, FloatConstant, Operator, Variable, RangeConstant, Execute,
+ FunctionCall, FakeSpace)
+
class TestCompiler(object):
def compile(self, code):
@@ -106,7 +109,7 @@
c -> 3
"""
interp = self.run(code)
- assert interp.results[-1].value.val == 9
+ assert interp.results[-1].value == 9
def test_array_getitem(self):
code = """
@@ -115,7 +118,7 @@
a + b -> 3
"""
interp = self.run(code)
- assert interp.results[0].value.val == 3 + 6
+ assert interp.results[0].value == 3 + 6
def test_range_getitem(self):
code = """
@@ -123,7 +126,7 @@
r -> 3
"""
interp = self.run(code)
- assert interp.results[0].value.val == 6
+ assert interp.results[0].value == 6
def test_sum(self):
code = """
@@ -132,7 +135,7 @@
r
"""
interp = self.run(code)
- assert interp.results[0].value.val == 15
+ assert interp.results[0].value.value == 15
def test_array_write(self):
code = """
@@ -141,7 +144,7 @@
a -> 3
"""
interp = self.run(code)
- assert interp.results[0].value.val == 15
+ assert interp.results[0].value == 15
def test_min(self):
interp = self.run("""
@@ -150,7 +153,7 @@
b = a + a
min(b)
""")
- assert interp.results[0].value.val == -24
+ assert interp.results[0].value.value == -24
def test_max(self):
interp = self.run("""
@@ -159,7 +162,7 @@
b = a + a
max(b)
""")
- assert interp.results[0].value.val == 256
+ assert interp.results[0].value.value == 256
def test_slice(self):
interp = self.run("""
@@ -167,7 +170,7 @@
b = a -> :
b -> 3
""")
- assert interp.results[0].value.val == 4
+ assert interp.results[0].value == 4
def test_slice_step(self):
interp = self.run("""
@@ -175,14 +178,35 @@
b = a -> ::2
b -> 3
""")
- assert interp.results[0].value.val == 6
+ assert interp.results[0].value == 6
+
+ def test_setslice(self):
+ interp = self.run("""
+ a = |30|
+ b = |10|
+ b[1] = 5
+ a[::3] = b
+ a -> 3
+ """)
+ assert interp.results[0].value == 5
+
+
+ def test_slice2(self):
+ interp = self.run("""
+ a = |30|
+ s1 = a -> 0:20:2
+ s2 = a -> 0:30:3
+ b = s1 + s2
+ b -> 3
+ """)
+ assert interp.results[0].value == 15
def test_multidim_getitem(self):
interp = self.run("""
a = [[1,2]]
a -> 0 -> 1
""")
- assert interp.results[0].value.val == 2
+ assert interp.results[0].value == 2
def test_multidim_getitem_2(self):
interp = self.run("""
@@ -190,4 +214,24 @@
b = a + a
b -> 1 -> 1
""")
- assert interp.results[0].value.val == 8
+ assert interp.results[0].value == 8
+
+ def test_set_slice(self):
+ interp = self.run("""
+ a = |30|
+ b = |30|
+ b[:] = a + a
+ b -> 3
+ """)
+ assert interp.results[0].value == 6
+
+ def test_set_slice2(self):
+ interp = self.run("""
+ a = |30|
+ b = |10|
+ b[1] = 5.5
+ c = b + b
+ a[0:30:3] = c
+ a -> 3
+ """)
+ assert interp.results[0].value == 11
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -30,7 +30,7 @@
def test_repr_str(self):
from numpypy import dtype
- assert repr(dtype) == "<type 'numpy.dtype'>"
+ assert repr(dtype) == "<type 'numpypy.dtype'>"
d = dtype('?')
assert repr(d) == "dtype('bool')"
assert str(d) == "bool"
@@ -44,13 +44,13 @@
assert a[i] is True_
def test_copy_array_with_dtype(self):
- from numpypy import array, False_, True_
+ from numpypy import array, False_, True_, int64
a = array([0, 1, 2, 3], dtype=long)
# int on 64-bit, long in 32-bit
- assert isinstance(a[0], (int, long))
+ assert isinstance(a[0], int64)
b = a.copy()
- assert isinstance(b[0], (int, long))
+ assert isinstance(b[0], int64)
a = array([0, 1, 2, 3], dtype=bool)
assert a[0] is False_
@@ -72,17 +72,17 @@
assert a[i] is True_
def test_zeros_long(self):
- from numpypy import zeros
+ from numpypy import zeros, int64
a = zeros(10, dtype=long)
for i in range(10):
- assert isinstance(a[i], (int, long))
+ assert isinstance(a[i], int64)
assert a[1] == 0
def test_ones_long(self):
- from numpypy import ones
+ from numpypy import ones, int64
a = ones(10, dtype=long)
for i in range(10):
- assert isinstance(a[i], (int, long))
+ assert isinstance(a[i], int64)
assert a[1] == 1
def test_overflow(self):
@@ -165,3 +165,99 @@
# You can't subclass dtype
raises(TypeError, type, "Foo", (dtype,), {})
+
+class AppTestTypes(BaseNumpyAppTest):
+ def test_abstract_types(self):
+ import numpypy as numpy
+ raises(TypeError, numpy.generic, 0)
+ raises(TypeError, numpy.number, 0)
+ raises(TypeError, numpy.integer, 0)
+ exc = raises(TypeError, numpy.signedinteger, 0)
+ assert str(exc.value) == "cannot create 'numpypy.signedinteger' instances"
+
+ raises(TypeError, numpy.floating, 0)
+ raises(TypeError, numpy.inexact, 0)
+
+ def test_bool(self):
+ import numpypy as numpy
+
+ assert numpy.bool_.mro() == [numpy.bool_, numpy.generic, object]
+ assert numpy.bool_(3) is numpy.True_
+ assert numpy.bool_("") is numpy.False_
+ assert type(numpy.True_) is type(numpy.False_) is numpy.bool_
+
+ class X(numpy.bool_):
+ pass
+
+ assert type(X(True)) is numpy.bool_
+ assert X(True) is numpy.True_
+
+ def test_int8(self):
+ import numpypy as numpy
+
+ assert numpy.int8.mro() == [numpy.int8, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+ a = numpy.array([1, 2, 3], numpy.int8)
+ assert type(a[1]) is numpy.int8
+ assert numpy.dtype("int8").type is numpy.int8
+
+ x = numpy.int8(128)
+ assert x == -128
+ assert x != 128
+ assert type(x) is numpy.int8
+ assert repr(x) == "-128"
+
+ assert type(int(x)) is int
+ assert int(x) == -128
+
+ def test_int16(self):
+ import numpypy as numpy
+
+ x = numpy.int16(3)
+ assert x == 3
+
+ def test_int32(self):
+ import numpypy as numpy
+
+ x = numpy.int32(23)
+ assert x == 23
+
+ def test_int_(self):
+ import numpypy as numpy
+
+ assert numpy.int_ is numpy.dtype(int).type
+ assert numpy.int_.mro() == [numpy.int_, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+
+ def test_int64(self):
+ import sys
+ import numpypy as numpy
+
+ if sys.maxint == 2 ** 63 -1:
+ assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+ else:
+ assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+ assert numpy.dtype(numpy.int64).type is numpy.int64
+ assert numpy.int64(3) == 3
+
+ def test_float64(self):
+ import numpypy as numpy
+
+ assert numpy.float64.mro() == [numpy.float64, numpy.floating, numpy.inexact, numpy.number, numpy.generic, float, object]
+
+ a = numpy.array([1, 2, 3], numpy.float64)
+ assert type(a[1]) is numpy.float64
+ assert numpy.dtype(float).type is numpy.float64
+
+ assert numpy.float64(2.0) == 2.0
+
+ def test_subclass_type(self):
+ import numpypy as numpy
+
+ class X(numpy.float64):
+ def m(self):
+ return self + 2
+
+ b = X(10)
+ assert type(b) is X
+ assert b.m() == 12
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1,16 +1,19 @@
import py
from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
-from pypy.module.micronumpy.interp_numarray import NDimArray, shape_agreement
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, shape_agreement
from pypy.module.micronumpy import signature
from pypy.interpreter.error import OperationError
from pypy.conftest import gettestobjspace
+
class MockDtype(object):
signature = signature.BaseSignature()
+
def malloc(self, size):
return None
+
class TestNumArrayDirect(object):
def newslice(self, *args):
return self.space.newslice(*[self.space.wrap(arg) for arg in args])
@@ -25,18 +28,18 @@
return self.space.newtuple(args_w)
def test_strides_f(self):
- a = NDimArray(100, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(100, [10, 5, 3], MockDtype(), 'F')
assert a.strides == [1, 10, 50]
assert a.backstrides == [9, 40, 100]
def test_strides_c(self):
- a = NDimArray(100, [10, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(100, [10, 5, 3], MockDtype(), 'C')
assert a.strides == [15, 3, 1]
assert a.backstrides == [135, 12, 2]
def test_create_slice_f(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
s = a.create_slice(space, [(3, 0, 0, 1)])
assert s.start == 3
assert s.strides == [10, 50]
@@ -55,7 +58,7 @@
def test_create_slice_c(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
s = a.create_slice(space, [(3, 0, 0, 1)])
assert s.start == 45
assert s.strides == [3, 1]
@@ -75,7 +78,7 @@
def test_slice_of_slice_f(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
s = a.create_slice(space, [(5, 0, 0, 1)])
assert s.start == 5
s2 = s.create_slice(space, [(3, 0, 0, 1)])
@@ -93,7 +96,7 @@
def test_slice_of_slice_c(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
s = a.create_slice(space, [(5, 0, 0, 1)])
assert s.start == 15 * 5
s2 = s.create_slice(space, [(3, 0, 0, 1)])
@@ -111,7 +114,7 @@
def test_negative_step_f(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
s = a.create_slice(space, [(9, -1, -2, 5)])
assert s.start == 9
assert s.strides == [-2, 10, 50]
@@ -119,14 +122,14 @@
def test_negative_step_c(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
s = a.create_slice(space, [(9, -1, -2, 5)])
assert s.start == 135
assert s.strides == [-30, 3, 1]
assert s.backstrides == [-120, 12, 2]
def test_index_of_single_item_f(self):
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
r = a._index_of_single_item(self.space, self.newtuple(1, 2, 2))
assert r == 1 + 2 * 10 + 2 * 50
s = a.create_slice(self.space, [(0, 10, 1, 10), (2, 0, 0, 1)])
@@ -136,7 +139,7 @@
assert r == a._index_of_single_item(self.space, self.newtuple(1, 2, 1))
def test_index_of_single_item_c(self):
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
r = a._index_of_single_item(self.space, self.newtuple(1, 2, 2))
assert r == 1 * 3 * 5 + 2 * 3 + 2
s = a.create_slice(self.space, [(0, 10, 1, 10), (2, 0, 0, 1)])
@@ -150,10 +153,28 @@
assert shape_agreement(self.space, [1, 2, 3], [1, 2, 3]) == [1, 2, 3]
py.test.raises(OperationError, shape_agreement, self.space, [2], [3])
assert shape_agreement(self.space, [4, 4], []) == [4, 4]
- assert shape_agreement(self.space, [8, 1, 6, 1], [7, 1, 5]) == [8, 7, 6, 5]
- assert shape_agreement(self.space, [5, 2], [4, 3, 5, 2]) == [4, 3, 5, 2]
+ assert shape_agreement(self.space,
+ [8, 1, 6, 1], [7, 1, 5]) == [8, 7, 6, 5]
+ assert shape_agreement(self.space,
+ [5, 2], [4, 3, 5, 2]) == [4, 3, 5, 2]
+
class AppTestNumArray(BaseNumpyAppTest):
+ def test_ndarray(self):
+ from numpypy import ndarray, array, dtype
+
+ assert type(ndarray) is type
+ assert type(array) is not type
+ a = ndarray((2, 3))
+ assert a.shape == (2, 3)
+ assert a.dtype == dtype(float)
+
+ raises(TypeError, ndarray, [[1], [2], [3]])
+
+ a = ndarray(3, dtype=int)
+ assert a.shape == (3,)
+ assert a.dtype is dtype(int)
+
def test_type(self):
from numpypy import array
ar = array(range(5))
@@ -170,8 +191,7 @@
def test_size(self):
from numpypy import array
- # XXX fixed on multidim branch
- #assert array(3).size == 1
+ assert array(3).size == 1
a = array([1, 2, 3])
assert a.size == 3
assert (a + a).size == 3
@@ -204,13 +224,13 @@
a[3] = 22
assert b[3] == 3
+ a = array(1)
+ assert a.copy() == a
+
def test_iterator_init(self):
from numpypy import array
a = array(range(5))
assert a[3] == 3
- a = array(1)
- assert a[0] == 1
- assert a.shape == ()
def test_getitem(self):
from numpypy import array
@@ -258,7 +278,7 @@
assert a[1] == 0.
assert a[3] == 1.
b[::-1] = b
- assert b[0] == 1.
+ assert b[0] == 0.
assert b[1] == 0.
def test_setslice_of_slice_array(self):
@@ -296,9 +316,13 @@
assert a[3] == 0.
def test_scalar(self):
- from numpypy import array
+ from numpypy import array, dtype
a = array(3)
- assert a[0] == 3
+ #assert a[0] == 3
+ raises(IndexError, "a[0]")
+ assert a.size == 1
+ assert a.shape == ()
+ assert a.dtype is dtype(int)
def test_len(self):
from numpypy import array
@@ -350,11 +374,11 @@
assert r[i] == i + 3
def test_add_list(self):
- from numpypy import array
+ from numpypy import array, ndarray
a = array(range(5))
b = list(reversed(range(5)))
c = a + b
- assert isinstance(c, array)
+ assert isinstance(c, ndarray)
for i in range(5):
assert c[i] == 4
@@ -455,9 +479,11 @@
a = array(range(5), float)
b = a ** a
for i in range(5):
- print b[i], i ** i
assert b[i] == i ** i
+ a = array(range(5))
+ assert (a ** 2 == a * a).all()
+
def test_pow_other(self):
from numpypy import array
a = array(range(5), float)
@@ -681,12 +707,14 @@
assert c.any() == False
def test_dot(self):
- from numpypy import array
+ from numpypy import array, dot
a = array(range(5))
assert a.dot(a) == 30.0
a = array(range(5))
assert a.dot(range(5)) == 30
+ assert dot(range(5), range(5)) == 30
+ assert (dot(5, [1, 2, 3]) == [5, 10, 15]).all()
def test_dot_constant(self):
from numpypy import array
@@ -696,7 +724,7 @@
assert b[i] == 2.5 * a[i]
def test_dtype_guessing(self):
- from numpypy import array, dtype
+ from numpypy import array, dtype, float64, int8, bool_
assert array([True]).dtype is dtype(bool)
assert array([True, False]).dtype is dtype(bool)
@@ -706,6 +734,10 @@
assert array([1.2, True]).dtype is dtype(float)
assert array([1.2, 5]).dtype is dtype(float)
assert array([]).dtype is dtype(float)
+ assert array([float64(2)]).dtype is dtype(float)
+ assert array([int8(3)]).dtype is dtype("int8")
+ assert array([bool_(True)]).dtype is dtype(bool)
+ assert array([bool_(True), 3.0]).dtype is dtype(float)
def test_comparison(self):
import operator
@@ -737,6 +769,29 @@
assert bool(array([1]))
assert not bool(array([0]))
+ def test_slice_assignment(self):
+ from numpypy import array
+ a = array(range(5))
+ a[::-1] = a
+ assert (a == [0, 1, 2, 1, 0]).all()
+ # but we force intermediates
+ a = array(range(5))
+ a[::-1] = a + a
+ assert (a == [8, 6, 4, 2, 0]).all()
+
+ def test_debug_repr(self):
+ from numpypy import zeros, sin
+ a = zeros(1)
+ assert a.__debug_repr__() == 'Array'
+ assert (a + a).__debug_repr__() == 'Call2(add, Array, Array)'
+ assert (a[::2]).__debug_repr__() == 'Slice(Array)'
+ assert (a + 2).__debug_repr__() == 'Call2(add, Array, Scalar)'
+ assert (a + a.flat).__debug_repr__() == 'Call2(add, Array, FlatIter(Array))'
+ assert sin(a).__debug_repr__() == 'Call1(sin, Array)'
+ b = a + a
+ b[0] = 3
+ assert b.__debug_repr__() == 'Call2(add, forced=Array)'
+
class AppTestMultiDim(BaseNumpyAppTest):
def test_init(self):
import numpypy
@@ -829,7 +884,8 @@
def test_ufunc(self):
from numpypy import array
a = array([[1, 2], [3, 4], [5, 6]])
- assert ((a + a) == array([[1 + 1, 2 + 2], [3 + 3, 4 + 4], [5 + 5, 6 + 6]])).all()
+ assert ((a + a) == \
+ array([[1 + 1, 2 + 2], [3 + 3, 4 + 4], [5 + 5, 6 + 6]])).all()
def test_getitem_add(self):
from numpypy import array
@@ -844,7 +900,8 @@
def test_getitem_3(self):
from numpypy import array
- a = array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14]])
+ a = array([[1, 2], [3, 4], [5, 6], [7, 8],
+ [9, 10], [11, 12], [13, 14]])
b = a[::2]
print a
print b
@@ -877,11 +934,12 @@
b = array(((10, 11, 12), (20, 21, 22), (30, 31, 32)))
c = ((a + b) == [b, b, b])
assert c.all()
- a = array((((10,11,12), ), ((20, 21, 22), ), ((30,31,32), )))
+ a = array((((10, 11, 12), ), ((20, 21, 22), ), ((30, 31, 32), )))
assert(a.shape == (3, 1, 3))
d = zeros((3, 3))
c = ((a + d) == [b, b, b])
- c = ((a + d) == array([[[10., 11., 12.]]*3, [[20.,21.,22.]]*3, [[30.,31.,32.]]*3]))
+ c = ((a + d) == array([[[10., 11., 12.]] * 3,
+ [[20., 21., 22.]] * 3, [[30., 31., 32.]] * 3]))
assert c.all()
def test_broadcast_scalar(self):
@@ -906,14 +964,15 @@
from numpypy import array
a = array([[1, 2], [3, 4], [5, 6]])
assert a.argmax() == 5
- assert a[:2,].argmax() == 3
+ assert a[:2, ].argmax() == 3
def test_broadcast_wrong_shapes(self):
from numpypy import zeros
a = zeros((4, 3, 2))
b = zeros((4, 2))
exc = raises(ValueError, lambda: a + b)
- assert str(exc.value) == "operands could not be broadcast together with shapes (4,3,2) (4,2)"
+ assert str(exc.value) == "operands could not be broadcast" \
+ " together with shapes (4,3,2) (4,2)"
def test_reduce(self):
from numpypy import array
@@ -923,10 +982,55 @@
c = b + b
assert c.sum() == (6 + 8 + 10 + 12) * 2
-class AppTestSupport(object):
+ def test_transpose(self):
+ from numpypy import array
+ a = array(((range(3), range(3, 6)),
+ (range(6, 9), range(9, 12)),
+ (range(12, 15), range(15, 18)),
+ (range(18, 21), range(21, 24))))
+ assert a.shape == (4, 2, 3)
+ b = a.T
+ assert b.shape == (3, 2, 4)
+ assert(b[0, :, 0] == [0, 3]).all()
+ b[:, 0, 0] = 1000
+ assert(a[0, 0, :] == [1000, 1000, 1000]).all()
+ a = array(range(5))
+ b = a.T
+ assert(b == range(5)).all()
+ a = array((range(10), range(20, 30)))
+ b = a.T
+ assert(b[:, 0] == a[0, :]).all()
+
+ def test_flatiter(self):
+ from numpypy import array, flatiter
+ a = array([[10, 30], [40, 60]])
+ f_iter = a.flat
+ assert f_iter.next() == 10
+ assert f_iter.next() == 30
+ assert f_iter.next() == 40
+ assert f_iter.next() == 60
+ raises(StopIteration, "f_iter.next()")
+ raises(TypeError, "flatiter()")
+ s = 0
+ for k in a.flat:
+ s += k
+ assert s == 140
+
+ def test_flatiter_array_conv(self):
+ from numpypy import array, dot
+ a = array([1, 2, 3])
+ assert dot(a.flat, a.flat) == 14
+
+ def test_slice_copy(self):
+ from numpypy import zeros
+ a = zeros((10, 10))
+ b = a[0].copy()
+ assert (b == zeros(10)).all()
+
+class AppTestSupport(BaseNumpyAppTest):
def setup_class(cls):
import struct
- cls.space = gettestobjspace(usemodules=('micronumpy',))
+ BaseNumpyAppTest.setup_class.im_func(cls)
cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
def test_fromstring(self):
@@ -936,6 +1040,7 @@
assert a[i] == i + 1
raises(ValueError, fromstring, "abc")
+
class AppTestRepr(BaseNumpyAppTest):
def test_repr(self):
from numpypy import array, zeros
@@ -1008,7 +1113,9 @@
assert str(a) == "3"
a = zeros((400, 400), dtype=int)
- assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
+ assert str(a) == "[[0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]\n" \
+ " [0 0 0 ..., 0 0 0]\n ..., \n [0 0 0 ..., 0 0 0]\n" \
+ " [0 0 0 ..., 0 0 0]\n [0 0 0 ..., 0 0 0]]"
a = zeros((2, 2, 2))
r = str(a)
assert r == '[[[0.0 0.0]\n [0.0 0.0]]\n\n [[0.0 0.0]\n [0.0 0.0]]]'
@@ -1026,3 +1133,25 @@
assert str(b) == "[7 8 9]"
b = a[2:1, ]
assert str(b) == "[]"
+
+
+class AppTestRanges(BaseNumpyAppTest):
+ def test_arange(self):
+ from numpypy import arange, array, dtype
+ a = arange(3)
+ assert (a == [0, 1, 2]).all()
+ assert a.dtype is dtype(int)
+ a = arange(3.0)
+ assert (a == [0., 1., 2.]).all()
+ assert a.dtype is dtype(float)
+ a = arange(3, 7)
+ assert (a == [3, 4, 5, 6]).all()
+ assert a.dtype is dtype(int)
+ a = arange(3, 7, 2)
+ assert (a == [3, 5]).all()
+ a = arange(3, dtype=float)
+ assert (a == [0., 1., 2.]).all()
+ assert a.dtype is dtype(float)
+ a = arange(0, 0.8, 0.1)
+ assert len(a) == 8
+ assert arange(False, True, True).dtype is dtype(int)
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -8,7 +8,7 @@
assert isinstance(add, ufunc)
assert repr(add) == "<ufunc 'add'>"
- assert repr(ufunc) == "<type 'numpy.ufunc'>"
+ assert repr(ufunc) == "<type 'numpypy.ufunc'>"
def test_ufunc_attrs(self):
from numpypy import add, multiply, sin
@@ -37,36 +37,36 @@
assert minimum(2.0, 3.0) == 2.0
def test_sequence(self):
- from numpypy import array, negative, minimum
+ from numpypy import array, ndarray, negative, minimum
a = array(range(3))
b = [2.0, 1.0, 0.0]
c = 1.0
b_neg = negative(b)
- assert isinstance(b_neg, array)
+ assert isinstance(b_neg, ndarray)
for i in range(3):
assert b_neg[i] == -b[i]
min_a_b = minimum(a, b)
- assert isinstance(min_a_b, array)
+ assert isinstance(min_a_b, ndarray)
for i in range(3):
assert min_a_b[i] == min(a[i], b[i])
min_b_a = minimum(b, a)
- assert isinstance(min_b_a, array)
+ assert isinstance(min_b_a, ndarray)
for i in range(3):
assert min_b_a[i] == min(a[i], b[i])
min_a_c = minimum(a, c)
- assert isinstance(min_a_c, array)
+ assert isinstance(min_a_c, ndarray)
for i in range(3):
assert min_a_c[i] == min(a[i], c)
min_c_a = minimum(c, a)
- assert isinstance(min_c_a, array)
+ assert isinstance(min_c_a, ndarray)
for i in range(3):
assert min_c_a[i] == min(a[i], c)
min_b_c = minimum(b, c)
- assert isinstance(min_b_c, array)
+ assert isinstance(min_b_c, ndarray)
for i in range(3):
assert min_b_c[i] == min(b[i], c)
min_c_b = minimum(c, b)
- assert isinstance(min_c_b, array)
+ assert isinstance(min_c_b, ndarray)
for i in range(3):
assert min_c_b[i] == min(b[i], c)
@@ -111,6 +111,8 @@
for i in range(3):
assert c[i] == a[i] / b[i]
+ assert (divide(array([-10]), array([2])) == array([-5])).all()
+
def test_fabs(self):
from numpypy import array, fabs
from math import fabs as math_fabs
@@ -319,6 +321,17 @@
for v in [1.0, -1.0]:
assert arctanh(v) == math.copysign(float("inf"), v)
+ def test_sqrt(self):
+ import math
+ from numpypy import sqrt
+
+ nan, inf = float("nan"), float("inf")
+ data = [1, 2, 3, inf]
+ results = [math.sqrt(1), math.sqrt(2), math.sqrt(3), inf]
+ assert (sqrt(data) == results).all()
+ assert math.isnan(sqrt(-1))
+ assert math.isnan(sqrt(nan))
+
def test_reduce_errors(self):
from numpypy import sin, add
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -8,10 +8,11 @@
from pypy.jit.metainterp import pyjitpl
from pypy.jit.metainterp.test.support import LLJitMixin
from pypy.jit.metainterp.warmspot import reset_stats
-from pypy.module.micronumpy import interp_ufuncs, signature
+from pypy.module.micronumpy import interp_boxes, interp_ufuncs, signature
from pypy.module.micronumpy.compile import (numpy_compile, FakeSpace,
FloatObject, IntObject, BoolObject, Parser, InterpreterState)
-from pypy.module.micronumpy.interp_numarray import NDimArray, NDimSlice
+from pypy.module.micronumpy.interp_numarray import (W_NDimArray, NDimSlice,
+ BaseArray)
from pypy.rlib.nonconst import NonConstant
from pypy.rpython.annlowlevel import llstr, hlstr
@@ -47,16 +48,15 @@
def f(i):
interp = InterpreterState(codes[i])
interp.run(space)
- res = interp.results[-1]
- w_res = res.eval(res.start_iter()).wrap(interp.space)
- if isinstance(w_res, BoolObject):
- return float(w_res.boolval)
- elif isinstance(w_res, FloatObject):
- return w_res.floatval
- elif isinstance(w_res, IntObject):
- return w_res.intval
- else:
- return -42.
+ w_res = interp.results[-1]
+ if isinstance(w_res, BaseArray):
+ w_res = w_res.eval(w_res.start_iter())
+
+ if isinstance(w_res, interp_boxes.W_Float64Box):
+ return w_res.value
+ elif isinstance(w_res, interp_boxes.W_BoolBox):
+ return float(w_res.value)
+ raise TypeError(w_res)
if self.graph is None:
interp, graph = self.meta_interp(f, [i],
@@ -78,10 +78,9 @@
def test_add(self):
result = self.run("add")
- self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 19, 'guard_class': 11,
- 'int_add': 6, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
- 'guard_value': 1})
+ self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+ 'setinteriorfield_raw': 1, 'int_add': 3,
+ 'int_ge': 1, 'guard_false': 1, 'jump': 1})
assert result == 3 + 3
def define_float_add():
@@ -93,10 +92,9 @@
def test_floatadd(self):
result = self.run("float_add")
assert result == 3 + 3
- self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 17, 'guard_class': 11,
- 'int_add': 4, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
- 'getarrayitem_raw': 2, 'float_add': 2, 'guard_false': 2,
- 'guard_value': 1})
+ self.check_simple_loop({"getinteriorfield_raw": 1, "float_add": 1,
+ "setinteriorfield_raw": 1, "int_add": 2,
+ "int_ge": 1, "guard_false": 1, "jump": 1})
def define_sum():
return """
@@ -108,9 +106,9 @@
def test_sum(self):
result = self.run("sum")
assert result == 2 * sum(range(30))
- self.check_resops({'guard_class': 10, 'getfield_gc': 17, 'jump': 1,
- 'getarrayitem_raw': 4, 'guard_value': 2, 'int_add': 4,
- 'guard_isnull': 1, 'int_ge': 2, 'float_add': 4, 'guard_false': 2})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 2,
+ "int_add": 2, "int_ge": 1, "guard_false": 1,
+ "jump": 1})
def define_prod():
return """
@@ -125,11 +123,9 @@
for i in range(30):
expected *= i * 2
assert result == expected
- self.check_resops({'guard_class': 10, 'getfield_gc': 17, 'int_add': 4,
- 'float_mul': 2, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
- 'guard_value': 2})
-
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_mul": 1, "int_add": 2,
+ "int_ge": 1, "guard_false": 1, "jump": 1})
def test_max(self):
py.test.skip("broken, investigate")
@@ -140,9 +136,9 @@
max(b)
""")
assert result == 256
- self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
- "float_mul": 1, "int_add": 1,
- "int_lt": 1, "guard_true": 1, "jump": 1})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_mul": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1})
def test_min(self):
py.test.skip("broken, investigate")
@@ -153,10 +149,9 @@
min(b)
""")
assert result == -24
- self.check_resops({'guard_class': 10, 'getfield_gc': 15, 'guard_value': 1,
- 'int_add': 4, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
- 'float_ne': 2})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_mul": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1})
def define_any():
return """
@@ -169,10 +164,10 @@
def test_any(self):
result = self.run("any")
assert result == 1
- self.check_resops({'guard_class': 10, 'getfield_gc': 15, 'guard_value': 1,
- 'int_add': 4, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
- 'float_ne': 2})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_ne": 1, "int_add": 2,
+ "int_ge": 1, "jump": 1,
+ "guard_false": 2})
def define_already_forced():
return """
@@ -189,13 +184,14 @@
# This is the sum of the ops for both loops, however if you remove the
# optimization then you end up with 2 float_adds, so we can still be
# sure it was optimized correctly.
- self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35,
+ # XXX the comment above is wrong now. We need preferrably a way to
+ # count the two loops separately
+ self.check_resops({'setinteriorfield_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 41,
'guard_class': 22, 'int_add': 8, 'float_mul': 2,
'guard_isnull': 2, 'jump': 2, 'int_ge': 4,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+ 'getinteriorfield_raw': 4, 'float_add': 2, 'guard_false': 4,
'guard_value': 2})
-
def define_ufunc():
return """
a = |30|
@@ -207,11 +203,9 @@
def test_ufunc(self):
result = self.run("ufunc")
assert result == -6
- self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 24, 'guard_class': 14,
- 'int_add': 6, 'float_neg': 2, 'guard_isnull': 2, 'jump': 1,
- 'int_ge': 2, 'getarrayitem_raw': 4, 'float_add': 2,
- 'guard_false': 2, 'guard_value': 2})
-
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1, "float_neg": 1,
+ "setinteriorfield_raw": 1, "int_add": 3,
+ "int_ge": 1, "guard_false": 1, "jump": 1})
def define_specialization():
return """
@@ -249,10 +243,28 @@
def test_slice(self):
result = self.run("slice")
assert result == 18
- py.test.skip("Few remaining arraylen_gc left")
- self.check_loops({'int_mul': 2, 'getarrayitem_raw': 2, 'float_add': 1,
- 'setarrayitem_raw': 1, 'int_add': 3,
- 'int_lt': 1, 'guard_true': 1, 'jump': 1})
+ self.check_simple_loop({'getinteriorfield_raw': 2,
+ 'float_add': 1,
+ 'setinteriorfield_raw': 1,
+ 'int_add': 3,
+ 'int_ge': 1, 'guard_false': 1,
+ 'jump': 1})
+
+ def define_slice2():
+ return """
+ a = |30|
+ s1 = a -> :20:2
+ s2 = a -> :30:3
+ b = s1 + s2
+ b -> 3
+ """
+
+ def test_slice2(self):
+ result = self.run("slice2")
+ assert result == 15
+ self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+ 'setinteriorfield_raw': 1, 'int_add': 3,
+ 'int_ge': 1, 'guard_false': 1, 'jump': 1})
def define_multidim():
return """
@@ -264,12 +276,11 @@
def test_multidim(self):
result = self.run('multidim')
assert result == 8
- self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 19, 'guard_class': 11,
- 'int_add': 6, 'guard_isnull': 1, 'jump': 1, 'int_ge': 2,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
- 'guard_value': 1})
# int_add might be 1 here if we try slightly harder with
# reusing indexes or some optimization
+ self.check_simple_loop({'float_add': 1, 'getinteriorfield_raw': 2,
+ 'guard_false': 1, 'int_add': 3, 'int_ge': 1,
+ 'jump': 1, 'setinteriorfield_raw': 1})
def define_multidim_slice():
return """
@@ -285,7 +296,7 @@
py.test.skip("improve")
# XXX the bridge here is scary. Hopefully jit-targets will fix that,
# otherwise it looks kind of good
- self.check_loops({})
+ self.check_simple_loop({})
def define_broadcast():
return """
@@ -299,58 +310,34 @@
result = self.run("broadcast")
assert result == 10
py.test.skip("improve")
- self.check_loops({})
+ self.check_simple_loop({})
+
+ def define_setslice():
+ return """
+ a = |30|
+ b = |10|
+ b[1] = 5.5
+ c = b + b
+ a[0:30:3] = c
+ a -> 3
+ """
+
+ def test_setslice(self):
+ result = self.run("setslice")
+ assert result == 11.0
+ self.check_loop_count(1)
+ self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add' : 1,
+ 'setinteriorfield_raw': 1, 'int_add': 3,
+ 'int_eq': 1, 'guard_false': 1, 'jump': 1})
class TestNumpyOld(LLJitMixin):
def setup_class(cls):
py.test.skip("old")
from pypy.module.micronumpy.compile import FakeSpace
- from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+ from pypy.module.micronumpy.interp_dtype import get_dtype_cache
cls.space = FakeSpace()
- cls.float64_dtype = cls.space.fromcache(W_Float64Dtype)
-
- def test_slice2(self):
- def f(i):
- step1 = 2
- step2 = 3
- ar = NDimArray(step2*i, dtype=self.float64_dtype)
- new_sig = signature.Signature.find_sig([
- NDimSlice.signature, ar.signature
- ])
- s1 = NDimSlice(0, step1*i, step1, i, ar, new_sig)
- new_sig = signature.Signature.find_sig([
- NDimSlice.signature, s1.signature
- ])
- s2 = NDimSlice(0, step2*i, step2, i, ar, new_sig)
- v = interp_ufuncs.get(self.space).add.call(self.space, [s1, s2])
- return v.get_concrete().eval(3).val
-
- result = self.meta_interp(f, [5], listops=True, backendopt=True)
- self.check_loops({'int_mul': 2, 'getarrayitem_raw': 2, 'float_add': 1,
- 'setarrayitem_raw': 1, 'int_add': 1,
- 'int_lt': 1, 'guard_true': 1, 'jump': 1})
- assert result == f(5)
-
- def test_setslice(self):
- space = self.space
- float64_dtype = self.float64_dtype
-
- def f(i):
- step = NonConstant(3)
- ar = NDimArray(step*i, dtype=float64_dtype)
- ar2 = NDimArray(i, dtype=float64_dtype)
- ar2.get_concrete().setitem(1, float64_dtype.box(5.5))
- arg = ar2.descr_add(space, ar2)
- ar.setslice(space, 0, step*i, step, i, arg)
- return ar.get_concrete().eval(3).val
-
- result = self.meta_interp(f, [5], listops=True, backendopt=True)
- self.check_loops({'getarrayitem_raw': 2,
- 'float_add' : 1,
- 'setarrayitem_raw': 1, 'int_add': 2,
- 'int_lt': 1, 'guard_true': 1, 'jump': 1})
- assert result == 11.0
+ cls.float64_dtype = get_dtype_cache(cls.space).w_float64dtype
def test_int32_sum(self):
py.test.skip("pypy/jit/backend/llimpl.py needs to be changed to "
@@ -365,7 +352,7 @@
dtype = float64_dtype
else:
dtype = int32_dtype
- ar = NDimArray(n, [n], dtype=dtype)
+ ar = W_NDimArray(n, [n], dtype=dtype)
i = 0
while i < n:
ar.get_concrete().setitem(i, int32_dtype.box(7))
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/types.py
@@ -0,0 +1,389 @@
+import functools
+import math
+
+from pypy.module.micronumpy import interp_boxes
+from pypy.objspace.std.floatobject import float2string
+from pypy.rlib import rfloat, libffi, clibffi
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT, widen
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+def simple_unary_op(func):
+ specialize.argtype(1)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v):
+ return self.box(
+ func(
+ self,
+ self.for_computation(self.unbox(v))
+ )
+ )
+ return dispatcher
+
+def simple_binary_op(func):
+ specialize.argtype(1, 2)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v1, v2):
+ return self.box(
+ func(
+ self,
+ self.for_computation(self.unbox(v1)),
+ self.for_computation(self.unbox(v2)),
+ )
+ )
+ return dispatcher
+
+def raw_binary_op(func):
+ specialize.argtype(1, 2)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v1, v2):
+ return func(self,
+ self.for_computation(self.unbox(v1)),
+ self.for_computation(self.unbox(v2))
+ )
+ return dispatcher
+
+class BaseType(object):
+ def _unimplemented_ufunc(self, *args):
+ raise NotImplementedError
+ # add = sub = mul = div = mod = pow = eq = ne = lt = le = gt = ge = max = \
+ # min = copysign = pos = neg = abs = sign = reciprocal = fabs = floor = \
+ # exp = sin = cos = tan = arcsin = arccos = arctan = arcsinh = \
+ # arctanh = _unimplemented_ufunc
+
+class Primitive(object):
+ _mixin_ = True
+ def get_element_size(self):
+ return rffi.sizeof(self.T)
+
+ @specialize.argtype(1)
+ def box(self, value):
+ return self.BoxType(rffi.cast(self.T, value))
+
+ def unbox(self, box):
+ assert isinstance(box, self.BoxType)
+ return box.value
+
+ def coerce(self, space, w_item):
+ if isinstance(w_item, self.BoxType):
+ return w_item
+ return self.coerce_subtype(space, space.gettypefor(self.BoxType), w_item)
+
+ def coerce_subtype(self, space, w_subtype, w_item):
+ # XXX: ugly
+ w_obj = space.allocate_instance(self.BoxType, w_subtype)
+ assert isinstance(w_obj, self.BoxType)
+ w_obj.__init__(self._coerce(space, w_item).value)
+ return w_obj
+
+ def _coerce(self, space, w_item):
+ raise NotImplementedError
+
+ def read(self, storage, width, i, offset):
+ return self.box(libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+ width, storage, i, offset
+ ))
+
+ def store(self, storage, width, i, offset, box):
+ value = self.unbox(box)
+ libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+ width, storage, i, offset, value
+ )
+
+ def fill(self, storage, width, box, start, stop, offset):
+ value = self.unbox(box)
+ for i in xrange(start, stop):
+ libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+ width, storage, i, offset, value
+ )
+
+ @simple_binary_op
+ def add(self, v1, v2):
+ return v1 + v2
+
+ @simple_binary_op
+ def sub(self, v1, v2):
+ return v1 - v2
+
+ @simple_binary_op
+ def mul(self, v1, v2):
+ return v1 * v2
+
+ @simple_unary_op
+ def pos(self, v):
+ return +v
+
+ @simple_unary_op
+ def neg(self, v):
+ return -v
+
+ @simple_unary_op
+ def abs(self, v):
+ return abs(v)
+
+ @raw_binary_op
+ def eq(self, v1, v2):
+ return v1 == v2
+
+ @raw_binary_op
+ def ne(self, v1, v2):
+ return v1 != v2
+
+ @raw_binary_op
+ def lt(self, v1, v2):
+ return v1 < v2
+
+ @raw_binary_op
+ def le(self, v1, v2):
+ return v1 <= v2
+
+ @raw_binary_op
+ def gt(self, v1, v2):
+ return v1 > v2
+
+ @raw_binary_op
+ def ge(self, v1, v2):
+ return v1 >= v2
+
+ def bool(self, v):
+ return bool(self.for_computation(self.unbox(v)))
+
+ @simple_binary_op
+ def max(self, v1, v2):
+ return max(v1, v2)
+
+ @simple_binary_op
+ def min(self, v1, v2):
+ return min(v1, v2)
+
+class Bool(BaseType, Primitive):
+ T = lltype.Bool
+ BoxType = interp_boxes.W_BoolBox
+
+ True = BoxType(True)
+ False = BoxType(False)
+
+ @specialize.argtype(1)
+ def box(self, value):
+ box = Primitive.box(self, value)
+ if box.value:
+ return self.True
+ else:
+ return self.False
+
+ def coerce_subtype(self, space, w_subtype, w_item):
+ # Doesn't return subclasses so it can return the constants.
+ return self._coerce(space, w_item)
+
+ def _coerce(self, space, w_item):
+ return self.box(space.is_true(w_item))
+
+ def str_format(self, box):
+ value = self.unbox(box)
+ return "True" if value else "False"
+
+ def for_computation(self, v):
+ return int(v)
+
+class Integer(Primitive):
+ _mixin_ = True
+
+ def _coerce(self, space, w_item):
+ return self.box(space.int_w(space.int(w_item)))
+
+ def str_format(self, box):
+ value = self.unbox(box)
+ return str(self.for_computation(value))
+
+ def for_computation(self, v):
+ return widen(v)
+
+ @simple_binary_op
+ def div(self, v1, v2):
+ if v2 == 0:
+ return 0
+ return v1 / v2
+
+ @simple_binary_op
+ def mod(self, v1, v2):
+ return v1 % v2
+
+ @simple_binary_op
+ def pow(self, v1, v2):
+ res = 1
+ while v2 > 0:
+ if v2 & 1:
+ res *= v1
+ v2 >>= 1
+ if v2 == 0:
+ break
+ v1 *= v1
+ return res
+
+ @simple_unary_op
+ def sign(self, v):
+ if v > 0:
+ return 1
+ elif v < 0:
+ return -1
+ else:
+ assert v == 0
+ return 0
+
+class Int8(BaseType, Integer):
+ T = rffi.SIGNEDCHAR
+ BoxType = interp_boxes.W_Int8Box
+
+class UInt8(BaseType, Integer):
+ T = rffi.UCHAR
+ BoxType = interp_boxes.W_UInt8Box
+
+class Int16(BaseType, Integer):
+ T = rffi.SHORT
+ BoxType = interp_boxes.W_Int16Box
+
+class UInt16(BaseType, Integer):
+ T = rffi.USHORT
+ BoxType = interp_boxes.W_UInt16Box
+
+class Int32(BaseType, Integer):
+ T = rffi.INT
+ BoxType = interp_boxes.W_Int32Box
+
+class UInt32(BaseType, Integer):
+ T = rffi.UINT
+ BoxType = interp_boxes.W_UInt32Box
+
+class Long(BaseType, Integer):
+ T = rffi.LONG
+ BoxType = interp_boxes.W_LongBox
+
+class ULong(BaseType, Integer):
+ T = rffi.ULONG
+ BoxType = interp_boxes.W_ULongBox
+
+class Int64(BaseType, Integer):
+ T = rffi.LONGLONG
+ BoxType = interp_boxes.W_Int64Box
+
+class UInt64(BaseType, Integer):
+ T = rffi.ULONGLONG
+ BoxType = interp_boxes.W_UInt64Box
+
+class Float(Primitive):
+ _mixin_ = True
+
+ def _coerce(self, space, w_item):
+ return self.box(space.float_w(space.float(w_item)))
+
+ def str_format(self, box):
+ value = self.unbox(box)
+ return float2string(self.for_computation(value), "g", rfloat.DTSF_STR_PRECISION)
+
+ def for_computation(self, v):
+ return float(v)
+
+ @simple_binary_op
+ def div(self, v1, v2):
+ try:
+ return v1 / v2
+ except ZeroDivisionError:
+ if v1 == v2 == 0.0:
+ return rfloat.NAN
+ return rfloat.copysign(rfloat.INFINITY, v1 * v2)
+
+ @simple_binary_op
+ def mod(self, v1, v2):
+ return math.fmod(v1, v2)
+
+ @simple_binary_op
+ def pow(self, v1, v2):
+ return math.pow(v1, v2)
+
+ @simple_binary_op
+ def copysign(self, v1, v2):
+ return math.copysign(v1, v2)
+
+ @simple_unary_op
+ def sign(self, v):
+ if v == 0.0:
+ return 0.0
+ return rfloat.copysign(1.0, v)
+
+ @simple_unary_op
+ def fabs(self, v):
+ return math.fabs(v)
+
+ @simple_unary_op
+ def reciprocal(self, v):
+ if v == 0.0:
+ return rfloat.copysign(rfloat.INFINITY, v)
+ return 1.0 / v
+
+ @simple_unary_op
+ def floor(self, v):
+ return math.floor(v)
+
+ @simple_unary_op
+ def exp(self, v):
+ try:
+ return math.exp(v)
+ except OverflowError:
+ return rfloat.INFINITY
+
+ @simple_unary_op
+ def sin(self, v):
+ return math.sin(v)
+
+ @simple_unary_op
+ def cos(self, v):
+ return math.cos(v)
+
+ @simple_unary_op
+ def tan(self, v):
+ return math.tan(v)
+
+ @simple_unary_op
+ def arcsin(self, v):
+ if not -1.0 <= v <= 1.0:
+ return rfloat.NAN
+ return math.asin(v)
+
+ @simple_unary_op
+ def arccos(self, v):
+ if not -1.0 <= v <= 1.0:
+ return rfloat.NAN
+ return math.acos(v)
+
+ @simple_unary_op
+ def arctan(self, v):
+ return math.atan(v)
+
+ @simple_unary_op
+ def arcsinh(self, v):
+ return math.asinh(v)
+
+ @simple_unary_op
+ def arctanh(self, v):
+ if v == 1.0 or v == -1.0:
+ return math.copysign(rfloat.INFINITY, v)
+ if not -1.0 < v < 1.0:
+ return rfloat.NAN
+ return math.atanh(v)
+
+ @simple_unary_op
+ def sqrt(self, v):
+ try:
+ return math.sqrt(v)
+ except ValueError:
+ return rfloat.NAN
+
+
+class Float32(BaseType, Float):
+ T = rffi.FLOAT
+ BoxType = interp_boxes.W_Float32Box
+
+class Float64(BaseType, Float):
+ T = rffi.DOUBLE
+ BoxType = interp_boxes.W_Float64Box
\ No newline at end of file
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -3,7 +3,7 @@
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
from pypy.rlib import rmmap
-from pypy.rlib.rmmap import RValueError, RTypeError, ROverflowError
+from pypy.rlib.rmmap import RValueError, RTypeError
class W_MMap(Wrappable):
@@ -212,8 +212,6 @@
raise OperationError(space.w_ValueError, space.wrap(e.message))
except RTypeError, e:
raise OperationError(space.w_TypeError, space.wrap(e.message))
- except ROverflowError, e:
- raise OperationError(space.w_OverflowError, space.wrap(e.message))
return space.wrap(self)
elif rmmap._MS_WINDOWS:
@@ -233,8 +231,6 @@
raise OperationError(space.w_ValueError, space.wrap(e.message))
except RTypeError, e:
raise OperationError(space.w_TypeError, space.wrap(e.message))
- except ROverflowError, e:
- raise OperationError(space.w_OverflowError, space.wrap(e.message))
return space.wrap(self)
W_MMap.typedef = TypeDef("mmap",
diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -3,7 +3,7 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.gateway import unwrap_spec
from pypy.rpython.lltypesystem import lltype
-from pypy.rlib.rarithmetic import ovfcheck_float_to_int
+from pypy.rlib.rarithmetic import ovfcheck_float_to_int, intmask
from pypy.rlib import rposix
from pypy.translator.tool.cbuild import ExternalCompilationInfo
import os
@@ -585,7 +585,7 @@
# More likely, the format yields an empty result,
# e.g. an empty format, or %Z when the timezone
# is unknown.
- result = rffi.charp2strn(outbuf, buflen)
+ result = rffi.charp2strn(outbuf, intmask(buflen))
return space.wrap(result)
finally:
lltype.free(outbuf, flavor='raw')
diff --git a/pypy/objspace/flow/model.py b/pypy/objspace/flow/model.py
--- a/pypy/objspace/flow/model.py
+++ b/pypy/objspace/flow/model.py
@@ -38,7 +38,6 @@
def __init__(self, name, startblock, return_var=None):
self.name = name # function name (possibly mangled already)
self.startblock = startblock
- self.startblock.isstartblock = True
# build default returnblock
self.returnblock = Block([return_var or Variable()])
self.returnblock.operations = ()
@@ -171,11 +170,10 @@
class Block(object):
- __slots__ = """isstartblock inputargs operations exitswitch
+ __slots__ = """inputargs operations exitswitch
exits blockcolor""".split()
def __init__(self, inputargs):
- self.isstartblock = False
self.inputargs = list(inputargs) # mixed list of variable/const XXX
self.operations = [] # list of SpaceOperation(s)
self.exitswitch = None # a variable or
@@ -452,7 +450,6 @@
newblock.closeblock(*newlinks)
newstartblock = blockmap[graph.startblock]
- newstartblock.isstartblock = True
newgraph = FunctionGraph(graph.name, newstartblock)
newgraph.returnblock = blockmap[graph.returnblock]
newgraph.exceptblock = blockmap[graph.exceptblock]
@@ -490,7 +487,6 @@
for block in graph.iterblocks():
- assert bool(block.isstartblock) == (block is graph.startblock)
assert type(block.exits) is tuple, (
"block.exits is a %s (closeblock() or recloseblock() missing?)"
% (type(block.exits).__name__,))
diff --git a/pypy/objspace/flow/test/test_checkgraph.py b/pypy/objspace/flow/test/test_checkgraph.py
--- a/pypy/objspace/flow/test/test_checkgraph.py
+++ b/pypy/objspace/flow/test/test_checkgraph.py
@@ -13,20 +13,6 @@
py.test.raises(AssertionError, checkgraph, g)
-def test_nostartblock():
- g = FunctionGraph("g", Block([]))
- g.startblock.closeblock(Link([Constant(1)], g.returnblock))
- g.startblock.isstartblock = False
- py.test.raises(AssertionError, checkgraph, g)
-
-def test_twostartblocks():
- g = FunctionGraph("g", Block([]))
- b = Block([])
- b.isstartblock = True
- g.startblock.closeblock(Link([], b))
- b.closeblock(Link([Constant(1)], g.returnblock))
- py.test.raises(AssertionError, checkgraph, g)
-
def test_exitlessblocknotexitblock():
g = FunctionGraph("g", Block([]))
py.test.raises(AssertionError, checkgraph, g)
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -50,6 +50,13 @@
else:
return space.fromcache(StringListStrategy)
+ # check for floats
+ for w_obj in list_w:
+ if not is_W_FloatObject(w_obj):
+ break
+ else:
+ return space.fromcache(FloatListStrategy)
+
return space.fromcache(ObjectListStrategy)
def is_W_IntObject(w_object):
@@ -60,7 +67,9 @@
from pypy.objspace.std.stringobject import W_StringObject
return type(w_object) is W_StringObject
-
+def is_W_FloatObject(w_object):
+ from pypy.objspace.std.floatobject import W_FloatObject
+ return type(w_object) is W_FloatObject
class W_ListObject(W_AbstractListObject):
from pypy.objspace.std.listtype import list_typedef as typedef
@@ -317,6 +326,8 @@
to the added item.
W_Lists do not switch back to EmptyListStrategy when becoming empty again."""
+ _applevel_repr = "empty"
+
def __init__(self, space):
ListStrategy.__init__(self, space)
# cache an empty list that is used whenever getitems is called (i.e. sorting)
@@ -364,6 +375,8 @@
strategy = self.space.fromcache(IntegerListStrategy)
elif is_W_StringObject(w_item):
strategy = self.space.fromcache(StringListStrategy)
+ elif is_W_FloatObject(w_item):
+ strategy = self.space.fromcache(FloatListStrategy)
else:
strategy = self.space.fromcache(ObjectListStrategy)
@@ -415,6 +428,8 @@
On any operation destroying the range (inserting, appending non-ints)
the strategy is switched to IntegerListStrategy."""
+ _applevel_repr = "range"
+
def switch_to_integer_strategy(self, w_list):
items = self._getitems_range(w_list, False)
strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
@@ -853,6 +868,7 @@
class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
_none_value = None
+ _applevel_repr = "object"
def unwrap(self, w_obj):
return w_obj
@@ -881,6 +897,7 @@
class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
_none_value = 0
+ _applevel_repr = "int"
def wrap(self, intval):
return self.space.wrap(intval)
@@ -905,8 +922,36 @@
if reverse:
l.reverse()
+class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+ _none_value = 0.0
+ _applevel_repr = "float"
+
+ def wrap(self, floatval):
+ return self.space.wrap(floatval)
+
+ def unwrap(self, w_float):
+ return self.space.float_w(w_float)
+
+ erase, unerase = rerased.new_erasing_pair("float")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def is_correct_type(self, w_obj):
+ return is_W_FloatObject(w_obj)
+
+ def list_is_correct_type(self, w_list):
+ return w_list.strategy is self.space.fromcache(FloatListStrategy)
+
+ def sort(self, w_list, reverse):
+ l = self.unerase(w_list.lstorage)
+ sorter = FloatSort(l, len(l))
+ sorter.sort()
+ if reverse:
+ l.reverse()
+
class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
_none_value = None
+ _applevel_repr = "str"
def wrap(self, stringval):
return self.space.wrap(stringval)
@@ -934,6 +979,7 @@
def getitems_str(self, w_list):
return self.unerase(w_list.lstorage)
+
# _______________________________________________________
init_signature = Signature(['sequence'], None, None)
@@ -1282,6 +1328,7 @@
TimSort = make_timsort_class()
IntBaseTimSort = make_timsort_class()
+FloatBaseTimSort = make_timsort_class()
StringBaseTimSort = make_timsort_class()
class KeyContainer(baseobjspace.W_Root):
@@ -1302,6 +1349,10 @@
def lt(self, a, b):
return a < b
+class FloatSort(FloatBaseTimSort):
+ def lt(self, a, b):
+ return a < b
+
class StringSort(StringBaseTimSort):
def lt(self, a, b):
return a < b
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -453,12 +453,12 @@
multi = r_uint(1822399083) + r_uint(1822399083) + 1
if w_set.hash != 0:
return space.wrap(w_set.hash)
- hash = 1927868237
- hash *= (len(w_set.setdata) + 1)
+ hash = r_uint(1927868237)
+ hash *= r_uint(len(w_set.setdata) + 1)
for w_item in w_set.setdata:
h = space.hash_w(w_item)
- value = ((h ^ (h << 16) ^ 89869747) * multi)
- hash = intmask(hash ^ value)
+ value = (r_uint(h ^ (h << 16) ^ 89869747) * multi)
+ hash = hash ^ value
hash = hash * 69069 + 907133923
if hash == 0:
hash = 590923713
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -470,11 +470,17 @@
l.extend(iter([1, 2, 3, 4]))
assert l is l0
assert l == [1, 1, 2, 3, 4]
+
l = l0 = ['a']
l.extend(iter(['b', 'c', 'd']))
assert l == ['a', 'b', 'c', 'd']
assert l is l0
+ l = l0 = [1.2]
+ l.extend(iter([2.3, 3.4, 4.5]))
+ assert l == [1.2, 2.3, 3.4, 4.5]
+ assert l is l0
+
def test_sort(self):
l = l0 = [1, 5, 3, 0]
l.sort()
@@ -493,6 +499,10 @@
l.sort(reverse=True)
assert l == ["d", "c", "b", "a"]
+ l = [3.3, 2.2, 4.4, 1.1, 3.1, 5.5]
+ l.sort()
+ assert l == [1.1, 2.2, 3.1, 3.3, 4.4, 5.5]
+
def test_sort_cmp(self):
def lencmp(a,b): return cmp(len(a), len(b))
l = [ 'a', 'fiver', 'tre', '' ]
@@ -546,11 +556,19 @@
assert l[-2] == 6
raises(IndexError, "l[len(l)]")
raises(IndexError, "l[-len(l)-1]")
+
l = ['a', 'b', 'c']
assert l[0] == 'a'
assert l[-1] == 'c'
assert l[-2] == 'b'
raises(IndexError, "l[len(l)]")
+
+ l = [1.1, 2.2, 3.3]
+ assert l[0] == 1.1
+ assert l[-1] == 3.3
+ assert l[-2] == 2.2
+ raises(IndexError, "l[len(l)]")
+
l = []
raises(IndexError, "l[1]")
@@ -588,6 +606,16 @@
assert l is l0
raises(IndexError, "del l[0]")
+ l = l0 = [1.1, 2.2, 3.3]
+ del l[0]
+ assert l == [2.2, 3.3]
+ del l[-1]
+ assert l == [2.2]
+ del l[-1]
+ assert l == []
+ assert l is l0
+ raises(IndexError, "del l[0]")
+
l = range(10)
del l[5]
assert l == [0, 1, 2, 3, 4, 6, 7, 8, 9]
@@ -627,9 +655,15 @@
del l[:]
assert l is l0
assert l == []
+
l = ['a', 'b']
del l[:]
assert l == []
+
+ l = [1.1, 2.2]
+ del l[:]
+ assert l == []
+
l = range(5)
del l[:]
assert l == []
@@ -640,6 +674,11 @@
assert l is l0
assert l == [1,2,3,4,5]
+ l = l0 = [1.1,2.2,3.3]
+ l += [4.4,5.5]
+ assert l is l0
+ assert l == [1.1,2.2,3.3,4.4,5.5]
+
l = l0 = ['a', 'b', 'c']
l1 = l[:]
l += ['d']
@@ -697,6 +736,11 @@
l *= -5
assert l == []
+ l = l0 = [1.1, 2.2]
+ l *= 2
+ assert l is l0
+ assert l == [1.1, 2.2, 1.1, 2.2]
+
l = range(2)
l *= 2
assert l == [0, 1, 0, 1]
@@ -731,6 +775,10 @@
assert c.index(0) == 0
raises(ValueError, c.index, 3)
+ c = [0.0, 2.2, 4.4]
+ assert c.index(0) == 0.0
+ raises(ValueError, c.index, 3)
+
def test_index_cpython_bug(self):
if self.on_cpython:
skip("cpython has a bug here")
@@ -779,6 +827,10 @@
l[::3] = ('a', 'b')
assert l == ['a', 1, 2, 'b', 4, 5]
+ l = [0.0, 1.1, 2.2, 3.3, 4.4, 5.5]
+ l[::3] = ('a', 'b')
+ assert l == ['a', 1.1, 2.2, 'b', 4.4, 5.5]
+
def test_setslice_with_self(self):
l = [1,2,3,4]
l[:] = l
@@ -835,6 +887,10 @@
l.append("a")
assert l == [1,2,3,"a"]
+ l = [1.1, 2.2, 3.3]
+ l.append(4.4)
+ assert l == [1.1, 2.2, 3.3, 4.4]
+
def test_count(self):
c = list('hello')
assert c.count('l') == 2
@@ -875,6 +931,10 @@
l.pop()
assert l == range(9)
+ l = [1.1, 2.2, 3.3]
+ l.pop()
+ assert l == [1.1, 2.2]
+
l = []
raises(IndexError, l.pop, 0)
@@ -897,16 +957,19 @@
l2 = ["1", "2", "3", "4"]
l3 = range(5)
l4 = [1, 2, 3, "4"]
+ l5 = [1.1, 2.2, 3.3, 4.4]
raises(IndexError, l1.pop, -5)
raises(IndexError, l2.pop, -5)
raises(IndexError, l3.pop, -6)
raises(IndexError, l4.pop, -5)
+ raises(IndexError, l5.pop, -5)
assert l1.pop(-2) == 3
assert l2.pop(-2) == "3"
assert l3.pop(-2) == 3
assert l4.pop(-2) == 3
+ assert l5.pop(-2) == 3.3
def test_remove(self):
c = list('hello world')
@@ -925,6 +988,13 @@
l = [0, 3, 5]
raises(ValueError, c.remove, 2)
+ l = [0.0, 1.1, 2.2, 3.3, 4.4]
+ l.remove(2.2)
+ assert l == [0.0, 1.1, 3.3, 4.4]
+ l = [0.0, 3.3, 5.5]
+ raises(ValueError, c.remove, 2)
+ raises(ValueError, c.remove, 2.2)
+
def test_reverse(self):
c = list('hello world')
c.reverse()
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -1,4 +1,4 @@
-from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, StringListStrategy, RangeListStrategy, make_range_list
+from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, FloatListStrategy, StringListStrategy, RangeListStrategy, make_range_list
from pypy.objspace.std import listobject
from pypy.objspace.std.test.test_listobject import TestW_ListObject
@@ -15,7 +15,7 @@
def test_empty_to_any(self):
l = W_ListObject(self.space, [])
assert isinstance(l.strategy, EmptyListStrategy)
- l.append(self.space.wrap(1.))
+ l.append(self.space.wrap((1,3)))
assert isinstance(l.strategy, ObjectListStrategy)
l = W_ListObject(self.space, [])
@@ -28,6 +28,11 @@
l.append(self.space.wrap('a'))
assert isinstance(l.strategy, StringListStrategy)
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.append(self.space.wrap(1.2))
+ assert isinstance(l.strategy, FloatListStrategy)
+
def test_int_to_any(self):
l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
assert isinstance(l.strategy, IntegerListStrategy)
@@ -44,6 +49,14 @@
l.append(self.space.wrap(3))
assert isinstance(l.strategy, ObjectListStrategy)
+ def test_float_to_any(self):
+ l = W_ListObject(self.space, [self.space.wrap(1.1),self.space.wrap(2.2),self.space.wrap(3.3)])
+ assert isinstance(l.strategy, FloatListStrategy)
+ l.append(self.space.wrap(4.4))
+ assert isinstance(l.strategy, FloatListStrategy)
+ l.append(self.space.wrap("a"))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
def test_setitem(self):
# This should work if test_listobject.py passes
l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
@@ -65,6 +78,12 @@
l.setitem(0, self.space.wrap(2))
assert isinstance(l.strategy, ObjectListStrategy)
+ # FloatStrategy to ObjectStrategy
+ l = W_ListObject(self.space, [self.space.wrap(1.2),self.space.wrap(2.3),self.space.wrap(3.4)])
+ assert isinstance(l.strategy, FloatListStrategy)
+ l.setitem(0, self.space.wrap("a"))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
def test_insert(self):
# no change
l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
@@ -84,6 +103,12 @@
l.insert(3, self.space.wrap('d'))
assert isinstance(l.strategy, ObjectListStrategy)
+ # FloatStrategy
+ l = W_ListObject(self.space, [self.space.wrap(1.1),self.space.wrap(2.2),self.space.wrap(3.3)])
+ assert isinstance(l.strategy, FloatListStrategy)
+ l.insert(3, self.space.wrap('d'))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
# EmptyStrategy
l = W_ListObject(self.space, [])
assert isinstance(l.strategy, EmptyListStrategy)
@@ -95,7 +120,9 @@
l.insert(0, self.space.wrap(2))
assert isinstance(l.strategy, IntegerListStrategy)
- def notest_list_empty_after_delete(self):
+ def test_list_empty_after_delete(self):
+ import py
+ py.test.skip("return to emptyliststrategy is not supported anymore")
l = W_ListObject(self.space, [self.space.wrap(3)])
assert isinstance(l.strategy, IntegerListStrategy)
l.deleteitem(0)
@@ -117,21 +144,36 @@
l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
assert isinstance(l.strategy, IntegerListStrategy)
+ # IntegerStrategy to IntegerStrategy
l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
assert isinstance(l.strategy, IntegerListStrategy)
l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
assert isinstance(l.strategy, IntegerListStrategy)
+ # ObjectStrategy to ObjectStrategy
l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap('b'), self.space.wrap(3)])
assert isinstance(l.strategy, ObjectListStrategy)
l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
assert isinstance(l.strategy, ObjectListStrategy)
+ # IntegerStrategy to ObjectStrategy
l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
assert isinstance(l.strategy, IntegerListStrategy)
l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')]))
assert isinstance(l.strategy, ObjectListStrategy)
+ # StringStrategy to ObjectStrategy
+ l = W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')])
+ assert isinstance(l.strategy, StringListStrategy)
+ l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ # FloatStrategy to ObjectStrategy
+ l = W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)])
+ assert isinstance(l.strategy, FloatListStrategy)
+ l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
def test_setslice_List(self):
def wrapitems(items):
@@ -160,6 +202,11 @@
keep_other_strategy(l, 0, 2, other.length(), other)
assert l.strategy is self.space.fromcache(StringListStrategy)
+ l = W_ListObject(self.space, wrapitems([1.1, 2.2, 3.3, 4.4, 5.5]))
+ other = W_ListObject(self.space, [])
+ keep_other_strategy(l, 0, 1, l.length(), other)
+ assert l.strategy is self.space.fromcache(FloatListStrategy)
+
l = W_ListObject(self.space, wrapitems(["a",3,"c",4,"e"]))
other = W_ListObject(self.space, wrapitems(["a", "b", "c"]))
keep_other_strategy(l, 0, 2, other.length(), other)
@@ -194,6 +241,11 @@
l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
assert isinstance(l.strategy, IntegerListStrategy)
+ l = W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)])
+ assert isinstance(l.strategy, FloatListStrategy)
+ l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
def test_empty_extend_with_any(self):
empty = W_ListObject(self.space, [])
assert isinstance(empty.strategy, EmptyListStrategy)
@@ -220,6 +272,11 @@
empty = W_ListObject(self.space, [])
assert isinstance(empty.strategy, EmptyListStrategy)
+ empty.extend(W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)]))
+ assert isinstance(empty.strategy, FloatListStrategy)
+
+ empty = W_ListObject(self.space, [])
+ assert isinstance(empty.strategy, EmptyListStrategy)
empty.extend(W_ListObject(self.space, []))
assert isinstance(empty.strategy, EmptyListStrategy)
@@ -293,12 +350,13 @@
l.setslice(0, 1, 3, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
assert isinstance(l.strategy, IntegerListStrategy)
- def test_get_items_copy(self):
+ def test_copy_list(self):
l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
- l2 = l1.getitems()
+ l2 = l1.clone()
l2.append(self.space.wrap(4))
assert not l2 == l1.getitems()
+ def test_getitems_does_not_copy_object_list(self):
l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap("two"), self.space.wrap(3)])
l2 = l1.getitems()
l2.append(self.space.wrap("four"))
@@ -345,7 +403,6 @@
# should not raise
assert getslice__List_ANY_ANY(self.space, l, self.space.wrap(15), self.space.wrap(2222)).strategy == self.space.fromcache(EmptyListStrategy)
-
def test_add_to_rangelist(self):
l1 = make_range_list(self.space, 1, 1, 3)
l2 = W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5)])
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -102,6 +102,7 @@
'instancetypedef',
'terminator',
'_version_tag?',
+ 'name?',
]
# for config.objspace.std.getattributeshortcut
diff --git a/pypy/rlib/_rsocket_rffi.py b/pypy/rlib/_rsocket_rffi.py
--- a/pypy/rlib/_rsocket_rffi.py
+++ b/pypy/rlib/_rsocket_rffi.py
@@ -418,7 +418,7 @@
if _MSVC:
def invalid_socket(fd):
return fd == INVALID_SOCKET
- INVALID_SOCKET = cConfig.INVALID_SOCKET
+ INVALID_SOCKET = intmask(cConfig.INVALID_SOCKET)
else:
def invalid_socket(fd):
return fd < 0
diff --git a/pypy/rlib/_stacklet_n_a.py b/pypy/rlib/_stacklet_n_a.py
--- a/pypy/rlib/_stacklet_n_a.py
+++ b/pypy/rlib/_stacklet_n_a.py
@@ -1,4 +1,5 @@
from pypy.rlib import _rffi_stacklet as _c
+from pypy.rlib import objectmodel, debug
from pypy.rpython.annlowlevel import llhelper
from pypy.tool.staticmethods import StaticMethods
@@ -21,6 +22,9 @@
def destroy(thrd, h):
_c.destroy(thrd._thrd, h)
+ if objectmodel.we_are_translated():
+ debug.debug_print("not using a framework GC: "
+ "stacklet_destroy() may leak")
is_empty_handle = _c.is_empty_handle
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -176,7 +176,6 @@
return decorator
@oopspec("jit.isconstant(value)")
- at specialize.ll()
def isconstant(value):
"""
While tracing, returns whether or not the value is currently known to be
@@ -186,9 +185,9 @@
This is for advanced usage only.
"""
return NonConstant(False)
+isconstant._annspecialcase_ = "specialize:call_location"
@oopspec("jit.isvirtual(value)")
- at specialize.ll()
def isvirtual(value):
"""
Returns if this value is virtual, while tracing, it's relatively
@@ -197,6 +196,7 @@
This is for advanced usage only.
"""
return NonConstant(False)
+isvirtual._annspecialcase_ = "specialize:call_location"
class Entry(ExtRegistryEntry):
_about_ = hint
@@ -738,3 +738,29 @@
return hop.genop('jit_marker', vlist,
resulttype=lltype.Void)
+def record_known_class(value, cls):
+ """
+ Assure the JIT that value is an instance of cls. This is not a precise
+ class check, unlike a guard_class.
+ """
+ assert isinstance(value, cls)
+
+
+class Entry(ExtRegistryEntry):
+ _about_ = record_known_class
+
+ def compute_result_annotation(self, s_inst, s_cls):
+ from pypy.annotation import model as annmodel
+ assert s_cls.is_constant()
+ assert not s_inst.can_be_none()
+ assert isinstance(s_inst, annmodel.SomeInstance)
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype, rclass
+ classrepr = rclass.get_type_repr(hop.rtyper)
+
+ hop.exception_cannot_occur()
+ v_inst = hop.inputarg(hop.args_r[0], arg=0)
+ v_cls = hop.inputarg(classrepr, arg=1)
+ return hop.genop('jit_record_known_class', [v_inst, v_cls],
+ resulttype=lltype.Void)
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -411,6 +411,10 @@
def getaddressindll(self, name):
return dlsym(self.lib, name)
+# These specialize.call_location's should really be specialize.arg(0), however
+# you can't hash a pointer obj, which the specialize machinery wants to do.
+# Given the present usage of these functions, it's good enough.
+ at specialize.call_location()
@jit.oopspec("libffi_array_getitem(ffitype, width, addr, index, offset)")
def array_getitem(ffitype, width, addr, index, offset):
for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -420,6 +424,7 @@
return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
assert False
+ at specialize.call_location()
@jit.oopspec("libffi_array_setitem(ffitype, width, addr, index, offset, value)")
def array_setitem(ffitype, width, addr, index, offset, value):
for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -428,4 +433,4 @@
addr = rffi.ptradd(addr, offset)
rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
return
- assert False
\ No newline at end of file
+ assert False
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -91,9 +91,18 @@
return decorated_func
+ def call_location(self):
+ """ Specializes the function for each call site.
+ """
+ def decorated_func(func):
+ func._annspecialcase_ = "specialize:call_location"
+ return func
+
+ return decorated_func
+
def _wrap(self, args):
return "("+','.join([repr(arg) for arg in args]) +")"
-
+
specialize = _Specialize()
def enforceargs(*args):
@@ -125,7 +134,7 @@
def __hash__(self):
raise TypeError("Symbolics are not hashable!")
-
+
def __nonzero__(self):
raise TypeError("Symbolics are not comparable")
@@ -155,7 +164,7 @@
def lltype(self):
from pypy.rpython.lltypesystem import lltype
return lltype.Signed
-
+
malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
running_on_llinterp = CDefinedIntSymbolic('RUNNING_ON_LLINTERP', default=1)
# running_on_llinterp is meant to have the value 0 in all backends
@@ -221,7 +230,7 @@
def compute_result_annotation(self, s_sizehint):
from pypy.annotation.model import SomeInteger
-
+
assert isinstance(s_sizehint, SomeInteger)
return self.bookkeeper.newlist()
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -143,7 +143,9 @@
return self_type
if self_type in (bool, int, long):
return other_type
- return build_int(None, self_type.SIGNED and other_type.SIGNED, max(self_type.BITS, other_type.BITS))
+ if self_type.SIGNED == other_type.SIGNED:
+ return build_int(None, self_type.SIGNED, max(self_type.BITS, other_type.BITS))
+ raise AssertionError, "Merging these types (%s, %s) is not supported" % (self_type, other_type)
def signedtype(t):
if t in (bool, int, long):
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -229,7 +229,7 @@
sign = self.sign
if intmask(x) < 0 and (sign > 0 or (x << 1) != 0):
raise OverflowError
- return intmask(x * sign)
+ return intmask(intmask(x) * sign)
def tolonglong(self):
return _AsLongLong(self)
@@ -1384,7 +1384,7 @@
# Now remove the excess 2 bits, rounding to nearest integer (with
# ties rounded to even).
- q = (q >> 2) + (bool(q & 2) and bool(q & 5))
+ q = (q >> 2) + r_uint((bool(q & 2) and bool(q & 5)))
if exp > DBL_MAX_EXP or (exp == DBL_MAX_EXP and
q == r_ulonglong(1) << DBL_MANT_DIG):
@@ -1540,8 +1540,8 @@
assert extra_bits == 2 or extra_bits == 3
# Round by remembering a modified copy of the low digit of x
- mask = 1 << (extra_bits - 1)
- low = x.udigit(0) | inexact
+ mask = r_uint(1 << (extra_bits - 1))
+ low = x.udigit(0) | r_uint(inexact)
if (low & mask) != 0 and (low & (3*mask-1)) != 0:
low += mask
x_digit_0 = low & ~(mask-1)
@@ -1790,7 +1790,7 @@
i = v.numdigits() - 1
while i >= 0:
prev = x
- x = (x << SHIFT) + v.widedigit(i)
+ x = (x << SHIFT) + r_ulonglong(v.widedigit(i))
if (x >> SHIFT) != prev:
raise OverflowError(
"long int too large to convert to unsigned long long int")
@@ -1833,8 +1833,8 @@
if x < v.udigit(i):
x += 1
i -= 1
- x = intmask(x * sign)
- return x
+ res = intmask(intmask(x) * sign)
+ return res
#_________________________________________________________________
diff --git a/pypy/rlib/rmmap.py b/pypy/rlib/rmmap.py
--- a/pypy/rlib/rmmap.py
+++ b/pypy/rlib/rmmap.py
@@ -23,10 +23,6 @@
def __init__(self, message):
self.message = message
-class ROverflowError(Exception):
- def __init__(self, message):
- self.message = message
-
includes = ["sys/types.h"]
if _POSIX:
includes += ['unistd.h', 'sys/mman.h']
@@ -597,8 +593,6 @@
def _check_map_size(size):
if size < 0:
raise RTypeError("memory mapped size must be positive")
- if rffi.cast(size_t, size) != size:
- raise ROverflowError("memory mapped size is too large (limited by C int)")
if _POSIX:
def mmap(fileno, length, flags=MAP_SHARED,
diff --git a/pypy/rlib/rrandom.py b/pypy/rlib/rrandom.py
--- a/pypy/rlib/rrandom.py
+++ b/pypy/rlib/rrandom.py
@@ -31,7 +31,7 @@
mt[0]= s & MASK_32
for mti in range(1, N):
mt[mti] = (MAGIC_CONSTANT_A *
- (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti)
+ (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + r_uint(mti))
# See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
# In the previous versions, MSBs of the seed affect
# only MSBs of the array mt[].
@@ -52,7 +52,7 @@
for k in range(max_k, 0, -1):
mt[i] = ((mt[i] ^
((mt[i - 1] ^ (mt[i - 1] >> 30)) * MAGIC_CONSTANT_C))
- + init_key[j] + j) # non linear
+ + init_key[j] + r_uint(j)) # non linear
mt[i] &= MASK_32 # for WORDSIZE > 32 machines
i += 1
j += 1
@@ -104,5 +104,5 @@
j = n % i
mt[i], mt[j] = mt[j], mt[i]
for i in range(N):
- mt[i] += i + 1
+ mt[i] += r_uint(i + 1)
self.index = N
diff --git a/pypy/rlib/rsocket.py b/pypy/rlib/rsocket.py
--- a/pypy/rlib/rsocket.py
+++ b/pypy/rlib/rsocket.py
@@ -17,7 +17,7 @@
from pypy.rlib.objectmodel import instantiate, keepalive_until_here
from pypy.rlib import _rsocket_rffi as _c
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rpython.lltypesystem.rffi import sizeof, offsetof
@@ -131,11 +131,12 @@
from_object = staticmethod(from_object)
@staticmethod
- def _check_port(space, port):
+ def make_ushort_port(space, port):
from pypy.interpreter.error import OperationError
if port < 0 or port > 0xffff:
raise OperationError(space.w_ValueError, space.wrap(
"port must be 0-65535."))
+ return rffi.cast(rffi.USHORT, port)
def fill_from_object(self, space, w_address):
""" Purely abstract
@@ -167,7 +168,7 @@
# IPv4 also supports the special name "<broadcast>".
if name == '<broadcast>':
- return makeipv4addr(intmask(INADDR_BROADCAST), result)
+ return makeipv4addr(r_uint(INADDR_BROADCAST), result)
# "dd.dd.dd.dd" format.
digits = name.split('.')
@@ -184,9 +185,11 @@
0 <= d1 <= 255 and
0 <= d2 <= 255 and
0 <= d3 <= 255):
- return makeipv4addr(intmask(htonl(
- (intmask(d0 << 24)) | (d1 << 16) | (d2 << 8) | (d3 << 0))),
- result)
+
+ addr = intmask(d0 << 24) | (d1 << 16) | (d2 << 8) | (d3 << 0)
+ addr = rffi.cast(rffi.UINT, addr)
+ addr = htonl(addr)
+ return makeipv4addr(addr, result)
# generic host name to IP conversion
info = getaddrinfo(name, None, family=family, address_to_fill=result)
@@ -236,7 +239,9 @@
def get_protocol(self):
a = self.lock(_c.sockaddr_ll)
- res = ntohs(rffi.getintfield(a, 'c_sll_protocol'))
+ proto = rffi.getintfield(a, 'c_sll_protocol')
+ proto = rffi.cast(rffi.USHORT, proto)
+ res = ntohs(proto)
self.unlock()
return res
@@ -277,6 +282,7 @@
def __init__(self, host, port):
makeipaddr(host, self)
a = self.lock(_c.sockaddr_in)
+ port = rffi.cast(rffi.USHORT, port)
rffi.setintfield(a, 'c_sin_port', htons(port))
self.unlock()
@@ -309,7 +315,7 @@
raise TypeError("AF_INET address must be a tuple of length 2")
host = space.str_w(w_host)
port = space.int_w(w_port)
- Address._check_port(space, port)
+ port = Address.make_ushort_port(space, port)
return INETAddress(host, port)
from_object = staticmethod(from_object)
@@ -318,7 +324,7 @@
from pypy.interpreter.error import OperationError
_, w_port = space.unpackiterable(w_address, 2)
port = space.int_w(w_port)
- self._check_port(space, port)
+ port = self.make_ushort_port(space, port)
a = self.lock(_c.sockaddr_in)
rffi.setintfield(a, 'c_sin_port', htons(port))
self.unlock()
@@ -403,7 +409,7 @@
"to 4, not %d" % len(pieces_w))
host = space.str_w(pieces_w[0])
port = space.int_w(pieces_w[1])
- Address._check_port(space, port)
+ port = Address.make_ushort_port(space, port)
if len(pieces_w) > 2: flowinfo = space.uint_w(pieces_w[2])
else: flowinfo = 0
if len(pieces_w) > 3: scope_id = space.uint_w(pieces_w[3])
@@ -419,7 +425,7 @@
raise RSocketError("AF_INET6 address must be a tuple of length 2 "
"to 4, not %d" % len(pieces_w))
port = space.int_w(pieces_w[1])
- self._check_port(space, port)
+ port = self.make_ushort_port(space, port)
if len(pieces_w) > 2: flowinfo = space.uint_w(pieces_w[2])
else: flowinfo = 0
if len(pieces_w) > 3: scope_id = space.uint_w(pieces_w[3])
@@ -1295,9 +1301,13 @@
servent = _c.getservbyname(name, proto)
if not servent:
raise RSocketError("service/proto not found")
- return ntohs(servent.c_s_port)
+ port = rffi.cast(rffi.UINT, servent.c_s_port)
+ return ntohs(port)
def getservbyport(port, proto=None):
+ # This function is only called from pypy/module/_socket and the range of
+ # port is checked there
+ port = rffi.cast(rffi.USHORT, port)
servent = _c.getservbyport(htons(port), proto)
if not servent:
raise RSocketError("port/proto not found")
diff --git a/pypy/rlib/rstruct/standardfmttable.py b/pypy/rlib/rstruct/standardfmttable.py
--- a/pypy/rlib/rstruct/standardfmttable.py
+++ b/pypy/rlib/rstruct/standardfmttable.py
@@ -206,7 +206,7 @@
if signed and i == 0 and x >= 128:
x -= 256
intvalue <<= 8
- intvalue |= x
+ intvalue |= inttype(x)
idx += 1
else:
for i in unroll_range_size:
diff --git a/pypy/rlib/rwin32.py b/pypy/rlib/rwin32.py
--- a/pypy/rlib/rwin32.py
+++ b/pypy/rlib/rwin32.py
@@ -98,8 +98,13 @@
INVALID_HANDLE_VALUE = rffi.cast(HANDLE, -1)
PFILETIME = rffi.CArrayPtr(FILETIME)
- GetLastError = winexternal('GetLastError', [], DWORD, threadsafe=False)
- SetLastError = winexternal('SetLastError', [DWORD], lltype.Void)
+ _GetLastError = winexternal('GetLastError', [], DWORD, threadsafe=False)
+ _SetLastError = winexternal('SetLastError', [DWORD], lltype.Void)
+
+ def GetLastError():
+ return rffi.cast(lltype.Signed, _GetLastError())
+ def SetLastError(err):
+ _SetLastError(rffi.cast(DWORD, err))
# In tests, the first call to GetLastError is always wrong, because error
# is hidden by operations in ll2ctypes. Call it now.
@@ -184,12 +189,12 @@
msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
None,
- code,
+ rffi.cast(DWORD, code),
DEFAULT_LANGUAGE,
rffi.cast(rffi.CCHARP, buf),
0, None)
- if msglen <= 2 or msglen > sys.maxint:
+ if msglen <= 2: # includes the case msglen < 0
return fake_FormatError(code)
# FormatMessage always appends \r\n.
diff --git a/pypy/rlib/test/test_rarithmetic.py b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -126,13 +126,18 @@
cmp = f(r_uint(arg))
assert res == cmp
- def binary_test(self, f, rargs = None):
+ def binary_test(self, f, rargs = None, translated=False):
mask = maxint_mask
if not rargs:
rargs = (1, 3, 55)
+ # when translated merging different int types is not allowed
+ if translated:
+ alltypes = [(r_uint, r_uint)]
+ else:
+ alltypes = [(int, r_uint), (r_uint, int), (r_uint, r_uint)]
for larg in (0, 1, 2, 3, 1234):
for rarg in rargs:
- for types in ((int, r_uint), (r_uint, int), (r_uint, r_uint)):
+ for types in alltypes:
res = f(larg, rarg)
left, right = types
cmp = f(left(larg), right(rarg))
@@ -335,6 +340,14 @@
from pypy.rpython.lltypesystem.rffi import r_int_real
assert compute_restype(r_int_real, r_int_real) is r_int_real
+def test_compute_restype_incompatible():
+ from pypy.rpython.lltypesystem.rffi import r_int_real, r_short, r_ushort
+ testcases = [(r_uint, r_longlong), (r_int_real, r_uint),
+ (r_short, r_ushort)]
+ for t1, t2 in testcases:
+ py.test.raises(AssertionError, compute_restype, t1, t2)
+ py.test.raises(AssertionError, compute_restype, t2, t1)
+
def test_most_neg_value_of():
assert most_neg_value_of_same_type(123) == -sys.maxint-1
assert most_neg_value_of_same_type(r_uint(123)) == 0
diff --git a/pypy/rlib/test/test_rrandom.py b/pypy/rlib/test/test_rrandom.py
--- a/pypy/rlib/test/test_rrandom.py
+++ b/pypy/rlib/test/test_rrandom.py
@@ -1,4 +1,5 @@
from pypy.rlib.rrandom import Random, N, r_uint
+from pypy.rlib.rarithmetic import intmask
import _random
# the numbers were created by using CPython's _randommodule.c
@@ -24,13 +25,13 @@
def test_init_by_array():
rnd = Random()
- rnd.init_by_array([1, 2, 3, 4])
+ rnd.init_by_array([r_uint(n) for n in [1, 2, 3, 4]])
assert rnd.state[:14] == [2147483648, 1269538435, 699006892, 381364451,
172015551, 3237099449, 3609464087, 2187366456, 654585064,
2665903765, 3735624613, 1241943673, 2038528247, 3774211972]
# try arrays of various sizes to test for corner cases
for size in [N, N - 1, N + 1, N // 2, 2 * N]:
- rnd.init_by_array(range(N))
+ rnd.init_by_array([r_uint(n) for n in range(N)])
def test_jumpahead():
rnd = Random()
@@ -47,8 +48,8 @@
def f(x, y):
rnd = Random(x)
rnd.init_by_array([x, y])
- rnd.jumpahead(y)
+ rnd.jumpahead(intmask(y))
return rnd.genrand32(), rnd.random()
t = Translation(f)
- fc = t.compile_c([int, int])
- assert fc(1, 2) == f(1, 2)
+ fc = t.compile_c([r_uint, r_uint])
+ assert fc(r_uint(1), r_uint(2)) == f(r_uint(1), r_uint(2))
diff --git a/pypy/rlib/test/test_rstacklet.py b/pypy/rlib/test/test_rstacklet.py
--- a/pypy/rlib/test/test_rstacklet.py
+++ b/pypy/rlib/test/test_rstacklet.py
@@ -1,4 +1,4 @@
-import gc
+import gc, sys
import py
from pypy.rpython.tool.rffi_platform import CompilationError
try:
@@ -65,6 +65,15 @@
self.tasks[0].withdepth(self.random.genrand32() % 50)
assert len(self.tasks[0].lst) == 0
+ @here_is_a_test
+ def test_destroy(self):
+ # this used to give MemoryError in shadowstack tests
+ for i in range(100000):
+ self.status = 0
+ h = self.sthread.new(switchbackonce_callback,
+ rffi.cast(llmemory.Address, 321))
+ self.sthread.destroy(h)
+
def any_alive(self):
for task in self.tasks:
if task.h:
@@ -228,6 +237,8 @@
cls.old_values = Runner.config, Runner.STATUSMAX
Runner.config = config
Runner.STATUSMAX = 25000
+ if cls.gcrootfinder == "asmgcc" and sys.platform == "win32":
+ py.test.skip("fails with asmgcc on win32")
def teardown_class(cls):
Runner.config, Runner.STATUSMAX = cls.old_values
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -548,6 +548,9 @@
def op_jit_marker(self, *args):
pass
+ def op_jit_record_known_class(self, *args):
+ pass
+
def op_get_exception_addr(self, *args):
raise NotImplementedError
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -430,6 +430,7 @@
'jit_force_virtual': LLOp(canrun=True),
'jit_is_virtual': LLOp(canrun=True),
'jit_force_quasi_immutable': LLOp(canrun=True),
+ 'jit_record_known_class' : LLOp(canrun=True),
'get_exception_addr': LLOp(),
'get_exc_value_addr': LLOp(),
'do_malloc_fixedsize_clear':LLOp(canmallocgc=True),
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -548,6 +548,9 @@
def op_jit_force_quasi_immutable(*args):
pass
+def op_jit_record_known_class(x, y):
+ pass
+
def op_get_group_member(TYPE, grpptr, memberoffset):
from pypy.rpython.lltypesystem import llgroup
assert isinstance(memberoffset, llgroup.GroupMemberOffset)
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -711,7 +711,7 @@
#
# Record the newly allocated object and its full malloced size.
# The object is young or old depending on the argument.
- self.rawmalloced_total_size += allocsize
+ self.rawmalloced_total_size += r_uint(allocsize)
if can_make_young:
if not self.young_rawmalloced_objects:
self.young_rawmalloced_objects = self.AddressDict()
@@ -886,8 +886,8 @@
#return (num_bits + (LONG_BIT - 1)) >> LONG_BIT_SHIFT
# --- Optimized version:
return intmask(
- ((r_uint(length) + ((LONG_BIT << self.card_page_shift) - 1)) >>
- (self.card_page_shift + LONG_BIT_SHIFT)))
+ ((r_uint(length) + r_uint((LONG_BIT << self.card_page_shift) - 1)) >>
+ (self.card_page_shift + LONG_BIT_SHIFT)))
def card_marking_bytes_for_length(self, length):
# --- Unoptimized version:
@@ -895,7 +895,7 @@
#return (num_bits + 7) >> 3
# --- Optimized version:
return intmask(
- ((r_uint(length) + ((8 << self.card_page_shift) - 1)) >>
+ ((r_uint(length) + r_uint((8 << self.card_page_shift) - 1)) >>
(self.card_page_shift + 3)))
def debug_check_consistency(self):
@@ -1523,7 +1523,7 @@
llarena.arena_reserve(arena, totalsize)
#
size_gc_header = self.gcheaderbuilder.size_gc_header
- self.rawmalloced_total_size += raw_malloc_usage(totalsize)
+ self.rawmalloced_total_size += r_uint(raw_malloc_usage(totalsize))
self.old_rawmalloced_objects.append(arena + size_gc_header)
return arena
@@ -1689,7 +1689,7 @@
allocsize += extra_words * WORD
#
llarena.arena_free(arena)
- self.rawmalloced_total_size -= allocsize
+ self.rawmalloced_total_size -= r_uint(allocsize)
def free_unvisited_rawmalloc_objects(self):
list = self.old_rawmalloced_objects
diff --git a/pypy/rpython/memory/gc/minimarkpage.py b/pypy/rpython/memory/gc/minimarkpage.py
--- a/pypy/rpython/memory/gc/minimarkpage.py
+++ b/pypy/rpython/memory/gc/minimarkpage.py
@@ -149,7 +149,7 @@
ll_assert(nsize > 0, "malloc: size is null or negative")
ll_assert(nsize <= self.small_request_threshold,"malloc: size too big")
ll_assert((nsize & (WORD-1)) == 0, "malloc: size is not aligned")
- self.total_memory_used += nsize
+ self.total_memory_used += r_uint(nsize)
#
# Get the page to use from the size
size_class = nsize >> WORD_POWER_2
@@ -474,7 +474,7 @@
obj += block_size
#
# Update the global total size of objects.
- self.total_memory_used += surviving * block_size
+ self.total_memory_used += r_uint(surviving * block_size)
#
# Return the number of surviving objects.
return surviving
diff --git a/pypy/rpython/memory/gctransform/asmgcroot.py b/pypy/rpython/memory/gctransform/asmgcroot.py
--- a/pypy/rpython/memory/gctransform/asmgcroot.py
+++ b/pypy/rpython/memory/gctransform/asmgcroot.py
@@ -92,7 +92,6 @@
# make a copy of the graph that will reload the values
graph2 = copygraph(fnptr._obj.graph)
block2 = graph2.startblock
- block2.isstartblock = False
block1 = Block([])
reloadedvars = []
for v, c_p in zip(block2.inputargs, sra):
@@ -109,7 +108,6 @@
[w], v))
reloadedvars.append(v)
block1.closeblock(Link(reloadedvars, block2))
- block1.isstartblock = True
graph2.startblock = block1
FUNC2 = lltype.FuncType([], FUNC1.RESULT)
fnptr2 = lltype.functionptr(FUNC2,
diff --git a/pypy/rpython/memory/gctransform/shadowstack.py b/pypy/rpython/memory/gctransform/shadowstack.py
--- a/pypy/rpython/memory/gctransform/shadowstack.py
+++ b/pypy/rpython/memory/gctransform/shadowstack.py
@@ -307,7 +307,7 @@
"restore_state_from: broken shadowstack")
self.gcdata.root_stack_base = shadowstackref.base
self.gcdata.root_stack_top = shadowstackref.top
- self.destroy(shadowstackref)
+ self._cleanup(shadowstackref)
def start_fresh_new_state(self):
self.gcdata.root_stack_base = self.unused_full_stack
@@ -315,6 +315,10 @@
self.unused_full_stack = llmemory.NULL
def destroy(self, shadowstackref):
+ llmemory.raw_free(shadowstackref.base)
+ self._cleanup(shadowstackref)
+
+ def _cleanup(self, shadowstackref):
shadowstackref.base = llmemory.NULL
shadowstackref.top = llmemory.NULL
shadowstackref.context = llmemory.NULL
diff --git a/pypy/rpython/memory/gctransform/test/test_transform.py b/pypy/rpython/memory/gctransform/test/test_transform.py
--- a/pypy/rpython/memory/gctransform/test/test_transform.py
+++ b/pypy/rpython/memory/gctransform/test/test_transform.py
@@ -102,12 +102,12 @@
llops.genop("gc_pop_alive", [var])
-def checkblock(block, is_borrowed):
+def checkblock(block, is_borrowed, is_start_block):
if block.operations == ():
# a return/exception block -- don't want to think about them
# (even though the test passes for somewhat accidental reasons)
return
- if block.isstartblock:
+ if is_start_block:
refs_in = 0
else:
refs_in = len([v for v in block.inputargs if isinstance(v, Variable)
@@ -167,7 +167,7 @@
if check:
for graph, is_borrowed in graphs_borrowed.iteritems():
for block in graph.iterblocks():
- checkblock(block, is_borrowed)
+ checkblock(block, is_borrowed, block is graph.startblock)
return t, transformer
def getops(graph):
diff --git a/pypy/rpython/memory/gctransform/transform.py b/pypy/rpython/memory/gctransform/transform.py
--- a/pypy/rpython/memory/gctransform/transform.py
+++ b/pypy/rpython/memory/gctransform/transform.py
@@ -263,9 +263,7 @@
# still be empty (but let's check)
if starts_with_empty_block(graph) and inserted_empty_startblock:
old_startblock = graph.startblock
- graph.startblock.isstartblock = False
graph.startblock = graph.startblock.exits[0].target
- graph.startblock.isstartblock = True
checkgraph(graph)
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -1773,7 +1773,7 @@
@registering(rwin32.FormatError)
def register_rwin32_FormatError(self):
- return extdef([rwin32.DWORD], str,
+ return extdef([lltype.Signed], str,
"rwin32_FormatError",
llimpl=rwin32.llimpl_FormatError,
ooimpl=rwin32.fake_FormatError)
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -12,6 +12,7 @@
from pypy.rpython.tool import rffi_platform as platform
from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
from pypy.rlib import rposix
+from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import specialize
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.rpython.annlowlevel import hlstr
@@ -442,20 +443,19 @@
# Helper functions for win32
def make_longlong(high, low):
- return (lltype.r_longlong(high) << 32) + lltype.r_longlong(low)
+ return (rffi.r_longlong(high) << 32) + rffi.r_longlong(low)
# Seconds between 1.1.1601 and 1.1.1970
-secs_between_epochs = lltype.r_longlong(11644473600)
+secs_between_epochs = rffi.r_longlong(11644473600)
def FILE_TIME_to_time_t_nsec(filetime):
ft = make_longlong(filetime.c_dwHighDateTime, filetime.c_dwLowDateTime)
# FILETIME is in units of 100 nsec
nsec = (ft % 10000000) * 100
time = (ft / 10000000) - secs_between_epochs
- return time, nsec
+ return intmask(time), intmask(nsec)
def time_t_to_FILE_TIME(time, filetime):
- ft = lltype.r_longlong((time + secs_between_epochs) * 10000000)
- filetime.c_dwHighDateTime = lltype.r_uint(ft >> 32)
- filetime.c_dwLowDateTime = lltype.r_uint(ft & lltype.r_uint(-1))
-
+ ft = (rffi.r_longlong(time) + secs_between_epochs) * 10000000
+ filetime.c_dwHighDateTime = rffi.r_uint(ft >> 32)
+ filetime.c_dwLowDateTime = rffi.r_uint(ft) # masking off high bits
diff --git a/pypy/rpython/module/ll_termios.py b/pypy/rpython/module/ll_termios.py
--- a/pypy/rpython/module/ll_termios.py
+++ b/pypy/rpython/module/ll_termios.py
@@ -72,9 +72,14 @@
def tcsetattr_llimpl(fd, when, attributes):
c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')
- c_struct.c_c_iflag, c_struct.c_c_oflag, c_struct.c_c_cflag, \
- c_struct.c_c_lflag, ispeed, ospeed, cc = attributes
try:
+ c_struct.c_c_iflag = r_uint(attributes[0])
+ c_struct.c_c_oflag = r_uint(attributes[1])
+ c_struct.c_c_cflag = r_uint(attributes[2])
+ c_struct.c_c_lflag = r_uint(attributes[3])
+ ispeed = r_uint(attributes[4])
+ ospeed = r_uint(attributes[5])
+ cc = attributes[6]
for i in range(NCCS):
c_struct.c_c_cc[i] = rffi.r_uchar(ord(cc[i][0]))
if c_cfsetispeed(c_struct, ispeed) < 0:
@@ -87,8 +92,8 @@
lltype.free(c_struct, flavor='raw')
r_uint = rffi.r_uint
-register_external(rtermios.tcsetattr, [int, int, (r_uint, r_uint, r_uint,
- r_uint, r_uint, r_uint, [str])], llimpl=tcsetattr_llimpl,
+register_external(rtermios.tcsetattr, [int, int, (int, int, int,
+ int, int, int, [str])], llimpl=tcsetattr_llimpl,
export_name='termios.tcsetattr')
# a bit C-c C-v code follows...
diff --git a/pypy/rpython/normalizecalls.py b/pypy/rpython/normalizecalls.py
--- a/pypy/rpython/normalizecalls.py
+++ b/pypy/rpython/normalizecalls.py
@@ -116,8 +116,6 @@
v = Constant(default)
outlist.append(v)
newblock.closeblock(Link(outlist, oldblock))
- oldblock.isstartblock = False
- newblock.isstartblock = True
graph.startblock = newblock
for i in range(len(newdefaults)-1,-1,-1):
if newdefaults[i] is NODEFAULT:
@@ -171,8 +169,6 @@
# prepare the output args of newblock and link
outlist = inlist[:]
newblock.closeblock(Link(outlist, oldblock))
- oldblock.isstartblock = False
- newblock.isstartblock = True
graph.startblock = newblock
# finished
checkgraph(graph)
diff --git a/pypy/tool/nullpath.py b/pypy/tool/nullpath.py
--- a/pypy/tool/nullpath.py
+++ b/pypy/tool/nullpath.py
@@ -1,4 +1,4 @@
-import py
+import py, os
class NullPyPathLocal(py.path.local):
@@ -6,7 +6,7 @@
return self.__class__(py.path.local.join(self, *args))
def open(self, mode):
- return open('/dev/null', mode)
+ return open(os.devnull, mode)
def __repr__(self):
return py.path.local.__repr__(self) + ' [fake]'
diff --git a/pypy/tool/test/test_nullpath.py b/pypy/tool/test/test_nullpath.py
--- a/pypy/tool/test/test_nullpath.py
+++ b/pypy/tool/test/test_nullpath.py
@@ -1,11 +1,7 @@
-import sys
+import sys, os
import py
from pypy.tool.nullpath import NullPyPathLocal
-def setup_module():
- if 'posix' not in sys.builtin_module_names:
- py.test.skip('posix only')
-
def test_nullpath(tmpdir):
path = NullPyPathLocal(tmpdir)
assert repr(path).endswith('[fake]')
@@ -13,4 +9,4 @@
assert isinstance(foo_txt, NullPyPathLocal)
#
f = foo_txt.open('w')
- assert f.name == '/dev/null'
+ assert f.name == os.devnull
diff --git a/pypy/translator/backendopt/constfold.py b/pypy/translator/backendopt/constfold.py
--- a/pypy/translator/backendopt/constfold.py
+++ b/pypy/translator/backendopt/constfold.py
@@ -37,8 +37,9 @@
except (KeyboardInterrupt, SystemExit):
raise
except Exception, e:
- log.WARNING('constant-folding %r:' % (spaceop,))
- log.WARNING(' %s: %s' % (e.__class__.__name__, e))
+ pass # turn off reporting these as warnings: useless
+ #log.WARNING('constant-folding %r:' % (spaceop,))
+ #log.WARNING(' %s: %s' % (e.__class__.__name__, e))
else:
# success in folding this space operation
if spaceop.opname in fixup_op_result:
diff --git a/pypy/translator/backendopt/inline.py b/pypy/translator/backendopt/inline.py
--- a/pypy/translator/backendopt/inline.py
+++ b/pypy/translator/backendopt/inline.py
@@ -453,7 +453,6 @@
#vars that need to be passed through the blocks of the inlined function
linktoinlined = splitlink
copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
- copiedstartblock.isstartblock = False
#find args passed to startblock of inlined function
passon_args = []
for arg in self.op.args[1:]:
diff --git a/pypy/translator/backendopt/mallocv.py b/pypy/translator/backendopt/mallocv.py
--- a/pypy/translator/backendopt/mallocv.py
+++ b/pypy/translator/backendopt/mallocv.py
@@ -391,7 +391,6 @@
virtualframe = VirtualFrame(graph2.startblock, 0, nodelist)
graphbuilder = GraphBuilder(self, graph2)
specblock = graphbuilder.start_from_virtualframe(virtualframe)
- specblock.isstartblock = True
specgraph = graph2
specgraph.name += '_mallocv'
specgraph.startblock = specblock
diff --git a/pypy/translator/backendopt/test/test_malloc.py b/pypy/translator/backendopt/test/test_malloc.py
--- a/pypy/translator/backendopt/test/test_malloc.py
+++ b/pypy/translator/backendopt/test/test_malloc.py
@@ -50,7 +50,8 @@
# we do the loop ourselves instead of calling remove_simple_mallocs()
while True:
progress = remover.remove_mallocs_once(graph)
- simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()))
+ simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()),
+ [graph])
if progress and option.view:
t.view()
if expected_result is not Ellipsis:
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -542,7 +542,7 @@
mk.rule(*rule)
if self.config.translation.gcrootfinder == 'asmgcc':
- trackgcfiles = [cfile[:-2] for cfile in mk.cfiles]
+ trackgcfiles = [cfile[:cfile.rfind('.')] for cfile in mk.cfiles]
if self.translator.platform.name == 'msvc':
trackgcfiles = [f for f in trackgcfiles
if f.startswith(('implement', 'testing',
@@ -579,7 +579,7 @@
if self.translator.platform.name == 'msvc':
lblofiles = []
for cfile in mk.cfiles:
- f = cfile[:-2]
+ f = cfile[:cfile.rfind('.')]
if f in trackgcfiles:
ofile = '%s.lbl.obj' % (f,)
else:
diff --git a/pypy/translator/c/src/support.h b/pypy/translator/c/src/support.h
--- a/pypy/translator/c/src/support.h
+++ b/pypy/translator/c/src/support.h
@@ -11,6 +11,7 @@
#endif /* MIN */
#define RUNNING_ON_LLINTERP 0
+#define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */
#define FAIL_EXCEPTION(exc, msg) \
{ \
diff --git a/pypy/translator/c/test/test_lltyped.py b/pypy/translator/c/test/test_lltyped.py
--- a/pypy/translator/c/test/test_lltyped.py
+++ b/pypy/translator/c/test/test_lltyped.py
@@ -476,12 +476,13 @@
def f(n):
result = ()
for cls in classes:
+ nn = cls(n)
for OP in operators:
x = getmin(cls)
- res1 = OP(x, n)
+ res1 = OP(x, nn)
result = result + (res1,)
x = getmax(cls)
- res1 = OP(x, n)
+ res1 = OP(x, nn)
result = result + (res1,)
return result
diff --git a/pypy/translator/c/test/test_refcount.py b/pypy/translator/c/test/test_refcount.py
--- a/pypy/translator/c/test/test_refcount.py
+++ b/pypy/translator/c/test/test_refcount.py
@@ -229,7 +229,6 @@
graph = t.buildflowgraph(g)
assert graph.startblock.operations == []
graph.startblock = graph.startblock.exits[0].target
- graph.startblock.isstartblock = True
from pypy.objspace.flow.model import checkgraph
checkgraph(graph)
t._prebuilt_graphs[g] = graph
diff --git a/pypy/translator/c/test/test_standalone.py b/pypy/translator/c/test/test_standalone.py
--- a/pypy/translator/c/test/test_standalone.py
+++ b/pypy/translator/c/test/test_standalone.py
@@ -224,7 +224,7 @@
filename = str(udir.join('test_standalone_largefile'))
r4800000000 = r_longlong(4800000000L)
def entry_point(argv):
- assert str(r4800000000 + len(argv)) == '4800000003'
+ assert str(r4800000000 + r_longlong(len(argv))) == '4800000003'
fd = os.open(filename, os.O_RDWR | os.O_CREAT, 0644)
os.lseek(fd, r4800000000, 0)
newpos = os.lseek(fd, 0, 1)
diff --git a/pypy/translator/c/test/test_typed.py b/pypy/translator/c/test/test_typed.py
--- a/pypy/translator/c/test/test_typed.py
+++ b/pypy/translator/c/test/test_typed.py
@@ -261,7 +261,7 @@
f._annspecialcase_ = "specialize:argtype(0)"
def g(n):
if n > 0:
- return f(r_longlong(0))
+ return intmask(f(r_longlong(0)))
else:
return f(0)
diff --git a/pypy/translator/jvm/test/test_rarithmetic.py b/pypy/translator/jvm/test/test_rarithmetic.py
--- a/pypy/translator/jvm/test/test_rarithmetic.py
+++ b/pypy/translator/jvm/test/test_rarithmetic.py
@@ -32,7 +32,7 @@
cache[types] = fun
return cache[types](x, y)
return f(x,y)
- super(BaseAdaptedTest,self).binary_test(new_func, rargs)
+ super(BaseAdaptedTest,self).binary_test(new_func, rargs, translated=True)
class Test_r_uint(BaseAdaptedTest, BaseTest_r_uint):
RTYPE = ra.r_uint
diff --git a/pypy/translator/platform/darwin.py b/pypy/translator/platform/darwin.py
--- a/pypy/translator/platform/darwin.py
+++ b/pypy/translator/platform/darwin.py
@@ -12,17 +12,10 @@
so_ext = 'dylib'
- # NOTE: GCC 4.2 will fail at runtime due to subtle issues, possibly
- # related to GC roots. Using LLVM-GCC or Clang will break the build.
- default_cc = 'gcc-4.0'
-
- def __init__(self, cc=None):
- if cc is None:
- try:
- cc = os.environ['CC']
- except KeyError:
- cc = self.default_cc
- self.cc = cc
+ # NOTE: With asmgcc GCC 4.2 will fail at runtime due to subtle issues,
+ # possibly related to GC roots. Using LLVM-GCC or Clang will break the
+ # build. On Darwin asmgcc is not the default anymore, so it is fine to use
+ # whatever gcc we find on the system
def _args_for_shared(self, args):
return (list(self.shared_only)
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -179,7 +179,7 @@
# The c compiler accepts any order of arguments, while
# the assembler still has the old behavior that all options
# must come first, and after the file name all options are ignored.
- # So please be careful with the oder of parameters! ;-)
+ # So please be careful with the order of parameters! ;-)
args = ['/nologo', '/c'] + compile_args + ['/Fo%s' % (oname,), str(cfile)]
self._execute_c_compiler(cc, args, oname)
return oname
@@ -265,7 +265,7 @@
return fpath
rel_cfiles = [m.pathrel(cfile) for cfile in cfiles]
- rel_ofiles = [rel_cfile[:-2]+'.obj' for rel_cfile in rel_cfiles]
+ rel_ofiles = [rel_cfile[:rel_cfile.rfind('.')]+'.obj' for rel_cfile in rel_cfiles]
m.cfiles = rel_cfiles
rel_includedirs = [pypyrel(incldir) for incldir in eci.include_dirs]
@@ -296,6 +296,7 @@
rules = [
('all', '$(DEFAULT_TARGET)', []),
('.c.obj', '', '$(CC) /nologo $(CFLAGS) $(CFLAGSEXTRA) /Fo$@ /c $< $(INCLUDEDIRS)'),
+ ('.asm.obj', '', '$(MASM) /nologo /Fo$@ /c $< $(INCLUDEDIRS)'),
]
for rule in rules:
diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -397,7 +397,8 @@
def transform_dead_op_vars(graph, translator=None):
"""Remove dead operations and variables that are passed over a link
but not used in the target block. Input is a graph."""
- return transform_dead_op_vars_in_blocks(list(graph.iterblocks()), translator)
+ return transform_dead_op_vars_in_blocks(list(graph.iterblocks()),
+ [graph], translator)
# the set of operations that can safely be removed
# (they have no side effects, at least in R-Python)
@@ -419,11 +420,19 @@
hasattr: True,
}
-def transform_dead_op_vars_in_blocks(blocks, translator=None):
+def find_start_blocks(graphs):
+ start_blocks = set()
+ for graph in graphs:
+ start_blocks.add(graph.startblock)
+ return start_blocks
+
+def transform_dead_op_vars_in_blocks(blocks, graphs, translator=None):
"""Remove dead operations and variables that are passed over a link
but not used in the target block. Input is a set of blocks"""
read_vars = {} # set of variables really used
variable_flow = {} # map {Var: list-of-Vars-it-depends-on}
+ set_of_blocks = set(blocks)
+ start_blocks = find_start_blocks(graphs)
def canremove(op, block):
if op.opname not in CanRemove:
@@ -451,7 +460,7 @@
if block.exits:
for link in block.exits:
- if link.target not in blocks:
+ if link.target not in set_of_blocks:
for arg, targetarg in zip(link.args, link.target.inputargs):
read_vars[arg] = True
read_vars[targetarg] = True
@@ -465,7 +474,7 @@
read_vars[arg] = True
# an input block's inputargs should not be modified, even if some
# of the function's input arguments are not actually used
- if block.isstartblock:
+ if block in start_blocks:
for arg in block.inputargs:
read_vars[arg] = True
diff --git a/pypy/translator/transform.py b/pypy/translator/transform.py
--- a/pypy/translator/transform.py
+++ b/pypy/translator/transform.py
@@ -115,7 +115,7 @@
# to kill dead (never-followed) links,
# which can possibly remove more variables.
from pypy.translator.simplify import transform_dead_op_vars_in_blocks
- transform_dead_op_vars_in_blocks(block_subset)
+ transform_dead_op_vars_in_blocks(block_subset, self.translator.graphs)
def transform_dead_code(self, block_subset):
"""Remove dead code: these are the blocks that are not annotated at all
diff --git a/pypy/translator/unsimplify.py b/pypy/translator/unsimplify.py
--- a/pypy/translator/unsimplify.py
+++ b/pypy/translator/unsimplify.py
@@ -42,9 +42,7 @@
vars = [copyvar(annotator, v) for v in graph.startblock.inputargs]
newblock = Block(vars)
newblock.closeblock(Link(vars, graph.startblock))
- graph.startblock.isstartblock = False
graph.startblock = newblock
- graph.startblock.isstartblock = True
def starts_with_empty_block(graph):
return (not graph.startblock.operations
@@ -151,9 +149,7 @@
newop = SpaceOperation('direct_call', [c_initial_func], v_none)
extrablock.operations = [newop]
extrablock.closeblock(Link(args, entry_point.startblock))
- entry_point.startblock.isstartblock = False
entry_point.startblock = extrablock
- entry_point.startblock.isstartblock = True
checkgraph(entry_point)
def call_final_function(translator, final_func, annhelper=None):
More information about the pypy-commit
mailing list