~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/rpython/lltypesystem/rtagged.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from pypy.objspace.flow.model import Constant
 
2
from pypy.rpython.rclass import getclassrepr, getinstancerepr, get_type_repr
 
3
from pypy.rpython.lltypesystem import lltype
 
4
from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE
 
5
from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute
 
6
from pypy.rpython.lltypesystem.rclass import ll_issubclass_const
 
7
from pypy.rpython.rmodel import TyperError, inputconst
 
8
 
 
9
 
 
10
class TaggedInstanceRepr(InstanceRepr):
 
11
 
 
12
    def __init__(self, rtyper, classdef, unboxedclassdef):
 
13
        InstanceRepr.__init__(self, rtyper, classdef)
 
14
        self.unboxedclassdef = unboxedclassdef
 
15
        self.is_parent = unboxedclassdef is not classdef
 
16
 
 
17
    def _setup_repr(self):
 
18
        InstanceRepr._setup_repr(self)
 
19
        flds = self.allinstancefields.keys()
 
20
        flds.remove('__class__')
 
21
        if self.is_parent:
 
22
            if flds:
 
23
                raise TyperError("%r is a base class of an UnboxedValue,"
 
24
                                 "so it cannot have fields: %r" % (
 
25
                    self.classdef, flds))
 
26
        else:
 
27
            if len(flds) != 1:
 
28
                raise TyperError("%r must have exactly one field: %r" % (
 
29
                    self.classdef, flds))
 
30
            self.specialfieldname = flds[0]
 
31
 
 
32
    def new_instance(self, llops, classcallhop=None):
 
33
        if self.is_parent:
 
34
            raise TyperError("don't instantiate %r, it is a parent of an "
 
35
                             "UnboxedValue class" % (self.classdef,))
 
36
        if classcallhop is None:
 
37
            raise TyperError("must instantiate %r by calling the class" % (
 
38
                self.classdef,))
 
39
        hop = classcallhop
 
40
        if not (hop.spaceop.opname == 'simple_call' and hop.nb_args == 2):
 
41
            raise TyperError("must instantiate %r with a simple class call" % (
 
42
                self.classdef,))
 
43
        v_value = hop.inputarg(lltype.Signed, arg=1)
 
44
        c_one = hop.inputconst(lltype.Signed, 1)
 
45
        hop.exception_is_here()
 
46
        v2 = hop.genop('int_lshift_ovf', [v_value, c_one],
 
47
                       resulttype = lltype.Signed)
 
48
        v2p1 = hop.genop('int_add', [v2, c_one],
 
49
                         resulttype = lltype.Signed)
 
50
        v_instance =  hop.genop('cast_int_to_ptr', [v2p1],
 
51
                                resulttype = self.lowleveltype)
 
52
        return v_instance, False   # don't call __init__
 
53
 
 
54
    def convert_const_exact(self, value):
 
55
        self.setup()
 
56
        number = value.getvalue()
 
57
        return ll_int_to_unboxed(self.lowleveltype, number)
 
58
 
 
59
    def getvalue_from_unboxed(self, llops, vinst):
 
60
        assert not self.is_parent
 
61
        v2 = llops.genop('cast_ptr_to_int', [vinst],  resulttype=lltype.Signed)
 
62
        c_one = inputconst(lltype.Signed, 1)
 
63
        return llops.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed)
 
64
 
 
65
    def gettype_from_unboxed(self, llops, vinst):
 
66
        unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef)
 
67
        cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable())
 
68
        if self.is_parent:
 
69
            # If the lltype of vinst shows that it cannot be a tagged value,
 
70
            # we can directly read the typeptr.  Otherwise, call a helper that
 
71
            # checks if the tag bit is set in the pointer.
 
72
            unboxedinstance_repr = getinstancerepr(self.rtyper,
 
73
                                                   self.unboxedclassdef)
 
74
            try:
 
75
                lltype.castable(unboxedinstance_repr.lowleveltype,
 
76
                                vinst.concretetype)
 
77
            except lltype.InvalidCast:
 
