def specialize_call(self, hop): from rpython.rtyper.lltypesystem import lltype from rpython.rtyper import rclass classrepr = rclass.get_type_repr(hop.rtyper) v_inst = hop.inputarg(hop.args_r[0], arg=0) v_cls = hop.inputarg(classrepr, arg=1) hop.exception_is_here() return hop.gendirectcall(ll_record_exact_class, v_inst, v_cls)
def rtype_issubtype(self, hop): class_repr = get_type_repr(self.rtyper) v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr) if isinstance(v_cls2, Constant): cls2 = v_cls2.value minid = hop.inputconst(Signed, cls2.subclassrange_min) maxid = hop.inputconst(Signed, cls2.subclassrange_max) return hop.gendirectcall(ll_issubclass_const, v_cls1, minid, maxid) else: v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr) return hop.gendirectcall(ll_issubclass, v_cls1, v_cls2)
def specialize_call(self, hop): from rpython.rtyper.lltypesystem import lltype from rpython.rtyper import rclass classrepr = rclass.get_type_repr(hop.rtyper) hop.exception_cannot_occur() v_inst = hop.inputarg(hop.args_r[0], arg=0) v_cls = hop.inputarg(classrepr, arg=1) return hop.genop('jit_record_known_class', [v_inst, v_cls], resulttype=lltype.Void)
def rtype_instantiate(hop): hop.exception_cannot_occur() s_class = hop.args_s[0] assert isinstance(s_class, annmodel.SomePBC) if len(s_class.descriptions) != 1: # instantiate() on a variable class vtypeptr, = hop.inputargs(rclass.get_type_repr(hop.rtyper)) r_class = hop.args_r[0] return r_class._instantiate_runtime_class(hop, vtypeptr, hop.r_result.lowleveltype) classdef = s_class.any_description().getuniqueclassdef() return rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops)
def rtype_isinstance(self, hop): if not hop.args_s[1].is_constant(): raise TyperError("isinstance() too complicated") [classdesc] = hop.args_s[1].descriptions classdef = classdesc.getuniqueclassdef() class_repr = get_type_repr(self.rtyper) instance_repr = self.common_repr() v_obj, v_cls = hop.inputargs(instance_repr, class_repr) cls = v_cls.value answer = self.unboxedclassdef.issubclass(classdef) c_answer_if_unboxed = hop.inputconst(lltype.Bool, answer) minid = hop.inputconst(lltype.Signed, cls.subclassrange_min) maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max) return hop.gendirectcall(ll_unboxed_isinstance_const, v_obj, minid, maxid, c_answer_if_unboxed)
def rtype_isinstance(self, hop): class_repr = get_type_repr(hop.rtyper) instance_repr = self.common_repr() v_obj, v_cls = hop.inputargs(instance_repr, class_repr) if isinstance(v_cls, Constant): cls = v_cls.value # XXX re-implement the following optimization #if cls.subclassrange_max == cls.subclassrange_min: # # a class with no subclass # return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls) #else: minid = hop.inputconst(Signed, cls.subclassrange_min) maxid = hop.inputconst(Signed, cls.subclassrange_max) return hop.gendirectcall(ll_isinstance_const, v_obj, minid, maxid) else: return hop.gendirectcall(ll_isinstance, v_obj, v_cls)
def rtype_instantiate(hop, i_nonmovable=None): hop.exception_cannot_occur() s_class = hop.args_s[0] assert isinstance(s_class, annmodel.SomePBC) v_nonmovable, = parse_kwds(hop, (i_nonmovable, None)) nonmovable = (i_nonmovable is not None and v_nonmovable.value) if len(s_class.descriptions) != 1: # instantiate() on a variable class if nonmovable: raise TyperError("instantiate(x, nonmovable=True) cannot be used " "if x is not a constant class") vtypeptr, = hop.inputargs(rclass.get_type_repr(hop.rtyper)) r_class = hop.args_r[0] return r_class._instantiate_runtime_class(hop, vtypeptr, hop.r_result.lowleveltype) classdef = s_class.any_description().getuniqueclassdef() return rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops, nonmovable=nonmovable)
def _convert_link(self, block, link): if link.exitcase is not None and link.exitcase != 'default': if isinstance(block.exitswitch, Variable): r_case = self.bindingrepr(block.exitswitch) else: assert block.exitswitch == c_last_exception r_case = rclass.get_type_repr(self) link.llexitcase = r_case.convert_const(link.exitcase) else: link.llexitcase = None a = link.last_exception if isinstance(a, Variable): a.concretetype = self.exceptiondata.lltype_of_exception_type elif isinstance(a, Constant): link.last_exception = inputconst( self.exceptiondata.r_exception_type, a.value) a = link.last_exc_value if isinstance(a, Variable): a.concretetype = self.exceptiondata.lltype_of_exception_value elif isinstance(a, Constant): link.last_exc_value = inputconst( self.exceptiondata.r_exception_value, a.value)
def _convert_link(self, block, link): if link.exitcase is not None and link.exitcase != 'default': if isinstance(block.exitswitch, Variable): r_case = self.bindingrepr(block.exitswitch) else: assert block.canraise r_case = rclass.get_type_repr(self) link.llexitcase = r_case.convert_const(link.exitcase) else: link.llexitcase = None a = link.last_exception if isinstance(a, Variable): a.concretetype = self.exceptiondata.lltype_of_exception_type elif isinstance(a, Constant): link.last_exception = inputconst( self.exceptiondata.r_exception_type, a.value) a = link.last_exc_value if isinstance(a, Variable): a.concretetype = self.exceptiondata.lltype_of_exception_value elif isinstance(a, Constant): link.last_exc_value = inputconst( self.exceptiondata.r_exception_value, a.value)
def _instantiate_runtime_class(self, hop, v_class, r_instance): classdef = hop.s_result.classdef resulttype = getinstancerepr(hop.rtyper, classdef).lowleveltype # convert v_class from META to ootype.Class if necessary: v_class = get_type_repr(hop.rtyper).fromclasstype(v_class, hop.llops) return hop.genop('runtimenew', [v_class], resulttype=resulttype)
def rtype_issubtype(self, hop): class_repr = get_type_repr(self.rtyper) vcls1, vcls2 = hop.inputargs(class_repr, class_repr) return hop.genop('subclassof', [vcls1, vcls2], resulttype=ootype.Bool)
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. AbstractInstanceRepr._setup_repr(self) self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes attrs = self.classdef.attrs.items() attrs.sort() myllfields = [] for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r myllfields.append((mangled_name, r.lowleveltype)) # Sort the instance attributes by decreasing "likely size", # as reported by rffi.sizeof(), to minimize padding holes in C. # Fields of the same size are sorted by name (by attrs.sort() # above) just to minimize randomness. def keysize((_, T)): if T is lltype.Void: return None from rpython.rtyper.lltypesystem.rffi import sizeof try: return -sizeof(T) except StandardError: return None myllfields.sort(key=keysize) if llfields is None: llfields = myllfields else: llfields = llfields + myllfields self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) kwds = {} if self.gcflavor == 'gc': kwds['rtti'] = True for name, attrdef in attrs: if not attrdef.readonly and self.is_quasi_immutable(name): llfields.append(('mutate_' + name, OBJECTPTR)) object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields, **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. AbstractInstanceRepr._setup_repr(self) self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes attrs = self.classdef.attrs.items() attrs.sort() myllfields = [] for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r myllfields.append((mangled_name, r.lowleveltype)) # Sort the instance attributes by decreasing "likely size", # as reported by rffi.sizeof(), to minimize padding holes in C. # Fields of the same size are sorted by name (by attrs.sort() # above) just to minimize randomness. def keysize((_, T)): if T is lltype.Void: return None from rpython.rtyper.lltypesystem.rffi import sizeof try: return -sizeof(T) except StandardError: return None myllfields.sort(key = keysize) if llfields is None: llfields = myllfields else: llfields = llfields + myllfields self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) kwds = {} if self.gcflavor == 'gc': kwds['rtti'] = True for name, attrdef in attrs: if not attrdef.readonly and self.is_quasi_immutable(name): llfields.append(('mutate_' + name, OBJECTPTR)) object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields, **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields