def RTTI_dtor(self, STRUCT): try: destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr if destr_ptr: return True except (ValueError, AttributeError), e: pass
def malloc_to_stack(t): adi = AbstractDataFlowInterpreter(t) for graph in t.graphs: if graph.startblock not in adi.flown_blocks: adi.schedule_function(graph) adi.complete() for graph in t.graphs: loop_blocks = support.find_loop_blocks(graph) for block, op in graph.iterblockops(): if op.opname != 'malloc': continue STRUCT = op.args[0].value # must not remove mallocs of structures that have a RTTI with a destructor try: destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr if destr_ptr: continue except (ValueError, AttributeError), e: pass varstate = adi.getstate(op.result) assert len(varstate.creation_points) == 1 crep = varstate.creation_points.keys()[0] if not crep.escapes: if block not in loop_blocks: print "moving object from heap to stack %s in %s" % (op, graph.name) flags = op.args[1].value assert flags == {'flavor': 'gc'} op.args[1] = Constant({'flavor': 'stack'}, lltype.Void) else: print "%s in %s is a non-escaping malloc in a loop" % (op, graph.name)
def get_rtti(TYPE): if isinstance(TYPE, lltype.RttiStruct): try: return lltype.getRuntimeTypeInfo(TYPE) except ValueError: pass return None
def find_malloc_creps(graph, adi, translator, malloc_graphs): # mapping from malloc creation point to graphs that it flows into malloc_creps = {} # find all mallocs that don't escape for block, op in graph.iterblockops(): if op.opname == 'malloc': STRUCT = op.args[0].value # must not remove mallocs of structures that have a RTTI with a destructor flags = op.args[1].value if flags != {'flavor': 'gc'}: continue try: destr_ptr = lltype.getRuntimeTypeInfo( STRUCT)._obj.destructor_funcptr if destr_ptr: continue except (ValueError, AttributeError), e: pass varstate = adi.getstate(op.result) assert len(varstate.creation_points) == 1 crep, = varstate.creation_points if not crep.escapes and not crep.returns: malloc_creps[crep] = {} if op.opname == 'direct_call': called_graph = get_graph(op.args[0], translator) if called_graph not in malloc_graphs: continue varstate = adi.getstate(op.result) assert len(varstate.creation_points) == 1 crep, = varstate.creation_points if not crep.escapes and not crep.returns: malloc_creps[crep] = {}
def setup_vtable(self, vtable, rsubcls): """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: # 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 malloc_to_stack(t): adi = AbstractDataFlowInterpreter(t) for graph in t.graphs: if graph.startblock not in adi.flown_blocks: adi.schedule_function(graph) adi.complete() for graph in t.graphs: loop_blocks = support.find_loop_blocks(graph) for block, op in graph.iterblockops(): if op.opname == 'malloc': STRUCT = op.args[0].value # must not remove mallocs of structures that have a RTTI with a destructor try: destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr if destr_ptr: continue except (ValueError, AttributeError), e: pass varstate = adi.getstate(op.result) assert len(varstate.creation_points) == 1 crep = varstate.creation_points.keys()[0] if not crep.escapes: if block not in loop_blocks: print "moving object from heap to stack %s in %s" % (op, graph.name) op.opname = 'flavored_malloc' op.args.insert(0, inputconst(lltype.Void, 'stack')) else: print "%s in %s is a non-escaping malloc in a loop" % (op, graph.name)
def RTTI_dtor(self, STRUCT): try: destr_ptr = lltype.getRuntimeTypeInfo( STRUCT)._obj.destructor_funcptr if destr_ptr: return True except (ValueError, AttributeError), e: pass
def setup_vtable(self, vtable, rsubcls): """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: # 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 in RTTIFLAVORS: vtable.rtti = getRuntimeTypeInfo(rinstance.object_type) if rsubcls.classdef is None: name = 'object' else: name = rsubcls.classdef.shortname vtable.name = malloc(Array(Char), len(name)+1, immortal=True) for i in range(len(name)): vtable.name[i] = name[i] vtable.name[len(name)] = '\x00' 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 hasdestructor(STRUCT): if not isinstance(STRUCT, lltype.Struct): return False try: destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr if destr_ptr: return True except (ValueError, AttributeError), e: pass
def check_no_destructor(self): STRUCT = self.MALLOCTYPE try: rttiptr = lltype.getRuntimeTypeInfo(STRUCT) except ValueError: return # ok destr_ptr = getattr(rttiptr._obj, 'destructor_funcptr', None) if destr_ptr: raise CannotRemoveThisType
def computegcinfo(self): # let the gcpolicy do its own setup self.gcinfo = None # unless overwritten below rtti = None STRUCT = self.STRUCT if isinstance(STRUCT, RttiStruct): try: rtti = getRuntimeTypeInfo(STRUCT) except ValueError: pass if self.varlength == 1: self.db.gcpolicy.struct_setup(self, rtti) return self.gcinfo
def find_malloc_creps(graph, adi, translator): # mapping from malloc creation point to graphs that it flows into malloc_creps = {} # find all mallocs that don't escape for block, op in graph.iterblockops(): if op.opname == 'malloc': STRUCT = op.args[0].value # must not remove mallocs of structures that have a RTTI with a destructor try: destr_ptr = lltype.getRuntimeTypeInfo( STRUCT)._obj.destructor_funcptr if destr_ptr: continue except (ValueError, AttributeError), e: pass varstate = adi.getstate(op.result) assert len(varstate.creation_points) == 1 crep = varstate.creation_points.keys()[0] if not crep.escapes: malloc_creps[crep] = {}
def getRuntimeTypeInfo(T): assert T.is_constant() return immutablevalue(lltype.getRuntimeTypeInfo(T.const))
def type_info_S(s): return lltype.getRuntimeTypeInfo(S)
def type_info_T(p): return lltype.getRuntimeTypeInfo(T)