78
                can_be_tagged = False
 
79
            else:
 
80
                can_be_tagged = True
 
81
            vinst = llops.genop('cast_pointer', [vinst],
 
82
                                resulttype=self.common_repr())
 
83
            if can_be_tagged:
 
84
                return llops.gendirectcall(ll_unboxed_getclass, vinst,
 
85
                                           cunboxedcls)
 
86
            else:
 
87
                ctypeptr = inputconst(lltype.Void, 'typeptr')
 
88
                return llops.genop('getfield', [vinst, ctypeptr],
 
89
                                   resulttype = CLASSTYPE)
 
90
        else:
 
91
            return cunboxedcls
 
92
 
 
93
    def getfield(self, vinst, attr, llops, force_cast=False, flags={}):
 
94
        if not self.is_parent and attr == self.specialfieldname:
 
95
            return self.getvalue_from_unboxed(llops, vinst)
 
96
        elif attr == '__class__':
 
97
            return self.gettype_from_unboxed(llops, vinst)
 
98
        else:
 
99
            raise MissingRTypeAttribute(attr)
 
100
 
 
101
    def rtype_type(self, hop):
 
102
        [vinst] = hop.inputargs(self)
 
103
        return self.gettype_from_unboxed(hop.llops, vinst)
 
104
 
 
105
    def rtype_setattr(self, hop):
 
106
        # only for UnboxedValue.__init__(), which is not actually called
 
107
        hop.genop('UnboxedValue_setattr', [])
 
108
 
 
109
    def ll_str(self, i):
 
110
        if lltype.cast_ptr_to_int(i) & 1:
 
111
            from pypy.rpython.lltypesystem import rstr
 
112
            from pypy.rpython.rint import signed_repr
 
113
            llstr1 = signed_repr.ll_str(ll_unboxed_to_int(i))
 
114
            return rstr.ll_strconcat(rstr.unboxed_instance_str_prefix,
 
115
                      rstr.ll_strconcat(llstr1,
 
116
                                        rstr.unboxed_instance_str_suffix))
 
117
        else:
 
118
            return InstanceRepr.ll_str(self, i)
 
119
 
 
120
    def rtype_isinstance(self, hop):
 
121
        if not hop.args_s[1].is_constant():
 
122
            raise TyperError("isinstance() too complicated")
 
123
        [classdesc] = hop.args_s[1].descriptions
 
124
        classdef = classdesc.getuniqueclassdef()
 
125
 
 
126
        class_repr = get_type_repr(self.rtyper)
 
127
        instance_repr = self.common_repr()
 
128
        v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
 
129
        cls = v_cls.value
 
130
        answer = self.unboxedclassdef.issubclass(classdef)
 
131
        c_answer_if_unboxed = hop.inputconst(lltype.Bool, answer)
 
132
        minid = hop.inputconst(lltype.Signed, cls.subclassrange_min)
 
133
        maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max)
 
134
        return hop.gendirectcall(ll_unboxed_isinstance_const, v_obj,
 
135
                                 minid, maxid, c_answer_if_unboxed)
 
136
 
 
137
 
 
138
def ll_int_to_unboxed(PTRTYPE, value):
 
139
    return lltype.cast_int_to_ptr(PTRTYPE, value*2+1)
 
140
 
 
141
def ll_unboxed_to_int(p):
 
142
    return lltype.cast_ptr_to_int(p) >> 1
 
143
 
 
144
def ll_unboxed_getclass(instance, class_if_unboxed):
 
145
    if lltype.cast_ptr_to_int(instance) & 1:
 
146
        return class_if_unboxed
 
147
    else:
 
148
        return instance.typeptr
 
149
 
 
150
def ll_unboxed_isinstance_const(obj, minid, maxid, answer_if_unboxed):
 
151
    if not obj:
 
152
        return False
 
153
    if lltype.cast_ptr_to_int(obj) & 1:
 
154
        return answer_if_unboxed
 
155
    else:
 
156
        return ll_issubclass_const(obj.typeptr, minid, maxid)