[pypy-commit] pypy callfamily: Merge rpython.rtyper.lltypesystem.rpbc into rpython.rtyper.rpbc
rlamy
noreply at buildbot.pypy.org
Sat Apr 18 21:09:58 CEST 2015
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: callfamily
Changeset: r76829:19ac7c5e6243
Date: 2015-04-18 20:10 +0100
http://bitbucket.org/pypy/pypy/changeset/19ac7c5e6243/
Log: Merge rpython.rtyper.lltypesystem.rpbc into rpython.rtyper.rpbc
diff --git a/rpython/rtyper/lltypesystem/rpbc.py b/rpython/rtyper/lltypesystem/rpbc.py
deleted file mode 100644
--- a/rpython/rtyper/lltypesystem/rpbc.py
+++ /dev/null
@@ -1,302 +0,0 @@
-import types
-
-from rpython.annotator import description
-from rpython.rlib.debug import ll_assert
-from rpython.rlib.unroll import unrolling_iterable
-from rpython.rtyper import callparse
-from rpython.rtyper.lltypesystem import llmemory
-from rpython.rtyper.lltypesystem.lltype import (typeOf, Void, ForwardReference,
- Struct, Bool, Char, Ptr, malloc, nullptr, Array, Signed)
-from rpython.rtyper.rmodel import Repr, inputconst
-from rpython.rtyper.rpbc import (
- AbstractMultipleFrozenPBCRepr,
- AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr,
- SingleFrozenPBCRepr, get_concrete_calltable)
-from rpython.rtyper.typesystem import getfunctionptr
-from rpython.tool.pairtype import pairtype
-
-
-class MultipleFrozenPBCRepr(AbstractMultipleFrozenPBCRepr):
- """Representation selected for multiple non-callable pre-built constants."""
- def __init__(self, rtyper, access_set):
- self.rtyper = rtyper
- self.access_set = access_set
- self.pbc_type = ForwardReference()
- self.lowleveltype = Ptr(self.pbc_type)
- self.pbc_cache = {}
-
- def _setup_repr(self):
- llfields = self._setup_repr_fields()
- kwds = {'hints': {'immutable': True}}
- self.pbc_type.become(Struct('pbc', *llfields, **kwds))
-
- def create_instance(self):
- return malloc(self.pbc_type, immortal=True)
-
- def null_instance(self):
- return nullptr(self.pbc_type)
-
- def getfield(self, vpbc, attr, llops):
- mangled_name, r_value = self.fieldmap[attr]
- cmangledname = inputconst(Void, mangled_name)
- return llops.genop('getfield', [vpbc, cmangledname],
- resulttype=r_value)
-
-
-class MultipleUnrelatedFrozenPBCRepr(AbstractMultipleUnrelatedFrozenPBCRepr):
- """Representation selected for multiple non-callable pre-built constants
- with no common access set."""
-
- lowleveltype = llmemory.Address
- EMPTY = Struct('pbc', hints={'immutable': True})
-
- def convert_pbc(self, pbcptr):
- return llmemory.fakeaddress(pbcptr)
-
- def create_instance(self):
- return malloc(self.EMPTY, immortal=True)
-
- def null_instance(self):
- return llmemory.Address._defl()
-
-
-class __extend__(pairtype(MultipleUnrelatedFrozenPBCRepr,
- MultipleUnrelatedFrozenPBCRepr),
- pairtype(MultipleUnrelatedFrozenPBCRepr,
- SingleFrozenPBCRepr),
- pairtype(SingleFrozenPBCRepr,
- MultipleUnrelatedFrozenPBCRepr)):
- def rtype_is_((robj1, robj2), hop):
- if isinstance(robj1, MultipleUnrelatedFrozenPBCRepr):
- r = robj1
- else:
- r = robj2
- vlist = hop.inputargs(r, r)
- return hop.genop('adr_eq', vlist, resulttype=Bool)
-
-
-class __extend__(pairtype(MultipleFrozenPBCRepr,
- MultipleUnrelatedFrozenPBCRepr)):
- def convert_from_to((robj1, robj2), v, llops):
- return llops.genop('cast_ptr_to_adr', [v], resulttype=llmemory.Address)
-
-
-# ____________________________________________________________
-
-class FunctionsPBCRepr(AbstractFunctionsPBCRepr):
- """Representation selected for a PBC of function(s)."""
-
- def setup_specfunc(self):
- fields = []
- for row in self.uniquerows:
- fields.append((row.attrname, row.fntype))
- kwds = {'hints': {'immutable': True}}
- return Ptr(Struct('specfunc', *fields, **kwds))
-
- def create_specfunc(self):
- return malloc(self.lowleveltype.TO, immortal=True)
-
- def get_specfunc_row(self, llop, v, c_rowname, resulttype):
- return llop.genop('getfield', [v, c_rowname], resulttype=resulttype)
-
-
-class SmallFunctionSetPBCRepr(Repr):
- def __init__(self, rtyper, s_pbc):
- self.rtyper = rtyper
- self.s_pbc = s_pbc
- self.callfamily = s_pbc.any_description().getcallfamily()
- llct = get_concrete_calltable(self.rtyper, self.callfamily)
- assert len(llct.uniquerows) == 1
- self.lowleveltype = Char
- self.pointer_repr = FunctionsPBCRepr(rtyper, s_pbc)
- self._conversion_tables = {}
- self._compression_function = None
- self._dispatch_cache = {}
-
- def _setup_repr(self):
- if self.s_pbc.subset_of:
- assert self.s_pbc.can_be_None == self.s_pbc.subset_of.can_be_None
- r = self.rtyper.getrepr(self.s_pbc.subset_of)
- if r is not self:
- r.setup()
- self.descriptions = r.descriptions
- self.c_pointer_table = r.c_pointer_table
- return
- self.descriptions = list(self.s_pbc.descriptions)
- if self.s_pbc.can_be_None:
- self.descriptions.insert(0, None)
- POINTER_TABLE = Array(self.pointer_repr.lowleveltype,
- hints={'nolength': True})
- pointer_table = malloc(POINTER_TABLE, len(self.descriptions),
- immortal=True)
- for i, desc in enumerate(self.descriptions):
- if desc is not None:
- pointer_table[i] = self.pointer_repr.convert_desc(desc)
- else:
- pointer_table[i] = self.pointer_repr.convert_const(None)
- self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table)
-
- def get_s_callable(self):
- return self.s_pbc
-
- def get_r_implfunc(self):
- return self, 0
-
- def get_s_signatures(self, shape):
- funcdesc = self.s_pbc.any_description()
- return funcdesc.get_s_signatures(shape)
-
- def convert_desc(self, funcdesc):
- return chr(self.descriptions.index(funcdesc))
-
- def convert_const(self, value):
- if isinstance(value, types.MethodType) and value.im_self is None:
- value = value.im_func # unbound method -> bare function
- if value is None:
- return chr(0)
- funcdesc = self.rtyper.annotator.bookkeeper.getdesc(value)
- return self.convert_desc(funcdesc)
-
- def rtype_simple_call(self, hop):
- return self.call(hop)
-
- def rtype_call_args(self, hop):
- return self.call(hop)
-
- def dispatcher(self, shape, index, argtypes, resulttype):
- key = shape, index, tuple(argtypes), resulttype
- if key in self._dispatch_cache:
- return self._dispatch_cache[key]
- from rpython.translator.unsimplify import varoftype
- from rpython.flowspace.model import FunctionGraph, Link, Block, SpaceOperation
- inputargs = [varoftype(t) for t in [Char] + argtypes]
- startblock = Block(inputargs)
- startblock.exitswitch = inputargs[0]
- graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype))
- row_of_graphs = self.callfamily.calltables[shape][index]
- links = []
- descs = list(self.s_pbc.descriptions)
- if self.s_pbc.can_be_None:
- descs.insert(0, None)
- for desc in descs:
- if desc is None:
- continue
- args_v = [varoftype(t) for t in argtypes]
- b = Block(args_v)
- llfn = self.rtyper.getcallable(row_of_graphs[desc])
- v_fn = inputconst(typeOf(llfn), llfn)
- v_result = varoftype(resulttype)
- b.operations.append(
- SpaceOperation("direct_call", [v_fn] + args_v, v_result))
- b.closeblock(Link([v_result], graph.returnblock))
- i = self.descriptions.index(desc)
- links.append(Link(inputargs[1:], b, chr(i)))
- links[-1].llexitcase = chr(i)
- startblock.closeblock(*links)
- self.rtyper.annotator.translator.graphs.append(graph)
- ll_ret = getfunctionptr(graph)
- #FTYPE = FuncType
- c_ret = self._dispatch_cache[key] = inputconst(typeOf(ll_ret), ll_ret)
- return c_ret
-
- def call(self, hop):
- bk = self.rtyper.annotator.bookkeeper
- args = hop.spaceop.build_args(hop.args_s[1:])
- s_pbc = hop.args_s[0] # possibly more precise than self.s_pbc
- descs = list(s_pbc.descriptions)
- vfcs = description.FunctionDesc.variant_for_call_site
- shape, index = vfcs(bk, self.callfamily, descs, args, hop.spaceop)
- row_of_graphs = self.callfamily.calltables[shape][index]
- anygraph = row_of_graphs.itervalues().next() # pick any witness
- vlist = [hop.inputarg(self, arg=0)]
- vlist += callparse.callparse(self.rtyper, anygraph, hop)
- rresult = callparse.getrresult(self.rtyper, anygraph)
- hop.exception_is_here()
- v_dispatcher = self.dispatcher(shape, index, [v.concretetype for v in vlist[1:]], rresult.lowleveltype)
- v_result = hop.genop('direct_call', [v_dispatcher] + vlist,
- resulttype=rresult)
- return hop.llops.convertvar(v_result, rresult, hop.r_result)
-
- def rtype_bool(self, hop):
- if not self.s_pbc.can_be_None:
- return inputconst(Bool, True)
- else:
- v1, = hop.inputargs(self)
- return hop.genop('char_ne', [v1, inputconst(Char, '\000')],
- resulttype=Bool)
-
-
-class __extend__(pairtype(SmallFunctionSetPBCRepr, FunctionsPBCRepr)):
- def convert_from_to((r_set, r_ptr), v, llops):
- if r_ptr.lowleveltype is Void:
- return inputconst(Void, None)
- else:
- assert v.concretetype is Char
- v_int = llops.genop('cast_char_to_int', [v],
- resulttype=Signed)
- return llops.genop('getarrayitem', [r_set.c_pointer_table, v_int],
- resulttype=r_ptr.lowleveltype)
-
-
-def compression_function(r_set):
- if r_set._compression_function is None:
- table = []
- for i, p in enumerate(r_set.c_pointer_table.value):
- table.append((chr(i), p))
- last_c, last_p = table[-1]
- unroll_table = unrolling_iterable(table[:-1])
-
- def ll_compress(fnptr):
- for c, p in unroll_table:
- if fnptr == p:
- return c
- else:
- ll_assert(fnptr == last_p, "unexpected function pointer")
- return last_c
- r_set._compression_function = ll_compress
- return r_set._compression_function
-
-
-class __extend__(pairtype(FunctionsPBCRepr, SmallFunctionSetPBCRepr)):
- def convert_from_to((r_ptr, r_set), v, llops):
- if r_ptr.lowleveltype is Void:
- desc, = r_ptr.s_pbc.descriptions
- return inputconst(Char, r_set.convert_desc(desc))
- else:
- ll_compress = compression_function(r_set)
- return llops.gendirectcall(ll_compress, v)
-
-
-def conversion_table(r_from, r_to):
- if r_to in r_from._conversion_tables:
- return r_from._conversion_tables[r_to]
- else:
- t = malloc(Array(Char, hints={'nolength': True}),
- len(r_from.descriptions), immortal=True)
- l = []
- for i, d in enumerate(r_from.descriptions):
- if d in r_to.descriptions:
- j = r_to.descriptions.index(d)
- l.append(j)
- t[i] = chr(j)
- else:
- l.append(None)
- if l == range(len(r_from.descriptions)):
- r = None
- else:
- r = inputconst(Ptr(Array(Char, hints={'nolength': True})), t)
- r_from._conversion_tables[r_to] = r
- return r
-
-
-class __extend__(pairtype(SmallFunctionSetPBCRepr, SmallFunctionSetPBCRepr)):
- def convert_from_to((r_from, r_to), v, llops):
- c_table = conversion_table(r_from, r_to)
- if c_table:
- assert v.concretetype is Char
- v_int = llops.genop('cast_char_to_int', [v],
- resulttype=Signed)
- return llops.genop('getarrayitem', [c_table, v_int],
- resulttype=Char)
- else:
- return v
diff --git a/rpython/rtyper/rnone.py b/rpython/rtyper/rnone.py
--- a/rpython/rtyper/rnone.py
+++ b/rpython/rtyper/rnone.py
@@ -3,7 +3,7 @@
from rpython.rtyper.rmodel import Repr, TyperError, inputconst
from rpython.rtyper.lltypesystem.lltype import Void, Bool, Ptr, Char
from rpython.rtyper.lltypesystem.llmemory import Address
-from rpython.rtyper.lltypesystem.rpbc import SmallFunctionSetPBCRepr
+from rpython.rtyper.rpbc import SmallFunctionSetPBCRepr
from rpython.rtyper.annlowlevel import llstr
from rpython.tool.pairtype import pairtype
diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -5,13 +5,20 @@
FunctionDesc, ClassDesc, MethodDesc, FrozenDesc, MethodOfFrozenDesc)
from rpython.flowspace.model import Constant
from rpython.annotator.argument import simple_args
+from rpython.rlib.debug import ll_assert
+from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper import rclass, callparse
from rpython.rtyper.rclass import CLASSTYPE, OBJECT_VTABLE, OBJECTPTR
from rpython.rtyper.error import TyperError
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem import rffi
+from rpython.rtyper.lltypesystem import llmemory
+from rpython.rtyper.lltypesystem.lltype import (typeOf, Void, ForwardReference,
+ Struct, Bool, Char, Ptr, malloc, nullptr, Array, Signed)
from rpython.rtyper.rmodel import (Repr, inputconst, CanBeNull, mangle,
warning, impossible_repr)
+from rpython.rtyper.typesystem import getfunctionptr
from rpython.tool.pairtype import pair, pairtype
+from rpython.translator.unsimplify import varoftype
def small_cand(rtyper, s_pbc):
@@ -25,8 +32,6 @@
class __extend__(annmodel.SomePBC):
def rtyper_makerepr(self, rtyper):
- from rpython.rtyper.lltypesystem.rpbc import (
- FunctionsPBCRepr, SmallFunctionSetPBCRepr)
kind = self.getKind()
if issubclass(kind, FunctionDesc):
sample = self.any_description()
@@ -124,7 +129,7 @@
concreterow[funcdesc] = llfn
assert len(concreterow) > 0
# 'llfn' should be the same for all graphs
- concreterow.fntype = lltype.typeOf(llfn)
+ concreterow.fntype = typeOf(llfn)
concreterows[shape, index] = concreterow
for row in concreterows.values():
@@ -162,7 +167,7 @@
return llct
-class AbstractFunctionsPBCRepr(CanBeNull, Repr):
+class FunctionsPBCRepr(CanBeNull, Repr):
"""Representation selected for a PBC of function(s)."""
def __init__(self, rtyper, s_pbc):
@@ -171,7 +176,7 @@
self.callfamily = s_pbc.any_description().getcallfamily()
if len(s_pbc.descriptions) == 1 and not s_pbc.can_be_None:
# a single function
- self.lowleveltype = lltype.Void
+ self.lowleveltype = Void
else:
llct = get_concrete_calltable(self.rtyper, self.callfamily)
self.concretetable = llct.table
@@ -186,6 +191,19 @@
self.lowleveltype = self.setup_specfunc()
self.funccache = {}
+ def setup_specfunc(self):
+ fields = []
+ for row in self.uniquerows:
+ fields.append((row.attrname, row.fntype))
+ kwds = {'hints': {'immutable': True}}
+ return Ptr(Struct('specfunc', *fields, **kwds))
+
+ def create_specfunc(self):
+ return malloc(self.lowleveltype.TO, immortal=True)
+
+ def get_specfunc_row(self, llop, v, c_rowname, resulttype):
+ return llop.genop('getfield', [v, c_rowname], resulttype=resulttype)
+
def get_s_callable(self):
return self.s_pbc
@@ -202,7 +220,7 @@
return self.funccache[funcdesc]
except KeyError:
pass
- if self.lowleveltype is lltype.Void:
+ if self.lowleveltype is Void:
result = None
else:
llfns = {}
@@ -238,7 +256,7 @@
value = value.im_func # unbound method -> bare function
elif isinstance(value, staticmethod):
value = value.__get__(42) # hackish, get the function wrapped by staticmethod
- if self.lowleveltype is lltype.Void:
+ if self.lowleveltype is Void:
return None
if value is None:
null = self.rtyper.type_system.null_callable(self.lowleveltype)
@@ -252,27 +270,27 @@
'index' and 'shape' tells which of its items we are interested in.
"""
assert v.concretetype == self.lowleveltype
- if self.lowleveltype is lltype.Void:
+ if self.lowleveltype is Void:
assert len(self.s_pbc.descriptions) == 1
# lowleveltype wouldn't be Void otherwise
funcdesc, = self.s_pbc.descriptions
row_of_one_graph = self.callfamily.calltables[shape][index]
graph = row_of_one_graph[funcdesc]
llfn = self.rtyper.getcallable(graph)
- return inputconst(lltype.typeOf(llfn), llfn)
+ return inputconst(typeOf(llfn), llfn)
elif len(self.uniquerows) == 1:
return v
else:
# 'v' is a Struct pointer, read the corresponding field
row = self.concretetable[shape, index]
- cname = inputconst(lltype.Void, row.attrname)
+ cname = inputconst(Void, row.attrname)
return self.get_specfunc_row(llop, v, cname, row.fntype)
def get_unique_llfn(self):
# try to build a unique low-level function. Avoid to use
# whenever possible! Doesn't work with specialization, multiple
# different call sites, etc.
- if self.lowleveltype is not lltype.Void:
+ if self.lowleveltype is not Void:
raise TyperError("cannot pass multiple functions here")
assert len(self.s_pbc.descriptions) == 1
# lowleveltype wouldn't be Void otherwise
@@ -294,7 +312,7 @@
if graphs != [graph] * len(graphs):
raise TyperError("cannot pass a specialized function here")
llfn = self.rtyper.getcallable(graph)
- return inputconst(lltype.typeOf(llfn), llfn)
+ return inputconst(typeOf(llfn), llfn)
def get_concrete_llfn(self, s_pbc, args_s, op):
bk = self.rtyper.annotator.bookkeeper
@@ -306,7 +324,7 @@
row_of_one_graph = self.callfamily.calltables[shape][index]
graph = row_of_one_graph[funcdesc]
llfn = self.rtyper.getcallable(graph)
- return inputconst(lltype.typeOf(llfn), llfn)
+ return inputconst(typeOf(llfn), llfn)
def rtype_simple_call(self, hop):
return self.call(hop)
@@ -332,28 +350,227 @@
if isinstance(vlist[0], Constant):
v = hop.genop('direct_call', vlist, resulttype=rresult)
else:
- vlist.append(hop.inputconst(lltype.Void, row_of_graphs.values()))
+ vlist.append(hop.inputconst(Void, row_of_graphs.values()))
v = hop.genop('indirect_call', vlist, resulttype=rresult)
if hop.r_result is impossible_repr:
return None # see test_always_raising_methods
else:
return hop.llops.convertvar(v, rresult, hop.r_result)
-class __extend__(pairtype(AbstractFunctionsPBCRepr, AbstractFunctionsPBCRepr)):
+class __extend__(pairtype(FunctionsPBCRepr, FunctionsPBCRepr)):
def convert_from_to((r_fpbc1, r_fpbc2), v, llops):
# this check makes sense because both source and dest repr are FunctionsPBCRepr
if r_fpbc1.lowleveltype == r_fpbc2.lowleveltype:
return v
- if r_fpbc1.lowleveltype is lltype.Void:
+ if r_fpbc1.lowleveltype is Void:
return inputconst(r_fpbc2, r_fpbc1.s_pbc.const)
- if r_fpbc2.lowleveltype is lltype.Void:
- return inputconst(lltype.Void, None)
+ if r_fpbc2.lowleveltype is Void:
+ return inputconst(Void, None)
return NotImplemented
+class SmallFunctionSetPBCRepr(Repr):
+ def __init__(self, rtyper, s_pbc):
+ self.rtyper = rtyper
+ self.s_pbc = s_pbc
+ self.callfamily = s_pbc.any_description().getcallfamily()
+ llct = get_concrete_calltable(self.rtyper, self.callfamily)
+ assert len(llct.uniquerows) == 1
+ self.lowleveltype = Char
+ self.pointer_repr = FunctionsPBCRepr(rtyper, s_pbc)
+ self._conversion_tables = {}
+ self._compression_function = None
+ self._dispatch_cache = {}
+
+ def _setup_repr(self):
+ if self.s_pbc.subset_of:
+ assert self.s_pbc.can_be_None == self.s_pbc.subset_of.can_be_None
+ r = self.rtyper.getrepr(self.s_pbc.subset_of)
+ if r is not self:
+ r.setup()
+ self.descriptions = r.descriptions
+ self.c_pointer_table = r.c_pointer_table
+ return
+ self.descriptions = list(self.s_pbc.descriptions)
+ if self.s_pbc.can_be_None:
+ self.descriptions.insert(0, None)
+ POINTER_TABLE = Array(self.pointer_repr.lowleveltype,
+ hints={'nolength': True})
+ pointer_table = malloc(POINTER_TABLE, len(self.descriptions),
+ immortal=True)
+ for i, desc in enumerate(self.descriptions):
+ if desc is not None:
+ pointer_table[i] = self.pointer_repr.convert_desc(desc)
+ else:
+ pointer_table[i] = self.pointer_repr.convert_const(None)
+ self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table)
+
+ def get_s_callable(self):
+ return self.s_pbc
+
+ def get_r_implfunc(self):
+ return self, 0
+
+ def get_s_signatures(self, shape):
+ funcdesc = self.s_pbc.any_description()
+ return funcdesc.get_s_signatures(shape)
+
+ def convert_desc(self, funcdesc):
+ return chr(self.descriptions.index(funcdesc))
+
+ def convert_const(self, value):
+ if isinstance(value, types.MethodType) and value.im_self is None:
+ value = value.im_func # unbound method -> bare function
+ if value is None:
+ return chr(0)
+ funcdesc = self.rtyper.annotator.bookkeeper.getdesc(value)
+ return self.convert_desc(funcdesc)
+
+ def rtype_simple_call(self, hop):
+ return self.call(hop)
+
+ def rtype_call_args(self, hop):
+ return self.call(hop)
+
+ def dispatcher(self, shape, index, argtypes, resulttype):
+ key = shape, index, tuple(argtypes), resulttype
+ if key in self._dispatch_cache:
+ return self._dispatch_cache[key]
+ inputargs = [varoftype(t) for t in [Char] + argtypes]
+ startblock = Block(inputargs)
+ startblock.exitswitch = inputargs[0]
+ graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype))
+ row_of_graphs = self.callfamily.calltables[shape][index]
+ links = []
+ descs = list(self.s_pbc.descriptions)
+ if self.s_pbc.can_be_None:
+ descs.insert(0, None)
+ for desc in descs:
+ if desc is None:
+ continue
+ args_v = [varoftype(t) for t in argtypes]
+ b = Block(args_v)
+ llfn = self.rtyper.getcallable(row_of_graphs[desc])
+ v_fn = inputconst(typeOf(llfn), llfn)
+ v_result = varoftype(resulttype)
+ b.operations.append(
+ SpaceOperation("direct_call", [v_fn] + args_v, v_result))
+ b.closeblock(Link([v_result], graph.returnblock))
+ i = self.descriptions.index(desc)
+ links.append(Link(inputargs[1:], b, chr(i)))
+ links[-1].llexitcase = chr(i)
+ startblock.closeblock(*links)
+ self.rtyper.annotator.translator.graphs.append(graph)
+ ll_ret = getfunctionptr(graph)
+ #FTYPE = FuncType
+ c_ret = self._dispatch_cache[key] = inputconst(typeOf(ll_ret), ll_ret)
+ return c_ret
+
+ def call(self, hop):
+ bk = self.rtyper.annotator.bookkeeper
+ args = hop.spaceop.build_args(hop.args_s[1:])
+ s_pbc = hop.args_s[0] # possibly more precise than self.s_pbc
+ descs = list(s_pbc.descriptions)
+ vfcs = FunctionDesc.variant_for_call_site
+ shape, index = vfcs(bk, self.callfamily, descs, args, hop.spaceop)
+ row_of_graphs = self.callfamily.calltables[shape][index]
+ anygraph = row_of_graphs.itervalues().next() # pick any witness
+ vlist = [hop.inputarg(self, arg=0)]
+ vlist += callparse.callparse(self.rtyper, anygraph, hop)
+ rresult = callparse.getrresult(self.rtyper, anygraph)
+ hop.exception_is_here()
+ v_dispatcher = self.dispatcher(shape, index,
+ [v.concretetype for v in vlist[1:]], rresult.lowleveltype)
+ v_result = hop.genop('direct_call', [v_dispatcher] + vlist,
+ resulttype=rresult)
+ return hop.llops.convertvar(v_result, rresult, hop.r_result)
+
+ def rtype_bool(self, hop):
+ if not self.s_pbc.can_be_None:
+ return inputconst(Bool, True)
+ else:
+ v1, = hop.inputargs(self)
+ return hop.genop('char_ne', [v1, inputconst(Char, '\000')],
+ resulttype=Bool)
+
+
+class __extend__(pairtype(SmallFunctionSetPBCRepr, FunctionsPBCRepr)):
+ def convert_from_to((r_set, r_ptr), v, llops):
+ if r_ptr.lowleveltype is Void:
+ return inputconst(Void, None)
+ else:
+ assert v.concretetype is Char
+ v_int = llops.genop('cast_char_to_int', [v],
+ resulttype=Signed)
+ return llops.genop('getarrayitem', [r_set.c_pointer_table, v_int],
+ resulttype=r_ptr.lowleveltype)
+
+
+def compression_function(r_set):
+ if r_set._compression_function is None:
+ table = []
+ for i, p in enumerate(r_set.c_pointer_table.value):
+ table.append((chr(i), p))
+ last_c, last_p = table[-1]
+ unroll_table = unrolling_iterable(table[:-1])
+
+ def ll_compress(fnptr):
+ for c, p in unroll_table:
+ if fnptr == p:
+ return c
+ else:
+ ll_assert(fnptr == last_p, "unexpected function pointer")
+ return last_c
+ r_set._compression_function = ll_compress
+ return r_set._compression_function
+
+
+class __extend__(pairtype(FunctionsPBCRepr, SmallFunctionSetPBCRepr)):
+ def convert_from_to((r_ptr, r_set), v, llops):
+ if r_ptr.lowleveltype is Void:
+ desc, = r_ptr.s_pbc.descriptions
+ return inputconst(Char, r_set.convert_desc(desc))
+ else:
+ ll_compress = compression_function(r_set)
+ return llops.gendirectcall(ll_compress, v)
+
+
+def conversion_table(r_from, r_to):
+ if r_to in r_from._conversion_tables:
+ return r_from._conversion_tables[r_to]
+ else:
+ t = malloc(Array(Char, hints={'nolength': True}),
+ len(r_from.descriptions), immortal=True)
+ l = []
+ for i, d in enumerate(r_from.descriptions):
+ if d in r_to.descriptions:
+ j = r_to.descriptions.index(d)
+ l.append(j)
+ t[i] = chr(j)
+ else:
+ l.append(None)
+ if l == range(len(r_from.descriptions)):
+ r = None
+ else:
+ r = inputconst(Ptr(Array(Char, hints={'nolength': True})), t)
+ r_from._conversion_tables[r_to] = r
+ return r
+
+
+class __extend__(pairtype(SmallFunctionSetPBCRepr, SmallFunctionSetPBCRepr)):
+ def convert_from_to((r_from, r_to), v, llops):
+ c_table = conversion_table(r_from, r_to)
+ if c_table:
+ assert v.concretetype is Char
+ v_int = llops.genop('cast_char_to_int', [v],
+ resulttype=Signed)
+ return llops.genop('getarrayitem', [c_table, v_int],
+ resulttype=Char)
+ else:
+ return v
+
+
def getFrozenPBCRepr(rtyper, s_pbc):
- from rpython.rtyper.lltypesystem.rpbc import (
- MultipleUnrelatedFrozenPBCRepr, MultipleFrozenPBCRepr)
descs = list(s_pbc.descriptions)
assert len(descs) >= 1
if len(descs) == 1 and not s_pbc.can_be_None:
@@ -380,7 +597,7 @@
class SingleFrozenPBCRepr(Repr):
"""Representation selected for a single non-callable pre-built constant."""
- lowleveltype = lltype.Void
+ lowleveltype = Void
def __init__(self, frozendesc):
self.frozendesc = frozendesc
@@ -405,9 +622,18 @@
return self.getstr()
-class AbstractMultipleUnrelatedFrozenPBCRepr(CanBeNull, Repr):
+class MultipleFrozenPBCReprBase(CanBeNull, Repr):
+ def convert_const(self, pbc):
+ if pbc is None:
+ return self.null_instance()
+ frozendesc = self.rtyper.annotator.bookkeeper.getdesc(pbc)
+ return self.convert_desc(frozendesc)
+
+class MultipleUnrelatedFrozenPBCRepr(MultipleFrozenPBCReprBase):
"""For a SomePBC of frozen PBCs that have no common access set.
The only possible operation on such a thing is comparison with 'is'."""
+ lowleveltype = llmemory.Address
+ EMPTY = Struct('pbc', hints={'immutable': True})
def __init__(self, rtyper):
self.rtyper = rtyper
@@ -418,7 +644,7 @@
return self.converted_pbc_cache[frozendesc]
except KeyError:
r = self.rtyper.getrepr(annmodel.SomePBC([frozendesc]))
- if r.lowleveltype is lltype.Void:
+ if r.lowleveltype is Void:
# must create a new empty structure, as a placeholder
pbc = self.create_instance()
else:
@@ -427,20 +653,62 @@
self.converted_pbc_cache[frozendesc] = convpbc
return convpbc
- def convert_const(self, pbc):
- if pbc is None:
- return self.null_instance()
- frozendesc = self.rtyper.annotator.bookkeeper.getdesc(pbc)
- return self.convert_desc(frozendesc)
+ def convert_pbc(self, pbcptr):
+ return llmemory.fakeaddress(pbcptr)
+
+ def create_instance(self):
+ return malloc(self.EMPTY, immortal=True)
+
+ def null_instance(self):
+ return llmemory.Address._defl()
def rtype_getattr(_, hop):
if not hop.s_result.is_constant():
raise TyperError("getattr on a constant PBC returns a non-constant")
return hop.inputconst(hop.r_result, hop.s_result.const)
-class AbstractMultipleFrozenPBCRepr(AbstractMultipleUnrelatedFrozenPBCRepr):
+class __extend__(pairtype(MultipleUnrelatedFrozenPBCRepr,
+ MultipleUnrelatedFrozenPBCRepr),
+ pairtype(MultipleUnrelatedFrozenPBCRepr,
+ SingleFrozenPBCRepr),
+ pairtype(SingleFrozenPBCRepr,
+ MultipleUnrelatedFrozenPBCRepr)):
+ def rtype_is_((robj1, robj2), hop):
+ if isinstance(robj1, MultipleUnrelatedFrozenPBCRepr):
+ r = robj1
+ else:
+ r = robj2
+ vlist = hop.inputargs(r, r)
+ return hop.genop('adr_eq', vlist, resulttype=Bool)
+
+
+class MultipleFrozenPBCRepr(MultipleFrozenPBCReprBase):
"""For a SomePBC of frozen PBCs with a common attribute access set."""
+ def __init__(self, rtyper, access_set):
+ self.rtyper = rtyper
+ self.access_set = access_set
+ self.pbc_type = ForwardReference()
+ self.lowleveltype = Ptr(self.pbc_type)
+ self.pbc_cache = {}
+
+ def _setup_repr(self):
+ llfields = self._setup_repr_fields()
+ kwds = {'hints': {'immutable': True}}
+ self.pbc_type.become(Struct('pbc', *llfields, **kwds))
+
+ def create_instance(self):
+ return malloc(self.pbc_type, immortal=True)
+
+ def null_instance(self):
+ return nullptr(self.pbc_type)
+
+ def getfield(self, vpbc, attr, llops):
+ mangled_name, r_value = self.fieldmap[attr]
+ cmangledname = inputconst(Void, mangled_name)
+ return llops.genop('getfield', [vpbc, cmangledname],
+ resulttype=r_value)
+
def _setup_repr_fields(self):
fields = []
self.fieldmap = {}
@@ -466,7 +734,7 @@
result = self.create_instance()
self.pbc_cache[frozendesc] = result
for attr, (mangled_name, r_value) in self.fieldmap.items():
- if r_value.lowleveltype is lltype.Void:
+ if r_value.lowleveltype is Void:
continue
try:
thisattrvalue = frozendesc.attrcache[attr]
@@ -483,18 +751,23 @@
return hop.inputconst(hop.r_result, hop.s_result.const)
attr = hop.args_s[1].const
- vpbc, vattr = hop.inputargs(self, lltype.Void)
+ vpbc, vattr = hop.inputargs(self, Void)
v_res = self.getfield(vpbc, attr, hop.llops)
mangled_name, r_res = self.fieldmap[attr]
return hop.llops.convertvar(v_res, r_res, hop.r_result)
-class __extend__(pairtype(AbstractMultipleFrozenPBCRepr, AbstractMultipleFrozenPBCRepr)):
+class __extend__(pairtype(MultipleFrozenPBCRepr,
+ MultipleUnrelatedFrozenPBCRepr)):
+ def convert_from_to((robj1, robj2), v, llops):
+ return llops.genop('cast_ptr_to_adr', [v], resulttype=llmemory.Address)
+
+class __extend__(pairtype(MultipleFrozenPBCRepr, MultipleFrozenPBCRepr)):
def convert_from_to((r_pbc1, r_pbc2), v, llops):
if r_pbc1.access_set == r_pbc2.access_set:
return v
return NotImplemented
-class __extend__(pairtype(SingleFrozenPBCRepr, AbstractMultipleFrozenPBCRepr)):
+class __extend__(pairtype(SingleFrozenPBCRepr, MultipleFrozenPBCRepr)):
def convert_from_to((r_pbc1, r_pbc2), v, llops):
frozendesc1 = r_pbc1.frozendesc
access = frozendesc1.queryattrfamily()
@@ -504,10 +777,10 @@
return Constant(value, lltype)
return NotImplemented
-class __extend__(pairtype(AbstractMultipleUnrelatedFrozenPBCRepr,
+class __extend__(pairtype(MultipleFrozenPBCReprBase,
SingleFrozenPBCRepr)):
def convert_from_to((r_pbc1, r_pbc2), v, llops):
- return inputconst(lltype.Void, r_pbc2.frozendesc)
+ return inputconst(Void, r_pbc2.frozendesc)
class MethodOfFrozenPBCRepr(Repr):
@@ -601,7 +874,7 @@
# raise TyperError("unsupported: variable of type "
# "class-pointer or None")
if s_pbc.is_constant():
- self.lowleveltype = lltype.Void
+ self.lowleveltype = Void
else:
self.lowleveltype = self.getlowleveltype()
@@ -624,7 +897,7 @@
def convert_desc(self, desc):
if desc not in self.s_pbc.descriptions:
raise TyperError("%r not in %r" % (desc, self))
- if self.lowleveltype is lltype.Void:
+ if self.lowleveltype is Void:
return None
subclassdef = desc.getuniqueclassdef()
r_subclass = rclass.getclassrepr(self.rtyper, subclassdef)
@@ -632,7 +905,7 @@
def convert_const(self, cls):
if cls is None:
- if self.lowleveltype is lltype.Void:
+ if self.lowleveltype is Void:
return None
else:
T = self.lowleveltype
@@ -649,12 +922,12 @@
if attr == '__name__':
from rpython.rtyper.lltypesystem import rstr
class_repr = self.rtyper.rootclass_repr
- vcls, vattr = hop.inputargs(class_repr, lltype.Void)
- cname = inputconst(lltype.Void, 'name')
+ vcls, vattr = hop.inputargs(class_repr, Void)
+ cname = inputconst(Void, 'name')
return hop.genop('getfield', [vcls, cname],
- resulttype = lltype.Ptr(rstr.STR))
+ resulttype = Ptr(rstr.STR))
access_set, class_repr = self.get_access_set(attr)
- vcls, vattr = hop.inputargs(class_repr, lltype.Void)
+ vcls, vattr = hop.inputargs(class_repr, Void)
v_res = class_repr.getpbcfield(vcls, access_set, attr, hop.llops)
s_res = access_set.s_value
r_res = self.rtyper.getrepr(s_res)
@@ -683,7 +956,7 @@
if len(self.s_pbc.descriptions) == 1:
# instantiating a single class
- if self.lowleveltype is not lltype.Void:
+ if self.lowleveltype is not Void:
assert 0, "XXX None-or-1-class instantation not implemented"
assert isinstance(s_instance, annmodel.SomeInstance)
classdef = s_instance.classdef
@@ -740,10 +1013,10 @@
classdef = desc.getclassdef(None)
assert hasattr(classdef, 'my_instantiate_graph')
graphs.append(classdef.my_instantiate_graph)
- c_graphs = hop.inputconst(lltype.Void, graphs)
+ c_graphs = hop.inputconst(Void, graphs)
#
# "my_instantiate = typeptr.instantiate"
- c_name = hop.inputconst(lltype.Void, 'instantiate')
+ c_name = hop.inputconst(Void, 'instantiate')
v_instantiate = hop.genop('getfield', [vtypeptr, c_name],
resulttype=OBJECT_VTABLE.instantiate)
# "my_instantiate()"
@@ -774,7 +1047,7 @@
# turn a PBC of classes to a standard pointer-to-vtable class repr
if r_clspbc.lowleveltype == r_cls.lowleveltype:
return v
- if r_clspbc.lowleveltype is lltype.Void:
+ if r_clspbc.lowleveltype is Void:
return inputconst(r_cls, r_clspbc.s_pbc.const)
# convert from ptr-to-object-vtable to ptr-to-more-precise-vtable
return r_cls.fromclasstype(v, llops)
@@ -784,10 +1057,10 @@
# this check makes sense because both source and dest repr are ClassesPBCRepr
if r_clspbc1.lowleveltype == r_clspbc2.lowleveltype:
return v
- if r_clspbc1.lowleveltype is lltype.Void:
+ if r_clspbc1.lowleveltype is Void:
return inputconst(r_clspbc2, r_clspbc1.s_pbc.const)
- if r_clspbc2.lowleveltype is lltype.Void:
- return inputconst(lltype.Void, r_clspbc2.s_pbc.const)
+ if r_clspbc2.lowleveltype is Void:
+ return inputconst(Void, r_clspbc2.s_pbc.const)
return NotImplemented
def adjust_shape(hop2, s_shape):
@@ -864,8 +1137,6 @@
return self.redispatch_call(hop, call_args=True)
def redispatch_call(self, hop, call_args):
- from rpython.rtyper.lltypesystem.rpbc import (
- FunctionsPBCRepr, SmallFunctionSetPBCRepr)
r_class = self.r_im_self.rclass
mangled_name, r_func = r_class.clsfields[self.methodname]
assert isinstance(r_func, (FunctionsPBCRepr,
@@ -890,28 +1161,3 @@
# now hop2 looks like simple_call(function, self, args...)
return hop2.dispatch()
-
-# ____________________________________________________________
-
-def samesig(funcs):
- import inspect
- argspec = inspect.getargspec(funcs[0])
- for func in funcs:
- if inspect.getargspec(func) != argspec:
- return False
- return True
-
-# ____________________________________________________________
-
-def commonbase(classdefs):
- result = classdefs[0]
- for cdef in classdefs[1:]:
- result = result.commonbase(cdef)
- if result is None:
- raise TyperError("no common base class in %r" % (classdefs,))
- return result
-
-def allattributenames(classdef):
- for cdef1 in classdef.getmro():
- for attrname in cdef1.attrs:
- yield cdef1, attrname
More information about the pypy-commit
mailing list