def func_info(cls, func: types.FunctionType) -> types.FunctionType: names = func.__code__.co_names code = Bytecode.from_code(func.__code__) codeinfo = cls.code_info(code) def r_compile(): jit_func = Aware.f(self) print("jit_func", type(jit_func)) bc = Bytecode() bc.append(PyInstr(InstrNames.LOAD_CONST, jit_func)) bc.extend([load_arg(each, cellvars, lineno) for each in argnames]) bc.extend([ PyInstr(InstrNames.CALL_FUNCTION, len(argnames)), PyInstr(InstrNames.RETURN_VALUE) ]) bc._copy_attr_from(code) start_func.__code__ = bc.to_code() start_func.__jit__ = jit_func return jit_func start_func = copy_func(func) start_func_code = Bytecode() lineno = code.first_lineno argnames = code.argnames start_func_code.argnames = argnames cellvars = code.cellvars start_func_code.extend([ PyInstr(InstrNames.LOAD_CONST, r_compile, lineno=lineno), PyInstr(InstrNames.CALL_FUNCTION, 0, lineno=lineno), *(load_arg(each, cellvars, lineno) for each in argnames), PyInstr(InstrNames.CALL_FUNCTION, len(argnames), lineno=lineno), PyInstr(InstrNames.RETURN_VALUE, lineno=lineno) ]) start_func_code._copy_attr_from(code) self = PyFuncInfo(func.__name__, func.__module__, func.__defaults__, func.__kwdefaults__, func.__closure__, func.__globals__, codeinfo, func, {}, names) start_func.__code__ = start_func_code.to_code() start_func.__func_info__ = self start_func.__compile__ = r_compile start_func.__jit__ = None return start_func
def modify(self, code, *, inner=False): initial_bytecode = Bytecode.from_code(code) modified_bytecode = Bytecode() modified_bytecode.first_lineno = initial_bytecode.first_lineno modified_bytecode.argcount = code.co_argcount modified_bytecode.argnames = initial_bytecode.argnames modified_bytecode.name = initial_bytecode.name modified_bytecode.freevars = code.co_freevars modified_bytecode.cellvars = code.co_cellvars first_line_no = initial_bytecode.first_lineno if inner: modified_bytecode.extend([ Instr('LOAD_NAME', arg=self._command, lineno=first_line_no), Instr('LOAD_CONST', arg=DebugCommand.STEP_OVER, lineno=first_line_no), Instr('COMPARE_OP', arg=Compare.EQ, lineno=first_line_no), Instr('STORE_NAME', arg='is_over', lineno=first_line_no), ]) # добавляем инструкции отладки перед первой строкой модуля if not inner: modified_bytecode.extend( self._get_trace_func_call_instructions(first_line_no)) previous_line_no = first_line_no for instr in initial_bytecode: if not isinstance(instr, Instr): modified_bytecode.append(instr) continue if isinstance(instr.arg, types.CodeType): old_instr_name = instr.name new_co = self.modify(instr.arg, inner=True) instr.set(old_instr_name, new_co) skip = Label() if instr.lineno != previous_line_no: if inner: modified_bytecode.extend([ Instr('LOAD_NAME', arg='is_over', lineno=instr.lineno), Instr('POP_JUMP_IF_TRUE', arg=skip, lineno=instr.lineno) ]) modified_bytecode.extend([ Instr('LOAD_NAME', arg=self._command, lineno=instr.lineno), Instr('LOAD_CONST', arg=DebugCommand.STEP_OUT, lineno=instr.lineno), Instr('COMPARE_OP', arg=Compare.EQ, lineno=instr.lineno), Instr('POP_JUMP_IF_TRUE', arg=skip, lineno=instr.lineno) ]) modified_bytecode.extend( self._get_trace_func_call_instructions(instr.lineno)) if inner: modified_bytecode.append(skip) previous_line_no = instr.lineno modified_bytecode.append(instr) code = modified_bytecode.to_code() return code