Jit/jit_context.h (104 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #pragma once #include "Python.h" #include "Jit/compiler.h" #include "Jit/containers.h" #include "Jit/hir/preload.h" #include "Jit/pyjit_result.h" #include "Jit/pyjit_typeslots.h" #include "Jit/ref.h" #include "Jit/slot_gen.h" #include "Jit/util.h" #include <functional> #include <memory> #include <vector> // Lookup key for _PyJITContext::compiled_codes: a code object and a globals // dict it was JIT-compiled with. struct CompilationKey { // These are both weak references; the values are kept alive by strong // references in the corresponding jit::CodeRuntime. PyObject* code; PyObject* globals; CompilationKey(PyObject* code, PyObject* globals) : code(code), globals(globals) {} bool operator==(const CompilationKey& other) const { return code == other.code && globals == other.globals; } }; template <> struct std::hash<CompilationKey> { std::size_t operator()(const CompilationKey& key) const { std::hash<PyObject*> hasher; return jit::combineHash(hasher(key.code), hasher(key.globals)); } }; /* Deoptimization information for a compiled type. */ struct TypeDeoptInfo { explicit TypeDeoptInfo(PyTypeObject* type) : orig_tp_call{type->tp_call}, orig_tp_init{type->tp_init}, orig_tp_repr{type->tp_repr}, orig_tp_str{type->tp_str}, orig_tp_getattro{type->tp_getattro}, orig_tp_descr_get{type->tp_descr_get} {} // Original values for compiled type objects. ternaryfunc orig_tp_call; initproc orig_tp_init; reprfunc orig_tp_repr; reprfunc orig_tp_str; getattrofunc orig_tp_getattro; descrgetfunc orig_tp_descr_get; }; /* * A JIT context encapsulates all the state managed by an instance of the JIT. */ struct _PyJITContext { ~_PyJITContext(); jit::SlotGen slot_gen; /* General purpose jit compiler */ jit::Compiler jit_compiler; /* * Map from compiled types to deoptimization information. */ jit::UnorderedMap<BorrowedRef<PyTypeObject>, TypeDeoptInfo> type_deopt; /* * Set of which functions have JIT-compiled entrypoints. */ jit::UnorderedSet<BorrowedRef<PyFunctionObject>> compiled_funcs; /* * Compiled code objects, keyed by PyCodeObject* and the globals dict they * were compiled with. */ jit::UnorderedMap<CompilationKey, std::unique_ptr<jit::CompiledFunction>> compiled_codes; /* * Code which is being kept alive in case it was in use when * _PyJITContext_ClearCache was called. Only intended to be used during * multithreaded_compile_test. */ std::vector<std::unique_ptr<jit::CompiledFunction>> orphaned_compiled_codes; }; /* * Clear cache of compiled code such that subsequent compilations are always * full rather than just re-binding pre-compiled code. Only intended to be used * during multithreaded_compile_test. */ void _PyJITContext_ClearCache(_PyJITContext* ctx); /* * Generate specialized functions for type object slots. Calls the other * _PyJITContext_Specialize* functions and handles setting up deoptimization * support. * * Returns PYJIT_RESULT_OK on success. */ _PyJIT_Result _PyJITContext_SpecializeType( _PyJITContext* ctx, BorrowedRef<PyTypeObject> type, _PyJIT_TypeSlots* slots); /* * JIT compile func and patch its entry point. * * On success, positional only calls to func will use the JIT compiled version. * * Returns PYJIT_RESULT_OK on success, or if the function was already compiled. */ _PyJIT_Result _PyJITContext_CompileFunction( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * JIT compile code and store the result in ctx. * * This does not patch the entry point of any functions; it is primarily useful * to pre-compile the code object for a nested function so it's available for * use after disabling the JIT. * * Returns 1 on success, 0 on failure. */ _PyJIT_Result _PyJITContext_CompileCode( _PyJITContext* ctx, BorrowedRef<> module, BorrowedRef<PyCodeObject> code, BorrowedRef<PyDictObject> globals); /* * JIT compile function/code-object from Preloader. * * Patches func entrypoint if Preloader contains a func. */ _PyJIT_Result _PyJITContext_CompilePreloader( _PyJITContext* ctx, const jit::hir::Preloader& preloader); /* * Attach already-compiled code to the given function, if it exists. * * Intended for (but not limited to) use with nested functions after the JIT is * disabled. * * Returns PYJIT_RESULT_OK on success or if the given function already had * compiled code attached. */ _PyJIT_Result _PyJITContext_AttachCompiledCode( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Callbacks invoked by the runtime when a PyFunctionObject is modified or * destroyed. */ void _PyJITContext_FuncModified( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); void _PyJITContext_FuncDestroyed( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Callbacks invoked by the runtime when a PyTypeObject is modified or * destroyed. */ void _PyJITContext_TypeModified( _PyJITContext* ctx, BorrowedRef<PyTypeObject> type); void _PyJITContext_TypeDestroyed( _PyJITContext* ctx, BorrowedRef<PyTypeObject> type); /* * Return whether or not this context compiled the supplied function. * * Return 1 if so, 0 if not, and -1 if an error occurred. */ int _PyJITContext_DidCompile( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Returns the code size in bytes for a specified JIT-compiled function. * * Returns 0 if the function is not JIT-compiled. * * Returns -1 if an error occurred. */ int _PyJITContext_GetCodeSize( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Returns the stack size in bytes for a specified JIT-compiled function. * * Returns -1 if an error occurred. */ int _PyJITContext_GetStackSize( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Returns the stack size used for spills in bytes for a specified JIT-compiled * function. * * Returns -1 if an error occurred. */ int _PyJITContext_GetSpillStackSize( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Return a list of functions that are currently JIT-compiled. * * Returns a new reference. * */ PyObject* _PyJITContext_GetCompiledFunctions(_PyJITContext* ctx); /* * Print the HIR for func to stdout if it was JIT-compiled. * This function is a no-op if func was not JIT-compiled. * * Returns -1 if an error occurred or 0 otherwise. */ int _PyJITContext_PrintHIR( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func); /* * Print the disassembled code for func to stdout if it was JIT-compiled. * This function is a no-op if func was not JIT-compiled. * * Returns -1 if an error occurred or 0 otherwise. */ int _PyJITContext_Disassemble( _PyJITContext* ctx, BorrowedRef<PyFunctionObject> func);