[pypy-svn] pypy jit-lsprofile: merge default
fijal
commits-noreply at bitbucket.org
Sat Apr 9 21:46:01 CEST 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: jit-lsprofile
Changeset: r43258:629b5b05a04c
Date: 2011-04-09 21:45 +0200
http://bitbucket.org/pypy/pypy/changeset/629b5b05a04c/
Log: merge default
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
@@ -895,3 +895,10 @@
fn = self.getcompiled(llf)
assert fn() == 45
+ def test_rstring_to_float(self):
+ from pypy.rlib.rfloat import rstring_to_float
+ def llf(i):
+ s = ['42.3', '123.4'][i]
+ return rstring_to_float(s)
+ fn = self.getcompiled(llf, [int])
+ assert fn(0) == 42.3
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
@@ -179,6 +179,9 @@
"""
raise NotImplementedError
+ def count_fields_if_immutable(self):
+ return -1
+
def _clone_if_mutable(self):
return self
def clone_if_mutable(self):
diff --git a/pypy/module/sys/interp_encoding.py b/pypy/module/sys/interp_encoding.py
--- a/pypy/module/sys/interp_encoding.py
+++ b/pypy/module/sys/interp_encoding.py
@@ -37,6 +37,10 @@
base_encoding = None
def _getfilesystemencoding(space):
+ if (space.config.translation.type_system == 'ootype'):
+ # XXX: fix this for ootype
+ return base_encoding
+ #
encoding = base_encoding
if rlocale.HAVE_LANGINFO and rlocale.CODESET:
oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -457,6 +457,12 @@
args_s.append(s_arg)
bk.emulate_pbc_call(uniquekey, s_func, args_s)
+ def get_getfield_op(self, rtyper):
+ if rtyper.type_system.name == 'ootypesystem':
+ return 'oogetfield'
+ else:
+ return 'getfield'
+
def specialize_call(self, hop, **kwds_i):
# XXX to be complete, this could also check that the concretetype
# of the variables are the same for each of the calls.
@@ -471,8 +477,8 @@
r_green = hop.args_r[i]
v_green = hop.inputarg(r_green, arg=i)
else:
- if hop.rtyper.type_system.name == 'ootypesystem':
- py.test.skip("lltype only")
+ #if hop.rtyper.type_system.name == 'ootypesystem':
+ #py.test.skip("lltype only")
objname, fieldname = name.split('.') # see test_green_field
assert objname in driver.reds
i = kwds_i['i_' + objname]
@@ -488,7 +494,10 @@
"field %r not found in %r" % (name,
r_red.lowleveltype.TO))
r_red = r_red.rbase
- GTYPE = r_red.lowleveltype.TO
+ if hop.rtyper.type_system.name == 'ootypesystem':
+ GTYPE = r_red.lowleveltype
+ else:
+ GTYPE = r_red.lowleveltype.TO
assert GTYPE._immutable_field(mangled_name), (
"field %r must be declared as immutable" % name)
if not hasattr(driver, 'll_greenfields'):
@@ -497,7 +506,8 @@
#
v_red = hop.inputarg(r_red, arg=i)
c_llname = hop.inputconst(lltype.Void, mangled_name)
- v_green = hop.genop('getfield', [v_red, c_llname],
+ getfield_op = self.get_getfield_op(hop.rtyper)
+ v_green = hop.genop(getfield_op, [v_red, c_llname],
resulttype = r_field)
s_green = s_red.classdef.about_attribute(fieldname)
assert s_green is not None
diff --git a/pypy/jit/metainterp/test/test_optimizeutil.py b/pypy/jit/metainterp/test/test_optimizeutil.py
--- a/pypy/jit/metainterp/test/test_optimizeutil.py
+++ b/pypy/jit/metainterp/test/test_optimizeutil.py
@@ -68,6 +68,16 @@
nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj)
refdescr = cpu.fielddescrof(NODEOBJ, 'ref')
+ INTOBJ_NOIMMUT = lltype.GcStruct('INTOBJ_NOIMMUT', ('parent', OBJECT),
+ ('intval', lltype.Signed))
+ INTOBJ_IMMUT = lltype.GcStruct('INTOBJ_IMMUT', ('parent', OBJECT),
+ ('intval', lltype.Signed),
+ hints={'immutable': True})
+ intobj_noimmut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+ intobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+ noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
+ immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')
+
arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
@@ -155,6 +165,8 @@
register_known_gctype(cpu, node_vtable2, NODE2)
register_known_gctype(cpu, u_vtable, U)
register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF)
+ register_known_gctype(cpu, intobj_noimmut_vtable, INTOBJ_NOIMMUT)
+ register_known_gctype(cpu, intobj_immut_vtable, INTOBJ_IMMUT)
namespace = locals()
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
@@ -2,6 +2,7 @@
from pypy.rlib import rgc
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.debug import fatalerror
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
from pypy.rpython.lltypesystem import llgroup
from pypy.rpython.lltypesystem.lloperation import llop
@@ -22,6 +23,8 @@
class GcLLDescription(GcCache):
minimal_size_in_nursery = 0
+ get_malloc_slowpath_addr = None
+
def __init__(self, gcdescr, translator=None, rtyper=None):
GcCache.__init__(self, translator is not None, rtyper)
self.gcdescr = gcdescr
@@ -35,6 +38,8 @@
pass
def can_inline_malloc(self, descr):
return False
+ def can_inline_malloc_varsize(self, descr, num_elem):
+ return False
def has_write_barrier_class(self):
return None
def freeing_block(self, start, stop):
@@ -588,6 +593,10 @@
self.max_size_of_young_obj = self.GCClass.JIT_max_size_of_young_obj()
self.minimal_size_in_nursery=self.GCClass.JIT_minimal_size_in_nursery()
+ # for the fast path of mallocs, the following must be true, at least
+ assert self.GCClass.inline_simple_malloc
+ assert self.GCClass.inline_simple_malloc_varsize
+
# make a malloc function, with three arguments
def malloc_basic(size, tid):
type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
@@ -666,20 +675,23 @@
x3 = x0 * 0.3
for_test_only.x = x0 + x1 + x2 + x3
#
- def malloc_fixedsize_slowpath(size):
+ def malloc_slowpath(size):
if self.DEBUG:
random_usage_of_xmm_registers()
assert size >= self.minimal_size_in_nursery
try:
+ # NB. although we call do_malloc_fixedsize_clear() here,
+ # it's a bit of a hack because we set tid to 0 and may
+ # also use it to allocate varsized objects. The tid
+ # and possibly the length are both set afterward.
gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
0, size, True, False, False)
except MemoryError:
fatalerror("out of memory (from JITted code)")
return 0
return rffi.cast(lltype.Signed, gcref)
- self.malloc_fixedsize_slowpath = malloc_fixedsize_slowpath
- self.MALLOC_FIXEDSIZE_SLOWPATH = lltype.FuncType([lltype.Signed],
- lltype.Signed)
+ self.malloc_slowpath = malloc_slowpath
+ self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.Signed)
def get_nursery_free_addr(self):
nurs_addr = llop.gc_adr_of_nursery_free(llmemory.Address)
@@ -689,9 +701,8 @@
nurs_top_addr = llop.gc_adr_of_nursery_top(llmemory.Address)
return rffi.cast(lltype.Signed, nurs_top_addr)
- def get_malloc_fixedsize_slowpath_addr(self):
- fptr = llhelper(lltype.Ptr(self.MALLOC_FIXEDSIZE_SLOWPATH),
- self.malloc_fixedsize_slowpath)
+ def get_malloc_slowpath_addr(self):
+ fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath)
return rffi.cast(lltype.Signed, fptr)
def initialize(self):
@@ -837,6 +848,16 @@
return True
return False
+ def can_inline_malloc_varsize(self, arraydescr, num_elem):
+ assert isinstance(arraydescr, BaseArrayDescr)
+ basesize = arraydescr.get_base_size(self.translate_support_code)
+ itemsize = arraydescr.get_item_size(self.translate_support_code)
+ try:
+ size = ovfcheck(basesize + ovfcheck(itemsize * num_elem))
+ return size < self.max_size_of_young_obj
+ except OverflowError:
+ return False
+
def has_write_barrier_class(self):
return WriteBarrierDescr
diff --git a/pypy/rlib/rlocale.py b/pypy/rlib/rlocale.py
--- a/pypy/rlib/rlocale.py
+++ b/pypy/rlib/rlocale.py
@@ -7,6 +7,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.rpython.tool import rffi_platform as platform
+from pypy.rpython.extfunc import register_external
class LocaleError(Exception):
def __init__(self, message):
@@ -156,23 +157,35 @@
HAVE_BIND_TEXTDOMAIN_CODESET = cConfig.HAVE_BIND_TEXTDOMAIN_CODESET
-def external(name, args, result, calling_conv='c'):
+def external(name, args, result, calling_conv='c', **kwds):
return rffi.llexternal(name, args, result,
compilation_info=CConfig._compilation_info_,
calling_conv=calling_conv,
- sandboxsafe=True)
+ sandboxsafe=True, **kwds)
_lconv = lltype.Ptr(cConfig.lconv)
localeconv = external('localeconv', [], _lconv)
def numeric_formatting():
"""Specialized function to get formatting for numbers"""
+ return numeric_formatting_impl()
+
+def numeric_formatting_impl():
conv = localeconv()
decimal_point = rffi.charp2str(conv.c_decimal_point)
thousands_sep = rffi.charp2str(conv.c_thousands_sep)
grouping = rffi.charp2str(conv.c_grouping)
return decimal_point, thousands_sep, grouping
+def oo_numeric_formatting():
+ return '.', '', ''
+
+register_external(numeric_formatting, [], (str, str, str),
+ llimpl=numeric_formatting_impl,
+ ooimpl=oo_numeric_formatting,
+ sandboxsafe=True)
+
+
_setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP)
def setlocale(category, locale):
@@ -184,11 +197,11 @@
raise LocaleError("unsupported locale setting")
return rffi.charp2str(ll_result)
-isalpha = external('isalpha', [rffi.INT], rffi.INT)
-isupper = external('isupper', [rffi.INT], rffi.INT)
-islower = external('islower', [rffi.INT], rffi.INT)
-tolower = external('tolower', [rffi.INT], rffi.INT)
-isalnum = external('isalnum', [rffi.INT], rffi.INT)
+isalpha = external('isalpha', [rffi.INT], rffi.INT, oo_primitive='locale_isalpha')
+isupper = external('isupper', [rffi.INT], rffi.INT, oo_primitive='locale_isupper')
+islower = external('islower', [rffi.INT], rffi.INT, oo_primitive='locale_islower')
+tolower = external('tolower', [rffi.INT], rffi.INT, oo_primitive='locale_tolower')
+isalnum = external('isalnum', [rffi.INT], rffi.INT, oo_primitive='locale_isalnum')
if HAVE_LANGINFO:
_nl_langinfo = external('nl_langinfo', [rffi.INT], rffi.CCHARP)
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -14,7 +14,7 @@
modname, _ = modname.split('.', 1)
if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
'imp', 'sys', 'array', '_ffi', 'itertools', 'operator',
- '_socket', '_sre', '_lsprof']:
+ '_socket', '_sre', '_lsprof', '_file']:
return True
return False
diff --git a/pypy/translator/goal/targetpypystandalone.py b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -105,13 +105,6 @@
return parser
def handle_config(self, config, translateconfig):
- if config.translation.type_system == 'ootype':
- print
- print 'Translation to cli and jvm is known to be broken at the moment'
- print 'Please try the "cli-jit" branch at:'
- print 'http://codespeak.net/svn/pypy/branch/cli-jit/'
- sys.exit(1)
-
self.translateconfig = translateconfig
# set up the objspace optimizations based on the --opt argument
from pypy.config.pypyoption import set_pypy_opt_level
@@ -159,8 +152,8 @@
from pypy.config.pypyoption import enable_translationmodules
enable_translationmodules(config)
- if config.translation.type_system == 'ootype':
- config.objspace.usemodules.suggest(rbench=True)
+ ## if config.translation.type_system == 'ootype':
+ ## config.objspace.usemodules.suggest(rbench=True)
if config.translation.thread:
config.objspace.usemodules.thread = True
diff --git a/pypy/module/cpyext/include/compile.h b/pypy/module/cpyext/include/compile.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/compile.h
@@ -0,0 +1,13 @@
+#ifndef Py_COMPILE_H
+#define Py_COMPILE_H
+
+#include "code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_COMPILE_H */
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -522,7 +522,7 @@
return
code = frame.pycode
if frame.instr_lb <= frame.last_instr < frame.instr_ub:
- if frame.last_instr <= frame.instr_prev:
+ if frame.last_instr < frame.instr_prev_plus_one:
# We jumped backwards in the same line.
executioncontext._trace(frame, 'line', self.space.w_None)
else:
@@ -560,5 +560,5 @@
frame.f_lineno = line
executioncontext._trace(frame, 'line', self.space.w_None)
- frame.instr_prev = frame.last_instr
+ frame.instr_prev_plus_one = frame.last_instr + 1
self.space.frame_trace_action.fire() # continue tracing
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -42,3 +42,13 @@
assert arr[1:].tolist() == [2,3,4]
assert arr[:2].tolist() == [1,2]
assert arr[1:3].tolist() == [2,3]
+
+ def test_buffer(self):
+ module = self.import_module(name='array')
+ arr = module.array('i', [1,2,3,4])
+ # XXX big-endian
+ assert str(buffer(arr)) == ('\x01\0\0\0'
+ '\x02\0\0\0'
+ '\x03\0\0\0'
+ '\x04\0\0\0')
+
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -194,8 +194,8 @@
c_buf = py_str.c_ob_type.c_tp_as_buffer
assert c_buf
py_obj = rffi.cast(PyObject, py_str)
- assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(rffi.INTP.TO)) == 1
- ref = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+ assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(Py_ssize_tP.TO)) == 1
+ ref = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
assert c_buf.c_bf_getsegcount(py_obj, ref) == 1
assert ref[0] == 10
lltype.free(ref, flavor='raw')
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -201,6 +201,23 @@
assert cmpr == 3
assert cmpr != 42
+ def test_richcompare(self):
+ module = self.import_module("comparisons")
+ cmpr = module.CmpType()
+
+ # should not crash
+ cmpr < 4
+ cmpr <= 4
+ cmpr > 4
+ cmpr >= 4
+
+ assert cmpr.__le__(4) is NotImplemented
+
+ def test_tpcompare(self):
+ module = self.import_module("comparisons")
+ cmpr = module.OldCmpType()
+ assert cmpr < cmpr
+
def test_hash(self):
module = self.import_module("comparisons")
cmpr = module.CmpType()
diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test/test_pystate.py
--- a/pypy/module/cpyext/test/test_pystate.py
+++ b/pypy/module/cpyext/test/test_pystate.py
@@ -29,20 +29,14 @@
state = api.PyInterpreterState_Head()
assert nullptr(PyInterpreterState.TO) == api.PyInterpreterState_Next(state)
-def clear_threadstate(space):
- # XXX: this should collect the ThreadState memory
- del space.getexecutioncontext().cpyext_threadstate
-
class TestThreadState(BaseApiTest):
def test_thread_state_get(self, space, api):
ts = api.PyThreadState_Get()
assert ts != nullptr(PyThreadState.TO)
- clear_threadstate(space)
def test_thread_state_interp(self, space, api):
ts = api.PyThreadState_Get()
assert ts.c_interp == api.PyInterpreterState_Head()
- clear_threadstate(space)
def test_basic_threadstate_dance(self, space, api):
# Let extension modules call these functions,
@@ -54,5 +48,3 @@
api.PyEval_AcquireThread(tstate)
api.PyEval_ReleaseThread(tstate)
-
- clear_threadstate(space)
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -56,13 +56,10 @@
"""A frame is an environment supporting the execution of a code object.
Abstract base class."""
- def __init__(self, space, w_globals=None, numlocals=-1):
+ def __init__(self, space, w_globals=None):
self.space = space
self.w_globals = w_globals # wrapped dict of globals
self.w_locals = None # wrapped dict of locals
- if numlocals < 0: # compute the minimal size based on arguments
- numlocals = len(self.getcode().getvarnames())
- self.numlocals = numlocals
def run(self):
"Abstract method to override. Runs the frame"
@@ -96,6 +93,10 @@
where the order is according to self.getcode().signature()."""
raise TypeError, "abstract"
+ def getfastscopelength(self):
+ "Abstract. Get the expected number of locals."
+ raise TypeError, "abstract"
+
def fast2locals(self):
# Copy values from self.fastlocals_w to self.w_locals
if self.w_locals is None:
@@ -113,10 +114,11 @@
# Copy values from self.w_locals to self.fastlocals_w
assert self.w_locals is not None
varnames = self.getcode().getvarnames()
+ numlocals = self.getfastscopelength()
- new_fastlocals_w = [None]*self.numlocals
-
- for i in range(min(len(varnames), self.numlocals)):
+ new_fastlocals_w = [None] * numlocals
+
+ for i in range(min(len(varnames), numlocals)):
w_name = self.space.wrap(varnames[i])
try:
w_value = self.space.getitem(self.w_locals, w_name)
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
@@ -8,6 +8,8 @@
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.error import TyperError
+from pypy.rpython.ootypesystem import ootype
+
class SomeVRef(annmodel.SomeObject):
@@ -24,7 +26,10 @@
return self.s_instance
def rtyper_makerepr(self, rtyper):
- return vrefrepr
+ if rtyper.type_system.name == 'lltypesystem':
+ return vrefrepr
+ elif rtyper.type_system.name == 'ootypesystem':
+ return oovrefrepr
def rtyper_makekey(self):
return self.__class__,
@@ -54,4 +59,20 @@
" prebuilt virtual_ref")
return lltype.nullptr(OBJECTPTR.TO)
+from pypy.rpython.ootypesystem.rclass import OBJECT
+
+class OOVRefRepr(VRefRepr):
+ lowleveltype = OBJECT
+ def rtype_simple_call(self, hop):
+ [v] = hop.inputargs(self)
+ v = hop.genop('jit_force_virtual', [v], resulttype = OBJECT)
+ return hop.genop('oodowncast', [v], resulttype = hop.r_result)
+
+ def convert_const(self, value):
+ if value() is not None:
+ raise TypeError("only supports virtual_ref_None as a"
+ " prebuilt virtual_ref")
+ return ootype.ROOT._null
+
vrefrepr = VRefRepr()
+oovrefrepr = OOVRefRepr()
diff --git a/pypy/translator/cli/test/test_class.py b/pypy/translator/cli/test/test_class.py
--- a/pypy/translator/cli/test/test_class.py
+++ b/pypy/translator/cli/test/test_class.py
@@ -1,11 +1,8 @@
import py
from pypy.translator.cli.test.runtest import CliTest
-from pypy.translator.oosupport.test_template.class_ import BaseTestClass, BaseTestSpecialcase
+from pypy.translator.oosupport.test_template.class_ import BaseTestClass
# ====> ../../oosupport/test_template/class_.py
class TestCliClass(CliTest, BaseTestClass):
pass
-
-class TestCliSpecialCase(CliTest, BaseTestSpecialcase):
- pass
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -343,7 +343,11 @@
}
def final_check_config(config):
- pass
+ # XXX: this should be a real config option, but it is hard to refactor it;
+ # instead, we "just" patch it from here
+ from pypy.rlib import rfloat
+ if config.translation.type_system == 'ootype':
+ rfloat.USE_SHORT_FLOAT_REPR = False
def set_opt_level(config, level):
"""Apply optimization suggestions on the 'config'.
diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py
--- a/pypy/rlib/rfloat.py
+++ b/pypy/rlib/rfloat.py
@@ -4,6 +4,8 @@
from pypy.rpython.tool import rffi_platform
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.rlib import objectmodel
+from pypy.rpython.extfunc import register_external
+from pypy.annotation.model import SomeString
USE_SHORT_FLOAT_REPR = True # XXX make it a translation option?
@@ -24,16 +26,28 @@
globals().update(rffi_platform.configure(CConfig))
def rstring_to_float(s):
+ return rstring_to_float_impl(s)
+
+def rstring_to_float_impl(s):
if USE_SHORT_FLOAT_REPR:
from pypy.rlib.rdtoa import strtod
return strtod(s)
-
sign, before_point, after_point, exponent = break_up_float(s)
-
if not before_point and not after_point:
raise ValueError
+ return parts_to_float(sign, before_point, after_point, exponent)
- return parts_to_float(sign, before_point, after_point, exponent)
+def oo_rstring_to_float(s):
+ from pypy.rpython.annlowlevel import oostr
+ from pypy.rpython.ootypesystem import ootype
+ lls = oostr(s)
+ return ootype.ooparse_float(lls)
+
+register_external(rstring_to_float, [SomeString(can_be_None=False)], float,
+ llimpl=rstring_to_float_impl,
+ ooimpl=oo_rstring_to_float,
+ sandboxsafe=True)
+
# float as string -> sign, beforept, afterpt, exponent
def break_up_float(s):
diff --git a/pypy/translator/cli/src/debug.cs b/pypy/translator/cli/src/debug.cs
--- a/pypy/translator/cli/src/debug.cs
+++ b/pypy/translator/cli/src/debug.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Collections.Generic;
using System.Diagnostics;
// this code is modeled after translator/c/src/debug.h
@@ -21,7 +22,7 @@
static int have_debug_prints = -1;
static bool debug_ready = false;
static bool debug_profile = false;
- static string debug_prefix = null;
+ static string[] active_categories = null;
public static void close_file()
{
@@ -29,6 +30,14 @@
debug_file.Close();
}
+ public static bool startswithoneof(string category, string[] active_categories)
+ {
+ foreach(string cat in active_categories)
+ if (category.StartsWith(cat))
+ return true;
+ return false;
+ }
+
public static bool HAVE_DEBUG_PRINTS()
{
if ((have_debug_prints & 1) != 0) {
@@ -48,7 +57,8 @@
have_debug_prints <<= 1;
if (!debug_profile) {
/* non-profiling version */
- if (debug_prefix == null || !category.StartsWith(debug_prefix)) {
+ if (active_categories == null ||
+ !startswithoneof(category, active_categories)) {
/* wrong section name, or no PYPYLOG at all, skip it */
return;
}
@@ -83,7 +93,8 @@
}
else {
/* PYPYLOG=prefix:filename --- conditional logging */
- debug_prefix = filename.Substring(0, colon);
+ string debug_prefix = filename.Substring(0, colon);
+ active_categories = debug_prefix.Split(',');
filename = filename.Substring(colon+1);
}
if (filename != "-")
diff --git a/pypy/translator/backendopt/merge_if_blocks.py b/pypy/translator/backendopt/merge_if_blocks.py
--- a/pypy/translator/backendopt/merge_if_blocks.py
+++ b/pypy/translator/backendopt/merge_if_blocks.py
@@ -75,14 +75,19 @@
# False link
checkvar = [var for var in current.operations[-1].args
if isinstance(var, Variable)][0]
+ resvar = current.operations[-1].result
case = [var for var in current.operations[-1].args
if isinstance(var, Constant)][0]
- chain.append((current, case))
checkvars.append(checkvar)
falseexit = current.exits[0]
assert not falseexit.exitcase
trueexit = current.exits[1]
targetblock = falseexit.target
+ # if the result of the check is also passed through the link, we
+ # cannot construct the chain
+ if resvar in falseexit.args or resvar in trueexit.args:
+ break
+ chain.append((current, case))
if len(entrymap[targetblock]) != 1:
break
if checkvar not in falseexit.args:
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -4960,6 +4960,58 @@
p2 = new_with_vtable(ConstClass(node_vtable))
setfield_gc(p2, i1, descr=nextdescr)
"""
+ py.test.skip("no test here")
+
+ def test_immutable_not(self):
+ ops = """
+ []
+ p0 = new_with_vtable(ConstClass(intobj_noimmut_vtable))
+ setfield_gc(p0, 42, descr=noimmut_intval)
+ escape(p0)
+ jump()
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_immutable_variable(self):
+ ops = """
+ [i0]
+ p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+ setfield_gc(p0, i0, descr=immut_intval)
+ escape(p0)
+ jump(i0)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_immutable_incomplete(self):
+ ops = """
+ []
+ p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+ escape(p0)
+ jump()
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_immutable_constantfold(self):
+ ops = """
+ []
+ p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+ setfield_gc(p0, 1242, descr=immut_intval)
+ escape(p0)
+ jump()
+ """
+ from pypy.rpython.lltypesystem import lltype, llmemory
+ class IntObj1242(object):
+ _TYPE = llmemory.GCREF.TO
+ def __eq__(self, other):
+ return other.container.intval == 1242
+ self.namespace['intobj1242'] = lltype._ptr(llmemory.GCREF,
+ IntObj1242())
+ expected = """
+ []
+ escape(ConstPtr(intobj1242))
+ jump()
+ """
+ self.optimize_loop(ops, expected)
# ----------
def optimize_strunicode_loop(self, ops, optops, preamble=None):
diff --git a/pypy/rpython/test/test_rfloat.py b/pypy/rpython/test/test_rfloat.py
--- a/pypy/rpython/test/test_rfloat.py
+++ b/pypy/rpython/test/test_rfloat.py
@@ -156,6 +156,37 @@
return x
self.interpret(fn, [1.0, 2.0, 3.0])
+ def test_copysign(self):
+ import math
+ def fn(x, y):
+ return math.copysign(x, y)
+ assert self.interpret(fn, [42, -1]) == -42
+ assert self.interpret(fn, [42, -0.0]) == -42
+ assert self.interpret(fn, [42, 0.0]) == 42
+
+ def test_rstring_to_float(self):
+ from pypy.rlib.rfloat import rstring_to_float
+ def fn(i):
+ s = ['42.3', '123.4'][i]
+ return rstring_to_float(s)
+ assert self.interpret(fn, [0]) == 42.3
+
+ def test_isnan(self):
+ import math
+ def fn(x):
+ inf = x * x
+ nan = inf / inf
+ return math.isnan(nan)
+ assert self.interpret(fn, [1e200])
+
+ def test_isinf(self):
+ import math
+ def fn(x):
+ inf = x * x
+ return math.isinf(inf)
+ assert self.interpret(fn, [1e200])
+
+
class TestLLtype(BaseTestRfloat, LLRtypeMixin):
def test_hash(self):
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
@@ -514,12 +514,10 @@
break
else:
# all constant arguments: constant-fold away
- argboxes = [self.get_constant_box(op.getarg(i))
- for i in range(op.numargs())]
- resbox = execute_nonspec(self.cpu, None,
- op.getopnum(), argboxes, op.getdescr())
- # FIXME: Don't we need to check for an overflow here?
- self.make_constant(op.result, resbox.constbox())
+ resbox = self.constant_fold(op)
+ # note that INT_xxx_OVF is not done from here, and the
+ # overflows in the INT_xxx operations are ignored
+ self.make_constant(op.result, resbox)
return
# did we do the exact same operation already?
@@ -538,6 +536,13 @@
if nextop:
self.emit_operation(nextop)
+ def constant_fold(self, op):
+ argboxes = [self.get_constant_box(op.getarg(i))
+ for i in range(op.numargs())]
+ resbox = execute_nonspec(self.cpu, None,
+ op.getopnum(), argboxes, op.getdescr())
+ return resbox.constbox()
+
#def optimize_GUARD_NO_OVERFLOW(self, op):
# # otherwise the default optimizer will clear fields, which is unwanted
# # in this case
diff --git a/pypy/translator/cli/test/test_list.py b/pypy/translator/cli/test/test_list.py
--- a/pypy/translator/cli/test/test_list.py
+++ b/pypy/translator/cli/test/test_list.py
@@ -7,7 +7,10 @@
def test_recursive(self):
py.test.skip("CLI doesn't support recursive lists")
- def test_getitem_exc(self):
+ def test_getitem_exc_1(self):
+ py.test.skip('fixme!')
+
+ def test_getitem_exc_2(self):
py.test.skip('fixme!')
def test_list_unsigned(self):
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
@@ -860,15 +860,27 @@
self.PerformDiscard(op, arglocs)
self.rm.possibly_free_vars_for_op(op)
- def _fastpath_malloc(self, op, descr):
+ def fastpath_malloc_fixedsize(self, op, descr):
assert isinstance(descr, BaseSizeDescr)
+ self._do_fastpath_malloc(op, descr.size, descr.tid)
+
+ def fastpath_malloc_varsize(self, op, arraydescr, num_elem):
+ assert isinstance(arraydescr, BaseArrayDescr)
+ ofs_length = arraydescr.get_ofs_length(self.translate_support_code)
+ basesize = arraydescr.get_base_size(self.translate_support_code)
+ itemsize = arraydescr.get_item_size(self.translate_support_code)
+ size = basesize + itemsize * num_elem
+ self._do_fastpath_malloc(op, size, arraydescr.tid)
+ self.assembler.set_new_array_length(eax, ofs_length, imm(num_elem))
+
+ def _do_fastpath_malloc(self, op, size, tid):
gc_ll_descr = self.assembler.cpu.gc_ll_descr
self.rm.force_allocate_reg(op.result, selected_reg=eax)
if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
# ---- shadowstack ----
# We need edx as a temporary, but otherwise don't save any more
- # register. See comments in _build_malloc_fixedsize_slowpath().
+ # register. See comments in _build_malloc_slowpath().
tmp_box = TempBox()
self.rm.force_allocate_reg(tmp_box, selected_reg=edx)
self.rm.possibly_free_var(tmp_box)
@@ -885,16 +897,16 @@
self.rm.force_allocate_reg(tmp_box, selected_reg=reg)
self.rm.possibly_free_var(tmp_box)
- self.assembler.malloc_cond_fixedsize(
+ self.assembler.malloc_cond(
gc_ll_descr.get_nursery_free_addr(),
gc_ll_descr.get_nursery_top_addr(),
- descr.size, descr.tid,
+ size, tid,
)
def consider_new(self, op):
gc_ll_descr = self.assembler.cpu.gc_ll_descr
if gc_ll_descr.can_inline_malloc(op.getdescr()):
- self._fastpath_malloc(op, op.getdescr())
+ self.fastpath_malloc_fixedsize(op, op.getdescr())
else:
args = gc_ll_descr.args_for_new(op.getdescr())
arglocs = [imm(x) for x in args]
@@ -904,7 +916,7 @@
classint = op.getarg(0).getint()
descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint)
if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize):
- self._fastpath_malloc(op, descrsize)
+ self.fastpath_malloc_fixedsize(op, descrsize)
self.assembler.set_vtable(eax, imm(classint))
# result of fastpath malloc is in eax
else:
@@ -963,16 +975,25 @@
gc_ll_descr = self.assembler.cpu.gc_ll_descr
if gc_ll_descr.get_funcptr_for_newarray is not None:
# framework GC
- args = self.assembler.cpu.gc_ll_descr.args_for_new_array(op.getdescr())
+ box_num_elem = op.getarg(0)
+ if isinstance(box_num_elem, ConstInt):
+ num_elem = box_num_elem.value
+ if gc_ll_descr.can_inline_malloc_varsize(op.getdescr(),
+ num_elem):
+ self.fastpath_malloc_varsize(op, op.getdescr(), num_elem)
+ return
+ args = self.assembler.cpu.gc_ll_descr.args_for_new_array(
+ op.getdescr())
arglocs = [imm(x) for x in args]
- arglocs.append(self.loc(op.getarg(0)))
- return self._call(op, arglocs)
+ arglocs.append(self.loc(box_num_elem))
+ self._call(op, arglocs)
+ return
# boehm GC (XXX kill the following code at some point)
itemsize, basesize, ofs_length, _, _ = (
self._unpack_arraydescr(op.getdescr()))
scale_of_field = _get_scale(itemsize)
- return self._malloc_varsize(basesize, ofs_length, scale_of_field,
- op.getarg(0), op.result)
+ self._malloc_varsize(basesize, ofs_length, scale_of_field,
+ op.getarg(0), op.result)
def _unpack_arraydescr(self, arraydescr):
assert isinstance(arraydescr, BaseArrayDescr)
diff --git a/pypy/interpreter/test/test_eval.py b/pypy/interpreter/test/test_eval.py
--- a/pypy/interpreter/test/test_eval.py
+++ b/pypy/interpreter/test/test_eval.py
@@ -13,7 +13,8 @@
def __init__(self, space, code, numlocals):
self.code = code
- Frame.__init__(self, space, numlocals=numlocals)
+ Frame.__init__(self, space)
+ self.numlocals = numlocals
self.fastlocals_w = [None] * self.numlocals
def getcode(self):
@@ -24,7 +25,10 @@
def getfastscope(self):
return self.fastlocals_w
-
+
+ def getfastscopelength(self):
+ return self.numlocals
+
self.f = ConcreteFastscopeFrame(self.space, code, numlocals=5)
diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -110,6 +110,8 @@
#include "intobject.h"
#include "listobject.h"
#include "unicodeobject.h"
+#include "compile.h"
+#include "frameobject.h"
#include "eval.h"
#include "pymem.h"
#include "pycobject.h"
diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -578,6 +578,26 @@
res = self.interpret(fn, [3, 3])
assert res == 123
+ def test_dict_popitem(self):
+ def func():
+ d = {}
+ d[5] = 2
+ d[6] = 3
+ k1, v1 = d.popitem()
+ assert len(d) == 1
+ k2, v2 = d.popitem()
+ try:
+ d.popitem()
+ except KeyError:
+ pass
+ else:
+ assert 0, "should have raised KeyError"
+ assert len(d) == 0
+ return k1*1000 + v1*100 + k2*10 + v2
+
+ res = self.interpret(func, [])
+ assert res in [5263, 6352]
+
class TestLLtype(BaseTestRdict, LLRtypeMixin):
def test_dict_but_not_with_char_keys(self):
@@ -682,26 +702,6 @@
# if it does not crash, we are fine. It crashes if you forget the hash field.
self.interpret(func, [])
- def test_dict_popitem(self):
- def func():
- d = {}
- d[5] = 2
- d[6] = 3
- k1, v1 = d.popitem()
- assert len(d) == 1
- k2, v2 = d.popitem()
- try:
- d.popitem()
- except KeyError:
- pass
- else:
- assert 0, "should have raised KeyError"
- assert len(d) == 0
- return k1*1000 + v1*100 + k2*10 + v2
-
- res = self.interpret(func, [])
- assert res in [5263, 6352]
-
# ____________________________________________________________
def test_opt_nullkeymarker(self):
diff --git a/pypy/translator/cli/opcodes.py b/pypy/translator/cli/opcodes.py
--- a/pypy/translator/cli/opcodes.py
+++ b/pypy/translator/cli/opcodes.py
@@ -71,6 +71,8 @@
'hint': [PushArg(0), StoreResult],
'direct_call': [Call],
'indirect_call': [IndirectCall],
+ 'int_between': [PushAllArgs, 'call bool [pypylib]pypy.runtime.Utils::IntBetween(int32, int32, int32)'],
+
'cast_ptr_to_weakadr': [PushAllArgs, 'newobj instance void class %s::.ctor(object)' % WEAKREF],
'gc__collect': 'call void class [mscorlib]System.GC::Collect()',
@@ -147,7 +149,10 @@
'cast_float_to_uint': 'conv.u4',
'cast_longlong_to_float': 'conv.r8',
'cast_float_to_longlong': 'conv.i8',
+ 'cast_ulonglong_to_float': 'conv.r8',
+ 'cast_float_to_ulonglong': 'conv.u8',
'cast_primitive': [PushAllArgs, CastPrimitive],
+ 'force_cast': [PushAllArgs, CastPrimitive],
'truncate_longlong_to_int': 'conv.i4',
}
@@ -266,6 +271,8 @@
'ullong_ge': _not('clt.un'),
'ullong_lshift': [PushAllArgs, 'conv.u4', 'shl'],
'ullong_rshift': [PushAllArgs, 'conv.i4', 'shr'],
+ 'ullong_and': 'and',
+ 'ullong_or': 'or',
'oois': 'ceq',
'ooisnot': _not('ceq'),
diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -496,6 +496,13 @@
res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy())
assert res == 123
+ def test_force_cast(self):
+ def llfn(v):
+ return rffi.cast(rffi.SHORT, v)
+ res = self.interpret(llfn, [0x12345678])
+ assert res == 0x5678
+
+
class TestLLtype(BaseTestRbuiltin, LLRtypeMixin):
def test_isinstance_obj(self):
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -12,7 +12,6 @@
W_IOBase, DEFAULT_BUFFER_SIZE, convert_size,
check_readable_w, check_writable_w, check_seekable_w)
from pypy.module._io.interp_io import W_BlockingIOError
-from pypy.module.thread.os_lock import Lock
STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
@@ -121,7 +120,7 @@
## XXX cannot free a Lock?
## if self.lock:
## self.lock.free()
- self.lock = Lock(space)
+ self.lock = space.allocate_lock()
try:
self._raw_tell(space)
diff --git a/pypy/jit/backend/x86/test/test_gc_integration.py b/pypy/jit/backend/x86/test/test_gc_integration.py
--- a/pypy/jit/backend/x86/test/test_gc_integration.py
+++ b/pypy/jit/backend/x86/test/test_gc_integration.py
@@ -45,7 +45,8 @@
get_funcptr_for_newarray = get_funcptr_for_new
get_funcptr_for_newstr = get_funcptr_for_new
get_funcptr_for_newunicode = get_funcptr_for_new
-
+ get_malloc_slowpath_addr = None
+
moving_gc = True
gcrootmap = MockGcRootMap()
@@ -167,26 +168,29 @@
class GCDescrFastpathMalloc(GcLLDescription):
gcrootmap = None
-
+ expected_malloc_slowpath_size = WORD*2
+
def __init__(self):
GcCache.__init__(self, False)
# create a nursery
NTP = rffi.CArray(lltype.Signed)
self.nursery = lltype.malloc(NTP, 16, flavor='raw')
- self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 2,
+ self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 3,
flavor='raw')
self.addrs[0] = rffi.cast(lltype.Signed, self.nursery)
- self.addrs[1] = self.addrs[0] + 64
- # 64 bytes
+ self.addrs[1] = self.addrs[0] + 16*WORD
+ self.addrs[2] = 0
+ # 16 WORDs
def malloc_slowpath(size):
- assert size == WORD*2
+ assert size == self.expected_malloc_slowpath_size
nadr = rffi.cast(lltype.Signed, self.nursery)
self.addrs[0] = nadr + size
+ self.addrs[2] += 1
return nadr
self.malloc_slowpath = malloc_slowpath
self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed],
lltype.Signed)
- self._counter = 123
+ self._counter = 123000
def can_inline_malloc(self, descr):
return True
@@ -205,7 +209,7 @@
def get_nursery_top_addr(self):
return rffi.cast(lltype.Signed, self.addrs) + WORD
- def get_malloc_fixedsize_slowpath_addr(self):
+ def get_malloc_slowpath_addr(self):
fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath)
return rffi.cast(lltype.Signed, fptr)
@@ -221,9 +225,11 @@
cpu.gc_ll_descr = GCDescrFastpathMalloc()
cpu.setup_once()
- NODE = lltype.Struct('node', ('tid', lltype.Signed),
- ('value', lltype.Signed))
- nodedescr = cpu.sizeof(NODE) # xxx hack: NODE is not a GcStruct
+ # hack: specify 'tid' explicitly, because this test is not running
+ # with the gc transformer
+ NODE = lltype.GcStruct('node', ('tid', lltype.Signed),
+ ('value', lltype.Signed))
+ nodedescr = cpu.sizeof(NODE)
valuedescr = cpu.fielddescrof(NODE, 'value')
self.cpu = cpu
@@ -255,6 +261,7 @@
assert gc_ll_descr.nursery[1] == 42
nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*2)
+ assert gc_ll_descr.addrs[2] == 0 # slowpath never called
def test_malloc_slowpath(self):
ops = '''
@@ -275,6 +282,7 @@
gc_ll_descr = self.cpu.gc_ll_descr
nadr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
assert gc_ll_descr.addrs[0] == nadr + (WORD*2)
+ assert gc_ll_descr.addrs[2] == 1 # slowpath called once
def test_new_with_vtable(self):
ops = '''
@@ -290,3 +298,93 @@
assert gc_ll_descr.nursery[1] == self.vtable_int
nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*3)
+ assert gc_ll_descr.addrs[2] == 0 # slowpath never called
+
+
+class Seen(Exception):
+ pass
+
+class GCDescrFastpathMallocVarsize(GCDescrFastpathMalloc):
+ def can_inline_malloc_varsize(self, arraydescr, num_elem):
+ return num_elem < 5
+ def get_funcptr_for_newarray(self):
+ return 52
+ def init_array_descr(self, A, descr):
+ descr.tid = self._counter
+ self._counter += 1
+ def args_for_new_array(self, descr):
+ raise Seen("args_for_new_array")
+
+class TestMallocVarsizeFastpath(BaseTestRegalloc):
+ def setup_method(self, method):
+ cpu = CPU(None, None)
+ cpu.vtable_offset = WORD
+ cpu.gc_ll_descr = GCDescrFastpathMallocVarsize()
+ cpu.setup_once()
+ self.cpu = cpu
+
+ ARRAY = lltype.GcArray(lltype.Signed)
+ arraydescr = cpu.arraydescrof(ARRAY)
+ self.arraydescr = arraydescr
+
+ self.namespace = locals().copy()
+
+ def test_malloc_varsize_fastpath(self):
+ # Hack. Running the GcLLDescr_framework without really having
+ # a complete GC means that we end up with both the tid and the
+ # length being at offset 0. In this case, so the length overwrites
+ # the tid. This is of course only the case in this test class.
+ ops = '''
+ []
+ p0 = new_array(4, descr=arraydescr)
+ setarrayitem_gc(p0, 0, 142, descr=arraydescr)
+ setarrayitem_gc(p0, 3, 143, descr=arraydescr)
+ finish(p0)
+ '''
+ self.interpret(ops, [])
+ # check the nursery
+ gc_ll_descr = self.cpu.gc_ll_descr
+ assert gc_ll_descr.nursery[0] == 4
+ assert gc_ll_descr.nursery[1] == 142
+ assert gc_ll_descr.nursery[4] == 143
+ nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
+ assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*5)
+ assert gc_ll_descr.addrs[2] == 0 # slowpath never called
+
+ def test_malloc_varsize_slowpath(self):
+ ops = '''
+ []
+ p0 = new_array(4, descr=arraydescr)
+ setarrayitem_gc(p0, 0, 420, descr=arraydescr)
+ setarrayitem_gc(p0, 3, 430, descr=arraydescr)
+ p1 = new_array(4, descr=arraydescr)
+ setarrayitem_gc(p1, 0, 421, descr=arraydescr)
+ setarrayitem_gc(p1, 3, 431, descr=arraydescr)
+ p2 = new_array(4, descr=arraydescr)
+ setarrayitem_gc(p2, 0, 422, descr=arraydescr)
+ setarrayitem_gc(p2, 3, 432, descr=arraydescr)
+ p3 = new_array(4, descr=arraydescr)
+ setarrayitem_gc(p3, 0, 423, descr=arraydescr)
+ setarrayitem_gc(p3, 3, 433, descr=arraydescr)
+ finish(p0, p1, p2, p3)
+ '''
+ gc_ll_descr = self.cpu.gc_ll_descr
+ gc_ll_descr.expected_malloc_slowpath_size = 5*WORD
+ self.interpret(ops, [])
+ assert gc_ll_descr.addrs[2] == 1 # slowpath called once
+
+ def test_malloc_varsize_too_big(self):
+ ops = '''
+ []
+ p0 = new_array(5, descr=arraydescr)
+ finish(p0)
+ '''
+ py.test.raises(Seen, self.interpret, ops, [])
+
+ def test_malloc_varsize_variable(self):
+ ops = '''
+ [i0]
+ p0 = new_array(i0, descr=arraydescr)
+ finish(p0)
+ '''
+ py.test.raises(Seen, self.interpret, ops, [])
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -91,9 +91,10 @@
else:
# XXX that's slow
def case_ok(filename):
- index1 = filename.rfind(os.sep)
- index2 = filename.rfind(os.altsep)
- index = max(index1, index2)
+ index = filename.rfind(os.sep)
+ if os.altsep is not None:
+ index2 = filename.rfind(os.altsep)
+ index = max(index, index2)
if index < 0:
directory = os.curdir
else:
@@ -118,107 +119,6 @@
def check_sys_modules_w(space, modulename):
return space.finditem_str(space.sys.get('modules'), modulename)
-def _get_relative_name(space, modulename, level, w_globals):
- w = space.wrap
- ctxt_w_package = space.finditem(w_globals, w('__package__'))
-
- ctxt_package = None
- if ctxt_w_package is not None and ctxt_w_package is not space.w_None:
- try:
- ctxt_package = space.str_w(ctxt_w_package)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise OperationError(space.w_ValueError, space.wrap(
- "__package__ set to non-string"))
-
- if ctxt_package is not None:
- # __package__ is set, so use it
- if ctxt_package == '' and level < 0:
- return None, 0
-
- package_parts = ctxt_package.split('.')
- while level > 1 and package_parts:
- level -= 1
- package_parts.pop()
- if not package_parts:
- if len(ctxt_package) == 0:
- msg = "Attempted relative import in non-package"
- else:
- msg = "Attempted relative import beyond toplevel package"
- raise OperationError(space.w_ValueError, w(msg))
-
- # Try to import parent package
- try:
- w_parent = absolute_import(space, ctxt_package, 0,
- None, tentative=False)
- except OperationError, e:
- if not e.match(space, space.w_ImportError):
- raise
- if level > 0:
- raise OperationError(space.w_SystemError, space.wrap(
- "Parent module '%s' not loaded, "
- "cannot perform relative import" % ctxt_package))
- else:
- space.warn("Parent module '%s' not found "
- "while handling absolute import" % ctxt_package,
- space.w_RuntimeWarning)
-
- rel_level = len(package_parts)
- if modulename:
- package_parts.append(modulename)
- rel_modulename = '.'.join(package_parts)
- else:
- # __package__ not set, so figure it out and set it
- ctxt_w_name = space.finditem(w_globals, w('__name__'))
- ctxt_w_path = space.finditem(w_globals, w('__path__'))
-
- ctxt_name = None
- if ctxt_w_name is not None:
- try:
- ctxt_name = space.str_w(ctxt_w_name)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
-
- if not ctxt_name:
- return None, 0
-
- ctxt_name_prefix_parts = ctxt_name.split('.')
- if level > 0:
- n = len(ctxt_name_prefix_parts)-level+1
- assert n>=0
- ctxt_name_prefix_parts = ctxt_name_prefix_parts[:n]
- if ctxt_name_prefix_parts and ctxt_w_path is None: # plain module
- ctxt_name_prefix_parts.pop()
-
- if level > 0 and not ctxt_name_prefix_parts:
- msg = "Attempted relative import in non-package"
- raise OperationError(space.w_ValueError, w(msg))
-
- rel_modulename = '.'.join(ctxt_name_prefix_parts)
-
- if ctxt_w_path is not None:
- # __path__ is set, so __name__ is already the package name
- space.setitem(w_globals, w("__package__"), ctxt_w_name)
- else:
- # Normal module, so work out the package name if any
- if '.' not in ctxt_name:
- space.setitem(w_globals, w("__package__"), space.w_None)
- elif rel_modulename:
- space.setitem(w_globals, w("__package__"), w(rel_modulename))
-
- if modulename:
- if rel_modulename:
- rel_modulename += '.' + modulename
- else:
- rel_modulename = modulename
-
- rel_level = len(ctxt_name_prefix_parts)
-
- return rel_modulename, rel_level
-
-
@unwrap_spec(name=str, level=int)
def importhook(space, name, w_globals=None,
w_locals=None, w_fromlist=None, level=-1):
@@ -240,40 +140,68 @@
w_globals is not None and
space.isinstance_w(w_globals, space.w_dict)):
- rel_modulename, rel_level = _get_relative_name(space, modulename, level, w_globals)
+ ctxt_w_name = space.finditem(w_globals, w('__name__'))
+ ctxt_w_path = space.finditem(w_globals, w('__path__'))
- if rel_modulename:
- # if no level was set, ignore import errors, and
- # fall back to absolute import at the end of the
- # function.
- if level == -1:
- tentative = True
- else:
- tentative = False
+ ctxt_name = None
+ if ctxt_w_name is not None:
+ try:
+ ctxt_name = space.str_w(ctxt_w_name)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
- w_mod = absolute_import(space, rel_modulename, rel_level,
- fromlist_w, tentative=tentative)
- if w_mod is not None:
- space.timer.stop_name("importhook", modulename)
- return w_mod
+ if ctxt_name is not None:
+ ctxt_name_prefix_parts = ctxt_name.split('.')
+ if level > 0:
+ n = len(ctxt_name_prefix_parts)-level+1
+ assert n>=0
+ ctxt_name_prefix_parts = ctxt_name_prefix_parts[:n]
+ if ctxt_name_prefix_parts and ctxt_w_path is None: # plain module
+ ctxt_name_prefix_parts.pop()
+ if ctxt_name_prefix_parts:
+ rel_modulename = '.'.join(ctxt_name_prefix_parts)
+ if modulename:
+ rel_modulename += '.' + modulename
+ baselevel = len(ctxt_name_prefix_parts)
+ if rel_modulename is not None:
+ # XXX What is this check about? There is no test for it
+ w_mod = check_sys_modules(space, w(rel_modulename))
- w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0)
+ if (w_mod is None or
+ not space.is_w(w_mod, space.w_None) or
+ level > 0):
+
+ # if no level was set, ignore import errors, and
+ # fall back to absolute import at the end of the
+ # function.
+ if level == -1:
+ tentative = True
+ else:
+ tentative = False
+
+ w_mod = absolute_import(space, rel_modulename,
+ baselevel, fromlist_w,
+ tentative=tentative)
+ if w_mod is not None:
+ space.timer.stop_name("importhook", modulename)
+ return w_mod
+ else:
+ rel_modulename = None
+
+ if level > 0:
+ msg = "Attempted relative import in non-package"
+ raise OperationError(space.w_ValueError, w(msg))
+ w_mod = absolute_import_try(space, modulename, 0, fromlist_w)
+ if w_mod is None or space.is_w(w_mod, space.w_None):
+ w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0)
if rel_modulename is not None:
space.setitem(space.sys.get('modules'), w(rel_modulename), space.w_None)
space.timer.stop_name("importhook", modulename)
return w_mod
+ at jit.dont_look_inside
def absolute_import(space, modulename, baselevel, fromlist_w, tentative):
- # Short path: check in sys.modules
- w_mod = absolute_import_try(space, modulename, baselevel, fromlist_w)
- if w_mod is not None and not space.is_w(w_mod, space.w_None):
- return w_mod
- return absolute_import_with_lock(space, modulename, baselevel,
- fromlist_w, tentative)
-
- at jit.dont_look_inside
-def absolute_import_with_lock(space, modulename, baselevel,
- fromlist_w, tentative):
lock = getimportlock(space)
lock.acquire_lock()
try:
diff --git a/pypy/jit/backend/llsupport/test/test_descr.py b/pypy/jit/backend/llsupport/test/test_descr.py
--- a/pypy/jit/backend/llsupport/test/test_descr.py
+++ b/pypy/jit/backend/llsupport/test/test_descr.py
@@ -18,12 +18,33 @@
descr_t = get_size_descr(c0, T)
assert descr_s.size == symbolic.get_size(S, False)
assert descr_t.size == symbolic.get_size(T, False)
+ assert descr_s.count_fields_if_immutable() == -1
+ assert descr_t.count_fields_if_immutable() == -1
assert descr_s == get_size_descr(c0, S)
assert descr_s != get_size_descr(c1, S)
#
descr_s = get_size_descr(c1, S)
assert isinstance(descr_s.size, Symbolic)
+ assert descr_s.count_fields_if_immutable() == -1
+def test_get_size_descr_immut():
+ S = lltype.GcStruct('S', hints={'immutable': True})
+ T = lltype.GcStruct('T', ('parent', S),
+ ('x', lltype.Char),
+ hints={'immutable': True})
+ U = lltype.GcStruct('U', ('parent', T),
+ ('u', lltype.Ptr(T)),
+ ('v', lltype.Signed),
+ hints={'immutable': True})
+ V = lltype.GcStruct('V', ('parent', U),
+ ('miss1', lltype.Void),
+ ('miss2', lltype.Void),
+ hints={'immutable': True})
+ for STRUCT, expected in [(S, 0), (T, 1), (U, 3), (V, 3)]:
+ for translated in [False, True]:
+ c0 = GcCache(translated)
+ descr_s = get_size_descr(c0, STRUCT)
+ assert descr_s.count_fields_if_immutable() == expected
def test_get_field_descr():
U = lltype.Struct('U')
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -43,9 +43,14 @@
class SizeDescr(AbstractDescr):
size = 0 # help translation
+ is_immutable = False
- def __init__(self, size):
+ def __init__(self, size, count_fields_if_immut=-1):
self.size = size
+ self.count_fields_if_immut = count_fields_if_immut
+
+ def count_fields_if_immutable(self):
+ return self.count_fields_if_immut
def repr_of_descr(self):
return '<SizeDescr %s>' % self.size
@@ -62,15 +67,15 @@
return cache[STRUCT]
except KeyError:
size = symbolic.get_size(STRUCT, gccache.translate_support_code)
+ count_fields_if_immut = heaptracker.count_fields_if_immutable(STRUCT)
if heaptracker.has_gcstruct_a_vtable(STRUCT):
- sizedescr = SizeDescrWithVTable(size)
+ sizedescr = SizeDescrWithVTable(size, count_fields_if_immut)
else:
- sizedescr = SizeDescr(size)
+ sizedescr = SizeDescr(size, count_fields_if_immut)
gccache.init_size_descr(STRUCT, sizedescr)
cache[STRUCT] = sizedescr
return sizedescr
-
# ____________________________________________________________
# FieldDescrs
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -174,6 +174,17 @@
assert api.PyObject_Compare(space.wrap(72), space.wrap(42)) == 1
assert api.PyObject_Compare(space.wrap("a"), space.wrap("a")) == 0
+ def test_cmp(self, space, api):
+ w = space.wrap
+ with lltype.scoped_alloc(rffi.INTP.TO, 1) as ptr:
+ assert api.PyObject_Cmp(w(42), w(72), ptr) == 0
+ assert ptr[0] == -1
+ assert api.PyObject_Cmp(w("a"), w("a"), ptr) == 0
+ assert ptr[0] == 0
+ assert api.PyObject_Cmp(w(u"\xe9"), w("\xe9"), ptr) < 0
+ assert api.PyErr_Occurred()
+ api.PyErr_Clear()
+
def test_unicode(self, space, api):
assert space.unwrap(api.PyObject_Unicode(space.wrap([]))) == u"[]"
assert space.unwrap(api.PyObject_Unicode(space.wrap("e"))) == u"e"
diff --git a/pypy/module/cpyext/test/comparisons.c b/pypy/module/cpyext/test/comparisons.c
--- a/pypy/module/cpyext/test/comparisons.c
+++ b/pypy/module/cpyext/test/comparisons.c
@@ -69,12 +69,31 @@
};
+static int cmp_compare(PyObject *self, PyObject *other) {
+ return -1;
+}
+
+PyTypeObject OldCmpType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "comparisons.OldCmpType", /* tp_name */
+ sizeof(CmpObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)cmp_compare, /* tp_compare */
+};
+
+
void initcomparisons(void)
{
PyObject *m, *d;
if (PyType_Ready(&CmpType) < 0)
return;
+ if (PyType_Ready(&OldCmpType) < 0)
+ return;
m = Py_InitModule("comparisons", NULL);
if (m == NULL)
return;
@@ -83,4 +102,6 @@
return;
if (PyDict_SetItemString(d, "CmpType", (PyObject *)&CmpType) < 0)
return;
+ if (PyDict_SetItemString(d, "OldCmpType", (PyObject *)&OldCmpType) < 0)
+ return;
}
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -262,6 +262,8 @@
signal(SIGALRM, SIG_DFL)
class AppTestItimer:
+ spaceconfig = dict(usemodules=['signal'])
+
def test_itimer_real(self):
import signal
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
@@ -250,7 +250,6 @@
# this is the ticker check generated in PyFrame.handle_operation_error
exc_ticker_check = """
ticker2 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
- setfield_gc(_, _, descr=<GcPtrFieldDescr pypy.interpreter.pyframe.PyFrame.inst_w_f_trace .*>)
ticker_cond1 = int_lt(ticker2, 0)
guard_false(ticker_cond1, descr=...)
"""
@@ -266,7 +265,7 @@
if exp_v2 == '_':
return True
if self.is_const(v1) or self.is_const(exp_v2):
- return v1 == exp_v2
+ return v1[:-1].startswith(exp_v2[:-1])
if v1 not in self.alpha_map:
self.alpha_map[v1] = exp_v2
return self.alpha_map[v1] == exp_v2
diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -3,6 +3,7 @@
import py
from py.test import skip
import sys, os, re
+import subprocess
class BytecodeTrace(list):
def get_opnames(self, prefix=""):
@@ -116,13 +117,12 @@
print >> f, "print 'OK :-)'"
f.close()
- if sys.platform.startswith('win'):
- py.test.skip("XXX this is not Windows-friendly")
print logfilepath
- child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
- logfilepath, self.pypy_c, filepath), 'r')
- result = child_stdout.read()
- child_stdout.close()
+ env = os.environ.copy()
+ env['PYPYLOG'] = ":%s" % (logfilepath,)
+ p = subprocess.Popen([self.pypy_c, str(filepath)],
+ env=env, stdout=subprocess.PIPE)
+ result, _ = p.communicate()
assert result
if result.strip().startswith('SKIP:'):
py.test.skip(result.strip())
diff --git a/pypy/rpython/test/test_rint.py b/pypy/rpython/test/test_rint.py
--- a/pypy/rpython/test/test_rint.py
+++ b/pypy/rpython/test/test_rint.py
@@ -4,7 +4,7 @@
from pypy.annotation import model as annmodel
from pypy.rpython.test import snippet
from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
-from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask
+from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask, int_between
from pypy.rlib import objectmodel
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
@@ -215,6 +215,14 @@
assert res == f(inttype(0))
assert type(res) == inttype
+ def test_and_or(self):
+ inttypes = [int, r_uint, r_int64, r_ulonglong]
+ for inttype in inttypes:
+ def f(a, b, c):
+ return a&b|c
+ res = self.interpret(f, [inttype(0x1234), inttype(0x00FF), inttype(0x5600)])
+ assert res == f(0x1234, 0x00FF, 0x5600)
+
def test_neg_abs_ovf(self):
for op in (operator.neg, abs):
def f(x):
@@ -388,6 +396,18 @@
else:
assert res == 123456789012345678
+ def test_int_between(self):
+ def fn(a, b, c):
+ return int_between(a, b, c)
+ assert self.interpret(fn, [1, 1, 3])
+ assert self.interpret(fn, [1, 2, 3])
+ assert not self.interpret(fn, [1, 0, 2])
+ assert not self.interpret(fn, [1, 5, 2])
+ assert not self.interpret(fn, [1, 2, 2])
+ assert not self.interpret(fn, [1, 1, 1])
+
+
+
class TestLLtype(BaseTestRint, LLRtypeMixin):
pass
diff --git a/pypy/jit/codewriter/heaptracker.py b/pypy/jit/codewriter/heaptracker.py
--- a/pypy/jit/codewriter/heaptracker.py
+++ b/pypy/jit/codewriter/heaptracker.py
@@ -10,6 +10,30 @@
def int2adr(int):
return llmemory.cast_int_to_adr(int)
+def count_fields_if_immutable(STRUCT):
+ assert isinstance(STRUCT, lltype.GcStruct)
+ if STRUCT._hints.get('immutable', False):
+ try:
+ return _count_fields(STRUCT)
+ except ValueError:
+ pass
+ return -1
+
+def _count_fields(STRUCT):
+ if STRUCT == rclass.OBJECT:
+ return 0 # don't count 'typeptr'
+ result = 0
+ for fieldname, TYPE in STRUCT._flds.items():
+ if TYPE is lltype.Void:
+ pass # ignore Voids
+ elif not isinstance(TYPE, lltype.ContainerType):
+ result += 1
+ elif isinstance(TYPE, lltype.GcStruct):
+ result += _count_fields(TYPE)
+ else:
+ raise ValueError(TYPE)
+ return result
+
# ____________________________________________________________
def has_gcstruct_a_vtable(GCSTRUCT):
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -13,7 +13,7 @@
and not p.basename.startswith('test')]
essential_modules = dict.fromkeys(
- ["exceptions", "_file", "sys", "__builtin__", "posix", "signal"]
+ ["exceptions", "_file", "sys", "__builtin__", "posix"]
)
default_modules = essential_modules.copy()
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -5,6 +5,25 @@
import os, sys
exec 'import %s as posix' % os.name
+# this is the list of function which is *not* present in the posix module of
+# IronPython 2.6, and that we want to ignore for now
+lltype_only_defs = [
+ 'chown', 'chroot', 'closerange', 'confstr', 'confstr_names', 'ctermid', 'dup',
+ 'dup2', 'execv', 'execve', 'fchdir', 'fchmod', 'fchown', 'fdatasync', 'fork',
+ 'forkpty', 'fpathconf', 'fstatvfs', 'fsync', 'ftruncate', 'getegid', 'geteuid',
+ 'getgid', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getppid',
+ 'getsid', 'getuid', 'kill', 'killpg', 'lchown', 'link', 'lseek', 'major',
+ 'makedev', 'minor', 'mkfifo', 'mknod', 'nice', 'openpty', 'pathconf', 'pathconf_names',
+ 'pipe', 'readlink', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp',
+ 'setregid', 'setreuid', 'setsid', 'setuid', 'stat_float_times', 'statvfs',
+ 'statvfs_result', 'symlink', 'sysconf', 'sysconf_names', 'tcgetpgrp', 'tcsetpgrp',
+ 'ttyname', 'uname', 'wait', 'wait3', 'wait4'
+ ]
+
+# the Win32 urandom implementation isn't going to translate on JVM or CLI so
+# we have to remove it
+lltype_only_defs.append('urandom')
+
class Module(MixedModule):
"""This module provides access to operating system functionality that is
standardized by the C Standard and the POSIX standard (a thinly
@@ -160,11 +179,12 @@
interpleveldefs[name] = 'interp_posix.' + name
def __init__(self, space, w_name):
+ # if it's an ootype translation, remove all the defs that are lltype
+ # only
backend = space.config.translation.backend
- # the Win32 urandom implementation isn't going to translate on JVM or CLI
- # so we have to remove it
- if 'urandom' in self.interpleveldefs and (backend == 'cli' or backend == 'jvm'):
- del self.interpleveldefs['urandom']
+ if backend == 'cli' or backend == 'jvm':
+ for name in lltype_only_defs:
+ self.interpleveldefs.pop(name, None)
MixedModule.__init__(self, space, w_name)
def startup(self, space):
diff --git a/pypy/rpython/extfunc.py b/pypy/rpython/extfunc.py
--- a/pypy/rpython/extfunc.py
+++ b/pypy/rpython/extfunc.py
@@ -249,6 +249,9 @@
llfakeimpl, oofakeimpl: optional; if provided, they are called by the llinterpreter
sandboxsafe: use True if the function performs no I/O (safe for --sandbox)
"""
+
+ if export_name is None:
+ export_name = function.__name__
class FunEntry(ExtFuncEntry):
_about_ = function
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -46,6 +46,7 @@
import pypy.module.cpyext.complexobject
import pypy.module.cpyext.weakrefobject
import pypy.module.cpyext.funcobject
+import pypy.module.cpyext.frameobject
import pypy.module.cpyext.classobject
import pypy.module.cpyext.pypyintf
import pypy.module.cpyext.memoryobject
diff --git a/pypy/translator/cli/metavm.py b/pypy/translator/cli/metavm.py
--- a/pypy/translator/cli/metavm.py
+++ b/pypy/translator/cli/metavm.py
@@ -270,23 +270,38 @@
generator.ilasm.call('void [pypylib]pypy.runtime.DebugPrint::DEBUG_PRINT(%s)' % signature)
+INT_SIZE = {
+ ootype.Bool: 1,
+ ootype.Char: 2,
+ ootype.UniChar: 2,
+ rffi.SHORT: 2,
+ ootype.Signed: 4,
+ ootype.Unsigned: 4,
+ ootype.SignedLongLong: 8,
+ ootype.UnsignedLongLong: 8
+ }
-OOTYPE_TO_MNEMONIC = {
- ootype.Bool: 'i1',
- ootype.Char: 'i2',
- ootype.UniChar: 'i2',
- rffi.SHORT: 'i2',
- ootype.Signed: 'i4',
- ootype.SignedLongLong: 'i8',
- ootype.Unsigned: 'u4',
- ootype.UnsignedLongLong: 'u8',
- ootype.Float: 'r8',
- }
+UNSIGNED_TYPES = [ootype.Char, ootype.UniChar, rffi.USHORT,
+ ootype.Unsigned, ootype.UnsignedLongLong]
+
+def ootype_to_mnemonic(FROM, TO, default=None):
+ if TO == ootype.Float:
+ return 'r8'
+ #
+ try:
+ size = str(INT_SIZE[TO])
+ except KeyError:
+ return default
+ if FROM in UNSIGNED_TYPES:
+ return 'u' + size
+ else:
+ return 'i' + size
class _CastPrimitive(MicroInstruction):
def render(self, generator, op):
+ FROM = op.args[0].concretetype
TO = op.result.concretetype
- mnemonic = OOTYPE_TO_MNEMONIC[TO]
+ mnemonic = ootype_to_mnemonic(FROM, TO)
generator.ilasm.opcode('conv.%s' % mnemonic)
Call = _Call()
diff --git a/pypy/module/cpyext/include/frameobject.h b/pypy/module/cpyext/include/frameobject.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/frameobject.h
@@ -0,0 +1,17 @@
+#ifndef Py_FRAMEOBJECT_H
+#define Py_FRAMEOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ PyObject_HEAD
+ PyCodeObject *f_code;
+ PyObject *f_globals;
+ int f_lineno;
+} PyFrameObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_FRAMEOBJECT_H */
diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ b/pypy/module/_multiprocessing/test/test_connection.py
@@ -10,7 +10,7 @@
class AppTestBufferTooShort:
def setup_class(cls):
- space = gettestobjspace(usemodules=('_multiprocessing', 'thread'))
+ space = gettestobjspace(usemodules=('_multiprocessing', 'thread', 'signal'))
cls.space = space
if option.runappdirect:
@@ -88,7 +88,7 @@
class AppTestSocketConnection(BaseConnectionTest):
def setup_class(cls):
- space = gettestobjspace(usemodules=('_multiprocessing', 'thread'))
+ space = gettestobjspace(usemodules=('_multiprocessing', 'thread', 'signal'))
cls.space = space
cls.w_connections = space.newlist([])
diff --git a/pypy/module/thread/test/support.py b/pypy/module/thread/test/support.py
--- a/pypy/module/thread/test/support.py
+++ b/pypy/module/thread/test/support.py
@@ -32,7 +32,7 @@
class GenericTestThread:
def setup_class(cls):
- space = gettestobjspace(usemodules=('thread', 'time'))
+ space = gettestobjspace(usemodules=('thread', 'time', 'signal'))
cls.space = space
if option.runappdirect:
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -219,12 +219,14 @@
freevars = [self.space.interp_w(Cell, cell)
for cell in self.space.fixedview(w_freevarstuple)]
else:
- nfreevars = len(codeobj.co_freevars)
- freevars = [self.space.interp_w(Cell, self.popvalue())
- for i in range(nfreevars)]
- freevars.reverse()
- defaultarguments = [self.popvalue() for i in range(numdefaults)]
- defaultarguments.reverse()
+ n = len(codeobj.co_freevars)
+ freevars = [None] * n
+ while True:
+ n -= 1
+ if n < 0:
+ break
+ freevars[n] = self.space.interp_w(Cell, self.popvalue())
+ defaultarguments = self.popvalues(numdefaults)
fn = function.Function(self.space, codeobj, self.w_globals,
defaultarguments, freevars)
self.pushvalue(self.space.wrap(fn))
diff --git a/pypy/translator/cli/src/pypylib.cs b/pypy/translator/cli/src/pypylib.cs
--- a/pypy/translator/cli/src/pypylib.cs
+++ b/pypy/translator/cli/src/pypylib.cs
@@ -501,6 +501,11 @@
}
}
+ public static bool IntBetween(int a, int b, int c)
+ {
+ return a <= b && b < c;
+ }
+
public static bool Equal<T>(T t1, T t2)
{
if (t1 == null)
@@ -1148,10 +1153,36 @@
public class rffi
{
- public static int tolower(int chr)
- {
- return (int)Char.ToLower((char)chr);
- }
+ public static int tolower(int chr)
+ {
+ return (int)Char.ToLower((char)chr);
+ }
+
+ public static int locale_tolower(int chr)
+ {
+ return (int)Char.ToLower((char)chr);
+ }
+
+ public static int locale_isupper(int chr)
+ {
+ return Convert.ToInt32(Char.IsUpper((char)chr));
+ }
+
+ public static int locale_islower(int chr)
+ {
+ return Convert.ToInt32(Char.IsLower((char)chr));
+ }
+
+ public static int locale_isalpha(int chr)
+ {
+ return Convert.ToInt32(Char.IsLetter((char)chr));
+ }
+
+ public static int locale_isalnum(int chr)
+ {
+ return Convert.ToInt32(Char.IsLetterOrDigit((char)chr));
+ }
+
}
}
diff --git a/pypy/rpython/ootypesystem/rdict.py b/pypy/rpython/ootypesystem/rdict.py
--- a/pypy/rpython/ootypesystem/rdict.py
+++ b/pypy/rpython/ootypesystem/rdict.py
@@ -153,6 +153,13 @@
hop.exception_cannot_occur()
return self.send_message(hop, 'll_clear')
+ def rtype_method_popitem(self, hop):
+ v_dict, = hop.inputargs(self)
+ r_tuple = hop.r_result
+ cTUPLE = hop.inputconst(ootype.Void, r_tuple.lowleveltype)
+ hop.exception_is_here()
+ return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
+
def __get_func(self, interp, r_func, fn, TYPE):
if isinstance(r_func, MethodOfFrozenPBCRepr):
obj = r_func.r_im_self.convert_const(fn.im_self)
@@ -353,6 +360,16 @@
ll_dict_values = _make_ll_keys_values_items('values')
ll_dict_items = _make_ll_keys_values_items('items')
+def ll_popitem(ELEM, d):
+ it = d.ll_get_items_iterator()
+ if it.ll_go_next():
+ res = ootype.new(ELEM)
+ key = res.item0 = it.ll_current_key()
+ res.item1 = it.ll_current_value()
+ d.ll_remove(key)
+ return res
+ raise KeyError
+
# ____________________________________________________________
#
# Iteration.
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -138,11 +138,13 @@
# raised after the exception handler block was popped.
try:
trace = self.w_f_trace
- self.w_f_trace = None
+ if trace is not None:
+ self.w_f_trace = None
try:
ec.bytecode_trace_after_exception(self)
finally:
- self.w_f_trace = trace
+ if trace is not None:
+ self.w_f_trace = trace
except OperationError, e:
operr = e
pytraceback.record_application_traceback(
diff --git a/pypy/module/cpyext/test/test_frameobject.py b/pypy/module/cpyext/test/test_frameobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_frameobject.py
@@ -0,0 +1,66 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestFrameObject(AppTestCpythonExtensionBase):
+
+ def test_forge_frame(self):
+ module = self.import_extension('foo', [
+ ("raise_exception", "METH_NOARGS",
+ """
+ PyObject *py_srcfile = PyString_FromString("filename");
+ PyObject *py_funcname = PyString_FromString("funcname");
+ PyObject *py_globals = PyDict_New();
+ PyObject *empty_string = PyString_FromString("");
+ PyObject *empty_tuple = PyTuple_New(0);
+ PyCodeObject *py_code;
+ PyFrameObject *py_frame;
+
+ py_code = PyCode_New(
+ 0, /*int argcount,*/
+ #if PY_MAJOR_VERSION >= 3
+ 0, /*int kwonlyargcount,*/
+ #endif
+ 0, /*int nlocals,*/
+ 0, /*int stacksize,*/
+ 0, /*int flags,*/
+ empty_string, /*PyObject *code,*/
+ empty_tuple, /*PyObject *consts,*/
+ empty_tuple, /*PyObject *names,*/
+ empty_tuple, /*PyObject *varnames,*/
+ empty_tuple, /*PyObject *freevars,*/
+ empty_tuple, /*PyObject *cellvars,*/
+ py_srcfile, /*PyObject *filename,*/
+ py_funcname, /*PyObject *name,*/
+ 42, /*int firstlineno,*/
+ empty_string /*PyObject *lnotab*/
+ );
+
+ if (!py_code) goto bad;
+ py_frame = PyFrame_New(
+ PyThreadState_Get(), /*PyThreadState *tstate,*/
+ py_code, /*PyCodeObject *code,*/
+ py_globals, /*PyObject *globals,*/
+ 0 /*PyObject *locals*/
+ );
+ if (!py_frame) goto bad;
+ py_frame->f_lineno = 48; /* Does not work with CPython */
+ PyErr_SetString(PyExc_ValueError, "error message");
+ PyTraceBack_Here(py_frame);
+ bad:
+ Py_XDECREF(py_srcfile);
+ Py_XDECREF(py_funcname);
+ Py_XDECREF(empty_string);
+ Py_XDECREF(empty_tuple);
+ Py_XDECREF(py_globals);
+ Py_XDECREF(py_code);
+ Py_XDECREF(py_frame);
+ return NULL;
+ """),
+ ])
+ exc = raises(ValueError, module.raise_exception)
+ frame = exc.traceback.tb_frame
+ assert frame.f_code.co_filename == "filename"
+ assert frame.f_code.co_name == "funcname"
+
+ # Cython does not work on CPython as well...
+ assert exc.traceback.tb_lineno == 42 # should be 48
+ assert frame.f_lineno == 42
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
@@ -6,8 +6,12 @@
from pypy.annotation.annrpython import RPythonAnnotator
from pypy.rpython.test.test_llinterp import interpret
from pypy.rpython.lltypesystem.rclass import OBJECTPTR
+from pypy.rpython.ootypesystem.rclass import OBJECT
from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
+
+from pypy.rpython.ootypesystem import ootype
class X(object):
pass
@@ -79,37 +83,48 @@
assert s.s_instance.can_be_None
assert s.s_instance.classdef == a.bookkeeper.getuniqueclassdef(X)
-def test_rtype_1():
- def f():
- return virtual_ref(X())
- x = interpret(f, [])
- assert lltype.typeOf(x) == OBJECTPTR
+class BaseTestVRef(BaseRtypingTest):
+ def test_rtype_1(self):
+ def f():
+ return virtual_ref(X())
+ x = self.interpret(f, [])
+ assert lltype.typeOf(x) == self.OBJECTTYPE
-def test_rtype_2():
- def f():
- x1 = X()
- vref = virtual_ref(x1)
- x2 = vref()
- virtual_ref_finish(x2)
- return x2
- x = interpret(f, [])
- assert lltype.castable(OBJECTPTR, lltype.typeOf(x)) > 0
+ def test_rtype_2(self):
+ def f():
+ x1 = X()
+ vref = virtual_ref(x1)
+ x2 = vref()
+ virtual_ref_finish(x2)
+ return x2
+ x = self.interpret(f, [])
+ assert self.castable(self.OBJECTTYPE, x)
-def test_rtype_3():
- def f(n):
- if n > 0:
- return virtual_ref(Y())
- else:
- return non_virtual_ref(Z())
- x = interpret(f, [-5])
- assert lltype.typeOf(x) == OBJECTPTR
+ def test_rtype_3(self):
+ def f(n):
+ if n > 0:
+ return virtual_ref(Y())
+ else:
+ return non_virtual_ref(Z())
+ x = self.interpret(f, [-5])
+ assert lltype.typeOf(x) == self.OBJECTTYPE
-def test_rtype_4():
- def f(n):
- if n > 0:
- return virtual_ref(X())
- else:
- return vref_None
- x = interpret(f, [-5])
- assert lltype.typeOf(x) == OBJECTPTR
- assert not x
+ def test_rtype_4(self):
+ def f(n):
+ if n > 0:
+ return virtual_ref(X())
+ else:
+ return vref_None
+ x = self.interpret(f, [-5])
+ assert lltype.typeOf(x) == self.OBJECTTYPE
+ assert not x
+
+class TestLLtype(BaseTestVRef, LLRtypeMixin):
+ OBJECTTYPE = OBJECTPTR
+ def castable(self, TO, var):
+ return lltype.castable(TO, lltype.typeOf(var)) > 0
+
+class TestOOtype(BaseTestVRef, OORtypeMixin):
+ OBJECTTYPE = OBJECT
+ def castable(self, TO, var):
+ return ootype.isSubclass(lltype.typeOf(var), TO)
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/frameobject.py
@@ -0,0 +1,82 @@
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+ cpython_api, bootstrap_function, PyObjectFields, cpython_struct)
+from pypy.module.cpyext.pyobject import (
+ PyObject, Py_DecRef, make_ref, from_ref, track_reference,
+ make_typedescr, get_typedescr)
+from pypy.module.cpyext.state import State
+from pypy.module.cpyext.pystate import PyThreadState
+from pypy.module.cpyext.funcobject import PyCodeObject
+from pypy.interpreter.pyframe import PyFrame
+from pypy.interpreter.pycode import PyCode
+
+PyFrameObjectStruct = lltype.ForwardReference()
+PyFrameObject = lltype.Ptr(PyFrameObjectStruct)
+PyFrameObjectFields = (PyObjectFields +
+ (("f_code", PyCodeObject),
+ ("f_globals", PyObject),
+ ("f_lineno", rffi.INT),
+ ))
+cpython_struct("PyFrameObject", PyFrameObjectFields, PyFrameObjectStruct)
+
+ at bootstrap_function
+def init_frameobject(space):
+ make_typedescr(PyFrame.typedef,
+ basestruct=PyFrameObject.TO,
+ attach=frame_attach,
+ dealloc=frame_dealloc,
+ realize=frame_realize)
+
+def frame_attach(space, py_obj, w_obj):
+ "Fills a newly allocated PyFrameObject with a frame object"
+ frame = space.interp_w(PyFrame, w_obj)
+ py_frame = rffi.cast(PyFrameObject, py_obj)
+ py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, frame.pycode))
+ py_frame.c_f_globals = make_ref(space, frame.w_globals)
+ rffi.setintfield(py_frame, 'c_f_lineno', frame.f_lineno)
+
+ at cpython_api([PyObject], lltype.Void, external=False)
+def frame_dealloc(space, py_obj):
+ py_frame = rffi.cast(PyFrameObject, py_obj)
+ py_code = rffi.cast(PyObject, py_frame.c_f_code)
+ Py_DecRef(space, py_code)
+ Py_DecRef(space, py_frame.c_f_globals)
+ from pypy.module.cpyext.object import PyObject_dealloc
+ PyObject_dealloc(space, py_obj)
+
+def frame_realize(space, py_obj):
+ """
+ Creates the frame in the interpreter. The PyFrameObject structure must not
+ be modified after this call.
+ """
+ py_frame = rffi.cast(PyFrameObject, py_obj)
+ py_code = rffi.cast(PyObject, py_frame.c_f_code)
+ w_code = from_ref(space, py_code)
+ code = space.interp_w(PyCode, w_code)
+ w_globals = from_ref(space, py_frame.c_f_globals)
+
+ frame = PyFrame(space, code, w_globals, closure=None)
+ frame.f_lineno = py_frame.c_f_lineno
+ w_obj = space.wrap(frame)
+ track_reference(space, py_obj, w_obj)
+ return w_obj
+
+ at cpython_api([PyThreadState, PyCodeObject, PyObject, PyObject], PyFrameObject)
+def PyFrame_New(space, tstate, w_code, w_globals, w_locals):
+ typedescr = get_typedescr(PyFrame.typedef)
+ py_obj = typedescr.allocate(space, space.gettypeobject(PyFrame.typedef))
+ py_frame = rffi.cast(PyFrameObject, py_obj)
+ space.interp_w(PyCode, w_code) # sanity check
+ py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, w_code))
+ py_frame.c_f_globals = make_ref(space, w_globals)
+ return py_frame
+
+ at cpython_api([PyFrameObject], rffi.INT_real, error=-1)
+def PyTraceBack_Here(space, w_frame):
+ from pypy.interpreter.pytraceback import record_application_traceback
+ state = space.fromcache(State)
+ if state.operror is None:
+ return -1
+ frame = space.interp_w(PyFrame, w_frame)
+ record_application_traceback(space, state.operror, frame, 0)
+ return 0
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -28,7 +28,9 @@
self.items = items
def getitems(self):
- return jit.hint(self, promote=True).items
+ ## XXX! we would like: return jit.hint(self, promote=True).items
+ ## XXX! but it gives horrible performance in some cases
+ return self.items
def getitem(self, idx):
return self.getitems()[idx]
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -106,6 +106,11 @@
del obj
import gc; gc.collect()
+ try:
+ del space.getexecutioncontext().cpyext_threadstate
+ except AttributeError:
+ pass
+
for w_obj in state.non_heaptypes_w:
Py_DecRef(space, w_obj)
state.non_heaptypes_w[:] = []
diff --git a/pypy/translator/cli/src/ll_math.cs b/pypy/translator/cli/src/ll_math.cs
--- a/pypy/translator/cli/src/ll_math.cs
+++ b/pypy/translator/cli/src/ll_math.cs
@@ -224,5 +224,25 @@
{
return Math.Tanh(x);
}
+
+ static public bool ll_math_isnan(double x)
+ {
+ return double.IsNaN(x);
+ }
+
+ static public bool ll_math_isinf(double x)
+ {
+ return double.IsInfinity(x);
+ }
+
+ static public double ll_math_copysign(double x, double y)
+ {
+ if (x < 0.0)
+ x = -x;
+ if (y > 0.0 || (y == 0.0 && Math.Atan2(y, -1.0) > 0.0))
+ return x;
+ else
+ return -x;
+ }
}
}
diff --git a/pypy/module/thread/test/test_import_lock.py b/pypy/module/thread/test/test_import_lock.py
--- a/pypy/module/thread/test/test_import_lock.py
+++ b/pypy/module/thread/test/test_import_lock.py
@@ -61,27 +61,3 @@
assert not imp.lock_held()
self.waitfor(lambda: done)
assert done
-
-class TestImportLock:
- def test_lock(self, space, monkeypatch):
- from pypy.module.imp.importing import getimportlock, importhook
-
- # Monkeypatch the import lock and add a counter
- importlock = getimportlock(space)
- original_acquire = importlock.acquire_lock
- def acquire_lock():
- importlock.count += 1
- original_acquire()
- importlock.count = 0
- monkeypatch.setattr(importlock, 'acquire_lock', acquire_lock)
-
- # An already imported module
- importhook(space, 'sys')
- assert importlock.count == 0
- # A new module
- importhook(space, 're')
- assert importlock.count == 7
- # Import it again
- previous_count = importlock.count
- importhook(space, 're')
- assert importlock.count == previous_count
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -46,15 +46,15 @@
w_f_trace = None
# For tracing
instr_lb = 0
- instr_ub = -1
- instr_prev = -1
+ instr_ub = 0
+ instr_prev_plus_one = 0
is_being_profiled = False
def __init__(self, space, code, w_globals, closure):
self = hint(self, access_directly=True, fresh_virtualizable=True)
assert isinstance(code, pycode.PyCode)
self.pycode = code
- eval.Frame.__init__(self, space, w_globals, code.co_nlocals)
+ eval.Frame.__init__(self, space, w_globals)
self.valuestack_w = [None] * code.co_stacksize
self.valuestackdepth = 0
self.lastblock = None
@@ -63,7 +63,7 @@
# regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
# class bodies only have CO_NEWLOCALS.
self.initialize_frame_scopes(closure, code)
- self.fastlocals_w = [None]*self.numlocals
+ self.fastlocals_w = [None] * code.co_nlocals
make_sure_not_resized(self.fastlocals_w)
self.f_lineno = code.co_firstlineno
@@ -335,7 +335,7 @@
w(self.instr_lb), #do we need these three (that are for tracing)
w(self.instr_ub),
- w(self.instr_prev),
+ w(self.instr_prev_plus_one),
w_cells,
]
@@ -349,7 +349,7 @@
args_w = space.unpackiterable(w_args)
w_f_back, w_builtin, w_pycode, w_valuestack, w_blockstack, w_exc_value, w_tb,\
w_globals, w_last_instr, w_finished, w_f_lineno, w_fastlocals, w_f_locals, \
- w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev, w_cells = args_w
+ w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev_plus_one, w_cells = args_w
new_frame = self
pycode = space.interp_w(PyCode, w_pycode)
@@ -397,7 +397,7 @@
new_frame.instr_lb = space.int_w(w_instr_lb) #the three for tracing
new_frame.instr_ub = space.int_w(w_instr_ub)
- new_frame.instr_prev = space.int_w(w_instr_prev)
+ new_frame.instr_prev_plus_one = space.int_w(w_instr_prev_plus_one)
self._setcellvars(cellvars)
# XXX what if the frame is in another thread??
@@ -430,7 +430,10 @@
"""Initialize cellvars from self.fastlocals_w
This is overridden in nestedscope.py"""
pass
-
+
+ def getfastscopelength(self):
+ return self.pycode.co_nlocals
+
def getclosure(self):
return None
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -4,6 +4,8 @@
from pypy.jit.metainterp.optimizeutil import descrlist_dict
from pypy.rlib.objectmodel import we_are_translated
from pypy.jit.metainterp.optimizeopt import optimizer
+from pypy.jit.metainterp.executor import execute
+from pypy.jit.codewriter.heaptracker import vtable2descr
class AbstractVirtualValue(optimizer.OptValue):
@@ -72,28 +74,53 @@
assert isinstance(fieldvalue, optimizer.OptValue)
self._fields[ofs] = fieldvalue
+ def _get_descr(self):
+ raise NotImplementedError
+
+ def _is_immutable_and_filled_with_constants(self):
+ count = self._get_descr().count_fields_if_immutable()
+ if count != len(self._fields): # always the case if count == -1
+ return False
+ for value in self._fields.itervalues():
+ subbox = value.force_box()
+ if not isinstance(subbox, Const):
+ return False
+ return True
+
def _really_force(self):
- assert self.source_op is not None
+ op = self.source_op
+ assert op is not None
# ^^^ This case should not occur any more (see test_bug_3).
#
if not we_are_translated():
- self.source_op.name = 'FORCE ' + self.source_op.name
- newoperations = self.optimizer.newoperations
- newoperations.append(self.source_op)
- self.box = box = self.source_op.result
- #
- iteritems = self._fields.iteritems()
- if not we_are_translated(): #random order is fine, except for tests
- iteritems = list(iteritems)
- iteritems.sort(key = lambda (x,y): x.sort_key())
- for ofs, value in iteritems:
- if value.is_null():
- continue
- subbox = value.force_box()
- op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
- descr=ofs)
+ op.name = 'FORCE ' + self.source_op.name
+
+ if self._is_immutable_and_filled_with_constants():
+ box = self.optimizer.constant_fold(op)
+ self.make_constant(box)
+ for ofs, value in self._fields.iteritems():
+ subbox = value.force_box()
+ assert isinstance(subbox, Const)
+ execute(self.optimizer.cpu, None, rop.SETFIELD_GC,
+ ofs, box, subbox)
+ # keep self._fields, because it's all immutable anyway
+ else:
+ newoperations = self.optimizer.newoperations
newoperations.append(op)
- self._fields = None
+ self.box = box = op.result
+ #
+ iteritems = self._fields.iteritems()
+ if not we_are_translated(): #random order is fine, except for tests
+ iteritems = list(iteritems)
+ iteritems.sort(key = lambda (x,y): x.sort_key())
+ for ofs, value in iteritems:
+ if value.is_null():
+ continue
+ subbox = value.force_box()
+ op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
+ descr=ofs)
+ newoperations.append(op)
+ self._fields = None
def _get_field_descr_list(self):
_cached_sorted_fields = self._cached_sorted_fields
@@ -168,6 +195,9 @@
fielddescrs = self._get_field_descr_list()
return modifier.make_virtual(self.known_class, fielddescrs)
+ def _get_descr(self):
+ return vtable2descr(self.optimizer.cpu, self.known_class.getint())
+
def __repr__(self):
cls_name = self.known_class.value.adr.ptr._obj._TYPE._name
if self._fields is None:
@@ -185,6 +215,9 @@
fielddescrs = self._get_field_descr_list()
return modifier.make_vstruct(self.structdescr, fielddescrs)
+ def _get_descr(self):
+ return self.structdescr
+
class VArrayValue(AbstractVirtualValue):
def __init__(self, optimizer, arraydescr, size, keybox, source_op=None):
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -351,14 +351,6 @@
"""Return the number of free variables in co."""
raise NotImplementedError
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
-def PyCode_New(space, argcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, firstlineno, lnotab):
- """Return a new code object. If you need a dummy code object to
- create a frame, use PyCode_NewEmpty() instead. Calling
- PyCode_New() directly can bind you to a precise Python
- version since the definition of the bytecode changes often."""
- raise NotImplementedError
-
@cpython_api([PyObject], rffi.INT_real, error=-1)
def PyCodec_Register(space, search_function):
"""Register a new codec search function.
@@ -1116,20 +1108,6 @@
with an exception set on failure (the module still exists in this case)."""
raise NotImplementedError
- at cpython_api([rffi.CCHARP], PyObject)
-def PyImport_AddModule(space, name):
- """Return the module object corresponding to a module name. The name argument
- may be of the form package.module. First check the modules dictionary if
- there's one there, and if not, create a new one and insert it in the modules
- dictionary. Return NULL with an exception set on failure.
-
- This function does not load or import the module; if the module wasn't already
- loaded, you will get an empty module object. Use PyImport_ImportModule()
- or one of its variants to import a module. Package structures implied by a
- dotted name for name are not created if not already present."""
- borrow_from()
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, PyObject], PyObject)
def PyImport_ExecCodeModule(space, name, co):
"""Given a module name (possibly of the form package.module) and a code
@@ -1965,14 +1943,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
-def PyObject_Cmp(space, o1, o2, result):
- """Compare the values of o1 and o2 using a routine provided by o1, if one
- exists, otherwise with a routine provided by o2. The result of the
- comparison is returned in result. Returns -1 on failure. This is the
- equivalent of the Python statement result = cmp(o1, o2)."""
- raise NotImplementedError
-
@cpython_api([PyObject], PyObject)
def PyObject_Bytes(space, o):
"""Compute a bytes representation of object o. In 2.x, this is just a alias
diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -191,6 +191,10 @@
f = _io.BufferedReader(raw)
assert repr(f) == '<_io.BufferedReader name=%r>' % (self.tmpfile,)
+class AppTestBufferedReaderWithThreads(AppTestBufferedReader):
+ spaceconfig = dict(usemodules=['_io', 'thread'])
+
+
class AppTestBufferedWriter:
def setup_class(cls):
cls.space = gettestobjspace(usemodules=['_io'])
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -400,21 +400,9 @@
# So we need a forward and backward mapping in our State instance
PyObjectStruct = lltype.ForwardReference()
PyObject = lltype.Ptr(PyObjectStruct)
-PyBufferProcs = lltype.ForwardReference()
PyObjectFields = (("ob_refcnt", lltype.Signed), ("ob_type", PyTypeObjectPtr))
-def F(ARGS, RESULT=lltype.Signed):
- return lltype.Ptr(lltype.FuncType(ARGS, RESULT))
-PyBufferProcsFields = (
- ("bf_getreadbuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
- ("bf_getwritebuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
- ("bf_getsegcount", F([PyObject, rffi.INTP])),
- ("bf_getcharbuffer", F([PyObject, lltype.Signed, rffi.CCHARPP])),
-# we don't support new buffer interface for now
- ("bf_getbuffer", rffi.VOIDP),
- ("bf_releasebuffer", rffi.VOIDP))
PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
cpython_struct('PyObject', PyObjectFields, PyObjectStruct)
-cpython_struct('PyBufferProcs', PyBufferProcsFields, PyBufferProcs)
PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
PyVarObject = lltype.Ptr(PyVarObjectStruct)
@@ -539,7 +527,8 @@
elif is_PyObject(callable.api_func.restype):
if result is None:
- retval = make_ref(space, None)
+ retval = rffi.cast(callable.api_func.restype,
+ make_ref(space, None))
elif isinstance(result, Reference):
retval = result.get_ref(space)
elif not rffi._isllptr(result):
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -7,10 +7,10 @@
from pypy.objspace.std.typeobject import W_TypeObject
from pypy.interpreter.typedef import GetSetProperty
from pypy.module.cpyext.api import (
- cpython_api, cpython_struct, bootstrap_function, Py_ssize_t,
+ cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP,
generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
- PyBufferProcs, build_type_checkers)
+ build_type_checkers)
from pypy.module.cpyext.pyobject import (
PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
track_reference, RefcountState, borrow_from)
@@ -24,7 +24,7 @@
from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
from pypy.module.cpyext.typeobjectdefs import (
PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
- PyNumberMethods, PySequenceMethods)
+ PyNumberMethods, PySequenceMethods, PyBufferProcs)
from pypy.module.cpyext.slotdefs import (
slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
from pypy.interpreter.error import OperationError
@@ -361,14 +361,14 @@
# hopefully this does not clash with the memory model assumed in
# extension modules
- at cpython_api([PyObject, rffi.INTP], lltype.Signed, external=False,
+ at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, external=False,
error=CANNOT_FAIL)
def str_segcount(space, w_obj, ref):
if ref:
- ref[0] = rffi.cast(rffi.INT, space.len_w(w_obj))
+ ref[0] = space.len_w(w_obj)
return 1
- at cpython_api([PyObject, lltype.Signed, rffi.VOIDPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
external=False, error=-1)
def str_getreadbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.stringobject import PyString_AsString
@@ -381,7 +381,7 @@
Py_DecRef(space, pyref)
return space.len_w(w_str)
- at cpython_api([PyObject, lltype.Signed, rffi.CCHARPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
external=False, error=-1)
def str_getcharbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.stringobject import PyString_AsString
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -245,6 +245,16 @@
expression cmp(o1, o2)."""
return space.int_w(space.cmp(w_o1, w_o2))
+ at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
+def PyObject_Cmp(space, w_o1, w_o2, result):
+ """Compare the values of o1 and o2 using a routine provided by o1, if one
+ exists, otherwise with a routine provided by o2. The result of the
+ comparison is returned in result. Returns -1 on failure. This is the
+ equivalent of the Python statement result = cmp(o1, o2)."""
+ res = space.int_w(space.cmp(w_o1, w_o2))
+ result[0] = rffi.cast(rffi.INT, res)
+ return 0
+
@cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
def PyObject_RichCompare(space, w_o1, w_o2, opid_int):
"""Compare the values of o1 and o2 using the operation specified by opid,
@@ -385,7 +395,7 @@
raise OperationError(space.w_TypeError, space.wrap(
"expected a character buffer object"))
if generic_cpy_call(space, pb.c_bf_getsegcount,
- obj, lltype.nullptr(rffi.INTP.TO)) != 1:
+ obj, lltype.nullptr(Py_ssize_tP.TO)) != 1:
raise OperationError(space.w_TypeError, space.wrap(
"expected a single-segment buffer object"))
size = generic_cpy_call(space, pb.c_bf_getcharbuffer,
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -487,6 +487,7 @@
""")
def test_range_iter(self):
+ py.test.skip("until we fix defaults")
def main(n):
def g(n):
return range(n)
@@ -539,7 +540,7 @@
i12 = int_sub_ovf(i3, 1)
guard_no_overflow(descr=<Guard5>)
--TICK--
- jump(p0, p1, p2, i12, p4, descr=<Loop0>)
+ jump(p0, p1, p2, i12, descr=<Loop0>)
""")
def test_exception_inside_loop_2(self):
@@ -585,7 +586,7 @@
--EXC-TICK--
i14 = int_add(i4, 1)
--TICK--
- jump(p0, p1, p2, p3, i14, i5, p6, descr=<Loop0>)
+ jump(p0, p1, p2, p3, i14, i5, descr=<Loop0>)
""")
def test_chain_of_guards(self):
@@ -685,13 +686,13 @@
assert log.result == 500
loop, = log.loops_by_id('import')
assert loop.match_by_id('import', """
- p14 = call(ConstClass(ll_split_chr__GcStruct_listLlT_rpy_stringPtr_Char), p8, 46, -1, descr=<GcPtrCallDescr>)
+ p14 = call(ConstClass(ll_split_chr), p8, 46, -1, descr=<GcPtrCallDescr>)
guard_no_exception(descr=<Guard4>)
guard_nonnull(p14, descr=<Guard5>)
i15 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
i16 = int_is_true(i15)
guard_true(i16, descr=<Guard6>)
- p18 = call(ConstClass(ll_pop_default__dum_nocheckConst_listPtr), p14, descr=<GcPtrCallDescr>)
+ p18 = call(ConstClass(ll_pop_default), p14, descr=<GcPtrCallDescr>)
guard_no_exception(descr=<Guard7>)
i19 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
i20 = int_is_true(i19)
@@ -1009,6 +1010,7 @@
""")
def test_func_defaults(self):
+ py.test.skip("skipped until we fix defaults")
def main(n):
i = 1
while i < n:
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -1,8 +1,10 @@
from pypy.interpreter import module
from pypy.module.cpyext.api import (
generic_cpy_call, cpython_api, PyObject, CONST_STRING)
+from pypy.module.cpyext.pyobject import borrow_from
from pypy.rpython.lltypesystem import rffi
from pypy.interpreter.error import OperationError
+from pypy.interpreter.module import Module
@cpython_api([PyObject], PyObject)
def PyImport_Import(space, w_name):
@@ -51,3 +53,23 @@
from pypy.module.imp.importing import reload
return reload(space, w_mod)
+ at cpython_api([CONST_STRING], PyObject)
+def PyImport_AddModule(space, name):
+ """Return the module object corresponding to a module name. The name
+ argument may be of the form package.module. First check the modules
+ dictionary if there's one there, and if not, create a new one and insert
+ it in the modules dictionary. Return NULL with an exception set on
+ failure.
+
+ This function does not load or import the module; if the module wasn't
+ already loaded, you will get an empty module object. Use
+ PyImport_ImportModule() or one of its variants to import a module.
+ Package structures implied by a dotted name for name are not created if
+ not already present."""
+ from pypy.module.imp.importing import check_sys_modules_w
+ modulename = rffi.charp2str(name)
+ w_mod = check_sys_modules_w(space, modulename)
+ if not w_mod or space.is_w(w_mod, space.w_None):
+ w_mod = Module(space, space.wrap(modulename))
+ return borrow_from(None, w_mod)
+
diff --git a/pypy/translator/oosupport/test_template/builtin.py b/pypy/translator/oosupport/test_template/builtin.py
--- a/pypy/translator/oosupport/test_template/builtin.py
+++ b/pypy/translator/oosupport/test_template/builtin.py
@@ -227,6 +227,17 @@
assert res == ord('a')
+ def test_rlocale(self):
+ from pypy.rlib.rlocale import isupper, islower, isalpha, isalnum, tolower
+ def fn():
+ assert isupper(ord("A"))
+ assert islower(ord("a"))
+ assert not isalpha(ord(" "))
+ assert isalnum(ord("1"))
+ assert tolower(ord("A")) == ord("a")
+ self.interpret(fn, [])
+
+
class BaseTestTime(llBaseTestTime):
def test_time_clock(self):
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -25,12 +25,13 @@
class Descr(history.AbstractDescr):
def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
- arg_types=None):
+ arg_types=None, count_fields_if_immut=-1):
self.ofs = ofs
self.typeinfo = typeinfo
self.extrainfo = extrainfo
self.name = name
self.arg_types = arg_types
+ self.count_fields_if_immut = count_fields_if_immut
def get_arg_types(self):
return self.arg_types
@@ -63,6 +64,9 @@
def as_vtable_size_descr(self):
return self
+ def count_fields_if_immutable(self):
+ return self.count_fields_if_immut
+
def __lt__(self, other):
raise TypeError("cannot use comparison on Descrs")
def __le__(self, other):
@@ -109,12 +113,14 @@
return False
def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
- arg_types=None):
- key = (ofs, typeinfo, extrainfo, name, arg_types)
+ arg_types=None, count_fields_if_immut=-1):
+ key = (ofs, typeinfo, extrainfo, name, arg_types,
+ count_fields_if_immut)
try:
return self._descrs[key]
except KeyError:
- descr = Descr(ofs, typeinfo, extrainfo, name, arg_types)
+ descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
+ count_fields_if_immut)
self._descrs[key] = descr
return descr
@@ -284,7 +290,8 @@
def sizeof(self, S):
assert not isinstance(S, lltype.Ptr)
- return self.getdescr(symbolic.get_size(S))
+ count = heaptracker.count_fields_if_immutable(S)
+ return self.getdescr(symbolic.get_size(S), count_fields_if_immut=count)
class LLtypeCPU(BaseCPU):
diff --git a/pypy/module/cpyext/typeobjectdefs.py b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -1,9 +1,8 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
-from pypy.module.cpyext.api import cpython_struct, \
- PyVarObjectFields, Py_ssize_t, Py_TPFLAGS_READYING, \
- Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE, \
- PyTypeObject, PyTypeObjectPtr, PyBufferProcs, FILEP
+from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
+ PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
+ Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.module.cpyext.modsupport import PyMethodDef
@@ -55,6 +54,14 @@
wrapperfunc = P(FT([PyO, PyO, rffi.VOIDP], PyO))
wrapperfunc_kwds = P(FT([PyO, PyO, rffi.VOIDP, PyO], PyO))
+readbufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+writebufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
+charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
+## We don't support new buffer interface for now
+getbufferproc = rffi.VOIDP
+releasebufferproc = rffi.VOIDP
+
PyGetSetDef = cpython_struct("PyGetSetDef", (
("name", rffi.CCHARP),
@@ -127,7 +134,6 @@
("mp_ass_subscript", objobjargproc),
))
-"""
PyBufferProcs = cpython_struct("PyBufferProcs", (
("bf_getreadbuffer", readbufferproc),
("bf_getwritebuffer", writebufferproc),
@@ -136,7 +142,6 @@
("bf_getbuffer", getbufferproc),
("bf_releasebuffer", releasebufferproc),
))
-"""
PyMemberDef = cpython_struct("PyMemberDef", (
("name", rffi.CCHARP),
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -438,38 +438,6 @@
res = __import__('', mydict, None, ['bar'], 2)
assert res is pkg
- def test__package__(self):
- # Regression test for http://bugs.python.org/issue3221.
- def check_absolute():
- exec "from os import path" in ns
- def check_relative():
- exec "from . import a" in ns
-
- # Check both OK with __package__ and __name__ correct
- ns = dict(__package__='pkg', __name__='pkg.notarealmodule')
- check_absolute()
- check_relative()
-
- # Check both OK with only __name__ wrong
- ns = dict(__package__='pkg', __name__='notarealpkg.notarealmodule')
- check_absolute()
- check_relative()
-
- # Check relative fails with only __package__ wrong
- ns = dict(__package__='foo', __name__='pkg.notarealmodule')
- check_absolute() # XXX check warnings
- raises(SystemError, check_relative)
-
- # Check relative fails with __package__ and __name__ wrong
- ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule')
- check_absolute() # XXX check warnings
- raises(SystemError, check_relative)
-
- # Check both fail with package set to a non-string
- ns = dict(__package__=object())
- raises(ValueError, check_absolute)
- raises(ValueError, check_relative)
-
def test_universal_newlines(self):
import pkg_univnewlines
assert pkg_univnewlines.a == 5
diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -253,8 +253,10 @@
except OperationError, e:
parser._exc_info = e
XML_StopParser(parser.itself, XML_FALSE)
- return 0
- return 1
+ result = 0
+ else:
+ result = 1
+ return rffi.cast(rffi.INT, result)
callback_type = lltype.Ptr(lltype.FuncType(
[rffi.VOIDP, rffi.CCHARP, XML_Encoding_Ptr], rffi.INT))
XML_SetUnknownEncodingHandler = expat_external(
diff --git a/pypy/tool/pytest/appsupport.py b/pypy/tool/pytest/appsupport.py
--- a/pypy/tool/pytest/appsupport.py
+++ b/pypy/tool/pytest/appsupport.py
@@ -196,7 +196,7 @@
class _ExceptionInfo(object):
def __init__(self):
import sys
- self.type, self.value, _ = sys.exc_info()
+ self.type, self.value, self.traceback = sys.exc_info()
return _ExceptionInfo
""")
diff --git a/pypy/jit/metainterp/test/test_compile.py b/pypy/jit/metainterp/test/test_compile.py
--- a/pypy/jit/metainterp/test/test_compile.py
+++ b/pypy/jit/metainterp/test/test_compile.py
@@ -86,6 +86,8 @@
metainterp.history = History()
metainterp.history.operations = loop.operations[:]
metainterp.history.inputargs = loop.inputargs[:]
+ cpu._all_size_descrs_with_vtable = (
+ LLtypeMixin.cpu._all_size_descrs_with_vtable)
#
loop_tokens = []
loop_token = compile_new_loop(metainterp, loop_tokens, [], 0, None)
diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -114,6 +114,12 @@
def __del__(self):
free_ll_lock(self._lock)
+ def __enter__(self):
+ self.acquire(True)
+
+ def __exit__(self, *args):
+ self.release()
+
# ____________________________________________________________
#
# Stack size
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1350,6 +1350,11 @@
pass
def _freeze_(self):
return True
+ def __enter__(self):
+ pass
+ def __exit__(self, *args):
+ pass
+
dummy_lock = DummyLock()
## Table describing the regular part of the interface of object spaces,
diff --git a/pypy/translator/cli/ilgenerator.py b/pypy/translator/cli/ilgenerator.py
--- a/pypy/translator/cli/ilgenerator.py
+++ b/pypy/translator/cli/ilgenerator.py
@@ -443,8 +443,8 @@
self.ilasm.opcode('newarr', clitype.itemtype.typename())
def _array_suffix(self, ARRAY, erase_unsigned=False):
- from pypy.translator.cli.metavm import OOTYPE_TO_MNEMONIC
- suffix = OOTYPE_TO_MNEMONIC.get(ARRAY.ITEM, 'ref')
+ from pypy.translator.cli.metavm import ootype_to_mnemonic
+ suffix = ootype_to_mnemonic(ARRAY.ITEM, ARRAY.ITEM, 'ref')
if erase_unsigned:
suffix = suffix.replace('u', 'i')
return suffix
diff --git a/pypy/module/cpyext/include/code.h b/pypy/module/cpyext/include/code.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/code.h
@@ -0,0 +1,12 @@
+#ifndef Py_CODE_H
+#define Py_CODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject PyCodeObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CODE_H */
diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -61,6 +61,12 @@
except OperationError, e:
print e.errorstr(self.space)
raise
+
+ try:
+ del self.space.getexecutioncontext().cpyext_threadstate
+ except AttributeError:
+ pass
+
if self.check_and_print_leaks():
assert False, "Test leaks or loses object(s)."
diff --git a/pypy/module/cpyext/test/test_import.py b/pypy/module/cpyext/test/test_import.py
--- a/pypy/module/cpyext/test/test_import.py
+++ b/pypy/module/cpyext/test/test_import.py
@@ -1,5 +1,6 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.rpython.lltypesystem import rffi, lltype
class TestImport(BaseApiTest):
def test_import(self, space, api):
@@ -7,6 +8,16 @@
assert pdb
assert space.getattr(pdb, space.wrap("pm"))
+ def test_addmodule(self, space, api):
+ with rffi.scoped_str2charp("sys") as modname:
+ w_sys = api.PyImport_AddModule(modname)
+ assert w_sys is space.sys
+
+ with rffi.scoped_str2charp("foobar") as modname:
+ w_foobar = api.PyImport_AddModule(modname)
+ assert space.str_w(space.getattr(w_foobar,
+ space.wrap('__name__'))) == 'foobar'
+
def test_reload(self, space, api):
pdb = api.PyImport_Import(space.wrap("pdb"))
space.delattr(pdb, space.wrap("set_trace"))
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -1,16 +1,18 @@
import re
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject
+from pypy.module.cpyext.api import (
+ cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
from pypy.module.cpyext.typeobjectdefs import (
unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc,
ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
- hashfunc, descrgetfunc, descrsetfunc, objobjproc)
+ cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, readbufferproc)
from pypy.module.cpyext.pyobject import from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.buffer import Buffer as W_Buffer
from pypy.interpreter.argument import Arguments
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.objectmodel import specialize
@@ -193,18 +195,59 @@
check_num_args(space, w_args, 0)
return space.wrap(generic_cpy_call(space, func_target, w_self))
+class CPyBuffer(W_Buffer):
+ # Similar to Py_buffer
+
+ def __init__(self, ptr, size, w_obj):
+ self.ptr = ptr
+ self.size = size
+ self.w_obj = w_obj # kept alive
+
+ def getlength(self):
+ return self.size
+
+ def getitem(self, index):
+ return self.ptr[index]
+
+def wrap_getreadbuffer(space, w_self, w_args, func):
+ func_target = rffi.cast(readbufferproc, func)
+ with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
+ index = rffi.cast(Py_ssize_t, 0)
+ size = generic_cpy_call(space, func_target, w_self, index, ptr)
+ if size < 0:
+ space.fromcache(State).check_and_raise_exception(always=True)
+ return space.wrap(CPyBuffer(ptr[0], size, w_self))
+
def get_richcmp_func(OP_CONST):
def inner(space, w_self, w_args, func):
func_target = rffi.cast(richcmpfunc, func)
check_num_args(space, w_args, 1)
- args_w = space.fixedview(w_args)
- other_w = args_w[0]
+ w_other, = space.fixedview(w_args)
return generic_cpy_call(space, func_target,
- w_self, other_w, rffi.cast(rffi.INT_real, OP_CONST))
+ w_self, w_other, rffi.cast(rffi.INT_real, OP_CONST))
return inner
richcmp_eq = get_richcmp_func(Py_EQ)
richcmp_ne = get_richcmp_func(Py_NE)
+richcmp_lt = get_richcmp_func(Py_LT)
+richcmp_le = get_richcmp_func(Py_LE)
+richcmp_gt = get_richcmp_func(Py_GT)
+richcmp_ge = get_richcmp_func(Py_GE)
+
+def wrap_cmpfunc(space, w_self, w_args, func):
+ func_target = rffi.cast(cmpfunc, func)
+ check_num_args(space, w_args, 1)
+ w_other, = space.fixedview(w_args)
+
+ if not space.is_true(space.issubtype(space.type(w_self),
+ space.type(w_other))):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'" %
+ (space.type(w_self).getname(space),
+ space.type(w_self).getname(space),
+ space.type(w_other).getname(space))))
+
+ return space.wrap(generic_cpy_call(space, func_target, w_self, w_other))
@cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, external=False)
def slot_tp_new(space, type, w_args, w_kwds):
@@ -571,12 +614,19 @@
for regex, repl in slotdef_replacements:
slotdefs_str = re.sub(regex, repl, slotdefs_str)
+slotdefs = eval(slotdefs_str)
+# PyPy addition
+slotdefs += (
+ TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+)
+
slotdefs_for_tp_slots = unrolling_iterable(
[(x.method_name, x.slot_name, x.slot_names, x.slot_func)
- for x in eval(slotdefs_str)])
+ for x in slotdefs])
+
slotdefs_for_wrappers = unrolling_iterable(
[(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc)
- for x in eval(slotdefs_str)])
+ for x in slotdefs])
if __name__ == "__main__":
print slotdefs_str
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -14,6 +14,10 @@
(("func_name", PyObject),)
cpython_struct("PyFunctionObject", PyFunctionObjectFields, PyFunctionObjectStruct)
+PyCodeObjectStruct = lltype.ForwardReference()
+PyCodeObject = lltype.Ptr(PyCodeObjectStruct)
+cpython_struct("PyCodeObject", PyObjectFields, PyCodeObjectStruct)
+
@bootstrap_function
def init_functionobject(space):
make_typedescr(Function.typedef,
@@ -65,7 +69,36 @@
assert isinstance(w_method, Method)
return borrow_from(w_method, w_method.w_class)
- at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyObject)
+def unwrap_list_of_strings(space, w_list):
+ return [space.str_w(w_item) for w_item in space.fixedview(w_list)]
+
+ at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+ PyObject, PyObject, PyObject, PyObject, PyObject, PyObject,
+ PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
+def PyCode_New(space, argcount, nlocals, stacksize, flags,
+ w_code, w_consts, w_names, w_varnames, w_freevars, w_cellvars,
+ w_filename, w_funcname, firstlineno, w_lnotab):
+ """Return a new code object. If you need a dummy code object to
+ create a frame, use PyCode_NewEmpty() instead. Calling
+ PyCode_New() directly can bind you to a precise Python
+ version since the definition of the bytecode changes often."""
+ return space.wrap(PyCode(space,
+ argcount=rffi.cast(lltype.Signed, argcount),
+ nlocals=rffi.cast(lltype.Signed, nlocals),
+ stacksize=rffi.cast(lltype.Signed, stacksize),
+ flags=rffi.cast(lltype.Signed, flags),
+ code=space.str_w(w_code),
+ consts=space.fixedview(w_consts),
+ names=unwrap_list_of_strings(space, w_names),
+ varnames=unwrap_list_of_strings(space, w_varnames),
+ filename=space.str_w(w_filename),
+ name=space.str_w(w_funcname),
+ firstlineno=rffi.cast(lltype.Signed, firstlineno),
+ lnotab=space.str_w(w_lnotab),
+ freevars=unwrap_list_of_strings(space, w_freevars),
+ cellvars=unwrap_list_of_strings(space, w_cellvars)))
+
+ at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyCodeObject)
def PyCode_NewEmpty(space, filename, funcname, firstlineno):
"""Creates a new empty code object with the specified source location."""
return space.wrap(PyCode(space,
diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -151,9 +151,9 @@
class CPythonFakeFrame(eval.Frame):
- def __init__(self, space, code, w_globals=None, numlocals=-1):
+ def __init__(self, space, code, w_globals=None):
self.fakecode = code
- eval.Frame.__init__(self, space, w_globals, numlocals)
+ eval.Frame.__init__(self, space, w_globals)
def getcode(self):
return self.fakecode
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
@@ -77,8 +77,8 @@
self.loop_run_counters = []
self.float_const_neg_addr = 0
self.float_const_abs_addr = 0
- self.malloc_fixedsize_slowpath1 = 0
- self.malloc_fixedsize_slowpath2 = 0
+ self.malloc_slowpath1 = 0
+ self.malloc_slowpath2 = 0
self.memcpy_addr = 0
self.setup_failure_recovery()
self._debug = False
@@ -123,8 +123,8 @@
self._build_failure_recovery(True, withfloats=True)
support.ensure_sse2_floats()
self._build_float_constants()
- if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
- self._build_malloc_fixedsize_slowpath()
+ if gc_ll_descr.get_malloc_slowpath_addr is not None:
+ self._build_malloc_slowpath()
self._build_stack_check_slowpath()
debug_start('jit-backend-counts')
self.set_debug(have_debug_prints())
@@ -171,7 +171,7 @@
self.float_const_neg_addr = float_constants
self.float_const_abs_addr = float_constants + 16
- def _build_malloc_fixedsize_slowpath(self):
+ def _build_malloc_slowpath(self):
# With asmgcc, we need two helpers, so that we can write two CALL
# instructions in assembler, with a mark_gc_roots in between.
# With shadowstack, this is not needed, so we produce a single helper.
@@ -183,7 +183,7 @@
for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8
mc.MOVSD_sx((WORD*2)+8*i, i)
mc.SUB_rr(edx.value, eax.value) # compute the size we want
- addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr()
+ addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
#
if gcrootmap is not None and gcrootmap.is_shadow_stack:
# ---- shadowstack ----
@@ -208,7 +208,7 @@
mc.MOV_rr(edi.value, edx.value)
mc.JMP(imm(addr)) # tail call to the real malloc
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
- self.malloc_fixedsize_slowpath1 = rawstart
+ self.malloc_slowpath1 = rawstart
# ---------- second helper for the slow path of malloc ----------
mc = codebuf.MachineCodeBlockWrapper()
#
@@ -219,7 +219,7 @@
mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX
mc.RET()
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
- self.malloc_fixedsize_slowpath2 = rawstart
+ self.malloc_slowpath2 = rawstart
def _build_stack_check_slowpath(self):
_, _, slowpathaddr = self.cpu.insert_stack_check()
@@ -1273,6 +1273,11 @@
assert isinstance(loc_vtable, ImmedLoc)
self.mc.MOV(mem(loc, self.cpu.vtable_offset), loc_vtable)
+ def set_new_array_length(self, loc, ofs_length, loc_num_elem):
+ assert isinstance(loc, RegLoc)
+ assert isinstance(loc_num_elem, ImmedLoc)
+ self.mc.MOV(mem(loc, ofs_length), loc_num_elem)
+
# XXX genop_new is abused for all varsized mallocs with Boehm, for now
# (instead of genop_new_array, genop_newstr, genop_newunicode)
def genop_new(self, op, arglocs, result_loc):
@@ -2094,8 +2099,7 @@
else:
self.mc.JMP(imm(loop_token._x86_loop_code))
- def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
- size, tid):
+ def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, tid):
size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
self.mc.MOV(eax, heap(nursery_free_adr))
self.mc.LEA_rm(edx.value, (eax.value, size))
@@ -2103,7 +2107,7 @@
self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
jmp_adr = self.mc.get_relative_pos()
- # See comments in _build_malloc_fixedsize_slowpath for the
+ # See comments in _build_malloc_slowpath for the
# details of the two helper functions that we are calling below.
# First, we need to call two of them and not just one because we
# need to have a mark_gc_roots() in between. Then the calling
@@ -2122,11 +2126,11 @@
shadow_stack = (gcrootmap is not None and gcrootmap.is_shadow_stack)
if not shadow_stack:
# there are two helpers to call only with asmgcc
- slowpath_addr1 = self.malloc_fixedsize_slowpath1
+ slowpath_addr1 = self.malloc_slowpath1
self.mc.CALL(imm(slowpath_addr1))
self.mark_gc_roots(self.write_new_force_index(),
use_copy_area=shadow_stack)
- slowpath_addr2 = self.malloc_fixedsize_slowpath2
+ slowpath_addr2 = self.malloc_slowpath2
self.mc.CALL(imm(slowpath_addr2))
offset = self.mc.get_relative_pos() - jmp_adr
diff --git a/pypy/module/cpyext/include/traceback.h b/pypy/module/cpyext/include/traceback.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/traceback.h
@@ -0,0 +1,12 @@
+#ifndef Py_TRACEBACK_H
+#define Py_TRACEBACK_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject PyTracebackObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_TRACEBACK_H */
More information about the Pypy-commit
mailing list