LCOV - differential code coverage report
Current view: top level - src/backend/jit - jit.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 78.9 % 57 45 12 1 44 1
Current Date: 2023-04-08 17:13:01 Functions: 85.7 % 7 6 1 1 5
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 78.6 % 56 44 12 44
Function coverage date bins:
(240..) days: 85.7 % 7 6 1 1 5

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * jit.c
                                  4                 :  *    Provider independent JIT infrastructure.
                                  5                 :  *
                                  6                 :  * Code related to loading JIT providers, redirecting calls into JIT providers
                                  7                 :  * and error handling.  No code specific to a specific JIT implementation
                                  8                 :  * should end up here.
                                  9                 :  *
                                 10                 :  *
                                 11                 :  * Copyright (c) 2016-2023, PostgreSQL Global Development Group
                                 12                 :  *
                                 13                 :  * IDENTIFICATION
                                 14                 :  *    src/backend/jit/jit.c
                                 15                 :  *
                                 16                 :  *-------------------------------------------------------------------------
                                 17                 :  */
                                 18                 : #include "postgres.h"
                                 19                 : 
                                 20                 : #include <sys/types.h>
                                 21                 : #include <sys/stat.h>
                                 22                 : #include <unistd.h>
                                 23                 : 
                                 24                 : #include "executor/execExpr.h"
                                 25                 : #include "fmgr.h"
                                 26                 : #include "jit/jit.h"
                                 27                 : #include "miscadmin.h"
                                 28                 : #include "utils/fmgrprotos.h"
                                 29                 : #include "utils/resowner_private.h"
                                 30                 : 
                                 31                 : /* GUCs */
                                 32                 : bool        jit_enabled = true;
                                 33                 : char       *jit_provider = NULL;
                                 34                 : bool        jit_debugging_support = false;
                                 35                 : bool        jit_dump_bitcode = false;
                                 36                 : bool        jit_expressions = true;
                                 37                 : bool        jit_profiling_support = false;
                                 38                 : bool        jit_tuple_deforming = true;
                                 39                 : double      jit_above_cost = 100000;
                                 40                 : double      jit_inline_above_cost = 500000;
                                 41                 : double      jit_optimize_above_cost = 500000;
                                 42                 : 
                                 43                 : static JitProviderCallbacks provider;
                                 44                 : static bool provider_successfully_loaded = false;
                                 45                 : static bool provider_failed_loading = false;
                                 46                 : 
                                 47                 : 
                                 48                 : static bool provider_init(void);
                                 49                 : static bool file_exists(const char *name);
                                 50                 : 
                                 51                 : 
                                 52                 : /*
                                 53                 :  * SQL level function returning whether JIT is available in the current
                                 54                 :  * backend. Will attempt to load JIT provider if necessary.
                                 55                 :  */
                                 56                 : Datum
 1845 andres                     57 UBC           0 : pg_jit_available(PG_FUNCTION_ARGS)
                                 58                 : {
                                 59               0 :     PG_RETURN_BOOL(provider_init());
                                 60                 : }
                                 61                 : 
                                 62                 : 
                                 63                 : /*
                                 64                 :  * Return whether a JIT provider has successfully been loaded, caching the
                                 65                 :  * result.
                                 66                 :  */
                                 67                 : static bool
 1845 andres                     68 CBC        5176 : provider_init(void)
                                 69                 : {
                                 70                 :     char        path[MAXPGPATH];
                                 71                 :     JitProviderInit init;
                                 72                 : 
                                 73                 :     /* don't even try to load if not enabled */
                                 74            5176 :     if (!jit_enabled)
 1845 andres                     75 UBC           0 :         return false;
                                 76                 : 
                                 77                 :     /*
                                 78                 :      * Don't retry loading after failing - attempting to load JIT provider
                                 79                 :      * isn't cheap.
                                 80                 :      */
 1845 andres                     81 CBC        5176 :     if (provider_failed_loading)
 1845 andres                     82 UBC           0 :         return false;
 1845 andres                     83 CBC        5176 :     if (provider_successfully_loaded)
                                 84            4783 :         return true;
                                 85                 : 
                                 86                 :     /*
                                 87                 :      * Check whether shared library exists. We do that check before actually
                                 88                 :      * attempting to load the shared library (via load_external_function()),
                                 89                 :      * because that'd error out in case the shlib isn't available.
                                 90                 :      */
                                 91             393 :     snprintf(path, MAXPGPATH, "%s/%s%s", pkglib_path, jit_provider, DLSUFFIX);
                                 92             393 :     elog(DEBUG1, "probing availability of JIT provider at %s", path);
                                 93             393 :     if (!file_exists(path))
                                 94                 :     {
 1845 andres                     95 UBC           0 :         elog(DEBUG1,
                                 96                 :              "provider not available, disabling JIT for current session");
                                 97               0 :         provider_failed_loading = true;
                                 98               0 :         return false;
                                 99                 :     }
                                100                 : 
                                101                 :     /*
                                102                 :      * If loading functions fails, signal failure. We do so because
                                103                 :      * load_external_function() might error out despite the above check if
                                104                 :      * e.g. the library's dependencies aren't installed. We want to signal
                                105                 :      * ERROR in that case, so the user is notified, but we don't want to
                                106                 :      * continually retry.
                                107                 :      */
 1845 andres                    108 CBC         393 :     provider_failed_loading = true;
                                109                 : 
                                110                 :     /* and initialize */
                                111             393 :     init = (JitProviderInit)
                                112             393 :         load_external_function(path, "_PG_jit_provider_init", true, NULL);
                                113             393 :     init(&provider);
                                114                 : 
                                115             393 :     provider_successfully_loaded = true;
                                116             393 :     provider_failed_loading = false;
                                117                 : 
                                118             393 :     elog(DEBUG1, "successfully loaded JIT provider in current session");
                                119                 : 
                                120             393 :     return true;
                                121                 : }
                                122                 : 
                                123                 : /*
                                124                 :  * Reset JIT provider's error handling. This'll be called after an error has
                                125                 :  * been thrown and the main-loop has re-established control.
                                126                 :  */
                                127                 : void
                                128           17749 : jit_reset_after_error(void)
                                129                 : {
                                130           17749 :     if (provider_successfully_loaded)
                                131            1453 :         provider.reset_after_error();
                                132           17749 : }
                                133                 : 
                                134                 : /*
                                135                 :  * Release resources required by one JIT context.
                                136                 :  */
                                137                 : void
                                138             839 : jit_release_context(JitContext *context)
                                139                 : {
                                140             839 :     if (provider_successfully_loaded)
                                141             839 :         provider.release_context(context);
                                142                 : 
                                143             839 :     ResourceOwnerForgetJIT(context->resowner, PointerGetDatum(context));
                                144             839 :     pfree(context);
                                145             839 : }
                                146                 : 
                                147                 : /*
                                148                 :  * Ask provider to JIT compile an expression.
                                149                 :  *
                                150                 :  * Returns true if successful, false if not.
                                151                 :  */
                                152                 : bool
 1846                           153         1095510 : jit_compile_expr(struct ExprState *state)
                                154                 : {
                                155                 :     /*
                                156                 :      * We can easily create a one-off context for functions without an
                                157                 :      * associated PlanState (and thus EState). But because there's no executor
                                158                 :      * shutdown callback that could deallocate the created function, they'd
                                159                 :      * live to the end of the transactions, where they'd be cleaned up by the
                                160                 :      * resowner machinery. That can lead to a noticeable amount of memory
                                161                 :      * usage, and worse, trigger some quadratic behaviour in gdb. Therefore,
                                162                 :      * at least for now, don't create a JITed function in those circumstances.
                                163                 :      */
                                164         1095510 :     if (!state->parent)
                                165          388031 :         return false;
                                166                 : 
                                167                 :     /* if no jitting should be performed at all */
                                168          707479 :     if (!(state->parent->state->es_jit_flags & PGJIT_PERFORM))
                                169          702303 :         return false;
                                170                 : 
                                171                 :     /* or if expressions aren't JITed */
                                172            5176 :     if (!(state->parent->state->es_jit_flags & PGJIT_EXPR))
 1846 andres                    173 UBC           0 :         return false;
                                174                 : 
                                175                 :     /* this also takes !jit_enabled into account */
 1846 andres                    176 CBC        5176 :     if (provider_init())
                                177            5176 :         return provider.compile_expr(state);
                                178                 : 
 1846 andres                    179 UBC           0 :     return false;
                                180                 : }
                                181                 : 
                                182                 : /* Aggregate JIT instrumentation information */
                                183                 : void
 1657 andres                    184 CBC          48 : InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
                                185                 : {
                                186              48 :     dst->created_functions += add->created_functions;
                                187              48 :     INSTR_TIME_ADD(dst->generation_counter, add->generation_counter);
                                188              48 :     INSTR_TIME_ADD(dst->inlining_counter, add->inlining_counter);
                                189              48 :     INSTR_TIME_ADD(dst->optimization_counter, add->optimization_counter);
                                190              48 :     INSTR_TIME_ADD(dst->emission_counter, add->emission_counter);
                                191              48 : }
                                192                 : 
                                193                 : static bool
 1845                           194             393 : file_exists(const char *name)
                                195                 : {
                                196                 :     struct stat st;
                                197                 : 
  163 peter                     198 GNC         393 :     Assert(name != NULL);
                                199                 : 
 1845 andres                    200 CBC         393 :     if (stat(name, &st) == 0)
  578 michael                   201             393 :         return !S_ISDIR(st.st_mode);
 1845 andres                    202 UBC           0 :     else if (!(errno == ENOENT || errno == ENOTDIR))
                                203               0 :         ereport(ERROR,
                                204                 :                 (errcode_for_file_access(),
                                205                 :                  errmsg("could not access file \"%s\": %m", name)));
                                206                 : 
                                207               0 :     return false;
                                208                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a