PostgreSQL Source Code  git master
jit.c
Go to the documentation of this file.
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-2024, 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 "fmgr.h"
25 #include "jit/jit.h"
26 #include "miscadmin.h"
27 #include "nodes/execnodes.h"
28 #include "portability/instr_time.h"
29 #include "utils/fmgrprotos.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 
44 static bool provider_successfully_loaded = false;
45 static bool provider_failed_loading = false;
46 
47 
48 static bool provider_init(void);
49 
50 
51 /*
52  * SQL level function returning whether JIT is available in the current
53  * backend. Will attempt to load JIT provider if necessary.
54  */
55 Datum
57 {
59 }
60 
61 
62 /*
63  * Return whether a JIT provider has successfully been loaded, caching the
64  * result.
65  */
66 static bool
68 {
69  char path[MAXPGPATH];
71 
72  /* don't even try to load if not enabled */
73  if (!jit_enabled)
74  return false;
75 
76  /*
77  * Don't retry loading after failing - attempting to load JIT provider
78  * isn't cheap.
79  */
81  return false;
83  return true;
84 
85  /*
86  * Check whether shared library exists. We do that check before actually
87  * attempting to load the shared library (via load_external_function()),
88  * because that'd error out in case the shlib isn't available.
89  */
90  snprintf(path, MAXPGPATH, "%s/%s%s", pkglib_path, jit_provider, DLSUFFIX);
91  elog(DEBUG1, "probing availability of JIT provider at %s", path);
92  if (!pg_file_exists(path))
93  {
94  elog(DEBUG1,
95  "provider not available, disabling JIT for current session");
97  return false;
98  }
99 
100  /*
101  * If loading functions fails, signal failure. We do so because
102  * load_external_function() might error out despite the above check if
103  * e.g. the library's dependencies aren't installed. We want to signal
104  * ERROR in that case, so the user is notified, but we don't want to
105  * continually retry.
106  */
108 
109  /* and initialize */
111  load_external_function(path, "_PG_jit_provider_init", true, NULL);
112  init(&provider);
113 
115  provider_failed_loading = false;
116 
117  elog(DEBUG1, "successfully loaded JIT provider in current session");
118 
119  return true;
120 }
121 
122 /*
123  * Reset JIT provider's error handling. This'll be called after an error has
124  * been thrown and the main-loop has re-established control.
125  */
126 void
128 {
131 }
132 
133 /*
134  * Release resources required by one JIT context.
135  */
136 void
138 {
140  provider.release_context(context);
141 
142  pfree(context);
143 }
144 
145 /*
146  * Ask provider to JIT compile an expression.
147  *
148  * Returns true if successful, false if not.
149  */
150 bool
152 {
153  /*
154  * We can easily create a one-off context for functions without an
155  * associated PlanState (and thus EState). But because there's no executor
156  * shutdown callback that could deallocate the created function, they'd
157  * live to the end of the transactions, where they'd be cleaned up by the
158  * resowner machinery. That can lead to a noticeable amount of memory
159  * usage, and worse, trigger some quadratic behaviour in gdb. Therefore,
160  * at least for now, don't create a JITed function in those circumstances.
161  */
162  if (!state->parent)
163  return false;
164 
165  /* if no jitting should be performed at all */
166  if (!(state->parent->state->es_jit_flags & PGJIT_PERFORM))
167  return false;
168 
169  /* or if expressions aren't JITed */
170  if (!(state->parent->state->es_jit_flags & PGJIT_EXPR))
171  return false;
172 
173  /* this also takes !jit_enabled into account */
174  if (provider_init())
175  return provider.compile_expr(state);
176 
177  return false;
178 }
179 
180 /* Aggregate JIT instrumentation information */
181 void
183 {
190 }
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:105
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:224
bool pg_file_exists(const char *name)
Definition: fd.c:503
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char pkglib_path[MAXPGPATH]
Definition: globals.c:79
#define INSTR_TIME_ADD(x, y)
Definition: instr_time.h:178
int init
Definition: isn.c:75
void jit_reset_after_error(void)
Definition: jit.c:127
double jit_optimize_above_cost
Definition: jit.c:41
bool jit_dump_bitcode
Definition: jit.c:35
bool jit_enabled
Definition: jit.c:32
static bool provider_successfully_loaded
Definition: jit.c:44
char * jit_provider
Definition: jit.c:33
bool jit_expressions
Definition: jit.c:36
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:182
Datum pg_jit_available(PG_FUNCTION_ARGS)
Definition: jit.c:56
bool jit_compile_expr(struct ExprState *state)
Definition: jit.c:151
bool jit_tuple_deforming
Definition: jit.c:38
void jit_release_context(JitContext *context)
Definition: jit.c:137
double jit_above_cost
Definition: jit.c:39
static bool provider_failed_loading
Definition: jit.c:45
double jit_inline_above_cost
Definition: jit.c:40
static bool provider_init(void)
Definition: jit.c:67
bool jit_profiling_support
Definition: jit.c:37
bool jit_debugging_support
Definition: jit.c:34
static JitProviderCallbacks provider
Definition: jit.c:43
#define PGJIT_EXPR
Definition: jit.h:23
void(* JitProviderInit)(JitProviderCallbacks *cb)
Definition: jit.h:70
#define PGJIT_PERFORM
Definition: jit.h:20
void pfree(void *pointer)
Definition: mcxt.c:1508
#define MAXPGPATH
#define snprintf
Definition: port.h:238
uintptr_t Datum
Definition: postgres.h:64
Definition: jit.h:58
instr_time generation_counter
Definition: jit.h:33
size_t created_functions
Definition: jit.h:30
instr_time optimization_counter
Definition: jit.h:42
instr_time deform_counter
Definition: jit.h:36
instr_time emission_counter
Definition: jit.h:45
instr_time inlining_counter
Definition: jit.h:39
JitProviderCompileExprCB compile_expr
Definition: jit.h:80
JitProviderResetAfterErrorCB reset_after_error
Definition: jit.h:78
JitProviderReleaseContextCB release_context
Definition: jit.h:79
Definition: regguts.h:323