[pypy-svn] r67624 - in pypy/branch/spine-of-frames/pypy: annotation annotation/test config doc/config interpreter interpreter/astcompiler/tools interpreter/test jit/backend jit/backend/llgraph jit/backend/llsupport jit/backend/llsupport/test jit/backend/test jit/backend/x86 jit/backend/x86/test jit/metainterp jit/metainterp/test jit/tl module/__builtin__ module/_ast module/_ast/test module/_pickle_support module/_testing module/parser module/parser/test module/posix module/posix/test module/pypyjit module/pypyjit/test/loops module/token module/token/test objspace/std objspace/std/test rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gc rpython/memory/gctransform rpython/module rpython/ootypesystem rpython/ootypesystem/test rpython/test translator translator/c translator/c/gcc translator/c/gcc/test translator/c/src translator/c/test translator/cli translator/jvm translator/platform translator/tool
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Sep 10 16:45:17 CEST 2009
Author: cfbolz
Date: Thu Sep 10 16:45:13 2009
New Revision: 67624
Added:
pypy/branch/spine-of-frames/pypy/doc/config/objspace.std.newshortcut.txt
- copied unchanged from r67623, pypy/trunk/pypy/doc/config/objspace.std.newshortcut.txt
pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_gc_integration.py
- copied unchanged from r67623, pypy/trunk/pypy/jit/backend/x86/test/test_gc_integration.py
pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_recompilation.py
- copied unchanged from r67623, pypy/trunk/pypy/jit/backend/x86/test/test_recompilation.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_executor.py
- copied unchanged from r67623, pypy/trunk/pypy/jit/metainterp/test/test_executor.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_float.py
- copied unchanged from r67623, pypy/trunk/pypy/jit/metainterp/test/test_float.py
pypy/branch/spine-of-frames/pypy/rlib/rweakref.py
- copied unchanged from r67623, pypy/trunk/pypy/rlib/rweakref.py
pypy/branch/spine-of-frames/pypy/rlib/rweakrefimpl.py
- copied unchanged from r67623, pypy/trunk/pypy/rlib/rweakrefimpl.py
pypy/branch/spine-of-frames/pypy/rlib/test/test_rweakref.py
- copied unchanged from r67623, pypy/trunk/pypy/rlib/test/test_rweakref.py
Modified:
pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py
pypy/branch/spine-of-frames/pypy/annotation/builtin.py
pypy/branch/spine-of-frames/pypy/annotation/classdef.py
pypy/branch/spine-of-frames/pypy/annotation/model.py
pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py
pypy/branch/spine-of-frames/pypy/annotation/unaryop.py
pypy/branch/spine-of-frames/pypy/config/pypyoption.py
pypy/branch/spine-of-frames/pypy/interpreter/astcompiler/tools/ (props changed)
pypy/branch/spine-of-frames/pypy/interpreter/error.py
pypy/branch/spine-of-frames/pypy/interpreter/function.py
pypy/branch/spine-of-frames/pypy/interpreter/pycode.py
pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py
pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py
pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py
pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py
pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py
pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py
pypy/branch/spine-of-frames/pypy/jit/backend/model.py
pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py
pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py
pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py
pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py
pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py
pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py
pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py
pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py
pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py
pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py
pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py
pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py
pypy/branch/spine-of-frames/pypy/module/_ast/ (props changed)
pypy/branch/spine-of-frames/pypy/module/_ast/__init__.py (props changed)
pypy/branch/spine-of-frames/pypy/module/_ast/test/ (props changed)
pypy/branch/spine-of-frames/pypy/module/_ast/test/__init__.py (props changed)
pypy/branch/spine-of-frames/pypy/module/_ast/test/test_ast.py (props changed)
pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py
pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py
pypy/branch/spine-of-frames/pypy/module/_testing/ (props changed)
pypy/branch/spine-of-frames/pypy/module/parser/ (props changed)
pypy/branch/spine-of-frames/pypy/module/parser/test/ (props changed)
pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py
pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py
pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py
pypy/branch/spine-of-frames/pypy/module/pypyjit/test/loops/ (props changed)
pypy/branch/spine-of-frames/pypy/module/pypyjit/test/loops/dict_lookup.py (props changed)
pypy/branch/spine-of-frames/pypy/module/pypyjit/test/loops/simple_add.py (props changed)
pypy/branch/spine-of-frames/pypy/module/token/ (props changed)
pypy/branch/spine-of-frames/pypy/module/token/test/ (props changed)
pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py
pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py
pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py
pypy/branch/spine-of-frames/pypy/rlib/jit.py
pypy/branch/spine-of-frames/pypy/rlib/libffi.py
pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py
pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py
pypy/branch/spine-of-frames/pypy/rlib/rwin32.py
pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py
pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py
pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py
pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py
pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py
pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py
pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py
pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py
pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py
pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py
pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py
pypy/branch/spine-of-frames/pypy/rpython/rint.py
pypy/branch/spine-of-frames/pypy/rpython/rpbc.py
pypy/branch/spine-of-frames/pypy/rpython/rtyper.py
pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py
pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py
pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py
pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py
pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py
pypy/branch/spine-of-frames/pypy/translator/c/genc.py
pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h
pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py
pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py
pypy/branch/spine-of-frames/pypy/translator/driver.py
pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py
pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py
pypy/branch/spine-of-frames/pypy/translator/platform/posix.py
pypy/branch/spine-of-frames/pypy/translator/platform/windows.py
pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py
Log:
merge in changes from revisions r67429 through r67623 of trunk.
Modified: pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py (original)
+++ pypy/branch/spine-of-frames/pypy/annotation/bookkeeper.py Thu Sep 10 16:45:13 2009
@@ -11,8 +11,8 @@
SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
SomeUnicodeString, SomeList, SomeObject, HarmlesslyBlocked, \
SomeWeakRef, lltype_to_annotation
-from pypy.annotation.classdef import InstanceSource
-from pypy.annotation.listdef import ListDef
+from pypy.annotation.classdef import InstanceSource, ClassDef
+from pypy.annotation.listdef import ListDef, ListItem
from pypy.annotation.dictdef import DictDef
from pypy.annotation import description
from pypy.annotation.signature import annotationoftype
@@ -228,6 +228,38 @@
finally:
self.leave()
+ # sanity check: no flags attached to heap stored instances
+
+ seen = set()
+
+ def check_no_flags(s_value_or_def):
+ if isinstance(s_value_or_def, SomeInstance):
+ assert not s_value_or_def.flags, "instance annotation with flags escaped to the heap"
+ check_no_flags(s_value_or_def.classdef)
+ elif isinstance(s_value_or_def, SomeList):
+ check_no_flags(s_value_or_def.listdef.listitem)
+ elif isinstance(s_value_or_def, SomeDict):
+ check_no_flags(s_value_or_def.dictdef.dictkey)
+ check_no_flags(s_value_or_def.dictdef.dictvalue)
+ elif isinstance(s_value_or_def, SomeTuple):
+ for s_item in s_value_or_def.items:
+ check_no_flags(s_item)
+ elif isinstance(s_value_or_def, ClassDef):
+ if s_value_or_def in seen:
+ return
+ seen.add(s_value_or_def)
+ for attr in s_value_or_def.attrs.values():
+ s_attr = attr.s_value
+ check_no_flags(s_attr)
+ elif isinstance(s_value_or_def, ListItem):
+ if s_value_or_def in seen:
+ return
+ seen.add(s_value_or_def)
+ check_no_flags(s_value_or_def.s_value)
+
+ for clsdef in self.classdefs:
+ check_no_flags(clsdef)
+
def consider_call_site(self, call_op):
binding = self.annotator.binding
s_callable = binding(call_op.args[0])
Modified: pypy/branch/spine-of-frames/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/builtin.py (original)
+++ pypy/branch/spine-of-frames/pypy/annotation/builtin.py Thu Sep 10 16:45:13 2009
@@ -270,6 +270,9 @@
def OSError_init(s_self, *args):
pass
+def WindowsError_init(s_self, *args):
+ pass
+
def termios_error_init(s_self, *args):
pass
@@ -386,6 +389,15 @@
BUILTIN_ANALYZERS[getattr(OSError.__init__, 'im_func', OSError.__init__)] = (
OSError_init)
+try:
+ WindowsError
+except NameError:
+ pass
+else:
+ BUILTIN_ANALYZERS[getattr(WindowsError.__init__, 'im_func',
+ WindowsError.__init__)] = (
+ WindowsError_init)
+
BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf
try:
import unicodedata
Modified: pypy/branch/spine-of-frames/pypy/annotation/classdef.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/classdef.py (original)
+++ pypy/branch/spine-of-frames/pypy/annotation/classdef.py Thu Sep 10 16:45:13 2009
@@ -442,6 +442,13 @@
}
try:
+ WindowsError
+except NameError:
+ pass
+else:
+ FORCE_ATTRIBUTES_INTO_CLASSES[WindowsError] = {'winerror': SomeInteger()}
+
+try:
import termios
except ImportError:
pass
Modified: pypy/branch/spine-of-frames/pypy/annotation/model.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/model.py (original)
+++ pypy/branch/spine-of-frames/pypy/annotation/model.py Thu Sep 10 16:45:13 2009
@@ -632,15 +632,6 @@
# i think we can only get here in the case of void-returning
# functions
return s_None
- if isinstance(v, MethodType):
- ll_ptrtype = lltype.typeOf(v.im_self)
- assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
- return SomeLLADTMeth(ll_ptrtype, v.im_func)
- if isinstance(v, FunctionType):
- # this case should only be for staticmethod instances used in
- # adtmeths: the getattr() result is then a plain FunctionType object.
- from pypy.annotation.bookkeeper import getbookkeeper
- return getbookkeeper().immutablevalue(v)
if isinstance(v, lltype._interior_ptr):
ob = v._parent
if ob is None:
Modified: pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py (original)
+++ pypy/branch/spine-of-frames/pypy/annotation/test/test_annrpython.py Thu Sep 10 16:45:13 2009
@@ -2785,6 +2785,64 @@
assert isinstance(s.items[2], annmodel.SomeInstance)
assert s.items[2].flags == {}
+ def test_no_access_directly_on_heap(self):
+ from pypy.rlib.jit import hint
+
+ class A:
+ _virtualizable2_ = []
+
+ class I:
+ pass
+
+ def f():
+ x = A()
+ x = hint(x, access_directly=True)
+ i = I()
+ i.x = x
+
+ a = self.RPythonAnnotator()
+ py.test.raises(Exception, a.build_types, f, [])
+
+
+ class M:
+ def __init__(self):
+ self.l = []
+ self.d = {}
+
+ class C:
+ def _freeze_(self):
+ return True
+
+ def __init__(self):
+ self.m = M()
+ self.l2 = []
+
+ c = C()
+
+ def f():
+ x = A()
+ x = hint(x, access_directly=True)
+ c.m.l.append(x)
+
+ a = self.RPythonAnnotator()
+ py.test.raises(AssertionError, a.build_types, f, [])
+
+ def f():
+ x = A()
+ x = hint(x, access_directly=True)
+ c.m.d[None] = x
+
+ a = self.RPythonAnnotator()
+ py.test.raises(AssertionError, a.build_types, f, [])
+
+ def f():
+ x = A()
+ x = hint(x, access_directly=True)
+ c.m.d[x] = None
+
+ a = self.RPythonAnnotator()
+ py.test.raises(AssertionError, a.build_types, f, [])
+
def test_ctr_location(self):
from pypy.rlib.jit import hint
Modified: pypy/branch/spine-of-frames/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/annotation/unaryop.py (original)
+++ pypy/branch/spine-of-frames/pypy/annotation/unaryop.py Thu Sep 10 16:45:13 2009
@@ -2,6 +2,7 @@
Unary operations on SomeValues.
"""
+from types import MethodType
from pypy.annotation.model import \
SomeObject, SomeInteger, SomeBool, SomeString, SomeChar, SomeList, \
SomeDict, SomeTuple, SomeImpossibleValue, \
@@ -727,8 +728,19 @@
def getattr(p, s_attr):
assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype
- v = getattr(p.ll_ptrtype._example(), s_attr.const)
- return ll_to_annotation(v)
+ example = p.ll_ptrtype._example()
+ try:
+ v = example._lookup_adtmeth(s_attr.const)
+ except AttributeError:
+ v = getattr(example, s_attr.const)
+ return ll_to_annotation(v)
+ else:
+ if isinstance(v, MethodType):
+ from pypy.rpython.lltypesystem import lltype
+ ll_ptrtype = lltype.typeOf(v.im_self)
+ assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
+ return SomeLLADTMeth(ll_ptrtype, v.im_func)
+ return getbookkeeper().immutablevalue(v)
getattr.can_only_throw = []
def len(p):
Modified: pypy/branch/spine-of-frames/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/config/pypyoption.py (original)
+++ pypy/branch/spine-of-frames/pypy/config/pypyoption.py Thu Sep 10 16:45:13 2009
@@ -328,6 +328,9 @@
BoolOption("getattributeshortcut",
"track types that override __getattribute__",
default=False),
+ BoolOption("newshortcut",
+ "cache and shortcut calling __new__ from builtin types",
+ default=False),
BoolOption("logspaceoptypes",
"a instrumentation option: before exit, print the types seen by "
@@ -369,6 +372,7 @@
config.objspace.std.suggest(builtinshortcut=True)
config.objspace.std.suggest(optimized_list_getitem=True)
config.objspace.std.suggest(getattributeshortcut=True)
+ config.objspace.std.suggest(newshortcut=True)
# extra costly optimizations only go in level 3
if level == '3':
@@ -396,7 +400,8 @@
# extra optimizations with the JIT
if level == 'jit':
- config.objspace.std.suggest(withsharingdict=True)
+ if type_system != 'ootype':
+ config.objspace.std.suggest(withsharingdict=True)
config.objspace.std.suggest(withcelldict=True)
Modified: pypy/branch/spine-of-frames/pypy/interpreter/error.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/error.py (original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/error.py Thu Sep 10 16:45:13 2009
@@ -262,8 +262,33 @@
# 31: ANSI color code "red"
ansi_print(text, esc="31", file=file, newline=newline)
+try:
+ WindowsError
+except NameError:
+ _WINDOWS = False
+else:
+ _WINDOWS = True
+
+ def wrap_windowserror(space, e):
+ from pypy.rlib import rwin32
+
+ winerror = e.winerror
+ try:
+ msg = rwin32.FormatError(winerror)
+ except ValueError:
+ msg = 'Windows Error %d' % winerror
+ exc = space.w_WindowsError
+ w_error = space.call_function(exc,
+ space.wrap(winerror),
+ space.wrap(msg))
+ return OperationError(exc, w_error)
+
def wrap_oserror(space, e, exception_name='w_OSError'):
assert isinstance(e, OSError)
+
+ if _WINDOWS and isinstance(e, WindowsError):
+ return wrap_windowserror(space, e)
+
errno = e.errno
try:
msg = os.strerror(errno)
Modified: pypy/branch/spine-of-frames/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/function.py (original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/function.py Thu Sep 10 16:45:13 2009
@@ -39,11 +39,11 @@
def call_args(self, args):
# delegate activation to code
- return self.code.funcrun(self, args)
+ return self.getcode().funcrun(self, args)
def call_obj_args(self, w_obj, args):
# delegate activation to code
- return self.code.funcrun_obj(self, w_obj, args)
+ return self.getcode().funcrun_obj(self, w_obj, args)
def getcode(self):
return hint(self.code, promote=True)
Modified: pypy/branch/spine-of-frames/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/pycode.py (original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/pycode.py Thu Sep 10 16:45:13 2009
@@ -184,28 +184,30 @@
self.fast_natural_arity = PyCode.FLATPYCALL | self.co_argcount
- @jit.dont_look_inside
def funcrun(self, func, args):
frame = self.space.createframe(self, func.w_func_globals,
func.closure)
sig = self._signature
# speed hack
- args_matched = args.parse_into_scope(None, frame.fastlocals_w,
+ fresh_frame = jit.hint(frame, access_directly=True,
+ fresh_virtualizable=True)
+ args_matched = args.parse_into_scope(None, fresh_frame.fastlocals_w,
func.name,
sig, func.defs_w)
- frame.init_cells()
+ fresh_frame.init_cells()
return frame.run()
- @jit.dont_look_inside
def funcrun_obj(self, func, w_obj, args):
frame = self.space.createframe(self, func.w_func_globals,
func.closure)
sig = self._signature
# speed hack
- args_matched = args.parse_into_scope(w_obj, frame.fastlocals_w,
+ fresh_frame = jit.hint(frame, access_directly=True,
+ fresh_virtualizable=True)
+ args_matched = args.parse_into_scope(w_obj, fresh_frame.fastlocals_w,
func.name,
sig, func.defs_w)
- frame.init_cells()
+ fresh_frame.init_cells()
return frame.run()
def getvarnames(self):
Modified: pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py (original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/test/test_compiler.py Thu Sep 10 16:45:13 2009
@@ -641,21 +641,17 @@
def setup_method(self, method):
self.compiler = CPythonCompiler(self.space)
- _unicode_error_kind = "w_SyntaxError"
-
- if sys.version_info < (2, 4):
- def skip_on_2_3(self):
- py.test.skip("syntax not supported by the CPython 2.3 compiler")
- test_unicodeliterals = skip_on_2_3
- test_none_assignment = skip_on_2_3
- test_import = skip_on_2_3
- elif sys.version_info < (2, 5):
+ if sys.version_info < (2, 5):
def skip_on_2_4(self):
py.test.skip("syntax not supported by the CPython 2.4 compiler")
_unicode_error_kind = "w_UnicodeError"
test_continue_in_nested_finally = skip_on_2_4
test_try_except_finally = skip_on_2_4
test_yield_in_finally = skip_on_2_4
+ elif sys.version_info < (2, 6):
+ _unicode_error_kind = "w_UnicodeDecodeError"
+ else:
+ _unicode_error_kind = "w_SyntaxError"
class TestPythonAstCompiler_25_grammar(BaseTestCompiler):
def setup_method(self, method):
Modified: pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py (original)
+++ pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py Thu Sep 10 16:45:13 2009
@@ -374,7 +374,19 @@
result = pickle.loads(pckl)
raises(TypeError, len, diter)
assert list(diter) == list(result)
-
+
+ def test_pickle_reversed(self):
+ import pickle
+ r = reversed(tuple(range(10)))
+ r.next()
+ r.next()
+ pickled = pickle.dumps(r)
+ result = pickle.loads(pickled)
+ result.next()
+ r.next()
+ assert type(r) is type(result)
+ assert list(r) == list(result)
+
def test_pickle_enum(self):
import pickle
e = enumerate(range(10))
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/llimpl.py Thu Sep 10 16:45:13 2009
@@ -8,7 +8,8 @@
from pypy.objspace.flow.model import Variable, Constant
from pypy.annotation import model as annmodel
from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr,
- BoxInt, BoxPtr, BoxObj, REF)
+ BoxInt, BoxPtr, BoxObj, BoxFloat,
+ REF, INT, FLOAT)
from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.module.support import LLSupport, OOSupport
@@ -82,6 +83,21 @@
'uint_ge' : (('int', 'int'), 'bool'),
'uint_xor' : (('int', 'int'), 'int'),
'uint_rshift' : (('int', 'int'), 'int'),
+ 'float_add' : (('float', 'float'), 'float'),
+ 'float_sub' : (('float', 'float'), 'float'),
+ 'float_mul' : (('float', 'float'), 'float'),
+ 'float_truediv' : (('float', 'float'), 'float'),
+ 'float_lt' : (('float', 'float'), 'bool'),
+ 'float_le' : (('float', 'float'), 'bool'),
+ 'float_eq' : (('float', 'float'), 'bool'),
+ 'float_ne' : (('float', 'float'), 'bool'),
+ 'float_gt' : (('float', 'float'), 'bool'),
+ 'float_ge' : (('float', 'float'), 'bool'),
+ 'float_neg' : (('float',), 'float'),
+ 'float_abs' : (('float',), 'float'),
+ 'float_is_true' : (('float',), 'bool'),
+ 'cast_float_to_int':(('float',), 'int'),
+ 'cast_int_to_float':(('int',), 'float'),
'same_as' : (('int',), 'int'), # could also be ptr=>ptr
'new_with_vtable' : (('ref',), 'ref'),
'new' : ((), 'ref'),
@@ -124,7 +140,6 @@
'unicodegetitem' : (('ref', 'int'), 'int'),
'unicodesetitem' : (('ref', 'int', 'int'), 'int'),
'cast_ptr_to_int' : (('ref',), 'int'),
- 'cast_int_to_ptr' : (('int',), 'ref'),
'debug_merge_point': (('ref',), None),
#'getitem' : (('void', 'ref', 'int'), 'int'),
#'setitem' : (('void', 'ref', 'int', 'int'), None),
@@ -249,6 +264,8 @@
return str(bool(x))
#elif tp == 'fieldname':
# return str(symbolic.TokenToField[x...][1])
+ elif tp == 'float':
+ return str(x)
else:
raise NotImplementedError("tp = %s" % tp)
@@ -259,14 +276,10 @@
return _to_opaque(CompiledLoop())
def compile_start_int_var(loop):
- loop = _from_opaque(loop)
- assert not loop.operations
- v = Variable()
- v.concretetype = lltype.Signed
- loop.inputargs.append(v)
- r = len(_variables)
- _variables.append(v)
- return r
+ return compile_start_ref_var(loop, lltype.Signed)
+
+def compile_start_float_var(loop):
+ return compile_start_ref_var(loop, lltype.Float)
def compile_start_ref_var(loop, TYPE):
loop = _from_opaque(loop)
@@ -295,11 +308,10 @@
op.args.append(_variables[intvar])
def compile_add_int_const(loop, value):
- loop = _from_opaque(loop)
- const = Constant(value)
- const.concretetype = lltype.Signed
- op = loop.operations[-1]
- op.args.append(const)
+ compile_add_ref_const(loop, value, lltype.Signed)
+
+def compile_add_float_const(loop, value):
+ compile_add_ref_const(loop, value, lltype.Float)
def compile_add_ref_const(loop, value, TYPE):
loop = _from_opaque(loop)
@@ -309,14 +321,10 @@
op.args.append(const)
def compile_add_int_result(loop):
- loop = _from_opaque(loop)
- v = Variable()
- v.concretetype = lltype.Signed
- op = loop.operations[-1]
- op.result = v
- r = len(_variables)
- _variables.append(v)
- return r
+ return compile_add_ref_result(loop, lltype.Signed)
+
+def compile_add_float_result(loop):
+ return compile_add_ref_result(loop, lltype.Float)
def compile_add_ref_result(loop, TYPE):
loop = _from_opaque(loop)
@@ -411,6 +419,8 @@
x = self.as_ptr(result)
elif RESTYPE is ootype.Object:
x = self.as_object(result)
+ elif RESTYPE is lltype.Float:
+ x = self.as_float(result)
else:
raise Exception("op.result.concretetype is %r"
% (RESTYPE,))
@@ -473,6 +483,9 @@
def as_object(self, x):
return ootype.cast_to_object(x)
+ def as_float(self, x):
+ return cast_to_float(x)
+
def log_progress(self):
count = sum(_stats.exec_counters.values())
count_jumps = _stats.exec_jumps
@@ -501,6 +514,8 @@
for x in args:
if type(x) is int:
boxedargs.append(BoxInt(x))
+ elif type(x) is float:
+ boxedargs.append(BoxFloat(x))
elif isinstance(ootype.typeOf(x), ootype.OOType):
boxedargs.append(BoxObj(ootype.cast_to_object(x)))
else:
@@ -617,24 +632,36 @@
def op_getarrayitem_gc(self, arraydescr, array, index):
if arraydescr.typeinfo == REF:
return do_getarrayitem_gc_ptr(array, index)
- else:
+ elif arraydescr.typeinfo == INT:
return do_getarrayitem_gc_int(array, index, self.memocast)
+ elif arraydescr.typeinfo == FLOAT:
+ return do_getarrayitem_gc_float(array, index)
+ else:
+ raise NotImplementedError
op_getarrayitem_gc_pure = op_getarrayitem_gc
def op_getfield_gc(self, fielddescr, struct):
if fielddescr.typeinfo == REF:
return do_getfield_gc_ptr(struct, fielddescr.ofs)
- else:
+ elif fielddescr.typeinfo == INT:
return do_getfield_gc_int(struct, fielddescr.ofs, self.memocast)
+ elif fielddescr.typeinfo == FLOAT:
+ return do_getfield_gc_float(struct, fielddescr.ofs)
+ else:
+ raise NotImplementedError
op_getfield_gc_pure = op_getfield_gc
def op_getfield_raw(self, fielddescr, struct):
if fielddescr.typeinfo == REF:
return do_getfield_raw_ptr(struct, fielddescr.ofs, self.memocast)
- else:
+ elif fielddescr.typeinfo == INT:
return do_getfield_raw_int(struct, fielddescr.ofs, self.memocast)
+ elif fielddescr.typeinfo == FLOAT:
+ return do_getfield_raw_float(struct, fielddescr.ofs, self.memocast)
+ else:
+ raise NotImplementedError
def op_new(self, size):
return do_new(size.ofs)
@@ -650,23 +677,36 @@
def op_setarrayitem_gc(self, arraydescr, array, index, newvalue):
if arraydescr.typeinfo == REF:
do_setarrayitem_gc_ptr(array, index, newvalue)
- else:
+ elif arraydescr.typeinfo == INT:
do_setarrayitem_gc_int(array, index, newvalue, self.memocast)
+ elif arraydescr.typeinfo == FLOAT:
+ do_setarrayitem_gc_float(array, index, newvalue)
+ else:
+ raise NotImplementedError
def op_setfield_gc(self, fielddescr, struct, newvalue):
if fielddescr.typeinfo == REF:
do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
- else:
+ elif fielddescr.typeinfo == INT:
do_setfield_gc_int(struct, fielddescr.ofs, newvalue,
self.memocast)
+ elif fielddescr.typeinfo == FLOAT:
+ do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
+ else:
+ raise NotImplementedError
def op_setfield_raw(self, fielddescr, struct, newvalue):
if fielddescr.typeinfo == REF:
do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue,
self.memocast)
- else:
+ elif fielddescr.typeinfo == INT:
do_setfield_raw_int(struct, fielddescr.ofs, newvalue,
self.memocast)
+ elif fielddescr.typeinfo == FLOAT:
+ do_setfield_raw_float(struct, fielddescr.ofs, newvalue,
+ self.memocast)
+ else:
+ raise NotImplementedError
def op_call(self, calldescr, func, *args):
_call_args[:] = args
@@ -674,9 +714,12 @@
err_result = None
elif calldescr.typeinfo == REF:
err_result = lltype.nullptr(llmemory.GCREF.TO)
- else:
- assert calldescr.typeinfo == 'i'
+ elif calldescr.typeinfo == INT:
err_result = 0
+ elif calldescr.typeinfo == FLOAT:
+ err_result = 0.0
+ else:
+ raise NotImplementedError
return _do_call_common(func, self.memocast, err_result)
op_call_pure = op_call
@@ -696,9 +739,6 @@
def op_cast_ptr_to_int(self, descr, ptr):
return cast_to_int(ptr, self.memocast)
- def op_cast_int_to_ptr(self, descr, val):
- return cast_from_int(llmemory.GCREF, val, self.memocast)
-
def op_uint_xor(self, descr, arg1, arg2):
return arg1 ^ arg2
@@ -735,6 +775,8 @@
obj = ootype.cast_from_object(TYPE, obj)
if isinstance(ootype.typeOf(newvalue), ootype.OOType):
newvalue = ootype.cast_from_object(T, newvalue)
+ elif isinstance(T, lltype.Primitive):
+ newvalue = lltype.cast_primitive(T, newvalue)
setattr(obj, fieldname, newvalue)
def op_getarrayitem_gc(self, typedescr, obj, index):
@@ -834,6 +876,15 @@
def cast_from_ptr(TYPE, x):
return lltype.cast_opaque_ptr(TYPE, x)
+def cast_to_float(x): # not really a cast, just a type check
+ assert isinstance(x, float)
+ return x
+
+def cast_from_float(TYPE, x): # not really a cast, just a type check
+ assert TYPE is lltype.Float
+ assert isinstance(x, float)
+ return x
+
def new_frame(memocast, is_oo):
if is_oo:
@@ -857,9 +908,10 @@
del _future_values[:]
def set_future_value_int(index, value):
- del _future_values[index:]
- assert len(_future_values) == index
- _future_values.append(value)
+ set_future_value_ref(index, value)
+
+def set_future_value_float(index, value):
+ set_future_value_ref(index, value)
def set_future_value_ref(index, value):
del _future_values[index:]
@@ -890,6 +942,10 @@
frame = _from_opaque(frame)
return frame.fail_args[num]
+def frame_float_getvalue(frame, num):
+ frame = _from_opaque(frame)
+ return frame.fail_args[num]
+
def frame_ptr_getvalue(frame, num):
frame = _from_opaque(frame)
result = frame.fail_args[num]
@@ -1013,33 +1069,41 @@
array = array._obj.container
return cast_to_int(array.getitem(index), memocast)
+def do_getarrayitem_gc_float(array, index):
+ array = array._obj.container
+ return cast_to_float(array.getitem(index))
+
def do_getarrayitem_gc_ptr(array, index):
array = array._obj.container
return cast_to_ptr(array.getitem(index))
-def do_getfield_gc_int(struct, fieldnum, memocast):
+def _getfield_gc(struct, fieldnum):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
- x = getattr(ptr, fieldname)
- return cast_to_int(x, memocast)
+ return getattr(ptr, fieldname)
+
+def do_getfield_gc_int(struct, fieldnum, memocast):
+ return cast_to_int(_getfield_gc(struct, fieldnum), memocast)
+
+def do_getfield_gc_float(struct, fieldnum):
+ return cast_to_float(_getfield_gc(struct, fieldnum))
def do_getfield_gc_ptr(struct, fieldnum):
- STRUCT, fieldname = symbolic.TokenToField[fieldnum]
- ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
- x = getattr(ptr, fieldname)
- return cast_to_ptr(x)
+ return cast_to_ptr(_getfield_gc(struct, fieldnum))
-def do_getfield_raw_int(struct, fieldnum, memocast):
+def _getfield_raw(struct, fieldnum, memocast):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
- x = getattr(ptr, fieldname)
- return cast_to_int(x, memocast)
+ return getattr(ptr, fieldname)
+
+def do_getfield_raw_int(struct, fieldnum, memocast):
+ return cast_to_int(_getfield_raw(struct, fieldnum, memocast), memocast)
+
+def do_getfield_raw_float(struct, fieldnum, memocast):
+ return cast_to_float(_getfield_raw(struct, fieldnum, memocast))
def do_getfield_raw_ptr(struct, fieldnum, memocast):
- STRUCT, fieldname = symbolic.TokenToField[fieldnum]
- ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
- x = getattr(ptr, fieldname)
- return cast_to_ptr(x)
+ return cast_to_ptr(_getfield_raw(struct, fieldnum, memocast))
def do_new(size):
TYPE = symbolic.Size2Type[size]
@@ -1057,6 +1121,12 @@
newvalue = cast_from_int(ITEMTYPE, newvalue, memocast)
array.setitem(index, newvalue)
+def do_setarrayitem_gc_float(array, index, newvalue):
+ array = array._obj.container
+ ITEMTYPE = lltype.typeOf(array).OF
+ newvalue = cast_from_float(ITEMTYPE, newvalue)
+ array.setitem(index, newvalue)
+
def do_setarrayitem_gc_ptr(array, index, newvalue):
array = array._obj.container
ITEMTYPE = lltype.typeOf(array).OF
@@ -1070,6 +1140,13 @@
newvalue = cast_from_int(FIELDTYPE, newvalue, memocast)
setattr(ptr, fieldname, newvalue)
+def do_setfield_gc_float(struct, fieldnum, newvalue):
+ STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+ ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
+ FIELDTYPE = getattr(STRUCT, fieldname)
+ newvalue = cast_from_float(FIELDTYPE, newvalue)
+ setattr(ptr, fieldname, newvalue)
+
def do_setfield_gc_ptr(struct, fieldnum, newvalue):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
@@ -1084,6 +1161,13 @@
newvalue = cast_from_int(FIELDTYPE, newvalue, memocast)
setattr(ptr, fieldname, newvalue)
+def do_setfield_raw_float(struct, fieldnum, newvalue, memocast):
+ STRUCT, fieldname = symbolic.TokenToField[fieldnum]
+ ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
+ FIELDTYPE = getattr(STRUCT, fieldname)
+ newvalue = cast_from_float(FIELDTYPE, newvalue)
+ setattr(ptr, fieldname, newvalue)
+
def do_setfield_raw_ptr(struct, fieldnum, newvalue, memocast):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = cast_from_int(lltype.Ptr(STRUCT), struct, memocast)
@@ -1113,6 +1197,9 @@
def do_call_pushint(x):
_call_args.append(x)
+def do_call_pushfloat(x):
+ _call_args.append(x)
+
def do_call_pushptr(x):
_call_args.append(x)
@@ -1143,6 +1230,10 @@
x = _do_call_common(f, memocast, 0)
return cast_to_int(x, memocast)
+def do_call_float(f, memocast):
+ x = _do_call_common(f, memocast, 0)
+ return cast_to_float(x)
+
def do_call_ptr(f, memocast):
x = _do_call_common(f, memocast, lltype.nullptr(llmemory.GCREF.TO))
return cast_to_ptr(x)
@@ -1159,6 +1250,8 @@
x = ootype.cast_from_object(TYPE, x)
elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
x = cast_from_ptr(TYPE, x)
+ elif TYPE is lltype.Float:
+ x = cast_from_float(TYPE, x)
else:
x = cast_from_int(TYPE, x, memocast)
args.append(x)
@@ -1175,15 +1268,15 @@
else:
mymethod = meth
myargs = args
- if hasattr(mymethod, 'graph'):
- llinterp = _llinterp # it's a global set here by CPU.__init__()
- try:
+ try:
+ if hasattr(mymethod, 'graph'):
+ llinterp = _llinterp # it's a global set here by CPU.__init__()
result = llinterp.eval_graph(mymethod.graph, myargs)
- except LLException, e:
- _last_exception = e
- result = get_err_result_for_type(mymethod._TYPE.RESULT)
- else:
- result = meth(*args) # no exception support in this case
+ else:
+ result = meth(*args)
+ except LLException, e:
+ _last_exception = e
+ result = get_err_result_for_type(mymethod._TYPE.RESULT)
return result
def get_err_result_for_type(T):
@@ -1248,13 +1341,16 @@
setannotation(compile_start, s_CompiledLoop)
setannotation(compile_start_int_var, annmodel.SomeInteger())
setannotation(compile_start_ref_var, annmodel.SomeInteger())
+setannotation(compile_start_float_var, annmodel.SomeInteger())
setannotation(compile_add, annmodel.s_None)
setannotation(compile_add_descr, annmodel.s_None)
setannotation(compile_add_var, annmodel.s_None)
setannotation(compile_add_int_const, annmodel.s_None)
setannotation(compile_add_ref_const, annmodel.s_None)
+setannotation(compile_add_float_const, annmodel.s_None)
setannotation(compile_add_int_result, annmodel.SomeInteger())
setannotation(compile_add_ref_result, annmodel.SomeInteger())
+setannotation(compile_add_float_result, annmodel.SomeInteger())
setannotation(compile_add_jump_target, annmodel.s_None)
setannotation(compile_add_fail, annmodel.s_None)
setannotation(compile_suboperations, s_CompiledLoop)
@@ -1264,9 +1360,11 @@
setannotation(frame_clear, annmodel.s_None)
setannotation(set_future_value_int, annmodel.s_None)
setannotation(set_future_value_ref, annmodel.s_None)
+setannotation(set_future_value_float, annmodel.s_None)
setannotation(frame_execute, annmodel.SomeInteger())
setannotation(frame_int_getvalue, annmodel.SomeInteger())
setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF))
+setannotation(frame_float_getvalue, annmodel.SomeFloat())
setannotation(get_exception, annmodel.SomeAddress())
setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF))
@@ -1288,18 +1386,24 @@
setannotation(do_unicodegetitem, annmodel.SomeInteger())
setannotation(do_getarrayitem_gc_int, annmodel.SomeInteger())
setannotation(do_getarrayitem_gc_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getarrayitem_gc_float, annmodel.SomeFloat())
setannotation(do_getfield_gc_int, annmodel.SomeInteger())
setannotation(do_getfield_gc_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getfield_gc_float, annmodel.SomeFloat())
setannotation(do_getfield_raw_int, annmodel.SomeInteger())
setannotation(do_getfield_raw_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_getfield_raw_float, annmodel.SomeFloat())
setannotation(do_new, annmodel.SomePtr(llmemory.GCREF))
setannotation(do_new_array, annmodel.SomePtr(llmemory.GCREF))
setannotation(do_setarrayitem_gc_int, annmodel.s_None)
setannotation(do_setarrayitem_gc_ptr, annmodel.s_None)
+setannotation(do_setarrayitem_gc_float, annmodel.s_None)
setannotation(do_setfield_gc_int, annmodel.s_None)
setannotation(do_setfield_gc_ptr, annmodel.s_None)
+setannotation(do_setfield_gc_float, annmodel.s_None)
setannotation(do_setfield_raw_int, annmodel.s_None)
setannotation(do_setfield_raw_ptr, annmodel.s_None)
+setannotation(do_setfield_raw_float, annmodel.s_None)
setannotation(do_newstr, annmodel.SomePtr(llmemory.GCREF))
setannotation(do_strsetitem, annmodel.s_None)
setannotation(do_newunicode, annmodel.SomePtr(llmemory.GCREF))
@@ -1308,4 +1412,5 @@
setannotation(do_call_pushptr, annmodel.s_None)
setannotation(do_call_int, annmodel.SomeInteger())
setannotation(do_call_ptr, annmodel.SomePtr(llmemory.GCREF))
+setannotation(do_call_float, annmodel.SomeFloat())
setannotation(do_call_void, annmodel.s_None)
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llgraph/runner.py Thu Sep 10 16:45:13 2009
@@ -8,7 +8,7 @@
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.llinterp import LLInterpreter
from pypy.jit.metainterp import history
-from pypy.jit.metainterp.history import REF
+from pypy.jit.metainterp.history import REF, INT, FLOAT
from pypy.jit.metainterp.warmspot import unwrap
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.backend import model
@@ -74,6 +74,7 @@
class BaseCPU(model.AbstractCPU):
+ supports_floats = True
def __init__(self, rtyper, stats=None, translate_support_code=False,
annmixlevel=None, gcdescr=None):
@@ -118,6 +119,8 @@
elif isinstance(box, self.ts.BoxRef):
TYPE = self.ts.BASETYPE
var2index[box] = llimpl.compile_start_ref_var(c, TYPE)
+ elif isinstance(box, history.BoxFloat):
+ var2index[box] = llimpl.compile_start_float_var(c)
else:
raise Exception("box is: %r" % (box,))
self._compile_branch(c, loop.operations, var2index)
@@ -144,6 +147,8 @@
llimpl.compile_add_ref_const(c, x.value, self.ts.BASETYPE)
elif isinstance(x, history.ConstAddr):
llimpl.compile_add_int_const(c, x.getint())
+ elif isinstance(x, history.ConstFloat):
+ llimpl.compile_add_float_const(c, x.value)
else:
raise Exception("%s args contain: %r" % (op.getopname(),
x))
@@ -156,6 +161,8 @@
var2index[x] = llimpl.compile_add_int_result(c)
elif isinstance(x, self.ts.BoxRef):
var2index[x] = llimpl.compile_add_ref_result(c, self.ts.BASETYPE)
+ elif isinstance(x, history.BoxFloat):
+ var2index[x] = llimpl.compile_add_float_result(c)
else:
raise Exception("%s.result contain: %r" % (op.getopname(),
x))
@@ -186,12 +193,18 @@
def set_future_value_ref(self, index, objvalue):
llimpl.set_future_value_ref(index, objvalue)
+ def set_future_value_float(self, index, floatvalue):
+ llimpl.set_future_value_float(index, floatvalue)
+
def get_latest_value_int(self, index):
return llimpl.frame_int_getvalue(self.latest_frame, index)
def get_latest_value_ref(self, index):
return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+ def get_latest_value_float(self, index):
+ return llimpl.frame_float_getvalue(self.latest_frame, index)
+
# ----------
def get_exception(self):
@@ -228,6 +241,9 @@
def cast_int_to_adr(self, int):
return llimpl.cast_int_to_adr(self.memo_cast, int)
+ def cast_gcref_to_int(self, gcref):
+ return self.cast_adr_to_int(llmemory.cast_ptr_to_adr(gcref))
+
class LLtypeCPU(BaseCPU):
@@ -299,9 +315,14 @@
index = args[1].getint()
if arraydescr.typeinfo == REF:
return history.BoxPtr(llimpl.do_getarrayitem_gc_ptr(array, index))
- else:
+ elif arraydescr.typeinfo == INT:
return history.BoxInt(llimpl.do_getarrayitem_gc_int(array, index,
self.memo_cast))
+ elif arraydescr.typeinfo == FLOAT:
+ return history.BoxFloat(llimpl.do_getarrayitem_gc_float(array,
+ index))
+ else:
+ raise NotImplementedError
def do_getfield_gc(self, args, fielddescr):
assert isinstance(fielddescr, Descr)
@@ -309,10 +330,16 @@
if fielddescr.typeinfo == REF:
return history.BoxPtr(llimpl.do_getfield_gc_ptr(struct,
fielddescr.ofs))
- else:
+ elif fielddescr.typeinfo == INT:
return history.BoxInt(llimpl.do_getfield_gc_int(struct,
fielddescr.ofs,
self.memo_cast))
+ elif fielddescr.typeinfo == FLOAT:
+ return history.BoxFloat(llimpl.do_getfield_gc_float(struct,
+ fielddescr.ofs))
+ else:
+ raise NotImplementedError
+
def do_getfield_raw(self, args, fielddescr):
assert isinstance(fielddescr, Descr)
struct = self.cast_int_to_adr(args[0].getint())
@@ -320,10 +347,16 @@
return history.BoxPtr(llimpl.do_getfield_raw_ptr(struct,
fielddescr.ofs,
self.memo_cast))
- else:
+ elif fielddescr.typeinfo == INT:
return history.BoxInt(llimpl.do_getfield_raw_int(struct,
fielddescr.ofs,
self.memo_cast))
+ elif fielddescr.typeinfo == FLOAT:
+ return history.BoxFloat(llimpl.do_getfield_raw_float(struct,
+ fielddescr.ofs,
+ self.memo_cast))
+ else:
+ raise NotImplementedError
def do_new(self, args, size):
assert isinstance(size, Descr)
@@ -350,10 +383,15 @@
if arraydescr.typeinfo == REF:
newvalue = args[2].getref_base()
llimpl.do_setarrayitem_gc_ptr(array, index, newvalue)
- else:
+ elif arraydescr.typeinfo == INT:
newvalue = args[2].getint()
llimpl.do_setarrayitem_gc_int(array, index, newvalue,
self.memo_cast)
+ elif arraydescr.typeinfo == FLOAT:
+ newvalue = args[2].getfloat()
+ llimpl.do_setarrayitem_gc_float(array, index, newvalue)
+ else:
+ raise NotImplementedError
def do_setfield_gc(self, args, fielddescr):
assert isinstance(fielddescr, Descr)
@@ -361,10 +399,15 @@
if fielddescr.typeinfo == REF:
newvalue = args[1].getref_base()
llimpl.do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
- else:
+ elif fielddescr.typeinfo == INT:
newvalue = args[1].getint()
llimpl.do_setfield_gc_int(struct, fielddescr.ofs, newvalue,
self.memo_cast)
+ elif fielddescr.typeinfo == FLOAT:
+ newvalue = args[1].getfloat()
+ llimpl.do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
+ else:
+ raise NotImplementedError
def do_setfield_raw(self, args, fielddescr):
assert isinstance(fielddescr, Descr)
@@ -373,10 +416,16 @@
newvalue = args[1].getref_base()
llimpl.do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue,
self.memo_cast)
- else:
+ elif fielddescr.typeinfo == INT:
newvalue = args[1].getint()
llimpl.do_setfield_raw_int(struct, fielddescr.ofs, newvalue,
self.memo_cast)
+ elif fielddescr.typeinfo == FLOAT:
+ newvalue = args[1].getfloat()
+ llimpl.do_setfield_raw_float(struct, fielddescr.ofs, newvalue,
+ self.memo_cast)
+ else:
+ raise NotImplementedError
def do_same_as(self, args, descr=None):
return args[0].clonebox()
@@ -416,16 +465,14 @@
llimpl.do_call_pushint(arg.getint())
if calldescr.typeinfo == REF:
return history.BoxPtr(llimpl.do_call_ptr(func, self.memo_cast))
- elif calldescr.typeinfo == 'i':
+ elif calldescr.typeinfo == INT:
return history.BoxInt(llimpl.do_call_int(func, self.memo_cast))
- else: # calldescr.typeinfo == 'v' # void
+ elif calldescr.typeinfo == FLOAT:
+ return history.BoxFloat(llimpl.do_call_float(func, self.memo_cast))
+ elif calldescr.typeinfo == 'v': # void
llimpl.do_call_void(func, self.memo_cast)
-
- def do_cast_int_to_ptr(self, args, descr=None):
- assert descr is None
- return history.BoxPtr(llimpl.cast_from_int(llmemory.GCREF,
- args[0].getint(),
- self.memo_cast))
+ else:
+ raise NotImplementedError
def do_cast_ptr_to_int(self, args, descr=None):
assert descr is None
@@ -573,6 +620,8 @@
def boxresult(RESULT, result):
if isinstance(RESULT, ootype.OOType):
return history.BoxObj(ootype.cast_to_object(result))
+ elif RESULT is lltype.Float:
+ return history.BoxFloat(result)
else:
return history.BoxInt(lltype.cast_primitive(ootype.Signed, result))
boxresult._annspecialcase_ = 'specialize:arg(0)'
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/gc.py Thu Sep 10 16:45:13 2009
@@ -343,7 +343,7 @@
return llop1.do_malloc_varsize_clear(
llmemory.GCREF,
type_id, num_elem, self.array_basesize, itemsize,
- self.array_length_ofs, True, False)
+ self.array_length_ofs, True)
self.malloc_array = malloc_array
self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType(
[lltype.Signed] * 3, llmemory.GCREF))
@@ -359,12 +359,12 @@
return llop1.do_malloc_varsize_clear(
llmemory.GCREF,
str_type_id, length, str_basesize, str_itemsize,
- str_ofs_length, True, False)
+ str_ofs_length, True)
def malloc_unicode(length):
return llop1.do_malloc_varsize_clear(
llmemory.GCREF,
unicode_type_id, length, unicode_basesize, unicode_itemsize,
- unicode_ofs_length, True, False)
+ unicode_ofs_length, True)
self.malloc_str = malloc_str
self.malloc_unicode = malloc_unicode
self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/llmodel.py Thu Sep 10 16:45:13 2009
@@ -1,8 +1,10 @@
import sys
from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
+from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.annlowlevel import llhelper
from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values
-from pypy.jit.metainterp.typesystem import llhelper
from pypy.jit.backend.model import AbstractCPU
from pypy.jit.backend.llsupport import symbolic
from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
@@ -19,7 +21,7 @@
class AbstractLLCPU(AbstractCPU):
- ts = llhelper
+ from pypy.jit.metainterp.typesystem import llhelper as ts
def __init__(self, rtyper, stats, translate_support_code=False,
gcdescr=None):
@@ -37,6 +39,11 @@
translate_support_code)
self._setup_prebuilt_error('ovf', OverflowError)
self._setup_prebuilt_error('zer', ZeroDivisionError)
+ if translate_support_code:
+ self._setup_exception_handling_translated()
+ else:
+ self._setup_exception_handling_untranslated()
+ self.clear_exception()
def set_class_sizes(self, class_sizes):
self.class_sizes = class_sizes
@@ -54,13 +61,99 @@
immortal=True)
setattr(self, '_%s_error_vtable' % prefix,
llmemory.cast_ptr_to_adr(ll_inst.typeptr))
- setattr(self, '_%s_error_inst' % prefix,
- llmemory.cast_ptr_to_adr(ll_inst))
+ setattr(self, '_%s_error_inst' % prefix, ll_inst)
+
+
+ def _setup_exception_handling_untranslated(self):
+ # for running un-translated only, all exceptions occurring in the
+ # llinterpreter are stored in '_exception_emulator', which is then
+ # read back by the machine code reading at the address given by
+ # pos_exception() and pos_exc_value().
+ _exception_emulator = lltype.malloc(rffi.CArray(lltype.Signed), 2,
+ zero=True, flavor='raw')
+ self._exception_emulator = _exception_emulator
+
+ def _store_exception(lle):
+ self._last_exception = lle # keepalive
+ tp_i = rffi.cast(lltype.Signed, lle.args[0])
+ v_i = rffi.cast(lltype.Signed, lle.args[1])
+ _exception_emulator[0] = tp_i
+ _exception_emulator[1] = v_i
+
+ self.debug_ll_interpreter = LLInterpreter(self.rtyper)
+ self.debug_ll_interpreter._store_exception = _store_exception
+
+ def pos_exception():
+ return rffi.cast(lltype.Signed, _exception_emulator)
+
+ def pos_exc_value():
+ return (rffi.cast(lltype.Signed, _exception_emulator) +
+ rffi.sizeof(lltype.Signed))
+
+ def save_exception():
+ # copy from _exception_emulator to the real attributes on self
+ tp_i = _exception_emulator[0]
+ v_i = _exception_emulator[1]
+ _exception_emulator[0] = 0
+ _exception_emulator[1] = 0
+ self.saved_exception = tp_i
+ self.saved_exc_value = self._cast_int_to_gcref(v_i)
+
+ self.pos_exception = pos_exception
+ self.pos_exc_value = pos_exc_value
+ self.save_exception = save_exception
+
+
+ def _setup_exception_handling_translated(self):
+
+ def pos_exception():
+ addr = llop.get_exception_addr(llmemory.Address)
+ return llmemory.cast_adr_to_int(addr)
+
+ def pos_exc_value():
+ addr = llop.get_exc_value_addr(llmemory.Address)
+ return llmemory.cast_adr_to_int(addr)
+
+ def save_exception():
+ addr = llop.get_exception_addr(llmemory.Address)
+ exception = rffi.cast(lltype.Signed, addr.address[0])
+ addr.address[0] = llmemory.NULL
+ addr = llop.get_exc_value_addr(llmemory.Address)
+ exc_value = rffi.cast(llmemory.GCREF, addr.address[0])
+ addr.address[0] = llmemory.NULL
+ # from now on, the state is again consistent -- no more RPython
+ # exception is set. The following code produces a write barrier
+ # in the assignment to self.saved_exc_value, as needed.
+ self.saved_exception = exception
+ self.saved_exc_value = exc_value
+
+ self.pos_exception = pos_exception
+ self.pos_exc_value = pos_exc_value
+ self.save_exception = save_exception
+
+ _SAVE_EXCEPTION_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
+
+ def get_save_exception_int(self):
+ f = llhelper(self._SAVE_EXCEPTION_FUNC, self.save_exception)
+ return rffi.cast(lltype.Signed, f)
+
+ def get_exception(self):
+ return self.saved_exception
+
+ def get_exc_value(self):
+ return self.saved_exc_value
+
+ def clear_exception(self):
+ self.saved_exception = 0
+ self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
+
# ------------------- helpers and descriptions --------------------
@staticmethod
- def cast_int_to_gcref(x):
+ def _cast_int_to_gcref(x):
+ # dangerous! only use if you are sure no collection could occur
+ # between reading the integer and casting it to a pointer
if not we_are_translated():
_check_addr_range(x)
return rffi.cast(llmemory.GCREF, x)
@@ -109,14 +202,14 @@
def get_overflow_error(self):
ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
- ovf_inst = self.cast_int_to_gcref(
- self.cast_adr_to_int(self._ovf_error_inst))
+ ovf_inst = lltype.cast_opaque_ptr(llmemory.GCREF,
+ self._ovf_error_inst)
return ovf_vtable, ovf_inst
def get_zero_division_error(self):
zer_vtable = self.cast_adr_to_int(self._zer_error_vtable)
- zer_inst = self.cast_int_to_gcref(
- self.cast_adr_to_int(self._zer_error_inst))
+ zer_inst = lltype.cast_opaque_ptr(llmemory.GCREF,
+ self._zer_error_inst)
return zer_vtable, zer_inst
# ____________________________________________________________
@@ -142,7 +235,7 @@
else:
raise NotImplementedError("size = %d" % size)
if ptr:
- return BoxPtr(self.cast_int_to_gcref(val))
+ return BoxPtr(self._cast_int_to_gcref(val))
else:
return BoxInt(val)
@@ -207,7 +300,7 @@
else:
raise NotImplementedError("size = %d" % size)
if ptr:
- return BoxPtr(self.cast_int_to_gcref(val))
+ return BoxPtr(self._cast_int_to_gcref(val))
else:
return BoxInt(val)
@@ -311,9 +404,6 @@
def do_cast_ptr_to_int(self, args, descr=None):
return BoxInt(self.cast_gcref_to_int(args[0].getref_base()))
- def do_cast_int_to_ptr(self, args, descr=None):
- return BoxPtr(self.cast_int_to_gcref(args[0].getint()))
-
import pypy.jit.metainterp.executor
pypy.jit.metainterp.executor.make_execute_list(AbstractLLCPU)
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/llsupport/test/test_gc.py Thu Sep 10 16:45:13 2009
@@ -124,10 +124,8 @@
return p
def do_malloc_varsize_clear(self, RESTYPE, type_id, length, size,
- itemsize, offset_to_length, can_collect,
- has_finalizer):
+ itemsize, offset_to_length, can_collect):
assert can_collect
- assert not has_finalizer
p = llmemory.raw_malloc(size + itemsize * length)
(p + offset_to_length).signed[0] = length
p = llmemory.cast_adr_to_ptr(p, RESTYPE)
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/model.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/model.py Thu Sep 10 16:45:13 2009
@@ -1,4 +1,5 @@
class AbstractCPU(object):
+ supports_floats = False
def set_class_sizes(self, class_sizes):
self.class_sizes = class_sizes
@@ -160,9 +161,6 @@
def do_cond_call_gc_malloc(self, args, calldescr):
xxx
- def do_cast_int_to_ptr(self, args, descr=None):
- raise NotImplementedError
-
def do_cast_ptr_to_int(self, args, descr=None):
raise NotImplementedError
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/test/runner_test.py Thu Sep 10 16:45:13 2009
@@ -1,8 +1,8 @@
import py, sys, random
from pypy.jit.metainterp.history import (BoxInt, Box, BoxPtr, TreeLoop,
- ConstInt, ConstPtr, BoxObj,
- ConstObj)
+ ConstInt, ConstPtr, BoxObj, Const,
+ ConstObj, BoxFloat, ConstFloat)
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.metainterp.typesystem import deref
from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
@@ -26,6 +26,11 @@
elif isinstance(box, (BoxPtr, BoxObj)):
self.cpu.set_future_value_ref(j, box.getref_base())
j += 1
+ elif isinstance(box, BoxFloat):
+ self.cpu.set_future_value_float(j, box.getfloat())
+ j += 1
+ else:
+ assert isinstance(box, Const)
res = self.cpu.execute_operations(loop)
if res is loop.operations[-1]:
self.guard_failed = False
@@ -35,6 +40,8 @@
return BoxInt(self.cpu.get_latest_value_int(0))
elif result_type == 'ref':
return BoxPtr(self.cpu.get_latest_value_ref(0))
+ elif result_type == 'float':
+ return BoxFloat(self.cpu.get_latest_value_float(0))
elif result_type == 'void':
return None
else:
@@ -48,6 +55,8 @@
result = BoxInt()
elif result_type == 'ref':
result = BoxPtr()
+ elif result_type == 'float':
+ result = BoxFloat()
else:
raise ValueError(result_type)
if result is None:
@@ -210,6 +219,19 @@
'int')
assert res.value == y
+ def test_float_operations(self):
+ from pypy.jit.metainterp.test.test_executor import get_float_tests
+ for opnum, boxargs, rettype, retvalue in get_float_tests(self.cpu):
+ if len(boxargs) == 2:
+ args_variants = [(boxargs[0], boxargs[1]),
+ (boxargs[0], boxargs[1].constbox()),
+ (boxargs[0].constbox(), boxargs[1])]
+ else:
+ args_variants = [boxargs]
+ for argboxes in args_variants:
+ res = self.execute_operation(opnum, argboxes, rettype)
+ assert res.value == retvalue
+
def test_ovf_operations(self, reversed=False):
minint = -sys.maxint-1
boom = 'boom'
@@ -620,14 +642,10 @@
x = lltype.cast_opaque_ptr(llmemory.GCREF, x)
res = self.execute_operation(rop.CAST_PTR_TO_INT,
[BoxPtr(x)], 'int').value
- res2 = self.execute_operation(rop.CAST_INT_TO_PTR,
- [BoxInt(res)], 'ref').value
- x = lltype.cast_opaque_ptr(llmemory.GCREF, x)
+ assert res == self.cpu.cast_gcref_to_int(x)
res = self.execute_operation(rop.CAST_PTR_TO_INT,
[ConstPtr(x)], 'int').value
- res2 = self.execute_operation(rop.CAST_INT_TO_PTR,
- [ConstInt(res)], 'ref').value
- assert res2 == x
+ assert res == self.cpu.cast_gcref_to_int(x)
def test_ooops_non_gc(self):
x = lltype.malloc(lltype.Struct('x'), flavor='raw')
@@ -851,9 +869,7 @@
x = cpu.do_newstr([BoxInt(5)])
y = cpu.do_cast_ptr_to_int([x])
assert isinstance(y, BoxInt)
- z = cpu.do_cast_int_to_ptr([y])
- assert isinstance(z, BoxPtr)
- assert z.value == x.value
+ assert y.value == cpu.cast_gcref_to_int(x.value)
def test_sorting_of_fields(self):
S = self.S
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/test/test_random.py Thu Sep 10 16:45:13 2009
@@ -502,6 +502,7 @@
bridge_builder = self.builder.fork(self.builder.cpu, subloop,
op.args[:])
self.generate_ops(bridge_builder, r, subloop, op.args[:])
+ dont_compile = False
if r.random() < 0.1:
subset = bridge_builder.subset_of_intvars(r)
if len(subset) == 0:
@@ -517,17 +518,22 @@
if self.guard_op is None:
guard_op.suboperations[-1] = jump_op
else:
+ self.guard_op.suboperations[0].args.extend(subset)
+ self.builder.cpu.compile_operations(self.loop, guard_op)
if self.guard_op.is_guard_exception():
# exception clearing
self.guard_op.suboperations.insert(-1, exc_handling(
self.guard_op))
self.guard_op.suboperations[-1] = jump_op
+ self.builder.cpu.compile_operations(self.loop, self.guard_op)
+ dont_compile = True
self.guard_op = jump_target.guard_op
self.prebuilt_ptr_consts += jump_target.prebuilt_ptr_consts
self.dont_generate_more = True
if r.random() < .05:
return False
- self.builder.cpu.compile_operations(self.loop)
+ if not dont_compile:
+ self.builder.cpu.compile_operations(self.loop, guard_op)
return True
def check_random_function(cpu, BuilderClass, r, num=None, max=None):
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/assembler.py Thu Sep 10 16:45:13 2009
@@ -5,7 +5,6 @@
from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory
from pypy.rpython.lltypesystem.rclass import OBJECT
from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.annotation import model as annmodel
from pypy.tool.uid import fixid
from pypy.jit.backend.logger import Logger
from pypy.jit.backend.x86.regalloc import (RegAlloc, WORD, REGS, TempBox,
@@ -15,9 +14,13 @@
from pypy.jit.backend.x86.ri386 import *
from pypy.jit.metainterp.resoperation import rop
-# our calling convention - we pass three first args as edx, ecx and eax
+
+
+# our calling convention - we pass first 6 args in registers
# and the rest stays on the stack
+RET_BP = 5 # ret ip + bp + bx + esi + edi = 5 words
+
MAX_FAIL_BOXES = 1000
if sys.platform == 'darwin':
# darwin requires the stack to be 16 bytes aligned on calls
@@ -60,24 +63,6 @@
if name.upper() == name:
setattr(MachineCodeBlockWrapper, name, _new_method(name))
-class MachineCodeStack(object):
- def __init__(self):
- self.mcstack = []
- self.counter = 0
-
- def next_mc(self):
- if len(self.mcstack) == self.counter:
- mc = MachineCodeBlockWrapper()
- self.mcstack.append(mc)
- else:
- mc = self.mcstack[self.counter]
- self.counter += 1
- return mc
-
- def give_mc_back(self, mc):
- mc.done()
- assert self.mcstack[self.counter - 1] is mc
- self.counter -= 1
class Assembler386(object):
mc = None
@@ -92,9 +77,6 @@
self.malloc_array_func_addr = 0
self.malloc_str_func_addr = 0
self.malloc_unicode_func_addr = 0
- self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed))
- self._exception_addr = 0
- self.mcstack = MachineCodeStack()
self.logger = Logger(cpu.ts)
self.fail_boxes_int = lltype.malloc(lltype.GcArray(lltype.Signed),
MAX_FAIL_BOXES, zero=True)
@@ -111,22 +93,6 @@
lltype.direct_arrayitems(self.fail_boxes_ptr))
self.logger.create_log()
- # we generate the loop body in 'mc'
- # 'mc2' is for guard recovery code
- if we_are_translated():
- addr = llop.get_exception_addr(llmemory.Address)
- self._exception_data = llmemory.cast_adr_to_ptr(addr, rffi.CArrayPtr(lltype.Signed))
- else:
- self._exception_data = lltype.malloc(rffi.CArray(lltype.Signed), 2,
- zero=True, flavor='raw')
- self._exception_addr = self.cpu.cast_ptr_to_int(
- self._exception_data)
- # a backup, in case our exception can be somehow mangled,
- # by a handling code
- self._exception_bck = lltype.malloc(rffi.CArray(lltype.Signed), 2,
- zero=True, flavor='raw')
- self._exception_bck_addr = self.cpu.cast_ptr_to_int(
- self._exception_bck)
# the address of the function called by 'new'
gc_ll_descr = self.cpu.gc_ll_descr
gc_ll_descr.initialize()
@@ -145,9 +111,10 @@
self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
ll_new_unicode)
# done
- self.mc2 = self.mcstack.next_mc()
- self.mc = self.mcstack.next_mc()
-
+ # we generate the loop body in 'mc'
+ # 'mc2' is for guard recovery code
+ self.mc = MachineCodeBlockWrapper()
+ self.mc2 = MachineCodeBlockWrapper()
def _compute_longest_fail_op(self, ops):
max_so_far = 0
@@ -160,48 +127,57 @@
assert max_so_far < MAX_FAIL_BOXES
return max_so_far
- def assemble(self, tree):
- self.places_to_patch_framesize = []
- self.jumps_to_look_at = []
+ def assemble_loop(self, loop):
+ self.assemble(loop, loop.operations, None)
+
+ def assemble_from_guard(self, tree, guard_op):
+ newaddr = self.assemble(tree, guard_op.suboperations, guard_op)
+ # patch the jump from original guard
+ addr = guard_op._x86_addr
+ mc = codebuf.InMemoryCodeBuilder(addr, addr + 128)
+ mc.write(packimm32(newaddr - addr - 4))
+ mc.done()
+
+ def assemble(self, tree, operations, guard_op):
# the last operation can be 'jump', 'return' or 'guard_pause';
# a 'jump' can either close a loop, or end a bridge to some
# previously-compiled code.
- self._compute_longest_fail_op(tree.operations)
+ self._compute_longest_fail_op(operations)
self.tree = tree
self.make_sure_mc_exists()
- inputargs = tree.inputargs
- self.logger.log_loop(tree)
- regalloc = RegAlloc(self, tree, self.cpu.translate_support_code)
+ newpos = self.mc.tell()
+ regalloc = RegAlloc(self, tree, self.cpu.translate_support_code,
+ guard_op)
self._regalloc = regalloc
- regalloc.walk_operations(tree)
- self.sanitize_tree(tree.operations)
+ adr_lea = 0
+ if guard_op is None:
+ inputargs = tree.inputargs
+ self.logger.log_loop(tree)
+ regalloc.walk_operations(tree)
+ else:
+ inputargs = regalloc.inputargs
+ self.logger.log_operations(inputargs, guard_op.suboperations, {})
+ mc = self.mc._mc
+ adr_lea = mc.tell()
+ mc.LEA(esp, fixedsize_ebp_ofs(0))
+ regalloc._walk_operations(operations)
+ stack_depth = regalloc.max_stack_depth
self.mc.done()
self.mc2.done()
- stack_words = regalloc.max_stack_depth
# possibly align, e.g. for Mac OS X
- RET_BP = 5 # ret ip + bp + bx + esi + edi = 5 words
- stack_words = align_stack_words(stack_words+RET_BP)
- tree._x86_stack_depth = stack_words-RET_BP
- for place in self.places_to_patch_framesize:
- mc = codebuf.InMemoryCodeBuilder(place, place + 128)
- mc.ADD(esp, imm32(tree._x86_stack_depth * WORD))
+ if guard_op is None:
+ tree._x86_stack_depth = stack_depth
+ else:
+ if not we_are_translated():
+ # for the benefit of tests
+ guard_op._x86_bridge_stack_depth = stack_depth
+ mc = codebuf.InMemoryCodeBuilder(adr_lea, adr_lea + 128)
+
+ mc.LEA(esp, fixedsize_ebp_ofs(-(stack_depth + RET_BP - 2) * WORD))
mc.done()
- for op, pos in self.jumps_to_look_at:
- if op.jump_target._x86_stack_depth != tree._x86_stack_depth:
- tl = op.jump_target
- self.patch_jump(pos, tl._x86_compiled, tl.arglocs, tl.arglocs,
- tree._x86_stack_depth, tl._x86_stack_depth)
if we_are_translated():
self._regalloc = None # else keep it around for debugging
-
- def sanitize_tree(self, operations):
- """ Cleans up all attributes attached by regalloc and backend
- """
- for op in operations:
- if op.is_guard():
- op.inputargs = None
- op.longevity = None
- self.sanitize_tree(op.suboperations)
+ return newpos
def assemble_bootstrap_code(self, jumpaddr, arglocs, args, framesize):
self.make_sure_mc_exists()
@@ -272,14 +248,14 @@
def regalloc_perform_discard(self, op, arglocs):
genop_discard_list[op.opnum](self, op, arglocs)
- def regalloc_perform_with_guard(self, op, guard_op, regalloc,
+ def regalloc_perform_with_guard(self, op, guard_op, faillocs,
arglocs, resloc):
- addr = self.implement_guard_recovery(guard_op, regalloc)
+ addr = self.implement_guard_recovery(guard_op, faillocs)
genop_guard_list[op.opnum](self, op, guard_op, addr, arglocs,
resloc)
- def regalloc_perform_guard(self, op, regalloc, arglocs, resloc):
- addr = self.implement_guard_recovery(op, regalloc)
+ def regalloc_perform_guard(self, op, faillocs, arglocs, resloc):
+ addr = self.implement_guard_recovery(op, faillocs)
genop_guard_list[op.opnum](self, op, None, addr, arglocs,
resloc)
@@ -339,9 +315,7 @@
nargs = len(args)
extra_on_stack = self.align_stack_for_call(nargs)
for i in range(nargs-1, -1, -1):
- arg = args[i]
- assert not isinstance(arg, MODRM)
- self.mc.PUSH(arg)
+ self.mc.PUSH(args[i])
self.mc.CALL(rel32(addr))
self.mark_gc_roots()
self.mc.ADD(esp, imm(extra_on_stack * WORD))
@@ -444,7 +418,6 @@
def genop_same_as(self, op, arglocs, resloc):
self.mc.MOV(resloc, arglocs[0])
- genop_cast_int_to_ptr = genop_same_as
genop_cast_ptr_to_int = genop_same_as
def genop_int_mod(self, op, arglocs, resloc):
@@ -599,40 +572,9 @@
def make_merge_point(self, tree, locs):
pos = self.mc.tell()
tree._x86_compiled = pos
- #tree.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(pos,
- # locs, stacklocs)
-
- def patch_jump(self, old_pos, new_pos, oldlocs, newlocs, olddepth, newdepth):
- for i in range(len(oldlocs)):
- oldloc = oldlocs[i]
- newloc = newlocs[i]
- if isinstance(newloc, MODRM):
- assert isinstance(oldloc, MODRM)
- assert newloc.position == oldloc.position
- else:
- assert newloc is oldloc
- # newlocs should be sorted in acending order, excluding the regs
- if not we_are_translated():
- locs = [loc.position for loc in newlocs if isinstance(loc, MODRM)]
- assert locs == sorted(locs)
- #
- mc = codebuf.InMemoryCodeBuilder(old_pos, old_pos +
- MachineCodeBlockWrapper.MC_SIZE)
- mc.SUB(esp, imm(WORD * (newdepth - olddepth)))
- mc.JMP(rel32(new_pos))
- mc.done()
def genop_discard_jump(self, op, locs):
- targetmp = op.jump_target
- # don't break the following code sequence!
- mc = self.mc._mc
- if op.jump_target is not self.tree:
- self.jumps_to_look_at.append((op, mc.tell()))
- mc.JMP(rel32(targetmp._x86_compiled))
- if op.jump_target is not self.tree:
- # Reserve 6 bytes for a possible later patch by patch_jump().
- # Put them after the JMP by default, as it's not doing anything.
- mc.SUB(esp, imm32(0))
+ self.mc.JMP(rel32(op.jump_target._x86_compiled))
def genop_guard_guard_true(self, op, ign_1, addr, locs, ign_2):
loc = locs[0]
@@ -640,19 +582,19 @@
self.implement_guard(addr, op, self.mc.JZ)
def genop_guard_guard_no_exception(self, op, ign_1, addr, locs, ign_2):
- self.mc.CMP(heap(self._exception_addr), imm(0))
+ self.mc.CMP(heap(self.cpu.pos_exception()), imm(0))
self.implement_guard(addr, op, self.mc.JNZ)
def genop_guard_guard_exception(self, op, ign_1, addr, locs, resloc):
loc = locs[0]
loc1 = locs[1]
- self.mc.MOV(loc1, heap(self._exception_addr))
+ self.mc.MOV(loc1, heap(self.cpu.pos_exception()))
self.mc.CMP(loc1, loc)
self.implement_guard(addr, op, self.mc.JNE)
if resloc is not None:
- self.mc.MOV(resloc, addr_add(imm(self._exception_addr), imm(WORD)))
- self.mc.MOV(heap(self._exception_addr), imm(0))
- self.mc.MOV(addr_add(imm(self._exception_addr), imm(WORD)), imm(0))
+ self.mc.MOV(resloc, heap(self.cpu.pos_exc_value()))
+ self.mc.MOV(heap(self.cpu.pos_exception()), imm(0))
+ self.mc.MOV(heap(self.cpu.pos_exc_value()), imm(0))
def genop_guard_guard_no_overflow(self, op, ign_1, addr, locs, resloc):
self.implement_guard(addr, op, self.mc.JO)
@@ -674,27 +616,21 @@
self.mc.CMP(mem(locs[0], offset), locs[1])
self.implement_guard(addr, op, self.mc.JNE)
- def implement_guard_recovery(self, guard_op, regalloc):
- oldmc = self.mc
- self.mc = self.mc2
- self.mc2 = self.mcstack.next_mc()
- addr = self.mc.tell()
+ def implement_guard_recovery(self, guard_op, fail_locs):
+ addr = self.mc2.tell()
exc = (guard_op.opnum == rop.GUARD_EXCEPTION or
guard_op.opnum == rop.GUARD_NO_EXCEPTION)
- # XXX this is a heuristics to detect whether we're handling this
- # exception or not. We should have a bit better interface to deal
- # with that I fear
- if (exc and (guard_op.suboperations[0].opnum == rop.GUARD_EXCEPTION or
- guard_op.suboperations[0].opnum == rop.GUARD_NO_EXCEPTION)):
- exc = False
- regalloc.walk_guard_ops(guard_op.inputargs, guard_op.suboperations, exc)
- self.mcstack.give_mc_back(self.mc2)
- self.mc2 = self.mc
- self.mc = oldmc
+ guard_op._x86_faillocs = fail_locs
+ # XXX horrible hack that allows us to preserve order
+ # of inputargs to bridge
+ guard_op._fail_op = guard_op.suboperations[0]
+ self.generate_failure(self.mc2, guard_op.suboperations[0], fail_locs,
+ exc)
return addr
- def generate_failure(self, op, locs, exc):
- pos = self.mc.tell()
+ def generate_failure(self, mc, op, locs, exc):
+ assert op.opnum == rop.FAIL
+ pos = mc.tell()
for i in range(len(locs)):
loc = locs[i]
if isinstance(loc, REG):
@@ -702,7 +638,7 @@
base = self.fail_box_ptr_addr
else:
base = self.fail_box_int_addr
- self.mc.MOV(addr_add(imm(base), imm(i*WORD)), loc)
+ mc.MOV(addr_add(imm(base), imm(i*WORD)), loc)
for i in range(len(locs)):
loc = locs[i]
if not isinstance(loc, REG):
@@ -710,19 +646,20 @@
base = self.fail_box_ptr_addr
else:
base = self.fail_box_int_addr
- self.mc.MOV(eax, loc)
- self.mc.MOV(addr_add(imm(base), imm(i*WORD)), eax)
+ mc.MOV(eax, loc)
+ mc.MOV(addr_add(imm(base), imm(i*WORD)), eax)
if self.debug_markers:
- self.mc.MOV(eax, imm(pos))
- self.mc.MOV(addr_add(imm(self.fail_box_int_addr),
+ mc.MOV(eax, imm(pos))
+ mc.MOV(addr_add(imm(self.fail_box_int_addr),
imm(len(locs) * WORD)),
eax)
if exc:
- self.generate_exception_handling(eax)
+ # note that we don't have to save and restore eax, ecx and edx here
+ addr = self.cpu.get_save_exception_int()
+ mc.CALL(rel32(addr))
# don't break the following code sequence!
- mc = self.mc._mc
- self.places_to_patch_framesize.append(mc.tell())
- mc.ADD(esp, imm32(0))
+ mc = mc._mc
+ mc.LEA(esp, addr_add(imm(0), ebp, (-RET_BP + 2) * WORD))
guard_index = self.cpu.make_guard_index(op)
mc.MOV(eax, imm(guard_index))
mc.POP(edi)
@@ -731,19 +668,10 @@
mc.POP(ebp)
mc.RET()
- def generate_exception_handling(self, loc):
- self.mc.MOV(loc, heap(self._exception_addr))
- self.mc.MOV(heap(self._exception_bck_addr), loc)
- self.mc.MOV(loc, addr_add(imm(self._exception_addr), imm(WORD)))
- self.mc.MOV(addr_add(imm(self._exception_bck_addr), imm(WORD)), loc)
- # clean up the original exception, we don't want
- # to enter more rpython code with exc set
- self.mc.MOV(heap(self._exception_addr), imm(0))
- self.mc.MOV(addr_add(imm(self._exception_addr), imm(WORD)), imm(0))
-
@specialize.arg(3)
def implement_guard(self, addr, guard_op, emit_jump):
emit_jump(rel32(addr))
+ guard_op._x86_addr = self.mc.tell() - 4
def genop_call(self, op, arglocs, resloc):
sizeloc = arglocs[0]
@@ -808,15 +736,6 @@
print "not implemented operation (guard): %s" % op.getopname()
raise NotImplementedError
- #def genop_call__1(self, op, arglocs, resloc):
- # self.gen_call(op, arglocs, resloc)
- # self.mc.MOVZX(eax, al)
-
- #def genop_call__2(self, op, arglocs, resloc):
- # # XXX test it test it test it
- # self.gen_call(op, arglocs, resloc)
- # self.mc.MOVZX(eax, eax)
-
def mark_gc_roots(self):
gcrootmap = self.cpu.gc_ll_descr.gcrootmap
if gcrootmap:
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/regalloc.py Thu Sep 10 16:45:13 2009
@@ -18,6 +18,9 @@
REGS = [eax, ecx, edx, ebx, esi, edi]
WORD = 4
+class NoVariableToSpill(Exception):
+ pass
+
class TempBox(Box):
def __init__(self):
pass
@@ -54,46 +57,56 @@
exc = False
def __init__(self, assembler, tree, translate_support_code=False,
- regalloc=None, guard_op=None):
+ guard_op=None):
# variables that have place in register
self.assembler = assembler
self.translate_support_code = translate_support_code
- if regalloc is None:
- cpu = self.assembler.cpu
+ cpu = self.assembler.cpu
+ self.reg_bindings = newcheckdict()
+ self.stack_bindings = newcheckdict()
+ self.tree = tree
+ if guard_op is not None:
+ locs = guard_op._x86_faillocs
+ cpu.gc_ll_descr.rewrite_assembler(cpu, guard_op.suboperations)
+ inpargs = [arg for arg in guard_op._fail_op.args if
+ isinstance(arg, Box)]
+ self._compute_vars_longevity(inpargs, guard_op.suboperations)
+ self.inputargs = inpargs
+ self.position = -1
+ self._update_bindings(locs, inpargs)
+ self.current_stack_depth = guard_op._x86_current_stack_depth
+ self.loop_consts = {}
+ else:
cpu.gc_ll_descr.rewrite_assembler(cpu, tree.operations)
- self.tree = tree
- self.reg_bindings = newcheckdict()
- self.stack_bindings = newcheckdict()
- # compute longevity of variables
self._compute_vars_longevity(tree.inputargs, tree.operations)
- self.free_regs = REGS[:]
+ # compute longevity of variables
jump = tree.operations[-1]
loop_consts = self._compute_loop_consts(tree.inputargs, jump)
self.loop_consts = loop_consts
self.current_stack_depth = 0
- else:
- inp = guard_op.inputargs
- assert inp is not None
- self.reg_bindings = {}
- self.stack_bindings = {}
- for arg in inp:
- if arg in regalloc.reg_bindings:
- self.reg_bindings[arg] = regalloc.reg_bindings[arg]
- if arg in regalloc.stack_bindings:
- self.stack_bindings[arg] = regalloc.stack_bindings[arg]
- else:
- assert arg in regalloc.reg_bindings
- allocated_regs = self.reg_bindings.values()
- self.free_regs = [v for v in REGS if v not in allocated_regs]
- self.current_stack_depth = regalloc.current_stack_depth
- self.longevity = guard_op.longevity
- jump_or_fail = guard_op.suboperations[-1]
- self.loop_consts = {}
- self.tree = regalloc.tree
+ self.free_regs = REGS[:]
- def regalloc_for_guard(self, guard_op):
- return RegAlloc(self.assembler, None, self.translate_support_code,
- self, guard_op)
+ def _update_bindings(self, locs, args):
+ newlocs = []
+ for loc in locs:
+ if not isinstance(loc, IMM8) and not isinstance(loc, IMM32):
+ newlocs.append(loc)
+ locs = newlocs
+ assert len(locs) == len(args)
+ used = {}
+ for i in range(len(locs)):
+ v = args[i]
+ loc = locs[i]
+ if isinstance(loc, REG) and self.longevity[v][1] > -1:
+ self.reg_bindings[v] = loc
+ used[loc] = None
+ else:
+ self.stack_bindings[v] = loc
+ self.free_regs = []
+ for reg in REGS:
+ if reg not in used:
+ self.free_regs.append(reg)
+ self._check_invariants()
def _compute_loop_consts(self, inputargs, jump):
if jump.opnum != rop.JUMP or jump.jump_target is not self.tree:
@@ -136,24 +149,22 @@
self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
self.assembler.regalloc_perform(op, arglocs, result_loc)
- def perform_with_guard(self, op, guard_op, regalloc, arglocs, result_loc):
+ def perform_with_guard(self, op, guard_op, locs, arglocs, result_loc):
+ guard_op._x86_current_stack_depth = self.current_stack_depth
if not we_are_translated():
self.assembler.dump('%s <- %s(%s) [GUARDED]' % (result_loc, op,
arglocs))
- self.assembler.regalloc_perform_with_guard(op, guard_op, regalloc,
+ self.assembler.regalloc_perform_with_guard(op, guard_op, locs,
arglocs, result_loc)
- self.max_stack_depth = max(self.max_stack_depth,
- regalloc.max_stack_depth)
- def perform_guard(self, op, regalloc, arglocs, result_loc):
+ def perform_guard(self, op, locs, arglocs, result_loc):
+ op._x86_current_stack_depth = self.current_stack_depth
if not we_are_translated():
if result_loc is not None:
self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
else:
self.assembler.dump('%s(%s)' % (op, arglocs))
- self.assembler.regalloc_perform_guard(op, regalloc, arglocs, result_loc)
- self.max_stack_depth = max(self.max_stack_depth,
- regalloc.max_stack_depth)
+ self.assembler.regalloc_perform_guard(op, locs, arglocs, result_loc)
def PerformDiscard(self, op, arglocs):
if not we_are_translated():
@@ -170,25 +181,24 @@
if operations[i + 1].args[0] is not op.result:
return False
if (self.longevity[op.result][1] > i + 1 or
- op.result in operations[i + 1].inputargs):
- print "!!!! boolean flag not optimized away !!!!"
+ op.result in operations[i + 1].suboperations[0].args):
return False
return True
def walk_operations(self, tree):
# first pass - walk along the operations in order to find
# load/store places
- operations = tree.operations
self.position = -1
+ operations = tree.operations
self.process_inputargs(tree)
self._walk_operations(operations)
- def walk_guard_ops(self, inputargs, operations, exc):
- self.exc = exc
- old_regalloc = self.assembler._regalloc
- self.assembler._regalloc = self
- self._walk_operations(operations)
- self.assembler._regalloc = old_regalloc
+ #def walk_guard_ops(self, inputargs, operations, exc):
+ # self.exc = exc
+ # old_regalloc = self.assembler._regalloc
+ # self.assembler._regalloc = self
+ # self._walk_operations(operations)
+ # self.assembler._regalloc = old_regalloc
def _walk_operations(self, operations):
i = 0
@@ -210,11 +220,8 @@
i += 1
assert not self.reg_bindings
jmp = operations[-1]
- #if jmp.opnum == rop.JUMP and jmp.jump_target is not self.tree:
- # self.max_stack_depth = max(jmp.jump_target._x86_stack_depth,
- # self.max_stack_depth)
- self.max_stack_depth = max(self.max_stack_depth,
- self.current_stack_depth + 1)
+ self.max_stack_depth = max(self.current_stack_depth,
+ self.max_stack_depth)
def _compute_vars_longevity(self, inputargs, operations):
# compute a dictionary that maps variables to index in
@@ -234,8 +241,7 @@
raise AssertionError
longevity[arg] = (start_live[arg], i)
if op.is_guard():
- self._compute_inpargs(op)
- for arg in op.inputargs:
+ for arg in op.suboperations[0].args:
if isinstance(arg, Box):
if arg not in start_live:
print "Bogus arg in guard %d at %d" % (op.opnum, i)
@@ -248,35 +254,32 @@
assert isinstance(arg, Box)
self.longevity = longevity
- def _compute_inpargs(self, guard):
- if guard.inputargs is not None:
- return
- operations = guard.suboperations
- longevity = {}
- end = {}
- for i in range(len(operations)-1, -1, -1):
- op = operations[i]
- if op.is_guard():
- self._compute_inpargs(op)
- for arg in op.inputargs:
- if isinstance(arg, Box) and arg not in end:
- end[arg] = i
- for arg in op.args:
- if isinstance(arg, Box) and arg not in end:
- end[arg] = i
- if op.result:
- if op.result in end:
- longevity[op.result] = (i, end[op.result])
- del end[op.result]
- # otherwise this var is never ever used
- for v, e in end.items():
- longevity[v] = (0, e)
- guard.longevity = longevity
- guard.inputargs = end.keys()
- for arg in longevity:
- assert isinstance(arg, Box)
- for arg in guard.inputargs:
- assert isinstance(arg, Box)
+# def _compute_inpargs(self, guard):
+# operations = guard.suboperations
+# longevity = {}
+# end = {}
+# for i in range(len(operations)-1, -1, -1):
+# op = operations[i]
+# if op.is_guard():
+# for arg in op.suboperations[0].args:
+# if isinstance(arg, Box) and arg not in end:
+# end[arg] = i
+# for arg in op.args:
+# if isinstance(arg, Box) and arg not in end:
+# end[arg] = i
+# if op.result:
+# if op.result in end:
+# longevity[op.result] = (i, end[op.result])
+# del end[op.result]
+# # otherwise this var is never ever used
+# for v, e in end.items():
+# longevity[v] = (0, e)
+# inputargs = end.keys()
+# for arg in longevity:
+# assert isinstance(arg, Box)
+# for arg in inputargs:
+# assert isinstance(arg, Box)
+# return inputargs, longevity
def try_allocate_reg(self, v, selected_reg=None, need_lower_byte=False):
assert not isinstance(v, Const)
@@ -424,24 +427,30 @@
reg = self.reg_bindings[next]
if next in forbidden_vars:
continue
- if selected_reg is not None and reg is selected_reg:
- return next
+ if selected_reg is not None:
+ if reg is selected_reg:
+ return next
+ else:
+ continue
if need_lower_byte and (reg is esi or reg is edi):
continue
- candidates.append(next)
- assert candidates
- if len(candidates) == 1:
- return candidates[0]
- max = 0
- chosen = None
- for one in candidates:
- next_usage = self._compute_next_usage(one, self.position)
- if next_usage == -1:
- return one
- elif next_usage > max:
- next_usage = max
- chosen = one
- return chosen
+ return next
+ raise NoVariableToSpill
+ # below is the slightly better (even optimal, under certain
+ # assumptions) algorithm, which is slow. Just go with the
+ # first hit
+ #if len(candidates) == 1:
+ # return candidates[0]
+ #max = 0
+ #chosen = None
+ #for one in candidates:
+ # next_usage = self._compute_next_usage(one, self.position)
+ # if next_usage == -1:
+ # return one
+ # elif next_usage > max:
+ # next_usage = max
+ # chosen = one
+ #return chosen
def move_variable_away(self, v, prev_loc):
reg = None
@@ -482,6 +491,10 @@
loc = self.reg_bindings[result_v]
return loc
+ def locs_for_fail(self, guard_op):
+ assert len(guard_op.suboperations) == 1
+ return [self.loc(v) for v in guard_op.suboperations[0].args]
+
def process_inputargs(self, tree):
# XXX we can sort out here by longevity if we need something
# more optimal
@@ -504,16 +517,17 @@
locs[i] = loc
# otherwise we have it saved on stack, so no worry
self.free_regs.insert(0, tmpreg)
+ assert tmpreg not in locs
tree.arglocs = locs
self.assembler.make_merge_point(tree, locs)
self.eventually_free_vars(inputargs)
def _consider_guard(self, op, ignored):
loc = self.make_sure_var_in_reg(op.args[0], [])
- regalloc = self.regalloc_for_guard(op)
- self.perform_guard(op, regalloc, [loc], None)
+ locs = self.locs_for_fail(op)
+ self.perform_guard(op, locs, [loc], None)
self.eventually_free_var(op.args[0])
- self.eventually_free_vars(op.inputargs)
+ self.eventually_free_vars(op.suboperations[0].args)
consider_guard_true = _consider_guard
consider_guard_false = _consider_guard
@@ -521,13 +535,13 @@
def consider_fail(self, op, ignored):
# make sure all vars are on stack
locs = [self.loc(arg) for arg in op.args]
- self.assembler.generate_failure(op, locs, self.exc)
+ self.assembler.generate_failure(self.assembler.mc, op, locs, self.exc)
self.eventually_free_vars(op.args)
def consider_guard_no_exception(self, op, ignored):
- regalloc = self.regalloc_for_guard(op)
- self.perform_guard(op, regalloc, [], None)
- self.eventually_free_vars(op.inputargs)
+ faillocs = self.locs_for_fail(op)
+ self.perform_guard(op, faillocs, [], None)
+ self.eventually_free_vars(op.suboperations[0].args)
def consider_guard_exception(self, op, ignored):
loc = self.make_sure_var_in_reg(op.args[0], [])
@@ -538,9 +552,9 @@
resloc = self.force_allocate_reg(op.result, op.args + [box])
else:
resloc = None
- regalloc = self.regalloc_for_guard(op)
- self.perform_guard(op, regalloc, [loc, loc1], resloc)
- self.eventually_free_vars(op.inputargs)
+ faillocs = self.locs_for_fail(op)
+ self.perform_guard(op, faillocs, [loc, loc1], resloc)
+ self.eventually_free_vars(op.suboperations[0].args)
self.eventually_free_vars(op.args)
self.eventually_free_var(box)
@@ -550,18 +564,18 @@
def consider_guard_value(self, op, ignored):
x = self.make_sure_var_in_reg(op.args[0], [])
y = self.loc(op.args[1])
- regalloc = self.regalloc_for_guard(op)
- self.perform_guard(op, regalloc, [x, y], None)
- self.eventually_free_vars(op.inputargs)
+ faillocs = self.locs_for_fail(op)
+ self.perform_guard(op, faillocs, [x, y], None)
+ self.eventually_free_vars(op.suboperations[0].args)
self.eventually_free_vars(op.args)
def consider_guard_class(self, op, ignored):
assert isinstance(op.args[0], Box)
x = self.make_sure_var_in_reg(op.args[0], [])
y = self.loc(op.args[1])
- regalloc = self.regalloc_for_guard(op)
- self.perform_guard(op, regalloc, [x, y], None)
- self.eventually_free_vars(op.inputargs)
+ faillocs = self.locs_for_fail(op)
+ self.perform_guard(op, faillocs, [x, y], None)
+ self.eventually_free_vars(op.suboperations[0].args)
self.eventually_free_vars(op.args)
def _consider_binop_part(self, op, ignored):
@@ -640,11 +654,11 @@
need_lower_byte=True)
self.Perform(op, arglocs, loc)
else:
- regalloc = self.regalloc_for_guard(guard_op)
+ faillocs = self.locs_for_fail(guard_op)
self.position += 1
- self.perform_with_guard(op, guard_op, regalloc, arglocs, None)
+ self.perform_with_guard(op, guard_op, faillocs, arglocs, None)
self.eventually_free_var(op.result)
- self.eventually_free_vars(guard_op.inputargs)
+ self.eventually_free_vars(guard_op.suboperations[0].args)
consider_int_lt = _consider_compop
consider_int_gt = _consider_compop
@@ -864,11 +878,11 @@
if guard_op is not None:
argloc = self.make_sure_var_in_reg(op.args[0], [])
self.eventually_free_var(op.args[0])
- regalloc = self.regalloc_for_guard(guard_op)
+ faillocs = self.locs_for_fail(guard_op)
self.position += 1
- self.perform_with_guard(op, guard_op, regalloc, [argloc], None)
+ self.perform_with_guard(op, guard_op, faillocs, [argloc], None)
self.eventually_free_var(op.result)
- self.eventually_free_vars(guard_op.inputargs)
+ self.eventually_free_vars(guard_op.suboperations[0].args)
else:
argloc = self.loc(op.args[0])
self.eventually_free_var(op.args[0])
@@ -885,7 +899,6 @@
self.eventually_free_var(op.args[0])
resloc = self.force_allocate_reg(op.result, [])
self.Perform(op, [argloc], resloc)
- consider_cast_int_to_ptr = consider_same_as
consider_cast_ptr_to_int = consider_same_as
def consider_strlen(self, op, ignored):
@@ -926,6 +939,7 @@
dst_locations, tmploc)
self.eventually_free_var(box)
self.eventually_free_vars(op.args)
+ self.max_stack_depth = op.jump_target._x86_stack_depth
self.PerformDiscard(op, [])
def consider_debug_merge_point(self, op, ignored):
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/runner.py Thu Sep 10 16:45:13 2009
@@ -10,7 +10,7 @@
history.TreeLoop._x86_compiled = 0
history.TreeLoop._x86_bootstrap_code = 0
-
+history.TreeLoop._x86_stack_depth = 0
class CPU386(AbstractLLCPU):
debug = True
@@ -21,16 +21,6 @@
gcdescr=None):
AbstractLLCPU.__init__(self, rtyper, stats, translate_support_code,
gcdescr)
- if not translate_support_code:
- self.current_interpreter = LLInterpreter(self.rtyper)
-
- def _store_exception(lle):
- tp_i = self.cast_ptr_to_int(lle.args[0])
- v_i = self.cast_gcref_to_int(lle.args[1])
- self.assembler._exception_data[0] = tp_i
- self.assembler._exception_data[1] = v_i
-
- self.current_interpreter._store_exception = _store_exception
TP = lltype.GcArray(llmemory.GCREF)
self._bootstrap_cache = {}
self._guard_list = []
@@ -45,34 +35,12 @@
def setup_once(self):
pass
- def get_exception(self):
- self.assembler.make_sure_mc_exists()
- return self.assembler._exception_bck[0]
-
- def get_exc_value(self):
- self.assembler.make_sure_mc_exists()
- return self.cast_int_to_gcref(self.assembler._exception_bck[1])
-
- def clear_exception(self):
- self.assembler.make_sure_mc_exists()
- self.assembler._exception_bck[0] = 0
- self.assembler._exception_bck[1] = 0
-
- def compile_operations(self, tree, bridge=None):
- old_loop = tree._x86_compiled
- if old_loop:
- olddepth = tree._x86_stack_depth
- oldlocs = tree.arglocs
+ def compile_operations(self, tree, guard_op=None):
+ if guard_op is not None:
+ self.assembler.assemble_from_guard(tree, guard_op)
else:
- oldlocs = None
- olddepth = 0
- stack_depth = self.assembler.assemble(tree)
- newlocs = tree.arglocs
- if old_loop != 0:
- self.assembler.patch_jump(old_loop, tree._x86_compiled,
- oldlocs, newlocs, olddepth,
- tree._x86_stack_depth)
-
+ self.assembler.assemble_loop(tree)
+
def get_bootstrap_code(self, loop):
addr = loop._x86_bootstrap_code
if not addr:
@@ -119,7 +87,7 @@
prev_interpreter = None
if not self.translate_support_code:
prev_interpreter = LLInterpreter.current_interpreter
- LLInterpreter.current_interpreter = self.current_interpreter
+ LLInterpreter.current_interpreter = self.debug_ll_interpreter
res = 0
try:
self.caught_exception = None
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_regalloc.py Thu Sep 10 16:45:13 2009
@@ -2,6 +2,7 @@
""" Tests for register allocation for common constructs
"""
+import py
from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\
BoxPtr, ConstPtr, TreeLoop
from pypy.jit.metainterp.resoperation import rop, ResOperation
@@ -14,20 +15,33 @@
from pypy.rpython.lltypesystem import rclass, rstr
from pypy.jit.backend.x86.ri386 import *
+
class DummyTree(object):
operations = [ResOperation(rop.FAIL, [], None)]
inputargs = []
+class MockGcDescr(GcCache):
+ def get_funcptr_for_new(self):
+ return 123
+ get_funcptr_for_newarray = get_funcptr_for_new
+ get_funcptr_for_newstr = get_funcptr_for_new
+ get_funcptr_for_newunicode = get_funcptr_for_new
+
+ def rewrite_assembler(self, cpu, operations):
+ pass
+
class MockAssembler(object):
gcrefs = None
- def __init__(self, cpu=None):
+ def __init__(self, cpu=None, gc_ll_descr=None):
self.loads = []
self.stores = []
self.performs = []
self.lea = []
self.cpu = cpu or CPU(None, None)
- self.cpu.gc_ll_descr = MockGcDescr(False)
+ if gc_ll_descr is None:
+ gc_ll_descr = MockGcDescr(False)
+ self.cpu.gc_ll_descr = gc_ll_descr
def dump(self, *args):
pass
@@ -47,55 +61,25 @@
def load_effective_addr(self, *args):
self.lea.append(args)
-class MockGcRootMap(object):
- def get_basic_shape(self):
- return ['shape']
- def add_ebp_offset(self, shape, offset):
- shape.append(offset)
- def add_ebx(self, shape):
- shape.append('ebx')
- def add_esi(self, shape):
- shape.append('esi')
- def add_edi(self, shape):
- shape.append('edi')
- def compress_callshape(self, shape):
- assert shape[0] == 'shape'
- return ['compressed'] + shape[1:]
-
-class MockGcDescr(GcCache):
- def get_funcptr_for_new(self):
- return 123
- get_funcptr_for_newarray = get_funcptr_for_new
- get_funcptr_for_newstr = get_funcptr_for_new
- get_funcptr_for_newunicode = get_funcptr_for_new
+def fill_regs(regalloc, cls=BoxInt):
+ allboxes = []
+ for reg in REGS:
+ box = cls()
+ allboxes.append(box)
+ regalloc.reg_bindings[box] = reg
+ regalloc.free_regs = []
+ return allboxes
- moving_gc = True
- gcrootmap = MockGcRootMap()
-
- def initialize(self):
- pass
- def rewrite_assembler(self, cpu, operations):
- pass
-
-
class RegAllocForTests(RegAlloc):
position = 0
def _compute_next_usage(self, v, _):
return -1
class TestRegallocDirect(object):
- def fill_regs(self, regalloc, cls=BoxInt):
- allboxes = []
- for reg in REGS:
- box = cls()
- allboxes.append(box)
- regalloc.reg_bindings[box] = reg
- regalloc.free_regs = []
- return allboxes
-
+
def test_make_sure_var_in_reg(self):
regalloc = RegAlloc(MockAssembler(), DummyTree())
- boxes = self.fill_regs(regalloc)
+ boxes = fill_regs(regalloc)
box = boxes[-1]
oldloc = regalloc.loc(box)
newloc = regalloc.make_sure_var_in_reg(box, [])
@@ -136,7 +120,7 @@
def test_registers_around_call(self):
cpu = CPU(None, None)
regalloc = RegAlloc(MockAssembler(cpu), DummyTree())
- boxes = self.fill_regs(regalloc)
+ boxes = fill_regs(regalloc)
TP = lltype.FuncType([], lltype.Void)
calldescr = cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
regalloc._check_invariants()
@@ -149,31 +133,10 @@
assert len(regalloc.assembler.stores) == 3
regalloc._check_invariants()
- def test_mark_gc_roots(self):
- cpu = CPU(None, None)
- regalloc = RegAlloc(MockAssembler(cpu), DummyTree())
- cpu = regalloc.assembler.cpu
- boxes = self.fill_regs(regalloc, cls=BoxPtr)
- TP = lltype.FuncType([], lltype.Signed)
- calldescr = cpu.calldescrof(TP, TP.ARGS, TP.RESULT)
- regalloc._check_invariants()
- for box in boxes:
- regalloc.longevity[box] = (0, 1)
- box = boxes[0]
- regalloc.position = 0
- regalloc.consider_call(ResOperation(rop.CALL, [box], BoxInt(),
- calldescr), None)
- assert len(regalloc.assembler.stores) == 3
- #
- mark = regalloc.get_mark_gc_roots(cpu.gc_ll_descr.gcrootmap)
- assert mark[0] == 'compressed'
- expected = ['ebx', 'esi', 'edi', -16, -20, -24]
- assert dict.fromkeys(mark[1:]) == dict.fromkeys(expected)
-
def test_registers_around_newstr(self):
cpu = CPU(None, None)
regalloc = RegAllocForTests(MockAssembler(cpu), DummyTree())
- boxes = self.fill_regs(regalloc)
+ boxes = fill_regs(regalloc)
regalloc._check_invariants()
for box in boxes:
regalloc.longevity[box] = (0, 1)
@@ -247,9 +210,9 @@
gcref = self.cpu.get_latest_value_ref(index)
return lltype.cast_opaque_ptr(T, gcref)
- def attach_bridge(self, ops, loop, guard_op):
+ def attach_bridge(self, ops, loop, guard_op, **kwds):
assert guard_op.is_guard()
- bridge = self.parse(ops)
+ bridge = self.parse(ops, **kwds)
guard_op.suboperations = bridge.operations
self.cpu.compile_operations(loop, guard_op)
return bridge
@@ -268,34 +231,6 @@
self.interpret(ops, [0])
assert self.getint(0) == 20
- def test_compile_and_recompile(self):
- ops = '''
- [i0]
- i1 = int_add(i0, 1)
- i2 = int_lt(i1, 20)
- guard_true(i2)
- fail(i1)
- jump(i1)
- '''
- loop = self.interpret(ops, [0])
- assert self.getint(0) == 20
- ops = '''
- [i1]
- i3 = int_add(i1, 1)
- i4 = int_add(i3, 1)
- i5 = int_add(i4, 1)
- i6 = int_add(i5, 1)
- fail(i3, i4, i5, i6)
- '''
- bridge = self.attach_bridge(ops, loop, loop.operations[-2])
- self.cpu.set_future_value_int(0, 0)
- op = self.cpu.execute_operations(loop)
- assert op is bridge.operations[-1]
- assert self.getint(0) == 21
- assert self.getint(1) == 22
- assert self.getint(2) == 23
- assert self.getint(3) == 24
-
def test_two_loops_and_a_bridge(self):
ops = '''
[i0, i1, i2, i3]
@@ -305,7 +240,7 @@
fail(i4, i1, i2, i3)
jump(i4, i1, i2, i3)
'''
- loop = self.interpret(ops, [0])
+ loop = self.interpret(ops, [0, 0, 0, 0])
ops2 = '''
[i5]
i1 = int_add(i5, 1)
@@ -313,10 +248,18 @@
i4 = int_add(i3, 1)
i2 = int_lt(i4, 30)
guard_true(i2)
- jump(i4, i4, i4, i4)
+ fail(i4)
jump(i4)
'''
- loop2 = self.interpret(ops2, [0], jump_targets=[loop, 'self'])
+ loop2 = self.interpret(ops2, [0])
+ bridge_ops = '''
+ [i4]
+ jump(i4, i4, i4, i4)
+ '''
+ bridge = self.attach_bridge(bridge_ops, loop2, loop2.operations[4],
+ jump_targets=[loop])
+ self.cpu.set_future_value_int(0, 0)
+ self.cpu.execute_operations(loop2)
assert self.getint(0) == 31
assert self.getint(1) == 30
assert self.getint(2) == 30
@@ -339,18 +282,24 @@
assert not self.cpu.assembler.fail_boxes_ptr[1]
def test_exception_bridge_no_exception(self):
-
-
ops = '''
[i0]
call(ConstClass(raising_fptr), i0, descr=raising_calldescr)
guard_exception(ConstClass(zero_division_error))
- guard_no_exception()
- fail(2)
fail(1)
fail(0)
'''
- self.interpret(ops, [0])
+ bridge_ops = '''
+ []
+ guard_no_exception()
+ fail(2)
+ fail(1)
+ '''
+ loop = self.interpret(ops, [0])
+ assert self.getint(0) == 1
+ bridge = self.attach_bridge(bridge_ops, loop, loop.operations[1])
+ self.cpu.set_future_value_int(0, 0)
+ self.cpu.execute_operations(loop)
assert self.getint(0) == 1
def test_inputarg_unused(self):
@@ -365,15 +314,43 @@
ops = '''
[i0, i1]
guard_true(i0)
- guard_true(i0)
- fail(i0, i1)
- fail(3)
+ fail(i0, i1)
fail(4)
'''
- self.interpret(ops, [0, 10])
+ bridge_ops = '''
+ [i0, i1]
+ guard_true(i0)
+ fail(i0, i1)
+ fail(3)
+ '''
+ loop = self.interpret(ops, [0, 10])
+ assert self.getint(0) == 0
+ assert self.getint(1) == 10
+ bridge = self.attach_bridge(bridge_ops, loop, loop.operations[0])
+ self.cpu.set_future_value_int(0, 0)
+ self.cpu.set_future_value_int(1, 10)
+ self.cpu.execute_operations(loop)
assert self.getint(0) == 0
assert self.getint(1) == 10
+ def test_nested_unused_arg(self):
+ ops = '''
+ [i0, i1]
+ guard_true(i0)
+ fail(i0, i1)
+ fail(1)
+ '''
+ loop = self.interpret(ops, [0, 1])
+ assert self.getint(0) == 0
+ bridge_ops = '''
+ [i0, i1]
+ fail(1, 2)
+ '''
+ self.attach_bridge(bridge_ops, loop, loop.operations[0])
+ self.cpu.set_future_value_int(0, 0)
+ self.cpu.set_future_value_int(1, 1)
+ self.cpu.execute_operations(loop)
+
def test_spill_for_constant(self):
ops = '''
[i0, i1, i2, i3]
@@ -476,6 +453,26 @@
self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0])
assert self.getint(0) == 0
+ def test_bug_wrong_stack_adj(self):
+ ops = '''
+ [i0, i1, i2, i3, i4, i5, i6, i7, i8]
+ guard_true(i0)
+ fail(0, i0, i1, i2, i3, i4, i5, i6, i7, i8)
+ fail(1, i0, i1, i2, i3, i4, i5, i6, i7, i8)
+ '''
+ loop = self.interpret(ops, [0, 1, 2, 3, 4, 5, 6, 7, 8])
+ assert self.getint(0) == 0
+ bridge_ops = '''
+ [i0, i1, i2, i3, i4, i5, i6, i7, i8]
+ call(ConstClass(raising_fptr), 0, descr=raising_calldescr)
+ fail(i0, i1, i2, i3, i4, i5, i6, i7, i8)
+ '''
+ self.attach_bridge(bridge_ops, loop, loop.operations[0])
+ for i in range(9):
+ self.cpu.set_future_value_int(i, i)
+ self.cpu.execute_operations(loop)
+ assert self.getints(9) == range(9)
+
class TestRegallocCompOps(BaseTestRegalloc):
def test_cmp_op_0(self):
@@ -574,99 +571,3 @@
s = lltype.malloc(self.A, 3)
self.interpret(ops, [s, ord('a')])
assert s[1] == 'a'
-
-
-class TestRegallocGc(BaseTestRegalloc):
- cpu = CPU(None, None)
- cpu.gc_ll_descr = MockGcDescr(False)
-
- S = lltype.GcForwardReference()
- S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)),
- ('int', lltype.Signed)))
-
- fielddescr = cpu.fielddescrof(S, 'field')
-
- struct_ptr = lltype.malloc(S)
- struct_ref = lltype.cast_opaque_ptr(llmemory.GCREF, struct_ptr)
- child_ptr = lltype.nullptr(S)
- struct_ptr.field = child_ptr
-
-
- descr0 = cpu.fielddescrof(S, 'int')
- ptr0 = struct_ref
-
- namespace = locals().copy()
-
- def test_basic(self):
- ops = '''
- [p0]
- p1 = getfield_gc(p0, descr=fielddescr)
- fail(p1)
- '''
- self.interpret(ops, [self.struct_ptr])
- assert not self.getptr(0, lltype.Ptr(self.S))
-
- def test_rewrite_constptr(self):
- ops = '''
- []
- p1 = getfield_gc(ConstPtr(struct_ref), descr=fielddescr)
- fail(p1)
- '''
- self.interpret(ops, [])
- assert not self.getptr(0, lltype.Ptr(self.S))
-
- def test_rewrite_constptr_in_brdige(self):
- ops = '''
- [i0]
- guard_true(i0)
- p1 = getfield_gc(ConstPtr(struct_ref), descr=fielddescr)
- fail(p1)
- fail(0)
- '''
- self.interpret(ops, [0])
- assert not self.getptr(0, lltype.Ptr(self.S))
-
- def test_bug_0(self):
- ops = '''
- [i0, i1, i2, i3, i4, i5, i6, i7, i8]
- guard_value(i2, 1)
- fail(i2, i3, i4, i5, i6, i7, i0, i1, i8)
- guard_class(i4, 138998336)
- fail(i4, i5, i6, i7, i0, i1, i8)
- i11 = getfield_gc(i4, descr=descr0)
- i12 = ooisnull(i11)
- guard_false(i12)
- fail(i4, i5, i6, i7, i0, i1, i11, i8)
- i13 = getfield_gc(i11, descr=descr0)
- i14 = ooisnull(i13)
- guard_true(i14)
- fail(i4, i5, i6, i7, i0, i1, i11, i8)
- i15 = getfield_gc(i4, descr=descr0)
- i17 = int_lt(i15, 0)
- guard_false(i17)
- fail(i4, i5, i6, i7, i0, i1, i11, i15, i8)
- i18 = getfield_gc(i11, descr=descr0)
- i19 = int_ge(i15, i18)
- guard_false(i19)
- fail(i4, i5, i6, i7, i0, i1, i11, i15, i8)
- i20 = int_lt(i15, 0)
- guard_false(i20)
- fail(i4, i5, i6, i7, i0, i1, i11, i15, i8)
- i21 = getfield_gc(i11, descr=descr0)
- i22 = getfield_gc(i11, descr=descr0)
- i23 = int_mul(i15, i22)
- i24 = int_add(i21, i23)
- i25 = getfield_gc(i4, descr=descr0)
- i27 = int_add(i25, 1)
- setfield_gc(i4, i27, descr=descr0)
- i29 = getfield_raw(144839744, descr=descr0)
- i31 = int_and(i29, -2141192192)
- i32 = int_is_true(i31)
- guard_false(i32)
- fail(i4, i6, i7, i0, i1, i24)
- i33 = getfield_gc(i0, descr=descr0)
- guard_value(i33, ConstPtr(ptr0))
- fail(i4, i6, i7, i0, i1, i33, i24)
- jump(i0, i1, 1, 17, i4, ConstPtr(ptr0), i6, i7, i24)
- '''
- self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0, 0], run=False)
Modified: pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/backend/x86/test/test_virtual.py Thu Sep 10 16:45:13 2009
@@ -8,6 +8,7 @@
# for the individual tests see
# ====> ../../../metainterp/test/test_virtual.py
_new_op = 'new_with_vtable'
+ _field_prefix = 'inst_'
@staticmethod
def _new():
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/codewriter.py Thu Sep 10 16:45:13 2009
@@ -251,7 +251,8 @@
graph, oosend_methdescr = graph_key
self.bytecode = self.codewriter.get_jitcode(graph,
oosend_methdescr=oosend_methdescr)
- if not codewriter.policy.look_inside_graph(graph):
+ if not codewriter.policy.look_inside_graph(graph,
+ self.cpu.supports_floats):
assert not portal, "portal has been hidden!"
graph = make_calling_stub(codewriter.rtyper, graph)
self.graph = graph
@@ -612,6 +613,9 @@
def serialize_op_uint_xor(self, op): self._defl(op, 'int_xor')
def serialize_op_uint_lshift(self, op): self._defl(op, 'int_lshift')
+ def serialize_op_cast_bool_to_float(self, op):
+ self.default_serialize_op(op, 'cast_int_to_float')
+
serialize_op_unichar_eq = serialize_op_char_eq
serialize_op_unichar_ne = serialize_op_char_ne
@@ -717,7 +721,8 @@
pass
else:
if hasattr(rtti._obj, 'destructor_funcptr'):
- self.handle_builtin_call(op)
+ c_vtable = Constant(vtable, lltype.typeOf(vtable))
+ self._do_builtin_call(op, 'alloc_with_del', [c_vtable])
return
# store the vtable as an address -- that's fine, because the
# GC doesn't need to follow them
@@ -751,6 +756,21 @@
self.const_position(cls))
self.codewriter.register_known_ooclass(cls, TYPE)
self.register_var(op.result)
+ # initialize fields with a non-default value: while in ootype it's
+ # new() that takes care of it, for the jit we explicitly insert the
+ # corresponding setfields(). This way, the backends don't need to care
+ # about default fields and moreover the resulting code is more similar
+ # to the lltype version, so the optimizer doesn't need to take special
+ # care for them.
+ if isinstance(TYPE, ootype.Instance):
+ fields = TYPE._get_fields_with_different_default()
+ var_inst = self.var_position(op.result)
+ for name, (T, value) in fields:
+ descr = self.cpu.fielddescrof(TYPE, name)
+ self.emit('setfield_gc')
+ self.emit(var_inst)
+ self.emit(self.get_position(descr))
+ self.emit(self.var_position(Constant(value)))
def serialize_op_oonewarray(self, op):
ARRAY = op.args[0].value
@@ -1003,20 +1023,24 @@
self.emit('can_enter_jit')
def serialize_op_direct_call(self, op):
- kind = self.codewriter.policy.guess_call_kind(op)
+ kind = self.codewriter.policy.guess_call_kind(op,
+ self.codewriter.cpu.supports_floats)
return getattr(self, 'handle_%s_call' % kind)(op)
def serialize_op_indirect_call(self, op):
- kind = self.codewriter.policy.guess_call_kind(op)
+ kind = self.codewriter.policy.guess_call_kind(op,
+ self.codewriter.cpu.supports_floats)
return getattr(self, 'handle_%s_indirect_call' % kind)(op)
def serialize_op_oosend(self, op):
- kind = self.codewriter.policy.guess_call_kind(op)
+ kind = self.codewriter.policy.guess_call_kind(op,
+ self.codewriter.cpu.supports_floats)
return getattr(self, 'handle_%s_oosend' % kind)(op)
def handle_regular_call(self, op, oosend_methdescr=None):
self.minimize_variables()
- [targetgraph] = self.codewriter.policy.graphs_from(op)
+ [targetgraph] = self.codewriter.policy.graphs_from(op,
+ self.codewriter.cpu.supports_floats)
jitbox = self.codewriter.get_jitcode(targetgraph, self.graph,
oosend_methdescr=oosend_methdescr)
if oosend_methdescr:
@@ -1063,6 +1087,8 @@
calldescr, non_void_args = self.codewriter.getcalldescr(op.args[0],
args,
op.result)
+ self.emit('recursion_leave_prep')
+ self.emit_varargs(non_void_args)
self.emit('recursive_call')
self.emit(self.get_position(calldescr))
self.emit_varargs([op.args[0]] + non_void_args)
@@ -1071,7 +1097,8 @@
handle_residual_indirect_call = handle_residual_call
def handle_regular_indirect_call(self, op):
- targets = self.codewriter.policy.graphs_from(op)
+ targets = self.codewriter.policy.graphs_from(op,
+ self.codewriter.cpu.supports_floats)
assert targets is not None
self.minimize_variables()
indirectcallset = self.codewriter.get_indirectcallset(targets)
@@ -1101,6 +1128,9 @@
def handle_builtin_call(self, op):
oopspec_name, args = support.decode_builtin_call(op)
+ return self._do_builtin_call(op, oopspec_name, args)
+
+ def _do_builtin_call(self, op, oopspec_name, args):
argtypes = [v.concretetype for v in args]
resulttype = op.result.concretetype
c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper,
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/compile.py Thu Sep 10 16:45:13 2009
@@ -7,7 +7,7 @@
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.metainterp.history import TreeLoop, log, Box, History
from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj,\
- Const
+ BoxFloat, Const
from pypy.jit.metainterp import history
from pypy.jit.metainterp.specnode import NotSpecNode
from pypy.jit.metainterp.typesystem import llhelper, oohelper
@@ -163,6 +163,17 @@
result = resultbox.getref_base()
raise metainterp_sd.DoneWithThisFrameRef(cpu, result)
+class DoneWithThisFrameDescrFloat(AbstractDescr):
+ def handle_fail_op(self, metainterp_sd, fail_op):
+ assert metainterp_sd.result_type == 'float'
+ resultbox = fail_op.args[0]
+ if isinstance(resultbox, BoxFloat):
+ result = metainterp_sd.cpu.get_latest_value_float(0)
+ else:
+ assert isinstance(resultbox, history.Const)
+ result = resultbox.getfloat()
+ raise metainterp_sd.DoneWithThisFrameFloat(result)
+
class ExitFrameWithExceptionDescrRef(AbstractDescr):
def handle_fail_op(self, metainterp_sd, fail_op):
assert len(fail_op.args) == 1
@@ -178,6 +189,7 @@
done_with_this_frame_descr_void = DoneWithThisFrameDescrVoid()
done_with_this_frame_descr_int = DoneWithThisFrameDescrInt()
done_with_this_frame_descr_ref = DoneWithThisFrameDescrRef()
+done_with_this_frame_descr_float = DoneWithThisFrameDescrFloat()
exit_frame_with_exception_descr_ref = ExitFrameWithExceptionDescrRef()
class TerminatingLoop(TreeLoop):
@@ -204,6 +216,12 @@
_loop.finishdescr = done_with_this_frame_descr_ref
oohelper.loops_done_with_this_frame_ref = [_loop]
+_loop = TerminatingLoop('done_with_this_frame_float')
+_loop.specnodes = [prebuiltNotSpecNode]
+_loop.inputargs = [BoxFloat()]
+_loop.finishdescr = done_with_this_frame_descr_float
+loops_done_with_this_frame_float = [_loop]
+
_loop = TerminatingLoop('done_with_this_frame_void')
_loop.specnodes = []
_loop.inputargs = []
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/executor.py Thu Sep 10 16:45:13 2009
@@ -7,7 +7,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.rarithmetic import ovfcheck, r_uint, intmask
from pypy.jit.metainterp.history import BoxInt, ConstInt, check_descr
-from pypy.jit.metainterp.history import INT, REF
+from pypy.jit.metainterp.history import INT, REF, ConstFloat
from pypy.jit.metainterp.resoperation import rop
@@ -218,6 +218,53 @@
cpu._overflow_flag = ovf
return BoxInt(z)
+# ----------
+
+def do_float_neg(cpu, args, descr=None):
+ return ConstFloat(-args[0].getfloat())
+
+def do_float_abs(cpu, args, descr=None):
+ return ConstFloat(abs(args[0].getfloat()))
+
+def do_float_is_true(cpu, args, descr=None):
+ return ConstInt(bool(args[0].getfloat()))
+
+def do_float_add(cpu, args, descr=None):
+ return ConstFloat(args[0].getfloat() + args[1].getfloat())
+
+def do_float_sub(cpu, args, descr=None):
+ return ConstFloat(args[0].getfloat() - args[1].getfloat())
+
+def do_float_mul(cpu, args, descr=None):
+ return ConstFloat(args[0].getfloat() * args[1].getfloat())
+
+def do_float_truediv(cpu, args, descr=None):
+ return ConstFloat(args[0].getfloat() / args[1].getfloat())
+
+def do_float_lt(cpu, args, descr=None):
+ return ConstInt(args[0].getfloat() < args[1].getfloat())
+
+def do_float_le(cpu, args, descr=None):
+ return ConstInt(args[0].getfloat() <= args[1].getfloat())
+
+def do_float_eq(cpu, args, descr=None):
+ return ConstInt(args[0].getfloat() == args[1].getfloat())
+
+def do_float_ne(cpu, args, descr=None):
+ return ConstInt(args[0].getfloat() != args[1].getfloat())
+
+def do_float_gt(cpu, args, descr=None):
+ return ConstInt(args[0].getfloat() > args[1].getfloat())
+
+def do_float_ge(cpu, args, descr=None):
+ return ConstInt(args[0].getfloat() >= args[1].getfloat())
+
+def do_cast_float_to_int(cpu, args, descr=None):
+ return ConstInt(int(args[0].getfloat()))
+
+def do_cast_int_to_float(cpu, args, descr=None):
+ return ConstFloat(float(args[0].getint()))
+
# ____________________________________________________________
def do_debug_merge_point(cpu, args, descr=None):
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/history.py Thu Sep 10 16:45:13 2009
@@ -16,13 +16,16 @@
# ____________________________________________________________
-INT = 'i'
-REF = 'r'
+INT = 'i'
+REF = 'r'
+FLOAT = 'f'
-def getkind(TYPE):
+def getkind(TYPE, supports_floats=True):
if TYPE is lltype.Void:
return "void"
elif isinstance(TYPE, lltype.Primitive):
+ if TYPE is lltype.Float and supports_floats:
+ return 'float'
if TYPE in (lltype.Float, lltype.SingleFloat):
raise NotImplementedError("type %s not supported" % TYPE)
# XXX fix this for oo...
@@ -68,7 +71,7 @@
self.seen = {}
def repr_rpython(self, box, typechars):
n = self.seen.setdefault(box, len(self.seen))
- return '%s/%s%d' % (box.get_(), typechars, n)
+ return '%s/%s%d' % (box._get_hash_(), typechars, n)
repr_rpython = ReprRPython().repr_rpython
@@ -79,6 +82,9 @@
def getint(self):
raise NotImplementedError
+ def getfloat(self):
+ raise NotImplementedError
+
def getref_base(self):
raise NotImplementedError
@@ -86,7 +92,7 @@
raise NotImplementedError
getref._annspecialcase_ = 'specialize:arg(1)'
- def get_(self):
+ def _get_hash_(self):
raise NotImplementedError
def nonnull(self):
@@ -157,6 +163,8 @@
return ConstInt(intval)
elif kind == "ref":
return cpu.ts.new_ConstRef(x)
+ elif kind == "float":
+ return ConstFloat(x)
else:
raise NotImplementedError(kind)
@@ -212,7 +220,7 @@
def getaddr(self, cpu):
return cpu.cast_int_to_adr(self.value)
- def get_(self):
+ def _get_hash_(self):
return self.value
def nonnull(self):
@@ -258,7 +266,7 @@
def getaddr(self, cpu):
return self.value
- def get_(self):
+ def _get_hash_(self):
return llmemory.cast_adr_to_int(self.value)
def nonnull(self):
@@ -276,6 +284,38 @@
def repr_rpython(self):
return repr_rpython(self, 'ca')
+class ConstFloat(Const):
+ type = FLOAT
+ value = 0.0
+ _attrs_ = ('value',)
+
+ def __init__(self, floatval):
+ assert isinstance(floatval, float)
+ self.value = floatval
+
+ def clonebox(self):
+ return BoxFloat(self.value)
+
+ nonconstbox = clonebox
+
+ def getfloat(self):
+ return self.value
+
+ def _get_hash_(self):
+ return hash(self.value)
+
+ def set_future_value(self, cpu, j):
+ cpu.set_future_value_float(j, self.getfloat())
+
+ def equals(self, other):
+ return self.value == other.getfloat()
+
+ def _getrepr_(self):
+ return self.value
+
+ def repr_rpython(self):
+ return repr_rpython(self, 'cf')
+
class ConstPtr(Const):
type = REF
value = lltype.nullptr(llmemory.GCREF.TO)
@@ -297,7 +337,7 @@
return lltype.cast_opaque_ptr(PTR, self.getref_base())
getref._annspecialcase_ = 'specialize:arg(1)'
- def get_(self):
+ def _get_hash_(self):
return lltype.cast_ptr_to_int(self.value)
def getaddr(self, cpu):
@@ -343,9 +383,9 @@
return ootype.cast_from_object(OBJ, self.getref_base())
getref._annspecialcase_ = 'specialize:arg(1)'
- def get_(self):
+ def _get_hash_(self):
if self.value:
- return ootype.ooidentityhash(self.value) # XXX: check me
+ return ootype.ooidentityhash(self.value)
else:
return 0
@@ -390,6 +430,8 @@
# XXX add ootype support?
ptrval = lltype.cast_opaque_ptr(llmemory.GCREF, x)
return BoxPtr(ptrval)
+ elif kind == "float":
+ return BoxFloat(x)
else:
raise NotImplementedError(kind)
@@ -448,7 +490,7 @@
def getaddr(self, cpu):
return cpu.cast_int_to_adr(self.value)
- def get_(self):
+ def _get_hash_(self):
return self.value
def nonnull(self):
@@ -468,6 +510,40 @@
changevalue_int = __init__
+class BoxFloat(Box):
+ type = FLOAT
+ _attrs_ = ('value',)
+
+ def __init__(self, floatval=0.0):
+ assert isinstance(floatval, float)
+ self.value = floatval
+
+ def clonebox(self):
+ return BoxFloat(self.value)
+
+ def constbox(self):
+ return ConstFloat(self.value)
+
+ def getfloat(self):
+ return self.value
+
+ def _get_hash_(self):
+ return hash(self.value)
+
+ def set_future_value(self, cpu, j):
+ cpu.set_future_value_float(j, self.value)
+
+ def _getrepr_(self):
+ return self.value
+
+ def repr_rpython(self):
+ return repr_rpython(self, 'bf')
+
+ def changevalue_box(self, srcbox):
+ self.changevalue_float(srcbox.getfloat())
+
+ changevalue_float = __init__
+
class BoxPtr(Box):
type = REF
_attrs_ = ('value',)
@@ -492,7 +568,7 @@
def getaddr(self, cpu):
return llmemory.cast_ptr_to_adr(self.value)
- def get_(self):
+ def _get_hash_(self):
return lltype.cast_ptr_to_int(self.value)
def nonnull(self):
@@ -534,9 +610,9 @@
return ootype.cast_from_object(OBJ, self.getref_base())
getref._annspecialcase_ = 'specialize:arg(1)'
- def get_(self):
+ def _get_hash_(self):
if self.value:
- return ootype.ooidentityhash(self.value) # XXX: check me
+ return ootype.ooidentityhash(self.value)
else:
return 0
@@ -577,7 +653,7 @@
if isinstance(c.value, Symbolic):
return id(c.value)
try:
- return c.get_()
+ return c._get_hash_()
except lltype.DelayedPointer:
return -2 # xxx risk of changing hash...
@@ -712,6 +788,7 @@
compiled_count = 0
enter_count = 0
+ aborted_count = 0
def __init__(self):
self.loops = []
@@ -777,10 +854,9 @@
class Options:
logger_noopt = None
- def __init__(self, specialize=True, listops=False, inline=False):
+ def __init__(self, specialize=True, listops=False):
self.specialize = specialize
self.listops = listops
- self.inline = inline
def _freeze_(self):
return True
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/jitprof.py Thu Sep 10 16:45:13 2009
@@ -3,6 +3,7 @@
"""
import time
+from pypy.rlib.debug import debug_print
TRACING = 0
BACKEND = 1
@@ -69,11 +70,11 @@
t0 = self.t1
self.t1 = self.timer()
if not self.current:
- print "BROKEN PROFILER DATA!"
+ debug_print("BROKEN PROFILER DATA!")
return
ev1 = self.current.pop()
if ev1 != event:
- print "BROKEN PROFILER DATA!"
+ debug_print("BROKEN PROFILER DATA!")
return
self.times[ev1] += self.t1 - t0
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/optimizeopt.py Thu Sep 10 16:45:13 2009
@@ -560,7 +560,8 @@
def optimize_GUARD_VALUE(self, op):
assert isinstance(op.args[1], Const)
- assert op.args[0].get_() == op.args[1].get_()
+ if not we_are_translated():
+ assert op.args[0].value == op.args[1].value
self.optimize_guard(op)
def optimize_GUARD_TRUE(self, op):
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/policy.py Thu Sep 10 16:45:13 2009
@@ -16,20 +16,22 @@
return False
return True
- def look_inside_graph(self, graph):
- if contains_unsupported_variable_type(graph):
- return False
+ def look_inside_graph(self, graph, supports_floats):
try:
func = graph.func
except AttributeError:
- return True
- return self.look_inside_function(func)
+ see_function = True
+ else:
+ see_function = self.look_inside_function(func)
+ return (see_function and
+ not contains_unsupported_variable_type(graph,
+ supports_floats))
- def graphs_from(self, op):
+ def graphs_from(self, op, supports_floats):
if op.opname == 'direct_call':
funcobj = get_funcobj(op.args[0].value)
graph = funcobj.graph
- if self.look_inside_graph(graph):
+ if self.look_inside_graph(graph, supports_floats):
return [graph] # common case: look inside this graph
else:
assert op.opname in ('indirect_call', 'oosend')
@@ -40,13 +42,13 @@
graphs = v_obj._lookup_graphs(op.args[0].value)
if graphs is not None:
for graph in graphs:
- if self.look_inside_graph(graph):
+ if self.look_inside_graph(graph, supports_floats):
return graphs # common case: look inside at
# least one of the graphs
# residual call case: we don't need to look into any graph
return None
- def guess_call_kind(self, op):
+ def guess_call_kind(self, op, supports_floats):
if op.opname == 'direct_call':
funcobj = get_funcobj(op.args[0].value)
if isinstance(lltype.typeOf(funcobj), lltype.Ptr):
@@ -69,20 +71,20 @@
return 'builtin'
# TODO: return 'recursive' if the oosend ends with calling the
# portal
- if self.graphs_from(op) is None:
+ if self.graphs_from(op, supports_floats) is None:
return 'residual'
return 'regular'
-def contains_unsupported_variable_type(graph):
+def contains_unsupported_variable_type(graph, supports_floats):
getkind = history.getkind
try:
for block in graph.iterblocks():
for v in block.inputargs:
- getkind(v.concretetype)
+ getkind(v.concretetype, supports_floats)
for op in block.operations:
for v in op.args:
- getkind(v.concretetype)
- getkind(op.result.concretetype)
+ getkind(v.concretetype, supports_floats)
+ getkind(op.result.concretetype, supports_floats)
except NotImplementedError, e:
history.log.WARNING('%s, ignoring graph' % (e,))
history.log.WARNING(' %s' % (graph,))
@@ -99,96 +101,3 @@
if func in self.funcs:
return False
return super(StopAtXPolicy, self).look_inside_function(func)
-
-# ____________________________________________________________
-
-from pypy.annotation.specialize import getuniquenondirectgraph
-
-class ManualJitPolicy(JitPolicy):
- def __init__(self, translator):
- self.translator = translator
- self.bookkeeper = translator.annotator.bookkeeper
- self.enabled_graphs = {}
- self.memo = {}
- self.fill_seen_graphs()
-
- def look_inside_graph(self, graph):
- if graph in self.enabled_graphs:
- return self.enabled_graphs[graph]
- res = super(ManualJitPolicy, self).look_inside_graph(graph)
- self.enabled_graphs[graph] = res # cache the result
- return res
-
- def fill_seen_graphs(self):
- # subclasses should have their own
- pass
-
- def _graph(self, func):
- func = getattr(func, 'im_func', func)
- desc = self.bookkeeper.getdesc(func)
- return getuniquenondirectgraph(desc)
-
- def seefunc(self, fromfunc, *tofuncs):
- targetgraphs = {}
- for tofunc in tofuncs:
- targetgraphs[self._graph(tofunc)] = True
- graphs = graphs_on_the_path_to(self.translator, self._graph(fromfunc),
- targetgraphs, self.memo)
- for graph in graphs:
- if graph not in self.enabled_graphs:
- self.enabled_graphs[graph] = True
- print '++', graph
-
- def seepath(self, *path):
- assert len(path) >= 2
- for i in range(1, len(path)):
- self.seefunc(path[i-1], path[i])
-
- def seegraph(self, func, look=True):
- graph = self._graph(func)
- self.enabled_graphs[graph] = look
- if look:
- print '++', graph
- else:
- print '--', graph
-
-def enumerate_reachable_graphs(translator, startgraph, memo=None):
- from pypy.translator.backendopt.support import find_calls_from
- pending = [(startgraph, None)]
- yield pending[0]
- seen = {startgraph: True}
- while pending:
- yield None # hack: a separator meaning "length increases now"
- nextlengthlist = []
- nextseen = {}
- for node in pending:
- head, tail = node
- for block, callee in find_calls_from(translator, head, memo):
- if callee not in seen:
- newnode = callee, node
- yield newnode
- nextlengthlist.append(newnode)
- nextseen[callee] = True
- pending = nextlengthlist
- seen.update(nextseen)
- yield None
-
-def graphs_on_the_path_to(translator, startgraph, targetgraphs, memo=None):
- targetgraphs = targetgraphs.copy()
- result = {}
- found = {}
- for node in enumerate_reachable_graphs(translator, startgraph, memo):
- if node is None: # hack: a separator meaning "length increases now"
- for graph in found:
- del targetgraphs[graph]
- found.clear()
- if not targetgraphs:
- return result
- elif node[0] in targetgraphs:
- found[node[0]] = True
- while node is not None:
- head, tail = node
- result[head] = True
- node = tail
- raise Exception("did not reach all targets:\nmissing %r" % (
- targetgraphs.keys(),))
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/pyjitpl.py Thu Sep 10 16:45:13 2009
@@ -227,6 +227,9 @@
'int_and', 'int_or', 'int_xor',
'int_rshift', 'int_lshift', 'uint_rshift',
'uint_lt', 'uint_le', 'uint_gt', 'uint_ge',
+ 'float_add', 'float_sub', 'float_mul', 'float_truediv',
+ 'float_lt', 'float_le', 'float_eq',
+ 'float_ne', 'float_gt', 'float_ge',
]:
exec py.code.Source('''
@arguments("box", "box")
@@ -243,7 +246,9 @@
''' % (_opimpl, _opimpl.upper())).compile()
for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not',
- 'cast_ptr_to_int', 'cast_int_to_ptr',
+ 'cast_ptr_to_int', 'cast_float_to_int',
+ 'cast_int_to_float', 'float_neg', 'float_abs',
+ 'float_is_true',
]:
exec py.code.Source('''
@arguments("box")
@@ -470,9 +475,8 @@
def opimpl_ptr_iszero(self, box):
self.execute(rop.OOISNULL, [box])
- @arguments("box")
- def opimpl_oononnull(self, box):
- self.execute(rop.OONONNULL, [box])
+ opimpl_oononnull = opimpl_ptr_nonzero
+ opimpl_ooisnull = opimpl_ptr_iszero
@arguments("box", "box")
def opimpl_ptr_eq(self, box1, box2):
@@ -483,6 +487,7 @@
self.execute(rop.OOISNOT, [box1, box2])
opimpl_oois = opimpl_ptr_eq
+ opimpl_ooisnot = opimpl_ptr_ne
@arguments("box", "descr")
def opimpl_getfield_gc(self, box, fielddesc):
@@ -638,14 +643,27 @@
def opimpl_residual_call(self, calldescr, varargs):
return self.execute_with_exc(rop.CALL, varargs, descr=calldescr)
+ @arguments("varargs")
+ def opimpl_recursion_leave_prep(self, varargs):
+ warmrunnerstate = self.metainterp.staticdata.state
+ if warmrunnerstate.inlining:
+ num_green_args = self.metainterp.staticdata.num_green_args
+ greenkey = varargs[:num_green_args]
+ if warmrunnerstate.can_inline_callable(greenkey):
+ return False
+ leave_code = self.metainterp.staticdata.leave_code
+ if leave_code is None:
+ return False
+ return self.perform_call(leave_code, varargs)
+
@arguments("descr", "varargs")
def opimpl_recursive_call(self, calldescr, varargs):
- if self.metainterp.staticdata.options.inline:
+ warmrunnerstate = self.metainterp.staticdata.state
+ if warmrunnerstate.inlining:
num_green_args = self.metainterp.staticdata.num_green_args
portal_code = self.metainterp.staticdata.portal_code
greenkey = varargs[1:num_green_args + 1]
- if self.metainterp.staticdata.state.can_inline_callable(greenkey):
- self.metainterp.in_recursion += 1
+ if warmrunnerstate.can_inline_callable(greenkey):
return self.perform_call(portal_code, varargs[1:])
return self.execute_with_exc(rop.CALL, varargs, descr=calldescr)
@@ -1000,7 +1018,8 @@
virtualizable_info = None
def __init__(self, portal_graph, graphs, cpu, stats, options,
- optimizer=None, profile=None, warmrunnerdesc=None):
+ optimizer=None, profile=None, warmrunnerdesc=None,
+ leave_graph=None):
self.portal_graph = portal_graph
self.cpu = cpu
self.stats = stats
@@ -1034,6 +1053,8 @@
self.jit_starting_line = 'JIT starting (%s, %s)' % (optmodule,
backendmodule)
+ self.leave_graph = leave_graph
+
def _freeze_(self):
return True
@@ -1070,6 +1091,11 @@
self._codewriter = codewriter.CodeWriter(self, policy)
self.portal_code = self._codewriter.make_portal_bytecode(
self.portal_graph)
+ self.leave_code = None
+ if self.leave_graph:
+ self.leave_code = self._codewriter.make_one_bytecode(
+ (self.leave_graph, None),
+ False)
self._class_sizes = self._codewriter.class_sizes
# ---------- construction-time interface ----------
@@ -1123,14 +1149,20 @@
def newframe(self, jitcode):
if not we_are_translated():
self._debug_history.append(['enter', jitcode, None])
+ if jitcode is self.staticdata.portal_code:
+ self.in_recursion += 1
f = MIFrame(self, jitcode)
self.framestack.append(f)
return f
- def finishframe(self, resultbox):
+ def popframe(self):
frame = self.framestack.pop()
if frame.jitcode is self.staticdata.portal_code:
self.in_recursion -= 1
+ return frame
+
+ def finishframe(self, resultbox):
+ frame = self.popframe()
if not we_are_translated():
self._debug_history.append(['leave', frame.jitcode, None])
if self.framestack:
@@ -1148,6 +1180,8 @@
raise sd.DoneWithThisFrameInt(resultbox.getint())
elif sd.result_type == 'ref':
raise sd.DoneWithThisFrameRef(self.cpu, resultbox.getref_base())
+ elif sd.result_type == 'float':
+ raise sd.DoneWithThisFrameFloat(resultbox.getfloat())
else:
assert False
@@ -1171,11 +1205,29 @@
return True
if not we_are_translated():
self._debug_history.append(['leave_exc', frame.jitcode, None])
- self.framestack.pop()
+ self.popframe()
if not self.is_blackholing():
self.compile_exit_frame_with_exception(excvaluebox)
raise self.staticdata.ExitFrameWithExceptionRef(self.cpu, excvaluebox.getref_base())
+ def check_recursion_invariant(self):
+ in_recursion = -1
+ for frame in self.framestack:
+ jitcode = frame.jitcode
+ if jitcode is self.staticdata.portal_code:
+ in_recursion += 1
+ if in_recursion != self.in_recursion:
+ print "in_recursion problem!!!"
+ print in_recursion, self.in_recursion
+ for frame in self.framestack:
+ jitcode = frame.jitcode
+ if jitcode is self.staticdata.portal_code:
+ print "P",
+ else:
+ print " ",
+ print jitcode.name
+ raise Exception
+
def raise_overflow_error(self):
etype, evalue = self.cpu.get_overflow_error()
return self.finishframe_exception(
@@ -1189,6 +1241,7 @@
self.cpu.ts.get_exc_value_box(evalue))
def create_empty_history(self):
+ warmrunnerstate = self.staticdata.state
self.history = history.History(self.cpu)
if self.staticdata.stats is not None:
self.staticdata.stats.history = self.history
@@ -1238,6 +1291,19 @@
op.pc = self.framestack[-1].pc
op.name = self.framestack[-1].jitcode.name
+ def switch_to_blackhole_if_trace_too_long(self):
+ if not self.is_blackholing():
+ warmrunnerstate = self.staticdata.state
+ if len(self.history.operations) > warmrunnerstate.trace_limit:
+ self.history = history.BlackHole(self.cpu)
+ if not we_are_translated():
+ self.staticdata.stats.aborted_count += 1
+ history.log.event('ABORTING TRACING' + self.history.extratext)
+ elif DEBUG:
+ debug_print('~~~ ABORTING TRACING', self.history.extratext)
+ self.staticdata.profiler.end_tracing()
+ self.staticdata.profiler.start_blackhole()
+
def _interpret(self):
# Execute the frames forward until we raise a DoneWithThisFrame,
# a ContinueRunningNormally, or a GenerateMergePoint exception.
@@ -1249,6 +1315,9 @@
try:
while True:
self.framestack[-1].run_one_step()
+ self.switch_to_blackhole_if_trace_too_long()
+ if not we_are_translated():
+ self.check_recursion_invariant()
finally:
if self.is_blackholing():
self.staticdata.profiler.end_blackhole()
@@ -1285,7 +1354,8 @@
return self.designate_target_loop(gmp)
def handle_guard_failure(self, exec_result, key):
- self.initialize_state_from_guard_failure(exec_result)
+ from pypy.jit.metainterp.warmspot import ContinueRunningNormallyBase
+ resumedescr = self.initialize_state_from_guard_failure(exec_result)
assert isinstance(key, compile.ResumeGuardDescr)
top_history = key.find_toplevel_history()
source_loop = top_history.source_link
@@ -1295,12 +1365,18 @@
self.resumekey = key
self.seen_can_enter_jit = False
guard_op = key.get_guard_op()
+ started_as_blackhole = self.is_blackholing()
try:
self.prepare_resume_from_failure(guard_op.opnum)
self.interpret()
assert False, "should always raise"
except GenerateMergePoint, gmp:
return self.designate_target_loop(gmp)
+ except ContinueRunningNormallyBase:
+ if not started_as_blackhole:
+ warmrunnerstate = self.staticdata.state
+ warmrunnerstate.reset_counter_from_failure(resumedescr)
+ raise
def forget_consts(self, boxes, startindex=0):
for i in range(startindex, len(boxes)):
@@ -1456,6 +1532,9 @@
elif sd.result_type == 'ref':
exits = [exitbox]
loops = sd.cpu.ts.loops_done_with_this_frame_ref
+ elif sd.result_type == 'float':
+ exits = [exitbox]
+ loops = compile.loops_done_with_this_frame_float
else:
assert False
self.history.record(rop.JUMP, exits, None)
@@ -1489,7 +1568,7 @@
*args[1:])
def initialize_state_from_start(self, *args):
- self.in_recursion = 0
+ self.in_recursion = -1 # always one portal around
self.staticdata._setup_once()
self.staticdata.profiler.start_tracing()
self.create_empty_history()
@@ -1506,7 +1585,7 @@
def initialize_state_from_guard_failure(self, guard_failure):
# guard failure: rebuild a complete MIFrame stack
- self.in_recursion = 0
+ self.in_recursion = -1 # always one portal around
resumedescr = guard_failure.descr
assert isinstance(resumedescr, compile.ResumeGuardDescr)
warmrunnerstate = self.staticdata.state
@@ -1532,6 +1611,7 @@
# the BlackHole is invalid because it doesn't start with
# guard_failure.key.guard_op.suboperations, but that's fine
self.rebuild_state_after_failure(resumedescr, guard_failure.args)
+ return resumedescr
def initialize_virtualizable(self, original_boxes):
vinfo = self.staticdata.virtualizable_info
@@ -1632,10 +1712,7 @@
jitcode, pc, exception_target = resumereader.consume_frame_info()
env = resumereader.consume_boxes()
f = self.newframe(jitcode)
- if jitcode is self.staticdata.portal_code:
- self.in_recursion += 1
f.setup_resume_at_op(pc, exception_target, env)
- self.in_recursion -= 1 # always one portal around
def check_synchronized_virtualizable(self):
if not we_are_translated():
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/resoperation.py Thu Sep 10 16:45:13 2009
@@ -126,7 +126,6 @@
'OOSEND_PURE', # ootype operation
'CALL_PURE',
#
- 'CAST_INT_TO_PTR',
'CAST_PTR_TO_INT',
'INT_ADD',
'INT_SUB',
@@ -139,6 +138,15 @@
'INT_RSHIFT',
'INT_LSHIFT',
'UINT_RSHIFT',
+ 'FLOAT_ADD',
+ 'FLOAT_SUB',
+ 'FLOAT_MUL',
+ 'FLOAT_TRUEDIV',
+ 'FLOAT_NEG',
+ 'FLOAT_ABS',
+ 'FLOAT_IS_TRUE',
+ 'CAST_FLOAT_TO_INT',
+ 'CAST_INT_TO_FLOAT',
#
'_COMPARISON_FIRST',
'INT_LT',
@@ -152,6 +160,12 @@
'UINT_GT',
'UINT_GE',
'_COMPARISON_LAST',
+ 'FLOAT_LT', # maybe these ones should be comparisons too
+ 'FLOAT_LE',
+ 'FLOAT_EQ',
+ 'FLOAT_NE',
+ 'FLOAT_GT',
+ 'FLOAT_GE',
#
'INT_IS_TRUE',
'INT_NEG',
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/support.py Thu Sep 10 16:45:13 2009
@@ -186,9 +186,11 @@
# ---------- malloc with del ----------
- def _ll_0_alloc_with_del(RESULT):
- return lltype.malloc(RESULT)
- _ll_0_alloc_with_del.need_result_type = True
+ def _ll_1_alloc_with_del(RESULT, vtable):
+ p = lltype.malloc(RESULT)
+ lltype.cast_pointer(rclass.OBJECTPTR, p).typeptr = vtable
+ return p
+ _ll_1_alloc_with_del.need_result_type = True
class OOtypeHelpers:
@@ -341,10 +343,6 @@
else:
raise Exception("oohash() of type %r" % (T,))
-def get_malloc_oopspec(op):
- assert op.args[1].value == {'flavor': 'gc'}
- return 'alloc_with_del', []
-
RENAMED_ADT_NAME = {
'list': {
@@ -375,8 +373,6 @@
return get_oostring_oopspec(op)
elif op.opname == 'oohash':
return get_oohash_oopspec(op)
- elif op.opname == 'malloc': # for malloc with a __del__
- return get_malloc_oopspec(op)
else:
raise ValueError(op.opname)
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/oparser.py Thu Sep 10 16:45:13 2009
@@ -97,6 +97,8 @@
return vars
def getvar(self, arg):
+ if not arg:
+ return ConstInt(0)
try:
return ConstInt(int(arg))
except ValueError:
@@ -145,7 +147,10 @@
argspec = line[num + 1:endnum]
if not argspec.strip():
return opnum, [], None
- allargs = argspec.split(",")
+ if opname == 'debug_merge_point':
+ allargs = [argspec]
+ else:
+ allargs = argspec.split(",")
args = []
descr = None
poss_descr = allargs[-1].strip()
@@ -195,8 +200,15 @@
ops = []
newlines = []
for line in lines:
- if '#' in line:
- line = line[:line.index('#')] # remove comment
+ # for simplicity comments are not allowed on
+ # debug_merge_point lines
+ if '#' in line and 'debug_merge_point(' not in line:
+ if line.lstrip()[0] == '#': # comment only
+ continue
+ comm = line.rfind('#')
+ rpar = line.find(')') # assume there's a op(...)
+ if comm > rpar:
+ line = line[:comm].rstrip()
if not line.strip():
continue # a comment or empty line
newlines.append(line)
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_basic.py Thu Sep 10 16:45:13 2009
@@ -1,4 +1,5 @@
import py
+import sys
from pypy.rlib.jit import JitDriver, we_are_jitted, hint, dont_look_inside
from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
from pypy.jit.backend.llgraph import runner
@@ -49,6 +50,8 @@
assert get_stats().enter_count <= count
def check_jumps(self, maxcount):
assert get_stats().exec_jumps <= maxcount
+ def check_aborted_count(self, maxcount):
+ assert get_stats().aborted_count == maxcount
def meta_interp(self, *args, **kwds):
kwds['CPUClass'] = self.CPUClass
@@ -70,6 +73,8 @@
class FakeWarmRunnerDesc:
def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
pass
+
+ trace_limit = sys.maxint
if policy is None:
policy = JitPolicy()
@@ -89,6 +94,7 @@
metainterp.staticdata.state = FakeWarmRunnerDesc()
metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame
metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef
+ metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame
self.metainterp = metainterp
try:
metainterp.compile_and_run_once(*args)
@@ -402,6 +408,24 @@
assert res == 210
self.check_history_(getfield_gc=0)
+ def test_setfield_bool(self):
+ class A:
+ def __init__(self):
+ self.flag = True
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'obj'])
+ def f(n):
+ obj = A()
+ res = False
+ while n > 0:
+ myjitdriver.can_enter_jit(n=n, obj=obj)
+ myjitdriver.jit_merge_point(n=n, obj=obj)
+ obj.flag = False
+ n -= 1
+ return res
+ res = self.meta_interp(f, [7])
+ assert type(res) == bool
+ assert not res
+
def test_switch_dict(self):
def f(x):
if x == 1: return 61
@@ -915,16 +939,21 @@
lltype.free(x, flavor='raw')
def test_casts(self):
+ if not self.basic:
+ py.test.skip("test written in a style that "
+ "means it's frontend only")
from pypy.rpython.lltypesystem import lltype, llmemory
TP = lltype.GcStruct('x')
def f(p):
n = lltype.cast_ptr_to_int(p)
- return lltype.cast_int_to_ptr(lltype.Ptr(TP), n)
+ return n
x = lltype.malloc(TP)
- expected = lltype.cast_opaque_ptr(llmemory.GCREF, x)
- assert self.interp_operations(f, [x]) == expected
+ res = self.interp_operations(f, [x])
+ expected = self.metainterp.cpu.do_cast_ptr_to_int(
+ [history.BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, x))]).value
+ assert res == expected
class TestLLtype(BaseLLtypeTests, LLJitMixin):
pass
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_del.py Thu Sep 10 16:45:13 2009
@@ -27,6 +27,33 @@
'guard_true': 1,
'jump': 1})
+ def test_class_of_allocated(self):
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
+ class Foo:
+ def __del__(self):
+ pass
+ def f(self):
+ return self.meth()
+ class X(Foo):
+ def meth(self):
+ return 456
+ class Y(Foo):
+ def meth(self):
+ return 123
+ def f(n):
+ x = None
+ while n > 0:
+ myjitdriver.can_enter_jit(x=x, n=n)
+ myjitdriver.jit_merge_point(x=x, n=n)
+ x = X()
+ y = Y()
+ assert x.f() == 456
+ assert y.f() == 123
+ n -= 1
+ return 42
+ res = self.meta_interp(f, [20])
+ assert res == 42
+
class TestLLtype(DelTests, LLJitMixin):
def test_signal_action(self):
@@ -52,6 +79,6 @@
self.check_loops(getfield_raw=1, call=0, call_pure=0)
class TestOOtype(DelTests, OOJitMixin):
- def test_del_keep_obj(self):
+ def setup_class(cls):
py.test.skip("XXX dels are not implemented in the"
" static CLI or JVM backend")
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_oparser.py Thu Sep 10 16:45:13 2009
@@ -8,10 +8,10 @@
def test_basic_parse():
x = """
[i0, i1]
- i2 = int_add(i0, i1)
# a comment
- i3 = int_sub(i2, 3)
- fail()
+ i2 = int_add(i0, i1)
+ i3 = int_sub(i2, 3) # another comment
+ fail() # (tricky)
"""
loop = parse(x)
assert len(loop.operations) == 3
@@ -146,10 +146,15 @@
[]
debug_merge_point("info")
debug_merge_point('info')
+ debug_merge_point('<some ('other,')> info')
+ debug_merge_point('(stuff) #1')
'''
loop = parse(x)
assert loop.operations[0].args[0]._get_str() == 'info'
assert loop.operations[1].args[0]._get_str() == 'info'
+ assert loop.operations[2].args[0]._get_str() == "<some ('other,')> info"
+ assert loop.operations[3].args[0]._get_str() == "(stuff) #1"
+
def test_descr_with_obj_print():
x = '''
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_policy.py Thu Sep 10 16:45:13 2009
@@ -19,11 +19,29 @@
jitpolicy = policy.JitPolicy()
translator = rtyper.annotator.translator
- res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator)
+ res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+ True)
funcs = [graph.func for graph in res]
assert funcs == [i, f]
+def test_find_all_graphs_without_floats():
+ def g(x):
+ return int(x * 12.5)
+ def f(x):
+ return g(x) + 1
+ rtyper = support.annotate(f, [7])
+ jitpolicy = policy.JitPolicy()
+ translator = rtyper.annotator.translator
+ res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+ supports_floats=True)
+ funcs = [graph.func for graph in res]
+ assert funcs == [f, g]
+ res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+ supports_floats=False)
+ funcs = [graph.func for graph in res]
+ assert funcs == [f]
+
def test_find_all_graphs_str_join():
def i(x, y):
return "hello".join([str(x), str(y), "bye"])
@@ -32,7 +50,8 @@
jitpolicy = policy.JitPolicy()
translator = rtyper.annotator.translator
- res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator)
+ res = warmspot.find_all_graphs(translator.graphs[0], jitpolicy, translator,
+ True)
funcs = [graph.func for graph in res]
assert funcs[:1] == [i]
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_pyjitpl.py Thu Sep 10 16:45:13 2009
@@ -1,7 +1,7 @@
# some unit tests for the bytecode decoding
-from pypy.jit.metainterp import pyjitpl, codewriter
+from pypy.jit.metainterp import pyjitpl, codewriter, resoperation
def make_frame(code):
bytecode = codewriter.JitCode("hello")
@@ -24,3 +24,11 @@
frame = make_frame("\x01")
assert frame.load_bool()
+
+def test_simple_opimpl_exist():
+ rop = resoperation.rop
+ for opnum, opname in resoperation.opname.items():
+ if opnum in (rop.SAME_AS, rop.CALL_PURE, rop.OOSEND_PURE):
+ continue
+ if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST:
+ assert hasattr(pyjitpl.MIFrame, 'opimpl_' + opname.lower()), opname
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_recursive.py Thu Sep 10 16:45:13 2009
@@ -1,10 +1,10 @@
import py
-from pypy.rlib.jit import JitDriver
+from pypy.rlib.jit import JitDriver, we_are_jitted
from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
from pypy.jit.metainterp import simple_optimize
from pypy.jit.metainterp.policy import StopAtXPolicy
from pypy.rpython.annlowlevel import hlstr
-from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit
+from pypy.jit.metainterp.warmspot import CannotInlineCanEnterJit, get_stats
class RecursiveTests:
@@ -213,10 +213,239 @@
res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
assert res == 0
+ def test_exception_in_inlined_function(self):
+ from pypy.rpython.annlowlevel import hlstr
+ def p(code, pc):
+ code = hlstr(code)
+ return "%s %d %s" % (code, pc, code[pc])
+ def c(code, pc):
+ return "l" not in hlstr(code)
+ myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'],
+ get_printable_location=p, can_inline=c)
+
+ class Exc(Exception):
+ pass
+
+ def f(code, n):
+ pc = 0
+ while pc < len(code):
+
+ myjitdriver.jit_merge_point(n=n, code=code, pc=pc)
+ op = code[pc]
+ if op == "-":
+ n -= 1
+ elif op == "c":
+ try:
+ n = f("---i---", n)
+ except Exc:
+ pass
+ elif op == "i":
+ if n % 5 == 1:
+ raise Exc
+ elif op == "l":
+ if n > 0:
+ myjitdriver.can_enter_jit(n=n, code=code, pc=0)
+ pc = 0
+ continue
+ else:
+ assert 0
+ pc += 1
+ return n
+ def main(n):
+ return f("c-l", n)
+ res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
+ assert res == main(100)
+
+ def test_recurse_during_blackholing(self):
+ # this passes, if the blackholing shortcut for calls is turned off
+ # it fails, it is very delicate in terms of parameters,
+ # bridge/loop creation order
+ from pypy.rpython.annlowlevel import hlstr
+ def p(code, pc):
+ code = hlstr(code)
+ return "%s %d %s" % (code, pc, code[pc])
+ def c(code, pc):
+ return "l" not in hlstr(code)
+ myjitdriver = JitDriver(greens=['code', 'pc'], reds=['n'],
+ get_printable_location=p, can_inline=c)
+
+ def f(code, n):
+ pc = 0
+ while pc < len(code):
+
+ myjitdriver.jit_merge_point(n=n, code=code, pc=pc)
+ op = code[pc]
+ if op == "-":
+ n -= 1
+ elif op == "c":
+ if n < 70 and n % 3 == 1:
+ print "F"
+ n = f("--", n)
+ elif op == "l":
+ if n > 0:
+ myjitdriver.can_enter_jit(n=n, code=code, pc=0)
+ pc = 0
+ continue
+ else:
+ assert 0
+ pc += 1
+ return n
+ def main(n):
+ myjitdriver.set_param('threshold', 3)
+ myjitdriver.set_param('trace_eagerness', 5)
+ return f("c-l", n)
+ expected = main(100)
+ res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
+ assert res == expected
+
+ def check_max_trace_length(self, length):
+ for loop in get_stats().loops:
+ assert len(loop.operations) <= length + 5 # because we only check once per metainterp bytecode
+ for op in loop.operations:
+ if op.is_guard():
+ assert len(op.suboperations) <= length + 5
+
+ def test_inline_trace_limit(self):
+ myjitdriver = JitDriver(greens=[], reds=['n'])
+ def recursive(n):
+ if n > 0:
+ return recursive(n - 1) + 1
+ return 0
+ def loop(n):
+ myjitdriver.set_param("threshold", 10)
+ pc = 0
+ while n:
+ myjitdriver.can_enter_jit(n=n)
+ myjitdriver.jit_merge_point(n=n)
+ n = recursive(n)
+ n -= 1
+ return n
+ TRACE_LIMIT = 66
+ res = self.meta_interp(loop, [100], optimizer=simple_optimize, inline=True, trace_limit=TRACE_LIMIT)
+ assert res == 0
+ self.check_max_trace_length(TRACE_LIMIT)
+ self.check_enter_count(15) # maybe
+ self.check_aborted_count(7)
+
+ def test_trace_limit_bridge(self):
+ def recursive(n):
+ if n > 0:
+ return recursive(n - 1) + 1
+ return 0
+ myjitdriver = JitDriver(greens=[], reds=['n'])
+ def loop(n):
+ myjitdriver.set_param("threshold", 4)
+ myjitdriver.set_param("trace_eagerness", 2)
+ while n:
+ myjitdriver.can_enter_jit(n=n)
+ myjitdriver.jit_merge_point(n=n)
+ if n % 5 == 0:
+ n -= 1
+ if n < 50:
+ n = recursive(n)
+ n -= 1
+ TRACE_LIMIT = 20
+ res = self.meta_interp(loop, [100], optimizer=simple_optimize, inline=True, trace_limit=TRACE_LIMIT)
+ self.check_max_trace_length(TRACE_LIMIT)
+ self.check_aborted_count(8)
+ self.check_enter_count_at_most(30)
+
+ def test_set_param_inlining(self):
+ myjitdriver = JitDriver(greens=[], reds=['n', 'recurse'])
+ def loop(n, recurse=False):
+ while n:
+ myjitdriver.jit_merge_point(n=n, recurse=recurse)
+ n -= 1
+ if not recurse:
+ loop(10, True)
+ myjitdriver.can_enter_jit(n=n, recurse=recurse)
+ return n
+ TRACE_LIMIT = 66
+
+ def main(inline):
+ myjitdriver.set_param("threshold", 10)
+ if inline:
+ myjitdriver.set_param('inlining', True)
+ else:
+ myjitdriver.set_param('inlining', False)
+ return loop(100)
+
+ res = self.meta_interp(main, [0], optimizer=simple_optimize, trace_limit=TRACE_LIMIT)
+ self.check_loops(call=1)
+
+ res = self.meta_interp(main, [1], optimizer=simple_optimize, trace_limit=TRACE_LIMIT)
+ self.check_loops(call=0)
+
+ def test_leave_jit_hook(self):
+ from pypy.rpython.annlowlevel import hlstr
+ def p(code, pc):
+ code = hlstr(code)
+ return "%s %d %s" % (code, pc, code[pc])
+ def c(code, pc):
+ return "L" not in hlstr(code)
+
+ def leave(code, pc, frame):
+ frame.hookcalled = True
+
+ class ExpectedHook(Exception):
+ pass
+ class UnexpectedHook(Exception):
+ pass
+
+ myjitdriver = JitDriver(greens=['code', 'pc'], reds=['self'],
+ get_printable_location=p, can_inline=c,
+ leave=leave)
+ class Frame(object):
+ hookcalled = True
+
+ def __init__(self, n):
+ self.n = n
+ self.hookcalled = False
+ def f(self, code):
+ pc = 0
+ while pc < len(code):
+
+ myjitdriver.jit_merge_point(self=self, code=code, pc=pc)
+ op = code[pc]
+ if op == "-":
+ self.n -= 1
+ elif op == "c":
+ frame = Frame(self.n)
+ self.n = frame.f("---i---")
+ if we_are_jitted():
+ if frame.hookcalled:
+ raise UnexpectedHook
+ elif op == "C":
+ frame = Frame(self.n)
+ self.n = frame.f("cL")
+ if we_are_jitted():
+ if not frame.hookcalled:
+ raise ExpectedHook
+ elif op == "i":
+ if self.n % 5 == 1:
+ return self.n
+ elif op == "l":
+ if self.n > 0:
+ myjitdriver.can_enter_jit(self=self, code=code, pc=0)
+ pc = 0
+ continue
+ elif op == "L":
+ if self.n > 50:
+ myjitdriver.can_enter_jit(self=self, code=code, pc=0)
+ pc = 0
+ continue
+ else:
+ assert 0
+ pc += 1
+ return self.n
+ def main(n):
+ frame = Frame(n)
+ return frame.f("C-l")
+ res = self.meta_interp(main, [100], optimizer=simple_optimize, inline=True)
+ assert res == main(100)
class TestLLtype(RecursiveTests, LLJitMixin):
pass
class TestOOtype(RecursiveTests, OOJitMixin):
- def test_simple_recursion_with_exc(self):
- py.test.skip("Fails")
+ pass
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_virtual.py Thu Sep 10 16:45:13 2009
@@ -4,6 +4,7 @@
from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
from pypy.rpython.lltypesystem import lltype, rclass
from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.ootypesystem import ootype
from pypy.jit.metainterp import heaptracker
class VirtualTests:
@@ -272,9 +273,9 @@
return f
res = self.meta_interp(f, [21], repeat=7)
- # hack
- assert (getattr(res, "inst_value", -100) == f(21).value or
- getattr(res, "value", -100) == f(21).value)
+
+ fieldname = self._field_prefix + 'value'
+ assert getattr(res, fieldname, -100) == f(21).value
self.check_tree_loop_count(2) # the loop and the entry path
# we get:
@@ -285,9 +286,6 @@
self.check_enter_count(4)
-##class TestOOtype(VirtualTests, OOJitMixin):
-## _new = staticmethod(ootype.new)
-
# ____________________________________________________________
# Run 1: all the tests instantiate a real RPython class
@@ -296,10 +294,47 @@
class TestLLtype_Instance(VirtualTests, LLJitMixin):
_new_op = 'new_with_vtable'
+ _field_prefix = 'inst_'
+
+ @staticmethod
+ def _new():
+ return MyClass()
+
+ def test_class_with_default_fields(self):
+ class MyClass:
+ value = 2
+
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'res'])
+ def f(n):
+ res = 0
+ node = MyClass()
+ node.value = n # so that the annotator doesn't think that value is constant
+ while n > 0:
+ myjitdriver.can_enter_jit(n=n, res=res)
+ myjitdriver.jit_merge_point(n=n, res=res)
+ node = MyClass()
+ res += node.value
+ n -= 1
+ return res
+ assert f(10) == 20
+ res = self.meta_interp(f, [10])
+ assert res == 20
+ self.check_loop_count(1)
+ self.check_loops(new=0, new_with_vtable=0,
+ getfield_gc=0, setfield_gc=0)
+
+
+
+class TestOOtype_Instance(VirtualTests, OOJitMixin):
+ _new_op = 'new_with_vtable'
+ _field_prefix = 'o'
+
@staticmethod
def _new():
return MyClass()
+ test_class_with_default_fields = TestLLtype_Instance.test_class_with_default_fields.im_func
+
# ____________________________________________________________
# Run 2: all the tests use lltype.malloc to make a NODE
@@ -308,11 +343,25 @@
class TestLLtype_NotObject(VirtualTests, LLJitMixin):
_new_op = 'new'
-
+ _field_prefix = ''
+
@staticmethod
def _new():
return lltype.malloc(NODE)
+
+OONODE = ootype.Instance('NODE', ootype.ROOT, {})
+OONODE._add_fields({'value': ootype.Signed,
+ 'extra': ootype.Signed})
+
+class TestOOtype_NotObject(VirtualTests, OOJitMixin):
+ _new_op = 'new_with_vtable'
+ _field_prefix = ''
+
+ @staticmethod
+ def _new():
+ return ootype.new(OONODE)
+
# ____________________________________________________________
# Run 3: all the tests use lltype.malloc to make a NODE2
# (same as Run 2 but it is part of the OBJECT hierarchy)
@@ -326,6 +375,8 @@
class TestLLtype_Object(VirtualTests, LLJitMixin):
_new_op = 'new_with_vtable'
+ _field_prefix = ''
+
@staticmethod
def _new():
p = lltype.malloc(NODE2)
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/test/test_zrpy_basic.py Thu Sep 10 16:45:13 2009
@@ -90,7 +90,9 @@
pass
def check_enter_count_at_most(self, count):
pass
- def check_jumps(self, maxcount):
+ def check_jumps(self, maxcount):
+ pass
+ def check_aborted_count(self, count):
pass
def interp_operations(self, *args, **kwds):
Modified: pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/metainterp/warmspot.py Thu Sep 10 16:45:13 2009
@@ -26,7 +26,9 @@
# ____________________________________________________________
# Bootstrapping
-def apply_jit(translator, backend_name="auto", debug_level="steps", **kwds):
+def apply_jit(translator, backend_name="auto", debug_level="steps",
+ inline=False,
+ **kwds):
if 'CPUClass' not in kwds:
from pypy.jit.backend.detect_cpu import getcpuclass
kwds['CPUClass'] = getcpuclass(backend_name)
@@ -38,9 +40,9 @@
warmrunnerdesc = WarmRunnerDesc(translator,
translate_support_code=True,
listops=True,
- #inline=True,
profile=profile,
**kwds)
+ warmrunnerdesc.state.set_param_inlining(inline)
warmrunnerdesc.finish()
translator.warmrunnerdesc = warmrunnerdesc # for later debugging
@@ -52,13 +54,15 @@
clear_tcache()
return jittify_and_run(interp, graph, args, backendopt=backendopt, **kwds)
-def jittify_and_run(interp, graph, args, repeat=1, hash_bits=None, backendopt=False,
- **kwds):
+def jittify_and_run(interp, graph, args, repeat=1, hash_bits=None, backendopt=False, trace_limit=sys.maxint,
+ inline=False, **kwds):
translator = interp.typer.annotator.translator
translator.config.translation.gc = "boehm"
warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds)
warmrunnerdesc.state.set_param_threshold(3) # for tests
warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests
+ warmrunnerdesc.state.set_param_trace_limit(trace_limit)
+ warmrunnerdesc.state.set_param_inlining(inline)
warmrunnerdesc.state.create_tables_now() # for tests
if hash_bits:
warmrunnerdesc.state.set_param_hash_bits(hash_bits)
@@ -120,6 +124,9 @@
class JitException(Exception):
_go_through_llinterp_uncaught_ = True # ugh
+class ContinueRunningNormallyBase(JitException):
+ pass
+
class CannotInlineCanEnterJit(JitException):
pass
@@ -127,18 +134,21 @@
class WarmRunnerDesc:
- def __init__(self, translator, policy=None, backendopt=True, **kwds):
+ def __init__(self, translator, policy=None, backendopt=True, CPUClass=None,
+ **kwds):
pyjitpl._warmrunnerdesc = self # this is a global for debugging only!
if policy is None:
policy = JitPolicy()
self.set_translator(translator)
self.find_portal()
- graphs = find_all_graphs(self.portal_graph, policy, self.translator)
+ self.make_leave_jit_graph()
+ graphs = find_all_graphs(self.portal_graph, policy, self.translator,
+ CPUClass.supports_floats)
self.check_access_directly_sanity(graphs)
if backendopt:
self.prejit_optimizations(policy, graphs)
- self.build_meta_interp(**kwds)
+ self.build_meta_interp(CPUClass, **kwds)
self.make_args_specification()
self.rewrite_jit_merge_point()
self.make_driverhook_graph()
@@ -206,7 +216,7 @@
remove_asserts=True,
really_remove_asserts=True)
- def build_meta_interp(self, CPUClass=None, translate_support_code=False,
+ def build_meta_interp(self, CPUClass, translate_support_code=False,
view="auto", optimizer=None, profile=None, **kwds):
assert CPUClass is not None
opt = history.Options(**kwds)
@@ -224,7 +234,8 @@
self.stats, opt,
optimizer=optimizer,
profile=profile,
- warmrunnerdesc=self)
+ warmrunnerdesc=self,
+ leave_graph=self.leave_graph)
def make_enter_function(self):
WarmEnterState = make_state_class(self)
@@ -259,6 +270,21 @@
self.maybe_enter_jit_fn = maybe_enter_jit
+ def make_leave_jit_graph(self):
+ self.leave_graph = None
+ if self.jitdriver.leave:
+ graph, block, index = self.jit_merge_point_pos
+ op = block.operations[index]
+ args = op.args[2:]
+ s_binding = self.translator.annotator.binding
+ args_s = [s_binding(v) for v in args]
+ from pypy.annotation import model as annmodel
+ annhelper = MixLevelHelperAnnotator(self.translator.rtyper)
+ s_result = annmodel.s_None
+ self.leave_graph = annhelper.getgraph(self.jitdriver.leave,
+ args_s, s_result)
+ annhelper.finish()
+
def make_driverhook_graph(self):
self.can_inline_ptr = self._make_hook_graph(
self.jitdriver.can_inline, bool)
@@ -393,6 +419,13 @@
def __str__(self):
return 'DoneWithThisFrameRef(%s)' % (self.result,)
+ class DoneWithThisFrameFloat(JitException):
+ def __init__(self, cpu, result):
+ assert lltype.typeOf(result) is lltype.Float
+ self.result = result
+ def __str__(self):
+ return 'DoneWithThisFrameFloat(%s)' % (self.result,)
+
class ExitFrameWithExceptionRef(JitException):
def __init__(self, cpu, value):
assert lltype.typeOf(value) == cpu.ts.BASETYPE
@@ -400,7 +433,7 @@
def __str__(self):
return 'ExitFrameWithExceptionRef(%s)' % (self.value,)
- class ContinueRunningNormally(JitException):
+ class ContinueRunningNormally(ContinueRunningNormallyBase):
def __init__(self, argboxes):
# accepts boxes as argument, but unpacks them immediately
# before we raise the exception -- the boxes' values will
@@ -416,11 +449,13 @@
self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
self.DoneWithThisFrameInt = DoneWithThisFrameInt
self.DoneWithThisFrameRef = DoneWithThisFrameRef
+ self.DoneWithThisFrameFloat = DoneWithThisFrameFloat
self.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
self.ContinueRunningNormally = ContinueRunningNormally
self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
self.metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
+ self.metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrameFloat
self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
rtyper = self.translator.rtyper
@@ -447,6 +482,9 @@
except DoneWithThisFrameRef, e:
assert result_kind == 'ref'
return ts.cast_from_ref(RESULT, e.result)
+ except DoneWithThisFrameFloat, e:
+ assert result_kind == 'float'
+ return e.result
except ExitFrameWithExceptionRef, e:
value = ts.cast_to_baseclass(e.value)
if not we_are_translated():
@@ -510,7 +548,7 @@
op.args[:3] = [closures[funcname]]
-def find_all_graphs(portal, policy, translator):
+def find_all_graphs(portal, policy, translator, supports_floats):
from pypy.translator.simplify import get_graph
all_graphs = [portal]
seen = set([portal])
@@ -520,13 +558,13 @@
for _, op in top_graph.iterblockops():
if op.opname not in ("direct_call", "indirect_call", "oosend"):
continue
- kind = policy.guess_call_kind(op)
+ kind = policy.guess_call_kind(op, supports_floats)
if kind != "regular":
continue
- for graph in policy.graphs_from(op):
+ for graph in policy.graphs_from(op, supports_floats):
if graph in seen:
continue
- if policy.look_inside_graph(graph):
+ if policy.look_inside_graph(graph, supports_floats):
todo.append(graph)
all_graphs.append(graph)
seen.add(graph)
@@ -552,6 +590,8 @@
return box.getref(TYPE)
if isinstance(TYPE, ootype.OOType):
return box.getref(TYPE)
+ if TYPE == lltype.Float:
+ return box.getfloat()
else:
return lltype.cast_primitive(TYPE, box.getint())
unwrap._annspecialcase_ = 'specialize:arg(0)'
@@ -574,6 +614,11 @@
return history.ConstObj(value)
else:
return history.BoxObj(value)
+ elif isinstance(value, float):
+ if in_const_box:
+ return history.ConstFloat(value)
+ else:
+ return history.BoxFloat(value)
else:
value = intmask(value)
if in_const_box:
@@ -683,6 +728,9 @@
elif typecode == 'int':
intvalue = lltype.cast_primitive(lltype.Signed, value)
cpu.set_future_value_int(j, intvalue)
+ elif typecode == 'float':
+ assert isinstance(value, float)
+ cpu.set_future_value_float(j, value)
else:
assert False
set_future_value._annspecialcase_ = 'specialize:ll_and_arg(2)'
@@ -704,6 +752,12 @@
def set_param_trace_eagerness(self, value):
self.trace_eagerness = value
+ def set_param_trace_limit(self, value):
+ self.trace_limit = value
+
+ def set_param_inlining(self, value):
+ self.inlining = value
+
def set_param_hash_bits(self, value):
if value < 1:
value = 1
@@ -748,7 +802,13 @@
self.create_tables_now()
return
metainterp = MetaInterp(metainterp_sd)
- loop = metainterp.compile_and_run_once(*args)
+ try:
+ loop = metainterp.compile_and_run_once(*args)
+ except warmrunnerdesc.ContinueRunningNormally:
+ # the trace got too long, reset the counter
+ self.mccounters[argshash] = 0
+ raise
+
else:
# machine code was already compiled for these greenargs
# (or we have a hash collision)
@@ -837,6 +897,9 @@
key.counter += 1
return key.counter >= self.trace_eagerness
+ def reset_counter_from_failure(self, key):
+ key.counter = 0
+
def attach_unoptimized_bridge_from_interp(self, greenkey, bridge):
greenargs = self.unwrap_greenkey(greenkey)
newcell = MachineCodeEntryPoint(bridge, *greenargs)
Modified: pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py (original)
+++ pypy/branch/spine-of-frames/pypy/jit/tl/pypyjit_child.py Thu Sep 10 16:45:13 2009
@@ -38,6 +38,7 @@
print 'warmspot.jittify_and_run() started...'
from pypy.jit.backend.llgraph.runner import LLtypeCPU
+ LLtypeCPU.supports_floats = False # for now
policy = PyPyJitPolicy(interp.typer.annotator.translator)
option.view = True
warmspot.jittify_and_run(interp, graph, [], policy=policy,
Modified: pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/__builtin__/__init__.py Thu Sep 10 16:45:13 2009
@@ -27,23 +27,11 @@
'raw_input' : 'app_io.raw_input',
'input' : 'app_io.input',
- 'sum' : 'app_functional.sum',
'apply' : 'app_functional.apply',
- 'map' : 'app_functional.map',
- 'filter' : 'app_functional.filter',
- 'zip' : 'app_functional.zip',
- 'reduce' : 'app_functional.reduce',
#'range' : 'app_functional.range',
# redirected to functional.py, applevel version
# is still needed and should stay where it is.
- 'min' : 'app_functional.min',
- 'max' : 'app_functional.max',
- 'enumerate' : 'app_functional.enumerate',
'sorted' : 'app_functional.sorted',
- 'reversed' : 'app_functional.reversed',
- '_install_pickle_support_for_reversed_iterator':
- 'app_functional._install_pickle_support_for_reversed_iterator',
-
'globals' : 'app_inspect.globals',
'locals' : 'app_inspect.locals',
'vars' : 'app_inspect.vars',
@@ -106,8 +94,17 @@
'range' : 'functional.range_int',
'xrange' : 'functional.W_XRange',
+ 'enumerate' : 'functional.W_Enumerate',
'all' : 'functional.all',
'any' : 'functional.any',
+ 'min' : 'functional.min',
+ 'max' : 'functional.max',
+ 'sum' : 'functional.sum',
+ 'map' : 'functional.map',
+ 'zip' : 'functional.zip',
+ 'reduce' : 'functional.reduce',
+ 'reversed' : 'functional.reversed',
+ 'filter' : 'functional.filter',
'super' : 'descriptor.W_Super',
'staticmethod' : 'descriptor.StaticMethod',
'classmethod' : 'descriptor.ClassMethod',
Modified: pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/__builtin__/app_functional.py Thu Sep 10 16:45:13 2009
@@ -3,151 +3,12 @@
functional programming.
"""
-
-def sum(sequence, total=0):
- """sum(sequence, start=0) -> value
-
-Returns the sum of a sequence of numbers (NOT strings) plus the value
-of parameter 'start'. When the sequence is empty, returns start."""
- # must forbid "summing" strings, per specs of built-in 'sum'
- if isinstance(total, str): raise TypeError
- for item in sequence:
- total = total + item
- return total
-
# ____________________________________________________________
def apply(function, args=(), kwds={}):
"""call a function (or other callable object) and return its result"""
return function(*args, **kwds)
-def map(function, *collections):
- """does 3 separate things, hence this enormous docstring.
- 1. if function is None, return a list of tuples, each with one
- item from each collection. If the collections have different
- lengths, shorter ones are padded with None.
-
- 2. if function is not None, and there is only one collection,
- apply function to every item in the collection and return a
- list of the results.
-
- 3. if function is not None, and there are several collections,
- repeatedly call the function with one argument from each
- collection. If the collections have different lengths,
- shorter ones are padded with None
- """
-
- if len(collections) == 0:
- raise TypeError, "map() requires at least one sequence"
-
- if len(collections) == 1:
- #it's the most common case, so make it faster
- if function is None:
- return list(collections[0])
- return [function(x) for x in collections[0]]
-
- iterators = [ iter(collection) for collection in collections ]
- res = []
- while 1:
- cont = False #is any collection not empty?
- args = []
- for iterator in iterators:
- try:
- elem = iterator.next()
- cont = True
- except StopIteration:
- elem = None
- args.append(elem)
- if cont:
- if function is None:
- res.append(tuple(args))
- else:
- res.append(function(*args))
- else:
- return res
-
-def filterstring(function, collection, str_type):
- if function is None and type(collection) is str_type:
- return collection
- res = []
- for i in xrange(len(collection)):
- c = collection[i]
- if function is None or function(c):
- if not isinstance(c, str_type):
- raise TypeError("can't filter %s to %s: __getitem__ returned different type", str_type.__name__, str_type.__name__)
- res.append(c)
- return str_type().join(res)
-
-def filtertuple(function, collection):
- if function is None:
- function = bool
- res = []
- for i in xrange(len(collection)):
- c = collection[i]
- if function(c):
- res.append(c)
- return tuple(res)
-
-def filter(function, collection):
- """construct a list of those elements of collection for which function
- is True. If function is None, then return the items in the sequence
- which are True."""
- if isinstance(collection, str):
- return filterstring(function, collection, str)
- elif isinstance(collection, unicode):
- return filterstring(function, collection, unicode)
- elif isinstance(collection, tuple):
- return filtertuple(function, collection)
-
- if function is None:
- return [item for item in collection if item]
- else:
- return [item for item in collection if function(item)]
-
-def zip(*collections):
- """return a list of tuples, where the nth tuple contains every
- nth item of each collection. If the collections have different
- lengths, zip returns a list as long as the shortest collection,
- ignoring the trailing items in the other collections."""
-
- if len(collections) == 0:
- import sys
- if sys.version_info < (2,4):
- raise TypeError("zip() requires at least one sequence")
- return []
- res = []
- iterators = [ iter(collection) for collection in collections ]
- while 1:
- try:
- elems = []
- for iterator in iterators:
- elems.append(iterator.next())
- res.append(tuple(elems))
- except StopIteration:
- return res
-
-def reduce(function, seq, *initialt):
- """ Apply function of two arguments cumulatively to the items of
- sequence, from left to right, so as to reduce the sequence to a
- single value. Optionally begin with an initial value."""
-
- seqiter = iter(seq)
- if initialt:
- initial, = initialt
- else:
- try:
- initial = seqiter.next()
- except StopIteration:
- raise TypeError, "reduce() of empty sequence with no initial value"
- while 1:
- try:
- arg = seqiter.next()
- except StopIteration:
- break
- initial = function(initial, arg)
-
- return initial
-
# ____________________________________________________________
"""
@@ -206,135 +67,10 @@
# ____________________________________________________________
-
-def _identity(arg):
- return arg
-
-
-def min(*arr, **kwargs):
- """return the smallest number in a list,
- or its smallest argument if more than one is given."""
- from operator import gt
-
- return min_max(gt, "min", *arr, **kwargs)
-
-def min_max(comp, funcname, *arr, **kwargs):
- key = kwargs.pop("key", _identity)
- if len(kwargs):
- raise TypeError, '%s() got an unexpected keyword argument' % funcname
-
- if not arr:
- raise TypeError, '%s() takes at least one argument' % funcname
-
- if len(arr) == 1:
- arr = arr[0]
-
- iterator = iter(arr)
- try:
- min_max_val = iterator.next()
- except StopIteration:
- raise ValueError, '%s() arg is an empty sequence' % funcname
-
- keyed_min_max_val = key(min_max_val)
-
- for i in iterator:
- keyed = key(i)
- if comp(keyed_min_max_val, keyed):
- min_max_val = i
- keyed_min_max_val = keyed
- return min_max_val
-
-def max(*arr, **kwargs):
- """return the largest number in a list,
- or its largest argument if more than one is given."""
- from operator import lt
-
- return min_max(lt, "max", *arr, **kwargs)
-
-class enumerate(object):
- """enumerate(iterable) -> iterator for (index, value) of iterable.
-
-Return an enumerate object. iterable must be an other object that supports
-iteration. The enumerate object yields pairs containing a count (from
-zero) and a value yielded by the iterable argument. enumerate is useful
-for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."""
-
- def __init__(self, collection):
- self._iter = iter(collection)
- self._index = 0
-
- def next(self):
- try:
- next = self._iter.next
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s object has no next() method' %
- (type(self._iter).__name__,))
- result = self._index, next()
- self._index += 1
- return result
-
- def __iter__(self):
- return self
-
-
-# ____________________________________________________________
-
def sorted(lst, cmp=None, key=None, reverse=None):
"sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"
sorted_lst = list(lst)
sorted_lst.sort(cmp, key, reverse)
return sorted_lst
-def reversed(sequence):
- "reversed(sequence) -> reverse iterator over values of the sequence"
- if hasattr(sequence, '__reversed__'):
- return sequence.__reversed__()
- if not hasattr(sequence, '__getitem__'):
- raise TypeError("argument to reversed() must be a sequence")
- return reversed_iterator(sequence)
-
-
-class reversed_iterator(object):
-
- def __init__(self, seq):
- self.seq = seq
- self.remaining = len(seq)
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.remaining > len(self.seq):
- self.remaining = 0
- i = self.remaining
- if i > 0:
- i -= 1
- item = self.seq[i]
- self.remaining = i
- return item
- raise StopIteration
-
-# XXX __length_hint__()
-## def __len__(self):
-## if self.remaining > len(self.seq):
-## self.remaining = 0
-## return self.remaining
-
- def __reduce__(self):
- tup = (self.seq, self.remaining)
- return (make_reversed_iterator, tup)
-
-def make_reversed_iterator(seq, remaining):
- ri = reversed_iterator.__new__(reversed_iterator)
- ri.seq = seq
- #or "ri = reversed_iterator(seq)" but that executes len(seq)
- ri.remaining = remaining
- return ri
-
-def _install_pickle_support_for_reversed_iterator():
- import _pickle_support
- make_reversed_iterator.__module__ = '_pickle_support'
- _pickle_support.make_reversed_iterator = make_reversed_iterator
-
Modified: pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/__builtin__/functional.py Thu Sep 10 16:45:13 2009
@@ -8,7 +8,9 @@
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.argument import Arguments
from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.rlib.objectmodel import specialize
from pypy.module.__builtin__.app_functional import range as app_range
from inspect import getsource, getfile
@@ -100,7 +102,239 @@
return W_ListMultiObject(space, impl)
+ at specialize.arg(2)
+def min_max(space, arguments, implementation_of):
+ if implementation_of == "max":
+ compare = space.gt
+ else:
+ compare = space.lt
+ args, kwargs = arguments.unpack()
+ if len(args) > 1:
+ w_sequence = space.newtuple(args)
+ elif len(args):
+ w_sequence = args[0]
+ else:
+ msg = "%s() expects at least one argument" % (implementation_of,)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ try:
+ w_key = kwargs["key"]
+ except KeyError:
+ w_key = None
+ else:
+ del kwargs["key"]
+ if kwargs:
+ msg = "%s() got unexpected keyword argument" % (implementation_of,)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ w_iter = space.iter(w_sequence)
+ w_max_item = None
+ w_max_val = None
+ while True:
+ try:
+ w_item = space.next(w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ if w_key is not None:
+ w_compare_with = space.call_function(w_key, w_item)
+ else:
+ w_compare_with = w_item
+ if w_max_item is None or \
+ space.is_true(compare(w_compare_with, w_max_val)):
+ w_max_item = w_item
+ w_max_val = w_compare_with
+ if w_max_item is None:
+ msg = "arg is an empty sequence"
+ raise OperationError(space.w_ValueError, space.wrap(msg))
+ return w_max_item
+
+def max(space, __args__):
+ """Return the largest item in a sequence.
+
+ If more than one argument is passed, return the maximum of them.
+ """
+ return min_max(space, __args__, "max")
+max.unwrap_spec = [ObjSpace, Arguments]
+
+def min(space, __args__):
+ """Return the smallest item in a sequence.
+
+ If more than one argument is passed, return the minimum of them.
+ """
+ return min_max(space, __args__, "min")
+min.unwrap_spec = [ObjSpace, Arguments]
+
+def map(space, w_func, collections_w):
+ """does 3 separate things, hence this enormous docstring.
+ 1. if function is None, return a list of tuples, each with one
+ item from each collection. If the collections have different
+ lengths, shorter ones are padded with None.
+
+ 2. if function is not None, and there is only one collection,
+ apply function to every item in the collection and return a
+ list of the results.
+
+ 3. if function is not None, and there are several collections,
+ repeatedly call the function with one argument from each
+ collection. If the collections have different lengths,
+ shorter ones are padded with None
+ """
+ if not collections_w:
+ msg = "map() requires at least two arguments"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ num_collections = len(collections_w)
+ none_func = space.is_w(w_func, space.w_None)
+ if none_func and num_collections == 1:
+ return space.call_function(space.w_list, collections_w[0])
+ result_w = []
+ iterators_w = [space.iter(w_seq) for w_seq in collections_w]
+ num_iterators = len(iterators_w)
+ while True:
+ cont = False
+ args_w = [space.w_None] * num_iterators
+ for i in range(len(iterators_w)):
+ try:
+ args_w[i] = space.next(iterators_w[i])
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ else:
+ cont = True
+ w_args = space.newtuple(args_w)
+ if cont:
+ if none_func:
+ result_w.append(w_args)
+ else:
+ w_res = space.call(w_func, w_args)
+ result_w.append(w_res)
+ else:
+ return space.newlist(result_w)
+map.unwrap_spec = [ObjSpace, W_Root, "args_w"]
+def sum(space, w_sequence, w_start=None):
+ if space.is_w(w_start, space.w_None):
+ w_start = space.wrap(0)
+ elif space.is_true(space.isinstance(w_start, space.w_basestring)):
+ msg = "sum() can't sum strings"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ w_iter = space.iter(w_sequence)
+ w_last = w_start
+ while True:
+ try:
+ w_next = space.next(w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ w_last = space.add(w_last, w_next)
+ return w_last
+sum.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+def zip(space, sequences_w):
+ """Return a list of tuples, where the nth tuple contains every nth item of
+ each collection.
+
+ If the collections have different lengths, zip returns a list as long as the
+ shortest collection, ignoring the trailing items in the other collections.
+ """
+ if not sequences_w:
+ return space.newlist([])
+ result_w = []
+ iterators_w = [space.iter(w_seq) for w_seq in sequences_w]
+ while True:
+ try:
+ items_w = [space.next(w_it) for w_it in iterators_w]
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ return space.newlist(result_w)
+ result_w.append(space.newtuple(items_w))
+zip.unwrap_spec = [ObjSpace, "args_w"]
+
+def reduce(space, w_func, w_sequence, w_initial=NoneNotWrapped):
+ """ Apply function of two arguments cumulatively to the items of sequence,
+ from left to right, so as to reduce the sequence to a single value.
+ Optionally begin with an initial value.
+ """
+ w_iter = space.iter(w_sequence)
+ if w_initial is None:
+ try:
+ w_initial = space.next(w_iter)
+ except OperationError, e:
+ if e.match(space, space.w_StopIteration):
+ msg = "reduce() of empty sequence with no initial value"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ raise
+ w_result = w_initial
+ while True:
+ try:
+ w_next = space.next(w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ w_result = space.call_function(w_func, w_result, w_next)
+ return w_result
+reduce.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root]
+
+def filter(space, w_func, w_seq):
+ """construct a list of those elements of collection for which function
+ is True. If function is None, then return the items in the sequence
+ which are True.
+ """
+ if space.is_true(space.isinstance(w_seq, space.w_str)):
+ return _filter_string(space, w_func, w_seq, space.w_str)
+ if space.is_true(space.isinstance(w_seq, space.w_unicode)):
+ return _filter_string(space, w_func, w_seq, space.w_unicode)
+ if space.is_true(space.isinstance(w_seq, space.w_tuple)):
+ return _filter_tuple(space, w_func, w_seq)
+ w_iter = space.iter(w_seq)
+ result_w = []
+ none_func = space.is_w(w_func, space.w_None)
+ while True:
+ try:
+ w_next = space.next(w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ if none_func:
+ w_keep = w_next
+ else:
+ w_keep = space.call_function(w_func, w_next)
+ if space.is_true(w_keep):
+ result_w.append(w_next)
+ return space.newlist(result_w)
+
+def _filter_tuple(space, w_func, w_tuple):
+ none_func = space.is_w(w_func, space.w_None)
+ length = space.int_w(space.len(w_tuple))
+ result_w = []
+ for i in range(length):
+ w_item = space.getitem(w_tuple, space.wrap(i))
+ if none_func:
+ w_keep = w_item
+ else:
+ w_keep = space.call_function(w_func, w_item)
+ if space.is_true(w_keep):
+ result_w.append(w_item)
+ return space.newtuple(result_w)
+
+def _filter_string(space, w_func, w_string, w_str_type):
+ none_func = space.is_w(w_func, space.w_None)
+ if none_func and space.is_w(space.type(w_string), w_str_type):
+ return w_string
+ length = space.int_w(space.len(w_string))
+ result_w = []
+ for i in range(length):
+ w_item = space.getitem(w_string, space.wrap(i))
+ if none_func or space.is_true(space.call_function(w_func, w_item)):
+ if not space.is_true(space.isinstance(w_item, w_str_type)):
+ msg = "__getitem__ returned a non-string type"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ result_w.append(w_item)
+ w_empty = space.call_function(w_str_type)
+ return space.call_method(w_empty, "join", space.newlist(result_w))
def all(space, w_S):
"""all(iterable) -> bool
@@ -138,6 +372,110 @@
any.unwrap_spec = [ObjSpace, W_Root]
+class W_Enumerate(Wrappable):
+
+ def __init__(self, w_iter, w_start):
+ self.w_iter = w_iter
+ self.w_index = w_start
+
+ def descr___new__(space, w_subtype, w_iterable):
+ self = space.allocate_instance(W_Enumerate, w_subtype)
+ self.__init__(space.iter(w_iterable), space.wrap(0))
+ return space.wrap(self)
+
+ def descr___iter__(self, space):
+ return space.wrap(self)
+ descr___iter__.unwrap_spec = ["self", ObjSpace]
+
+ def descr_next(self, space):
+ w_item = space.next(self.w_iter)
+ w_index = self.w_index
+ self.w_index = space.add(w_index, space.wrap(1))
+ return space.newtuple([w_index, w_item])
+ descr_next.unwrap_spec = ["self", ObjSpace]
+
+ def descr___reduce__(self, space):
+ from pypy.interpreter.mixedmodule import MixedModule
+ w_mod = space.getbuiltinmodule('_pickle_support')
+ mod = space.interp_w(MixedModule, w_mod)
+ w_new_inst = mod.get('enumerate_new')
+ w_info = space.newtuple([self.w_iter, self.w_index])
+ return space.newtuple([w_new_inst, w_info])
+ descr___reduce__.unwrap_spec = ["self", ObjSpace]
+
+# exported through _pickle_support
+def _make_enumerate(space, w_iter, w_index):
+ return space.wrap(W_Enumerate(w_iter, w_index))
+
+W_Enumerate.typedef = TypeDef("enumerate",
+ __new__=interp2app(W_Enumerate.descr___new__.im_func),
+ __iter__=interp2app(W_Enumerate.descr___iter__),
+ next=interp2app(W_Enumerate.descr_next),
+ __reduce__=interp2app(W_Enumerate.descr___reduce__),
+)
+
+
+def reversed(space, w_sequence):
+ """Return a iterator that yields items of sequence in reverse."""
+ w_reversed_descr = space.lookup(w_sequence, "__reversed__")
+ if w_reversed_descr is None:
+ return space.wrap(W_ReversedIterator(space, w_sequence))
+ return space.get_and_call_function(w_reversed_descr, w_sequence)
+reversed.unwrap_spec = [ObjSpace, W_Root]
+
+class W_ReversedIterator(Wrappable):
+
+ def __init__(self, space, w_sequence):
+ self.remaining = space.int_w(space.len(w_sequence)) - 1
+ self.w_sequence = w_sequence
+
+ def descr___iter__(self, space):
+ return space.wrap(self)
+ descr___iter__.unwrap_spec = ["self", ObjSpace]
+
+ def descr_next(self, space):
+ if self.remaining >= 0:
+ w_index = space.wrap(self.remaining)
+ try:
+ w_item = space.getitem(self.w_sequence, w_index)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ else:
+ self.remaining -= 1
+ return w_item
+
+ # Done
+ self.remaining = -1
+ raise OperationError(space.w_StopIteration, space.w_None)
+ descr_next.unwrap_spec = ["self", ObjSpace]
+
+ def descr___reduce__(self, space):
+ from pypy.interpreter.mixedmodule import MixedModule
+ w_mod = space.getbuiltinmodule('_pickle_support')
+ mod = space.interp_w(MixedModule, w_mod)
+ w_new_inst = mod.get('reversed_new')
+ info_w = [self.w_sequence, space.wrap(self.remaining)]
+ w_info = space.newtuple(info_w)
+ return space.newtuple([w_new_inst, w_info])
+ descr___reduce__.unwrap_spec = ["self", ObjSpace]
+
+W_ReversedIterator.typedef = TypeDef("reversed",
+ __iter__=interp2app(W_ReversedIterator.descr___iter__),
+ next=interp2app(W_ReversedIterator.descr_next),
+ __reduce__=interp2app(W_ReversedIterator.descr___reduce__),
+)
+
+# exported through _pickle_support
+def _make_reversed(space, w_seq, w_remaining):
+ w_type = space.gettypeobject(W_ReversedIterator.typedef)
+ iterator = space.allocate_instance(W_ReversedIterator, w_type)
+ iterator.w_sequence = w_seq
+ iterator.remaining = space.int_w(w_remaining)
+ return space.wrap(iterator)
+
+
+
class W_XRange(Wrappable):
def __init__(self, space, start, len, step):
self.space = space
Modified: pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/_pickle_support/__init__.py Thu Sep 10 16:45:13 2009
@@ -22,4 +22,6 @@
'xrangeiter_new': 'maker.xrangeiter_new',
'builtin_code': 'maker.builtin_code',
'builtin_function' : 'maker.builtin_function',
+ 'enumerate_new': 'maker.enumerate_new',
+ 'reversed_new': 'maker.reversed_new'
}
Modified: pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/_pickle_support/maker.py Thu Sep 10 16:45:13 2009
@@ -100,6 +100,17 @@
builtin_function.unwrap_spec = [ObjSpace, str]
+def enumerate_new(space, w_iter, w_index):
+ from pypy.module.__builtin__.functional import _make_enumerate
+ return _make_enumerate(space, w_iter, w_index)
+enumerate_new.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+def reversed_new(space, w_seq, w_remaining):
+ from pypy.module.__builtin__.functional import _make_reversed
+ return _make_reversed(space, w_seq, w_remaining)
+reversed_new.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+
# ___________________________________________________________________
# Helper functions for internal use
Modified: pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/posix/interp_posix.py Thu Sep 10 16:45:13 2009
@@ -843,7 +843,7 @@
from pypy.rlib import rwin32
eci = ExternalCompilationInfo(
- includes = ['windows.h'],
+ includes = ['windows.h', 'wincrypt.h'],
libraries = ['advapi32'],
)
Modified: pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/posix/test/test_posix2.py Thu Sep 10 16:45:13 2009
@@ -129,6 +129,19 @@
assert st.st_mtime == 42.1
assert st.st_ctime == 43
+ def test_stat_exception(self):
+ import sys, errno
+ try:
+ self.posix.stat("nonexistentdir/nonexistentfile")
+ except OSError, e:
+ assert e.errno == errno.ENOENT
+ # On Windows, when the parent directory does not exist,
+ # the winerror is 3 (cannot find the path specified)
+ # instead of 2 (cannot find the file specified)
+ if sys.platform == 'win32':
+ assert isinstance(e, WindowsError)
+ assert e.winerror == 3
+
def test_pickle(self):
import pickle, os
st = self.posix.stat(os.curdir)
Modified: pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py (original)
+++ pypy/branch/spine-of-frames/pypy/module/pypyjit/policy.py Thu Sep 10 16:45:13 2009
@@ -1,6 +1,9 @@
-from pypy.jit.metainterp.policy import ManualJitPolicy
+from pypy.jit.metainterp.policy import JitPolicy
-class PyPyJitPolicy(ManualJitPolicy):
+class PyPyJitPolicy(JitPolicy):
+
+ def __init__(self, translator=None):
+ pass # xxx
def look_inside_function(self, func):
mod = func.__module__ or '?'
@@ -53,6 +56,9 @@
# string builder interface
if mod == 'pypy.rpython.lltypesystem.rbuilder':
return False
+ # rweakvaluedict implementation
+ if mod == 'pypy.rlib.rweakrefimpl':
+ return False
#if (mod == 'pypy.rpython.rlist' or
# mod == 'pypy.rpython.lltypesystem.rdict' or
# mod == 'pypy.rpython.lltypesystem.rlist'):
Modified: pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py (original)
+++ pypy/branch/spine-of-frames/pypy/objspace/std/dictmultiobject.py Thu Sep 10 16:45:13 2009
@@ -5,6 +5,7 @@
from pypy.rlib.objectmodel import r_dict, we_are_translated
from pypy.rlib.jit import purefunction
+from pypy.rlib.rweakref import RWeakValueDictionary
def _is_str(space, w_key):
return space.is_w(space.type(w_key), space.w_str)
@@ -687,7 +688,6 @@
class SharedStructure(object):
def __init__(self, keys=None, length=0,
- other_structs=None,
last_key=None,
back_struct=None):
if keys is None:
@@ -695,20 +695,18 @@
self.keys = keys
self.length = length
self.back_struct = back_struct
- if other_structs is None:
- other_structs = {}
+ other_structs = RWeakValueDictionary(SharedStructure)
self.other_structs = other_structs
self.last_key = last_key
if last_key is not None:
assert back_struct is not None
- self.propagating = False
def new_structure(self, added_key):
keys = self.keys.copy()
keys[added_key] = len(self.keys)
new_structure = SharedStructure(keys, self.length + 1,
- {}, added_key, self)
- self.other_structs[added_key] = new_structure
+ added_key, self)
+ self.other_structs.set(added_key, new_structure)
return new_structure
def lookup_position(self, key):
@@ -725,7 +723,6 @@
class State(object):
def __init__(self, space):
self.empty_structure = SharedStructure()
- self.empty_structure.propagating = True
class SharedDictImplementation(DictImplementation):
@@ -762,13 +759,9 @@
if i != -1:
self.entries[i] = w_value
return self
- if not self.structure.propagating:
- return self._as_rdict(as_strdict=True).setitem_str(w_key, w_value)
- new_structure = self.structure.other_structs.get(key, None)
+ new_structure = self.structure.other_structs.get(key)
if new_structure is None:
new_structure = self.structure.new_structure(key)
- else:
- new_structure.propagating = True
self.entries.append(w_value)
assert self.structure.length + 1 == new_structure.length
self.structure = new_structure
Modified: pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py (original)
+++ pypy/branch/spine-of-frames/pypy/objspace/std/test/test_typeobject.py Thu Sep 10 16:45:13 2009
@@ -948,3 +948,125 @@
del list.a
raises(AttributeError, "l.a")
+class AppTestGetattributeShortcut:
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.getattributeshortcut": True})
+
+ def test_reset_logic(self):
+ class X(object):
+ pass
+
+ class Y(X):
+ pass
+
+ y = Y()
+ y.x = 3
+ assert y.x == 3
+
+ def ga(self, name):
+ return 'GA'
+
+ X.__getattribute__ = ga
+
+ assert y.x == 'GA'
+
+ class M(type):
+ pass
+
+ class X(object):
+ __metaclass__ = M
+
+ class Y(X):
+ pass
+
+ y = Y()
+ y.x = 3
+ assert y.x == 3
+
+ def ga(self, name):
+ return 'GA'
+
+ X.__getattribute__ = ga
+
+ assert y.x == 'GA'
+
+class TestNewShortcut:
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.newshortcut": True})
+
+ def test_mechanics(self):
+ space = self.space
+ w_tup = space.appexec([], """():
+ class A(object):
+ pass
+ class B(object):
+ __new__ = staticmethod(lambda t: 1)
+ class M(type):
+ pass
+ return A, B, M
+""")
+ w_A, w_B, w_M = space.unpackiterable(w_tup)
+
+ assert w_A.w_bltin_new is None
+ assert w_B.w_bltin_new is None
+ assert w_M.w_bltin_new is None
+
+ _, w_object_newdescr = space.lookup_in_type_where(space.w_object,
+ '__new__')
+ w_object___new__ = space.get(w_object_newdescr, None,
+ w_type=space.w_object)
+
+ w_a = space.call_function(w_A)
+ assert w_A.w_bltin_new is w_object___new__
+
+ # will shortcut
+ w_a = space.call_function(w_A)
+
+ w_b = space.call_function(w_B)
+ assert w_B.w_bltin_new is None
+
+ w_m = space.call_function(w_M, space.wrap('C'), space.newlist([]),
+ space.newdict())
+ assert w_M.w_bltin_new is None
+
+
+class AppTestNewShortcut:
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.newshortcut": True})
+
+ def test_reset_logic(self):
+ class X(object):
+ pass
+
+ class Y(X):
+ pass
+
+ y = Y()
+
+ assert isinstance(y, Y)
+
+
+ X.__new__ = staticmethod(lambda t: 1)
+
+ y = Y()
+
+ assert y == 1
+
+ def test_dont_explode_on_non_types(self):
+ class A:
+ __new__ = staticmethod(lambda t: 1)
+
+ class B(A, object):
+ pass
+
+ b = B()
+
+ assert b == 1
+
+
Modified: pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py (original)
+++ pypy/branch/spine-of-frames/pypy/objspace/std/typeobject.py Thu Sep 10 16:45:13 2009
@@ -50,11 +50,19 @@
lazyloaders = {} # can be overridden by specific instances
version_tag = None
- _immutable_fields_ = ["__flags__"]
+ _immutable_fields_ = ["__flags__",
+ 'needsdel',
+ 'weakrefable',
+ 'hasdict']
- uses_object_getattribute = False
- # ^^^ for config.objspace.std.getattributeshortcut
+ # for config.objspace.std.getattributeshortcut
# (False is a conservative default, fixed during real usage)
+ uses_object_getattribute = False
+
+ # used to cache the type __new__ function if it comes from a builtin type
+ # != 'type', in that case call__Type will also assumes the result
+ # of the __new__ is an instance of the type
+ w_bltin_new = None
def __init__(w_self, space, name, bases_w, dict_w,
overridetypedef=None):
@@ -86,24 +94,26 @@
def mutated(w_self):
space = w_self.space
+ if (not space.config.objspace.std.withtypeversion and
+ not space.config.objspace.std.getattributeshortcut and
+ not space.config.objspace.std.newshortcut):
+ return
+
if space.config.objspace.std.getattributeshortcut:
w_self.uses_object_getattribute = False
# ^^^ conservative default, fixed during real usage
- if not space.config.objspace.std.withtypeversion:
- return
- # Invariant: version_tag is None if and only if
- # 'w_self.instancetypedef.hasdict' is True, which is the case
- # for a built-in type that provides its instances with their own
- # __dict__. If 'hasdict' is True for a type T then it is also
- # True for all subtypes of T; so we don't need to look for
- # version_tags to update in the subclasses of a type T whose
- # version_tag is None.
- if w_self.version_tag is not None:
+
+ if space.config.objspace.std.newshortcut:
+ w_self.w_bltin_new = None
+
+ if (space.config.objspace.std.withtypeversion
+ and w_self.version_tag is not None):
w_self.version_tag = VersionTag()
- subclasses_w = w_self.get_subclasses()
- for w_subclass in subclasses_w:
- assert isinstance(w_subclass, W_TypeObject)
- w_subclass.mutated()
+
+ subclasses_w = w_self.get_subclasses()
+ for w_subclass in subclasses_w:
+ assert isinstance(w_subclass, W_TypeObject)
+ w_subclass.mutated()
def ready(w_self):
for w_base in w_self.bases_w:
@@ -572,10 +582,23 @@
else:
return space.type(w_obj)
# invoke the __new__ of the type
- w_newfunc = space.getattr(w_type, space.wrap('__new__'))
- w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
+ w_bltin_new = w_type.w_bltin_new
+ call_init = True
+ if w_bltin_new is not None:
+ w_newobject = space.call_obj_args(w_bltin_new, w_type, __args__)
+ else:
+ w_newtype, w_newdescr = w_type.lookup_where('__new__')
+ w_newfunc = space.get(w_newdescr, w_type)
+ if (space.config.objspace.std.newshortcut and
+ isinstance(w_newtype, W_TypeObject) and
+ not w_newtype.is_heaptype() and
+ not space.is_w(w_newtype, space.w_type)):
+ w_type.w_bltin_new = w_newfunc
+ w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
+ call_init = space.is_true(space.isinstance(w_newobject, w_type))
+
# maybe invoke the __init__ of the type
- if space.is_true(space.isinstance(w_newobject, w_type)):
+ if call_init:
w_descr = space.lookup(w_newobject, '__init__')
w_result = space.get_and_call_args(w_descr, w_newobject, __args__)
if not space.is_w(w_result, space.w_None):
Modified: pypy/branch/spine-of-frames/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/jit.py (original)
+++ pypy/branch/spine-of-frames/pypy/rlib/jit.py Thu Sep 10 16:45:13 2009
@@ -1,3 +1,4 @@
+import sys
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.rlib.objectmodel import CDefinedIntSymbolic
from pypy.rlib.unroll import unrolling_iterable
@@ -82,6 +83,8 @@
PARAMETERS = {'threshold': 1000,
'trace_eagerness': 200,
'hash_bits': 14,
+ 'trace_limit': 10000,
+ 'inlining': False,
}
unroll_parameters = unrolling_iterable(PARAMETERS.keys())
@@ -97,7 +100,8 @@
virtualizables = []
def __init__(self, greens=None, reds=None, virtualizables=None,
- can_inline=None, get_printable_location=None):
+ can_inline=None, get_printable_location=None,
+ leave=None):
if greens is not None:
self.greens = greens
if reds is not None:
@@ -112,6 +116,7 @@
self._make_extregistryentries()
self.get_printable_location = get_printable_location
self.can_inline = can_inline
+ self.leave = leave
def _freeze_(self):
return True
Modified: pypy/branch/spine-of-frames/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/libffi.py (original)
+++ pypy/branch/spine-of-frames/pypy/rlib/libffi.py Thu Sep 10 16:45:13 2009
@@ -311,8 +311,6 @@
"Procedure called with too many "
"arguments (%d bytes in excess) " % (result,))
-
- FormatError = rwin32.FormatError
LoadLibrary = rwin32.LoadLibrary
get_libc_handle = external('get_libc_handle', [], rwin32.HANDLE)
Modified: pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py (original)
+++ pypy/branch/spine-of-frames/pypy/rlib/objectmodel.py Thu Sep 10 16:45:13 2009
@@ -31,6 +31,7 @@
specialcase = "specialize:%s%s" % (self.tag, args)
def specialize_decorator(func):
+ "NOT_RPYTHON"
func._annspecialcase_ = specialcase
return func
Modified: pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py (original)
+++ pypy/branch/spine-of-frames/pypy/rlib/rarithmetic.py Thu Sep 10 16:45:13 2009
@@ -67,6 +67,7 @@
return int(n) # possibly bool->int
if isinstance(n, objectmodel.Symbolic):
return n # assume Symbolics don't overflow
+ assert not isinstance(n, float)
n = long(n)
n &= LONG_MASK
if n >= LONG_TEST:
Modified: pypy/branch/spine-of-frames/pypy/rlib/rwin32.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rlib/rwin32.py (original)
+++ pypy/branch/spine-of-frames/pypy/rlib/rwin32.py Thu Sep 10 16:45:13 2009
@@ -55,7 +55,8 @@
"MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)")
for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
- """.split():
+ MAX_PATH
+ """.split():
locals()[name] = rffi_platform.ConstantInteger(name)
@@ -112,10 +113,9 @@
LocalFree(buf[0])
return result
- def lastWindowsError(context=None):
+ def lastWindowsError(context="Windows Error"):
code = GetLastError()
- message = FormatError(code)
- return WindowsError(code, message)
+ return WindowsError(code, context)
def FAILED(hr):
return rffi.cast(HRESULT, hr) < 0
@@ -125,7 +125,7 @@
DWORD)
def GetModuleFileName(module):
- size = 255 # MAX_PATH
+ size = MAX_PATH
buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
try:
res = _GetModuleFileName(module, buf, size)
Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/ll2ctypes.py Thu Sep 10 16:45:13 2009
@@ -370,15 +370,18 @@
self._storage = None
def __eq__(self, other):
- if not isinstance(other, lltype._parentable):
- return False
- if self._storage is None or other._storage is None:
- raise RuntimeError("pointer comparison with a freed structure")
- if other._storage is True:
- return False # the other container is not ctypes-based
+ if isinstance(other, _llgcopaque):
+ addressof_other = other.intval
+ else:
+ if not isinstance(other, lltype._parentable):
+ return False
+ if self._storage is None or other._storage is None:
+ raise RuntimeError("pointer comparison with a freed structure")
+ if other._storage is True:
+ return False # the other container is not ctypes-based
+ addressof_other = ctypes.addressof(other._storage)
# both containers are ctypes-based, compare by address
- return (ctypes.addressof(self._storage) ==
- ctypes.addressof(other._storage))
+ return (ctypes.addressof(self._storage) == addressof_other)
def __ne__(self, other):
return not (self == other)
@@ -624,6 +627,7 @@
if isinstance(container, lltype._subarray):
topmost, index = _find_parent(container)
container = topmost
+ T = lltype.Ptr(lltype.typeOf(container))
if container._storage is None:
raise RuntimeError("attempting to pass a freed structure to C")
@@ -1099,7 +1103,13 @@
def __eq__(self, other):
if isinstance(other, _llgcopaque):
return self.intval == other.intval
- if other.container._storage in (None, True):
+ storage = object()
+ if hasattr(other, 'container'):
+ storage = other.container._storage
+ else:
+ storage = other._storage
+
+ if storage in (None, True):
return False
return force_cast(lltype.Signed, other._as_ptr()) == self.intval
Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/llarena.py Thu Sep 10 16:45:13 2009
@@ -94,6 +94,8 @@
return addr2
def setobject(self, objaddr, offset, bytes):
+ assert bytes > 0, ("llarena does not support GcStructs with no field"
+ " or empty arrays")
assert offset not in self.objectptrs
self.objectptrs[offset] = objaddr.ptr
self.objectsizes[offset] = bytes
Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/lltype.py Thu Sep 10 16:45:13 2009
@@ -994,25 +994,31 @@
return (type(self._obj0) not in (type(None), int) and
self._getobj(check=False)._was_freed())
- def __getattr__(self, field_name): # ! can only return basic or ptr !
- if isinstance(self._T, Struct):
- if field_name in self._T._flds:
- o = self._obj._getattr(field_name)
- return self._expose(field_name, o)
+ def _lookup_adtmeth(self, member_name):
if isinstance(self._T, ContainerType):
try:
- adtmeth = self._T._adtmeths[field_name]
+ adtmember = self._T._adtmeths[member_name]
except KeyError:
pass
else:
try:
- getter = adtmeth.__get__
+ getter = adtmember.__get__
except AttributeError:
- return adtmeth
+ return adtmember
else:
return getter(self)
- raise AttributeError("%r instance has no field %r" % (self._T,
- field_name))
+ raise AttributeError
+
+ def __getattr__(self, field_name): # ! can only return basic or ptr !
+ if isinstance(self._T, Struct):
+ if field_name in self._T._flds:
+ o = self._obj._getattr(field_name)
+ return self._expose(field_name, o)
+ try:
+ return self._lookup_adtmeth(field_name)
+ except AttributeError:
+ raise AttributeError("%r instance has no field %r" % (self._T,
+ field_name))
def __setattr__(self, field_name, val):
if isinstance(self._T, Struct):
Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/rdict.py Thu Sep 10 16:45:13 2009
@@ -507,7 +507,6 @@
PERTURB_SHIFT = 5
def ll_dict_lookup(d, key, hash):
- DICT = lltype.typeOf(d).TO
entries = d.entries
mask = len(entries) - 1
i = hash & mask
@@ -520,7 +519,7 @@
# correct hash, maybe the key is e.g. a different pointer to
# an equal object
found = d.keyeq(checkingkey, key)
- if DICT.paranoia:
+ if d.paranoia:
if (entries != d.entries or
not entries.valid(i) or entries[i].key != checkingkey):
# the compare did major nasty stuff to the dict: start over
@@ -555,7 +554,7 @@
# correct hash, maybe the key is e.g. a different pointer to
# an equal object
found = d.keyeq(checkingkey, key)
- if DICT.paranoia:
+ if d.paranoia:
if (entries != d.entries or
not entries.valid(i) or entries[i].key != checkingkey):
# the compare did major nasty stuff to the dict:
Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Thu Sep 10 16:45:13 2009
@@ -1091,8 +1091,38 @@
assert ref1 == ref2
assert ref2 == ref1
assert not (ref1 != ref2)
- assert not (ref2 != ref1)
-
+ assert not (ref2 != ref1)
+
+ def test_convert_subarray(self):
+ A = lltype.GcArray(lltype.Signed)
+ a = lltype.malloc(A, 20)
+ inside = lltype.direct_ptradd(lltype.direct_arrayitems(a), 3)
+
+ lltype2ctypes(inside)
+
+ start = rffi.cast(lltype.Signed, lltype.direct_arrayitems(a))
+ inside_int = rffi.cast(lltype.Signed, inside)
+
+ assert inside_int == start+rffi.sizeof(lltype.Signed)*3
+
+ def test_gcref_comparisons_through_addresses(self):
+ NODE = lltype.GcStruct('NODE')
+ n0 = lltype.malloc(NODE)
+ adr0 = llmemory.cast_ptr_to_adr(n0)
+
+ n1 = lltype.malloc(NODE)
+ i1 = rffi.cast(lltype.Signed, n1)
+ ref1 = rffi.cast(llmemory.GCREF, i1)
+ adr1 = llmemory.cast_ptr_to_adr(ref1)
+
+ assert adr1 != adr0
+ assert adr0 != adr1
+
+ adr1_2 = llmemory.cast_ptr_to_adr(n1)
+
+ #import pdb; pdb.set_trace()
+ assert adr1_2 == adr1
+ assert adr1 == adr1_2
class TestPlatform(object):
def test_lib_on_libpaths(self):
Modified: pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/lltypesystem/test/test_lltype.py Thu Sep 10 16:45:13 2009
@@ -528,7 +528,8 @@
A = GcArray(Signed,
adtmeths={"h_alloc": h_alloc,
- "h_length": h_length})
+ "h_length": h_length,
+ "stuff": 12})
a = A.h_alloc(10)
@@ -536,6 +537,9 @@
assert len(a) == 10
assert a.h_length() == 10
+ assert a._lookup_adtmeth("h_length")() == 10
+ assert a.stuff == 12
+ assert a._lookup_adtmeth("stuff") == 12
def test_adt_typemethod():
def h_newstruct(S):
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/base.py Thu Sep 10 16:45:13 2009
@@ -100,6 +100,7 @@
assert not (needs_finalizer and contains_weakptr)
if self.is_varsize(typeid):
assert not contains_weakptr
+ assert not needs_finalizer
itemsize = self.varsize_item_sizes(typeid)
offset_to_length = self.varsize_offset_to_length(typeid)
if zero or not hasattr(self, 'malloc_varsize'):
@@ -107,7 +108,7 @@
else:
malloc_varsize = self.malloc_varsize
ref = malloc_varsize(typeid, length, size, itemsize,
- offset_to_length, True, needs_finalizer)
+ offset_to_length, True)
else:
if zero or not hasattr(self, 'malloc_fixedsize'):
malloc_fixedsize = self.malloc_fixedsize_clear
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/generation.py Thu Sep 10 16:45:13 2009
@@ -160,8 +160,7 @@
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
def malloc_varsize_clear(self, typeid, length, size, itemsize,
- offset_to_length, can_collect,
- has_finalizer=False):
+ offset_to_length, can_collect):
# Only use the nursery if there are not too many items.
if not raw_malloc_usage(itemsize):
too_many_items = False
@@ -180,7 +179,7 @@
maxlength = maxlength_for_minimal_nursery << self.nursery_scale
too_many_items = length > maxlength
- if (has_finalizer or not can_collect or
+ if (not can_collect or
too_many_items or
(raw_malloc_usage(size) > self.lb_young_var_basesize and
raw_malloc_usage(size) > self.largest_young_var_basesize)):
@@ -190,7 +189,7 @@
# second comparison as well.
return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size,
itemsize, offset_to_length,
- can_collect, has_finalizer)
+ can_collect)
# with the above checks we know now that totalsize cannot be more
# than about half of the nursery size; in particular, the + and *
# cannot overflow
@@ -392,6 +391,9 @@
if self.is_in_nursery(pointer.address[0]):
pointer.address[0] = self.copy(pointer.address[0])
+ # The code relies on the fact that no weakref can be an old object
+ # weakly pointing to a young object. Indeed, weakrefs are immutable
+ # so they cannot point to an object that was created after it.
def invalidate_young_weakrefs(self):
# walk over the list of objects that contain weakrefs and are in the
# nursery. if the object it references survives then update the
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/hybrid.py Thu Sep 10 16:45:13 2009
@@ -132,12 +132,11 @@
# 'large'.
def malloc_varsize_clear(self, typeid, length, size, itemsize,
- offset_to_length, can_collect,
- has_finalizer=False):
- if has_finalizer or not can_collect:
+ offset_to_length, can_collect):
+ if not can_collect:
return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size,
itemsize, offset_to_length,
- can_collect, has_finalizer)
+ can_collect)
size_gc_header = self.gcheaderbuilder.size_gc_header
nonvarsize = size_gc_header + size
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/markcompact.py Thu Sep 10 16:45:13 2009
@@ -131,8 +131,7 @@
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
def malloc_varsize_clear(self, typeid, length, size, itemsize,
- offset_to_length, can_collect,
- has_finalizer=False):
+ offset_to_length, can_collect):
size_gc_header = self.gcheaderbuilder.size_gc_header
nonvarsize = size_gc_header + size
try:
@@ -147,8 +146,6 @@
self.init_gc_object(result, typeid)
(result + size_gc_header + offset_to_length).signed[0] = length
self.free = result + llarena.round_up_for_allocation(totalsize)
- if has_finalizer:
- self.objects_with_finalizers.append(result + size_gc_header)
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
def obtain_free_space(self, totalsize):
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/marksweep.py Thu Sep 10 16:45:13 2009
@@ -151,7 +151,7 @@
malloc_fixedsize_clear._dont_inline_ = True
def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
- can_collect, has_finalizer=False):
+ can_collect):
if can_collect:
self.maybe_collect()
size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -170,12 +170,8 @@
(result + size_gc_header + offset_to_length).signed[0] = length
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
hdr.typeid = typeid << 1
- if has_finalizer:
- hdr.next = self.malloced_objects_with_finalizer
- self.malloced_objects_with_finalizer = hdr
- else:
- hdr.next = self.malloced_objects
- self.malloced_objects = hdr
+ hdr.next = self.malloced_objects
+ self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
result += size_gc_header
@@ -187,8 +183,7 @@
malloc_varsize._dont_inline_ = True
def malloc_varsize_clear(self, typeid, length, size, itemsize,
- offset_to_length, can_collect,
- has_finalizer=False):
+ offset_to_length, can_collect):
if can_collect:
self.maybe_collect()
size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -208,12 +203,8 @@
(result + size_gc_header + offset_to_length).signed[0] = length
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
hdr.typeid = typeid << 1
- if has_finalizer:
- hdr.next = self.malloced_objects_with_finalizer
- self.malloced_objects_with_finalizer = hdr
- else:
- hdr.next = self.malloced_objects
- self.malloced_objects = hdr
+ hdr.next = self.malloced_objects
+ self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
result += size_gc_header
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gc/semispace.py Thu Sep 10 16:45:13 2009
@@ -83,8 +83,7 @@
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
def malloc_varsize_clear(self, typeid, length, size, itemsize,
- offset_to_length, can_collect,
- has_finalizer=False):
+ offset_to_length, can_collect):
size_gc_header = self.gcheaderbuilder.size_gc_header
nonvarsize = size_gc_header + size
try:
@@ -101,8 +100,6 @@
self.init_gc_object(result, typeid)
(result + size_gc_header + offset_to_length).signed[0] = length
self.free = result + llarena.round_up_for_allocation(totalsize)
- if has_finalizer:
- self.objects_with_finalizers.append(result + size_gc_header)
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
def obtain_free_space(self, needed):
Modified: pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/memory/gctransform/framework.py Thu Sep 10 16:45:13 2009
@@ -235,7 +235,7 @@
self.malloc_varsize_clear_ptr = getfn(
GCClass.malloc_varsize_clear.im_func,
[s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
- + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
+ + [annmodel.SomeBool()], s_gcref)
self.collect_ptr = getfn(GCClass.collect.im_func,
[s_gc], annmodel.s_None)
self.can_move_ptr = getfn(GCClass.can_move.im_func,
@@ -285,7 +285,7 @@
annmodel.SomeInteger(nonneg=True),
annmodel.SomeInteger(nonneg=True),
annmodel.SomeInteger(nonneg=True),
- s_True, s_False], s_gcref,
+ s_True], s_gcref,
inline = True)
else:
self.malloc_varsize_clear_fast_ptr = None
@@ -524,30 +524,28 @@
args = [self.c_const_gc, c_type_id, c_size, c_can_collect,
c_has_finalizer, rmodel.inputconst(lltype.Bool, False)]
else:
+ assert not c_has_finalizer.value
v_length = op.args[-1]
c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
if flags.get('resizable') and self.malloc_varsize_resizable_ptr:
assert c_can_collect.value
- assert not c_has_finalizer.value
malloc_ptr = self.malloc_varsize_resizable_ptr
args = [self.c_const_gc, c_type_id, v_length]
elif flags.get('nonmovable') and self.malloc_varsize_nonmovable_ptr:
# we don't have tests for such cases, let's fail
# explicitely
assert c_can_collect.value
- assert not c_has_finalizer.value
malloc_ptr = self.malloc_varsize_nonmovable_ptr
args = [self.c_const_gc, c_type_id, v_length]
else:
if (self.malloc_varsize_clear_fast_ptr is not None and
- c_can_collect.value and not c_has_finalizer.value):
+ c_can_collect.value):
malloc_ptr = self.malloc_varsize_clear_fast_ptr
else:
malloc_ptr = self.malloc_varsize_clear_ptr
args = [self.c_const_gc, c_type_id, v_length, c_size,
- c_varitemsize, c_ofstolength, c_can_collect,
- c_has_finalizer]
+ c_varitemsize, c_ofstolength, c_can_collect]
keep_current_args = flags.get('keep_current_args', False)
livevars = self.push_roots(hop, keep_current_args=keep_current_args)
v_result = hop.genop("direct_call", [malloc_ptr] + args,
@@ -623,12 +621,12 @@
# used by the JIT (see pypy.jit.backend.llsupport.gc)
op = hop.spaceop
[v_typeid, v_length, v_size, v_itemsize,
- v_offset_to_length, v_can_collect, v_has_finalizer] = op.args
+ v_offset_to_length, v_can_collect] = op.args
livevars = self.push_roots(hop)
hop.genop("direct_call",
[self.malloc_varsize_clear_ptr, self.c_const_gc,
v_typeid, v_length, v_size, v_itemsize,
- v_offset_to_length, v_can_collect, v_has_finalizer],
+ v_offset_to_length, v_can_collect],
resultvar=op.result)
self.pop_roots(hop, livevars)
Modified: pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/module/ll_os.py Thu Sep 10 16:45:13 2009
@@ -468,24 +468,22 @@
@registering(os.times)
def register_os_times(self):
if sys.platform.startswith('win'):
- HANDLE = rffi.ULONG
- FILETIME = rffi.CStruct('_FILETIME', ('dwLowDateTime', rffi.LONG),
- ('dwHighDateTime', rffi.LONG))
+ from pypy.rlib import rwin32
GetCurrentProcess = self.llexternal('GetCurrentProcess', [],
- HANDLE)
+ rwin32.HANDLE)
GetProcessTimes = self.llexternal('GetProcessTimes',
- [HANDLE,
- lltype.Ptr(FILETIME),
- lltype.Ptr(FILETIME),
- lltype.Ptr(FILETIME),
- lltype.Ptr(FILETIME)],
- lltype.Bool)
+ [rwin32.HANDLE,
+ lltype.Ptr(rwin32.FILETIME),
+ lltype.Ptr(rwin32.FILETIME),
+ lltype.Ptr(rwin32.FILETIME),
+ lltype.Ptr(rwin32.FILETIME)],
+ rwin32.BOOL)
def times_lltypeimpl():
- pcreate = lltype.malloc(FILETIME, flavor='raw')
- pexit = lltype.malloc(FILETIME, flavor='raw')
- pkernel = lltype.malloc(FILETIME, flavor='raw')
- puser = lltype.malloc(FILETIME, flavor='raw')
+ pcreate = lltype.malloc(rwin32.FILETIME, flavor='raw')
+ pexit = lltype.malloc(rwin32.FILETIME, flavor='raw')
+ pkernel = lltype.malloc(rwin32.FILETIME, flavor='raw')
+ puser = lltype.malloc(rwin32.FILETIME, flavor='raw')
hProc = GetCurrentProcess()
GetProcessTimes(hProc, pcreate, pexit, pkernel, puser)
# The fields of a FILETIME structure are the hi and lo parts
@@ -904,47 +902,29 @@
@registering_if(posix, '_getfullpathname')
def register_posix__getfullpathname(self):
+ from pypy.rlib import rwin32
# this nt function is not exposed via os, but needed
# to get a correct implementation of os.abspath
# XXX why do we ignore WINAPI conventions everywhere?
- class CConfig:
- _compilation_info_ = ExternalCompilationInfo(
- includes = ['Windows.h']
- )
- MAX_PATH = platform.ConstantInteger('MAX_PATH')
- DWORD = platform.SimpleType("DWORD", rffi.ULONG)
- LPCTSTR = platform.SimpleType("LPCTSTR", rffi.CCHARP)
- LPTSTR = platform.SimpleType("LPTSTR", rffi.CCHARP)
- LPTSTRP = platform.SimpleType("LPTSTR*", rffi.CCHARPP)
-
- config = platform.configure(CConfig)
- MAX_PATH = config['MAX_PATH']
- DWORD = config['DWORD']
- LPCTSTR = config['LPCTSTR']
- LPTSTR = config['LPTSTR']
- LPTSTRP = config['LPTSTRP']
+ LPSTRP = rffi.CArrayPtr(rwin32.LPSTR)
# XXX unicode?
- GetFullPathName = self.llexternal('GetFullPathNameA',
- [LPCTSTR, DWORD, LPTSTR, LPTSTRP], DWORD)
- GetLastError = self.llexternal('GetLastError', [], DWORD)
- ##DWORD WINAPI GetFullPathName(
- ## __in LPCTSTR lpFileName,
- ## __in DWORD nBufferLength,
- ## __out LPTSTR lpBuffer,
- ## __out LPTSTR* lpFilePart
- ##);
+ GetFullPathName = self.llexternal(
+ 'GetFullPathNameA',
+ [rwin32.LPCSTR,
+ rwin32.DWORD,
+ rwin32.LPSTR,
+ rffi.CArrayPtr(rwin32.LPSTR)],
+ rwin32.DWORD)
def _getfullpathname_llimpl(lpFileName):
- nBufferLength = MAX_PATH + 1
- lpBuffer = lltype.malloc(LPTSTR.TO, nBufferLength, flavor='raw')
+ nBufferLength = rwin32.MAX_PATH + 1
+ lpBuffer = lltype.malloc(rwin32.LPSTR.TO, nBufferLength, flavor='raw')
try:
res = GetFullPathName(
- lpFileName, rffi.cast(DWORD, nBufferLength),
- lpBuffer, lltype.nullptr(LPTSTRP.TO))
+ lpFileName, rffi.cast(rwin32.DWORD, nBufferLength),
+ lpBuffer, lltype.nullptr(LPSTRP.TO))
if res == 0:
- error = GetLastError()
- raise OSError(error, "_getfullpathname failed")
- # XXX ntpath expects WindowsError :-(
+ raise rwin32.lastWindowsError("_getfullpathname failed")
result = rffi.charp2str(lpBuffer)
return result
finally:
@@ -991,14 +971,13 @@
def register_os_listdir(self):
# we need a different approach on Windows and on Posix
if sys.platform.startswith('win'):
+ from pypy.rlib import rwin32
class CConfig:
_compilation_info_ = ExternalCompilationInfo(
includes = ['windows.h']
)
WIN32_FIND_DATA = platform.Struct('struct _WIN32_FIND_DATAA',
[('cFileName', lltype.FixedSizeArray(rffi.CHAR, 1))])
- INVALID_HANDLE_VALUE = platform.ConstantInteger(
- 'INVALID_HANDLE_VALUE')
ERROR_FILE_NOT_FOUND = platform.ConstantInteger(
'ERROR_FILE_NOT_FOUND')
ERROR_NO_MORE_FILES = platform.ConstantInteger(
@@ -1006,23 +985,19 @@
config = platform.configure(CConfig)
WIN32_FIND_DATA = config['WIN32_FIND_DATA']
- INVALID_HANDLE_VALUE = config['INVALID_HANDLE_VALUE']
ERROR_FILE_NOT_FOUND = config['ERROR_FILE_NOT_FOUND']
ERROR_NO_MORE_FILES = config['ERROR_NO_MORE_FILES']
LPWIN32_FIND_DATA = lltype.Ptr(WIN32_FIND_DATA)
- HANDLE = rffi.ULONG
- #MAX_PATH = WIN32_FIND_DATA.c_cFileName.length
- GetLastError = self.llexternal('GetLastError', [], lltype.Signed)
FindFirstFile = self.llexternal('FindFirstFile',
- [rffi.CCHARP, LPWIN32_FIND_DATA],
- HANDLE)
+ [rwin32.LPCSTR, LPWIN32_FIND_DATA],
+ rwin32.HANDLE)
FindNextFile = self.llexternal('FindNextFile',
- [HANDLE, LPWIN32_FIND_DATA],
- rffi.INT)
+ [rwin32.HANDLE, LPWIN32_FIND_DATA],
+ rwin32.BOOL)
FindClose = self.llexternal('FindClose',
- [HANDLE],
- rffi.INT)
+ [rwin32.HANDLE],
+ rwin32.BOOL)
def os_listdir_llimpl(path):
if path and path[-1] not in ('/', '\\', ':'):
@@ -1032,13 +1007,12 @@
try:
result = []
hFindFile = FindFirstFile(path, filedata)
- if hFindFile == INVALID_HANDLE_VALUE:
- error = GetLastError()
+ if hFindFile == rwin32.INVALID_HANDLE_VALUE:
+ error = rwin32.GetLastError()
if error == ERROR_FILE_NOT_FOUND:
return result
else:
- # XXX guess error code :-(
- raise OSError(errno.ENOENT, "FindFirstFile failed")
+ raise WindowsError(error, "FindFirstFile failed")
while True:
name = rffi.charp2str(rffi.cast(rffi.CCHARP,
filedata.c_cFileName))
@@ -1048,13 +1022,12 @@
break
# FindNextFile sets error to ERROR_NO_MORE_FILES if
# it got to the end of the directory
- error = GetLastError()
+ error = rwin32.GetLastError()
FindClose(hFindFile)
if error == ERROR_NO_MORE_FILES:
return result
else:
- # XXX guess error code :-(
- raise OSError(errno.EIO, "FindNextFile failed")
+ raise WindowsError(error, "FindNextFile failed")
finally:
lltype.free(filedata, flavor='raw')
@@ -1107,28 +1080,31 @@
def register_os_pipe(self):
# we need a different approach on Windows and on Posix
if sys.platform.startswith('win'):
- HANDLE = rffi.ULONG
- HANDLEP = lltype.Ptr(lltype.FixedSizeArray(HANDLE, 1))
- CreatePipe = self.llexternal('CreatePipe', [HANDLEP,
- HANDLEP,
+ from pypy.rlib import rwin32
+ CreatePipe = self.llexternal('CreatePipe', [rwin32.LPHANDLE,
+ rwin32.LPHANDLE,
rffi.VOIDP,
- rffi.ULONG],
- rffi.INT)
+ rwin32.DWORD],
+ rwin32.BOOL)
_open_osfhandle = self.llexternal('_open_osfhandle', [rffi.ULONG,
rffi.INT],
rffi.INT)
null = lltype.nullptr(rffi.VOIDP.TO)
def os_pipe_llimpl():
- pread = lltype.malloc(HANDLEP.TO, flavor='raw')
- pwrite = lltype.malloc(HANDLEP.TO, flavor='raw')
+ pread = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
+ pwrite = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
ok = CreatePipe(pread, pwrite, null, 0)
+ if ok:
+ error = 0
+ else:
+ error = rwin32.GetLastError()
hread = pread[0]
hwrite = pwrite[0]
lltype.free(pwrite, flavor='raw')
lltype.free(pread, flavor='raw')
- if not ok: # XXX guess the error, can't use GetLastError()
- raise OSError(errno.EMFILE, "os_pipe failed")
+ if error:
+ raise WindowsError(error, "os_pipe failed")
fdread = _open_osfhandle(hread, 0)
fdwrite = _open_osfhandle(hwrite, 1)
return (fdread, fdwrite)
Modified: pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/ootype.py Thu Sep 10 16:45:13 2009
@@ -258,6 +258,14 @@
graphs.update(SUBTYPE._lookup_graphs(meth_name))
return graphs
+ def _get_fields_with_different_default(self):
+ fields = []
+ example = self._example()
+ for field in self._allfields().iteritems():
+ name, (T, value) = field
+ if T._defl() != value:
+ fields.append(field)
+ return fields
class SpecializableType(OOType):
Modified: pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/rpbc.py Thu Sep 10 16:45:13 2009
@@ -21,9 +21,7 @@
if robj1 == none_frozen_pbc_repr:
return hop.inputconst(ootype.Bool, True)
v1 = hop.inputarg(robj1, pos)
- v2 = hop.genop('oononnull', [v1], resulttype=ootype.Bool)
- v3 = hop.genop('bool_not', [v2], resulttype=ootype.Bool)
- return v3
+ return hop.genop('ooisnull', [v1], resulttype=ootype.Bool)
class FunctionsPBCRepr(AbstractFunctionsPBCRepr):
Modified: pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/ootypesystem/test/test_ootype.py Thu Sep 10 16:45:13 2009
@@ -654,3 +654,11 @@
SM = StaticMethod([], Void)
sm = SM._defl()
assert not bool(sm)
+
+def test_get_fields_with_different_default():
+ A = Instance("A", ROOT, {"a": (Signed, 3),
+ "b": (Signed, 0),
+ "c": (ROOT, ROOT._defl())
+ })
+ fields = A._get_fields_with_different_default()
+ assert fields == [("a", (Signed, 3))]
Modified: pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rbuiltin.py Thu Sep 10 16:45:13 2009
@@ -268,6 +268,16 @@
v_errno = hop.inputarg(lltype.Signed, arg=1)
r_self.setfield(v_self, 'errno', v_errno, hop.llops)
+def rtype_WindowsError__init__(hop):
+ if hop.nb_args == 2:
+ raise TyperError("WindowsError() should not be called with "
+ "a single argument")
+ if hop.nb_args >= 3:
+ v_self = hop.args_v[0]
+ r_self = hop.args_r[0]
+ v_error = hop.inputarg(lltype.Signed, arg=1)
+ r_self.setfield(v_self, 'winerror', v_error, hop.llops)
+
def rtype_we_are_translated(hop):
hop.exception_cannot_occur()
return hop.inputconst(lltype.Bool, True)
@@ -318,6 +328,15 @@
BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = (
rtype_OSError__init__)
+try:
+ WindowsError
+except NameError:
+ pass
+else:
+ BUILTIN_TYPER[
+ getattr(WindowsError.__init__, 'im_func', WindowsError.__init__)] = (
+ rtype_WindowsError__init__)
+
BUILTIN_TYPER[object.__init__] = rtype_object__init__
# annotation of low-level types
Modified: pypy/branch/spine-of-frames/pypy/rpython/rint.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rint.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rint.py Thu Sep 10 16:45:13 2009
@@ -385,6 +385,7 @@
def rtype_float(_, hop):
vlist = hop.inputargs(Float)
+ hop.exception_cannot_occur()
return vlist[0]
# version picked by specialisation based on which
Modified: pypy/branch/spine-of-frames/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rpbc.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rpbc.py Thu Sep 10 16:45:13 2009
@@ -834,7 +834,15 @@
"classes with no common base: %r" % (mdescs,))
self.methodname = methodname
- self.classdef = classdef.locate_attribute(methodname)
+ # for ootype, the right thing to do is to always keep the most precise
+ # type of the instance, while for lltype we want to cast it to the
+ # type where the method is actually defined. See also
+ # test_rclass.test_method_specialized_with_subclass and
+ # rtyper.attach_methods_to_subclasses
+ if self.rtyper.type_system.name == 'ootypesystem':
+ self.classdef = classdef
+ else:
+ self.classdef = classdef.locate_attribute(methodname)
# the low-level representation is just the bound 'self' argument.
self.s_im_self = annmodel.SomeInstance(self.classdef, flags=flags)
self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef)
Modified: pypy/branch/spine-of-frames/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/rtyper.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/rtyper.py Thu Sep 10 16:45:13 2009
@@ -198,7 +198,9 @@
if self.exceptiondata is not None:
self.exceptiondata.make_helpers(self)
self.specialize_more_blocks() # for the helpers just made
-
+ if self.type_system.name == 'ootypesystem':
+ self.attach_methods_to_subclasses()
+
#
from pypy.annotation import listdef
ldef = listdef.ListDef(None, annmodel.SomeString())
@@ -268,6 +270,40 @@
if annmixlevel is not None:
annmixlevel.finish()
+ def attach_methods_to_subclasses(self):
+ # in ootype, it might happen that a method is defined in the
+ # superclass but the annotator discovers that it's always called
+ # through instances of a subclass (e.g. because of specialization, see
+ # test_rclass.test_method_specialized_with_subclass). In that cases,
+ # we copy the method also in the ootype.Instance of the subclass, so
+ # that the type of v_self coincides with the type returned by
+ # _lookup().
+ assert self.type_system.name == 'ootypesystem'
+ def allclasses(TYPE, seen):
+ '''Yield TYPE and all its subclasses'''
+ if TYPE in seen:
+ return
+ seen.add(TYPE)
+ yield TYPE
+ for SUB in TYPE._subclasses:
+ for T in allclasses(SUB, seen):
+ yield T
+
+ for TYPE in allclasses(ootype.ROOT, set()):
+ for methname, meth in TYPE._methods.iteritems():
+ try:
+ graph = meth.graph
+ except AttributeError:
+ continue
+ SELF = graph.getargs()[0].concretetype
+ if TYPE != SELF and ootype.isSubclass(SELF, TYPE):
+ # the annotator found that this method has a more precise
+ # type. Attach it to the proper subclass, so that the type
+ # of 'self' coincides with the type returned by _lookup(),
+ # else we might have type errors
+ if methname not in SELF._methods:
+ ootype.addMethods(SELF, {methname: meth})
+
def dump_typererrors(self, num=None, minimize=True, to_log=False):
c = 0
bc = 0
Modified: pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/test/test_llann.py Thu Sep 10 16:45:13 2009
@@ -389,6 +389,26 @@
lst.append(6)
self.annotate(llf, [])
+ def test_adtmeths(self):
+ def h_length(s):
+ return s.foo
+ S = GcStruct("S", ('foo', Signed),
+ adtmeths={"h_length": h_length,
+ "stuff": 12})
+ def llf():
+ s = malloc(S)
+ s.foo = 321
+ return s.h_length()
+ s = self.annotate(llf, [])
+ assert s.knowntype == int and not s.is_constant()
+
+ def llf():
+ s = malloc(S)
+ return s.stuff
+ s = self.annotate(llf, [])
+ assert s.is_constant() and s.const == 12
+
+
def test_pseudohighlevelcallable():
t = TranslationContext()
t.buildannotator()
Modified: pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/test/test_rclass.py Thu Sep 10 16:45:13 2009
@@ -266,6 +266,25 @@
res = self.interpret(f, [])
assert res == 246
+ def test_method_specialized_with_subclass(self):
+ class A:
+ def meth(self, n):
+ return -1
+ meth._annspecialcase_ = 'specialize:arg(1)'
+
+ class B(A):
+ pass
+
+ def f():
+ a = A()
+ b = B()
+ a.meth(1) # the self of this variant is annotated with A
+ b.meth(2) # the self of this variant is annotated with B
+ return 42
+
+ res = self.interpret(f, [])
+ assert res == 42
+
def test_issubclass_type(self):
class Abstract:
pass
Modified: pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py (original)
+++ pypy/branch/spine-of-frames/pypy/rpython/test/test_rint.py Thu Sep 10 16:45:13 2009
@@ -327,6 +327,16 @@
res = self.interpret(f, [sys.maxint])
assert res == 0
+ def test_cast_to_float_exc_check(self):
+ def f(x):
+ try:
+ return float(x)
+ except ValueError:
+ return 3.0
+
+ res = self.interpret(f, [3])
+ assert res == 3
+
class TestLLtype(BaseTestRint, LLRtypeMixin):
pass
Modified: pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/gcc/test/test_asmgcroot.py Thu Sep 10 16:45:13 2009
@@ -7,7 +7,9 @@
from pypy import conftest
if sys.platform == 'win32':
- py.test.skip("No asmgcc on Windows")
+ if not ('mingw' in os.popen('gcc --version').read() and
+ 'GNU' in os.popen('make --version').read()):
+ py.test.skip("mingw32 and MSYS are required for asmgcc on Windows")
class AbstractTestAsmGCRoot:
# the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
@@ -30,6 +32,8 @@
config = get_pypy_config(translating=True)
config.translation.gc = self.gcpolicy
config.translation.gcrootfinder = "asmgcc"
+ if sys.platform == 'win32':
+ config.translation.cc = 'mingw32'
t = TranslationContext(config=config)
self.t = t
a = t.buildannotator()
@@ -48,7 +52,7 @@
def run():
lines = []
print >> sys.stderr, 'RUN: starting', exe_name
- g = os.popen("'%s'" % (exe_name,), 'r')
+ g = os.popen('"%s"' % (exe_name,), 'r')
for line in g:
print >> sys.stderr, 'RUN:', line.rstrip()
lines.append(line)
Modified: pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/gcc/trackgcroot.py Thu Sep 10 16:45:13 2009
@@ -23,15 +23,16 @@
r_functionstart_darwin = re.compile(r"_(\w+):\s*$")
# inside functions
-r_label = re.compile(r"([.]?\w+)[:]\s*$")
+LABEL = r'([.]?[\w$@]+)'
+r_label = re.compile(LABEL+"[:]\s*$")
r_globl = re.compile(r"\t[.]globl\t(\w+)\s*$")
r_insn = re.compile(r"\t([a-z]\w*)\s")
-r_jump = re.compile(r"\tj\w+\s+([.]?[\w$]+)\s*$")
+r_jump = re.compile(r"\tj\w+\s+"+LABEL+"\s*$")
OPERAND = r'(?:[-\w$%+.:@"]+(?:[(][\w%,]+[)])?|[(][\w%,]+[)])'
r_unaryinsn = re.compile(r"\t[a-z]\w*\s+("+OPERAND+")\s*$")
r_unaryinsn_star= re.compile(r"\t[a-z]\w*\s+([*]"+OPERAND+")\s*$")
-r_jmp_switch = re.compile(r"\tjmp\t[*]([.]?\w+)[(]")
-r_jmptable_item = re.compile(r"\t.long\t([.]?\w+)\s*$")
+r_jmp_switch = re.compile(r"\tjmp\t[*]"+LABEL+"[(]")
+r_jmptable_item = re.compile(r"\t.long\t"+LABEL+"\s*$")
r_jmptable_end = re.compile(r"\t.text|\t.section\s+.text")
r_binaryinsn = re.compile(r"\t[a-z]\w*\s+("+OPERAND+"),\s*("+OPERAND+")\s*$")
LOCALVAR = r"%eax|%edx|%ecx|%ebx|%esi|%edi|%ebp|\d*[(]%esp[)]"
@@ -75,23 +76,22 @@
shapelines = []
shapeofs = 0
def _globalname(name):
- if self.format == 'darwin':
+ if self.format in ('darwin', 'mingw32'):
return '_' + name
return name
def _globl(name):
print >> output, "\t.globl %s" % _globalname(name)
def _label(name):
print >> output, "%s:" % _globalname(name)
- def _variant(elf, darwin):
- if self.format == 'darwin':
- txt = darwin
- else:
- txt = elf
+ def _variant(**kwargs):
+ txt = kwargs[self.format]
print >> output, "\t%s" % txt
-
+
print >> output, "\t.text"
_globl('pypy_asm_stackwalk')
- _variant('.type pypy_asm_stackwalk, @function', '')
+ _variant(elf='.type pypy_asm_stackwalk, @function',
+ darwin='',
+ mingw32='')
_label('pypy_asm_stackwalk')
print >> output, """\
/* See description in asmgcroot.py */
@@ -114,7 +114,9 @@
popl %eax
ret
"""
- _variant('.size pypy_asm_stackwalk, .-pypy_asm_stackwalk', '')
+ _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
+ darwin='',
+ mingw32='')
print >> output, '\t.data'
print >> output, '\t.align\t4'
_globl('__gcmapstart')
@@ -135,7 +137,9 @@
print >> output, '\t.long\t%d' % (n,)
_globl('__gcmapend')
_label('__gcmapend')
- _variant('.section\t.rodata', '.const')
+ _variant(elf='.section\t.rodata',
+ darwin='.const',
+ mingw32='')
_globl('__gccallshapes')
_label('__gccallshapes')
output.writelines(shapelines)
@@ -188,8 +192,10 @@
if functionlines:
yield in_function, functionlines
+ _find_functions_mingw32 = _find_functions_darwin
+
def process(self, iterlines, newfile, entrypoint='main', filename='?'):
- if self.format == 'darwin':
+ if self.format in ('darwin', 'mingw32'):
entrypoint = '_' + entrypoint
for in_function, lines in self.find_functions(iterlines):
if in_function:
@@ -232,6 +238,9 @@
elif format == 'darwin':
match = r_functionstart_darwin.match(lines[0])
funcname = '_'+match.group(1)
+ elif format == 'mingw32':
+ match = r_functionstart_darwin.match(lines[0])
+ funcname = '_'+match.group(1)
else:
assert False, "unknown format: %s" % format
@@ -738,8 +747,15 @@
if lineoffset >= 0:
assert lineoffset in (1,2)
return [InsnStackAdjust(-4)]
- return [InsnCall(self.currentlineno),
- InsnSetLocal('%eax')] # the result is there
+ insns = [InsnCall(self.currentlineno),
+ InsnSetLocal('%eax')] # the result is there
+ if sys.platform == 'win32':
+ # handle __stdcall calling convention:
+ # Stack cleanup is performed by the called function,
+ # Function name is decorated with "@N" where N is the stack size
+ if match and '@' in target:
+ insns.append(InsnStackAdjust(int(target.split('@')[1])))
+ return insns
class UnrecognizedOperation(Exception):
@@ -1108,6 +1124,8 @@
break
if sys.platform == 'darwin':
format = 'darwin'
+ elif sys.platform == 'win32':
+ format = 'mingw32'
else:
format = 'elf'
tracker = GcRootTracker(verbose=verbose, shuffle=shuffle, format=format)
Modified: pypy/branch/spine-of-frames/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/genc.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/genc.py Thu Sep 10 16:45:13 2009
@@ -492,8 +492,14 @@
mk.definition('GCMAPFILES', gcmapfiles)
mk.definition('OBJECTS', '$(ASMLBLFILES) gcmaptable.s')
mk.rule('%.s', '%.c', '$(CC) $(CFLAGS) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)')
- mk.rule('%.lbl.s %.gcmap', '%.s', '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $*.gcmap')
- mk.rule('gcmaptable.s', '$(GCMAPFILES)', '$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@')
+ if sys.platform == 'win32':
+ python = sys.executable.replace('\\', '/') + ' '
+ else:
+ python = ""
+ mk.rule('%.lbl.s %.gcmap', '%.s',
+ python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $*.gcmap')
+ mk.rule('gcmaptable.s', '$(GCMAPFILES)',
+ python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@')
mk.write()
#self.translator.platform,
@@ -785,7 +791,10 @@
for key, value in defines.items():
print >> fi, '#define %s %s' % (key, value)
- print >> fi, '#define Py_BUILD_CORE /* for Windows: avoid pulling libs in */'
+ if sys.platform == 'win32':
+ print >> fi, '#define Py_BUILD_CORE /* avoid pulling python libs in */'
+ print >> fi, '#define WIN32_LEAN_AND_MEAN /* winsock/winsock2 mess */'
+
print >> fi, '#include "pyconfig.h"'
eci.write_c_header(fi)
@@ -838,6 +847,9 @@
for key, value in defines.items():
print >> fi, '#define %s %s' % (key, value)
+ if sys.platform == 'win32':
+ print >> fi, '#define WIN32_LEAN_AND_MEAN /* winsock/winsock2 mess */'
+
print >> fi, '#include "pyconfig.h"'
eci.write_c_header(fi)
Modified: pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h (original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/src/thread_nt.h Thu Sep 10 16:45:13 2009
@@ -4,12 +4,6 @@
/* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch at iso.ru */
/* Eliminated some memory leaks, gsw at agere.com */
-/* Windows.h includes winsock.h, but the socket module needs */
-/* winsock2.h. So I include it before. Ugly. */
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
#include <windows.h>
#include <limits.h>
#include <process.h>
@@ -61,7 +55,7 @@
return GetCurrentThreadId();
}
-static int
+static void
bootstrap(void *call)
{
callobj *obj = (callobj*)call;
@@ -71,7 +65,6 @@
obj->id = RPyThreadGetIdent();
ReleaseSemaphore(obj->done, 1, NULL);
func();
- return 0;
}
long RPyThreadStart(void (*func)(void))
@@ -130,69 +123,14 @@
/************************************************************/
-typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ;
-
-/* Sorry mate, but we haven't got InterlockedCompareExchange in Win95! */
-static PVOID WINAPI interlocked_cmp_xchg(PVOID *dest, PVOID exc, PVOID comperand)
-{
- static LONG spinlock = 0 ;
- PVOID result ;
- DWORD dwSleep = 0;
-
- /* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
- while(InterlockedExchange(&spinlock, 1))
- {
- // Using Sleep(0) can cause a priority inversion.
- // Sleep(0) only yields the processor if there's
- // another thread of the same priority that's
- // ready to run. If a high-priority thread is
- // trying to acquire the lock, which is held by
- // a low-priority thread, then the low-priority
- // thread may never get scheduled and hence never
- // free the lock. NT attempts to avoid priority
- // inversions by temporarily boosting the priority
- // of low-priority runnable threads, but the problem
- // can still occur if there's a medium-priority
- // thread that's always runnable. If Sleep(1) is used,
- // then the thread unconditionally yields the CPU. We
- // only do this for the second and subsequent even
- // iterations, since a millisecond is a long time to wait
- // if the thread can be scheduled in again sooner
- // (~100,000 instructions).
- // Avoid priority inversion: 0, 1, 0, 1,...
- Sleep(dwSleep);
- dwSleep = !dwSleep;
- }
- result = *dest ;
- if (result == comperand)
- *dest = exc ;
- /* Release spinlock */
- spinlock = 0 ;
- return result ;
-} ;
-
-static interlocked_cmp_xchg_t *ixchg ;
BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex)
{
- if (!ixchg)
- {
- /* Sorely, Win95 has no InterlockedCompareExchange API (Win98 has), so we have to use emulation */
- HANDLE kernel = GetModuleHandle("kernel32.dll") ;
- if (!kernel || (ixchg = (interlocked_cmp_xchg_t *)GetProcAddress(kernel, "InterlockedCompareExchange")) == NULL)
- ixchg = interlocked_cmp_xchg ;
- }
-
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
mutex->thread_id = 0 ;
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
}
-#ifdef InterlockedCompareExchange
-#undef InterlockedCompareExchange
-#endif
-#define InterlockedCompareExchange(dest,exchange,comperand) (ixchg((dest), (exchange), (comperand)))
-
VOID DeleteNonRecursiveMutex(PNRMUTEX mutex)
{
/* No in-use check */
@@ -208,7 +146,7 @@
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
if (!wait)
{
- if (InterlockedCompareExchange((PVOID *)&mutex->owned, (PVOID)0, (PVOID)-1) != (PVOID)-1)
+ if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
return WAIT_TIMEOUT ;
ret = WAIT_OBJECT_0 ;
}
Modified: pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/c/test/test_extfunc.py Thu Sep 10 16:45:13 2009
@@ -173,6 +173,19 @@
if has_blocks:
assert res[4] == os.stat(filename).st_blocks
+def test_os_stat_raises_winerror():
+ if sys.platform != 'win32':
+ py.test.skip("no WindowsError on this platform")
+ def call_stat():
+ try:
+ os.stat("nonexistentdir/nonexistentfile")
+ except WindowsError, e:
+ return e.winerror
+ f = compile(call_stat, [])
+ res = f()
+ expected = call_stat()
+ assert res == expected
+
def test_os_fstat():
if os.environ.get('PYPY_CC', '').startswith('tcc'):
py.test.skip("segfault with tcc :-(")
Modified: pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/cli/opcodes.py Thu Sep 10 16:45:13 2009
@@ -114,9 +114,8 @@
'ullong_is_true': [PushAllArgs, 'ldc.i8 0', 'cgt.un'],
'ullong_invert': 'not',
- # XXX: why nop nop nop?
- 'ooisnull': [PushAllArgs, 'nop', 'nop', 'nop', 'ldnull', 'ceq'],
- 'oononnull': [PushAllArgs, 'nop', 'nop', 'nop', 'nop', 'ldnull', 'ceq']+Not,
+ 'ooisnull': [PushAllArgs, 'ldnull', 'ceq'],
+ 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not,
# when casting from bool we want that every truth value is casted
# to 1: we can't simply DoNothing, because the CLI stack could
Modified: pypy/branch/spine-of-frames/pypy/translator/driver.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/driver.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/driver.py Thu Sep 10 16:45:13 2009
@@ -362,7 +362,7 @@
from pypy.jit.metainterp.warmspot import apply_jit
apply_jit(self.translator, policy=self.jitpolicy,
debug_level=self.config.translation.jit_debug,
- backend_name=self.config.translation.jit_backend)
+ backend_name=self.config.translation.jit_backend, inline=True)
#
self.log.info("the JIT compiler was generated")
#
Modified: pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/jvm/cmpopcodes.py Thu Sep 10 16:45:13 2009
@@ -1,6 +1,6 @@
from pypy.translator.jvm.typesystem import \
IFLT, IFLE, IFEQ, IFNE, IFGT, IFGE, \
- IFNONNULL, IF_ACMPEQ, GOTO, ICONST, \
+ IFNONNULL, IFNULL, IF_ACMPEQ, GOTO, ICONST, \
DCONST_0, DCMPG, LCONST_0, LCMP, \
IF_ICMPLT, IF_ICMPLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPGT, IF_ICMPGE, \
PYPYUINTCMP, PYPYULONGCMP
@@ -52,6 +52,7 @@
# Double operand entries:
'oononnull': [IFNONNULL],
+ 'ooisnull': [IFNULL],
'oois': [IF_ACMPEQ],
'unichar_eq': [IF_ICMPEQ],
Modified: pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/platform/__init__.py Thu Sep 10 16:45:13 2009
@@ -110,9 +110,9 @@
errorfile = outname.new(ext='errors')
errorfile.write(stderr)
stderrlines = stderr.splitlines()
- for line in stderrlines[:20]:
+ for line in stderrlines[:50]:
log.ERROR(line)
- if len(stderrlines) > 20:
+ if len(stderrlines) > 50:
log.ERROR('...')
raise CompilationError(stdout, stderr)
Modified: pypy/branch/spine-of-frames/pypy/translator/platform/posix.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/platform/posix.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/platform/posix.py Thu Sep 10 16:45:13 2009
@@ -121,6 +121,7 @@
def write(self, f):
def write_list(prefix, lst):
for i, fn in enumerate(lst):
+ fn = fn.replace('\\', '\\\\')
print >> f, prefix, fn,
if i < len(lst)-1:
print >> f, '\\'
@@ -129,7 +130,7 @@
prefix = ' ' * len(prefix)
name, value = self.name, self.value
if isinstance(value, str):
- f.write('%s = %s\n' % (name, value))
+ f.write('%s = %s\n' % (name, value.replace('\\', '\\\\')))
else:
write_list('%s =' % (name,), value)
if value:
@@ -171,7 +172,8 @@
if fpath.dirpath() == self.makefile_dir:
return fpath.basename
elif fpath.dirpath().dirpath() == self.makefile_dir.dirpath():
- return '../' + fpath.relto(self.makefile_dir.dirpath())
+ path = '../' + fpath.relto(self.makefile_dir.dirpath())
+ return path.replace('\\', '/')
else:
return str(fpath)
Modified: pypy/branch/spine-of-frames/pypy/translator/platform/windows.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/platform/windows.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/platform/windows.py Thu Sep 10 16:45:13 2009
@@ -281,4 +281,7 @@
def library_dirs_for_libffi(self):
return []
-
+ def _handle_error(self, returncode, stderr, stdout, outname):
+ # Mingw tools write compilation errors to stdout
+ super(MingwPlatform, self)._handle_error(
+ returncode, stderr + stdout, '', outname)
Modified: pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py (original)
+++ pypy/branch/spine-of-frames/pypy/translator/tool/cbuild.py Thu Sep 10 16:45:13 2009
@@ -249,6 +249,8 @@
f = filename.open("w")
if being_main:
f.write("#define PYPY_NOT_MAIN_FILE\n")
+ if sys.platform == 'win32':
+ f.write("#define WIN32_LEAN_AND_MEAN\n")
self.write_c_header(f)
source = str(source)
f.write(source)
More information about the Pypy-commit
mailing list