[pypy-svn] r34887 - in pypy/branch/mininal-c-backend/pypy: . annotation annotation/test config doc interpreter interpreter/astcompiler jit/codegen/i386 jit/codegen/i386/test jit/codegen/llgraph jit/codegen/llvm jit/codegen/llvm/lib jit/codegen/llvm/test jit/codegen/ppc jit/codegen/ppc/test jit/hintannotator jit/hintannotator/test jit/timeshifter jit/timeshifter/test jit/tl lang/automata lib lib/constraint lib/distributed lib/pyontology lib/pyontology/test lib/test2 module/__builtin__ module/__builtin__/test module/_file module/_file/test module/_stackless module/_stackless/test module/pypymagic module/pypymagic/test module/rctime/test objspace objspace/cclp objspace/std objspace/std/test rlib rlib/parsing/test rlib/test rpython rpython/lltypesystem rpython/memory/gctransform rpython/test tool/build translator translator/asm/ppcgen translator/backendopt translator/backendopt/test translator/cl translator/cli translator/cli/src translator/cli/test translator/js translator/js/demo/jsdemo translator/js/demo/jsdemo/test translator/js/doc translator/js/modules translator/js/modules/test translator/llvm translator/oosupport translator/test translator/tool
ale at codespeak.net
ale at codespeak.net
Thu Nov 23 12:29:25 CET 2006
Author: ale
Date: Thu Nov 23 12:28:43 2006
New Revision: 34887
Added:
pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/test/test_genc_ts.py
- copied unchanged from r34886, pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_vdict.py
- copied unchanged from r34886, pypy/dist/pypy/jit/timeshifter/test/test_vdict.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/vdict.py
- copied unchanged from r34886, pypy/dist/pypy/jit/timeshifter/vdict.py
pypy/branch/mininal-c-backend/pypy/lib/distributed/ (props changed)
- copied from r34886, pypy/dist/pypy/lib/distributed/
pypy/branch/mininal-c-backend/pypy/lib/distributed/__init__.py
- copied unchanged from r34886, pypy/dist/pypy/lib/distributed/__init__.py
pypy/branch/mininal-c-backend/pypy/lib/distributed/objkeeper.py
- copied unchanged from r34886, pypy/dist/pypy/lib/distributed/objkeeper.py
pypy/branch/mininal-c-backend/pypy/lib/distributed/protocol.py
- copied unchanged from r34886, pypy/dist/pypy/lib/distributed/protocol.py
pypy/branch/mininal-c-backend/pypy/module/_stackless/clonable.py (props changed)
- copied unchanged from r34886, pypy/dist/pypy/module/_stackless/clonable.py
pypy/branch/mininal-c-backend/pypy/module/_stackless/test/test_clonable.py
- copied unchanged from r34886, pypy/dist/pypy/module/_stackless/test/test_clonable.py
pypy/branch/mininal-c-backend/pypy/module/pypymagic/test/test_special.py
- copied unchanged from r34886, pypy/dist/pypy/module/pypymagic/test/test_special.py
pypy/branch/mininal-c-backend/pypy/rpython/controllerentry.py
- copied unchanged from r34886, pypy/dist/pypy/rpython/controllerentry.py
pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_streamio.py
- copied unchanged from r34885, pypy/dist/pypy/translator/cli/test/test_streamio.py
pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/support.py
- copied unchanged from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/support.py
pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/test/ (props changed)
- copied from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/test/
pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/test/__init__.py
- copied unchanged from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/test/__init__.py
pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/test/test_demo.py
- copied unchanged from r34885, pypy/dist/pypy/translator/js/demo/jsdemo/test/test_demo.py
Removed:
pypy/branch/mininal-c-backend/pypy/lib/_osfilewrapper.py
pypy/branch/mininal-c-backend/pypy/lib/distributed.py
pypy/branch/mininal-c-backend/pypy/lib/test2/test_osfilewrapper.py
pypy/branch/mininal-c-backend/pypy/module/__builtin__/test/test_special.py
Modified:
pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py
pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py
pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py
pypy/branch/mininal-c-backend/pypy/annotation/builtin.py
pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py
pypy/branch/mininal-c-backend/pypy/annotation/model.py
pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py
pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py
pypy/branch/mininal-c-backend/pypy/config/pypyoption.py
pypy/branch/mininal-c-backend/pypy/conftest.py
pypy/branch/mininal-c-backend/pypy/doc/_ref.txt
pypy/branch/mininal-c-backend/pypy/doc/stackless.txt
pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py
pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py
pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/ (props changed)
pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp
pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py
pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py
pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py
pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_promotion.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_timeshift.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_tlc.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/transform.py
pypy/branch/mininal-c-backend/pypy/jit/timeshifter/vlist.py
pypy/branch/mininal-c-backend/pypy/jit/tl/tlc.py
pypy/branch/mininal-c-backend/pypy/lang/automata/dfa.py
pypy/branch/mininal-c-backend/pypy/lib/constraint/ (props changed)
pypy/branch/mininal-c-backend/pypy/lib/pyontology/constraint_classes.py
pypy/branch/mininal-c-backend/pypy/lib/pyontology/pyontology.py
pypy/branch/mininal-c-backend/pypy/lib/pyontology/sparql_grammar.py (props changed)
pypy/branch/mininal-c-backend/pypy/lib/pyontology/test/test_ontology.py
pypy/branch/mininal-c-backend/pypy/lib/pyontology/test/test_sparql.py (contents, props changed)
pypy/branch/mininal-c-backend/pypy/lib/stackless.py
pypy/branch/mininal-c-backend/pypy/lib/test2/test_binascii.py (props changed)
pypy/branch/mininal-c-backend/pypy/lib/test2/test_distributed.py
pypy/branch/mininal-c-backend/pypy/module/__builtin__/__init__.py
pypy/branch/mininal-c-backend/pypy/module/__builtin__/importing.py
pypy/branch/mininal-c-backend/pypy/module/__builtin__/special.py
pypy/branch/mininal-c-backend/pypy/module/_file/app_file.py
pypy/branch/mininal-c-backend/pypy/module/_file/test/test_file.py
pypy/branch/mininal-c-backend/pypy/module/_stackless/__init__.py
pypy/branch/mininal-c-backend/pypy/module/_stackless/coroutine.py
pypy/branch/mininal-c-backend/pypy/module/_stackless/interp_clonable.py
pypy/branch/mininal-c-backend/pypy/module/_stackless/interp_greenlet.py
pypy/branch/mininal-c-backend/pypy/module/pypymagic/__init__.py
pypy/branch/mininal-c-backend/pypy/module/pypymagic/interp_magic.py
pypy/branch/mininal-c-backend/pypy/module/rctime/test/test_rctime.py
pypy/branch/mininal-c-backend/pypy/objspace/cclp/misc.py
pypy/branch/mininal-c-backend/pypy/objspace/logic.py
pypy/branch/mininal-c-backend/pypy/objspace/std/multimethod.py
pypy/branch/mininal-c-backend/pypy/objspace/std/objspace.py
pypy/branch/mininal-c-backend/pypy/objspace/std/proxyobject.py
pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_multimethod.py
pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_proxy.py
pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_proxy_function.py
pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_proxy_internals.py
pypy/branch/mininal-c-backend/pypy/objspace/std/test/test_strjoinobject.py
pypy/branch/mininal-c-backend/pypy/objspace/std/transparent.py
pypy/branch/mininal-c-backend/pypy/rlib/objectmodel.py
pypy/branch/mininal-c-backend/pypy/rlib/parsing/test/test_ebnfparse.py
pypy/branch/mininal-c-backend/pypy/rlib/streamio.py
pypy/branch/mininal-c-backend/pypy/rlib/test/test_streamio.py
pypy/branch/mininal-c-backend/pypy/rpython/annlowlevel.py
pypy/branch/mininal-c-backend/pypy/rpython/callparse.py
pypy/branch/mininal-c-backend/pypy/rpython/llinterp.py
pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/opimpl.py
pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rdict.py
pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rlist.py
pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rstr.py
pypy/branch/mininal-c-backend/pypy/rpython/lltypesystem/rtupletype.py
pypy/branch/mininal-c-backend/pypy/rpython/memory/gctransform/framework.py
pypy/branch/mininal-c-backend/pypy/rpython/memory/gctransform/transform.py
pypy/branch/mininal-c-backend/pypy/rpython/rbuiltin.py
pypy/branch/mininal-c-backend/pypy/rpython/rint.py
pypy/branch/mininal-c-backend/pypy/rpython/rlist.py
pypy/branch/mininal-c-backend/pypy/rpython/rpbc.py
pypy/branch/mininal-c-backend/pypy/rpython/rtuple.py
pypy/branch/mininal-c-backend/pypy/rpython/test/test_rpbc.py
pypy/branch/mininal-c-backend/pypy/rpython/test/test_rtuple.py
pypy/branch/mininal-c-backend/pypy/tool/build/README.txt
pypy/branch/mininal-c-backend/pypy/translator/asm/ppcgen/ppc_assembler.py
pypy/branch/mininal-c-backend/pypy/translator/backendopt/all.py
pypy/branch/mininal-c-backend/pypy/translator/backendopt/graphanalyze.py
pypy/branch/mininal-c-backend/pypy/translator/backendopt/inline.py
pypy/branch/mininal-c-backend/pypy/translator/backendopt/test/test_inline.py
pypy/branch/mininal-c-backend/pypy/translator/cl/opformatter.py
pypy/branch/mininal-c-backend/pypy/translator/cli/constant.py
pypy/branch/mininal-c-backend/pypy/translator/cli/database.py
pypy/branch/mininal-c-backend/pypy/translator/cli/dotnet.py
pypy/branch/mininal-c-backend/pypy/translator/cli/function.py
pypy/branch/mininal-c-backend/pypy/translator/cli/ilgenerator.py
pypy/branch/mininal-c-backend/pypy/translator/cli/src/pypylib.cs
pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_constant.py
pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_dict.py
pypy/branch/mininal-c-backend/pypy/translator/cli/test/test_dotnet.py
pypy/branch/mininal-c-backend/pypy/translator/interactive.py
pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/example.py
pypy/branch/mininal-c-backend/pypy/translator/js/demo/jsdemo/pythonconsole.py
pypy/branch/mininal-c-backend/pypy/translator/js/doc/dom.txt
pypy/branch/mininal-c-backend/pypy/translator/js/modules/dom.py
pypy/branch/mininal-c-backend/pypy/translator/js/modules/test/test_dom.py
pypy/branch/mininal-c-backend/pypy/translator/js/opcodes.py
pypy/branch/mininal-c-backend/pypy/translator/llvm/opwriter.py
pypy/branch/mininal-c-backend/pypy/translator/oosupport/constant.py
pypy/branch/mininal-c-backend/pypy/translator/test/test_interactive.py
pypy/branch/mininal-c-backend/pypy/translator/tool/cbuild.py
pypy/branch/mininal-c-backend/pypy/translator/tool/pdbplus.py
Log:
svn merge -r 34627:HEAD to branch
Modified: pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/annrpython.py Thu Nov 23 12:28:43 2006
@@ -564,6 +564,10 @@
# later by reflowing). Throw the BlockedInference up to
# processblock().
raise
+
+ except annmodel.HarmlesslyBlocked:
+ return
+
else:
# dead code removal: don't follow all exits if the exitswitch
# is known
Modified: pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/binaryop.py Thu Nov 23 12:28:43 2006
@@ -5,7 +5,7 @@
import py
import operator
from pypy.annotation.pairtype import pair, pairtype
-from pypy.annotation.model import SomeObject, SomeInteger, SomeBool
+from pypy.annotation.model import SomeObject, SomeInteger, SomeBool, s_Bool
from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict
from pypy.annotation.model import SomeUnicodeCodePoint
from pypy.annotation.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
@@ -112,42 +112,42 @@
return immutablevalue(obj1.const < obj2.const)
else:
getbookkeeper().count("non_int_comp", obj1, obj2)
- return SomeBool()
+ return s_Bool
def le((obj1, obj2)):
if obj1.is_immutable_constant() and obj2.is_immutable_constant():
return immutablevalue(obj1.const <= obj2.const)
else:
getbookkeeper().count("non_int_comp", obj1, obj2)
- return SomeBool()
+ return s_Bool
def eq((obj1, obj2)):
if obj1.is_immutable_constant() and obj2.is_immutable_constant():
return immutablevalue(obj1.const == obj2.const)
else:
getbookkeeper().count("non_int_eq", obj1, obj2)
- return SomeBool()
+ return s_Bool
def ne((obj1, obj2)):
if obj1.is_immutable_constant() and obj2.is_immutable_constant():
return immutablevalue(obj1.const != obj2.const)
else:
getbookkeeper().count("non_int_eq", obj1, obj2)
- return SomeBool()
+ return s_Bool
def gt((obj1, obj2)):
if obj1.is_immutable_constant() and obj2.is_immutable_constant():
return immutablevalue(obj1.const > obj2.const)
else:
getbookkeeper().count("non_int_comp", obj1, obj2)
- return SomeBool()
+ return s_Bool
def ge((obj1, obj2)):
if obj1.is_immutable_constant() and obj2.is_immutable_constant():
return immutablevalue(obj1.const >= obj2.const)
else:
getbookkeeper().count("non_int_comp", obj1, obj2)
- return SomeBool()
+ return s_Bool
def cmp((obj1, obj2)):
getbookkeeper().count("cmp", obj1, obj2)
@@ -270,16 +270,15 @@
pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])
def _compare_helper((int1, int2), opname, operation):
+ r = SomeBool()
if int1.is_immutable_constant() and int2.is_immutable_constant():
- r = immutablevalue(operation(int1.const, int2.const))
+ r.const = operation(int1.const, int2.const)
else:
# XXX VERY temporary hack
if (opname == 'ge' and int2.is_immutable_constant() and
int2.const == 0 and
not rarithmetic.signedtype(int1.knowntype)):
- r = immutablevalue(True)
- else:
- r = SomeBool()
+ r.const = True
knowntypedata = {}
# XXX HACK HACK HACK
# propagate nonneg information between the two arguments
@@ -335,6 +334,36 @@
s.knowntypedata = ktd
return s
+ def and_((boo1, boo2)):
+ s = SomeBool()
+ if boo1.is_constant():
+ if not boo1.const:
+ s.const = False
+ else:
+ return boo2
+ if boo2.is_constant():
+ if not boo2.const:
+ s.const = False
+ return s
+
+ def or_((boo1, boo2)):
+ s = SomeBool()
+ if boo1.is_constant():
+ if boo1.const:
+ s.const = True
+ else:
+ return boo2
+ if boo2.is_constant():
+ if boo2.const:
+ s.const = True
+ return s
+
+ def xor((boo1, boo2)):
+ s = SomeBool()
+ if boo1.is_constant() and boo2.is_constant():
+ s.const = boo1.const ^ boo2.const
+ return s
+
class __extend__(pairtype(SomeString, SomeString)):
def union((str1, str2)):
@@ -386,7 +415,7 @@
def eq((lst1, lst2)):
lst1.listdef.agree(lst2.listdef)
- return SomeBool()
+ return s_Bool
ne = eq
Modified: pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/bookkeeper.py Thu Nov 23 12:28:43 2006
@@ -247,6 +247,8 @@
def consider_call_site_for_pbc(self, s_callable, opname, args_s, s_result):
descs = s_callable.descriptions.keys()
+ if not descs:
+ return
family = descs[0].getcallfamily()
args = self.build_args(opname, args_s)
s_callable.getKind().consider_call_site(self, family, descs, args,
Modified: pypy/branch/mininal-c-backend/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/builtin.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/builtin.py Thu Nov 23 12:28:43 2006
@@ -4,13 +4,13 @@
import sys
from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool
-from pypy.annotation.model import SomeString, SomeTuple, SomeSlice
+from pypy.annotation.model import SomeString, SomeTuple, SomeSlice, s_Bool
from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress
from pypy.annotation.model import SomeFloat, SomeWeakGcAddress, unionof
from pypy.annotation.model import SomePBC, SomeInstance, SomeDict
from pypy.annotation.model import SomeExternalObject
from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation
-from pypy.annotation.model import add_knowntypedata
+from pypy.annotation.model import add_knowntypedata, not_const
from pypy.annotation.model import s_ImpossibleValue
from pypy.annotation.bookkeeper import getbookkeeper
from pypy.annotation import description
@@ -299,7 +299,7 @@
return immutablevalue(None)
def robjmodel_hint(s, **kwds_s):
- return s
+ return not_const(s)
def llmemory_cast_ptr_to_adr(s):
return SomeAddress()
@@ -339,7 +339,7 @@
raise TypeError, "unicodedate.decimal() calls should not happen at interp-level"
def test(*args):
- return SomeBool()
+ return s_Bool
def import_func(*args):
return SomeObject()
@@ -517,7 +517,7 @@
def instanceof(i, I):
assert I.is_constant()
assert isinstance(I.const, ootype.Instance)
- return SomeBool()
+ return s_Bool
def classof(i):
assert isinstance(i, SomeOOInstance)
@@ -526,7 +526,7 @@
def subclassof(class1, class2):
assert isinstance(class1, SomeOOClass)
assert isinstance(class2, SomeOOClass)
- return SomeBool()
+ return s_Bool
def runtimenew(c):
assert isinstance(c, SomeOOClass)
Modified: pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/dictdef.py Thu Nov 23 12:28:43 2006
@@ -1,5 +1,5 @@
from pypy.annotation.model import SomeObject, s_ImpossibleValue
-from pypy.annotation.model import SomeInteger, SomeBool, unionof
+from pypy.annotation.model import SomeInteger, s_Bool, unionof
from pypy.annotation.model import SomeInstance
from pypy.annotation.listdef import ListItem
@@ -62,7 +62,7 @@
def check_eqfn(annotator, graph):
s = annotator.binding(graph.getreturnvar())
- assert SomeBool().contains(s), (
+ assert s_Bool.contains(s), (
"the custom eq function of an r_dict must return a boolean"
" (got %r)" % (s,))
self.bookkeeper.emulate_pbc_call(myeq, self.s_rdict_eqfn, [s_key, s_key],
Modified: pypy/branch/mininal-c-backend/pypy/annotation/model.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/model.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/model.py Thu Nov 23 12:28:43 2006
@@ -474,6 +474,7 @@
s_None = SomePBC([], can_be_None=True)
+s_Bool = SomeBool()
s_ImpossibleValue = SomeImpossibleValue()
# ____________________________________________________________
@@ -549,7 +550,7 @@
NUMBER = object()
annotation_to_ll_map = [
(s_None, lltype.Void), # also matches SomeImpossibleValue()
- (SomeBool(), lltype.Bool),
+ (s_Bool, lltype.Bool),
(SomeInteger(knowntype=r_ulonglong), NUMBER),
(SomeFloat(), lltype.Float),
(SomeChar(), lltype.Char),
@@ -658,6 +659,18 @@
r[truth_v] = unionof(ktd1[truth_v], ktd2[truth_v])
return r
+def not_const(s_obj):
+ if s_obj.is_constant():
+ new_s_obj = SomeObject()
+ new_s_obj.__class__ = s_obj.__class__
+ dic = new_s_obj.__dict__ = s_obj.__dict__.copy()
+ if 'const' in dic:
+ del new_s_obj.const
+ else:
+ del new_s_obj.const_box
+ s_obj = new_s_obj
+ return s_obj
+
# ____________________________________________________________
# internal
@@ -700,6 +713,11 @@
return s_ImpossibleValue
setattr(cls, name, default_op)
+class HarmlesslyBlocked(Exception):
+ """Raised by the unaryop/binaryop to signal a harmless kind of
+ BlockedInference: the current block is blocked, but not in a way
+ that gives 'Blocked block' errors at the end of annotation."""
+
#
# safety check that no-one is trying to make annotation and translation
# faster by providing the -O option to Python.
Modified: pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/test/test_annrpython.py Thu Nov 23 12:28:43 2006
@@ -1,9 +1,11 @@
import autopath
import py.test
+from pypy import conftest
from pypy.tool.udir import udir
-from pypy.annotation.annrpython import annmodel
+from pypy.annotation import model as annmodel
+from pypy.annotation.annrpython import RPythonAnnotator as _RPythonAnnotator
from pypy.translator.translator import graphof as tgraphof
from pypy.annotation import policy
from pypy.annotation import specialize
@@ -42,7 +44,15 @@
def setup_class(cls):
cls.space = FlowObjSpace()
- from pypy.annotation.annrpython import RPythonAnnotator
+ def teardown_method(self, meth):
+ assert annmodel.s_Bool == annmodel.SomeBool()
+
+ class RPythonAnnotator(_RPythonAnnotator):
+ def build_types(self, *args):
+ s = _RPythonAnnotator.build_types(self, *args)
+ if conftest.option.view:
+ self.translator.view()
+ return s
def make_fun(self, func):
import inspect
@@ -55,11 +65,6 @@
funcgraph.source = inspect.getsource(func)
return funcgraph
- def show(self, a):
- from pypy import conftest
- if conftest.option.view:
- a.translator.view()
-
def test_simple_func(self):
"""
one test source:
@@ -2293,7 +2298,6 @@
a = self.RPythonAnnotator()
a.build_types(f, [])
- self.show(a)
v1, v2 = graphof(a, readout).getargs()
assert not a.bindings[v1].is_constant()
assert not a.bindings[v2].is_constant()
@@ -2323,7 +2327,6 @@
a = self.RPythonAnnotator()
s = a.build_types(fun, [int])
- self.show(a)
assert isinstance(s, annmodel.SomeChar)
def test_range_nonneg(self):
@@ -2334,7 +2337,6 @@
return 0
a = self.RPythonAnnotator()
s = a.build_types(fun, [int, int])
- self.show(a)
assert isinstance(s, annmodel.SomeInteger)
assert s.nonneg
@@ -2346,7 +2348,6 @@
return 0
a = self.RPythonAnnotator()
s = a.build_types(fun, [int, int])
- self.show(a)
assert isinstance(s, annmodel.SomeInteger)
assert s.nonneg
@@ -2403,6 +2404,40 @@
from pypy.annotation.classdef import NoSuchSlotError
py.test.raises(NoSuchSlotError, a.build_types, fun, [int])
+
+ def test_simple_controllerentry(self):
+ from pypy.rpython.controllerentry import Controller, ControllerEntry
+
+ class C:
+ "Imagine some magic here to have a foo attribute on instances"
+
+ def fun():
+ lst = []
+ c = C()
+ c.foo = lst # side-effect on lst! well, it's a test
+ return c.foo, lst[0]
+
+ class C_Controller(Controller):
+ knowntype = C
+
+ def new(self):
+ return "4"
+
+ def get_foo(self, obj):
+ return obj + "2"
+
+ def set_foo(self, obj, value):
+ value.append(obj)
+
+ class Entry(ControllerEntry):
+ _about_ = C
+ _controller_ = C_Controller
+
+ a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy())
+ s = a.build_types(fun, [])
+ assert s.const == ("42", "4")
+
+
def g(n):
return [0,1,2,n]
Modified: pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py (original)
+++ pypy/branch/mininal-c-backend/pypy/annotation/unaryop.py Thu Nov 23 12:28:43 2006
@@ -7,8 +7,8 @@
SomeDict, SomeUnicodeCodePoint, SomeTuple, SomeImpossibleValue, \
SomeInstance, SomeBuiltin, SomeFloat, SomeIterator, SomePBC, \
SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \
- SomeCTypesObject, s_ImpossibleValue, \
- unionof, set, missing_operation, add_knowntypedata
+ SomeCTypesObject, s_ImpossibleValue, s_Bool, \
+ unionof, set, missing_operation, add_knowntypedata, HarmlesslyBlocked
from pypy.annotation.bookkeeper import getbookkeeper
from pypy.annotation import builtin
from pypy.annotation.binaryop import _clone ## XXX where to put this?
@@ -60,24 +60,22 @@
s_cls, vars)
if obj.is_constant() and s_cls.is_constant():
return immutablevalue(issubclass(obj.const, s_cls.const))
- return SomeBool()
+ return s_Bool
def len(obj):
return SomeInteger(nonneg=True)
- def is_true_behavior(obj):
+ def is_true_behavior(obj, s):
if obj.is_immutable_constant():
- return immutablevalue(bool(obj.const))
+ s.const = bool(obj.const)
else:
s_len = obj.len()
if s_len.is_immutable_constant():
- return immutablevalue(s_len.const > 0)
- else:
- return SomeBool()
+ s.const = s_len.const > 0
def is_true(s_obj):
- r = s_obj.is_true_behavior()
- assert isinstance(r, SomeBool)
+ r = SomeBool()
+ s_obj.is_true_behavior(r)
bk = getbookkeeper()
knowntypedata = r.knowntypedata = {}
@@ -174,7 +172,7 @@
return SomeObject()
def op_contains(obj, s_element):
- return SomeBool()
+ return s_Bool
def hint(self, *args_s):
return self
@@ -192,7 +190,7 @@
def is_true(self):
if self.is_immutable_constant():
return getbookkeeper().immutablevalue(bool(self.const))
- return SomeBool()
+ return s_Bool
def hash(flt):
return SomeInteger()
@@ -318,7 +316,7 @@
def op_contains(lst, s_element):
lst.listdef.generalize(s_element)
- return SomeBool()
+ return s_Bool
def hint(lst, *args_s):
hints = args_s[-1].const
@@ -399,16 +397,16 @@
def op_contains(dct, s_element):
dct.dictdef.generalize_key(s_element)
- return SomeBool()
+ return s_Bool
class __extend__(SomeString):
def method_startswith(str, frag):
- return SomeBool()
+ return s_Bool
def method_endswith(str, frag):
- return SomeBool()
+ return s_Bool
def method_find(str, frag, start=None, end=None):
return SomeInteger()
@@ -468,22 +466,22 @@
return immutablevalue(1)
def method_isspace(chr):
- return SomeBool()
+ return s_Bool
def method_isdigit(chr):
- return SomeBool()
+ return s_Bool
def method_isalpha(chr):
- return SomeBool()
+ return s_Bool
def method_isalnum(chr):
- return SomeBool()
+ return s_Bool
def method_islower(chr):
- return SomeBool()
+ return s_Bool
def method_isupper(chr):
- return SomeBool()
+ return s_Bool
class __extend__(SomeUnicodeCodePoint):
@@ -526,6 +524,9 @@
s_result = ins.classdef.lookup_filter(s_result, attr)
elif isinstance(s_result, SomeImpossibleValue):
ins.classdef.check_missing_attribute_update(attr)
+ if ins.classdef.classdesc.allslots is not None:
+ if attr in ins.classdef.classdesc.allslots:
+ raise HarmlesslyBlocked("getattr on a slot")
return s_result
return SomeObject()
getattr.can_only_throw = []
@@ -548,11 +549,9 @@
getbookkeeper().needs_hash_support[ins.classdef] = True
return SomeInteger()
- def is_true_behavior(ins):
- if ins.can_be_None:
- return SomeBool()
- else:
- return immutablevalue(True)
+ def is_true_behavior(ins, s):
+ if not ins.can_be_None:
+ s.const = True
class __extend__(SomeBuiltin):
@@ -594,13 +593,11 @@
d = [desc.bind_under(classdef, name) for desc in pbc.descriptions]
return SomePBC(d, can_be_None=pbc.can_be_None)
- def is_true_behavior(pbc):
+ def is_true_behavior(pbc, s):
if pbc.isNone():
- return immutablevalue(False)
- elif pbc.can_be_None:
- return SomeBool()
- else:
- return immutablevalue(True)
+ s.const = False
+ elif not pbc.can_be_None:
+ s.const = True
class __extend__(SomeExternalObject):
@@ -649,7 +646,7 @@
return ll_to_annotation(v)
def is_true(p):
- return SomeBool()
+ return s_Bool
class __extend__(SomeExternalBuiltin):
def getattr(p, s_attr):
@@ -680,7 +677,7 @@
return obj.knowntype.get_field(name)
def is_true(p):
- return SomeBool()
+ return s_Bool
class __extend__(SomeLLADTMeth):
@@ -706,7 +703,7 @@
setattr(r.ootype._example(), s_attr.const, v._example())
def is_true(p):
- return SomeBool()
+ return s_Bool
class __extend__(SomeOOBoundMeth):
def simple_call(m, *args_s):
@@ -739,7 +736,7 @@
return SomeObject()
def is_true(cto):
- return SomeBool()
+ return s_Bool
def simple_call(cto, *args_s):
# for variables containing ctypes function pointers
@@ -761,4 +758,4 @@
getattr.can_only_throw = []
def is_true(s_addr):
- return SomeBool()
+ return s_Bool
Modified: pypy/branch/mininal-c-backend/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/config/pypyoption.py (original)
+++ pypy/branch/mininal-c-backend/pypy/config/pypyoption.py Thu Nov 23 12:28:43 2006
@@ -1,6 +1,6 @@
import autopath
import py, os
-from pypy.config.config import OptionDescription, BoolOption, IntOption
+from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption
from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config
modulepath = py.magic.autopath().dirpath().dirpath().join("module")
@@ -58,6 +58,9 @@
BoolOption("logbytecodes",
"keep track of bytecode usage",
default=False),
+
+ BoolOption("usepycfiles", "Write and read pyc files when importing",
+ default=True),
OptionDescription("std", "Standard Object Space Options", [
BoolOption("withtproxy", "support transparent proxies",
@@ -159,6 +162,12 @@
BoolOption("debug_transform", "Perform the debug transformation",
default=False, cmdline="--debug-transform", negation=False),
+ BoolOption("instrument", "internal: turn instrumentation on",
+ default=False, cmdline=None),
+
+ ArbitraryOption("instrumentctl", "internal",
+ default=None),
+
# portability options
BoolOption("vanilla",
"Try to be as portable as possible, which is not much",
@@ -203,6 +212,10 @@
"optimizer remove the asserts", default=False),
IntOption("inline_threshold", "Threshold when to inline functions",
default=1, cmdline=None),
+ StrOption("profile_based_inline",
+ "Use call count profiling to drive inlining"
+ ", specify arguments",
+ default=None, cmdline="--prof-based-inline"),
]),
OptionDescription("cli", "GenCLI options", [
Modified: pypy/branch/mininal-c-backend/pypy/conftest.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/conftest.py (original)
+++ pypy/branch/mininal-c-backend/pypy/conftest.py Thu Nov 23 12:28:43 2006
@@ -113,6 +113,9 @@
def unpackiterable(self, itr):
return list(itr)
+ def is_true(self, obj):
+ return bool(obj)
+
class OpErrKeyboardInterrupt(KeyboardInterrupt):
pass
Modified: pypy/branch/mininal-c-backend/pypy/doc/_ref.txt
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/doc/_ref.txt (original)
+++ pypy/branch/mininal-c-backend/pypy/doc/_ref.txt Thu Nov 23 12:28:43 2006
@@ -1,4 +1,5 @@
.. _`demo/`: ../../demo
+.. _`demo/pickle_coroutine.py`: ../../demo/pickle_coroutine.py
.. _`lib-python/`: ../../lib-python
.. _`lib-python/2.4.1/dis.py`: ../../lib-python/2.4.1/dis.py
.. _`annotation/`:
@@ -48,7 +49,10 @@
.. _`objspace/thunk.py`: ../../pypy/objspace/thunk.py
.. _`objspace/trace.py`:
.. _`pypy/objspace/trace.py`: ../../pypy/objspace/trace.py
+.. _`pypy/rlib`: ../../pypy/rlib
.. _`pypy/rlib/objectmodel.py`: ../../pypy/rlib/objectmodel.py
+.. _`pypy/rlib/rarithmetic.py`: ../../pypy/rlib/rarithmetic.py
+.. _`pypy/rlib/test`: ../../pypy/rlib/test
.. _`pypy/rpython`:
.. _`pypy/rpython/`:
.. _`rpython/`: ../../pypy/rpython
Modified: pypy/branch/mininal-c-backend/pypy/doc/stackless.txt
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/doc/stackless.txt (original)
+++ pypy/branch/mininal-c-backend/pypy/doc/stackless.txt Thu Nov 23 12:28:43 2006
@@ -112,6 +112,42 @@
catch it, and that ``try: finally:`` clauses are not honored. This
will be fixed in the future.)
+Example
+~~~~~~~
+
+Here is a classical producer/consumer example: an algorithm computes a
+sequence of values, while another consumes them. For our purposes we
+assume that the producer can generate several values at once, and the
+consumer can process up to 3 values in a batch - it can also process
+batches with less than 3 values without waiting for the producer (which
+would be messy to express with a classical Python generator). ::
+
+ def producer(lst):
+ while True:
+ ...compute some more values...
+ lst.extend(new_values)
+ coro_consumer.switch()
+
+ def consumer(lst):
+ while True:
+ # First ask the producer for more values if needed
+ while len(lst) == 0:
+ coro_producer.switch()
+ # Process the available values in a batch, but at most 3
+ batch = lst[:3]
+ del lst[:3]
+ ...process batch...
+
+ # Initialize two coroutines with a shared list as argument
+ exchangelst = []
+ coro_producer = coroutine()
+ coro_producer.bind(producer, exchangelst)
+ coro_consumer = coroutine()
+ coro_consumer.bind(consumer, exchangelst)
+
+ # Start running the consumer coroutine
+ coro_consumer.switch()
+
Tasklets and channels
+++++++++++++++++++++
@@ -135,7 +171,7 @@
as possible. This makes the code somewhat unpythonic.
Bird's eye view of tasklets and channels
-----------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tasklets are a bit like threads: they encapsulate a function in such a way that
they can be suspended/restarted any time. Unlike threads, they won't
@@ -158,6 +194,44 @@
is removed from the scheduling queue and will be reinserted when it
becomes unblocked.
+Example
+~~~~~~~
+
+Here is a many-producers many-consumers example, where any consumer can
+process the result of any producer. For this situation we set up a
+single channel where all producer send, and on which all consumers
+wait::
+
+ def producer(chan):
+ while True:
+ chan.send(...next value...)
+
+ def consumer(chan):
+ while True:
+ x = chan.receive()
+ ...do something with x...
+
+ # Set up the N producer and M consumer tasklets
+ common_channel = stackless.channel()
+ for i in range(N):
+ stackless.tasklet(producer, common_channel)()
+ for i in range(M):
+ stackless.tasklet(consumer, common_channel)()
+
+ # Run it all
+ stackless.run()
+
+Each item sent over the channel is received by one of the waiting
+consumers; which one is not specified. The producers block until their
+item is consumed: the channel is not a queue, but rather a meeting point
+which causes tasklets to block until both a consumer and a producer are
+ready. In practice, the reason for having several consumers receiving
+on a single channel is that some of the consumers can be busy in other
+ways part of the time. For example, each consumer might receive a
+database request, process it, and send the result to a further channel
+before it asks for the next request. In this situation, further
+requests can still be received by other consumers.
+
Greenlets
+++++++++
@@ -169,8 +243,14 @@
precise tree, which fully determines their order of execution.
For usage reference, see the documentation of the `Py lib greenlets`_.
-The PyPy interface is identical, except that the ``greenlet`` class is
-in the ``stackless`` module instead of in the ``py.magic`` module.
+The PyPy interface is identical. You should use ``py.magic.greenlet``
+instead of ``stackless.greenlet`` directly, because the Py lib can now
+give you the latter when you ask for the former on top of PyPy.
+
+PyPy's greenlets do not suffer from the cyclic GC limitation that the
+CPython greenlets have: greenlets referencing each other via local
+variables tend to leak on top of CPython (where it is mostly impossible
+to do the right thing). It works correctly on top of PyPy.
Coroutine Pickling
@@ -222,7 +302,99 @@
interface that allows an RPython program to artifically rebuild a chain
of calls in a reflective way, completely from scratch, and jump to it.
-XXX examples, limitations?
+Example
+~~~~~~~
+
+(See `demo/pickle_coroutine.py`_ for the complete source of this demo.)
+
+Consider a program which contains a part performing a long-running
+computation::
+
+ def ackermann(x, y):
+ if x == 0:
+ return y + 1
+ if y == 0:
+ return ackermann(x - 1, 1)
+ return ackermann(x - 1, ackermann(x, y - 1))
+
+By using pickling, we can save the state of the computation while it is
+running, for the purpose of restoring it later and continuing the
+computation at another time or on a different machine. However,
+pickling does not produce a whole-program dump: it can only pickle
+individual coroutines. This means that the computation should be
+started in its own coroutine::
+
+ # Make a coroutine that will run 'ackermann(3, 8)'
+ coro = coroutine()
+ coro.bind(ackermann, 3, 8)
+
+ # Now start running the coroutine
+ result = coro.switch()
+
+The coroutine itself must switch back to the main program when it needs
+to be interrupted (we can only pickle suspended coroutines). Due to
+current limitations this requires an explicit check in the
+``ackermann()`` function::
+
+ def ackermann(x, y):
+ if interrupt_flag: # test a global flag
+ main.switch() # and switch back to 'main' if it is set
+ if x == 0:
+ return y + 1
+ if y == 0:
+ return ackermann(x - 1, 1)
+ return ackermann(x - 1, ackermann(x, y - 1))
+
+The global ``interrupt_flag`` would be set for example by a timeout, or
+by a signal handler reacting to Ctrl-C, etc. It causes the coroutine to
+transfer control back to the main program. The execution comes back
+just after the line ``coro.switch()``, where we can pickle the coroutine
+if necessary::
+
+ if not coro.is_alive:
+ print "finished; the result is:", result
+ else:
+ # save the state of the suspended coroutine
+ f = open('demo.pickle', 'w')
+ pickle.dump(coro, f)
+ f.close()
+
+The process can then stop. At any later time, or on another machine,
+we can reload the file and restart the coroutine with::
+
+ f = open('demo.pickle', 'r')
+ coro = pickle.load(f)
+ f.close()
+ result = coro.switch()
+
+Limitations
+~~~~~~~~~~~
+
+Coroutine pickling is subject to some limitations. First of all, it is
+not a whole-program "memory dump". It means that only the "local" state
+of a coroutine is saved. The local state is defined to include the
+chain of calls and the local variables, but not for example the value of
+any global variable.
+
+As in normal Python, the pickle will not include any function object's
+code, any class definition, etc., but only references to functions and
+classes. Unlike normal Python, the pickle contains frames. A pickled
+frame stores a bytecode index, representing the current execution
+position. This means that the user program cannot be modified *at all*
+between pickling and unpickling!
+
+On the other hand, the pickled data is fairly independent from the
+platform and from the PyPy version.
+
+Pickling/unpickling fails if the coroutine is suspended in a state that
+involves Python frames which were *indirectly* called. To define this
+more precisely, a Python function can issue a regular function or method
+call to invoke another Python function - this is a *direct* call and can
+be pickled and unpickled. But there are many ways to invoke a Python
+function indirectly. For example, most operators can invoke a special
+method ``__xyz__()`` on a class, various built-in functions can call
+back Python functions, signals can invoke signal handlers, and so on.
+These cases are not supported yet.
Coroutine Cloning
@@ -413,9 +585,34 @@
...generators_view.getcurrent()...
-Then the composition ``grab_values()`` works as expected.
-
-XXX a few words about how
+Then the composition ``grab_values()`` works as expected, because the
+two views are independent. The coroutine captured as ``self.caller`` in
+the ``generator_iterator.next()`` method is the main coroutine of the
+``generators_view``. It is no longer the same object as the main
+coroutine of the ``producer_view``, so when ``data_producer()`` issues
+the following command::
+
+ main_coro.switch()
+
+the control flow cannot accidentally jump back to
+``generator_iterator.next()``. In other words, from the point of view
+of ``producer_view``, the function ``grab_next_value()`` always runs in
+its main coroutine ``main_coro`` and the function ``data_producer`` in
+its coroutine ``producer_coro``. This is the case independently of
+which ``generators_view``-based coroutine is the current one when
+``grab_next_value()`` is called.
+
+Only code that has explicit access to the ``producer_view`` or its
+coroutine objects can perform switches that are relevant for the
+generator code. If the view object and the coroutine objects that share
+this view are all properly encapsulated inside the generator logic, no
+external code can accidentally temper with the expected control flow any
+longer.
+
+In conclusion: we will probably change the app-level interface of PyPy's
+stackless module in the future to not expose coroutines and greenlets at
+all, but only views. They are not much more difficult to use, and they
+scale automatically to larger programs.
.. _`Stackless Python`: http://www.stackless.com
Modified: pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py (original)
+++ pypy/branch/mininal-c-backend/pypy/interpreter/astcompiler/pycodegen.py Thu Nov 23 12:28:43 2006
@@ -137,6 +137,8 @@
"""Defines basic code generator for Python bytecode
"""
+ localsfullyknown = False
+
def __init__(self, space, graph):
self.space = space
self.setups = []
Modified: pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/mininal-c-backend/pypy/interpreter/executioncontext.py Thu Nov 23 12:28:43 2006
@@ -38,45 +38,41 @@
if not frame.hide():
self.framestack.pop()
- # coroutine: subcontext support
- def subcontext_new(coobj):
- coobj.framestack = new_framestack()
- coobj.w_tracefunc = None
- coobj.w_profilefunc = None
- coobj.is_tracing = 0
- subcontext_new = staticmethod(subcontext_new)
-
- def subcontext_enter(self, next):
- self.framestack = next.framestack
- self.w_tracefunc = next.w_tracefunc
- self.w_profilefunc = next.w_profilefunc
- self.is_tracing = next.is_tracing
-
- def subcontext_leave(self, current):
- current.framestack = self.framestack
- current.w_tracefunc = self.w_tracefunc
- current.w_profilefunc = self.w_profilefunc
- current.is_tracing = self.is_tracing
-
- # coroutine: I think this is all, folks!
-
- # well, not quite: we need an interface for pickling
- def subcontext_getstate(coobj):
- # we just save the framestack
- space = coobj.space
- items = [space.wrap(item) for item in coobj.framestack.items]
- return space.newtuple(items)
- subcontext_getstate = staticmethod(subcontext_getstate)
-
- def subcontext_setstate(coobj, w_state):
- from pypy.interpreter.pyframe import PyFrame
- space = coobj.space
- items = [space.interp_w(PyFrame, item)
- for item in space.unpackiterable(w_state)]
- coobj.framestack.items = items
- subcontext_setstate = staticmethod(subcontext_setstate)
- # coroutine: now I really I think this is all, folks!
+ class Subcontext(object):
+ # coroutine: subcontext support
+
+ def __init__(self):
+ self.framestack = new_framestack()
+ self.w_tracefunc = None
+ self.w_profilefunc = None
+ self.is_tracing = 0
+
+ def enter(self, ec):
+ ec.framestack = self.framestack
+ ec.w_tracefunc = self.w_tracefunc
+ ec.w_profilefunc = self.w_profilefunc
+ ec.is_tracing = self.is_tracing
+
+ def leave(self, ec):
+ self.framestack = ec.framestack
+ self.w_tracefunc = ec.w_tracefunc
+ self.w_profilefunc = ec.w_profilefunc
+ self.is_tracing = ec.is_tracing
+
+ # the following interface is for pickling and unpickling
+ def getstate(self, space):
+ # we just save the framestack
+ items = [space.wrap(item) for item in self.framestack.items]
+ return space.newtuple(items)
+
+ def setstate(self, space, w_state):
+ from pypy.interpreter.pyframe import PyFrame
+ items = [space.interp_w(PyFrame, w_item)
+ for w_item in space.unpackiterable(w_state)]
+ self.framestack.items = items
+ # coroutine: I think this is all, folks!
+
def get_builtin(self):
try:
Modified: pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py (original)
+++ pypy/branch/mininal-c-backend/pypy/interpreter/mixedmodule.py Thu Nov 23 12:28:43 2006
@@ -88,7 +88,15 @@
if '__doc__' not in loaders:
loaders['__doc__'] = cls.get__doc__
- buildloaders = classmethod(buildloaders)
+ buildloaders = classmethod(buildloaders)
+
+ def extra_interpdef(self, name, spec):
+ cls = self.__class__
+ pkgroot = cls.__module__
+ loader = getinterpevalloader(pkgroot, spec)
+ space = self.space
+ w_obj = loader(space)
+ space.setattr(space.wrap(self), space.wrap(name), w_obj)
def get__file__(cls, space):
""" NOT_RPYTHON.
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/rgenop.py Thu Nov 23 12:28:43 2006
@@ -297,6 +297,12 @@
op = eax
return self.returnvar(op)
+ def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index):
+ self.mc.MOV(edx, gv_ptr.operand(self))
+ op = self.itemaddr(edx, arraytoken, gv_index)
+ self.mc.LEA(eax, op)
+ return self.returnvar(eax)
+
def genop_getarraysize(self, arraytoken, gv_ptr):
lengthoffset, startoffset, itemoffset = arraytoken
self.mc.MOV(edx, gv_ptr.operand(self))
@@ -813,6 +819,9 @@
def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
return dummy_var
+ def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index):
+ return dummy_var
+
def genop_getarraysize(self, arraytoken, gv_ptr):
return dummy_var
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/i386/test/test_genc_ts.py Thu Nov 23 12:28:43 2006
@@ -140,6 +140,9 @@
def check_insns(self, expected=None, **counts):
"Cannot check instructions in the generated assembler."
+ def check_flexswitches(self, expected_count):
+ "Cannot check instructions in the generated assembler."
+
class TestTimeshiftI386(I386TimeshiftingTestMixin,
test_timeshift.TestTimeshift):
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/llimpl.py Thu Nov 23 12:28:43 2006
@@ -396,6 +396,7 @@
from pypy import conftest
if conftest.option.view:
graph = from_opaque_object(graph)
+ eliminate_empty_blocks(graph)
graph.show()
# ____________________________________________________________
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llgraph/rgenop.py Thu Nov 23 12:28:43 2006
@@ -107,6 +107,11 @@
return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv,
gv_ITEMTYPE.v))
+ def genop_getarraysubstruct(self, gv_ITEMTYPE, gv_ptr, gv_index):
+ vars_gv = [gv_ptr.v, gv_index.v]
+ return LLVar(llimpl.genop(self.b, 'getarraysubstruct', vars_gv,
+ gv_ITEMTYPE.v))
+
def genop_setarrayitem(self, gv_ITEMTYPE, gv_ptr, gv_index, gv_value):
vars_gv = [gv_ptr.v, gv_index.v, gv_value.v]
return LLVar(llimpl.genop(self.b, 'setarrayitem', vars_gv,
@@ -232,7 +237,10 @@
@staticmethod
@specialize.memo()
def arrayToken(A):
- return LLConst(llimpl.constTYPE(A.OF))
+ ITEMTYPE = A.OF
+ if isinstance(ITEMTYPE, lltype.ContainerType):
+ ITEMTYPE = lltype.Ptr(ITEMTYPE)
+ return LLConst(llimpl.constTYPE(ITEMTYPE))
@staticmethod
@specialize.memo()
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Thu Nov 23 12:28:43 2006
@@ -20,59 +20,45 @@
using namespace llvm;
-ExecutionEngine* g_execution_engine;
+Module* gp_module = new Module("llvmjit");
+ExecutionEngine* gp_execution_engine = ExecutionEngine::create(
+ new ExistingModuleProvider(gp_module), false);
void restart() {
- delete g_execution_engine; //XXX test if this correctly cleans up including generated code
- g_execution_engine = NULL;
+ delete gp_execution_engine; //XXX test if this correctly cleans up including generated code
+
+ gp_module = new Module("llvmjit");
+ gp_execution_engine = ExecutionEngine::create(new ExistingModuleProvider(gp_module), false);
}
int compile(const char* llsource) {
- Module* module = ParseAssemblyString(llsource, new Module("llvmjit"));
+ Module* module = ParseAssemblyString(llsource, gp_module);
if (!module) {
- std::cerr << "Error: can not parse " << llsource << "\n" << std::flush;
+ std::cerr << "Can not parse:\n" << llsource << "\n" << std::flush;
return false;
}
- //std::ostream *Out = new std::ofstream("temp-libllvmjit.bc",
- // std::ios::out | std::ios::trunc | std::ios::binary);
- //WriteBytecodeToFile(module, *Out); //XXX what to do with the 3rd param (NoCompress)?
-
- ModuleProvider* module_provider = new ExistingModuleProvider(module);
- if (!g_execution_engine) {
- g_execution_engine = ExecutionEngine::create(module_provider, false);
- } else {
- g_execution_engine->addModuleProvider(module_provider);
- }
-
return true;
}
void* find_function(const char* name) {
- if (!g_execution_engine) return NULL; //note: decided not to be treated as an error
-
- return g_execution_engine->FindFunctionNamed(name); //note: can be NULL
+ return gp_execution_engine->FindFunctionNamed(name); //note: can be NULL
}
int execute(const void* function, int param) { //XXX allow different function signatures
- if (!g_execution_engine) {
- std::cerr << "Error: no llvm code compiled yet!\n" << std::flush;
- return -1;
- }
-
if (!function) {
- std::cerr << "Error: no function supplied to libllvmjit.execute(...)\n" << std::flush;
+ std::cerr << "No function supplied to libllvmjit.execute(...)\n" << std::flush;
return -1;
}
std::vector<GenericValue> args;
args.push_back((void*)param);
- GenericValue gv = g_execution_engine->runFunction((Function*)function, args);
+ GenericValue gv = gp_execution_engine->runFunction((Function*)function, args);
return gv.IntVal;
}
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/llvmjit.py Thu Nov 23 12:28:43 2006
@@ -7,6 +7,7 @@
This file contains the ctypes specification to use the llvmjit library!
'''
from pypy.rpython.rctypes import implementation
+from pypy.rpython.rctypes.tool.util import load_library
from ctypes import _CFuncPtr, _FUNCFLAG_CDECL
from ctypes import *
@@ -31,10 +32,10 @@
if not os.path.exists(path):
import py
- py.test.skip("libllvmjit.so compilation failed (no llvm headers?)")
+ py.test.skip("libllvmjit.so compilation failed (no llvm headers or llvm version not up to date?)")
#load the actual library
-llvmjit = cdll.LoadLibrary(os.path.abspath(path))
+llvmjit = load_library(os.path.abspath(path))
class _FuncPtr(_CFuncPtr):
_flags_ = _FUNCFLAG_CDECL
# aaarghdistutilsunixaaargh (may need something different for standalone builds...)
@@ -56,11 +57,3 @@
execute.restype = c_int
execute.argtypes = [c_void_p, c_int]
-#helpers...
-class FindFunction(object):
- def __init__(self, function_name):
- self.function = find_function(function_name)
-
- def __call__(self, param): #XXX this does not seem to translate, how to do it instead?
- return execute(self.function, param)
-
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/llvm/test/test_llvmjit.py Thu Nov 23 12:28:43 2006
@@ -27,7 +27,9 @@
ret int %n2
}'''
-llacross1 = '''declare int %across2(int %n2)
+llacross1 = '''declare int %across2(int)
+
+implementation
int %across1(int %n) {
block0:
@@ -42,7 +44,9 @@
ret int %n3
}'''
-llacross2 = '''declare int %across1(int %n2)
+llacross2 = '''declare int %across1(int %dsf)
+
+implementation
int %across2(int %n) {
block0:
@@ -60,10 +64,9 @@
#helpers
def execute(llsource, function_name, param):
assert llvmjit.compile(llsource)
- f = llvmjit.FindFunction(function_name)
- assert f.function
- return llvmjit.execute(f.function, param)
- #return function(param) #XXX this does not seem to translate, how to do it instead?
+ function = llvmjit.find_function(function_name)
+ assert function
+ return llvmjit.execute(function, param)
#tests...
def test_restart():
@@ -90,6 +93,10 @@
llvmjit.restart()
assert execute(llsquare, 'square', 4) == 4 * 4
+def test_execute_nothing():
+ llvmjit.restart()
+ assert llvmjit.execute(None, 4) == -1 #-1 == no function supplied
+
def test_execute_multiple():
llvmjit.restart()
llvmjit.compile(llsquare)
@@ -104,13 +111,13 @@
llvmjit.restart()
llvmjit.compile(llsquare)
llvmjit.compile(llmul2)
- square = llvmjit.FindFunction('square')
- mul2 = llvmjit.FindFunction('mul2')
+ square = llvmjit.find_function('square')
+ mul2 = llvmjit.find_function('mul2')
for i in range(5):
- assert square(i) == i * i
- assert mul2(i) == i * 2
+ assert llvmjit.execute(square, i) == i * i
+ assert llvmjit.execute(mul2 , i) == i * 2
-def DONTtest_execute_across_module():
+def test_execute_across_module():
def my_across1(n):
return n * 3
@@ -126,11 +133,11 @@
llvmjit.restart()
llvmjit.compile(llacross1)
llvmjit.compile(llacross2)
- across1to2 = llvmjit.FindFunction('across1to2')
- across2to1 = llvmjit.FindFunction('across2to1')
+ across1to2 = llvmjit.find_function('across1to2')
+ across2to1 = llvmjit.find_function('across2to1')
for i in range(5):
- assert across1to2(i) == my_across1to2(i)
- assert across2to1(i) == my_across2to1(i)
+ assert llvmjit.execute(across1to2, i) == my_across1to2(i)
+ assert llvmjit.execute(across2to1, i) == my_across2to1(i)
def DONTtest_modify_global_data():
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/conftest.py Thu Nov 23 12:28:43 2006
@@ -17,7 +17,10 @@
Option = py.test.Config.Option
-option = py.test.Config.addoptions("ppc options",
- Option('--trap', action="store_true", default=False,
- dest="trap",
+option = py.test.Config.addoptions("ppc options",
+ Option('--trap', action="store_true", default=False,
+ dest="trap",
+ help=""),
+ Option('--debug-print', action="store_true", default=False,
+ dest="debug_print",
help=""))
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/instruction.py Thu Nov 23 12:28:43 2006
@@ -157,6 +157,44 @@
self.result_reg.number,
self.imm.value)
+class Insn_None__GPR_GPR_IMM(Insn):
+ def __init__(self, methptr, args):
+ Insn.__init__(self)
+ self.methptr = methptr
+ self.imm = args[2]
+
+ self.result = None
+ self.result_regclass = NO_REGISTER
+ self.reg_args = args[:2]
+ self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER]
+ def allocate(self, allocator):
+ self.reg1 = allocator.loc_of(self.reg_args[0])
+ self.reg2 = allocator.loc_of(self.reg_args[1])
+ def emit(self, asm):
+ self.methptr(asm,
+ self.reg1.number,
+ self.reg2.number,
+ self.imm.value)
+
+class Insn_None__GPR_GPR_GPR(Insn):
+ def __init__(self, methptr, args):
+ Insn.__init__(self)
+ self.methptr = methptr
+
+ self.result = None
+ self.result_regclass = NO_REGISTER
+ self.reg_args = args
+ self.reg_arg_regclasses = [GP_REGISTER, GP_REGISTER, GP_REGISTER]
+ def allocate(self, allocator):
+ self.reg1 = allocator.loc_of(self.reg_args[0])
+ self.reg2 = allocator.loc_of(self.reg_args[1])
+ self.reg3 = allocator.loc_of(self.reg_args[2])
+ def emit(self, asm):
+ self.methptr(asm,
+ self.reg1.number,
+ self.reg2.number,
+ self.reg3.number)
+
class CMPInsn(Insn):
info = (0,0) # please the annotator for tests that don't use CMPW/CMPWI
pass
@@ -267,10 +305,16 @@
self.argnumber = argnumber
self.arg = arg
def allocate(self, allocator):
- self.loc = allocator.loc_of(self.arg)
+ from pypy.jit.codegen.ppc.rgenop import Var
+ if isinstance(self.arg, Var):
+ self.loc = allocator.loc_of(self.arg)
+ else:
+ self.loc = None
def emit(self, asm):
targetreg = 3+self.argnumber
- if self.loc.is_register:
+ if self.loc is None:
+ self.arg.load_now(asm, gprs[targetreg])
+ elif self.loc.is_register:
asm.mr(targetreg, self.loc.number)
else:
asm.lwz(targetreg, rFP, self.loc.offset)
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/regalloc.py Thu Nov 23 12:28:43 2006
@@ -4,10 +4,15 @@
CMPInsn, Spill, Unspill, stack_slot, \
rSCRATCH
+from pypy.jit.codegen.ppc.conftest import option
+
+DEBUG_PRINT = option.debug_print
+
class RegisterAllocation:
def __init__(self, freeregs, initial_mapping, initial_spill_offset):
- #print
- #print "RegisterAllocation __init__", initial_mapping
+ if DEBUG_PRINT:
+ print
+ print "RegisterAllocation __init__", initial_mapping.items()
self.insns = [] # output list of instructions
@@ -74,7 +79,8 @@
if freeregs:
reg = freeregs.pop()
self.set(newarg, reg)
- #print "allocate_reg: Putting %r into fresh register %r" % (newarg, reg)
+ if DEBUG_PRINT:
+ print "allocate_reg: Putting %r into fresh register %r" % (newarg, reg)
return reg
# if not, find something to spill
@@ -93,11 +99,13 @@
self.spill(reg, argtospill)
- #print "allocate_reg: Spilled %r to %r." % (argtospill, self.loc_of(argtospill))
+ if DEBUG_PRINT:
+ print "allocate_reg: Spilled %r to %r." % (argtospill, self.loc_of(argtospill))
# update data structures to put newarg into the register
self.set(newarg, reg)
- #print "allocate_reg: Put %r in stolen reg %r." % (newarg, reg)
+ if DEBUG_PRINT:
+ print "allocate_reg: Put %r in stolen reg %r." % (newarg, reg)
return reg
def _promote(self, arg):
@@ -127,32 +135,37 @@
# Walk through instructions in forward order
for insn in insns2:
- #print "Processing instruction", insn,
- #print "with args", insn.reg_args, "and result", insn.result, ":"
+ if DEBUG_PRINT:
+ print "Processing instruction", insn,
+ print "with args", insn.reg_args, "and result", insn.result, ":"
- #print "LRU list was:", self.lru
+ print "LRU list was:", self.lru
# put things into the lru
for arg in insn.reg_args:
self._promote(arg)
if insn.result:
self._promote(insn.result)
- #print "LRU list is now:", self.lru
+ if DEBUG_PRINT:
+ print "LRU list is now:", self.lru
# We need to allocate a register for each used
# argument that is not already in one
for i in range(len(insn.reg_args)):
arg = insn.reg_args[i]
argcls = insn.reg_arg_regclasses[i]
- #print "Allocating register for", arg, "..."
+ if DEBUG_PRINT:
+ print "Allocating register for", arg, "..."
argloc = self.loc_of(arg)
- #print "currently in", argloc
+ if DEBUG_PRINT:
+ print "currently in", argloc
if not argloc.is_register:
# It has no register now because it has been spilled
self.forget(arg, argloc)
newargloc = self._allocate_reg(argcls, arg)
- #print "unspilling to", newargloc
+ if DEBUG_PRINT:
+ print "unspilling to", newargloc
self.insns.append(Unspill(arg, newargloc, argloc))
self.free_stack_slots.append(argloc)
elif argloc.regclass != argcls:
@@ -174,13 +187,15 @@
self.insns.append(
newargloc.move_from_gpr(self, gpr))
else:
- #print "it was in ", argloc
+ if DEBUG_PRINT:
+ print "it was in ", argloc
pass
# Need to allocate a register for the destination
assert not insn.result or insn.result not in self.var2loc
if insn.result_regclass != NO_REGISTER:
- #print "Allocating register for result %r..." % (insn.result,)
+ if DEBUG_PRINT:
+ print "Allocating register for result %r..." % (insn.result,)
resultreg = self._allocate_reg(insn.result_regclass, insn.result)
if isinstance(insn, CMPInsn):
self.crfinfo[resultreg.number] = insn.info
Modified: pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/codegen/ppc/rgenop.py Thu Nov 23 12:28:43 2006
@@ -14,12 +14,16 @@
from pypy.translator.asm.ppcgen.rassemblermaker import make_rassembler
from pypy.translator.asm.ppcgen.ppc_assembler import MyPPCAssembler
+from pypy.jit.codegen.i386.rgenop import gc_malloc_fnaddr
+
class RPPCAssembler(make_rassembler(MyPPCAssembler)):
def emit(self, value):
self.mc.write(value)
NSAVEDREGISTERS = 19
+DEBUG_TRAP = option.trap
+
_var_index = [0]
class Var(GenVar):
def __init__(self):
@@ -211,19 +215,100 @@
self.insns.append(insn.CALL(gv_result, gv_fnptr))
return gv_result
-## def genop_getfield(self, fieldtoken, gv_ptr):
-## def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
-## def genop_getsubstruct(self, fieldtoken, gv_ptr):
-## def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
-## def genop_getarraysize(self, arraytoken, gv_ptr):
-## def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value):
-## def genop_malloc_fixedsize(self, alloctoken):
-## def genop_malloc_varsize(self, varsizealloctoken, gv_size):
+ def genop_getfield(self, fieldtoken, gv_ptr):
+ gv_result = Var()
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.lwz,
+ gv_result, [gv_ptr, IntConst(fieldtoken)]))
+ return gv_result
+
+ def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
+ gv_result = Var()
+ self.insns.append(
+ insn.Insn_None__GPR_GPR_IMM(RPPCAssembler.stw,
+ [gv_value, gv_ptr, IntConst(fieldtoken)]))
+ return gv_result
+
+ def genop_getsubstruct(self, fieldtoken, gv_ptr):
+ gv_result = Var()
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.addi,
+ gv_result, [gv_ptr, IntConst(fieldtoken)]))
+ return gv_result
+
+ def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
+ _, _, itemsize = arraytoken
+ assert itemsize == 4
+ gv_itemoffset = self.itemoffset(arraytoken, gv_index)
+ gv_result = Var()
+ if gv_itemoffset.fits_in_immediate():
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.lwz,
+ gv_result, [gv_ptr, gv_itemoffset]))
+ else:
+ self.insns.append(
+ insn.Insn_GPR__GPR_GPR(RPPCAssembler.lwzx,
+ gv_result, [gv_ptr, gv_itemoffset]))
+ return gv_result
+
+ def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index):
+ _, _, itemsize = arraytoken
+ assert itemsize == 4
+ gv_itemoffset = self.itemoffset(arraytoken, gv_index)
+ gv_result = Var()
+ if gv_itemoffset.fits_in_immediate():
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.addi,
+ gv_result, [gv_ptr, gv_itemoffset]))
+ else:
+ self.insns.append(
+ insn.Insn_GPR__GPR_GPR(RPPCAssembler.add,
+ gv_result, [gv_ptr, gv_itemoffset]))
+ return gv_result
+
+ def genop_getarraysize(self, arraytoken, gv_ptr):
+ lengthoffset, _, _ = arraytoken
+ gv_result = Var()
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.lwz,
+ gv_result, [gv_ptr, IntConst(lengthoffset)]))
+ return gv_result
+
+ def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value):
+ _, _, itemsize = arraytoken
+ assert itemsize == 4
+ gv_itemoffset = self.itemoffset(arraytoken, gv_index)
+ gv_result = Var()
+ if gv_itemoffset.fits_in_immediate():
+ self.insns.append(
+ insn.Insn_None__GPR_GPR_IMM(RPPCAssembler.stw,
+ [gv_value, gv_ptr, gv_itemoffset]))
+ else:
+ self.insns.append(
+ insn.Insn_None__GPR_GPR_GPR(RPPCAssembler.stwx,
+ [gv_value, gv_ptr, gv_itemoffset]))
+
+ def genop_malloc_fixedsize(self, alloctoken):
+ return self.genop_call(1, # COUGH
+ IntConst(gc_malloc_fnaddr()),
+ [IntConst(alloctoken)])
+
+ def genop_malloc_varsize(self, varsizealloctoken, gv_size):
+ gv_itemoffset = self.itemoffset(varsizealloctoken, gv_size)
+ gv_result = self.genop_call(1, # COUGH
+ IntConst(gc_malloc_fnaddr()),
+ [gv_itemoffset])
+ lengthoffset, _, _ = varsizealloctoken
+ self.insns.append(
+ insn.Insn_None__GPR_GPR_IMM(RPPCAssembler.stw,
+ [gv_size, gv_result, IntConst(lengthoffset)]))
+ return gv_result
def genop_same_as(self, kindtoken, gv_arg):
if not isinstance(gv_arg, Var):
gv_result = Var()
gv_arg.load(self.insns, gv_result)
+ return gv_result
else:
return gv_arg
@@ -330,6 +415,20 @@
# ----------------------------------------------------------------
# ppc-specific interface:
+ def itemoffset(self, arraytoken, gv_index):
+ # if gv_index is constant, this can return a constant...
+ lengthoffset, startoffset, itemsize = arraytoken
+
+ gv_offset = Var()
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.mulli,
+ gv_offset, [gv_index, IntConst(itemsize)]))
+ gv_itemoffset = Var()
+ self.insns.append(
+ insn.Insn_GPR__GPR_IMM(RPPCAssembler.addi,
+ gv_itemoffset, [gv_offset, IntConst(startoffset)]))
+ return gv_itemoffset
+
def make_fresh_from_jump(self, initial_var2loc):
self.fresh_from_jump = True
self.initial_var2loc = initial_var2loc
@@ -337,7 +436,7 @@
def _write_prologue(self, sigtoken):
numargs = sigtoken # for now
- if not we_are_translated() and option.trap:
+ if DEBUG_TRAP:
self.asm.trap()
inputargs = [Var() for i in range(numargs)]
assert self.initial_var2loc is None
@@ -371,6 +470,8 @@
# save stack pointer into linkage area and set stack pointer for us.
self.asm.stwu(rSP, rSP, -minspace)
+ self.emit_stack_adjustment()
+
return inputargs
def _var_offset(self, v):
@@ -399,8 +500,8 @@
allocator = RegisterAllocation(
self.rgenop.freeregs, self.initial_var2loc, self.initial_spill_offset)
self.insns = allocator.allocate_for_insns(self.insns)
- if self.insns:
- self.patch_stack_adjustment(self._stack_size(allocator.spill_offset))
+ #if self.insns:
+ self.patch_stack_adjustment(self._stack_size(allocator.spill_offset))
for insn in self.insns:
insn.emit(self.asm)
return allocator
@@ -549,12 +650,21 @@
insn.CMPWI(self.cmp2info['ne'], gv_result, [gv_arg, self.rgenop.genconst(0)]))
return gv_result
+ def op_bool_not(self, gv_arg):
+ gv_result = Var()
+ self.insns.append(
+ insn.CMPWI(self.cmp2info['eq'], gv_result, [gv_arg, self.rgenop.genconst(0)]))
+ return gv_result
+
def op_int_neg(self, gv_arg):
gv_result = Var()
self.insns.append(
insn.Insn_GPR__GPR(RPPCAssembler.neg, gv_result, gv_arg))
return gv_result
+ op_ptr_nonzero = op_int_is_true
+ op_ptr_iszero = op_bool_not # for now
+
class RPPCGenOp(AbstractRGenOp):
@@ -607,21 +717,38 @@
## @staticmethod
## def erasedType(T):
-## @staticmethod
-## @specialize.memo()
-## def fieldToken(T, name):
+ @staticmethod
+ @specialize.memo()
+ def fieldToken(T, name):
+ return llmemory.offsetof(T, name)
-## @staticmethod
-## @specialize.memo()
-## def allocToken(T):
+ @staticmethod
+ @specialize.memo()
+ def allocToken(T):
+ return llmemory.sizeof(T)
-## @staticmethod
-## @specialize.memo()
-## def varsizeAllocToken(T):
+ @staticmethod
+ @specialize.memo()
+ def varsizeAllocToken(T):
+ if isinstance(T, lltype.Array):
+ return RPPCGenOp.arrayToken(T)
+ else:
+ # var-sized structs
+ arrayfield = T._arrayfld
+ ARRAYFIELD = getattr(T, arrayfield)
+ arraytoken = RPPCGenOp.arrayToken(ARRAYFIELD)
+ length_offset, items_offset, item_size = arraytoken
+ arrayfield_offset = llmemory.offsetof(T, arrayfield)
+ return (arrayfield_offset+length_offset,
+ arrayfield_offset+items_offset,
+ item_size)
-## @staticmethod
-## @specialize.memo()
-## def arrayToken(A):
+ @staticmethod
+ @specialize.memo()
+ def arrayToken(A):
+ return (llmemory.ArrayLengthOffset(A),
+ llmemory.ArrayItemsOffset(A),
+ llmemory.ItemOffset(A.OF))
@staticmethod
@specialize.memo()
Modified: pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/hintannotator/model.py Thu Nov 23 12:28:43 2006
@@ -125,9 +125,10 @@
class SomeLLAbstractValue(annmodel.SomeObject):
- def __init__(self, T):
+ def __init__(self, T, deepfrozen=False):
self.concretetype = T
assert self.__class__ != SomeLLAbstractValue
+ self.deepfrozen = deepfrozen
def is_green(self, frame=None):
return False
@@ -138,11 +139,10 @@
def __init__(self, T, origins, eager_concrete=False, myorigin=None,
deepfrozen=False):
- SomeLLAbstractValue.__init__(self, T)
+ SomeLLAbstractValue.__init__(self, T, deepfrozen)
self.origins = origins
self.eager_concrete = eager_concrete
self.myorigin = myorigin
- self.deepfrozen = deepfrozen
assert myorigin is None or myorigin.spaceop is not None
def fmt_origins(self, origins):
@@ -198,6 +198,7 @@
class SomeLLAbstractContainer(SomeLLAbstractValue):
+ deepfrozen = False # XXX for now
def __init__(self, contentdef):
self.contentdef = contentdef
@@ -249,6 +250,15 @@
else:
return hs.concretetype
+def deepunfreeze(hs):
+ if hs.deepfrozen:
+ hs1 = annmodel.SomeObject()
+ hs1.__class__ = hs.__class__
+ hs1.__dict__ = hs.__dict__.copy()
+ hs1.deepfrozen = False
+ hs = hs1
+ return hs
+
# ____________________________________________________________
# operations
@@ -281,7 +291,7 @@
def getfield(hs_v1, hs_fieldname):
S = hs_v1.concretetype.TO
FIELD_TYPE = getattr(S, hs_fieldname.const)
- return SomeLLAbstractVariable(FIELD_TYPE)
+ return SomeLLAbstractVariable(FIELD_TYPE, hs_v1.deepfrozen)
def setfield(hs_v1, hs_fieldname, hs_value):
pass
@@ -289,7 +299,7 @@
def getsubstruct(hs_v1, hs_fieldname):
S = hs_v1.concretetype.TO
FIELD_TYPE = getattr(S, hs_fieldname.const)
- return SomeLLAbstractVariable(lltype.Ptr(FIELD_TYPE))
+ return SomeLLAbstractVariable(lltype.Ptr(FIELD_TYPE), hs_v1.deepfrozen)
## def getarrayitem(hs_v1, hs_index):
## ARRAY = hs_v1.concretetype.TO
@@ -437,28 +447,44 @@
class __extend__(pairtype(SomeLLAbstractValue, SomeLLAbstractValue)):
def getarrayitem((hs_v1, hs_v2)):
- return SomeLLAbstractVariable(hs_v1.concretetype.TO.OF)
+ return SomeLLAbstractVariable(hs_v1.concretetype.TO.OF,
+ hs_v1.deepfrozen)
def setarrayitem((hs_v1, hs_v2), hs_v3):
pass
+ def getarraysubstruct((hs_v1, hs_v2)):
+ return SomeLLAbstractVariable(lltype.Ptr(hs_v1.concretetype.TO.OF),
+ hs_v1.deepfrozen)
+
def union((hs_v1, hs_v2)):
+ if hs_v1.deepfrozen != hs_v2.deepfrozen:
+ hs_v1 = deepunfreeze(hs_v1)
+ hs_v2 = deepunfreeze(hs_v2)
+ if hs_v1 == hs_v2:
+ return hs_v1
+ return pair(hs_v1, hs_v2).union_frozen_equal()
+
+ def invalid_union((hs_v1, hs_v2)):
raise annmodel.UnionError("%s %s don't mix" % (hs_v1, hs_v2))
+ union_frozen_equal = invalid_union
+
class __extend__(pairtype(SomeLLAbstractVariable, SomeLLAbstractConstant),
pairtype(SomeLLAbstractConstant, SomeLLAbstractVariable)):
- def union((hs_v1, hs_v2)):
+ def union_frozen_equal((hs_v1, hs_v2)):
assert hs_v1.concretetype == hs_v2.concretetype
- if getattr(hs_v1, 'eager_concrete', False) or getattr(hs_v2, 'eager_concrete', False):
- raise annmodel.UnionError("%s %s don't mix" % (hs_v1, hs_v2))
- return SomeLLAbstractVariable(hs_v1.concretetype)
+ if (getattr(hs_v1, 'eager_concrete', False) or
+ getattr(hs_v2, 'eager_concrete', False)):
+ pair(hs_v1, hs_v2).invalid_union()
+ return SomeLLAbstractVariable(hs_v1.concretetype, hs_v1.deepfrozen)
class __extend__(pairtype(SomeLLAbstractConstant, SomeLLAbstractConstant)):
- def union((hs_c1, hs_c2)):
+ def union_frozen_equal((hs_c1, hs_c2)):
assert hs_c1.concretetype == hs_c2.concretetype
d = newset(hs_c1.origins, hs_c2.origins)
if hs_c1.myorigin is hs_c2.myorigin:
@@ -469,7 +495,7 @@
eager_concrete = hs_c1.eager_concrete and
hs_c2.eager_concrete,
myorigin = myorigin,
- deepfrozen = hs_c1.deepfrozen and hs_c2.deepfrozen)
+ deepfrozen = hs_c1.deepfrozen)
def getarrayitem((hs_c1, hs_index)):
@@ -496,9 +522,9 @@
class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractContainer)):
- def union((hs_cont1, hs_cont2)):
+ def union_frozen_equal((hs_cont1, hs_cont2)):
contentdef = hs_cont1.contentdef.union(hs_cont2.contentdef)
- return SomeLLAbstractContainer(contentdef)
+ return SomeLLAbstractContainer(contentdef) # XXX deepfrozen?
def ptr_eq((hs_cont1, hs_cont2)):
return SomeLLAbstractConstant(lltype.Bool, {})
@@ -508,15 +534,15 @@
class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue)):
- def union((hs_cont1, hs_val2)):
+ def union_frozen_equal((hs_cont1, hs_val2)):
hs_cont1.contentdef.mark_degenerated()
assert hs_cont1.concretetype == hs_val2.concretetype
- return SomeLLAbstractVariable(hs_cont1.concretetype)
+ return SomeLLAbstractVariable(hs_cont1.concretetype) # XXX deepfrozen?
class __extend__(pairtype(SomeLLAbstractValue, SomeLLAbstractContainer)):
- def union((hs_val1, hs_cont2)):
- return pair(hs_cont2, hs_val1).union()
+ def union_frozen_equal((hs_val1, hs_cont2)):
+ return pair(hs_cont2, hs_val1).union_frozen_equal()
class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue),
@@ -550,6 +576,8 @@
operation_name, args = ll_func.oopspec.split('(', 1)
assert args.endswith(')')
args = args[:-1] + ',' # trailing comma to force tuple syntax
+ if args.strip() == ',':
+ args = '()'
argnames = ll_func.func_code.co_varnames[:len(args_hs)]
d = dict(zip(argnames, args_hs))
argtuple = eval(args, d)
Modified: pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/hintannotator/test/test_annotator.py Thu Nov 23 12:28:43 2006
@@ -525,6 +525,17 @@
assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
assert ha.binding(v1).deepfrozen
+def test_deepfreeze_variables():
+ l1 = [[1], [2, 3], [4], []]
+ def ll_function(i):
+ i = hint(i, variable=True)
+ l = hint(l1, deepfreeze=True)
+ return l[i]
+
+ hs, ha = hannotate(ll_function, [int], annotator=True, policy=P_NOVIRTUAL)
+ assert isinstance(hs, SomeLLAbstractVariable)
+ assert hs.deepfrozen
+
def test_propagate_fixing_across_func_arguments():
def ll_func2(z):
z = hint(z, concrete=True)
Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/hrtyper.py Thu Nov 23 12:28:43 2006
@@ -160,6 +160,10 @@
if nextgraph not in seen:
pending.append(nextgraph)
seen[nextgraph] = True
+ # only keep the hint-annotated graphs that are really useful
+ self.annotator.translator.graphs = [graph
+ for graph in self.annotator.translator.graphs
+ if graph in seen]
if view:
self.annotator.translator.view() # in the middle
for graph in seen:
@@ -456,9 +460,9 @@
del link.args[0] # Void
link.args = [v_jitstate] + link.args
- def generic_translate_operation(self, hop, force=False):
+ def generic_translate_operation(self, hop):
# detect constant-foldable all-green operations
- if not force and hop.spaceop.opname not in rtimeshift.FOLDABLE_OPS:
+ if hop.spaceop.opname not in rtimeshift.FOLDABLE_GREEN_OPS:
return None
green = True
for r_arg in hop.args_r:
@@ -492,7 +496,7 @@
[c_opdesc, v_jitstate] + args_v,
ts.s_RedBox)
- def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc
+ def translate_op_debug_assert(self, hop):
pass
def translate_op_keepalive(self,hop):
@@ -522,49 +526,39 @@
ts.s_RedBox)
# non virtual case
PTRTYPE = originalconcretetype(hop.args_s[0])
- if PTRTYPE.TO._hints.get('immutable', False): # foldable if all green
- res = self.generic_translate_operation(hop, force=True)
- if res is not None:
- return res
-
v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
green_void_repr)
v_argbox = hop.llops.as_ptrredbox(v_argbox)
+ c_deepfrozen = inputconst(lltype.Bool, hop.args_s[0].deepfrozen)
structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
fielddesc = structdesc.getfielddesc(c_fieldname.value)
c_fielddesc = inputconst(lltype.Void, fielddesc)
s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
v_jitstate = hop.llops.getjitstate()
return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gengetfield,
- [ts.s_JITState, s_fielddesc, ts.s_PtrRedBox],
- [v_jitstate, c_fielddesc, v_argbox ],
+ [ts.s_JITState, annmodel.s_Bool, s_fielddesc, ts.s_PtrRedBox],
+ [v_jitstate , c_deepfrozen , c_fielddesc, v_argbox ],
ts.s_RedBox)
def translate_op_getarrayitem(self, hop):
PTRTYPE = originalconcretetype(hop.args_s[0])
- if PTRTYPE.TO._hints.get('immutable', False): # foldable if all green
- res = self.generic_translate_operation(hop, force=True)
- if res is not None:
- return res
-
ts = self
v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE),
self.getredrepr(lltype.Signed))
+ c_deepfrozen = inputconst(lltype.Bool, hop.args_s[0].deepfrozen)
fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO)
c_fielddesc = inputconst(lltype.Void, fielddesc)
s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
v_jitstate = hop.llops.getjitstate()
return hop.llops.genmixlevelhelpercall(
rtimeshift.ll_gengetarrayitem,
- [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
- [v_jitstate, c_fielddesc, v_argbox, v_index ],
+ [ts.s_JITState, annmodel.s_Bool, s_fielddesc,
+ ts.s_RedBox, ts.s_RedBox],
+ [v_jitstate, c_deepfrozen, c_fielddesc,
+ v_argbox, v_index ],
ts.s_RedBox)
def translate_op_getarraysize(self, hop):
- res = self.generic_translate_operation(hop, force=True)
- if res is not None:
- return res
-
PTRTYPE = originalconcretetype(hop.args_s[0])
ts = self
[v_argbox] = hop.inputargs(self.getredrepr(PTRTYPE))
@@ -652,6 +646,22 @@
[v_jitstate, c_fielddesc, v_argbox ],
ts.s_RedBox)
+ def translate_op_getarraysubstruct(self, hop):
+ PTRTYPE = originalconcretetype(hop.args_s[0])
+ ts = self
+ v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE),
+ self.getredrepr(lltype.Signed))
+ fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE.TO)
+ c_fielddesc = inputconst(lltype.Void, fielddesc)
+ s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(
+ rtimeshift.ll_gengetarraysubstruct,
+ [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
+ [v_jitstate, c_fielddesc, v_argbox, v_index ],
+ ts.s_RedBox)
+
+
def translate_op_cast_pointer(self, hop):
FROM_TYPE = originalconcretetype(hop.args_s[0])
[v_argbox] = hop.inputargs(self.getredrepr(FROM_TYPE))
@@ -685,19 +695,36 @@
ts = self
PTRTYPE = originalconcretetype(hop.args_s[0])
v_argbox, = hop.inputargs(self.getredrepr(PTRTYPE))
+ v_argbox = hop.llops.as_ptrredbox(v_argbox)
v_jitstate = hop.llops.getjitstate()
c_reverse = hop.inputconst(lltype.Bool, reverse)
return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genptrnonzero,
- [ts.s_JITState, ts.s_RedBox, annmodel.SomeBool()],
- [v_jitstate, v_argbox, c_reverse ],
+ [ts.s_JITState, ts.s_PtrRedBox, annmodel.s_Bool],
+ [v_jitstate , v_argbox , c_reverse ],
ts.s_RedBox)
def translate_op_ptr_iszero(self, hop):
return self.translate_op_ptr_nonzero(hop, reverse=True)
+ def translate_op_ptr_eq(self, hop, reverse=False):
+ ts = self
+ PTRTYPE = originalconcretetype(hop.args_s[0])
+ r_ptr = self.getredrepr(PTRTYPE)
+ v_argbox0, v_argbox1 = hop.inputargs(r_ptr, r_ptr)
+ v_argbox0 = hop.llops.as_ptrredbox(v_argbox0)
+ v_argbox1 = hop.llops.as_ptrredbox(v_argbox1)
+ v_jitstate = hop.llops.getjitstate()
+ c_reverse = hop.inputconst(lltype.Bool, reverse)
+ return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genptreq,
+ [ts.s_JITState, ts.s_PtrRedBox, ts.s_PtrRedBox, annmodel.s_Bool],
+ [v_jitstate , v_argbox0 , v_argbox1 , c_reverse ],
+ ts.s_RedBox)
+
+ def translate_op_ptr_ne(self, hop):
+ return self.translate_op_ptr_eq(hop, reverse=True)
- # special operations inserted by the HintGraphTransformer
+ # special operations inserted by the HintGraphTransformer
def translate_op_ensure_queue(self, hop, prefix=''):
mpfamily = hop.args_v[0].value
@@ -1017,7 +1044,10 @@
# Pass them as constant Nones.
ts = self
ll_handler = oopspecdesc.ll_handler
- missing_args = ((ll_handler.func_code.co_argcount - 2) -
+
+ couldfold = oopspecdesc.couldfold
+
+ missing_args = ((ll_handler.func_code.co_argcount - 2 - couldfold) -
len(oopspecdesc.argtuple))
assert missing_args >= 0
if missing_args > 0:
@@ -1027,9 +1057,17 @@
args_v.extend([hop.llops.genconst(ll_None)] * missing_args)
args_s = [ts.s_RedBox] * len(args_v)
+
if oopspecdesc.is_method:
args_s[0] = ts.s_PtrRedBox # for more precise annotations
args_v[0] = hop.llops.as_ptrredbox(args_v[0])
+
+ if couldfold:
+ args_s.insert(0, annmodel.s_Bool)
+ hs_self = hop.args_s[oopspecdesc.argtuple[0].n]
+ c_deepfrozen = inputconst(lltype.Bool, hs_self.deepfrozen)
+ args_v.insert(0, c_deepfrozen)
+
RESULT = originalconcretetype(hop.s_result)
if RESULT is lltype.Void:
s_result = annmodel.s_None
Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/oop.py Thu Nov 23 12:28:43 2006
@@ -3,6 +3,7 @@
from pypy.jit.timeshifter.rcontainer import cachedtype
from pypy.jit.timeshifter import rvalue, rtimeshift
from pypy.translator.c import exceptiontransform
+from pypy.rlib.unroll import unrolling_iterable
class Index:
@@ -13,6 +14,8 @@
class OopSpecDesc:
__metaclass__ = cachedtype
+ do_call = None
+
def __init__(self, hrtyper, fnobj):
ll_func = fnobj._callable
FUNCTYPE = lltype.typeOf(fnobj)
@@ -22,6 +25,8 @@
operation_name, args = ll_func.oopspec.split('(', 1)
assert args.endswith(')')
args = args[:-1] + ',' # trailing comma to force tuple syntax
+ if args.strip() == ',':
+ args = '()'
argnames = ll_func.func_code.co_varnames[:nb_args]
d = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
self.argtuple = eval(args, d)
@@ -40,21 +45,28 @@
RGenOp = hrtyper.RGenOp
self.args_gv = [None] * nb_args
- self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnobj._as_ptr())
- self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT)
+ fnptr = fnobj._as_ptr()
+ self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnptr)
+ result_kind = RGenOp.kindToken(FUNCTYPE.RESULT)
+ self.result_kind = result_kind
if FUNCTYPE.RESULT is lltype.Void:
self.errorbox = None
else:
error_value = exceptiontransform.error_value(FUNCTYPE.RESULT)
self.errorbox = rvalue.redbox_from_prebuilt_value(RGenOp,
error_value)
- self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+ redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+ self.redboxbuilder = redboxbuilder
self.sigtoken = RGenOp.sigToken(FUNCTYPE)
if operation_name == 'newlist':
typename, method = 'list', 'oop_newlist'
SELFTYPE = FUNCTYPE.RESULT.TO
self.is_method = False
+ elif operation_name == 'newdict':
+ typename, method = 'dict', 'oop_newdict'
+ SELFTYPE = FUNCTYPE.RESULT.TO
+ self.is_method = False
else:
typename, method = operation_name.split('.')
method = 'oop_%s_%s' % (typename, method)
@@ -65,6 +77,7 @@
None, None, [method])
self.typedesc = vmodule.TypeDesc(hrtyper, SELFTYPE)
self.ll_handler = getattr(vmodule, method)
+ self.couldfold = getattr(self.ll_handler, 'couldfold', False)
# exception handling
graph = fnobj.graph
@@ -72,15 +85,41 @@
self.can_raise = etrafo.raise_analyzer.analyze_direct_call(graph)
self.fetch_global_excdata = hrtyper.fetch_global_excdata
- def residual_call(self, jitstate, argboxes):
+ if self.couldfold:
+ ARGS = FUNCTYPE.ARGS
+ argpos = unrolling_iterable(enumerate(self.argpositions))
+
+ def do_call(jitstate, argboxes):
+ args = (None,)*nb_args
+ for i, pos in argpos:
+ if pos >= 0:
+ T = ARGS[pos]
+ v = rvalue.ll_getvalue(argboxes[i], T)
+ args = args[:pos] +(v,) + args[pos+1:]
+ result = fnptr(*args)
+ if FUNCTYPE.RESULT == lltype.Void:
+ return None
+ return rvalue.ll_fromvalue(jitstate, result)
+
+ self.do_call = do_call
+
+ def residual_call(self, jitstate, argboxes, deepfrozen=False):
builder = jitstate.curbuilder
args_gv = self.args_gv[:]
argpositions = self.argpositions
+ fold = deepfrozen
for i in range(len(argpositions)):
pos = argpositions[i]
if pos >= 0:
gv_arg = argboxes[i].getgenvar(builder)
args_gv[pos] = gv_arg
+ fold &= gv_arg.is_const
+ if fold:
+ try:
+ return self.do_call(jitstate, argboxes)
+ except Exception, e:
+ jitstate.residual_exception(e)
+ return self.errorbox
gv_result = builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv)
if self.can_raise:
self.fetch_global_excdata(jitstate)
@@ -88,11 +127,7 @@
def residual_exception(self, jitstate, ExcCls):
ll_evalue = get_ll_instance_for_exccls(ExcCls)
- ll_etype = ll_evalue.typeptr
- etypebox = rvalue.ll_fromvalue(jitstate, ll_etype)
- evaluebox = rvalue.ll_fromvalue(jitstate, ll_evalue)
- rtimeshift.setexctypebox (jitstate, etypebox )
- rtimeshift.setexcvaluebox(jitstate, evaluebox)
+ jitstate.residual_ll_exception(ll_evalue)
return self.errorbox
residual_exception._annspecialcase_ = 'specialize:arg(2)'
Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rcontainer.py Thu Nov 23 12:28:43 2006
@@ -2,6 +2,11 @@
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.annlowlevel import cachedtype
from pypy.jit.timeshifter import rvalue
+from pypy.rlib.unroll import unrolling_iterable
+
+from pypy.rpython.lltypesystem import lloperation
+debug_print = lloperation.llop.debug_print
+debug_pdb = lloperation.llop.debug_pdb
class AbstractContainer(object):
__slots__ = []
@@ -15,6 +20,20 @@
def op_getsubstruct(self, jitstate, fielddesc):
raise NotImplementedError
+
+class VirtualContainer(AbstractContainer):
+ __slots__ = []
+
+
+class FrozenContainer(AbstractContainer):
+ __slots__ = []
+
+ def exactmatch(self, vstruct, outgoingvarboxes, memo):
+ raise NotImplementedError
+
+ def unfreeze(self, incomingvarboxes, memo):
+ raise NotImplementedError
+
# ____________________________________________________________
class StructTypeDesc(object):
@@ -23,6 +42,7 @@
arrayfielddesc = None
alloctoken = None
varsizealloctoken = None
+ materialize = None
def __init__(self, RGenOp, TYPE):
self.TYPE = TYPE
@@ -58,6 +78,22 @@
self.fielddesc_by_name = fielddesc_by_name
self.innermostdesc = innermostdesc
+ self.immutable = TYPE._hints.get('immutable', False)
+ self.noidentity = TYPE._hints.get('noidentity', False)
+
+ if self.immutable and self.noidentity:
+ descs = unrolling_iterable(fielddescs)
+ def materialize(rgenop, boxes):
+ s = lltype.malloc(TYPE)
+ i = 0
+ for desc in descs:
+ v = rvalue.ll_getvalue(boxes[i], desc.RESTYPE)
+ setattr(s, desc.fieldname, v)
+ i = i + 1
+ return rgenop.genconst(s)
+
+ self.materialize = materialize
+
def getfielddesc(self, name):
return self.fielddesc_by_name[name]
@@ -137,7 +173,7 @@
# ____________________________________________________________
-class FrozenVirtualStruct(AbstractContainer):
+class FrozenVirtualStruct(FrozenContainer):
def __init__(self, typedesc):
self.typedesc = typedesc
@@ -178,6 +214,7 @@
ownbox = typedesc.factory()
contmemo[self] = ownbox
vstruct = ownbox.content
+ assert isinstance(vstruct, VirtualStruct)
self_boxes = self.fz_content_boxes
for i in range(len(self_boxes)):
fz_box = self_boxes[i]
@@ -186,11 +223,7 @@
return ownbox
-class AbstractStruct(AbstractContainer):
- pass
-
-
-class VirtualStruct(AbstractStruct):
+class VirtualStruct(VirtualContainer):
def __init__(self, typedesc):
self.typedesc = typedesc
@@ -208,6 +241,17 @@
typedesc = self.typedesc
boxes = self.content_boxes
self.content_boxes = None
+ if typedesc.materialize is not None:
+ for box in boxes:
+ if box is None or not box.is_constant():
+ break
+ else:
+ gv = typedesc.materialize(builder.rgenop, boxes)
+ self.ownbox.genvar = gv
+ self.ownbox.content = None
+ return
+ debug_print(lltype.Void, "FORCE CONTAINER")
+ #debug_pdb(lltype.Void)
genvar = builder.genop_malloc_fixedsize(typedesc.alloctoken)
# force the box pointing to this VirtualStruct
self.ownbox.genvar = genvar
@@ -253,8 +297,46 @@
def op_getsubstruct(self, jitstate, fielddesc):
return self.ownbox
+# ____________________________________________________________
-class PartialDataStruct(AbstractStruct):
+class FrozenPartialDataStruct(AbstractContainer):
+
+ def __init__(self):
+ self.fz_data = []
+
+ def getfzbox(self, searchindex):
+ for index, fzbox in self.fz_data:
+ if index == searchindex:
+ return fzbox
+ else:
+ return None
+
+ def match(self, box, partialdatamatch):
+ content = box.content
+ if not isinstance(content, PartialDataStruct):
+ return False
+
+ cankeep = {}
+ for index, subbox in content.data:
+ selfbox = self.getfzbox(index)
+ if selfbox is not None and selfbox.is_constant_equal(subbox):
+ cankeep[index] = None
+ fullmatch = len(cankeep) == len(self.fz_data)
+ try:
+ prevkeep = partialdatamatch[box]
+ except KeyError:
+ partialdatamatch[box] = cankeep
+ else:
+ if prevkeep is not None:
+ d = {}
+ for index in prevkeep:
+ if index in cankeep:
+ d[index] = None
+ partialdatamatch[box] = d
+ return fullmatch
+
+
+class PartialDataStruct(AbstractContainer):
def __init__(self):
self.data = []
@@ -276,6 +358,19 @@
else:
self.data.append((searchindex, box))
+ def partialfreeze(self, memo):
+ contmemo = memo.containers
+ assert self not in contmemo # contmemo no longer used
+ result = contmemo[self] = FrozenPartialDataStruct()
+ for index, box in self.data:
+ if box.is_constant():
+ frozenbox = box.freeze(memo)
+ result.fz_data.append((index, frozenbox))
+ if len(result.fz_data) == 0:
+ return None
+ else:
+ return result
+
def copy(self, memo):
result = PartialDataStruct()
for index, box in self.data:
@@ -294,3 +389,18 @@
contmemo[self] = None
for index, box in self.data:
box.enter_block(incoming, memo)
+
+ def cleanup_partial_data(self, keep):
+ if keep is None:
+ return None
+ j = 0
+ data = self.data
+ for i in range(len(data)):
+ item = data[i]
+ if item[0] in keep:
+ data[j] = item
+ j += 1
+ if j == 0:
+ return None
+ del data[j:]
+ return self
Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rtimeshift.py Thu Nov 23 12:28:43 2006
@@ -2,7 +2,7 @@
from pypy.annotation import model as annmodel
from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
from pypy.jit.hintannotator.model import originalconcretetype
-from pypy.jit.timeshifter import rvalue
+from pypy.jit.timeshifter import rvalue, rcontainer
from pypy.rlib.unroll import unrolling_iterable
from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype
from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -10,6 +10,10 @@
FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
+FOLDABLE_GREEN_OPS = FOLDABLE_OPS.copy()
+FOLDABLE_GREEN_OPS['getfield'] = None
+FOLDABLE_GREEN_OPS['getarrayitem'] = None
+
debug_view = lloperation.llop.debug_view
debug_print = lloperation.llop.debug_print
@@ -96,8 +100,8 @@
genvar = jitstate.curbuilder.genop_malloc_varsize(alloctoken, gv_size)
return rvalue.PtrRedBox(contdesc.ptrkind, genvar)
-def ll_gengetfield(jitstate, fielddesc, argbox):
- if fielddesc.immutable and argbox.is_constant():
+def ll_gengetfield(jitstate, deepfrozen, fielddesc, argbox):
+ if (fielddesc.immutable or deepfrozen) and argbox.is_constant():
res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
fielddesc.fieldname)
return rvalue.ll_fromvalue(jitstate, res)
@@ -113,8 +117,9 @@
return rvalue.ll_fromvalue(jitstate, res)
return argbox.op_getsubstruct(jitstate, fielddesc)
-def ll_gengetarrayitem(jitstate, fielddesc, argbox, indexbox):
- if fielddesc.immutable and argbox.is_constant() and indexbox.is_constant():
+def ll_gengetarrayitem(jitstate, deepfrozen, fielddesc, argbox, indexbox):
+ if ((fielddesc.immutable or deepfrozen) and argbox.is_constant()
+ and indexbox.is_constant()):
array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)]
return rvalue.ll_fromvalue(jitstate, res)
@@ -125,6 +130,19 @@
return fielddesc.redboxcls(fielddesc.kind, genvar)
+def ll_gengetarraysubstruct(jitstate, fielddesc, argbox, indexbox):
+ if argbox.is_constant() and indexbox.is_constant():
+ array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
+ res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)]
+ return rvalue.ll_fromvalue(jitstate, res)
+ genvar = jitstate.curbuilder.genop_getarraysubstruct(
+ fielddesc.arraytoken,
+ argbox.getgenvar(jitstate.curbuilder),
+ indexbox.getgenvar(jitstate.curbuilder))
+
+ return fielddesc.redboxcls(fielddesc.kind, genvar)
+
+
def ll_gensetarrayitem(jitstate, fielddesc, destbox, indexbox, valuebox):
genvar = jitstate.curbuilder.genop_setarrayitem(
fielddesc.arraytoken,
@@ -149,7 +167,6 @@
if argbox.is_constant():
addr = rvalue.ll_getvalue(argbox, llmemory.Address)
return rvalue.ll_fromvalue(jitstate, bool(addr) ^ reverse)
- assert isinstance(argbox, rvalue.PtrRedBox)
builder = jitstate.curbuilder
if argbox.content is None:
gv_addr = argbox.getgenvar(builder)
@@ -161,6 +178,23 @@
gv_res = builder.rgenop.genconst(True ^ reverse)
return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res)
+def ll_genptreq(jitstate, argbox0, argbox1, reverse):
+ builder = jitstate.curbuilder
+ if argbox0.content is not None or argbox1.content is not None:
+ equal = argbox0.content is argbox1.content
+ return rvalue.ll_fromvalue(jitstate, equal ^ reverse)
+ elif argbox0.is_constant() and argbox1.is_constant():
+ addr0 = rvalue.ll_getvalue(argbox0, llmemory.Address)
+ addr1 = rvalue.ll_getvalue(argbox1, llmemory.Address)
+ return rvalue.ll_fromvalue(jitstate, (addr0 == addr1) ^ reverse)
+ gv_addr0 = argbox0.getgenvar(builder)
+ gv_addr1 = argbox1.getgenvar(builder)
+ if reverse:
+ gv_res = builder.genop2("ptr_ne", gv_addr0, gv_addr1)
+ else:
+ gv_res = builder.genop2("ptr_eq", gv_addr0, gv_addr1)
+ return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res)
+
# ____________________________________________________________
# other jitstate/graph level operations
@@ -185,6 +219,7 @@
outgoingvarboxes = []
res = frozen.exactmatch(jitstate, outgoingvarboxes, memo)
assert res, "exactmatch() failed"
+ cleanup_partial_data(memo.partialdatamatch)
newblock = enter_next_block(jitstate, outgoingvarboxes)
states_dic[key] = frozen, newblock
if global_resumer is not None and global_resumer is not return_marker:
@@ -217,6 +252,7 @@
# We need a more general block. Do it by generalizing all the
# redboxes from outgoingvarboxes, by making them variables.
# Then we make a new block based on this new state.
+ cleanup_partial_data(memo.partialdatamatch)
replace_memo = rvalue.copy_memo()
for box in outgoingvarboxes:
box.forcevar(jitstate.curbuilder, replace_memo)
@@ -228,6 +264,14 @@
return False # continue
retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)"
+def cleanup_partial_data(partialdatamatch):
+ # remove entries from PartialDataStruct unless they matched
+ # their frozen equivalent
+ for box, keep in partialdatamatch.iteritems():
+ content = box.content
+ if isinstance(content, rcontainer.PartialDataStruct):
+ box.content = content.cleanup_partial_data(keep)
+
def merge_generalized(jitstate):
resuming = jitstate.resuming
if resuming is None:
@@ -794,6 +838,17 @@
self.exc_value_box = self.exc_value_box.replace(memo)
+ def residual_ll_exception(self, ll_evalue):
+ ll_etype = ll_evalue.typeptr
+ etypebox = rvalue.ll_fromvalue(self, ll_etype)
+ evaluebox = rvalue.ll_fromvalue(self, ll_evalue)
+ setexctypebox (self, etypebox )
+ setexcvaluebox(self, evaluebox)
+
+ def residual_exception(self, e):
+ self.residual_ll_exception(cast_instance_to_base_ptr(e))
+
+
def ensure_queue(jitstate, DispatchQueueClass):
return DispatchQueueClass()
ensure_queue._annspecialcase_ = 'specialize:arg(1)'
Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/rvalue.py Thu Nov 23 12:28:43 2006
@@ -14,7 +14,9 @@
return Memo()
def exactmatch_memo():
- return Memo()
+ memo = Memo()
+ memo.partialdatamatch = {}
+ return memo
def copy_memo():
return Memo()
@@ -242,29 +244,35 @@
try:
return boxmemo[self]
except KeyError:
+ content = self.content
if not self.genvar:
- assert self.content is not None
+ from pypy.jit.timeshifter import rcontainer
+ assert isinstance(content, rcontainer.VirtualContainer)
result = FrozenPtrVirtual(self.kind)
boxmemo[self] = result
- result.fz_content = self.content.freeze(memo)
+ result.fz_content = content.freeze(memo)
+ return result
+ elif self.genvar.is_const:
+ result = FrozenPtrConst(self.kind, self.genvar)
+ elif content is None:
+ result = FrozenPtrVar(self.kind)
else:
- if self.is_constant():
- result = FrozenPtrConst(self.kind, self.genvar)
- else:
- result = FrozenPtrVar(self.kind)
- # if self.content is not None, it's a PartialDataStruct
- # - for now, we always remove it while freezing so that
- # we exactly match our frozen version
- # XXX unsure if it's the correct place to do that.
- # XXX maybe in exactmatch??
- self.content = None
+ # if self.content is not None, it's a PartialDataStruct
+ from pypy.jit.timeshifter import rcontainer
+ assert isinstance(content, rcontainer.PartialDataStruct)
+ result = FrozenPtrVarWithPartialData(self.kind)
boxmemo[self] = result
+ result.fz_partialcontent = content.partialfreeze(memo)
+ return result
+ boxmemo[self] = result
return result
def getgenvar(self, builder):
if not self.genvar:
- assert self.content
- self.content.force_runtime_container(builder)
+ content = self.content
+ from pypy.jit.timeshifter import rcontainer
+ assert isinstance(content, rcontainer.VirtualContainer)
+ content.force_runtime_container(builder)
assert self.genvar
return self.genvar
@@ -288,28 +296,21 @@
def __init__(self, kind):
self.kind = kind
+ def is_constant_equal(self, box):
+ return False
-class FrozenIntConst(FrozenValue):
- def __init__(self, kind, gv_const):
- self.kind = kind
- self.gv_const = gv_const
+class FrozenConst(FrozenValue):
def exactmatch(self, box, outgoingvarboxes, memo):
- if (box.is_constant() and
- self.gv_const.revealconst(lltype.Signed) ==
- box.genvar.revealconst(lltype.Signed)):
+ if self.is_constant_equal(box):
return True
else:
outgoingvarboxes.append(box)
return False
- def unfreeze(self, incomingvarboxes, memo):
- # XXX could return directly the original IntRedBox
- return IntRedBox(self.kind, self.gv_const)
-
-class FrozenIntVar(FrozenValue):
+class FrozenVar(FrozenValue):
def exactmatch(self, box, outgoingvarboxes, memo):
memo = memo.boxes
@@ -323,6 +324,25 @@
outgoingvarboxes.append(box)
return False
+
+class FrozenIntConst(FrozenConst):
+
+ def __init__(self, kind, gv_const):
+ self.kind = kind
+ self.gv_const = gv_const
+
+ def is_constant_equal(self, box):
+ return (box.is_constant() and
+ self.gv_const.revealconst(lltype.Signed) ==
+ box.genvar.revealconst(lltype.Signed))
+
+ def unfreeze(self, incomingvarboxes, memo):
+ # XXX could return directly the original IntRedBox
+ return IntRedBox(self.kind, self.gv_const)
+
+
+class FrozenIntVar(FrozenVar):
+
def unfreeze(self, incomingvarboxes, memo):
memo = memo.boxes
if self not in memo:
@@ -334,38 +354,22 @@
return memo[self]
-class FrozenDoubleConst(FrozenValue):
+class FrozenDoubleConst(FrozenConst):
def __init__(self, kind, gv_const):
self.kind = kind
self.gv_const = gv_const
- def exactmatch(self, box, outgoingvarboxes, memo):
- if (box.is_constant() and
- self.gv_const.revealconst(lltype.Float) ==
- box.genvar.revealconst(lltype.Float)):
- return True
- else:
- outgoingvarboxes.append(box)
- return False
+ def is_constant_equal(self, box):
+ return (box.is_constant() and
+ self.gv_const.revealconst(lltype.Float) ==
+ box.genvar.revealconst(lltype.Float))
def unfreeze(self, incomingvarboxes, memo):
return DoubleRedBox(self.kind, self.gv_const)
-class FrozenDoubleVar(FrozenValue):
-
- def exactmatch(self, box, outgoingvarboxes, memo):
- memo = memo.boxes
- if self not in memo:
- memo[self] = box
- outgoingvarboxes.append(box)
- return True
- elif memo[self] is box:
- return True
- else:
- outgoingvarboxes.append(box)
- return False
+class FrozenDoubleVar(FrozenVar):
def unfreeze(self, incomingvarboxes, memo):
memo = memo.boxes
@@ -378,38 +382,32 @@
return memo[self]
-class FrozenPtrConst(FrozenValue):
+class FrozenPtrConst(FrozenConst):
def __init__(self, kind, gv_const):
self.kind = kind
self.gv_const = gv_const
+ def is_constant_equal(self, box):
+ return (box.is_constant() and
+ self.gv_const.revealconst(llmemory.Address) ==
+ box.genvar.revealconst(llmemory.Address))
+
def exactmatch(self, box, outgoingvarboxes, memo):
- if (box.is_constant() and
- self.gv_const.revealconst(llmemory.Address) ==
- box.genvar.revealconst(llmemory.Address)):
- return True
- else:
- outgoingvarboxes.append(box)
- return False
+ assert isinstance(box, PtrRedBox)
+ memo.partialdatamatch[box] = None # could do better
+ return FrozenConst.exactmatch(self, box, outgoingvarboxes, memo)
def unfreeze(self, incomingvarboxes, memo):
return PtrRedBox(self.kind, self.gv_const)
-class FrozenPtrVar(FrozenValue):
+class FrozenPtrVar(FrozenVar):
def exactmatch(self, box, outgoingvarboxes, memo):
- memo = memo.boxes
- if self not in memo:
- memo[self] = box
- outgoingvarboxes.append(box)
- return True
- elif memo[self] is box:
- return True
- else:
- outgoingvarboxes.append(box)
- return False
+ assert isinstance(box, PtrRedBox)
+ memo.partialdatamatch[box] = None
+ return FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
def unfreeze(self, incomingvarboxes, memo):
memo = memo.boxes
@@ -422,6 +420,19 @@
return memo[self]
+class FrozenPtrVarWithPartialData(FrozenPtrVar):
+
+ def exactmatch(self, box, outgoingvarboxes, memo):
+ if self.fz_partialcontent is None:
+ return FrozenPtrVar.exactmatch(self, box, outgoingvarboxes, memo)
+ assert isinstance(box, PtrRedBox)
+ partialdatamatch = self.fz_partialcontent.match(box,
+ memo.partialdatamatch)
+ # skip the parent's exactmatch()!
+ exact = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
+ return exact and partialdatamatch
+
+
class FrozenPtrVirtual(FrozenValue):
def exactmatch(self, box, outgoingvarboxes, memo):
Modified: pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py (original)
+++ pypy/branch/mininal-c-backend/pypy/jit/timeshifter/test/test_portal.py Thu Nov 23 12:28:43 2006
@@ -3,6 +3,7 @@
from