[pypy-commit] pypy numpy NDimArray: merged default in
alex_gaynor
noreply at buildbot.pypy.org
Mon Oct 17 02:33:52 CEST 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy NDimArray
Changeset: r48104:cb0cdef747f2
Date: 2011-10-16 20:31 -0400
http://bitbucket.org/pypy/pypy/changeset/cb0cdef747f2/
Log: merged default in
diff --git a/pypy/interpreter/pyparser/pytokenizer.py b/pypy/interpreter/pyparser/pytokenizer.py
--- a/pypy/interpreter/pyparser/pytokenizer.py
+++ b/pypy/interpreter/pyparser/pytokenizer.py
@@ -226,7 +226,7 @@
parenlev = parenlev - 1
if parenlev < 0:
raise TokenError("unmatched '%s'" % initial, line,
- lnum-1, 0, token_list)
+ lnum, start + 1, token_list)
if token in python_opmap:
punct = python_opmap[token]
else:
diff --git a/pypy/interpreter/pyparser/test/test_pyparse.py b/pypy/interpreter/pyparser/test/test_pyparse.py
--- a/pypy/interpreter/pyparser/test/test_pyparse.py
+++ b/pypy/interpreter/pyparser/test/test_pyparse.py
@@ -87,6 +87,10 @@
assert exc.lineno == 1
assert exc.offset == 5
assert exc.lastlineno == 5
+ exc = py.test.raises(SyntaxError, parse, "abc)").value
+ assert exc.msg == "unmatched ')'"
+ assert exc.lineno == 1
+ assert exc.offset == 4
def test_is(self):
self.parse("x is y")
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
@@ -165,6 +165,7 @@
'unicodegetitem' : (('ref', 'int'), 'int'),
'unicodesetitem' : (('ref', 'int', 'int'), 'int'),
'cast_ptr_to_int' : (('ref',), 'int'),
+ 'cast_int_to_ptr' : (('int',), 'ref'),
'debug_merge_point': (('ref', 'int'), None),
'force_token' : ((), 'int'),
'call_may_force' : (('int', 'varargs'), 'intorptr'),
@@ -875,9 +876,6 @@
def op_new_array(self, arraydescr, count):
return do_new_array(arraydescr.ofs, count)
- def op_cast_ptr_to_int(self, descr, ptr):
- return cast_to_int(ptr)
-
def op_force_token(self, descr):
opaque_frame = _to_opaque(self)
return llmemory.cast_ptr_to_adr(opaque_frame)
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1468,20 +1468,16 @@
return u''.join(u.chars)
- def test_casts(self):
- py.test.skip("xxx fix or kill")
- from pypy.rpython.lltypesystem import lltype, llmemory
- TP = lltype.GcStruct('x')
- x = lltype.malloc(TP)
- x = lltype.cast_opaque_ptr(llmemory.GCREF, x)
+ def test_cast_int_to_ptr(self):
+ res = self.execute_operation(rop.CAST_INT_TO_PTR,
+ [BoxInt(-17)], 'ref').value
+ assert lltype.cast_ptr_to_int(res) == -17
+
+ def test_cast_ptr_to_int(self):
+ x = lltype.cast_int_to_ptr(llmemory.GCREF, -19)
res = self.execute_operation(rop.CAST_PTR_TO_INT,
- [BoxPtr(x)], 'int').value
- expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x))
- assert rffi.get_real_int(res) == rffi.get_real_int(expected)
- res = self.execute_operation(rop.CAST_PTR_TO_INT,
- [ConstPtr(x)], 'int').value
- expected = self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x))
- assert rffi.get_real_int(res) == rffi.get_real_int(expected)
+ [BoxPtr(x)], 'int').value
+ assert res == -19
def test_ooops_non_gc(self):
x = lltype.malloc(lltype.Struct('x'), flavor='raw')
@@ -2299,13 +2295,6 @@
#
cpu.bh_strsetitem(x, 4, ord('/'))
assert str.chars[4] == '/'
- #
-## x = cpu.bh_newstr(5)
-## y = cpu.bh_cast_ptr_to_int(x)
-## z = cpu.bh_cast_ptr_to_int(x)
-## y = rffi.get_real_int(y)
-## z = rffi.get_real_int(z)
-## assert type(y) == type(z) == int and y == z
def test_sorting_of_fields(self):
S = self.S
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1387,7 +1387,8 @@
def genop_same_as(self, op, arglocs, resloc):
self.mov(arglocs[0], resloc)
- #genop_cast_ptr_to_int = genop_same_as
+ genop_cast_ptr_to_int = genop_same_as
+ genop_cast_int_to_ptr = genop_same_as
def genop_int_mod(self, op, arglocs, resloc):
if IS_X86_32:
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
@@ -1152,7 +1152,8 @@
self.possibly_free_var(op.getarg(0))
resloc = self.force_allocate_reg(op.result)
self.Perform(op, [argloc], resloc)
- #consider_cast_ptr_to_int = consider_same_as
+ consider_cast_ptr_to_int = consider_same_as
+ consider_cast_int_to_ptr = consider_same_as
def consider_strlen(self, op):
args = op.getarglist()
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
@@ -800,8 +800,7 @@
def rewrite_op_cast_ptr_to_int(self, op):
if self._is_gc(op.args[0]):
- #return op
- raise NotImplementedError("cast_ptr_to_int")
+ return op
def rewrite_op_force_cast(self, op):
v_arg = op.args[0]
@@ -1543,6 +1542,10 @@
def rewrite_op_jit_force_virtual(self, op):
return self._do_builtin_call(op)
+ def rewrite_op_jit_is_virtual(self, op):
+ raise Exception, (
+ "'vref.virtual' should not be used from jit-visible code")
+
def rewrite_op_jit_force_virtualizable(self, op):
# this one is for virtualizables
vinfo = self.get_vinfo(op.args[0])
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
@@ -2,7 +2,7 @@
from pypy.rlib.rtimer import read_timestamp
from pypy.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck
from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.debug import debug_start, debug_stop
+from pypy.rlib.debug import debug_start, debug_stop, ll_assert
from pypy.rlib.debug import make_sure_not_resized
from pypy.rpython.lltypesystem import lltype, llmemory, rclass
from pypy.rpython.lltypesystem.lloperation import llop
@@ -503,6 +503,15 @@
@arguments("r", returns="r")
def bhimpl_cast_opaque_ptr(a):
return a
+ @arguments("r", returns="i")
+ def bhimpl_cast_ptr_to_int(a):
+ i = lltype.cast_ptr_to_int(a)
+ ll_assert((i & 1) == 1, "bhimpl_cast_ptr_to_int: not an odd int")
+ return i
+ @arguments("i", returns="r")
+ def bhimpl_cast_int_to_ptr(i):
+ ll_assert((i & 1) == 1, "bhimpl_cast_int_to_ptr: not an odd int")
+ return lltype.cast_int_to_ptr(llmemory.GCREF, i)
@arguments("i", returns="i")
def bhimpl_int_copy(a):
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
@@ -222,6 +222,7 @@
'cast_float_to_int', 'cast_int_to_float',
'cast_float_to_singlefloat', 'cast_singlefloat_to_float',
'float_neg', 'float_abs',
+ 'cast_ptr_to_int', 'cast_int_to_ptr',
]:
exec py.code.Source('''
@arguments("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
@@ -431,6 +431,8 @@
'INT_IS_TRUE/1b',
'INT_NEG/1',
'INT_INVERT/1',
+ 'CAST_PTR_TO_INT/1',
+ 'CAST_INT_TO_PTR/1',
#
'SAME_AS/1', # gets a Const or a Box, turns it into another Box
#
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
@@ -3440,7 +3440,6 @@
class TestLLtype(BaseLLtypeTests, LLJitMixin):
def test_tagged(self):
- py.test.skip("implement me")
from pypy.rlib.objectmodel import UnboxedValue
class Base(object):
__slots__ = ()
@@ -3492,3 +3491,35 @@
pc += 1
return pc
res = self.meta_interp(main, [False, 100, True], taggedpointers=True)
+
+ def test_rerased(self):
+ from pypy.rlib.rerased import erase_int, unerase_int, new_erasing_pair
+ eraseX, uneraseX = new_erasing_pair("X")
+ #
+ class X:
+ def __init__(self, a, b):
+ self.a = a
+ self.b = b
+ #
+ def f(i, j):
+ # 'j' should be 0 or 1, not other values
+ if j > 0:
+ e = eraseX(X(i, j))
+ else:
+ try:
+ e = erase_int(i)
+ except OverflowError:
+ return -42
+ if j & 1:
+ x = uneraseX(e)
+ return x.a - x.b
+ else:
+ return unerase_int(e)
+ #
+ x = self.interp_operations(f, [-128, 0], taggedpointers=True)
+ assert x == -128
+ bigint = sys.maxint//2 + 1
+ x = self.interp_operations(f, [bigint, 0], taggedpointers=True)
+ assert x == -42
+ x = self.interp_operations(f, [1000, 1], taggedpointers=True)
+ assert x == 999
diff --git a/pypy/jit/metainterp/test/test_virtualref.py b/pypy/jit/metainterp/test/test_virtualref.py
--- a/pypy/jit/metainterp/test/test_virtualref.py
+++ b/pypy/jit/metainterp/test/test_virtualref.py
@@ -3,6 +3,7 @@
from pypy.rpython.llinterp import LLException
from pypy.rlib.jit import JitDriver, dont_look_inside, vref_None
from pypy.rlib.jit import virtual_ref, virtual_ref_finish, InvalidVirtualRef
+from pypy.rlib.jit import non_virtual_ref
from pypy.rlib.objectmodel import compute_unique_id
from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin, _get_jitcodes
from pypy.jit.metainterp.resoperation import rop
@@ -595,6 +596,65 @@
res = self.meta_interp(fn, [10])
assert res == 6
+ def test_is_virtual(self):
+ myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])
+ class X:
+ pass
+ @dont_look_inside
+ def residual(vref):
+ return vref.virtual
+ #
+ def f(n):
+ res1 = -42
+ while n > 0:
+ myjitdriver.jit_merge_point(n=n, res1=res1)
+ x = X()
+ vref = virtual_ref(x)
+ res1 = residual(vref)
+ virtual_ref_finish(vref, x)
+ n -= 1
+ return res1
+ #
+ res = self.meta_interp(f, [10])
+ assert res == 1
+
+ def test_is_not_virtual_none(self):
+ myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])
+ @dont_look_inside
+ def residual(vref):
+ return vref.virtual
+ #
+ def f(n):
+ res1 = -42
+ while n > 0:
+ myjitdriver.jit_merge_point(n=n, res1=res1)
+ res1 = residual(vref_None)
+ n -= 1
+ return res1
+ #
+ res = self.meta_interp(f, [10])
+ assert res == 0
+
+ def test_is_not_virtual_non_none(self):
+ myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])
+ class X:
+ pass
+ @dont_look_inside
+ def residual(vref):
+ return vref.virtual
+ #
+ def f(n):
+ res1 = -42
+ while n > 0:
+ myjitdriver.jit_merge_point(n=n, res1=res1)
+ x = X()
+ res1 = residual(non_virtual_ref(x))
+ n -= 1
+ return res1
+ #
+ res = self.meta_interp(f, [10])
+ assert res == 0
+
class TestLLtype(VRefTests, LLJitMixin):
pass
diff --git a/pypy/jit/metainterp/virtualref.py b/pypy/jit/metainterp/virtualref.py
--- a/pypy/jit/metainterp/virtualref.py
+++ b/pypy/jit/metainterp/virtualref.py
@@ -39,6 +39,7 @@
def replace_force_virtual_with_call(self, graphs):
# similar to rvirtualizable2.replace_force_virtualizable_with_call().
c_force_virtual_ptr = None
+ c_is_virtual_ptr = None
force_virtual_count = 0
for graph in graphs:
for block in graph.iterblocks():
@@ -52,6 +53,13 @@
op.opname = 'direct_call'
op.args = [c_force_virtual_ptr, op.args[0]]
force_virtual_count += 1
+ #
+ if op.opname == 'jit_is_virtual':
+ if c_is_virtual_ptr is None:
+ c_is_virtual_ptr = self.get_is_virtual_fnptr()
+ #
+ op.opname = 'direct_call'
+ op.args = [c_is_virtual_ptr, op.args[0]]
#
if c_force_virtual_ptr is not None:
log("replaced %d 'jit_force_virtual' with %r" % (force_virtual_count,
@@ -129,6 +137,17 @@
force_virtual_if_necessary)
return inputconst(lltype.typeOf(funcptr), funcptr)
+ def get_is_virtual_fnptr(self):
+ #
+ def is_virtual(inst):
+ if not inst:
+ return False
+ return inst.typeptr == self.jit_virtual_ref_vtable
+ #
+ FUNC = lltype.FuncType([rclass.OBJECTPTR], lltype.Bool)
+ funcptr = self.warmrunnerdesc.helper_func(lltype.Ptr(FUNC), is_virtual)
+ return inputconst(lltype.typeOf(funcptr), funcptr)
+
def force_virtual(self, inst):
vref = lltype.cast_pointer(lltype.Ptr(self.JIT_VIRTUAL_REF), inst)
token = vref.virtual_token
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -84,8 +84,8 @@
raise OperationError(space.w_TypeError,
w('eval() arg 1 must be a string or code object'))
- caller = space.getexecutioncontext().gettopframe_nohidden()
if space.is_w(w_globals, space.w_None):
+ caller = space.getexecutioncontext().gettopframe_nohidden()
if caller is None:
w_globals = space.newdict()
if space.is_w(w_locals, space.w_None):
@@ -97,13 +97,6 @@
elif space.is_w(w_locals, space.w_None):
w_locals = w_globals
- try:
- space.getitem(w_globals, space.wrap('__builtins__'))
- except OperationError, e:
- if not e.match(space, space.w_KeyError):
- raise
- if caller is not None:
- w_builtin = space.builtin.pick_builtin(caller.w_globals)
- space.setitem(w_globals, space.wrap('__builtins__'), w_builtin)
+ space.builtin.pick_builtin(w_globals)
return codeobj.exec_code(space, w_globals, w_locals)
diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -19,6 +19,11 @@
# - normal: self.sthread != None, not is_empty_handle(self.h)
# - finished: self.sthread != None, is_empty_handle(self.h)
+ def __del__(self):
+ sthread = self.sthread
+ if sthread is not None and not sthread.is_empty_handle(self.h):
+ sthread.destroy(self.h)
+
def check_sthread(self):
ec = self.space.getexecutioncontext()
if ec.stacklet_thread is not self.sthread:
@@ -28,6 +33,8 @@
def descr_init(self, w_callable, __args__):
if self.sthread is not None:
raise geterror(self.space, "continulet already __init__ialized")
+ sthread = build_sthread(self.space)
+ workaround_disable_jit(sthread)
#
# hackish: build the frame "by hand", passing it the correct arguments
space = self.space
@@ -41,7 +48,6 @@
self.bottomframe = bottomframe
#
global_state.origin = self
- sthread = build_sthread(self.space)
self.sthread = sthread
h = sthread.new(new_stacklet_callback)
post_switch(sthread, h)
@@ -71,6 +77,7 @@
global_state.clear()
raise geterror(self.space, "continulet already finished")
self.check_sthread()
+ workaround_disable_jit(self.sthread)
#
global_state.origin = self
if to is None:
@@ -259,6 +266,16 @@
sthread = ec.stacklet_thread = SThread(space, ec)
return sthread
+def workaround_disable_jit(sthread):
+ # A bad workaround to kill the JIT anywhere in this thread.
+ # This forces all the frames. It's a bad workaround because
+ # it takes O(depth) time, and it will cause some "abort:
+ # vable escape" in the JIT. The goal is to prevent any frame
+ # from being still virtuals, because the JIT generates code
+ # to un-virtualizable them "on demand" by loading values based
+ # on FORCE_TOKEN, which is an address in the stack.
+ sthread.ec.force_all_frames()
+
# ____________________________________________________________
def permute(space, args_w):
diff --git a/pypy/module/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
@@ -161,12 +161,7 @@
@binop
def mul(self, v1, v2):
return v1 * v2
- @binop
- def div(self, v1, v2):
- try:
- return v1 / v2
- except ZeroDivisionError:
- return (1 if v1>=0 else -1) *(1 if v2>=0 else -1)*float('inf')
+
@unaryop
def pos(self, v):
return +v
@@ -219,6 +214,14 @@
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
@@ -297,6 +300,11 @@
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
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
@@ -291,7 +291,9 @@
assert b[i] == i * 5
def test_div(self):
- from numpy import array, dtype
+ from math import isnan
+ from numpy import array, dtype, inf
+
a = array(range(1, 6))
b = a / a
for i in range(5):
@@ -303,6 +305,24 @@
for i in range(5):
assert b[i] == 1
+ a = array([-1, 0, 1])
+ b = array([0, 0, 0])
+ c = a / b
+ assert (c == [0, 0, 0]).all()
+
+ a = array([-1.0, 0.0, 1.0])
+ b = array([0.0, 0.0, 0.0])
+ c = a / b
+ assert c[0] == -inf
+ assert isnan(c[1])
+ assert c[2] == inf
+
+ b = array([-0.0, -0.0, -0.0])
+ c = a / b
+ assert c[0] == inf
+ assert isnan(c[1])
+ assert c[2] == -inf
+
def test_div_other(self):
from numpy import array
a = array(range(5))
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -225,6 +225,8 @@
# strip comment
if '#' in line:
line = line[:line.index('#')]
+ if line.strip() == 'guard_not_invalidated?':
+ return 'guard_not_invalidated', None, [], '...', False
# find the resvar, if any
if ' = ' in line:
resvar, _, line = line.partition(' = ')
@@ -249,7 +251,7 @@
descr = descr[len('descr='):]
else:
descr = None
- return opname, resvar, args, descr
+ return opname, resvar, args, descr, True
@classmethod
def preprocess_expected_src(cls, src):
@@ -258,13 +260,23 @@
# replaced with the corresponding operations, so that tests don't have
# to repeat it every time
ticker_check = """
+ guard_not_invalidated?
+ ticker0 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
+ ticker_cond0 = int_lt(ticker0, 0)
+ guard_false(ticker_cond0, descr=...)
+ """
+ src = src.replace('--TICK--', ticker_check)
+ #
+ # this is the ticker check generated if we have threads
+ thread_ticker_check = """
+ guard_not_invalidated?
ticker0 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
ticker1 = int_sub(ticker0, 1)
setfield_raw(ticker_address, ticker1, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
ticker_cond0 = int_lt(ticker1, 0)
guard_false(ticker_cond0, descr=...)
"""
- src = src.replace('--TICK--', ticker_check)
+ src = src.replace('--THREAD-TICK--', thread_ticker_check)
#
# this is the ticker check generated in PyFrame.handle_operation_error
exc_ticker_check = """
@@ -298,7 +310,7 @@
if not cond:
raise InvalidMatch(message, frame=sys._getframe(1))
- def match_op(self, op, (exp_opname, exp_res, exp_args, exp_descr)):
+ def match_op(self, op, (exp_opname, exp_res, exp_args, exp_descr, _)):
self._assert(op.name == exp_opname, "operation mismatch")
self.match_var(op.res, exp_res)
if exp_args != ['...']:
@@ -341,7 +353,7 @@
what is after the '...'
"""
iter_exp_ops = iter(expected_ops)
- iter_ops = iter(self.ops)
+ iter_ops = RevertableIterator(self.ops)
for opindex, exp_op in enumerate(iter_exp_ops):
try:
if exp_op == '...':
@@ -360,6 +372,9 @@
break
self.match_op(op, exp_op)
except InvalidMatch, e:
+ if exp_op[4] is False: # optional operation
+ iter_ops.revert_one()
+ continue # try to match with the next exp_op
e.opindex = opindex
raise
#
@@ -398,3 +413,18 @@
else:
return True
+
+class RevertableIterator(object):
+ def __init__(self, sequence):
+ self.sequence = sequence
+ self.index = 0
+ def __iter__(self):
+ return self
+ def next(self):
+ index = self.index
+ if index == len(self.sequence):
+ raise StopIteration
+ self.index = index + 1
+ return self.sequence[index]
+ def revert_one(self):
+ self.index -= 1
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -145,15 +145,17 @@
def test_parse_op(self):
res = OpMatcher.parse_op(" a = int_add( b, 3 ) # foo")
- assert res == ("int_add", "a", ["b", "3"], None)
+ assert res == ("int_add", "a", ["b", "3"], None, True)
res = OpMatcher.parse_op("guard_true(a)")
- assert res == ("guard_true", None, ["a"], None)
+ assert res == ("guard_true", None, ["a"], None, True)
res = OpMatcher.parse_op("setfield_gc(p0, i0, descr=<foobar>)")
- assert res == ("setfield_gc", None, ["p0", "i0"], "<foobar>")
+ assert res == ("setfield_gc", None, ["p0", "i0"], "<foobar>", True)
res = OpMatcher.parse_op("i1 = getfield_gc(p0, descr=<foobar>)")
- assert res == ("getfield_gc", "i1", ["p0"], "<foobar>")
+ assert res == ("getfield_gc", "i1", ["p0"], "<foobar>", True)
res = OpMatcher.parse_op("p0 = force_token()")
- assert res == ("force_token", "p0", [], None)
+ assert res == ("force_token", "p0", [], None, True)
+ res = OpMatcher.parse_op("guard_not_invalidated?")
+ assert res == ("guard_not_invalidated", None, [], '...', False)
def test_exact_match(self):
loop = """
@@ -341,7 +343,7 @@
# this is the actual loop
'int_lt', 'guard_true', 'int_add',
# this is the signal checking stuff
- 'getfield_raw', 'int_sub', 'setfield_raw', 'int_lt', 'guard_false',
+ 'guard_not_invalidated', 'getfield_raw', 'int_lt', 'guard_false',
'jump'
]
@@ -407,7 +409,7 @@
# this is the actual loop
'int_lt', 'guard_true', 'force_token', 'int_add',
# this is the signal checking stuff
- 'getfield_raw', 'int_sub', 'setfield_raw', 'int_lt', 'guard_false',
+ 'guard_not_invalidated', 'getfield_raw', 'int_lt', 'guard_false',
'jump'
]
@@ -425,10 +427,9 @@
guard_true(i6, descr=...)
i8 = int_add(i4, 1)
# signal checking stuff
+ guard_not_invalidated(descr=...)
i10 = getfield_raw(37212896, descr=<.* pypysig_long_struct.c_value .*>)
- i12 = int_sub(i10, 1)
- setfield_raw(37212896, i12, descr=<.* pypysig_long_struct.c_value .*>)
- i14 = int_lt(i12, 0)
+ i14 = int_lt(i10, 0)
guard_false(i14, descr=...)
jump(p0, p1, p2, p3, i8, descr=...)
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_misc.py b/pypy/module/pypyjit/test_pypy_c/test_misc.py
--- a/pypy/module/pypyjit/test_pypy_c/test_misc.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_misc.py
@@ -329,4 +329,20 @@
guard_false(i28, descr=...)
i30 = int_lshift(i20, 24)
i31 = int_or(i26, i30)
- """ % {"32_bit_only": extra})
\ No newline at end of file
+ """ % {"32_bit_only": extra})
+
+ def test_eval(self):
+ def main():
+ i = 1
+ a = compile('x+x+x+x+x+x', 'eval', 'eval')
+ b = {'x': 7}
+ while i < 1000:
+ y = eval(a,b,b) # ID: eval
+ i += 1
+ return y
+
+ log = self.run(main)
+ assert log.result == 42
+ # the following assertion fails if the loop was cancelled due
+ # to "abort: vable escape"
+ assert len(log.loops_by_id("eval")) == 1
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py b/pypy/module/pypyjit/test_pypy_c/test_thread.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -0,0 +1,28 @@
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+
+class TestThread(BaseTestPyPyC):
+ def test_simple(self):
+ def main(n):
+ import thread
+ def f():
+ i = 0
+ while i < n:
+ i += 1
+ done.release()
+
+ done = thread.allocate_lock()
+ done.acquire()
+ thread.start_new_thread(f, ())
+ done.acquire()
+ return 0
+ log = self.run(main, [500])
+ assert round(log.result, 6) == round(main(500), 6)
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match("""
+ i2 = int_lt(i0, i1)
+ guard_true(i2, descr=...)
+ i3 = int_add(i0, 1)
+ --THREAD-TICK--
+ jump(..., descr=<Loop0>)
+ """)
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -47,7 +47,7 @@
'pypy_initial_path' : 'state.pypy_initial_path',
'_getframe' : 'vm._getframe',
- '_current_frames' : 'vm._current_frames',
+ '_current_frames' : 'currentframes._current_frames',
'setrecursionlimit' : 'vm.setrecursionlimit',
'getrecursionlimit' : 'vm.getrecursionlimit',
'setcheckinterval' : 'vm.setcheckinterval',
diff --git a/pypy/module/sys/currentframes.py b/pypy/module/sys/currentframes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/sys/currentframes.py
@@ -0,0 +1,78 @@
+"""
+Implementation of the 'sys._current_frames()' routine.
+"""
+from pypy.interpreter import gateway
+
+app = gateway.applevel('''
+"NOT_RPYTHON"
+import __builtin__
+
+class fake_code(object):
+ co_name = "?"
+ co_filename = "?"
+ co_firstlineno = 0
+
+class fake_frame(object):
+ f_back = None
+ f_builtins = __builtin__.__dict__
+ f_code = fake_code()
+ f_exc_traceback = None
+ f_exc_type = None
+ f_exc_value = None
+ f_globals = {}
+ f_lasti = -1
+ f_lineno = 0
+ f_locals = {}
+ f_restricted = False
+ f_trace = None
+
+ def __init__(self, f):
+ if f is not None:
+ for name in ["f_builtins", "f_code", "f_globals", "f_lasti",
+ "f_lineno"]:
+ setattr(self, name, getattr(f, name))
+''')
+
+def _current_frames(space):
+ """_current_frames() -> dictionary
+
+ Return a dictionary mapping each current thread T's thread id to T's
+ current stack "frame". Functions in the traceback module can build the
+ call stack given such a frame.
+
+ Note that in PyPy this returns fake frame objects, to avoid a runtime
+ penalty everywhere with the JIT. (So far these fake frames can be
+ completely uninformative depending on the JIT state; we could return
+ more with more efforts.)
+
+ This function should be used for specialized purposes only."""
+ w_result = space.newdict()
+ w_fake_frame = app.wget(space, "fake_frame")
+ w_fake_code = app.wget(space, "fake_code")
+ ecs = space.threadlocals.getallvalues()
+ for thread_ident, ec in ecs.items():
+ vref = ec.topframeref
+ frames = []
+ while not vref.virtual:
+ f = vref()
+ if f is None:
+ break
+ frames.append(f)
+ vref = f.f_backref
+ else:
+ frames.append(None)
+ #
+ w_topframe = space.wrap(None)
+ w_prevframe = None
+ for f in frames:
+ w_nextframe = space.call_function(w_fake_frame, space.wrap(f))
+ if w_prevframe is None:
+ w_topframe = w_nextframe
+ else:
+ space.setattr(w_prevframe, space.wrap('f_back'), w_nextframe)
+ w_prevframe = w_nextframe
+ #
+ space.setitem(w_result,
+ space.wrap(thread_ident),
+ w_topframe)
+ return w_result
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -556,7 +556,7 @@
return sys._current_frames()
frames = f()
assert frames.keys() == [0]
- assert frames[0].f_code.co_name == 'f'
+ assert frames[0].f_code.co_name in ('f', '?')
class AppTestCurrentFramesWithThread(AppTestCurrentFrames):
def setup_class(cls):
@@ -568,23 +568,25 @@
import thread
thread_id = thread.get_ident()
- self.ready = False
def other_thread():
- self.ready = True
print "thread started"
- time.sleep(5)
+ lock2.release()
+ lock1.acquire()
+ lock1 = thread.allocate_lock()
+ lock2 = thread.allocate_lock()
+ lock1.acquire()
+ lock2.acquire()
thread.start_new_thread(other_thread, ())
def f():
- for i in range(100):
- if self.ready: break
- time.sleep(0.1)
+ lock2.acquire()
return sys._current_frames()
frames = f()
+ lock1.release()
thisframe = frames.pop(thread_id)
- assert thisframe.f_code.co_name == 'f'
+ assert thisframe.f_code.co_name in ('f', '?')
assert len(frames) == 1
_, other_frame = frames.popitem()
- assert other_frame.f_code.co_name == 'other_thread'
+ assert other_frame.f_code.co_name in ('other_thread', '?')
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -45,25 +45,6 @@
f.mark_as_escaped()
return space.wrap(f)
-def _current_frames(space):
- """_current_frames() -> dictionary
-
- Return a dictionary mapping each current thread T's thread id to T's
- current stack frame.
-
- This function should be used for specialized purposes only."""
- raise OperationError(space.w_NotImplementedError,
- space.wrap("XXX sys._current_frames() incompatible with the JIT"))
- w_result = space.newdict()
- ecs = space.threadlocals.getallvalues()
- for thread_ident, ec in ecs.items():
- f = ec.gettopframe_nohidden()
- f.mark_as_escaped()
- space.setitem(w_result,
- space.wrap(thread_ident),
- space.wrap(f))
- return w_result
-
def setrecursionlimit(space, w_new_limit):
"""setrecursionlimit() sets the maximum number of nested calls that
can occur before a RuntimeError is raised. On PyPy the limit is
diff --git a/pypy/rlib/_jit_vref.py b/pypy/rlib/_jit_vref.py
--- a/pypy/rlib/_jit_vref.py
+++ b/pypy/rlib/_jit_vref.py
@@ -25,6 +25,10 @@
def simple_call(self):
return self.s_instance
+ def getattr(self, s_attr):
+ assert s_attr.const == 'virtual'
+ return annmodel.s_Bool
+
def rtyper_makerepr(self, rtyper):
if rtyper.type_system.name == 'lltypesystem':
return vrefrepr
@@ -61,6 +65,13 @@
" prebuilt virtual_ref")
return lltype.nullptr(OBJECTPTR.TO)
+ def rtype_getattr(self, hop):
+ s_attr = hop.args_s[1]
+ assert s_attr.const == 'virtual'
+ v = hop.inputarg(self, arg=0)
+ hop.exception_cannot_occur()
+ return hop.genop('jit_is_virtual', [v], resulttype = lltype.Bool)
+
from pypy.rpython.ootypesystem.rclass import OBJECT
class OOVRefRepr(VRefRepr):
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -317,6 +317,12 @@
raise InvalidVirtualRef
return self._x
+ @property
+ def virtual(self):
+ """A property that is True if the vref contains a virtual that would
+ be forced by the '()' operator."""
+ return self._state == 'non-forced'
+
def _finish(self):
if self._state == 'non-forced':
self._state = 'invalid'
diff --git a/pypy/rlib/rerased.py b/pypy/rlib/rerased.py
--- a/pypy/rlib/rerased.py
+++ b/pypy/rlib/rerased.py
@@ -218,15 +218,13 @@
[v_value] = hop.inputargs(lltype.Signed)
c_one = hop.inputconst(lltype.Signed, 1)
hop.exception_is_here()
- v2 = hop.genop('int_lshift_ovf', [v_value, c_one],
+ v2 = hop.genop('int_add_ovf', [v_value, v_value],
resulttype = lltype.Signed)
v2p1 = hop.genop('int_add', [v2, c_one],
resulttype = lltype.Signed)
v_instance = hop.genop('cast_int_to_ptr', [v2p1],
resulttype=self.lowleveltype)
- v = hop.genop('cast_opaque_ptr', [v_instance],
- resulttype=self.lowleveltype)
- return v
+ return v_instance
def convert_const(self, value):
if value._identity is _identity_for_ints:
@@ -266,10 +264,10 @@
return hop.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed)
def rtype_erase_int(self, hop):
- hop.exception_is_here()
[v_value] = hop.inputargs(lltype.Signed)
c_one = hop.inputconst(lltype.Signed, 1)
- v2 = hop.genop('int_lshift_ovf', [v_value, c_one],
+ hop.exception_is_here()
+ v2 = hop.genop('int_add_ovf', [v_value, v_value],
resulttype = lltype.Signed)
v2p1 = hop.genop('int_add', [v2, c_one],
resulttype = lltype.Signed)
diff --git a/pypy/rlib/test/test__jit_vref.py b/pypy/rlib/test/test__jit_vref.py
--- a/pypy/rlib/test/test__jit_vref.py
+++ b/pypy/rlib/test/test__jit_vref.py
@@ -27,10 +27,13 @@
x1 = X()
vref = virtual_ref(x1)
assert vref._state == 'non-forced'
+ assert vref.virtual is True
assert vref() is x1
assert vref._state == 'forced'
+ assert vref.virtual is False
virtual_ref_finish(vref, x1)
assert vref._state == 'forced'
+ assert vref.virtual is False
assert vref() is x1
def test_direct_invalid():
@@ -135,6 +138,13 @@
x = self.interpret(f, [])
assert x == 42
+ def test_rtype_virtualattr(self):
+ def f():
+ vref = virtual_ref(X())
+ return vref.virtual
+ x = self.interpret(f, [])
+ assert x is False
+
class TestLLtype(BaseTestVRef, LLRtypeMixin):
OBJECTTYPE = OBJECTPTR
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -658,6 +658,8 @@
if T == llmemory.GCREF:
if isinstance(llobj._obj, _llgcopaque):
return ctypes.c_void_p(llobj._obj.intval)
+ if isinstance(llobj._obj, int): # tagged pointer
+ return ctypes.c_void_p(llobj._obj)
container = llobj._obj.container
T = lltype.Ptr(lltype.typeOf(container))
# otherwise it came from integer and we want a c_void_p with
@@ -1268,6 +1270,7 @@
class _llgcopaque(lltype._container):
_TYPE = llmemory.GCREF.TO
_name = "_llgcopaque"
+ _read_directly_intval = True # for _ptr._cast_to_int()
def __init__(self, void_p):
if isinstance(void_p, (int, long)):
@@ -1299,11 +1302,6 @@
return _opaque_objs[self.intval // 2]
return force_cast(PTRTYPE, self.intval)
-## def _cast_to_int(self):
-## return self.intval
-
-## def _cast_to_adr(self):
-## return _lladdress(self.intval)
def cast_adr_to_int(addr):
if isinstance(addr, llmemory.fakeaddress):
diff --git a/pypy/rpython/lltypesystem/llmemory.py b/pypy/rpython/lltypesystem/llmemory.py
--- a/pypy/rpython/lltypesystem/llmemory.py
+++ b/pypy/rpython/lltypesystem/llmemory.py
@@ -498,6 +498,8 @@
def _cast_to_int(self, symbolic=False):
if self:
+ if isinstance(self.ptr._obj0, int): # tagged integer
+ return self.ptr._obj0
if symbolic:
return AddressAsInt(self)
else:
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
@@ -428,6 +428,7 @@
'jit_marker': LLOp(),
'jit_force_virtualizable':LLOp(canrun=True),
'jit_force_virtual': LLOp(canrun=True),
+ 'jit_is_virtual': LLOp(canrun=True),
'jit_force_quasi_immutable': LLOp(canrun=True),
'get_exception_addr': LLOp(),
'get_exc_value_addr': LLOp(),
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -1360,6 +1360,8 @@
obj = normalizeptr(self, check)._getobj(check)
if isinstance(obj, int):
return obj # special case for cast_int_to_ptr() results put into opaques
+ if getattr(obj, '_read_directly_intval', False):
+ return obj.intval # special case for _llgcopaque
result = intmask(obj._getid())
# assume that id() returns an addressish value which is
# not zero and aligned to at least a multiple of 4
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
@@ -538,6 +538,9 @@
def op_jit_force_virtual(x):
return x
+def op_jit_is_virtual(x):
+ return False
+
def op_jit_force_quasi_immutable(*args):
pass
diff --git a/pypy/rpython/lltypesystem/rtagged.py b/pypy/rpython/lltypesystem/rtagged.py
--- a/pypy/rpython/lltypesystem/rtagged.py
+++ b/pypy/rpython/lltypesystem/rtagged.py
@@ -43,7 +43,7 @@
v_value = hop.inputarg(lltype.Signed, arg=1)
c_one = hop.inputconst(lltype.Signed, 1)
hop.exception_is_here()
- v2 = hop.genop('int_lshift_ovf', [v_value, c_one],
+ v2 = hop.genop('int_add_ovf', [v_value, v_value],
resulttype = lltype.Signed)
v2p1 = hop.genop('int_add', [v2, c_one],
resulttype = lltype.Signed)
diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -1123,6 +1123,9 @@
#assert lltype.cast_ptr_to_int(ref1) == intval
+ x = rffi.cast(llmemory.GCREF, -17)
+ assert lltype.cast_ptr_to_int(x) == -17
+
def test_ptr_truth(self):
abc = rffi.cast(lltype.Ptr(lltype.FuncType([], lltype.Void)), 0)
assert not abc
diff --git a/pypy/translator/c/funcgen.py b/pypy/translator/c/funcgen.py
--- a/pypy/translator/c/funcgen.py
+++ b/pypy/translator/c/funcgen.py
@@ -833,7 +833,7 @@
return 'INSTRUMENT_COUNT(%s);' % counter_label
def OP_IS_EARLY_CONSTANT(self, op):
- return self.expr(op.result) + ' = 0;' # Allways false
+ return '%s = 0; /* IS_EARLY_CONSTANT */' % (self.expr(op.result),)
def OP_JIT_MARKER(self, op):
return '/* JIT_MARKER %s */' % op
@@ -845,6 +845,9 @@
return '%s = %s; /* JIT_FORCE_VIRTUAL */' % (self.expr(op.result),
self.expr(op.args[0]))
+ def OP_JIT_IS_VIRTUAL(self, op):
+ return '%s = 0; /* JIT_IS_VIRTUAL */' % (self.expr(op.result),)
+
def OP_JIT_FORCE_QUASI_IMMUTABLE(self, op):
return '/* JIT_FORCE_QUASI_IMMUTABLE %s */' % op
diff --git a/pypy/translator/platform/linux.py b/pypy/translator/platform/linux.py
--- a/pypy/translator/platform/linux.py
+++ b/pypy/translator/platform/linux.py
@@ -24,15 +24,14 @@
return self._pkg_config("libffi", "--libs-only-L",
['/usr/lib/libffi'])
+ def library_dirs_for_libffi_a(self):
+ # places where we need to look for libffi.a
+ return self.library_dirs_for_libffi() + ['/usr/lib']
+
class Linux(BaseLinux):
shared_only = () # it seems that on 32-bit linux, compiling with -fPIC
# gives assembler that asmgcc is not happy about.
- def library_dirs_for_libffi_a(self):
- # places where we need to look for libffi.a
- return self.library_dirs_for_libffi() + ['/usr/lib']
-
-
class Linux64(BaseLinux):
pass
More information about the pypy-commit
mailing list