def __init__(self, rtyper, classdef, gcflavor='ignored'): AbstractInstanceRepr.__init__(self, rtyper, classdef) self.baserepr = None if self.classdef is None: self.lowleveltype = OBJECT else: b = self.classdef.basedef if b is not None: self.baserepr = getinstancerepr(rtyper, b) b = self.baserepr.lowleveltype else: b = OBJECT if hasattr(classdef.classdesc.pyobj, '_rpython_hints'): hints = classdef.classdesc.pyobj._rpython_hints else: hints = {} hints = self._check_for_immutable_hints(hints) self.lowleveltype = ootype.Instance(classdef.name, b, {}, {}, _hints=hints) self.iprebuiltinstances = identity_dict() self.object_type = self.lowleveltype self.gcflavor = gcflavor
def gettype_from_unboxed(self, llops, vinst, can_be_none=False): unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) if self.is_parent: # If the lltype of vinst shows that it cannot be a tagged value, # we can directly read the typeptr. Otherwise, call a helper that # checks if the tag bit is set in the pointer. unboxedinstance_repr = getinstancerepr(self.rtyper, self.unboxedclassdef) try: lltype.castable(unboxedinstance_repr.lowleveltype, vinst.concretetype) except lltype.InvalidCast: can_be_tagged = False else: can_be_tagged = True vinst = llops.genop('cast_pointer', [vinst], resulttype=self.common_repr()) if can_be_tagged: if can_be_none: func = ll_unboxed_getclass_canbenone else: func = ll_unboxed_getclass return llops.gendirectcall(func, vinst, cunboxedcls) elif can_be_none: return llops.gendirectcall(ll_inst_type, vinst) else: ctypeptr = inputconst(lltype.Void, 'typeptr') return llops.genop('getfield', [vinst, ctypeptr], resulttype = CLASSTYPE) else: return cunboxedcls
def rtype_method_get(self, hop): r_object = getinstancerepr(self.rtyper, None) v_d, v_key = hop.inputargs(self, r_object) hop.exception_cannot_occur() v_result = hop.gendirectcall(ll_get, v_d, v_key) v_result = hop.genop("cast_pointer", [v_result], resulttype=hop.r_result.lowleveltype) return v_result
def setup_meta_instance(self, meta_instance, rsubcls): if self.classdef is None: rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) meta_instance.class_ = ootype.runtimeClass(rinstance.lowleveltype) else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls def assign(mangled_name, value): if isinstance(value, flowmodel.Constant) and isinstance( value.value, staticmethod): value = flowmodel.Constant(value.value.__get__( 42)) # staticmethod => bare function llvalue = r.convert_desc_or_const(value) setattr(meta_instance, mangled_name, llvalue) # extra PBC attributes for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): if rsubcls.classdef.classdesc not in access_set.descs: continue # only for the classes in the same pbc access set if r.lowleveltype is ootype.Void: continue attrvalue = rsubcls.classdef.classdesc.read_attribute( attr, None) if attrvalue is not None: assign(mangled_name, attrvalue) # then initialize the 'super' portion of the vtable self.rbase.setup_meta_instance(meta_instance, rsubcls)
def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) if self.gcflavor == 'gc': if (self.classdef is not None and self.classdef.classdesc.lookup('__del__') is not None): s_func = self.classdef.classdesc.s_read_attribute('__del__') source_desc = self.classdef.classdesc.lookup('__del__') source_classdef = source_desc.getclassdef(None) source_repr = getinstancerepr(self.rtyper, source_classdef) assert len(s_func.descriptions) == 1 funcdesc, = s_func.descriptions graph = funcdesc.getuniquegraph() self.check_graph_of_del_does_not_call_too_much(graph) FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void) destrptr = functionptr(FUNCTYPE, graph.name, graph=graph, _callable=graph.func) else: destrptr = None OBJECT = OBJECT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT, destrptr) vtable = self.rclass.getvtable() self.rtyper.set_type_for_typeptr(vtable, self.lowleveltype.TO)
def __init__(self, rtyper, s_pbc): self.rtyper = rtyper self.s_pbc = s_pbc mdescs = list(s_pbc.descriptions) methodname = mdescs[0].name classdef = mdescs[0].selfclassdef flags = mdescs[0].flags for mdesc in mdescs[1:]: if mdesc.name != methodname: raise TyperError("cannot find a unique name under which the " "methods can be found: %r" % ( mdescs,)) if mdesc.flags != flags: raise TyperError("inconsistent 'flags': %r versus %r" % ( mdesc.flags, flags)) classdef = classdef.commonbase(mdesc.selfclassdef) if classdef is None: raise TyperError("mixing methods coming from instances of " "classes with no common base: %r" % (mdescs,)) self.methodname = methodname self.classdef = classdef.get_owner(methodname) # the low-level representation is just the bound 'self' argument. self.s_im_self = annmodel.SomeInstance(self.classdef, flags=flags) self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef) self.lowleveltype = self.r_im_self.lowleveltype
def externalvsinternal(rtyper, item_repr): # -> external_item_repr, (internal_)item_repr from rpython.rtyper import rclass if (isinstance(item_repr, rclass.InstanceRepr) and getattr(item_repr, 'gcflavor', 'gc') == 'gc'): return item_repr, rclass.getinstancerepr(rtyper, None) else: return item_repr, item_repr
def setup_meta_instance(self, meta_instance, rsubcls): if self.classdef is None: rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) meta_instance.class_ = ootype.runtimeClass(rinstance.lowleveltype) else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls def assign(mangled_name, value): if isinstance(value, flowmodel.Constant) and isinstance(value.value, staticmethod): value = flowmodel.Constant(value.value.__get__(42)) # staticmethod => bare function llvalue = r.convert_desc_or_const(value) setattr(meta_instance, mangled_name, llvalue) # extra PBC attributes for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): if rsubcls.classdef.classdesc not in access_set.descs: continue # only for the classes in the same pbc access set if r.lowleveltype is ootype.Void: continue attrvalue = rsubcls.classdef.classdesc.read_attribute(attr, None) if attrvalue is not None: assign(mangled_name, attrvalue) # then initialize the 'super' portion of the vtable self.rbase.setup_meta_instance(meta_instance, rsubcls)
def __init__(self, rtyper, s_pbc): self.rtyper = rtyper self.s_pbc = s_pbc mdescs = list(s_pbc.descriptions) methodname = mdescs[0].name classdef = mdescs[0].selfclassdef flags = mdescs[0].flags for mdesc in mdescs[1:]: if mdesc.name != methodname: raise TyperError("cannot find a unique name under which the " "methods can be found: %r" % (mdescs, )) if mdesc.flags != flags: raise TyperError("inconsistent 'flags': %r versus %r" % (mdesc.flags, flags)) classdef = classdef.commonbase(mdesc.selfclassdef) if classdef is None: raise TyperError("mixing methods coming from instances of " "classes with no common base: %r" % (mdescs, )) self.methodname = methodname self.classdef = classdef.get_owner(methodname) # the low-level representation is just the bound 'self' argument. self.s_im_self = annmodel.SomeInstance(self.classdef, flags=flags) self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef) self.lowleveltype = self.r_im_self.lowleveltype
def convert_const(self, weakdict): if weakdict is None: return lltype.nullptr(self.WEAKDICT) if not isinstance(weakdict, RWeakValueDictionary): raise TyperError("expected an RWeakValueDictionary: %r" % (weakdict, )) try: key = Constant(weakdict) return self.dict_cache[key] except KeyError: self.setup() l_dict = self.ll_new_weakdict() self.dict_cache[key] = l_dict bk = self.rtyper.annotator.bookkeeper classdef = bk.getuniqueclassdef(weakdict._valueclass) r_value = getinstancerepr(self.rtyper, classdef) any_value = False for dictkey, dictvalue in weakdict._dict.items(): llkey = self.r_key.convert_const(dictkey) llvalue = r_value.convert_const(dictvalue) if llvalue: llvalue = lltype.cast_pointer(rclass.OBJECTPTR, llvalue) self.ll_set_nonnull(l_dict, llkey, llvalue) any_value = True if any_value: l_dict.resize_counter = -1 return l_dict
def gettype_from_unboxed(self, llops, vinst, can_be_none=False): unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) if self.is_parent: # If the lltype of vinst shows that it cannot be a tagged value, # we can directly read the typeptr. Otherwise, call a helper that # checks if the tag bit is set in the pointer. unboxedinstance_repr = getinstancerepr(self.rtyper, self.unboxedclassdef) try: lltype.castable(unboxedinstance_repr.lowleveltype, vinst.concretetype) except lltype.InvalidCast: can_be_tagged = False else: can_be_tagged = True vinst = llops.genop('cast_pointer', [vinst], resulttype=self.common_repr()) if can_be_tagged: if can_be_none: func = ll_unboxed_getclass_canbenone else: func = ll_unboxed_getclass return llops.gendirectcall(func, vinst, cunboxedcls) elif can_be_none: return llops.gendirectcall(ll_inst_type, vinst) else: ctypeptr = inputconst(lltype.Void, 'typeptr') return llops.genop('getfield', [vinst, ctypeptr], resulttype=CLASSTYPE) else: return cunboxedcls
def rtype_method_set(self, hop): r_object = getinstancerepr(self.rtyper, None) v_d, v_key, v_value = hop.inputargs(self, self.r_key, r_object) hop.exception_cannot_occur() if hop.args_s[2].is_constant() and hop.args_s[2].const is None: hop.gendirectcall(self.ll_set_null, v_d, v_key) else: hop.gendirectcall(self.ll_set, v_d, v_key, v_value)
def getruntime(self, expected_type): if expected_type == ootype.Class: rinstance = getinstancerepr(self.rtyper, self.classdef) return ootype.runtimeClass(rinstance.lowleveltype) else: assert ootype.isSubclass(expected_type, META) meta = self.get_meta_instance(cast_to_root_meta=False) return ootype.ooupcast(expected_type, meta)
def redispatch_call(self, hop, call_args): s_instance = hop.s_result r_instance = hop.r_result if len(self.s_pbc.descriptions) == 1: # instantiating a single class 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 s_init = classdef.classdesc.s_read_attribute('__init__') v_init = Constant("init-func-dummy") # this value not really used if (isinstance(s_init, annmodel.SomeImpossibleValue) and classdef.classdesc.is_exception_class() and classdef.has_no_attrs()): # special case for instanciating simple built-in # exceptions: always return the same prebuilt instance, # and ignore any arguments passed to the constructor. r_instance = rclass.getinstancerepr(hop.rtyper, classdef) example = r_instance.get_reusable_prebuilt_instance() hop.exception_cannot_occur() return hop.inputconst(r_instance.lowleveltype, example) v_instance = rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops, hop) if isinstance(v_instance, tuple): v_instance, must_call_init = v_instance if not must_call_init: return v_instance else: # instantiating a class from multiple possible classes vtypeptr = hop.inputarg(self, arg=0) try: access_set, r_class = self.get_access_set('__init__') except rclass.MissingRTypeAttribute: s_init = annmodel.s_ImpossibleValue else: s_init = access_set.s_value v_init = r_class.getpbcfield(vtypeptr, access_set, '__init__', hop.llops) v_instance = self._instantiate_runtime_class( hop, vtypeptr, r_instance) if isinstance(s_init, annmodel.SomeImpossibleValue): assert hop.nb_args == 1, ("arguments passed to __init__, " "but no __init__!") hop.exception_cannot_occur() else: hop2 = self.replace_class_with_inst_arg(hop, v_instance, s_instance, call_args) hop2.v_s_insertfirstarg(v_init, s_init) # add 'initfunc' hop2.s_result = annmodel.s_None hop2.r_result = self.rtyper.getrepr(hop2.s_result) # now hop2 looks like simple_call(initfunc, instance, args...) hop2.dispatch() return v_instance
def setup_vtable(self, vtable, rsubcls): """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: vtable.hash = hash(rsubcls) # initialize the 'subclassrange_*' and 'name' fields if rsubcls.classdef is not None: #vtable.parenttypeptr = rsubcls.rbase.getvtable() vtable.subclassrange_min = rsubcls.classdef.minid vtable.subclassrange_max = rsubcls.classdef.maxid else: #for the root class vtable.subclassrange_min = 0 vtable.subclassrange_max = sys.maxint rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) rinstance.setup() if rinstance.gcflavor == 'gc': vtable.rtti = getRuntimeTypeInfo(rinstance.object_type) if rsubcls.classdef is None: name = 'object' else: name = rsubcls.classdef.shortname vtable.name = alloc_array_name(name) if hasattr(rsubcls.classdef, 'my_instantiate_graph'): graph = rsubcls.classdef.my_instantiate_graph vtable.instantiate = self.rtyper.getcallable(graph) #else: the classdef was created recently, so no instantiate() # could reach it else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls def assign(mangled_name, value): if isinstance(value, Constant) and isinstance(value.value, staticmethod): value = Constant(value.value.__get__(42)) # staticmethod => bare function llvalue = r.convert_desc_or_const(value) setattr(vtable, mangled_name, llvalue) mro = list(rsubcls.classdef.getmro()) for fldname in self.clsfields: mangled_name, r = self.clsfields[fldname] if r.lowleveltype is Void: continue value = rsubcls.classdef.classdesc.read_attribute(fldname, None) if value is not None: assign(mangled_name, value) # extra PBC attributes for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): if rsubcls.classdef.classdesc not in access_set.descs: continue # only for the classes in the same pbc access set if r.lowleveltype is Void: continue attrvalue = rsubcls.classdef.classdesc.read_attribute(attr, None) if attrvalue is not None: assign(mangled_name, attrvalue) # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls)
def redispatch_call(self, hop, call_args): s_instance = hop.s_result r_instance = hop.r_result if len(self.s_pbc.descriptions) == 1: # instantiating a single class 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 s_init = classdef.classdesc.s_read_attribute('__init__') v_init = Constant("init-func-dummy") # this value not really used if (isinstance(s_init, annmodel.SomeImpossibleValue) and classdef.classdesc.is_exception_class() and classdef.has_no_attrs()): # special case for instanciating simple built-in # exceptions: always return the same prebuilt instance, # and ignore any arguments passed to the contructor. r_instance = rclass.getinstancerepr(hop.rtyper, classdef) example = r_instance.get_reusable_prebuilt_instance() hop.exception_cannot_occur() return hop.inputconst(r_instance.lowleveltype, example) v_instance = rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops, hop) if isinstance(v_instance, tuple): v_instance, must_call_init = v_instance if not must_call_init: return v_instance else: # instantiating a class from multiple possible classes vtypeptr = hop.inputarg(self, arg=0) try: access_set, r_class = self.get_access_set('__init__') except rclass.MissingRTypeAttribute: s_init = annmodel.s_ImpossibleValue else: s_init = access_set.s_value v_init = r_class.getpbcfield(vtypeptr, access_set, '__init__', hop.llops) v_instance = self._instantiate_runtime_class(hop, vtypeptr, r_instance) if isinstance(s_init, annmodel.SomeImpossibleValue): assert hop.nb_args == 1, ("arguments passed to __init__, " "but no __init__!") hop.exception_cannot_occur() else: hop2 = self.replace_class_with_inst_arg( hop, v_instance, s_instance, call_args) hop2.v_s_insertfirstarg(v_init, s_init) # add 'initfunc' hop2.s_result = annmodel.s_None hop2.r_result = self.rtyper.getrepr(hop2.s_result) # now hop2 looks like simple_call(initfunc, instance, args...) hop2.dispatch() return v_instance
def __init__(self, rtyper): # (NB. rclass identifies 'Exception' and 'object') r_type = rtyper.rootclass_repr r_instance = getinstancerepr(rtyper, None) r_type.setup() r_instance.setup() self.r_exception_type = r_type self.r_exception_value = r_instance self.lltype_of_exception_type = r_type.lowleveltype self.lltype_of_exception_value = r_instance.lowleveltype self.rtyper = rtyper
def __init__(self, rtyper): self.make_standard_exceptions(rtyper) # (NB. rclass identifies 'Exception' and 'object') r_type = rclass.getclassrepr(rtyper, None) r_instance = rclass.getinstancerepr(rtyper, None) r_type.setup() r_instance.setup() self.r_exception_type = r_type self.r_exception_value = r_instance self.lltype_of_exception_type = r_type.lowleveltype self.lltype_of_exception_value = r_instance.lowleveltype self.rtyper = rtyper
def convert_const(self, weakdict): if not isinstance(weakdict, RWeakValueDictionary): raise TyperError("expected an RWeakValueDictionary: %r" % ( weakdict,)) try: key = Constant(weakdict) return self.dict_cache[key] except KeyError: self.setup() l_dict = self.ll_new_weakdict() self.dict_cache[key] = l_dict bk = self.rtyper.annotator.bookkeeper classdef = bk.getuniqueclassdef(weakdict._valueclass) r_value = getinstancerepr(self.rtyper, classdef) for dictkey, dictvalue in weakdict._dict.items(): llkey = self.r_key.convert_const(dictkey) llvalue = r_value.convert_const(dictvalue) if llvalue: llvalue = lltype.cast_pointer(rclass.OBJECTPTR, llvalue) self.ll_set_nonnull(l_dict, llkey, llvalue) return l_dict
def __init__(self, rtyper, classdef, gcflavor='ignored'): AbstractInstanceRepr.__init__(self, rtyper, classdef) self.baserepr = None if self.classdef is None: self.lowleveltype = OBJECT else: b = self.classdef.basedef if b is not None: self.baserepr = getinstancerepr(rtyper, b) b = self.baserepr.lowleveltype else: b = OBJECT if hasattr(classdef.classdesc.pyobj, '_rpython_hints'): hints = classdef.classdesc.pyobj._rpython_hints else: hints = {} hints = self._check_for_immutable_hints(hints) self.lowleveltype = ootype.Instance(classdef.name, b, {}, {}, _hints = hints) self.iprebuiltinstances = identity_dict() self.object_type = self.lowleveltype self.gcflavor = gcflavor
def run_guards_translated(gcremovetypeptr): class A(object): pass class B(A): pass class C(B): pass def main(argv): A(); B().foo = len(argv); C() return 0 t = TranslationContext() t.config.translation.gc = "minimark" t.config.translation.gcremovetypeptr = gcremovetypeptr ann = t.buildannotator() ann.build_types(main, [s_list_of_strings], main_entry_point=True) rtyper = t.buildrtyper() rtyper.specialize() classdef = ann.bookkeeper.getuniqueclassdef(B) rclass = getclassrepr(rtyper, classdef) rinstance = getinstancerepr(rtyper, classdef) LLB = rinstance.lowleveltype.TO ptr_vtable_B = rclass.getvtable() adr_vtable_B = llmemory.cast_ptr_to_adr(ptr_vtable_B) vtable_B = llmemory.cast_adr_to_int(adr_vtable_B, mode="symbolic") CPU = getcpuclass() cpu = CPU(rtyper, NoStats(), translate_support_code=True, gcdescr=get_description(t.config)) execute_token = cpu.make_execute_token(llmemory.GCREF) finaldescr = BasicFinalDescr() faildescr = BasicFailDescr() descr_B = cpu.sizeof(LLB, ptr_vtable_B) typeid_B = descr_B.get_type_id() fielddescr_B = cpu.fielddescrof(LLB, 'inst_foo') LLD = lltype.GcStruct('D', ('dd', lltype.Signed)) descr_D = cpu.sizeof(LLD) fielddescr_D = cpu.fielddescrof(LLD, 'dd') ARRAY = lltype.GcArray(lltype.Signed) arraydescr = cpu.arraydescrof(ARRAY) loop1 = parse(""" [p0] guard_class(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B}) loop2 = parse(""" [p0] guard_gc_type(p0, ConstInt(typeid_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr, 'typeid_B': typeid_B}) loop3 = parse(""" [p0] guard_is_object(p0, descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr}) loop4 = parse(""" [p0] guard_subclass(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B}) def g(): cpu.setup_once() token1 = JitCellToken() token2 = JitCellToken() token3 = JitCellToken() token4 = JitCellToken() cpu.compile_loop(loop1.inputargs, loop1.operations, token1) cpu.compile_loop(loop2.inputargs, loop2.operations, token2) cpu.compile_loop(loop3.inputargs, loop3.operations, token3) cpu.compile_loop(loop4.inputargs, loop4.operations, token4) for token, p0 in [ (token1, rffi.cast(llmemory.GCREF, A())), (token1, rffi.cast(llmemory.GCREF, B())), (token1, rffi.cast(llmemory.GCREF, C())), (token2, rffi.cast(llmemory.GCREF, A())), (token2, rffi.cast(llmemory.GCREF, B())), (token2, rffi.cast(llmemory.GCREF, C())), (token2, rffi.cast(llmemory.GCREF, [42, 43])), (token3, rffi.cast(llmemory.GCREF, A())), (token3, rffi.cast(llmemory.GCREF, B())), (token3, rffi.cast(llmemory.GCREF, [44, 45])), (token4, rffi.cast(llmemory.GCREF, A())), (token4, rffi.cast(llmemory.GCREF, B())), (token4, rffi.cast(llmemory.GCREF, C())), ]: frame = execute_token(token, p0) descr = cpu.get_latest_descr(frame) if descr is finaldescr: print 'match' elif descr is faildescr: print 'fail' else: print '???' # if token is token2: # guard_gc_type print int(cpu.get_actual_typeid(p0) == typeid_B) if token is token3: # guard_is_object print int(cpu.check_is_object(p0)) for p0 in [lltype.nullptr(llmemory.GCREF.TO), rffi.cast(llmemory.GCREF, A()), rffi.cast(llmemory.GCREF, B()), rffi.cast(llmemory.GCREF, C()), rffi.cast(llmemory.GCREF, lltype.malloc(LLD)), rffi.cast(llmemory.GCREF, lltype.malloc(ARRAY, 5)), rffi.cast(llmemory.GCREF, "foobar"), rffi.cast(llmemory.GCREF, u"foobaz")]: results = ['B', 'D', 'A', 'S', 'U'] try: cpu.protect_speculative_field(p0, fielddescr_B) except SpeculativeError: results[0] = '-' try: cpu.protect_speculative_field(p0, fielddescr_D) except SpeculativeError: results[1] = '-' try: cpu.protect_speculative_array(p0, arraydescr) except SpeculativeError: results[2] = '-' try: cpu.protect_speculative_string(p0) except SpeculativeError: results[3] = '-' try: cpu.protect_speculative_unicode(p0) except SpeculativeError: results[4] = '-' print ''.join(results) call_initial_function(t, g) cbuilder = genc.CStandaloneBuilder(t, main, t.config) cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) cbuilder.compile() data = cbuilder.cmdexec('') assert data == ('fail\n' 'match\n' 'fail\n' 'fail\n' '0\n' 'match\n' '1\n' 'fail\n' '0\n' 'fail\n' '0\n' 'match\n' '1\n' 'match\n' '1\n' 'fail\n' '0\n' 'fail\n' 'match\n' 'match\n' '-----\n' # null '-----\n' # instance of A 'B----\n' # instance of B 'B----\n' # instance of C '-D---\n' '--A--\n' '---S-\n' '----U\n' )
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 _setup_repr(self, llfields=None, hints=None): if hints: self.lowleveltype._hints.update(hints) if self.classdef is None: self.fields = {} self.allfields = {} self.allmethods = {} self.allclassattributes = {} self.classattributes = {} return if self.baserepr is not None: allfields = self.baserepr.allfields.copy() allmethods = self.baserepr.allmethods.copy() allclassattributes = self.baserepr.allclassattributes.copy() else: allfields = {} allmethods = {} allclassattributes = {} fields = {} nonmangledfields = [] fielddefaults = {} if llfields: fields.update(dict(llfields)) selfattrs = self.classdef.attrs for name, attrdef in selfattrs.iteritems(): mangled = mangle(name, self.rtyper.getconfig()) if not attrdef.readonly: repr = self.rtyper.getrepr(attrdef.s_value) allfields[mangled] = repr oot = repr.lowleveltype fields[mangled] = oot nonmangledfields.append(name) try: value = self.classdef.classdesc.read_attribute(name) fielddefaults[mangled] = repr.convert_desc_or_const(value) except AttributeError: pass else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): if len(s_value.descriptions) > 0 and s_value.getKind() == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError("method overrides class attribute") allmethods[mangled] = name, self.classdef.lookup_filter(s_value) continue # class attribute if mangled in allmethods: raise TyperError("class attribute overrides method") allclassattributes[mangled] = name, s_value special_methods = ["__init__", "__del__"] for meth_name in special_methods: if meth_name not in selfattrs and \ self.classdef.classdesc.find_source_for(meth_name) is not None: s_meth = self.classdef.classdesc.s_get_value(self.classdef, meth_name) if isinstance(s_meth, annmodel.SomePBC): mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception ootype.addFields(self.lowleveltype, fields) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() for name, attrdef in selfattrs.iteritems(): if not attrdef.readonly and self.is_quasi_immutable(name): name = mangle('mutable_' + name, self.rtyper.getconfig()) ootype.addFields(self.lowleveltype, {name: OBJECT}) classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) # if this class has a corresponding metaclass, attach # a getmeta() method to get the corresponding meta_instance if classrepr.lowleveltype != ootype.Class: oovalue = classrepr.get_meta_instance() self.attach_class_attr_accessor('getmeta', oovalue) for classdef in self.classdef.getmro(): for name, attrdef in classdef.attrs.iteritems(): if not attrdef.readonly: continue mangled = mangle(name, self.rtyper.getconfig()) if mangled in allclassattributes: selfdesc = self.classdef.classdesc if name not in selfattrs: # if the attr was already found in a parent class, # we register it again only if it is overridden. if selfdesc.find_source_for(name) is None: continue value = selfdesc.read_attribute(name) else: # otherwise, for new attrs, we look in all parent # classes to see if it's defined in a parent but only # actually first used in self.classdef. value = selfdesc.read_attribute(name, None) # a non-method class attribute if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value self.fields = nonmangledfields self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes self.classattributes = classattributes # the following is done after the rest of the initialization because # convert_const can require 'self' to be fully initialized. # step 2: provide default values for fields for mangled, impl in fielddefaults.items(): oot = fields[mangled] ootype.addFields(self.lowleveltype, {mangled: (oot, impl)}, with_default=True)
def run_guards_translated(gcremovetypeptr): class A(object): pass class B(A): pass class C(B): pass def main(argv): A() B().foo = len(argv) C() return 0 t = TranslationContext() t.config.translation.gc = "minimark" t.config.translation.gcremovetypeptr = gcremovetypeptr ann = t.buildannotator() ann.build_types(main, [s_list_of_strings], main_entry_point=True) rtyper = t.buildrtyper() rtyper.specialize() classdef = ann.bookkeeper.getuniqueclassdef(B) rclass = getclassrepr(rtyper, classdef) rinstance = getinstancerepr(rtyper, classdef) LLB = rinstance.lowleveltype.TO ptr_vtable_B = rclass.getvtable() adr_vtable_B = llmemory.cast_ptr_to_adr(ptr_vtable_B) vtable_B = llmemory.cast_adr_to_int(adr_vtable_B, mode="symbolic") CPU = getcpuclass() cpu = CPU(rtyper, NoStats(), translate_support_code=True, gcdescr=get_description(t.config)) execute_token = cpu.make_execute_token(llmemory.GCREF) finaldescr = BasicFinalDescr() faildescr = BasicFailDescr() descr_B = cpu.sizeof(LLB, ptr_vtable_B) typeid_B = descr_B.get_type_id() fielddescr_B = cpu.fielddescrof(LLB, 'inst_foo') LLD = lltype.GcStruct('D', ('dd', lltype.Signed)) descr_D = cpu.sizeof(LLD) fielddescr_D = cpu.fielddescrof(LLD, 'dd') ARRAY = lltype.GcArray(lltype.Signed) arraydescr = cpu.arraydescrof(ARRAY) loop1 = parse(""" [p0] guard_class(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={ 'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B }) loop1a = parse(""" [p0] guard_nonnull_class(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={ 'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B }) loop2 = parse(""" [p0] guard_gc_type(p0, ConstInt(typeid_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={ 'finaldescr': finaldescr, 'faildescr': faildescr, 'typeid_B': typeid_B }) loop3 = parse(""" [p0] guard_is_object(p0, descr=faildescr) [] finish(descr=finaldescr) """, namespace={ 'finaldescr': finaldescr, 'faildescr': faildescr }) loop4 = parse(""" [p0] guard_subclass(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={ 'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B }) def g(): cpu.setup_once() token1 = JitCellToken() token1a = JitCellToken() token2 = JitCellToken() token3 = JitCellToken() token4 = JitCellToken() cpu.compile_loop(loop1.inputargs, loop1.operations, token1) cpu.compile_loop(loop1a.inputargs, loop1a.operations, token1a) cpu.compile_loop(loop2.inputargs, loop2.operations, token2) cpu.compile_loop(loop3.inputargs, loop3.operations, token3) cpu.compile_loop(loop4.inputargs, loop4.operations, token4) for token, p0 in [ (token1, rffi.cast(llmemory.GCREF, A())), (token1, rffi.cast(llmemory.GCREF, B())), (token1, rffi.cast(llmemory.GCREF, C())), (token1a, rffi.cast(llmemory.GCREF, A())), (token1a, lltype.nullptr(llmemory.GCREF.TO)), (token1a, rffi.cast(llmemory.GCREF, B())), (token1a, rffi.cast(llmemory.GCREF, C())), (token2, rffi.cast(llmemory.GCREF, A())), (token2, rffi.cast(llmemory.GCREF, B())), (token2, rffi.cast(llmemory.GCREF, C())), (token2, rffi.cast(llmemory.GCREF, [42, 43])), (token3, rffi.cast(llmemory.GCREF, A())), (token3, rffi.cast(llmemory.GCREF, B())), (token3, rffi.cast(llmemory.GCREF, [44, 45])), (token4, rffi.cast(llmemory.GCREF, A())), (token4, rffi.cast(llmemory.GCREF, B())), (token4, rffi.cast(llmemory.GCREF, C())), ]: frame = execute_token(token, p0) descr = cpu.get_latest_descr(frame) if descr is finaldescr: print 'match' elif descr is faildescr: print 'fail' else: print '???' # if token is token2: # guard_gc_type print int(cpu.get_actual_typeid(p0) == typeid_B) if token is token3: # guard_is_object print int(cpu.check_is_object(p0)) for p0 in [ lltype.nullptr(llmemory.GCREF.TO), rffi.cast(llmemory.GCREF, A()), rffi.cast(llmemory.GCREF, B()), rffi.cast(llmemory.GCREF, C()), rffi.cast(llmemory.GCREF, lltype.malloc(LLD)), rffi.cast(llmemory.GCREF, lltype.malloc(ARRAY, 5)), rffi.cast(llmemory.GCREF, "foobar"), rffi.cast(llmemory.GCREF, u"foobaz") ]: results = ['B', 'D', 'A', 'S', 'U'] try: cpu.protect_speculative_field(p0, fielddescr_B) except SpeculativeError: results[0] = '-' try: cpu.protect_speculative_field(p0, fielddescr_D) except SpeculativeError: results[1] = '-' try: cpu.protect_speculative_array(p0, arraydescr) except SpeculativeError: results[2] = '-' try: cpu.protect_speculative_string(p0) except SpeculativeError: results[3] = '-' try: cpu.protect_speculative_unicode(p0) except SpeculativeError: results[4] = '-' print ''.join(results) call_initial_function(t, g) cbuilder = genc.CStandaloneBuilder(t, main, t.config) cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) cbuilder.compile() data = cbuilder.cmdexec('') assert data == ( 'fail\n' 'match\n' 'fail\n' 'fail\n' 'fail\n' 'match\n' 'fail\n' 'fail\n' '0\n' 'match\n' '1\n' 'fail\n' '0\n' 'fail\n' '0\n' 'match\n' '1\n' 'match\n' '1\n' 'fail\n' '0\n' 'fail\n' 'match\n' 'match\n' '-----\n' # null '-----\n' # instance of A 'B----\n' # instance of B 'B----\n' # instance of C '-D---\n' '--A--\n' '---S-\n' '----U\n')
def specialize_call(self, hop): r_generic_object = getinstancerepr(hop.rtyper, None) [v] = hop.inputargs(r_generic_object) # might generate a cast_pointer hop.exception_cannot_occur() return v
def get_standard_ll_exc_instance(self, rtyper, clsdef): r_inst = getinstancerepr(rtyper, clsdef) example = r_inst.get_reusable_prebuilt_instance() example = ll_cast_to_object(example) return example
def common_repr(self): # -> object or nongcobject reprs return getinstancerepr(self.rtyper, None, self.gcflavor)
def run_guards_translated(gcremovetypeptr): class A(object): pass class B(A): pass class C(B): pass def main(argv): A(); B(); C() return 0 t = TranslationContext() t.config.translation.gc = "minimark" t.config.translation.gcremovetypeptr = gcremovetypeptr ann = t.buildannotator() ann.build_types(main, [s_list_of_strings], main_entry_point=True) rtyper = t.buildrtyper() rtyper.specialize() classdef = ann.bookkeeper.getuniqueclassdef(B) rclass = getclassrepr(rtyper, classdef) rinstance = getinstancerepr(rtyper, classdef) LLB = rinstance.lowleveltype.TO vtable_B = rclass.getvtable() adr_vtable_B = llmemory.cast_ptr_to_adr(vtable_B) vtable_B = llmemory.cast_adr_to_int(adr_vtable_B, mode="symbolic") CPU = getcpuclass() cpu = CPU(rtyper, NoStats(), translate_support_code=True, gcdescr=get_description(t.config)) execute_token = cpu.make_execute_token(llmemory.GCREF) finaldescr = BasicFinalDescr() faildescr = BasicFailDescr() descr_B = cpu.sizeof(LLB, vtable_B) typeid_B = descr_B.get_type_id() loop1 = parse(""" [p0] guard_class(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B}) loop2 = parse(""" [p0] guard_gc_type(p0, ConstInt(typeid_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr, 'typeid_B': typeid_B}) loop3 = parse(""" [p0] guard_is_object(p0, descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr}) loop4 = parse(""" [p0] guard_subclass(p0, ConstInt(vtable_B), descr=faildescr) [] finish(descr=finaldescr) """, namespace={'finaldescr': finaldescr, 'faildescr': faildescr, 'vtable_B': vtable_B}) def g(): cpu.setup_once() token1 = JitCellToken() token2 = JitCellToken() token3 = JitCellToken() token4 = JitCellToken() cpu.compile_loop(loop1.inputargs, loop1.operations, token1) cpu.compile_loop(loop2.inputargs, loop2.operations, token2) cpu.compile_loop(loop3.inputargs, loop3.operations, token3) cpu.compile_loop(loop4.inputargs, loop4.operations, token4) for token, p0 in [ (token1, rffi.cast(llmemory.GCREF, A())), (token1, rffi.cast(llmemory.GCREF, B())), (token1, rffi.cast(llmemory.GCREF, C())), (token2, rffi.cast(llmemory.GCREF, A())), (token2, rffi.cast(llmemory.GCREF, B())), (token2, rffi.cast(llmemory.GCREF, C())), (token2, rffi.cast(llmemory.GCREF, [42, 43])), (token3, rffi.cast(llmemory.GCREF, A())), (token3, rffi.cast(llmemory.GCREF, B())), (token3, rffi.cast(llmemory.GCREF, [44, 45])), (token4, rffi.cast(llmemory.GCREF, A())), (token4, rffi.cast(llmemory.GCREF, B())), (token4, rffi.cast(llmemory.GCREF, C())), ]: frame = execute_token(token, p0) descr = cpu.get_latest_descr(frame) if descr is finaldescr: print 'match' elif descr is faildescr: print 'fail' else: print '???' # if token is token2: # guard_gc_type print int(cpu.get_actual_typeid(p0) == typeid_B) if token is token3: # guard_is_object print int(cpu.check_is_object(p0)) call_initial_function(t, g) cbuilder = genc.CStandaloneBuilder(t, main, t.config) cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) cbuilder.compile() data = cbuilder.cmdexec('') assert data == ('fail\n' 'match\n' 'fail\n' 'fail\n' '0\n' 'match\n' '1\n' 'fail\n' '0\n' 'fail\n' '0\n' 'match\n' '1\n' 'match\n' '1\n' 'fail\n' '0\n' 'fail\n' 'match\n' 'match\n')
v = llops.genop('cast_pointer', [v], resulttype = r_ins2.lowleveltype) return v else: return NotImplemented def rtype_is_((r_ins1, r_ins2), hop): if r_ins1.gcflavor != r_ins2.gcflavor: # obscure logic, the is can be true only if both are None v_ins1, v_ins2 = hop.inputargs(r_ins1.common_repr(), r_ins2.common_repr()) return hop.gendirectcall(ll_both_none, v_ins1, v_ins2) if r_ins1.classdef is None or r_ins2.classdef is None: basedef = None else: basedef = r_ins1.classdef.commonbase(r_ins2.classdef) r_ins = getinstancerepr(r_ins1.rtyper, basedef, r_ins1.gcflavor) return pairtype(Repr, Repr).rtype_is_(pair(r_ins, r_ins), hop) rtype_eq = rtype_is_ def rtype_ne(rpair, hop): v = rpair.rtype_eq(hop) return hop.genop("bool_not", [v], resulttype=Bool) # ____________________________________________________________ # # Low-level implementation of operations on classes and instances # doesn't work for non-gc stuff! def ll_cast_to_object(obj): return cast_pointer(OBJECTPTR, obj)
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 get_standard_ll_exc_instance(self, rtyper, clsdef): rclass = rtyper.type_system.rclass r_inst = rclass.getinstancerepr(rtyper, clsdef) example = r_inst.get_reusable_prebuilt_instance() example = self.cast_exception(self.lltype_of_exception_value, example) return example
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): if hints: self.lowleveltype._hints.update(hints) if self.classdef is None: self.fields = {} self.allfields = {} self.allmethods = {} self.allclassattributes = {} self.classattributes = {} return if self.baserepr is not None: allfields = self.baserepr.allfields.copy() allmethods = self.baserepr.allmethods.copy() allclassattributes = self.baserepr.allclassattributes.copy() else: allfields = {} allmethods = {} allclassattributes = {} fields = {} nonmangledfields = [] fielddefaults = {} if llfields: fields.update(dict(llfields)) selfattrs = self.classdef.attrs for name, attrdef in selfattrs.iteritems(): mangled = mangle(name, self.rtyper.getconfig()) if not attrdef.readonly: repr = self.rtyper.getrepr(attrdef.s_value) allfields[mangled] = repr oot = repr.lowleveltype fields[mangled] = oot nonmangledfields.append(name) try: value = self.classdef.classdesc.read_attribute(name) fielddefaults[mangled] = repr.convert_desc_or_const(value) except AttributeError: pass else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): if len(s_value.descriptions) > 0 and s_value.getKind( ) == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError( "method overrides class attribute") allmethods[ mangled] = name, self.classdef.lookup_filter( s_value) continue # class attribute if mangled in allmethods: raise TyperError("class attribute overrides method") allclassattributes[mangled] = name, s_value special_methods = ["__init__", "__del__"] for meth_name in special_methods: if meth_name not in selfattrs and \ self.classdef.classdesc.find_source_for(meth_name) is not None: s_meth = self.classdef.classdesc.s_get_value( self.classdef, meth_name) if isinstance(s_meth, annmodel.SomePBC): mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception ootype.addFields(self.lowleveltype, fields) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() for name, attrdef in selfattrs.iteritems(): if not attrdef.readonly and self.is_quasi_immutable(name): name = mangle('mutable_' + name, self.rtyper.getconfig()) ootype.addFields(self.lowleveltype, {name: OBJECT}) classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) # if this class has a corresponding metaclass, attach # a getmeta() method to get the corresponding meta_instance if classrepr.lowleveltype != ootype.Class: oovalue = classrepr.get_meta_instance() self.attach_class_attr_accessor('getmeta', oovalue) for classdef in self.classdef.getmro(): for name, attrdef in classdef.attrs.iteritems(): if not attrdef.readonly: continue mangled = mangle(name, self.rtyper.getconfig()) if mangled in allclassattributes: selfdesc = self.classdef.classdesc if name not in selfattrs: # if the attr was already found in a parent class, # we register it again only if it is overridden. if selfdesc.find_source_for(name) is None: continue value = selfdesc.read_attribute(name) else: # otherwise, for new attrs, we look in all parent # classes to see if it's defined in a parent but only # actually first used in self.classdef. value = selfdesc.read_attribute(name, None) # a non-method class attribute if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value self.fields = nonmangledfields self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes self.classattributes = classattributes # the following is done after the rest of the initialization because # convert_const can require 'self' to be fully initialized. # step 2: provide default values for fields for mangled, impl in fielddefaults.items(): oot = fields[mangled] ootype.addFields(self.lowleveltype, {mangled: (oot, impl)}, with_default=True)
resulttype=r_ins2.lowleveltype) return v else: return NotImplemented def rtype_is_((r_ins1, r_ins2), hop): if r_ins1.gcflavor != r_ins2.gcflavor: # obscure logic, the is can be true only if both are None v_ins1, v_ins2 = hop.inputargs(r_ins1.common_repr(), r_ins2.common_repr()) return hop.gendirectcall(ll_both_none, v_ins1, v_ins2) if r_ins1.classdef is None or r_ins2.classdef is None: basedef = None else: basedef = r_ins1.classdef.commonbase(r_ins2.classdef) r_ins = getinstancerepr(r_ins1.rtyper, basedef, r_ins1.gcflavor) return pairtype(Repr, Repr).rtype_is_(pair(r_ins, r_ins), hop) rtype_eq = rtype_is_ def rtype_ne(rpair, hop): v = rpair.rtype_eq(hop) return hop.genop("bool_not", [v], resulttype=Bool) # ____________________________________________________________ # # Low-level implementation of operations on classes and instances # doesn't work for non-gc stuff!
def setup_vtable(self, vtable, rsubcls): """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: vtable.hash = hash(rsubcls) # initialize the 'subclassrange_*' and 'name' fields if rsubcls.classdef is not None: #vtable.parenttypeptr = rsubcls.rbase.getvtable() vtable.subclassrange_min = rsubcls.classdef.minid vtable.subclassrange_max = rsubcls.classdef.maxid else: #for the root class vtable.subclassrange_min = 0 vtable.subclassrange_max = sys.maxint rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) rinstance.setup() if rinstance.gcflavor == 'gc': vtable.rtti = getRuntimeTypeInfo(rinstance.object_type) if rsubcls.classdef is None: name = 'object' else: name = rsubcls.classdef.shortname vtable.name = alloc_array_name(name) if hasattr(rsubcls.classdef, 'my_instantiate_graph'): graph = rsubcls.classdef.my_instantiate_graph vtable.instantiate = self.rtyper.getcallable(graph) #else: the classdef was created recently, so no instantiate() # could reach it else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls def assign(mangled_name, value): if isinstance(value, Constant) and isinstance( value.value, staticmethod): value = Constant(value.value.__get__( 42)) # staticmethod => bare function llvalue = r.convert_desc_or_const(value) setattr(vtable, mangled_name, llvalue) mro = list(rsubcls.classdef.getmro()) for fldname in self.clsfields: mangled_name, r = self.clsfields[fldname] if r.lowleveltype is Void: continue value = rsubcls.classdef.classdesc.read_attribute( fldname, None) if value is not None: assign(mangled_name, value) # extra PBC attributes for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): if rsubcls.classdef.classdesc not in access_set.descs: continue # only for the classes in the same pbc access set if r.lowleveltype is Void: continue attrvalue = rsubcls.classdef.classdesc.read_attribute( attr, None) if attrvalue is not None: assign(mangled_name, attrvalue) # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls)