[pypy-svn] r49815 - in pypy/branch/lazy-write-barrier/pypy: annotation doc interpreter jit/hintannotator jit/hintannotator/test lib module/__builtin__ module/__builtin__/test module/_random module/crypt objspace/std rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/ootypesystem rpython/ootypesystem/test translator/c translator/c/test translator/cli translator/goal
fijal at codespeak.net
fijal at codespeak.net
Sat Dec 15 13:57:31 CET 2007
Author: fijal
Date: Sat Dec 15 13:57:29 2007
New Revision: 49815
Added:
pypy/branch/lazy-write-barrier/pypy/module/__builtin__/interp_classobj.py
- copied unchanged from r49814, pypy/dist/pypy/module/__builtin__/interp_classobj.py
pypy/branch/lazy-write-barrier/pypy/module/__builtin__/test/test_classobj.py
- copied unchanged from r49814, pypy/dist/pypy/module/__builtin__/test/test_classobj.py
Removed:
pypy/branch/lazy-write-barrier/pypy/lib/_classobj.py
pypy/branch/lazy-write-barrier/pypy/module/__builtin__/app_sets.py
Modified:
pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py
pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt
pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py
pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py
pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py
pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py
pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py
pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py
pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py
pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py
pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py
pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py
pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py
pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py
pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py
pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py
pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py
pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py
pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py
pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py
pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py
pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py
pypy/branch/lazy-write-barrier/pypy/translator/c/database.py
pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py
pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py
pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py
Log:
Merge dist -> branch
Modified: pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py Sat Dec 15 13:57:29 2007
@@ -16,6 +16,7 @@
from pypy.annotation.bookkeeper import getbookkeeper
from pypy.annotation import description
from pypy.objspace.flow.model import Constant
+from pypy.tool.error import AnnotatorError
import pypy.rlib.rarithmetic
import pypy.rlib.objectmodel
@@ -547,6 +548,20 @@
assert isinstance(i, SomeOOInstance)
return SomeInteger()
+def ooupcast(I, i):
+ assert isinstance(I.const, ootype.Instance)
+ if ootype.isSubclass(i.ootype, I.const):
+ return SomeOOInstance(I.const)
+ else:
+ raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const)
+
+def oodowncast(I, i):
+ assert isinstance(I.const, ootype.Instance)
+ if ootype.isSubclass(I.const, i.ootype):
+ return SomeOOInstance(I.const)
+ else:
+ raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const)
+
BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
BUILTIN_ANALYZERS[ootype.new] = new
BUILTIN_ANALYZERS[ootype.null] = null
@@ -554,6 +569,8 @@
BUILTIN_ANALYZERS[ootype.classof] = classof
BUILTIN_ANALYZERS[ootype.subclassof] = subclassof
BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash
+BUILTIN_ANALYZERS[ootype.ooupcast] = ooupcast
+BUILTIN_ANALYZERS[ootype.oodowncast] = oodowncast
#________________________________
# weakrefs
Modified: pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt (original)
+++ pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt Sat Dec 15 13:57:29 2007
@@ -25,7 +25,7 @@
.. _`Learn Prolog Now!`: http://www.coli.uni-saarland.de/~kris/learn-prolog-now/
.. _`A Prolog interpreter in Python`: http://codespeak.net/pypy/extradoc/paper/prolog-in-python.pdf
-Example useage
+Example usage
==============
First some simple examples that show simple unification::
Modified: pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py Sat Dec 15 13:57:29 2007
@@ -328,7 +328,7 @@
def visit__object(self, typ):
if typ not in (int, str, float, unicode, r_longlong):
- assert False, "unsupported basic type in uwnrap_spec"
+ assert False, "unsupported basic type in unwrap_spec"
self.unwrap.append("space.%s_w(%s)" % (typ.__name__,
self.nextarg()))
Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py Sat Dec 15 13:57:29 2007
@@ -6,7 +6,8 @@
from pypy.jit.hintannotator.bookkeeper import HintBookkeeper
from pypy.jit.hintannotator.policy import HintAnnotatorPolicy
from pypy.rpython.lltypesystem import lltype
-
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.simplify import get_funcobj
class HintAnnotator(RPythonAnnotator):
@@ -28,6 +29,15 @@
def getuserclassdefinitions(self):
return []
+ def consider_op_new(self, hs_TYPE):
+ TYPE = hs_TYPE.const
+ if self.policy.novirtualcontainer:
+ return hintmodel.SomeLLAbstractVariable(TYPE)
+ else:
+ # XXX: ootype
+ vstructdef = self.bookkeeper.getvirtualcontainerdef(TYPE)
+ return hintmodel.SomeLLAbstractContainer(vstructdef)
+
def consider_op_malloc(self, hs_TYPE, hs_flags):
TYPE = hs_TYPE.const
flags = hs_flags.const
@@ -65,10 +75,15 @@
def consider_op_ts_metacall(self, hs_f1, hs_metadesccls, *args_hs):
bookkeeper = self.bookkeeper
- fnobj = hs_f1.const._obj
+ fnobj = get_funcobj(hs_f1.const)
return hintmodel.cannot_follow_call(bookkeeper, fnobj.graph, args_hs,
lltype.typeOf(fnobj).RESULT)
+ def consider_op_oosend(self, hs_name, *args_hs):
+ assert hs_name.concretetype is ootype.Void
+ hs_obj, args_hs = args_hs[0], args_hs[1:]
+ return hs_obj.oosend(hs_name, *args_hs)
+
def simplify(self):
RPythonAnnotator.simplify(self, extra_passes=[])
Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py Sat Dec 15 13:57:29 2007
@@ -2,6 +2,8 @@
from pypy.tool.pairtype import pair, pairtype
from pypy.jit.hintannotator.bookkeeper import getbookkeeper
from pypy.rpython.lltypesystem import lltype, lloperation
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.simplify import get_funcobj
UNARY_OPERATIONS = """same_as hint getfield setfield getsubstruct getarraysize
getinteriorfield getinteriorarraysize setinteriorfield
@@ -20,6 +22,14 @@
ptr_nonzero
ptr_iszero
is_early_constant
+ oogetfield
+ oosetfield
+ oononnull
+ ooupcast
+ oodowncast
+ oois
+ subclassof
+ instanceof
""".split()
BINARY_OPERATIONS = """int_add int_sub int_mul int_mod int_and int_rshift
@@ -244,7 +254,11 @@
def __init__(self, contentdef):
self.contentdef = contentdef
- self.concretetype = lltype.Ptr(contentdef.T)
+ T = contentdef.T
+ if isinstance(T, ootype.OOType):
+ self.concretetype = T
+ else:
+ self.concretetype = lltype.Ptr(T)
def annotationcolor(self):
"""Compute the color of the variables with this annotation
@@ -339,9 +353,16 @@
FIELD_TYPE = getattr(S, hs_fieldname.const)
return variableoftype(FIELD_TYPE, hs_v1.deepfrozen)
+ def oogetfield(hs_v1, hs_fieldname):
+ _, FIELD_TYPE = hs_v1.concretetype._lookup_field(hs_fieldname.const)
+ return variableoftype(FIELD_TYPE, hs_v1.deepfrozen)
+
def setfield(hs_v1, hs_fieldname, hs_value):
pass
+ def oosetfield(hs_v1, hs_fieldname, hs_value):
+ pass
+
def getsubstruct(hs_v1, hs_fieldname):
S = hs_v1.concretetype.TO
FIELD_TYPE = getattr(S, hs_fieldname.const)
@@ -406,6 +427,9 @@
# function
return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
+ def oosend(hs_v1, hs_name, *args_hs):
+ RESTYPE = getbookkeeper().current_op_concretetype()
+ return SomeLLAbstractVariable(RESTYPE)
class __extend__(SomeLLAbstractConstant):
@@ -428,7 +452,7 @@
def direct_call(hs_f1, *args_hs):
bookkeeper = getbookkeeper()
- fnobj = hs_f1.const._obj
+ fnobj = get_funcobj(hs_f1.const)
if (bookkeeper.annotator.policy.oopspec and
hasattr(fnobj._callable, 'oopspec')):
# try to handle the call as a high-level operation
@@ -473,9 +497,34 @@
# function
return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
+ def oosend(hs_c1, hs_name, *args_hs):
+ TYPE = hs_c1.concretetype
+ name = hs_name.const
+ graph_list = TYPE._lookup_graphs(name)
+ if not graph_list:
+ # it's a method of a BuiltinType
+ bk = getbookkeeper()
+ origin = bk.myorigin()
+ d = setadd(hs_c1.origins, origin)
+ RESTYPE = bk.current_op_concretetype()
+ hs_res = SomeLLAbstractConstant(RESTYPE, d,
+ eager_concrete = hs_c1.eager_concrete,
+ myorigin = origin)
+ # if hs_c1.is_constant(): ...
+ return hs_res
+ #import pdb;pdb.set_trace()
+
def getfield(hs_c1, hs_fieldname):
S = hs_c1.concretetype.TO
FIELD_TYPE = getattr(S, hs_fieldname.const)
+ return hs_c1.getfield_impl(S, FIELD_TYPE)
+
+ def oogetfield(hs_c1, hs_fieldname):
+ S = hs_c1.concretetype
+ _, FIELD_TYPE = S._lookup_field(hs_fieldname.const)
+ return hs_c1.getfield_impl(S, FIELD_TYPE)
+
+ def getfield_impl(hs_c1, S, FIELD_TYPE):
if S._hints.get('immutable', False) or hs_c1.deepfrozen:
origin = getbookkeeper().myorigin()
d = setadd(hs_c1.origins, origin)
Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py Sat Dec 15 13:57:29 2007
@@ -20,956 +20,1002 @@
P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True,
entrypoint_returns_red=False)
-def hannotate(func, argtypes, policy=P_DEFAULT, annotator=False, inline=None,
- backendoptimize=False):
- # build the normal ll graphs for ll_function
- t = TranslationContext()
- a = t.buildannotator()
- a.build_types(func, argtypes)
- rtyper = t.buildrtyper()
- rtyper.specialize()
- if inline:
- auto_inlining(t, threshold=inline)
- if backendoptimize:
- from pypy.translator.backendopt.all import backend_optimizations
- backend_optimizations(t)
- graph1 = graphof(t, func)
-
- # build hint annotator types
- hannotator = HintAnnotator(base_translator=t, policy=policy)
- hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype,
- {OriginFlags(): True})
- for v in graph1.getargs()])
- hannotator.simplify()
- t = hannotator.translator
- if conftest.option.view:
- t.view()
- if annotator:
- return hs, hannotator
- else:
- return hs
-
-def test_simple():
- def ll_function(x, y):
- return x + y
- hs = hannotate(ll_function, [int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert len(hs.origins) == 3
- assert hs.concretetype == lltype.Signed
-
-def test_join():
- def ll_function(cond, x,y):
- if cond:
- z = x+y
- else:
- z = x-y
- return z
- hs = hannotate(ll_function, [bool, int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert len(hs.origins) == 4
- assert hs.concretetype == lltype.Signed
+class AbstractAnnotatorTest:
+ type_system = None
+
+ def hannotate(self, func, argtypes, policy=P_DEFAULT, annotator=False, inline=None,
+ backendoptimize=False):
+ # build the normal ll graphs for ll_function
+ t = TranslationContext()
+ a = t.buildannotator()
+ a.build_types(func, argtypes)
+ rtyper = t.buildrtyper(type_system = self.type_system)
+ rtyper.specialize()
+ if inline:
+ auto_inlining(t, threshold=inline)
+ if backendoptimize:
+ from pypy.translator.backendopt.all import backend_optimizations
+ backend_optimizations(t)
+ graph1 = graphof(t, func)
+
+ # build hint annotator types
+ hannotator = HintAnnotator(base_translator=t, policy=policy)
+ hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype,
+ {OriginFlags(): True})
+ for v in graph1.getargs()])
+ hannotator.simplify()
+ t = hannotator.translator
+ if conftest.option.view:
+ t.view()
+ if annotator:
+ return hs, hannotator
+ else:
+ return hs
+
+
+class BaseAnnotatorTest(AbstractAnnotatorTest):
+
+ def test_simple(self):
+ def ll_function(x, y):
+ return x + y
+ hs = self.hannotate(ll_function, [int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert len(hs.origins) == 3
+ assert hs.concretetype == lltype.Signed
+
+ def test_join(self):
+ def ll_function(cond, x,y):
+ if cond:
+ z = x+y
+ else:
+ z = x-y
+ return z
+ hs = self.hannotate(ll_function, [bool, int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert len(hs.origins) == 4
+ assert hs.concretetype == lltype.Signed
-def test_simple_hint_result():
- def ll_function(cond, x,y):
- if cond:
- z = x+y
- else:
- z = x-y
- z = hint(z, concrete=True)
- return z
- hs = hannotate(ll_function, [bool, int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.eager_concrete
- assert hs.concretetype == lltype.Signed
+ def test_simple_hint_result(self):
+ def ll_function(cond, x,y):
+ if cond:
+ z = x+y
+ else:
+ z = x-y
+ z = hint(z, concrete=True)
+ return z
+ hs = self.hannotate(ll_function, [bool, int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.eager_concrete
+ assert hs.concretetype == lltype.Signed
+
+ def test_deepfreeze(self):
+
+ A = lltype.GcArray(lltype.Signed)
+
+ def ll_function(a, i):
+ a = hint(a, deepfreeze=True)
+ res = a[i]
+ res = hint(res, concrete=True)
+
+ res = hint(res, variable=True)
+ return res
+
+ hs = self.hannotate(ll_function, [annmodel.SomePtr(lltype.Ptr(A)), int])
+ assert type(hs) is SomeLLAbstractVariable
+ assert hs.concretetype == lltype.Signed
+
+ def test_lists_deepfreeze(self):
+
+ l1 = [1,2,3,4,5]
+ l2 = [6,7,8,9,10]
+
+ def getlist(n):
+ if n:
+ return l1
+ else:
+ return l2
-def test_deepfreeze():
+ def ll_function(n, i):
+ l = getlist(n)
+ l = hint(l, deepfreeze=True)
- A = lltype.GcArray(lltype.Signed)
-
- def ll_function(a, i):
- a = hint(a, deepfreeze=True)
- res = a[i]
- res = hint(res, concrete=True)
-
- res = hint(res, variable=True)
- return res
-
- hs = hannotate(ll_function, [annmodel.SomePtr(lltype.Ptr(A)), int])
- assert type(hs) is SomeLLAbstractVariable
- assert hs.concretetype == lltype.Signed
+ res = l[i]
+ res = hint(res, concrete=True)
-def test_lists_deepfreeze():
+ res = hint(res, variable=True)
+ return res
- l1 = [1,2,3,4,5]
- l2 = [6,7,8,9,10]
-
- def getlist(n):
- if n:
- return l1
- else:
- return l2
-
- def ll_function(n, i):
- l = getlist(n)
- l = hint(l, deepfreeze=True)
-
- res = l[i]
- res = hint(res, concrete=True)
-
- res = hint(res, variable=True)
- return res
+ hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+ assert hs.concretetype == lltype.Signed
- hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
- assert hs.concretetype == lltype.Signed
+ def test_dicts_deepfreeze(self):
-def test_dicts_deepfreeze():
+ d1 = {1:2, 2:3}
+ d2 = {2:3, 3:4}
- d1 = {1:2, 2:3}
- d2 = {2:3, 3:4}
-
- def getdict(n):
- if n:
- return d1
- else:
- return d2
-
- def ll_function(n, i):
- d = getdict(n)
- d = hint(d, deepfreeze=True)
-
- res = d[i]
- res = hint(res, concrete=True)
-
- res = hint(res, variable=True)
- return res
-
- # must backendoptimize to remove the mallocs related to the interior ptrs
- hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL,
- backendoptimize=True)
- assert hs.concretetype == lltype.Signed
-
-
-def test_simple_hint_origins():
- def ll_function(cond, x,y):
- if cond:
- z = x+y
- else:
- z = x-y
- z1 = hint(z, concrete=True)
- return z # origin of z1
- hs, ha = hannotate(ll_function, [bool, int, int], annotator=True)
- assert isinstance(hs, SomeLLAbstractConstant)
- assert len(hs.origins) == 4
- assert hs.is_fixed()
- assert hs.concretetype == lltype.Signed
- ll_function_graph = graphof(ha.base_translator, ll_function)
- gdesc = ha.bookkeeper.getdesc(ll_function_graph)
- _, x_v, y_v = gdesc._cache[None].getargs()
- assert ha.binding(x_v).is_fixed()
- assert ha.binding(y_v).is_fixed()
-
-def test_simple_variable():
- def ll_function(x,y):
- x = hint(x, variable=True) # special hint only for testing purposes!!!
- return x + y
- hs = hannotate(ll_function, [int, int])
- assert type(hs) is SomeLLAbstractVariable
- assert hs.concretetype == lltype.Signed
-
-def test_simple_concrete_propagation():
- def ll_function(x,y):
- x = hint(x, concrete=True)
- return x + y
- hs = hannotate(ll_function, [int, int])
- assert type(hs) is SomeLLAbstractConstant
- assert hs.eager_concrete
- assert hs.concretetype == lltype.Signed
-
-def test_union():
- unionof = annmodel.unionof
- av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
- cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True), SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True)
- ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
- ac3 = SomeLLAbstractConstant(lltype.Signed, {})
- ac3.const = 3
- ac4 = SomeLLAbstractConstant(lltype.Signed, {})
- ac4.const = 4
- assert unionof(av1, av2) == av1
- assert unionof(cv1, cv2) == cv2
- assert unionof(ac1, ac2) == ac1
- assert unionof(ac3, ac3) == ac3
- assert unionof(ac3, ac2) == ac1
- assert unionof(ac4, ac3) == ac1
- # degenerating cases
- py.test.raises(annmodel.UnionError, "unionof(cv1, av1)")
- py.test.raises(annmodel.UnionError, "unionof(av1, cv1)")
-
- # MAYBE...
- #py.test.raises(annmodel.UnionError, "unionof(ac1, cv1)")
- #py.test.raises(annmodel.UnionError, "unionof(cv1, ac1)")
- assert unionof(cv1, ac1) == ac1
- assert unionof(ac1, cv1) == ac1
-
- # constant with values
- assert unionof(av1, ac1) == av1
- assert unionof(ac1, av1) == av1
- assert unionof(ac3, av1) == av1
- assert unionof(av2, ac4) == av1
-
-def test_op_meet():
- def meet(hs1, hs2):
- bk = HintBookkeeper(None)
- block = flowmodel.Block([])
- block.operations.append(flowmodel.SpaceOperation('x', [],
- flowmodel.Variable()))
- bk.enter(("graph", block, 0))
- bk.current_op_concretetype = lambda: lltype.Signed # hack
- return pair(hs1, hs2).int_add()
- av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
- cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, True), SomeLLAbstractConstant(lltype.Signed, {}, True)
- ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
- assert meet(av1, av2) == av1
- res = meet(cv1, cv2)
- assert res.eager_concrete
- assert isinstance(meet(ac1, ac2), SomeLLAbstractConstant)
- assert meet(ac1, cv1).eager_concrete
- assert meet(cv1, ac1).eager_concrete
- assert meet(av1, cv1) == av1
- assert meet(cv1, av1) == av1
- assert meet(ac1, av1) == av1
- assert meet(av1, ac1) == av1
-
-def test_loop():
- def ll_function(x, y):
- while x > 0:
- y += x
- x -= 1
- return y
- hs = hannotate(ll_function, [int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 4
-
-def test_loop1():
- def ll_function(x, y):
- while x > 0:
- x1 = hint(x, concrete=True)
- if x1 == 7:
+ def getdict(n):
+ if n:
+ return d1
+ else:
+ return d2
+
+ def ll_function(n, i):
+ d = getdict(n)
+ d = hint(d, deepfreeze=True)
+
+ res = d[i]
+ res = hint(res, concrete=True)
+
+ res = hint(res, variable=True)
+ return res
+
+ # must backendoptimize to remove the mallocs related to the interior ptrs
+ hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL,
+ backendoptimize=True)
+ assert hs.concretetype == lltype.Signed
+
+
+ def test_simple_hint_origins(self):
+ def ll_function(cond, x,y):
+ if cond:
+ z = x+y
+ else:
+ z = x-y
+ z1 = hint(z, concrete=True)
+ return z # origin of z1
+ hs, ha = self.hannotate(ll_function, [bool, int, int], annotator=True)
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert len(hs.origins) == 4
+ assert hs.is_fixed()
+ assert hs.concretetype == lltype.Signed
+ ll_function_graph = graphof(ha.base_translator, ll_function)
+ gdesc = ha.bookkeeper.getdesc(ll_function_graph)
+ _, x_v, y_v = gdesc._cache[None].getargs()
+ assert ha.binding(x_v).is_fixed()
+ assert ha.binding(y_v).is_fixed()
+
+ def test_simple_variable(self):
+ def ll_function(x,y):
+ x = hint(x, variable=True) # special hint only for testing purposes!!!
+ return x + y
+ hs = self.hannotate(ll_function, [int, int])
+ assert type(hs) is SomeLLAbstractVariable
+ assert hs.concretetype == lltype.Signed
+
+ def test_simple_concrete_propagation(self):
+ def ll_function(x,y):
+ x = hint(x, concrete=True)
+ return x + y
+ hs = self.hannotate(ll_function, [int, int])
+ assert type(hs) is SomeLLAbstractConstant
+ assert hs.eager_concrete
+ assert hs.concretetype == lltype.Signed
+
+ def test_union(self):
+ unionof = annmodel.unionof
+ av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
+ cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True), SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True)
+ ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
+ ac3 = SomeLLAbstractConstant(lltype.Signed, {})
+ ac3.const = 3
+ ac4 = SomeLLAbstractConstant(lltype.Signed, {})
+ ac4.const = 4
+ assert unionof(av1, av2) == av1
+ assert unionof(cv1, cv2) == cv2
+ assert unionof(ac1, ac2) == ac1
+ assert unionof(ac3, ac3) == ac3
+ assert unionof(ac3, ac2) == ac1
+ assert unionof(ac4, ac3) == ac1
+ # degenerating cases
+ py.test.raises(annmodel.UnionError, "unionof(cv1, av1)")
+ py.test.raises(annmodel.UnionError, "unionof(av1, cv1)")
+
+ # MAYBE...
+ #py.test.raises(annmodel.UnionError, "unionof(ac1, cv1)")
+ #py.test.raises(annmodel.UnionError, "unionof(cv1, ac1)")
+ assert unionof(cv1, ac1) == ac1
+ assert unionof(ac1, cv1) == ac1
+
+ # constant with values
+ assert unionof(av1, ac1) == av1
+ assert unionof(ac1, av1) == av1
+ assert unionof(ac3, av1) == av1
+ assert unionof(av2, ac4) == av1
+
+ def test_op_meet(self):
+ def meet(hs1, hs2):
+ bk = HintBookkeeper(None)
+ block = flowmodel.Block([])
+ block.operations.append(flowmodel.SpaceOperation('x', [],
+ flowmodel.Variable()))
+ bk.enter(("graph", block, 0))
+ bk.current_op_concretetype = lambda: lltype.Signed # hack
+ return pair(hs1, hs2).int_add()
+ av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
+ cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, True), SomeLLAbstractConstant(lltype.Signed, {}, True)
+ ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
+ assert meet(av1, av2) == av1
+ res = meet(cv1, cv2)
+ assert res.eager_concrete
+ assert isinstance(meet(ac1, ac2), SomeLLAbstractConstant)
+ assert meet(ac1, cv1).eager_concrete
+ assert meet(cv1, ac1).eager_concrete
+ assert meet(av1, cv1) == av1
+ assert meet(cv1, av1) == av1
+ assert meet(ac1, av1) == av1
+ assert meet(av1, ac1) == av1
+
+ def test_loop(self):
+ def ll_function(x, y):
+ while x > 0:
y += x
- x -= 1
- return y
- hs = hannotate(ll_function, [int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 4
-
-def test_simple_struct():
- S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
- ('world', lltype.Signed),
- hints={'immutable': True})
- def ll_function(s):
- return s.hello * s.world
- hs = hannotate(ll_function, [annmodel.SomePtr(lltype.Ptr(S))])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 4
-
-def test_simple_struct_malloc():
- S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
- ('world', lltype.Signed))
- def ll_function(x):
- s = lltype.malloc(S)
- s.hello = x
- return s.hello + s.world
-
- hs = hannotate(ll_function, [int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 2
-
-def test_container_union():
- S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
- ('world', lltype.Signed))
- def ll_function(cond, x, y):
- if cond:
- s = lltype.malloc(S)
+ x -= 1
+ return y
+ hs = self.hannotate(ll_function, [int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 4
+
+ def test_loop1(self):
+ def ll_function(x, y):
+ while x > 0:
+ x1 = hint(x, concrete=True)
+ if x1 == 7:
+ y += x
+ x -= 1
+ return y
+ hs = self.hannotate(ll_function, [int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 4
+
+ def test_simple_struct(self):
+ S = self.make_struct('helloworld', ('hello', lltype.Signed),
+ ('world', lltype.Signed),
+ hints={'immutable': True})
+ def ll_function(s):
+ return s.hello * s.world
+ hs = self.hannotate(ll_function, [self.annotate_struct(S)])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 4
+
+ def test_simple_struct_malloc(self):
+ S = self.make_struct('helloworld', ('hello', lltype.Signed),
+ ('world', lltype.Signed))
+ malloc = self.malloc
+ def ll_function(x):
+ s = malloc(S)
s.hello = x
- else:
- s = lltype.malloc(S)
- s.world = y
- return s.hello + s.world
+ return s.hello + s.world
- hs = hannotate(ll_function, [bool, int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 3
-
-def test_simple_call():
- def ll2(x, y, z):
- return x + (y + 42)
- def ll1(x, y, z):
- return ll2(x, y - z, x + y + z)
- hs = hannotate(ll1, [int, int, int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 5
-
-def test_simple_list_operations():
- def ll_function(x, y, index):
- l = [x]
- l.append(y)
- return l[index]
- hs = hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 4
-
-def test_some_more_list_operations():
- def ll_function(x, y, index):
- l = []
- l.append(x)
- l[0] = y
- return (l+list(l))[index]
- hs = hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
- assert len(hs.origins) == 4
-
-def test_make_a_list():
- def ll_function(x, y):
- return [x, y]
- hs = hannotate(ll_function, [int, int], policy=P_OOPSPEC)
- assert isinstance(hs, SomeLLAbstractContainer)
-
-def test_frozen_list():
- lst = [5, 7, 9]
- def ll_function(x):
- mylist = hint(lst, deepfreeze=True)
- z = mylist[x]
- hint(z, concrete=True)
- return z
- hs = hannotate(ll_function, [int], policy=P_OOPSPEC_NOVIRTUAL)
- assert hs.is_green()
-
-def test_simple_cast_pointer():
- GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
- GCS2 = lltype.GcStruct('s2', ('sub', GCS1), ('y', lltype.Signed))
- PGCS1 = lltype.Ptr(GCS1)
- PGCS2 = lltype.Ptr(GCS2)
- def ll1():
- s2 = lltype.malloc(GCS2)
- return lltype.cast_pointer(PGCS1, s2)
- hs = hannotate(ll1, [])
- assert isinstance(hs, SomeLLAbstractContainer)
- assert hs.concretetype == PGCS1
- def ll1():
- s2 = lltype.malloc(GCS2)
- s1 = s2.sub
- return lltype.cast_pointer(PGCS2, s1)
- hs = hannotate(ll1, [])
- assert isinstance(hs, SomeLLAbstractContainer)
- assert hs.concretetype == PGCS2
-
-def test_getarrayitem():
- A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
- a = lltype.malloc(A, 10)
- def ll1(n):
- v = a[n]
- v = hint(v, concrete=True)
- return v
- hs, ha = hannotate(ll1, [int], annotator=True)
- assert hs.eager_concrete
- g1 = graphof(ha.translator, ll1)
- hs_n = ha.binding(g1.getargs()[0])
- assert hs_n.origins.keys()[0].fixed
-
-def test_getvarrayitem():
- A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
- def ll1(n):
- a = lltype.malloc(A, 10)
- v = a[n]
- v = hint(v, concrete=True)
- return v
- hs, ha = hannotate(ll1, [int], annotator=True)
- assert hs.eager_concrete
- g1 = graphof(ha.translator, ll1)
- hs_n = ha.binding(g1.getargs()[0])
- assert hs_n.origins.keys()[0].fixed
-
-def test_prebuilt_structure():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- s = lltype.malloc(S)
- def ll1(n):
- s.n = n
- return s.n
- hs = hannotate(ll1, [int])
- assert isinstance(hs, SomeLLAbstractVariable)
-
-def test_degenerated_merge_substructure():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-
- def ll_function(flag):
- t = lltype.malloc(T)
- t.s.n = 3
- s = lltype.malloc(S)
- s.n = 4
- if flag:
- s = t.s
- return s, t
- hs = hannotate(ll_function, [bool])
- assert isinstance(hs, SomeLLAbstractContainer)
- assert not hs.contentdef.degenerated
- assert len(hs.contentdef.fields) == 2
- hs0 = hs.contentdef.fields['item0'].s_value # 's'
- assert isinstance(hs0, SomeLLAbstractContainer)
- assert hs0.contentdef.degenerated
- hs1 = hs.contentdef.fields['item1'].s_value # 't'
- assert isinstance(hs1, SomeLLAbstractContainer)
- assert hs1.contentdef.degenerated
-
-def test_degenerated_merge_cross_substructure():
- py.test.skip("no longer a valid test")
- from pypy.rlib import objectmodel
- S = lltype.Struct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('s1', S), ('n', lltype.Float))
-
- def ll_function(flag):
- t = lltype.malloc(T)
- t.s.n = 3
- t.s1.n = 3
- if flag:
- s = t.s
- else:
- s = t.s1
- objectmodel.keepalive_until_here(t)
- return s, t
- hs = hannotate(ll_function, [bool])
- assert isinstance(hs, SomeLLAbstractContainer)
- assert not hs.contentdef.degenerated
- assert len(hs.contentdef.fields) == 2
- hs0 = hs.contentdef.fields['item0'].s_value # 's'
- assert isinstance(hs0, SomeLLAbstractContainer)
- assert hs0.contentdef.degenerated
- hs1 = hs.contentdef.fields['item1'].s_value # 't'
- assert isinstance(hs1, SomeLLAbstractContainer)
- assert hs1.contentdef.degenerated
-
-
-def test_simple_fixed_call():
- def ll_help(cond, x, y):
- if cond:
- z = x+y
- else:
- z = x-y
- return z
- def ll_function(cond, x,y, x1, y1):
- z1 = ll_help(cond, x1, y1)
- z = ll_help(cond, x, y)
- z = hint(z, concrete=True)
- return z
- hs, ha = hannotate(ll_function, [bool, int, int, int, int], annotator=True)
- assert hs.eager_concrete
- assert hs.concretetype == lltype.Signed
- ll_help_graph = graphof(ha.base_translator, ll_help)
- gdesc = ha.bookkeeper.getdesc(ll_help_graph)
- assert not ha.binding(gdesc._cache[None].getreturnvar()).is_fixed()
- assert len(gdesc._cache) == 2
- assert ha.binding(gdesc._cache['fixed'].getreturnvar()).is_fixed()
-
-def test_specialize_calls():
- def ll_add(x, y):
- return x+y
- def ll_function(x,y):
- z0 = ll_add(y, 2)
- z1 = ll_add(x, y)
- x1 = hint(x, concrete=True)
- z2 = ll_add(x1, y)
- return z2
- hs, ha = hannotate(ll_function, [int, int], annotator=True)
- assert hs.eager_concrete
- assert hs.concretetype == lltype.Signed
- ll_add_graph = graphof(ha.base_translator, ll_add)
- gdesc = ha.bookkeeper.getdesc(ll_add_graph)
- assert len(gdesc._cache) == 2
- assert 'Exxx' in gdesc._cache
- v1, v2 = gdesc._cache['Exxx'].getargs()
-
- assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
- assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
- assert ha.binding(v1).eager_concrete
- assert not ha.binding(v2).is_fixed()
-
-def test_specialize_deepfreeze_calls():
+ hs = self.hannotate(ll_function, [int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 2
+
+ def test_container_union(self):
+ S = self.make_struct('helloworld', ('hello', lltype.Signed),
+ ('world', lltype.Signed))
+ malloc = self.malloc
+ def ll_function(cond, x, y):
+ if cond:
+ s = malloc(S)
+ s.hello = x
+ else:
+ s = malloc(S)
+ s.world = y
+ return s.hello + s.world
+
+ hs = self.hannotate(ll_function, [bool, int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 3
+
+ def test_simple_call(self):
+ def ll2(x, y, z):
+ return x + (y + 42)
+ def ll1(x, y, z):
+ return ll2(x, y - z, x + y + z)
+ hs = self.hannotate(ll1, [int, int, int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 5
+
+ def test_simple_list_operations(self):
+ def ll_function(x, y, index):
+ l = [x]
+ l.append(y)
+ return l[index]
+ hs = self.hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 4
+
+ def test_some_more_list_operations(self):
+ def ll_function(x, y, index):
+ l = []
+ l.append(x)
+ l[0] = y
+ return (l+list(l))[index]
+ hs = self.hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+ assert len(hs.origins) == 4
+
+ def test_make_a_list(self):
+ def ll_function(x, y):
+ return [x, y]
+ hs = self.hannotate(ll_function, [int, int], policy=P_OOPSPEC)
+ assert isinstance(hs, SomeLLAbstractContainer)
+
+ def test_frozen_list(self):
+ lst = [5, 7, 9]
+ def ll_function(x):
+ mylist = hint(lst, deepfreeze=True)
+ z = mylist[x]
+ hint(z, concrete=True)
+ return z
+ hs = self.hannotate(ll_function, [int], policy=P_OOPSPEC_NOVIRTUAL)
+ assert hs.is_green()
+
+ def test_prebuilt_structure(self):
+ S = self.make_struct('S', ('n', lltype.Signed))
+ s = self.malloc(S)
+ def ll1(n):
+ s.n = n
+ return s.n
+ hs = self.hannotate(ll1, [int])
+ assert isinstance(hs, SomeLLAbstractVariable)
+
+ def test_simple_fixed_call(self):
+ def ll_help(cond, x, y):
+ if cond:
+ z = x+y
+ else:
+ z = x-y
+ return z
+ def ll_function(cond, x,y, x1, y1):
+ z1 = ll_help(cond, x1, y1)
+ z = ll_help(cond, x, y)
+ z = hint(z, concrete=True)
+ return z
+ hs, ha = self.hannotate(ll_function, [bool, int, int, int, int], annotator=True)
+ assert hs.eager_concrete
+ assert hs.concretetype == lltype.Signed
+ ll_help_graph = graphof(ha.base_translator, ll_help)
+ gdesc = ha.bookkeeper.getdesc(ll_help_graph)
+ assert not ha.binding(gdesc._cache[None].getreturnvar()).is_fixed()
+ assert len(gdesc._cache) == 2
+ assert ha.binding(gdesc._cache['fixed'].getreturnvar()).is_fixed()
+
+ def test_specialize_calls(self):
+ def ll_add(x, y):
+ return x+y
+ def ll_function(x,y):
+ z0 = ll_add(y, 2)
+ z1 = ll_add(x, y)
+ x1 = hint(x, concrete=True)
+ z2 = ll_add(x1, y)
+ return z2
+ hs, ha = self.hannotate(ll_function, [int, int], annotator=True)
+ assert hs.eager_concrete
+ assert hs.concretetype == lltype.Signed
+ ll_add_graph = graphof(ha.base_translator, ll_add)
+ gdesc = ha.bookkeeper.getdesc(ll_add_graph)
+ assert len(gdesc._cache) == 2
+ assert 'Exxx' in gdesc._cache
+ v1, v2 = gdesc._cache['Exxx'].getargs()
+
+ assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
+ assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
+ assert ha.binding(v1).eager_concrete
+ assert not ha.binding(v2).is_fixed()
+
+ def test_specialize_deepfreeze_calls(self):
+
+ l1 = [1,2,3,4,5]
+ l2 = [6,7,8,9,10]
+
+ def getlist(n):
+ if n:
+ return l1
+ else:
+ return l2
- l1 = [1,2,3,4,5]
- l2 = [6,7,8,9,10]
-
- def getlist(n):
- if n:
- return l1
- else:
- return l2
+ def ll_get(l, i):
+ return l[i]
- def ll_get(l, i):
- return l[i]
+ def ll_function(n, i):
+ l = getlist(n)
- def ll_function(n, i):
- l = getlist(n)
+ l2 = ll_get(l, 0)
+
+ l = hint(l, deepfreeze=True)
+ res = ll_get(l, i)
+ return res
+
+ hs, ha = self.hannotate(ll_function, [int, int], annotator=True, policy=P_NOVIRTUAL)
+ assert hs.deepfrozen
+ assert hs.concretetype == lltype.Signed
+ ll_get_graph = graphof(ha.base_translator, ll_get)
+ gdesc = ha.bookkeeper.getdesc(ll_get_graph)
+ assert len(gdesc._cache) == 2
+ assert 'xDxx' in gdesc._cache
+ v1, v2 = gdesc._cache['xDxx'].getargs()
+
+ assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
+ assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
+ assert ha.binding(v1).deepfrozen
+
+ def test_deepfreeze_variables(self):
+ l1 = [[1], [2, 3], [4], []]
+ def ll_function(i):
+ i = hint(i, variable=True)
+ l = hint(l1, deepfreeze=True)
+ return l[i]
+
+ hs, ha = self.hannotate(ll_function, [int], annotator=True, policy=P_NOVIRTUAL)
+ assert isinstance(hs, SomeLLAbstractVariable)
+ assert hs.deepfrozen
+
+ def test_propagate_fixing_across_func_arguments(self):
+ def ll_func2(z):
+ z = hint(z, concrete=True)
+ return z + 1
+ def ll_function(cond, x,y):
+ if cond:
+ z = x+y
+ else:
+ z = x-y
+ z = ll_func2(z)
+ return z
+ hs, ha = self.hannotate(ll_function, [bool, int, int], annotator=True)
+ assert hs.eager_concrete
+ assert hs.concretetype == lltype.Signed
+ ll_function_graph = graphof(ha.base_translator, ll_function)
+ gdesc = ha.bookkeeper.getdesc(ll_function_graph)
+ _, x_v, y_v = gdesc._cache[None].getargs()
+ assert ha.binding(x_v).is_fixed()
+ assert ha.binding(y_v).is_fixed()
+
+ def test_hannotate_plus_minus(self):
+ def ll_plus_minus(s, x, y):
+ acc = x
+ n = len(s)
+ pc = 0
+ while pc < n:
+ op = s[pc]
+ op = hint(op, concrete=True)
+ if op == '+':
+ acc += y
+ elif op == '-':
+ acc -= y
+ pc += 1
+ return acc
+ assert ll_plus_minus("+-+", 0, 2) == 2
+ self.hannotate(ll_plus_minus, [str, int, int])
+ self.hannotate(ll_plus_minus, [str, int, int], inline=100000)
+
+ def test_invalid_hint_1(self):
+ S = self.make_struct('S', ('x', lltype.Signed))
+ def ll_getitem_switch(s):
+ n = s.x # -> variable
+ return hint(n, concrete=True)
+ py.test.raises(HintError, self.hannotate,
+ ll_getitem_switch, [self.annotate_struct(S)])
+
+ def undecided_relevance_test_invalid_hint_2(self):
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+ def ll_getitem_switch(s):
+ if s.x > 0: # variable exitswitch
+ sign = 1
+ else:
+ sign = -1
+ return hint(sign, concrete=True)
+ py.test.skip("in-progress: I think we expect a HintError here, do we?")
+ py.test.raises(HintError, hannotate,
+ ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
- l2 = ll_get(l, 0)
-
- l = hint(l, deepfreeze=True)
- res = ll_get(l, i)
- return res
-
- hs, ha = hannotate(ll_function, [int, int], annotator=True, policy=P_NOVIRTUAL)
- assert hs.deepfrozen
- assert hs.concretetype == lltype.Signed
- ll_get_graph = graphof(ha.base_translator, ll_get)
- gdesc = ha.bookkeeper.getdesc(ll_get_graph)
- assert len(gdesc._cache) == 2
- assert 'xDxx' in gdesc._cache
- v1, v2 = gdesc._cache['xDxx'].getargs()
-
- assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
- 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)
- return z + 1
- def ll_function(cond, x,y):
- if cond:
- z = x+y
- else:
- z = x-y
- z = ll_func2(z)
- return z
- hs, ha = hannotate(ll_function, [bool, int, int], annotator=True)
- assert hs.eager_concrete
- assert hs.concretetype == lltype.Signed
- ll_function_graph = graphof(ha.base_translator, ll_function)
- gdesc = ha.bookkeeper.getdesc(ll_function_graph)
- _, x_v, y_v = gdesc._cache[None].getargs()
- assert ha.binding(x_v).is_fixed()
- assert ha.binding(y_v).is_fixed()
-
-def test_hannotate_plus_minus():
- def ll_plus_minus(s, x, y):
- acc = x
- n = len(s)
- pc = 0
- while pc < n:
- op = s[pc]
- op = hint(op, concrete=True)
- if op == '+':
- acc += y
- elif op == '-':
- acc -= y
- pc += 1
- return acc
- assert ll_plus_minus("+-+", 0, 2) == 2
- hannotate(ll_plus_minus, [str, int, int])
- hannotate(ll_plus_minus, [str, int, int], inline=100000)
-
-def test_invalid_hint_1():
- S = lltype.GcStruct('S', ('x', lltype.Signed))
- def ll_getitem_switch(s):
- n = s.x # -> variable
- return hint(n, concrete=True)
- py.test.raises(HintError, hannotate,
- ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
-
-def undecided_relevance_test_invalid_hint_2():
- S = lltype.GcStruct('S', ('x', lltype.Signed))
- def ll_getitem_switch(s):
- if s.x > 0: # variable exitswitch
- sign = 1
- else:
- sign = -1
- return hint(sign, concrete=True)
- py.test.skip("in-progress: I think we expect a HintError here, do we?")
- py.test.raises(HintError, hannotate,
- ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
-
-
-def test_raise_exc():
- class E(Exception):
- pass
- def f1():
- raise E
- hannotate(f1, [], policy=P_OOPSPEC_NOVIRTUAL)
-
- def f2():
- e = E()
- e.a = 3
- raise e
- hannotate(f2, [], policy=P_OOPSPEC_NOVIRTUAL)
-
-def test_raise_and_catch_exc():
- class E(Exception):
- pass
- def f(flag):
- if flag:
+ def test_raise_exc(self):
+ class E(Exception):
+ pass
+ def f1():
raise E
+ self.hannotate(f1, [], policy=P_OOPSPEC_NOVIRTUAL)
- def g(flag):
- try:
- f(flag)
- except E:
- return -1
- return 0
-
- hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
-
- def f(flag):
- if flag:
+ def f2():
e = E()
e.a = 3
raise e
-
- hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.concretetype == lltype.Signed
-
-
-def test_more_green():
- def f(x):
- z = x + 1
- x2 = hint(x, concrete=True)
- return z
-
- hs = hannotate(f, [int])
- assert isinstance(hs, SomeLLAbstractConstant)
- assert hs.is_green()
- assert not hs.is_fixed()
-
-def test_blue_simple_meth():
- py.test.skip("with abstract containers this test explode in the cast_pointer annotation logic")
- class Base(object):
-
- def m(self):
- raise NotImplementedError
-
- class Concrete(Base):
-
- def m(self):
- return 42
-
- def f(flag):
- if flag:
- o = Base()
- else:
- o = Concrete()
- return o.m()
+ self.hannotate(f2, [], policy=P_OOPSPEC_NOVIRTUAL)
- hs = hannotate(f, [bool], policy=P_OOPSPEC)
+ def test_raise_and_catch_exc(self):
+ class E(Exception):
+ pass
+ def f(flag):
+ if flag:
+ raise E
+
+ def g(flag):
+ try:
+ f(flag)
+ except E:
+ return -1
+ return 0
+
+ hs = self.hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+
+ def f(flag):
+ if flag:
+ e = E()
+ e.a = 3
+ raise e
+
+ hs = self.hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.concretetype == lltype.Signed
+
+
+ def test_more_green(self):
+ def f(x):
+ z = x + 1
+ x2 = hint(x, concrete=True)
+ return z
+
+ hs = self.hannotate(f, [int])
+ assert isinstance(hs, SomeLLAbstractConstant)
+ assert hs.is_green()
+ assert not hs.is_fixed()
+
+ def test_blue_simple_meth(self):
+ py.test.skip("with abstract containers this test explode in the cast_pointer annotation logic")
+ class Base(object):
+
+ def m(self):
+ raise NotImplementedError
+
+ class Concrete(Base):
+
+ def m(self):
+ return 42
+
+ def f(flag):
+ if flag:
+ o = Base()
+ else:
+ o = Concrete()
+ return o.m()
-def test_simple_meth():
- class Base(object):
- def m(self):
- raise NotImplementedError
- pass # for inspect.getsource() bugs
-
- class Concrete(Base):
- def m(self):
- return 42
- pass # for inspect.getsource() bugs
-
- def f(flag):
- if flag:
- o = Base()
- else:
- o = Concrete()
- return o.m()
+ hs = self.hannotate(f, [bool], policy=P_OOPSPEC)
- hs = hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL)
+ def test_simple_meth(self):
+ class Base(object):
+ def m(self):
+ raise NotImplementedError
+ pass # for inspect.getsource() bugs
+
+ class Concrete(Base):
+ def m(self):
+ return 42
+ pass # for inspect.getsource() bugs
+
+ def f(flag):
+ if flag:
+ o = Base()
+ else:
+ o = Concrete()
+ return o.m()
-def test_green_isinstance():
- class Base(object):
- pass
- class Concrete(Base):
- pass
+ hs = self.hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL)
- def f(o):
- hint(o, concrete=True)
- return isinstance(o, Concrete)
- hs = hannotate(f, [Base], policy=P_OOPSPEC_NOVIRTUAL)
- assert hs.is_green()
+ def test_green_isinstance(self):
+ class Base(object):
+ pass
+ class Concrete(Base):
+ pass
+ def f(o):
+ hint(o, concrete=True)
+ return isinstance(o, Concrete)
-def test_cast_pointer_keeps_deepfreeze():
+ hs = self.hannotate(f, [Base], policy=P_OOPSPEC_NOVIRTUAL)
+ assert hs.is_green()
- class A(object):
- pass
- class B(A):
- pass
-
- def getinstance(n):
- if n:
- return A()
- else:
- return B()
-
- def ll_function(n):
- a = getinstance(n)
- a = hint(a, promote=True)
- a = hint(a, deepfreeze=True)
- if isinstance(a, B):
- return a
- return None
+ def test_cast_pointer_keeps_deepfreeze(self):
- hs = hannotate(ll_function, [int], policy=P_NOVIRTUAL)
- assert hs.deepfrozen
+ class A(object):
+ pass
+ class B(A):
+ pass
+ def getinstance(n):
+ if n:
+ return A()
+ else:
+ return B()
-def test_concrete_fnptr_for_green_call():
+ def ll_function(n):
+ a = getinstance(n)
+ a = hint(a, promote=True)
+ a = hint(a, deepfreeze=True)
- def h1(n):
- return n * 10
-
- def h2(n):
- return n + 20
-
- lst = [h1, h2]
-
- def ll_function(n, m):
- h = hint(lst, deepfreeze=True)[m]
- res = h(n)
- hint(res, concrete=True) # so 'h' gets green, so 'm' gets green
- return m
-
- hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
- assert hs.is_green()
-
-
-def test_indirect_yellow_call():
-
- def h1(n):
- return 123
-
- def h2(n):
- return 456
-
- lst = [h1, h2]
-
- def ll_function(n, m):
- h = hint(lst, deepfreeze=True)[m]
- return h(n)
-
- hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
- assert not hs.is_green()
-
-
-def test_indirect_sometimes_residual_pure_red_call():
- def h1(x):
- return x-2
- def h2(x):
- return x*4
- l = [h1, h2]
- def f(n, x):
- frozenl = hint(l, deepfreeze=True)
- h = frozenl[n&1]
- return h(x)
-
- P = StopAtXPolicy(h1)
- P.oopspec = True
- P.entrypoint_returns_red = False
- hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
- assert not hs.is_green()
- assert isinstance(hs, SomeLLAbstractConstant)
-
- tsgraph = graphof(hannotator.translator, h2)
- hs = hannotator.binding(tsgraph.getargs()[0])
- assert not hs.is_green()
-
-
-def test_indirect_sometimes_residual_red_call():
- class Stuff:
- pass
- stuff = Stuff()
- def h1(x):
- stuff.hello = 123
- return x-2
- def h2(x):
- return x*4
- l = [h1, h2]
- def f(n, x):
- frozenl = hint(l, deepfreeze=True)
- h = frozenl[n&1]
- return h(x)
-
- P = StopAtXPolicy(h1)
- P.oopspec = True
- P.entrypoint_returns_red = False
- hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
- assert not hs.is_green()
-
- tsgraph = graphof(hannotator.translator, h2)
- hs = hannotator.binding(tsgraph.getargs()[0])
- assert not hs.is_green()
-
-
-def test_indirect_sometimes_residual_pure_but_fixed_red_call():
- def h1(x):
- return x-2
- def h2(x):
- return x*4
- l = [h1, h2]
- def f(n, x):
- frozenl = hint(l, deepfreeze=True)
- h = frozenl[n&1]
- z = h(x)
- hint(z, concrete=True)
- return z
-
- P = StopAtXPolicy(h1)
- P.oopspec = True
- P.entrypoint_returns_red = False
- hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
- assert hs.is_green()
-
- #tsgraph = graphof(hannotator.translator, h2)
- #hs = hannotator.binding(tsgraph.getargs()[0])
- #assert hs.is_green()
-
- tsgraph = graphof(hannotator.translator, f)
- hs = hannotator.binding(tsgraph.getargs()[0])
- assert hs.is_green()
- hs = hannotator.binding(tsgraph.getargs()[1])
- assert hs.is_green()
-
-def test_ignore_nonjitted_path():
- def f(n):
- if we_are_jitted():
- return 5
- else:
- return n
- hs = hannotate(f, [int])
- assert hs.is_green()
-
- def g(n):
- if not we_are_jitted():
- return n
- else:
- return 5
- hs = hannotate(g, [int])
- assert hs.is_green()
-
- def g(n):
- if not we_are_jitted():
- return n
- else:
- return 5
- hs = hannotate(g, [int], backendoptimize=True)
- assert hs.is_green()
-
-
-def test_substitute_graph():
- class MetaG:
- pass # the details are only used by the timeshifter
-
- def g(m):
- return m * 17
-
- def f(n, m):
- x = g(n)
- y = g(m)
- hint(y, concrete=True)
- return g(m)
-
- class MyPolicy(HintAnnotatorPolicy):
- entrypoint_returns_red = False
- def look_inside_graph(self, graph):
- if graph.func is g:
- return MetaG # replaces g with a meta-call to metafunc()
- else:
- return True
-
- hs, hannotator = hannotate(f, [int, int], policy=MyPolicy(),
- annotator=True)
- assert hs.is_green()
- for graph in hannotator.translator.graphs:
- assert 'int_mul' not in flowmodel.summary(graph)
-
-
-def test_cast_ptr_to_int():
- GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
- def f():
- p = lltype.malloc(GCS1)
- return lltype.cast_ptr_to_int(p)
-
- hs = hannotate(f, [], policy=P_NOVIRTUAL)
- assert not hs.is_green()
-
-def test_strange_green_result_after_red_switch():
- py.test.skip("is this right?")
- class LinkedRules(object):
- _immutable_ = True
- def __init__(self, data, next=None):
- self.data = data
- self.next = next
-
- def find_applicable_rule(self, query):
- # self is green, query isn't
- # should the result really be green?
- while self:
- data = self.data
- hint(data, concrete=True)
- j = 0
- if self.data == query:
- return self
- self = self.next
+ if isinstance(a, B):
+ return a
return None
- chain = LinkedRules(1, LinkedRules(2, LinkedRules(0)))
- def f(x):
- rulechain = chain.find_applicable_rule(x)
- return rulechain
- hs = hannotate(f, [int], policy=P_OOPSPEC_NOVIRTUAL)
- assert isinstance(hs, SomeLLAbstractVariable)
-
-def test_manual_marking_of_pure_functions():
- d = {}
- def h1(s):
- try:
- return d[s]
- except KeyError:
- d[s] = r = hash(s)
- return r
- h1._pure_function_ = True
- def f(n):
- hint(n, concrete=True)
- if n == 0:
- s = "abc"
- else:
- s = "123"
- a = h1(s)
- return a
-
- P = StopAtXPolicy(h1)
- P.oopspec = True
- P.entrypoint_returns_red = False
- hs = hannotate(f, [int], policy=P)
- assert hs.is_green()
+ hs = self.hannotate(ll_function, [int], policy=P_NOVIRTUAL)
+ assert hs.deepfrozen
+
+
+ def test_concrete_fnptr_for_green_call(self):
+
+ def h1(n):
+ return n * 10
+
+ def h2(n):
+ return n + 20
+
+ lst = [h1, h2]
+
+ def ll_function(n, m):
+ h = hint(lst, deepfreeze=True)[m]
+ res = h(n)
+ hint(res, concrete=True) # so 'h' gets green, so 'm' gets green
+ return m
+
+ hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+ assert hs.is_green()
+
+
+ def test_indirect_yellow_call(self):
+
+ def h1(n):
+ return 123
+
+ def h2(n):
+ return 456
+
+ lst = [h1, h2]
+
+ def ll_function(n, m):
+ h = hint(lst, deepfreeze=True)[m]
+ return h(n)
+
+ hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+ assert not hs.is_green()
+
+
+ def test_indirect_sometimes_residual_pure_red_call(self):
+ def h1(x):
+ return x-2
+ def h2(x):
+ return x*4
+ l = [h1, h2]
+ def f(n, x):
+ frozenl = hint(l, deepfreeze=True)
+ h = frozenl[n&1]
+ return h(x)
+
+ P = StopAtXPolicy(h1)
+ P.oopspec = True
+ P.entrypoint_returns_red = False
+ hs, hannotator = self.hannotate(f, [int, int], policy=P, annotator=True)
+ assert not hs.is_green()
+ assert isinstance(hs, SomeLLAbstractConstant)
+
+ tsgraph = graphof(hannotator.translator, h2)
+ hs = hannotator.binding(tsgraph.getargs()[0])
+ assert not hs.is_green()
+
+
+ def test_indirect_sometimes_residual_red_call(self):
+ class Stuff:
+ pass
+ stuff = Stuff()
+ def h1(x):
+ stuff.hello = 123
+ return x-2
+ def h2(x):
+ return x*4
+ l = [h1, h2]
+ def f(n, x):
+ frozenl = hint(l, deepfreeze=True)
+ h = frozenl[n&1]
+ return h(x)
+
+ P = StopAtXPolicy(h1)
+ P.oopspec = True
+ P.entrypoint_returns_red = False
+ hs, hannotator = self.hannotate(f, [int, int], policy=P, annotator=True)
+ assert not hs.is_green()
+
+ tsgraph = graphof(hannotator.translator, h2)
+ hs = hannotator.binding(tsgraph.getargs()[0])
+ assert not hs.is_green()
+
+
+ def test_indirect_sometimes_residual_pure_but_fixed_red_call(self):
+ def h1(x):
+ return x-2
+ def h2(x):
+ return x*4
+ l = [h1, h2]
+ def f(n, x):
+ frozenl = hint(l, deepfreeze=True)
+ h = frozenl[n&1]
+ z = h(x)
+ hint(z, concrete=True)
+ return z
+
+ P = StopAtXPolicy(h1)
+ P.oopspec = True
+ P.entrypoint_returns_red = False
+ hs, hannotator = self.hannotate(f, [int, int], policy=P, annotator=True)
+ assert hs.is_green()
+
+ #tsgraph = graphof(hannotator.translator, h2)
+ #hs = hannotator.binding(tsgraph.getargs()[0])
+ #assert hs.is_green()
+
+ tsgraph = graphof(hannotator.translator, f)
+ hs = hannotator.binding(tsgraph.getargs()[0])
+ assert hs.is_green()
+ hs = hannotator.binding(tsgraph.getargs()[1])
+ assert hs.is_green()
+
+ def test_ignore_nonjitted_path(self):
+ def f(n):
+ if we_are_jitted():
+ return 5
+ else:
+ return n
+ hs = self.hannotate(f, [int])
+ assert hs.is_green()
+
+ def g(n):
+ if not we_are_jitted():
+ return n
+ else:
+ return 5
+ hs = self.hannotate(g, [int])
+ assert hs.is_green()
+
+ def g(n):
+ if not we_are_jitted():
+ return n
+ else:
+ return 5
+ hs = self.hannotate(g, [int], backendoptimize=True)
+ assert hs.is_green()
+
+
+ def test_substitute_graph(self):
+ class MetaG:
+ pass # the details are only used by the timeshifter
+
+ def g(m):
+ return m * 17
+
+ def f(n, m):
+ x = g(n)
+ y = g(m)
+ hint(y, concrete=True)
+ return g(m)
+
+ class MyPolicy(HintAnnotatorPolicy):
+ entrypoint_returns_red = False
+ def look_inside_graph(self, graph):
+ if graph.func is g:
+ return MetaG # replaces g with a meta-call to metafunc()
+ else:
+ return True
+
+ hs, hannotator = self.hannotate(f, [int, int], policy=MyPolicy(),
+ annotator=True)
+ assert hs.is_green()
+ for graph in hannotator.translator.graphs:
+ assert 'int_mul' not in flowmodel.summary(graph)
+
+ def test_strange_green_result_after_red_switch(self):
+ py.test.skip("is this right?")
+ class LinkedRules(object):
+ _immutable_ = True
+ def __init__(self, data, next=None):
+ self.data = data
+ self.next = next
+
+ def find_applicable_rule(self, query):
+ # self is green, query isn't
+ # should the result really be green?
+ while self:
+ data = self.data
+ hint(data, concrete=True)
+ j = 0
+ if self.data == query:
+ return self
+ self = self.next
+ return None
+
+ chain = LinkedRules(1, LinkedRules(2, LinkedRules(0)))
+ def f(x):
+ rulechain = chain.find_applicable_rule(x)
+ return rulechain
+ hs = self.hannotate(f, [int], policy=P_OOPSPEC_NOVIRTUAL)
+ assert isinstance(hs, SomeLLAbstractVariable)
+
+ def test_manual_marking_of_pure_functions(self):
+ d = {}
+ def h1(s):
+ try:
+ return d[s]
+ except KeyError:
+ d[s] = r = hash(s)
+ return r
+ h1._pure_function_ = True
+ def f(n):
+ hint(n, concrete=True)
+ if n == 0:
+ s = "abc"
+ else:
+ s = "123"
+ a = h1(s)
+ return a
+
+ P = StopAtXPolicy(h1)
+ P.oopspec = True
+ P.entrypoint_returns_red = False
+ hs = self.hannotate(f, [int], policy=P)
+ assert hs.is_green()
+
+class TestLLType(BaseAnnotatorTest):
+ type_system = 'lltype'
+
+ malloc = property(lambda self: lltype.malloc)
+
+ def make_struct(self, name, *fields, **kwds):
+ return lltype.GcStruct(name, *fields, **kwds)
+
+ def annotate_struct(self, S):
+ return annmodel.SomePtr(lltype.Ptr(S))
+
+ def test_simple_cast_pointer(self):
+ GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
+ GCS2 = lltype.GcStruct('s2', ('sub', GCS1), ('y', lltype.Signed))
+ PGCS1 = lltype.Ptr(GCS1)
+ PGCS2 = lltype.Ptr(GCS2)
+ def ll1():
+ s2 = lltype.malloc(GCS2)
+ return lltype.cast_pointer(PGCS1, s2)
+ hs = self.hannotate(ll1, [])
+ assert isinstance(hs, SomeLLAbstractContainer)
+ assert hs.concretetype == PGCS1
+ def ll1():
+ s2 = lltype.malloc(GCS2)
+ s1 = s2.sub
+ return lltype.cast_pointer(PGCS2, s1)
+ hs = self.hannotate(ll1, [])
+ assert isinstance(hs, SomeLLAbstractContainer)
+ assert hs.concretetype == PGCS2
+
+ def test_getarrayitem(self):
+ A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
+ a = lltype.malloc(A, 10)
+ def ll1(n):
+ v = a[n]
+ v = hint(v, concrete=True)
+ return v
+ hs, ha = self.hannotate(ll1, [int], annotator=True)
+ assert hs.eager_concrete
+ g1 = graphof(ha.translator, ll1)
+ hs_n = ha.binding(g1.getargs()[0])
+ assert hs_n.origins.keys()[0].fixed
+
+ def test_getvarrayitem(self):
+ A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
+ def ll1(n):
+ a = lltype.malloc(A, 10)
+ v = a[n]
+ v = hint(v, concrete=True)
+ return v
+ hs, ha = self.hannotate(ll1, [int], annotator=True)
+ assert hs.eager_concrete
+ g1 = graphof(ha.translator, ll1)
+ hs_n = ha.binding(g1.getargs()[0])
+ assert hs_n.origins.keys()[0].fixed
+
+ def test_degenerated_merge_substructure(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+
+ def ll_function(flag):
+ t = lltype.malloc(T)
+ t.s.n = 3
+ s = lltype.malloc(S)
+ s.n = 4
+ if flag:
+ s = t.s
+ return s, t
+ hs = self.hannotate(ll_function, [bool])
+ assert isinstance(hs, SomeLLAbstractContainer)
+ assert not hs.contentdef.degenerated
+ assert len(hs.contentdef.fields) == 2
+ hs0 = hs.contentdef.fields['item0'].s_value # 's'
+ assert isinstance(hs0, SomeLLAbstractContainer)
+ assert hs0.contentdef.degenerated
+ hs1 = hs.contentdef.fields['item1'].s_value # 't'
+ assert isinstance(hs1, SomeLLAbstractContainer)
+ assert hs1.contentdef.degenerated
+
+ def test_degenerated_merge_cross_substructure(self):
+ py.test.skip("no longer a valid test")
+ from pypy.rlib import objectmodel
+ S = lltype.Struct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('s1', S), ('n', lltype.Float))
+
+ def ll_function(flag):
+ t = lltype.malloc(T)
+ t.s.n = 3
+ t.s1.n = 3
+ if flag:
+ s = t.s
+ else:
+ s = t.s1
+ objectmodel.keepalive_until_here(t)
+ return s, t
+ hs = self.hannotate(ll_function, [bool])
+ assert isinstance(hs, SomeLLAbstractContainer)
+ assert not hs.contentdef.degenerated
+ assert len(hs.contentdef.fields) == 2
+ hs0 = hs.contentdef.fields['item0'].s_value # 's'
+ assert isinstance(hs0, SomeLLAbstractContainer)
+ assert hs0.contentdef.degenerated
+ hs1 = hs.contentdef.fields['item1'].s_value # 't'
+ assert isinstance(hs1, SomeLLAbstractContainer)
+ assert hs1.contentdef.degenerated
+
+ def test_cast_ptr_to_int(self):
+ GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
+ def f():
+ p = lltype.malloc(GCS1)
+ return lltype.cast_ptr_to_int(p)
+
+ hs = self.hannotate(f, [], policy=P_NOVIRTUAL)
+ assert not hs.is_green()
+
+
+class TestOOType(BaseAnnotatorTest):
+ type_system = 'ootype'
+
+ malloc = property(lambda self: ootype.new)
+
+ def make_struct(self, name, *fields, **kwds):
+ fields = dict(fields)
+ hints = kwds.pop('hints', None)
+ if hints:
+ kwds['_hints'] = hints
+ return ootype.Instance(name, ootype.ROOT, fields, **kwds)
+
+ def annotate_struct(self, S):
+ return annmodel.SomeOOInstance(S)
+
+ def skip_policy(self):
+ py.test.skip('fixme? (This policy is not relevant for now)')
+
+ test_simple_list_operations = skip_policy
+ test_some_more_list_operations = skip_policy
+ test_make_a_list = skip_policy
+ test_simple_struct_malloc = skip_policy
+ test_container_union = skip_policy
+ test_specialize_deepfreeze_calls = skip_policy
+ test_deepfreeze_variables = skip_policy
+ test_cast_pointer_keeps_deepfreeze = skip_policy
+ test_concrete_fnptr_for_green_call = skip_policy
Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py Sat Dec 15 13:57:29 2007
@@ -1,20 +1,27 @@
-from pypy.jit.hintannotator.test.test_annotator import hannotate, P_OOPSPEC
-from pypy.jit.hintannotator.test.test_annotator import P_OOPSPEC_NOVIRTUAL
+from pypy.jit.hintannotator.test.test_annotator import AbstractAnnotatorTest
+from pypy.jit.hintannotator.test.test_annotator import P_OOPSPEC, P_OOPSPEC_NOVIRTUAL
+class BaseToyTest(AbstractAnnotatorTest):
+ def test_hannotate_tl(self):
+ from pypy.jit.tl import tl
+ self.hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC)
-def test_hannotate_tl():
- from pypy.jit.tl import tl
- hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC)
-
-def test_hannotate_tl_novirtual():
- from pypy.jit.tl import tl
- hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL)
-
-def test_hannotate_tlr_novirtual():
- from pypy.jit.tl import tlr
- hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL)
-
-def test_hannotate_tlc_novirtual():
- from pypy.jit.tl import tlc
- hannotate(tlc.interp_without_call, [str, int, int],
- policy=P_OOPSPEC_NOVIRTUAL, backendoptimize=True)
+ def test_hannotate_tl_novirtual(self):
+ from pypy.jit.tl import tl
+ self.hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL)
+
+ def test_hannotate_tlr_novirtual(self):
+ from pypy.jit.tl import tlr
+ self.hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL)
+
+ def test_hannotate_tlc_novirtual(self):
+ from pypy.jit.tl import tlc
+ self.hannotate(tlc.interp_without_call, [str, int, int],
+ policy=P_OOPSPEC_NOVIRTUAL, backendoptimize=True)
+
+class TestLLType(BaseToyTest):
+ type_system = 'lltype'
+
+## XXX: all tests fail :-(
+##class TestOOType(BaseToyTest):
+## type_system = 'ootype'
Modified: pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py Sat Dec 15 13:57:29 2007
@@ -60,9 +60,6 @@
'buffer' : 'app_buffer.buffer',
'reload' : 'app_misc.reload',
- 'set' : 'app_sets.set',
- 'frozenset' : 'app_sets.frozenset',
-
'__filestub' : 'app_file_stub.file',
}
@@ -80,8 +77,8 @@
'open' : 'state.get(space).w_file',
# old-style classes dummy support
- '_classobj' : 'space.w_classobj',
- '_instance' : 'space.w_instance',
+ '_classobj' : 'interp_classobj.W_ClassObject',
+ '_instance' : 'interp_classobj.W_InstanceObject',
# default __metaclass__
'__metaclass__' : '(space.w_type)',
Modified: pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py Sat Dec 15 13:57:29 2007
@@ -110,7 +110,7 @@
getrandbits.unwrap_spec = ['self', ObjSpace, int]
-W_Random.typedef = TypeDef("W_Random",
+W_Random.typedef = TypeDef("Random",
__new__ = interp2app(descr_new__),
random = interp2app(W_Random.random),
seed = interp2app(W_Random.seed),
Modified: pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py Sat Dec 15 13:57:29 2007
@@ -2,8 +2,12 @@
from pypy.interpreter.baseobjspace import ObjSpace, W_Root
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.translator.tool.cbuild import ExternalCompilationInfo
+import sys
-eci = ExternalCompilationInfo(libraries=['crypt'])
+if sys.platform.startswith('darwin'):
+ eci = ExternalCompilationInfo()
+else:
+ eci = ExternalCompilationInfo(libraries=['crypt'])
c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP,
compilation_info=eci, threadsafe=False)
Modified: pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py Sat Dec 15 13:57:29 2007
@@ -282,15 +282,8 @@
def setup_old_style_classes(self):
"""NOT_RPYTHON"""
# sanity check that this approach is working and is not too late
- w_mod, w_dic = self.create_builtin_module('_classobj.py', 'classobj')
- w_purify = self.getitem(w_dic, self.wrap('purify'))
- w_classobj = self.getitem(w_dic, self.wrap('classobj'))
- w_instance = self.getitem(w_dic, self.wrap('instance'))
- self.call_function(w_purify)
- assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_classobj'))),"app-level code has seen dummy old style classes"
- assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_instance'))),"app-level code has seen dummy old style classes"
- self.w_classobj = w_classobj
- self.w_instance = w_instance
+ self.w_classobj = self.getattr(self.builtin, self.wrap('_classobj'))
+ self.w_instance = self.getattr(self.builtin, self.wrap('_instance'))
def create_builtin_module(self, pyname, publicname):
"""NOT_RPYTHON
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py Sat Dec 15 13:57:29 2007
@@ -61,7 +61,8 @@
assert index.startswith('item') # itemN => N
index = int(index[4:])
return parent.getitem(index + self.repeat)._as_ptr()
- elif isinstance(A, lltype.FixedSizeArray) and A.OF == self.TYPE:
+ elif (isinstance(A, lltype.FixedSizeArray) and
+ array_item_type_match(A.OF, self.TYPE)):
# for array of primitives or pointers
return lltype.direct_ptradd(firstitemptr, self.repeat)
else:
@@ -191,7 +192,7 @@
return '< ArrayItemsOffset %r >' % (self.TYPE,)
def ref(self, arrayptr):
- assert lltype.typeOf(arrayptr).TO == self.TYPE
+ assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
if isinstance(self.TYPE.OF, lltype.ContainerType):
# XXX this doesn't support empty arrays
o = arrayptr._obj.getitem(0)
@@ -228,7 +229,7 @@
return '< ArrayLengthOffset %r >' % (self.TYPE,)
def ref(self, arrayptr):
- assert lltype.typeOf(arrayptr).TO == self.TYPE
+ assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid)
@@ -405,6 +406,21 @@
# GCREF is similar to Address but it is GC-aware
GCREF = lltype.Ptr(lltype.GcOpaqueType('GCREF'))
+# A placeholder for any type that is a GcArray of pointers.
+# This can be used in the symbolic offsets above to access such arrays
+# in a generic way.
+GCARRAY_OF_PTR = lltype.GcArray(GCREF, hints={'placeholder': True})
+gcarrayofptr_lengthoffset = ArrayLengthOffset(GCARRAY_OF_PTR)
+gcarrayofptr_itemsoffset = ArrayItemsOffset(GCARRAY_OF_PTR)
+gcarrayofptr_singleitemoffset = ItemOffset(GCARRAY_OF_PTR.OF)
+def array_type_match(A1, A2):
+ return A1 == A2 or (A2 == GCARRAY_OF_PTR and
+ isinstance(A1, lltype.GcArray) and
+ isinstance(A1.OF, lltype.Ptr) and
+ not A1._hints.get('nolength'))
+def array_item_type_match(T1, T2):
+ return T1 == T2 or (T2 == GCREF and isinstance(T1, lltype.Ptr))
+
class _fakeaccessor(object):
def __init__(self, addr):
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py Sat Dec 15 13:57:29 2007
@@ -524,3 +524,21 @@
assert weakref_deref(lltype.Ptr(S), w) == lltype.nullptr(S)
assert weakref_deref(lltype.Ptr(S1), w) == lltype.nullptr(S1)
+def test_generic_gcarray_of_ptr():
+ S1 = lltype.GcStruct('S1', ('x', lltype.Signed))
+ A1 = lltype.GcArray(lltype.Ptr(S1))
+ A2 = lltype.GcArray(lltype.Ptr(A1))
+ a2 = lltype.malloc(A2, 3)
+ a2[1] = lltype.malloc(A1, 4)
+ a2[1][2] = lltype.malloc(S1)
+ a2[1][2].x = -33
+
+ adr = cast_ptr_to_adr(a2)
+ assert (adr + gcarrayofptr_lengthoffset).signed[0] == 3
+ adr += gcarrayofptr_itemsoffset
+ adr += gcarrayofptr_singleitemoffset
+ adr = adr.address[0] # => a2[1]
+ assert (adr + gcarrayofptr_lengthoffset).signed[0] == 4
+ adr += gcarrayofptr_itemsoffset + 2 * gcarrayofptr_singleitemoffset
+ adr = adr.address[0] # => s2[1][2]
+ assert (adr + FieldOffset(S1, 'x')).signed[0] == -33
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py Sat Dec 15 13:57:29 2007
@@ -8,6 +8,7 @@
needs_zero_gc_pointers = True
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
+ is_gcarrayofgcptr,
getfinalizer,
offsets_to_gc_pointers,
fixed_size, varsize_item_sizes,
@@ -18,6 +19,7 @@
self.getfinalizer = getfinalizer
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
+ self.is_gcarrayofgcptr = is_gcarrayofgcptr
self.offsets_to_gc_pointers = offsets_to_gc_pointers
self.fixed_size = fixed_size
self.varsize_item_sizes = varsize_item_sizes
@@ -115,6 +117,15 @@
Typically, 'callback' is a bound method and 'arg' can be None.
"""
typeid = self.get_type_id(obj)
+ if self.is_gcarrayofgcptr(typeid):
+ # a performance shortcut for GcArray(gcptr)
+ length = (obj + llmemory.gcarrayofptr_lengthoffset).signed[0]
+ item = obj + llmemory.gcarrayofptr_itemsoffset
+ while length > 0:
+ callback(item, arg)
+ item += llmemory.gcarrayofptr_singleitemoffset
+ length -= 1
+ return
offsets = self.offsets_to_gc_pointers(typeid)
i = 0
while i < len(offsets):
@@ -125,14 +136,13 @@
length = (obj + self.varsize_offset_to_length(typeid)).signed[0]
offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
itemlength = self.varsize_item_sizes(typeid)
- i = 0
- while i < length:
+ while length > 0:
j = 0
while j < len(offsets):
callback(item + offsets[j], arg)
j += 1
- i += 1
item += itemlength
+ length -= 1
trace._annspecialcase_ = 'specialize:arg(2)'
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py Sat Dec 15 13:57:29 2007
@@ -91,8 +91,6 @@
print "found %s initializing stores in %s" % (len(result), graph.name)
return result
-ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
-
class FrameworkGCTransformer(GCTransformer):
use_stackless = False
root_stack_depth = 163840
@@ -111,75 +109,21 @@
# for regular translation: pick the GC from the config
GCClass, GC_PARAMS = choose_gc_from_config(translator.config)
- self.FINALIZERTYPE = lltype.Ptr(ADDRESS_VOID_FUNC)
- class GCData(object):
- # types of the GC information tables
- OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
- TYPE_INFO = lltype.Struct("type_info",
- ("isvarsize", lltype.Bool),
- ("gcptrinvarsize", lltype.Bool),
- ("finalizer", self.FINALIZERTYPE),
- ("fixedsize", lltype.Signed),
- ("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)),
- ("varitemsize", lltype.Signed),
- ("ofstovar", lltype.Signed),
- ("ofstolength", lltype.Signed),
- ("varofstoptrs",lltype.Ptr(OFFSETS_TO_GC_PTR)),
- ("weakptrofs", lltype.Signed),
- )
- TYPE_INFO_TABLE = lltype.Array(TYPE_INFO)
-
- def q_is_varsize(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].isvarsize
-
- def q_has_gcptr_in_varsize(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].gcptrinvarsize
-
- def q_finalizer(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].finalizer
-
- def q_offsets_to_gc_pointers(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].ofstoptrs
-
- def q_fixed_size(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].fixedsize
-
- def q_varsize_item_sizes(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].varitemsize
-
- def q_varsize_offset_to_variable_part(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].ofstovar
-
- def q_varsize_offset_to_length(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].ofstolength
-
- def q_varsize_offsets_to_gcpointers_in_var_part(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].varofstoptrs
-
- def q_weakpointer_offset(typeid):
- ll_assert(typeid > 0, "invalid type_id")
- return gcdata.type_info_table[typeid].weakptrofs
-
self.layoutbuilder = TransformerLayoutBuilder(self)
self.get_type_id = self.layoutbuilder.get_type_id
- gcdata = GCData()
# set up dummy a table, to be overwritten with the real one in finish()
- gcdata.type_info_table = lltype.malloc(GCData.TYPE_INFO_TABLE, 0,
- immortal=True)
+ type_info_table = lltype._ptr(
+ lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE),
+ "delayed!type_info_table", solid=True)
+ gcdata = gctypelayout.GCData(type_info_table)
+
# initialize the following two fields with a random non-NULL address,
# to make the annotator happy. The fields are patched in finish()
- # to point to a real array (not 'static_roots', another one).
- a_random_address = llmemory.cast_ptr_to_adr(gcdata.type_info_table)
+ # to point to a real array.
+ foo = lltype.malloc(lltype.FixedSizeArray(llmemory.Address, 1),
+ immortal=True, zero=True)
+ a_random_address = llmemory.cast_ptr_to_adr(foo)
gcdata.static_root_start = a_random_address # patched in finish()
gcdata.static_root_nongcstart = a_random_address # patched in finish()
gcdata.static_root_end = a_random_address # patched in finish()
@@ -190,6 +134,7 @@
StackRootIterator = self.build_stack_root_iterator()
gcdata.gc = GCClass(AddressLinkedList, get_roots=StackRootIterator, **GC_PARAMS)
+ gcdata.set_query_functions(gcdata.gc)
self.num_pushs = 0
self.write_barrier_calls = 0
@@ -197,29 +142,12 @@
# run-time initialization code
StackRootIterator.setup_root_stack()
gcdata.gc.setup()
- gcdata.gc.set_query_functions(
- q_is_varsize,
- q_has_gcptr_in_varsize,
- q_finalizer,
- q_offsets_to_gc_pointers,
- q_fixed_size,
- q_varsize_item_sizes,
- q_varsize_offset_to_variable_part,
- q_varsize_offset_to_length,
- q_varsize_offsets_to_gcpointers_in_var_part,
- q_weakpointer_offset)
bk = self.translator.annotator.bookkeeper
# the point of this little dance is to not annotate
- # self.gcdata.type_info_table as a constant.
- data_classdef = bk.getuniqueclassdef(GCData)
- data_classdef.generalize_attr(
- 'type_info_table',
- annmodel.SomePtr(lltype.Ptr(GCData.TYPE_INFO_TABLE)))
- data_classdef.generalize_attr(
- 'static_roots',
- annmodel.SomePtr(lltype.Ptr(lltype.Array(llmemory.Address))))
+ # self.gcdata.static_root_xyz as constants. XXX is it still needed??
+ data_classdef = bk.getuniqueclassdef(gctypelayout.GCData)
data_classdef.generalize_attr(
'static_root_start',
annmodel.SomeAddress())
@@ -496,9 +424,10 @@
# replace the type_info_table pointer in gcdata -- at this point,
# the database is in principle complete, so it has already seen
- # the old (empty) array. We need to force it to consider the new
- # array now. It's a bit hackish as the old empty array will also
- # be generated in the C source, but that's a rather minor problem.
+ # the delayed pointer. We need to force it to consider the new
+ # array now.
+
+ self.gcdata.type_info_table._become(table)
# XXX because we call inputconst already in replace_malloc, we can't
# modify the instance, we have to modify the 'rtyped instance'
@@ -508,8 +437,6 @@
self.gcdata)
r_gcdata = self.translator.rtyper.getrepr(s_gcdata)
ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value
- ll_instance.inst_type_info_table = table
- #self.gcdata.type_info_table = table
addresses_of_static_ptrs = (
self.layoutbuilder.addresses_of_static_ptrs +
@@ -528,7 +455,7 @@
ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * (len(ll_static_roots_inside) - additional_ptrs)
newgcdependencies = []
- newgcdependencies.append(table)
+ newgcdependencies.append(self.gcdata.type_info_table)
newgcdependencies.append(ll_static_roots_inside)
self.write_typeid_list()
return newgcdependencies
@@ -543,6 +470,7 @@
all.sort()
for typeid, TYPE in all:
f.write("%s %s\n" % (typeid, TYPE))
+ f.close()
def transform_graph(self, graph):
if self.write_barrier_ptr:
@@ -573,7 +501,7 @@
c_type_id = rmodel.inputconst(lltype.Signed, type_id)
info = self.layoutbuilder.type_info_list[type_id]
- c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
+ c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE))
c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer)
@@ -592,8 +520,8 @@
c_has_finalizer, rmodel.inputconst(lltype.Bool, False)]
else:
v_length = op.args[-1]
- c_ofstolength = rmodel.inputconst(lltype.Signed, info['ofstolength'])
- c_varitemsize = rmodel.inputconst(lltype.Signed, info['varitemsize'])
+ c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
+ c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
malloc_ptr = self.malloc_varsize_clear_ptr
## if op.opname.startswith('zero'):
## malloc_ptr = self.malloc_varsize_clear_ptr
@@ -624,7 +552,7 @@
c_type_id = rmodel.inputconst(lltype.Signed, type_id)
info = self.layoutbuilder.type_info_list[type_id]
- c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
+ c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE))
assert not has_finalizer
@@ -635,8 +563,8 @@
args = [self.c_const_gc, v_coallocator, c_type_id, c_size]
else:
v_length = op.args[-1]
- c_ofstolength = rmodel.inputconst(lltype.Signed, info['ofstolength'])
- c_varitemsize = rmodel.inputconst(lltype.Signed, info['varitemsize'])
+ c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
+ c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
malloc_ptr = self.coalloc_varsize_clear_ptr
args = [self.c_const_gc, v_coallocator, c_type_id, v_length, c_size,
c_varitemsize, c_ofstolength]
@@ -698,7 +626,7 @@
c_type_id = rmodel.inputconst(lltype.Signed, type_id)
info = self.layoutbuilder.type_info_list[type_id]
- c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
+ c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
malloc_ptr = self.malloc_fixedsize_ptr
c_has_finalizer = rmodel.inputconst(lltype.Bool, False)
c_has_weakptr = c_can_collect = rmodel.inputconst(lltype.Bool, True)
@@ -856,31 +784,9 @@
[llmemory.Address],
lltype.Void)
else:
- fptr = lltype.nullptr(ADDRESS_VOID_FUNC)
+ fptr = lltype.nullptr(gctypelayout.GCData.FINALIZERTYPE.TO)
return fptr
- def offsets2table(self, offsets, TYPE):
- try:
- return self.offsettable_cache[TYPE]
- except KeyError:
- gcdata = self.transformer.gcdata
- cachedarray = lltype.malloc(gcdata.OFFSETS_TO_GC_PTR,
- len(offsets), immortal=True)
- for i, value in enumerate(offsets):
- cachedarray[i] = value
- self.offsettable_cache[TYPE] = cachedarray
- return cachedarray
-
- def flatten_table(self):
- self.can_add_new_types = False
- table = lltype.malloc(self.transformer.gcdata.TYPE_INFO_TABLE,
- len(self.type_info_list), immortal=True)
- for tableentry, newcontent in zip(table, self.type_info_list):
- for key, value in newcontent.items():
- setattr(tableentry, key, value)
- self.offsettable_cache = None
- return table
-
def gen_zero_gc_pointers(TYPE, v, llops, previous_steps=None):
if previous_steps is None:
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py Sat Dec 15 13:57:29 2007
@@ -279,7 +279,8 @@
self.need_minimal_transform(graph)
if inline:
self.graphs_to_inline[graph] = True
- return self.mixlevelannotator.graph2delayed(graph)
+ FUNCTYPE = lltype.FuncType(ll_args, ll_result)
+ return self.mixlevelannotator.graph2delayed(graph, FUNCTYPE=FUNCTYPE)
def inittime_helper(self, ll_helper, ll_args, ll_result, inline=True):
ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=inline)
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py Sat Dec 15 13:57:29 2007
@@ -1,13 +1,199 @@
from pypy.rpython.lltypesystem import lltype, llmemory, llarena
+from pypy.rlib.debug import ll_assert
+
+
+class GCData(object):
+ """The GC information tables, and the query functions that the GC
+ calls to decode their content. The encoding of this information
+ is done by encode_type_shape(). These two places should be in sync,
+ obviously, but in principle no other code should depend on the
+ details of the encoding in TYPE_INFO.
+ """
+ _alloc_flavor_ = 'raw'
+
+ OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
+ ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
+ FINALIZERTYPE = lltype.Ptr(ADDRESS_VOID_FUNC)
+
+ # structure describing the layout of a typeid
+ TYPE_INFO = lltype.Struct("type_info",
+ ("finalizer", FINALIZERTYPE),
+ ("fixedsize", lltype.Signed),
+ ("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)),
+ ("varitemsize", lltype.Signed),
+ ("ofstovar", lltype.Signed),
+ ("ofstolength", lltype.Signed),
+ ("varofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)),
+ ("weakptrofs", lltype.Signed),
+ )
+ TYPE_INFO_TABLE = lltype.Array(TYPE_INFO)
+
+ def __init__(self, type_info_table):
+ self.type_info_table = type_info_table
+ # 'type_info_table' is a list of TYPE_INFO structures when
+ # running with gcwrapper, or a real TYPE_INFO_TABLE after
+ # the gctransformer.
+
+ def q_is_varsize(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return (typeid & T_IS_FIXSIZE) == 0
+
+ def q_has_gcptr_in_varsize(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return (typeid & (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE)) == 0
+
+ def q_is_gcarrayofgcptr(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return (typeid &
+ (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE|T_NOT_SIMPLE_GCARRAY)) == 0
+
+ def q_finalizer(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].finalizer
+
+ def q_offsets_to_gc_pointers(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].ofstoptrs
+
+ def q_fixed_size(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].fixedsize
+
+ def q_varsize_item_sizes(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].varitemsize
+
+ def q_varsize_offset_to_variable_part(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].ofstovar
+
+ def q_varsize_offset_to_length(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].ofstolength
+
+ def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].varofstoptrs
+
+ def q_weakpointer_offset(self, typeid):
+ ll_assert(typeid > 0, "invalid type_id")
+ return self.type_info_table[typeid].weakptrofs
+
+ def set_query_functions(self, gc):
+ gc.set_query_functions(
+ self.q_is_varsize,
+ self.q_has_gcptr_in_varsize,
+ self.q_is_gcarrayofgcptr,
+ self.q_finalizer,
+ self.q_offsets_to_gc_pointers,
+ self.q_fixed_size,
+ self.q_varsize_item_sizes,
+ self.q_varsize_offset_to_variable_part,
+ self.q_varsize_offset_to_length,
+ self.q_varsize_offsets_to_gcpointers_in_var_part,
+ self.q_weakpointer_offset)
+
+# For the q_xxx functions that return flags, we use bit patterns
+# in the typeid instead of entries in the type_info_table. The
+# following flag combinations are used (the idea being that it's
+# very fast on CPUs to check if all flags in a set are all zero):
+
+# * if T_IS_FIXSIZE is set, the gc object is not var-sized
+# * if T_IS_FIXSIZE and T_NO_GCPTR_IN_VARSIZE are both cleared,
+# there are gc ptrs in the var-sized part
+# * if T_IS_FIXSIZE, T_NO_GCPTR_IN_VARSIZE and T_NOT_SIMPLE_GCARRAY
+# are all cleared, the shape is just like GcArray(gcptr)
+
+T_IS_FIXSIZE = 0x4
+T_NO_GCPTR_IN_VARSIZE = 0x2
+T_NOT_SIMPLE_GCARRAY = 0x1
+
+def get_typeid_bitmask(TYPE):
+ """Return the bits that we would like to be set or cleared in the type_id
+ corresponding to TYPE. This returns (mask, expected_value), where
+ the condition is that 'type_id & mask == expected_value'.
+ """
+ if not TYPE._is_varsize():
+ return (T_IS_FIXSIZE, T_IS_FIXSIZE) # not var-sized
+
+ if (isinstance(TYPE, lltype.GcArray)
+ and isinstance(TYPE.OF, lltype.Ptr)
+ and TYPE.OF.TO._gckind == 'gc'):
+ # a simple GcArray(gcptr)
+ return (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE|T_NOT_SIMPLE_GCARRAY, 0)
+
+ if isinstance(TYPE, lltype.Struct):
+ ARRAY = TYPE._flds[TYPE._arrayfld]
+ else:
+ ARRAY = TYPE
+ assert isinstance(ARRAY, lltype.Array)
+ if ARRAY.OF != lltype.Void and len(offsets_to_gc_pointers(ARRAY.OF)) > 0:
+ # var-sized, with gc pointers in the variable part
+ return (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE|T_NOT_SIMPLE_GCARRAY,
+ T_NOT_SIMPLE_GCARRAY)
+ else:
+ # var-sized, but no gc pointer in the variable part
+ return (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE, T_NO_GCPTR_IN_VARSIZE)
+
+
+def encode_type_shape(builder, info, TYPE):
+ """Encode the shape of the TYPE into the TYPE_INFO structure 'info'."""
+ offsets = offsets_to_gc_pointers(TYPE)
+ info.ofstoptrs = builder.offsets2table(offsets, TYPE)
+ info.finalizer = builder.make_finalizer_funcptr_for_type(TYPE)
+ info.weakptrofs = weakpointer_offset(TYPE)
+ if not TYPE._is_varsize():
+ #info.isvarsize = False
+ #info.gcptrinvarsize = False
+ info.fixedsize = llarena.round_up_for_allocation(
+ llmemory.sizeof(TYPE))
+ info.ofstolength = -1
+ # note about round_up_for_allocation(): in the 'info' table
+ # we put a rounded-up size only for fixed-size objects. For
+ # varsize ones, the GC must anyway compute the size at run-time
+ # and round up that result.
+ else:
+ #info.isvarsize = True
+ info.fixedsize = llmemory.sizeof(TYPE, 0)
+ if isinstance(TYPE, lltype.Struct):
+ ARRAY = TYPE._flds[TYPE._arrayfld]
+ ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
+ info.ofstolength = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
+ if ARRAY.OF != lltype.Void:
+ info.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
+ else:
+ info.fixedsize = ofs1 + llmemory.sizeof(lltype.Signed)
+ # XXX we probably don't need isrpystring any more
+ if ARRAY._hints.get('isrpystring'):
+ info.fixedsize = llmemory.sizeof(TYPE, 1)
+ else:
+ ARRAY = TYPE
+ info.ofstolength = llmemory.ArrayLengthOffset(ARRAY)
+ if ARRAY.OF != lltype.Void:
+ info.ofstovar = llmemory.itemoffsetof(TYPE, 0)
+ else:
+ info.fixedsize = (llmemory.ArrayLengthOffset(ARRAY) +
+ llmemory.sizeof(lltype.Signed))
+ assert isinstance(ARRAY, lltype.Array)
+ if ARRAY.OF != lltype.Void:
+ offsets = offsets_to_gc_pointers(ARRAY.OF)
+ else:
+ offsets = ()
+ info.varofstoptrs = builder.offsets2table(offsets, ARRAY.OF)
+ info.varitemsize = llmemory.sizeof(ARRAY.OF)
+ #info.gcptrinvarsize = len(offsets) > 0
+ #info.gcarrayofgcptr = (isinstance(TYPE, lltype.GcArray)
+ # and isinstance(TYPE.OF, lltype.Ptr)
+ # and TYPE.OF.TO._gckind == 'gc')
+
+# ____________________________________________________________
class TypeLayoutBuilder(object):
can_add_new_types = True
def __init__(self):
- dummy = {"weakptrofs": -1,
- "ofstolength": -1}
- self.type_info_list = [dummy] # don't use typeid 0, helps debugging
+ self.type_info_list = [None] # don't use typeid 0, helps debugging
self.id_of_type = {} # {LLTYPE: type_id}
self.seen_roots = {}
# the following are lists of addresses of gc pointers living inside the
@@ -20,6 +206,8 @@
# dictionary address -> list of addresses
self.additional_roots_sources = 0
self.finalizer_funcptrs = {}
+ self.offsettable_cache = {}
+ self.next_typeid_cache = {}
def get_type_id(self, TYPE):
try:
@@ -27,60 +215,56 @@
except KeyError:
assert self.can_add_new_types
assert isinstance(TYPE, (lltype.GcStruct, lltype.GcArray))
- # Record the new type_id description as a small dict for now.
- # The framework gc transformer will turn it into a
- # Struct("type_info") in flatten_table().
- type_id = len(self.type_info_list)
+ # Record the new type_id description as a TYPE_INFO structure.
+ # It goes into a list for now, which will be turned into a
+ # TYPE_INFO_TABLE in flatten_table() by the gc transformer.
+
+ # pick the next type_id with the correct bits set or cleared
+ mask, expected = get_typeid_bitmask(TYPE)
+ type_id = self.next_typeid_cache.get((mask, expected), 1)
+ while True:
+ if type_id == len(self.type_info_list):
+ self.type_info_list.append(None)
+ if (self.type_info_list[type_id] is None and
+ (type_id & mask) == expected):
+ break # can use this type_id
+ else:
+ type_id += 1 # continue searching
+ self.next_typeid_cache[mask, expected] = type_id + 1
assert type_id & 0xffff == type_id # make sure it fits into 2 bytes
- info = {}
- self.type_info_list.append(info)
+
+ # build the TYPE_INFO structure
+ info = lltype.malloc(GCData.TYPE_INFO, immortal=True, zero=True)
+ encode_type_shape(self, info, TYPE)
+ self.type_info_list[type_id] = info
self.id_of_type[TYPE] = type_id
- offsets = offsets_to_gc_pointers(TYPE)
- info["ofstoptrs"] = self.offsets2table(offsets, TYPE)
- info["finalizer"] = self.make_finalizer_funcptr_for_type(TYPE)
- info["weakptrofs"] = weakpointer_offset(TYPE)
- if not TYPE._is_varsize():
- info["isvarsize"] = False
- info["gcptrinvarsize"] = False
- info["fixedsize"] = llarena.round_up_for_allocation(
- llmemory.sizeof(TYPE))
- info["ofstolength"] = -1
- # note about round_up_for_allocation(): in the 'info' table
- # we put a rounded-up size only for fixed-size objects. For
- # varsize ones, the GC must anyway compute the size at run-time
- # and round up that result.
- else:
- info["isvarsize"] = True
- info["fixedsize"] = llmemory.sizeof(TYPE, 0)
- if isinstance(TYPE, lltype.Struct):
- ARRAY = TYPE._flds[TYPE._arrayfld]
- ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
- info["ofstolength"] = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
- if ARRAY.OF != lltype.Void:
- info["ofstovar"] = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
- else:
- info["fixedsize"] = ofs1 + llmemory.sizeof(lltype.Signed)
- if ARRAY._hints.get('isrpystring'):
- info["fixedsize"] = llmemory.sizeof(TYPE, 1)
- else:
- ARRAY = TYPE
- info["ofstolength"] = llmemory.ArrayLengthOffset(ARRAY)
- if ARRAY.OF != lltype.Void:
- info["ofstovar"] = llmemory.itemoffsetof(TYPE, 0)
- else:
- info["fixedsize"] = llmemory.ArrayLengthOffset(ARRAY) + llmemory.sizeof(lltype.Signed)
- assert isinstance(ARRAY, lltype.Array)
- if ARRAY.OF != lltype.Void:
- offsets = offsets_to_gc_pointers(ARRAY.OF)
- else:
- offsets = ()
- info["varofstoptrs"] = self.offsets2table(offsets, ARRAY.OF)
- info["varitemsize"] = llmemory.sizeof(ARRAY.OF)
- info["gcptrinvarsize"] = len(offsets) > 0
return type_id
def offsets2table(self, offsets, TYPE):
- return offsets
+ try:
+ return self.offsettable_cache[TYPE]
+ except KeyError:
+ cachedarray = lltype.malloc(GCData.OFFSETS_TO_GC_PTR,
+ len(offsets), immortal=True)
+ for i, value in enumerate(offsets):
+ cachedarray[i] = value
+ self.offsettable_cache[TYPE] = cachedarray
+ return cachedarray
+
+ def flatten_table(self):
+ self.can_add_new_types = False
+ self.offsettable_cache = None
+ table = lltype.malloc(GCData.TYPE_INFO_TABLE, len(self.type_info_list),
+ immortal=True)
+ fieldnames = GCData.TYPE_INFO._names
+ for tableentry, newcontent in zip(table, self.type_info_list):
+ if newcontent is None: # empty entry
+ tableentry.weakptrofs = -1
+ tableentry.ofstolength = -1
+ else:
+ for name in fieldnames:
+ setattr(tableentry, name, getattr(newcontent, name))
+ return table
def finalizer_funcptr_for_type(self, TYPE):
if TYPE in self.finalizer_funcptrs:
@@ -92,57 +276,8 @@
def make_finalizer_funcptr_for_type(self, TYPE):
return None # must be overridden for proper finalizer support
- def q_is_varsize(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["isvarsize"]
-
- def q_has_gcptr_in_varsize(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["gcptrinvarsize"]
-
- def q_finalizer(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["finalizer"]
-
- def q_offsets_to_gc_pointers(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["ofstoptrs"]
-
- def q_fixed_size(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["fixedsize"]
-
- def q_varsize_item_sizes(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["varitemsize"]
-
- def q_varsize_offset_to_variable_part(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["ofstovar"]
-
- def q_varsize_offset_to_length(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["ofstolength"]
-
- def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["varofstoptrs"]
-
- def q_weakpointer_offset(self, typeid):
- assert typeid > 0
- return self.type_info_list[typeid]["weakptrofs"]
-
- def get_query_functions(self):
- return (self.q_is_varsize,
- self.q_has_gcptr_in_varsize,
- self.q_finalizer,
- self.q_offsets_to_gc_pointers,
- self.q_fixed_size,
- self.q_varsize_item_sizes,
- self.q_varsize_offset_to_variable_part,
- self.q_varsize_offset_to_length,
- self.q_varsize_offsets_to_gcpointers_in_var_part,
- self.q_weakpointer_offset)
+ def initialize_gc_query_function(self, gc):
+ return GCData(self.type_info_list).set_query_functions(gc)
def consider_constant(self, TYPE, value, gc):
if value is not lltype.top_container(value):
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py Sat Dec 15 13:57:29 2007
@@ -1,5 +1,6 @@
from pypy.rpython.lltypesystem import lltype, llmemory, llheap
from pypy.rpython import llinterp
+from pypy.rpython.annlowlevel import llhelper
from pypy.rpython.memory.support import get_address_linked_list
from pypy.rpython.memory import gctypelayout
from pypy.objspace.flow.model import Constant
@@ -21,7 +22,7 @@
def prepare_graphs(self, flowgraphs):
layoutbuilder = DirectRunLayoutBuilder(self.llinterp)
self.get_type_id = layoutbuilder.get_type_id
- self.gc.set_query_functions(*layoutbuilder.get_query_functions())
+ layoutbuilder.initialize_gc_query_function(self.gc)
constants = collect_constants(flowgraphs)
for obj in constants:
@@ -144,7 +145,7 @@
DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
destrgraph = destrptr._obj.graph
else:
- return None
+ return lltype.nullptr(gctypelayout.GCData.FINALIZERTYPE.TO)
assert not type_contains_pyobjs(TYPE), "not implemented"
def ll_finalizer(addr):
@@ -154,7 +155,7 @@
except llinterp.LLException:
raise RuntimeError(
"a finalizer raised an exception, shouldn't happen")
- return ll_finalizer
+ return llhelper(gctypelayout.GCData.FINALIZERTYPE, ll_finalizer)
def collect_constants(graphs):
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py Sat Dec 15 13:57:29 2007
@@ -263,11 +263,12 @@
# We try to keep Record as similar to Instance as possible, so backends
# can treat them polymorphically, if they choose to do so.
- def __init__(self, fields):
+ def __init__(self, fields, _hints={}):
self._fields = frozendict()
for name, ITEMTYPE in fields.items():
self._fields[name] = ITEMTYPE, ITEMTYPE._defl()
self._null = _null_record(self)
+ self._hints = frozendict(_hints)
def _defl(self):
return self._null
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py Sat Dec 15 13:57:29 2007
@@ -40,6 +40,18 @@
return hop.genop('ooidentityhash', vlist,
resulttype = ootype.Signed)
+def rtype_ooupcast(hop):
+ assert isinstance(hop.args_s[0].const, ootype.Instance)
+ assert isinstance(hop.args_s[1], annmodel.SomeOOInstance)
+ v_inst = hop.inputarg(hop.args_r[1], arg=1)
+ return hop.genop('ooupcast', [v_inst], resulttype = hop.r_result.lowleveltype)
+
+def rtype_oodowncast(hop):
+ assert isinstance(hop.args_s[0].const, ootype.Instance)
+ assert isinstance(hop.args_s[1], annmodel.SomeOOInstance)
+ v_inst = hop.inputarg(hop.args_r[1], arg=1)
+ return hop.genop('oodowncast', [v_inst], resulttype = hop.r_result.lowleveltype)
+
def rtype_builtin_isinstance(hop):
if hop.s_result.is_constant():
return hop.inputconst(ootype.Bool, hop.s_result.const)
@@ -98,6 +110,8 @@
BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof
BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew
BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash
+BUILTIN_TYPER[ootype.ooupcast] = rtype_ooupcast
+BUILTIN_TYPER[ootype.oodowncast] = rtype_oodowncast
BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance
BUILTIN_TYPER[objectmodel.r_dict] = rtype_r_dict
BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py Sat Dec 15 13:57:29 2007
@@ -9,6 +9,7 @@
from pypy.translator.translator import TranslationContext, graphof
from pypy.rpython.test.test_llinterp import interpret
from pypy.rlib.objectmodel import r_dict
+from pypy.tool.error import AnnotatorError
from pypy.rpython.ootypesystem import ooregistry # side effects
def gengraph(f, args=[], viewBefore=False, viewAfter=False, mangle=True):
@@ -300,3 +301,40 @@
res = interpret(oof, [], type_system='ootype')
assert res == 42
+
+def test_ooupcast():
+ A = Instance('A', ootype.ROOT, {})
+ B = Instance('B', A, {})
+ C = Instance('C', ootype.ROOT)
+
+ def fn():
+ b = new(B)
+ return ooupcast(A, b)
+
+ res = interpret(fn, [], type_system='ootype')
+ assert typeOf(res) is A
+
+ def fn():
+ c = new(C)
+ return ooupcast(A, c)
+
+ py.test.raises(AnnotatorError, interpret, fn, [], type_system='ootype')
+
+def test_oodowncast():
+ A = Instance('A', ootype.ROOT, {})
+ B = Instance('B', A, {})
+ C = Instance('C', ootype.ROOT)
+
+ def fn():
+ b = new(B)
+ a = ooupcast(A, b)
+ return oodowncast(B, a)
+
+ res = interpret(fn, [], type_system='ootype')
+ assert typeOf(res) is B
+
+ def fn():
+ c = new(C)
+ return oodowncast(A, c)
+
+ py.test.raises(AnnotatorError, interpret, fn, [], type_system='ootype')
Modified: pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py Sat Dec 15 13:57:29 2007
@@ -666,7 +666,7 @@
if desc not in self.s_pbc.descriptions:
raise TyperError("%r not in %r" % (cls, self))
if self.lowleveltype is Void:
- return desc.pyobj
+ return None
return rclass.get_type_repr(self.rtyper).convert_desc(desc)
def convert_const(self, cls):
Modified: pypy/branch/lazy-write-barrier/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/c/database.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/c/database.py Sat Dec 15 13:57:29 2007
@@ -164,9 +164,9 @@
self.containerstats[kind] = self.containerstats.get(kind, 0) + 1
self.containerlist.append(node)
if self.completed:
- assert not node.globalcontainer
- # non-global containers are found very late, e.g. _subarrays
- # via addresses introduced by the GC transformer
+ pass # we would like to fail here, but a few containers
+ # are found very late, e.g. _subarrays via addresses
+ # introduced by the GC transformer, or the type_info_table
return node
def get(self, obj):
@@ -195,11 +195,15 @@
n = len('delayed!')
if len(name) == n:
raise
- if id(obj) in self.delayedfunctionnames:
- return self.delayedfunctionnames[id(obj)][0]
- funcname = name[n:]
- funcname = self.namespace.uniquename('g_' + funcname)
- self.delayedfunctionnames[id(obj)] = funcname, obj
+ if isinstance(lltype.typeOf(obj).TO, lltype.FuncType):
+ if id(obj) in self.delayedfunctionnames:
+ return self.delayedfunctionnames[id(obj)][0]
+ funcname = name[n:]
+ funcname = self.namespace.uniquename('g_'+funcname)
+ self.delayedfunctionnames[id(obj)] = funcname, obj
+ else:
+ funcname = None # can't use the name of a
+ # delayed non-function ptr
self.delayedfunctionptrs.append(obj)
return funcname
# /hack hack hack
Modified: pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py Sat Dec 15 13:57:29 2007
@@ -98,8 +98,9 @@
assert 0 < res <= 84
def test_id_is_weak(self):
- # test that id(obj) does not keep obj alive
+ # test that compute_unique_id(obj) does not keep obj alive
from pypy.rpython.lltypesystem.lloperation import llop
+ from pypy.rlib.objectmodel import compute_unique_id
class State:
pass
s = State()
@@ -113,11 +114,11 @@
pass
def run_once():
a = A()
- ida = id(a)
+ ida = compute_unique_id(a)
b = B()
- idb = id(b)
+ idb = compute_unique_id(b)
c = C()
- idc = id(c)
+ idc = compute_unique_id(c)
llop.gc__collect(lltype.Void)
llop.gc__collect(lltype.Void)
llop.gc__collect(lltype.Void)
Modified: pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py Sat Dec 15 13:57:29 2007
@@ -402,11 +402,13 @@
return OverloadingResolver.lltype_to_annotation(TYPE)
def specialize_call(self, hop):
- v_obj, v_type = hop.inputargs(*hop.args_r)
- if v_type.value is ootype.String or isinstance(v_type.value, (type, types.ClassType)):
+ TYPE = hop.args_v[1].value
+ v_obj = hop.inputarg(hop.args_r[0], arg=0)
+ if TYPE is ootype.String or isinstance(TYPE, (type, types.ClassType)):
return hop.genop('oodowncast', [v_obj], hop.r_result.lowleveltype)
else:
- return hop.genop('cliunbox', [v_obj, v_type], hop.r_result.lowleveltype)
+ c_type = hop.inputconst(ootype.Void, TYPE)
+ return hop.genop('cliunbox', [v_obj, c_type], hop.r_result.lowleveltype)
native_exc_cache = {}
Modified: pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py (original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py Sat Dec 15 13:57:29 2007
@@ -182,10 +182,8 @@
backends = [backend.strip() for backend in """
c
c--stackless--_faassen
- c--_faassen
+ c--_faassen--_allworkingmodules
c--thread
- c--_objspace=taint
- c--_allworkingmodules
c--gc=marksweep--_faassen
c--gc=semispace--_faassen
c--gc=generation--_faassen
More information about the Pypy-commit
mailing list