def gct_fv_gc_coalloc(self, hop, coallocator, flags, TYPE, *args): if self.coalloc_clear_ptr is None: return self.gct_fv_gc_malloc( hop, flags, TYPE, *args) op = hop.spaceop flavor = flags['flavor'] assert not flags.get("nocollect", False) PTRTYPE = op.result.concretetype assert PTRTYPE.TO == TYPE type_id = self.get_type_id(TYPE) c_type_id = rmodel.inputconst(lltype.Signed, type_id) info = self.layoutbuilder.type_info_list[type_id] c_size = rmodel.inputconst(lltype.Signed, info.fixedsize) has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) assert not has_finalizer v_coallocator = gen_cast(hop.llops, llmemory.Address, coallocator) if not op.opname.endswith('_varsize'): malloc_ptr = self.coalloc_clear_ptr args = [self.c_const_gc, v_coallocator, c_type_id, c_size] else: v_length = op.args[-1] c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) malloc_ptr = self.coalloc_varsize_clear_ptr args = [self.c_const_gc, v_coallocator, c_type_id, v_length, c_size, c_varitemsize, c_ofstolength] livevars = self.push_roots(hop) v_result = hop.genop("direct_call", [malloc_ptr] + args, resulttype=llmemory.GCREF) self.pop_roots(hop, livevars) return v_result
def pop_roots(self, hop, livevars): if not livevars: return # mark the values as gc roots for var in livevars: v_adr = gen_cast(hop.llops, llmemory.Address, var) v_newaddr = hop.genop("direct_call", [c_asm_gcroot, v_adr], resulttype=llmemory.Address) hop.genop("gc_reload_possibly_moved", [v_newaddr, var])
def specialize_call(self, hop): from pypy.rpython.rbuiltin import gen_cast hop.exception_cannot_occur() s_RESTYPE = hop.args_s[0] assert s_RESTYPE.is_constant() RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) TYPE1 = v_arg.concretetype return gen_cast(hop.llops, RESTYPE, v_arg)
def push_roots(self, hop, keep_current_args=False): livevars = self.get_livevars_for_roots(hop, keep_current_args) self.num_pushs += len(livevars) if not livevars: return [] for k, var in enumerate(livevars): c_k = rmodel.inputconst(lltype.Signed, k) v_adr = gen_cast(hop.llops, llmemory.Address, var) hop.genop("llvm_store_gcroot", [c_k, v_adr]) return livevars
def cast_result(self, var): v_result = self.spaceop.result resulttype = getattr(v_result, 'concretetype', PyObjPtr) curtype = getattr(var, 'concretetype', PyObjPtr) if curtype == resulttype: self.genop('same_as', [var], resultvar=v_result) else: v_new = gen_cast(self.llops, resulttype, var) assert v_new != var self.llops[-1].result = v_result
def push_roots(self, hop): if self.push_root_ptr is None: return livevars = [var for var in self.livevars if not var_ispyobj(var)] c_len = rmodel.inputconst(lltype.Signed, len(livevars) ) base_addr = hop.genop("direct_call", [self.incr_stack_ptr, c_len ], resulttype=llmemory.Address) for k,var in enumerate(livevars): c_k = rmodel.inputconst(lltype.Signed, k) v_adr = gen_cast(hop.llops, llmemory.Address, var) hop.genop("direct_call", [self.save_addr_ptr, base_addr, c_k, v_adr])
def pop_alive_nopyobj(self, var, llops): PTRTYPE = var.concretetype v_adr = gen_cast(llops, llmemory.Address, var) dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO) if dealloc_fptr is self.no_pointer_dealloc_ptr.value: # simple case llops.genop("direct_call", [self.decref_simple_ptr, v_adr]) else: cdealloc_fptr = rmodel.inputconst(lltype.typeOf(dealloc_fptr), dealloc_fptr) llops.genop("direct_call", [self.decref_ptr, v_adr, cdealloc_fptr])
def _generate_save_block(self, varsforcall, v_unwind_exception, saver): conc_types = tuple([v.concretetype for v in varsforcall]) if conc_types in self.curr_graph_save_blocks: return self.curr_graph_save_blocks[conc_types] rtyper = self.translator.rtyper edata = rtyper.getexceptiondata() etype = edata.lltype_of_exception_type evalue = edata.lltype_of_exception_value inputargs = [copyvar(v) for v in varsforcall] v_unwind_exception = copyvar(v_unwind_exception) save_state_block = model.Block(inputargs + [v_unwind_exception]) saveops = LowLevelOpList() v_exc = gen_cast(saveops, self.unwind_exception_type, v_unwind_exception) realvarsforcall = [v_exc] for v in inputargs: realvarsforcall.append(gen_cast(saveops, storage_type(v.concretetype), v)) saveops.genop('direct_call', [model.Constant(saver, lltype.typeOf(saver))] + realvarsforcall, resulttype=lltype.Void) save_state_block.operations = saveops type_repr = rclass.get_type_repr(rtyper) c_unwindexception = model.Constant( type_repr.convert_const(code.UnwindException), etype) if not hasattr(self.curr_graph.exceptblock.inputargs[0], 'concretetype'): self.curr_graph.exceptblock.inputargs[0].concretetype = etype if not hasattr(self.curr_graph.exceptblock.inputargs[1], 'concretetype'): self.curr_graph.exceptblock.inputargs[1].concretetype = evalue save_state_block.closeblock(model.Link( [c_unwindexception, v_unwind_exception], self.curr_graph.exceptblock)) self.translator.rtyper._convert_link( save_state_block, save_state_block.exits[0]) if SAVE_STATISTICS: self.stats.saveops += len(save_state_block.operations) self.curr_graph_save_blocks[conc_types] = save_state_block return save_state_block
def pop_alive_nopyobj(self, var, llops): PTRTYPE = var.concretetype v_adr = gen_cast(llops, llmemory.Address, var) dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO) if dealloc_fptr is self.no_pointer_dealloc_ptr.value: # simple case llops.genop("direct_call", [self.decref_simple_ptr, v_adr]) else: cdealloc_fptr = rmodel.inputconst( lltype.typeOf(dealloc_fptr), dealloc_fptr) llops.genop("direct_call", [self.decref_ptr, v_adr, cdealloc_fptr])
def pop_roots(self, hop, livevars): if not livevars: return # mark the values as gc roots for var in livevars: if 0: # uses direct support in genc - more compact code, # but it's probably not changing anything hop.genop("asm_gcroot", [var]) else: v_adr = gen_cast(hop.llops, llmemory.Address, var) v_newaddr = hop.genop("direct_call", [c_asm_gcroot, v_adr], resulttype=llmemory.Address) hop.genop("gc_reload_possibly_moved", [v_newaddr, var])
def insert_return_conversion(self, link, targettype, retvar): llops = LowLevelOpList() newvar = gen_cast(llops, targettype, retvar) convertblock = unsimplify.insert_empty_block(None, link, llops) # begin ouch! for index, linkvar in enumerate(convertblock.exits[0].args): # does this var come from retval ? try: index1 = convertblock.inputargs.index(linkvar) except ValueError: # e.g. linkvar is a Constant continue if link.args[index1] is retvar: # yes convertblock.exits[0].args[index] = newvar
def _make_cast_block(self, erased_types, exact_types): inputargs = [varoftype(t) for t in erased_types] cast_block = model.Block(inputargs) cast_block.operations = LowLevelOpList() output_args = [] assert len(inputargs) == len([typ for typ in exact_types if typ != lltype.Void]) i_arg = 0 for typ in exact_types: if typ == lltype.Void: output_args.append(model.Constant(None, lltype.Void)) else: arg = inputargs[i_arg] i_arg += 1 output_args.append(gen_cast(cast_block.operations, typ, arg)) assert i_arg == len(inputargs) return cast_block, output_args
def push_roots(self, hop, keep_current_args=False): if self.incr_stack_ptr is None: return livevars = self.get_livevars_for_roots(hop, keep_current_args) self.num_pushs += len(livevars) if not livevars: return [] c_len = rmodel.inputconst(lltype.Signed, len(livevars) ) base_addr = hop.genop("direct_call", [self.incr_stack_ptr, c_len ], resulttype=llmemory.Address) c_type = rmodel.inputconst(lltype.Void, llmemory.Address) for k,var in enumerate(livevars): c_k = rmodel.inputconst(lltype.Signed, k) v_adr = gen_cast(hop.llops, llmemory.Address, var) hop.genop("raw_store", [base_addr, c_type, c_k, v_adr]) return livevars
def _gct_resize_buffer_realloc(self, hop, v_newsize, grow=True): def intconst(c): return rmodel.inputconst(lltype.Signed, c) op = hop.spaceop flags = {'flavor':'gc', 'varsize': True} TYPE = op.args[0].concretetype.TO ARRAY = TYPE._flds[TYPE._arrayfld] offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ llmemory.ArrayLengthOffset(ARRAY) c_const_size = intconst(llmemory.sizeof(TYPE, 0)) c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) c_lengthofs = intconst(offset_to_length) v_ptr = op.args[0] v_ptr = gen_cast(hop.llops, llmemory.GCREF, v_ptr) c_grow = rmodel.inputconst(lltype.Bool, grow) v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, c_item_size, c_lengthofs, c_grow) hop.cast_result(v_raw)
def _gct_resize_buffer_realloc(self, hop, v_newsize, grow=True): def intconst(c): return rmodel.inputconst(lltype.Signed, c) op = hop.spaceop flags = {'flavor': 'gc', 'varsize': True} TYPE = op.args[0].concretetype.TO ARRAY = TYPE._flds[TYPE._arrayfld] offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ llmemory.ArrayLengthOffset(ARRAY) c_const_size = intconst(llmemory.sizeof(TYPE, 0)) c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) c_lengthofs = intconst(offset_to_length) v_ptr = op.args[0] v_ptr = gen_cast(hop.llops, llmemory.GCREF, v_ptr) c_grow = rmodel.inputconst(lltype.Bool, grow) v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, c_item_size, c_lengthofs, c_grow) hop.cast_result(v_raw)
def _make_resume_retrieval_block(self, FRAME_TYPE, erased_types): retrieve_block = model.Block([varoftype(lltype.Signed)]) retrieve_block.exitswitch = retrieve_block.inputargs[0] llops = LowLevelOpList() llops.genop("setfield", [self.ll_global_state, self.c_restart_substate_name, self.c_minus_one]) v_state_hdr = llops.genop("getfield", [self.ll_global_state, self.c_inst_top_name], resulttype=lltype.Ptr(STATE_HEADER)) v_state = gen_cast(llops, lltype.Ptr(FRAME_TYPE), v_state_hdr) llops.genop("setfield", [self.ll_global_state, self.c_inst_top_name, self.c_null_state]) output_args = [retrieve_block.inputargs[0]] assert len(FRAME_TYPE._names[1:]) == len(erased_types) for fieldname, TYPE in zip(FRAME_TYPE._names[1:], erased_types): assert FRAME_TYPE._flds[fieldname] == TYPE output_args.append(llops.genop("getfield", [v_state, model.Constant(fieldname, lltype.Void)], resulttype=TYPE)) retrieve_block.operations = llops return retrieve_block, output_args
def saving_function_for_type(self, FRAME_TYPE): v_exception = varoftype(self.transformer.unwind_exception_type) v_restart = varoftype(lltype.Signed) save_block = model.Block([v_exception, v_restart]) llops = LowLevelOpList() flags = {'flavor': 'gc'} if self.stackless_gc: flags['nocollect'] = True v_state = llops.genop('malloc', [model.Constant(FRAME_TYPE, lltype.Void), model.Constant(flags, lltype.Void)], resulttype=lltype.Ptr(FRAME_TYPE)) for fieldname in FRAME_TYPE._names[1:]: # skip the 'header' field v_arg = varoftype(FRAME_TYPE._flds[fieldname]) save_block.inputargs.append(v_arg) llops.genop('setfield', [v_state, model.Constant(fieldname, lltype.Void), v_arg], resulttype=lltype.Void) v_header = gen_cast(llops, lltype.Ptr(STATE_HEADER), v_state) llops.genop('direct_call', [self.transformer.add_frame_state_ptr, v_exception, v_header], resulttype=lltype.Void) llops.genop("setfield", [v_header, self.transformer.c_f_restart_name, v_restart], resulttype=lltype.Void) save_state_graph = model.FunctionGraph('save_' + FRAME_TYPE._name, save_block, varoftype(lltype.Void)) save_block.operations = llops save_block.closeblock(model.Link([v_header], save_state_graph.returnblock)) FUNC_TYPE = lltype.FuncType([v.concretetype for v in save_block.inputargs], lltype.Void) return lltype.functionptr(FUNC_TYPE, save_state_graph.name, graph=save_state_graph)
def gct_fv_gc_coalloc(self, hop, coallocator, flags, TYPE, *args): if self.coalloc_clear_ptr is None: return self.gct_fv_gc_malloc(hop, flags, TYPE, *args) op = hop.spaceop flavor = flags['flavor'] assert not flags.get("nocollect", False) PTRTYPE = op.result.concretetype assert PTRTYPE.TO == TYPE type_id = self.get_type_id(TYPE) c_type_id = rmodel.inputconst(lltype.Signed, type_id) info = self.layoutbuilder.type_info_list[type_id] c_size = rmodel.inputconst(lltype.Signed, info.fixedsize) has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) assert not has_finalizer v_coallocator = gen_cast(hop.llops, llmemory.Address, coallocator) if not op.opname.endswith('_varsize'): malloc_ptr = self.coalloc_clear_ptr args = [self.c_const_gc, v_coallocator, c_type_id, c_size] else: v_length = op.args[-1] c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) malloc_ptr = self.coalloc_varsize_clear_ptr args = [ self.c_const_gc, v_coallocator, c_type_id, v_length, c_size, c_varitemsize, c_ofstolength ] livevars = self.push_roots(hop) v_result = hop.genop("direct_call", [malloc_ptr] + args, resulttype=llmemory.GCREF) self.pop_roots(hop, livevars) return v_result
def pop_alive_pyobj(self, var, llops): if hasattr(var, 'concretetype') and var.concretetype != PyObjPtr: var = gen_cast(llops, PyObjPtr, var) llops.genop("gc_pop_alive_pyobj", [var])
def push_alive_nopyobj(self, var, llops): v_adr = gen_cast(llops, llmemory.Address, var) llops.genop("direct_call", [self.increfptr, v_adr])