示例#1
0
    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
示例#2
0
    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