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-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 
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
58 {
60 }
61 
62 
63 /*
64  * Return whether a JIT provider has successfully been loaded, caching the
65  * result.
66  */
67 static bool
69 {
70  char path[MAXPGPATH];
72 
73  /* don't even try to load if not enabled */
74  if (!jit_enabled)
75  return false;
76 
77  /*
78  * Don't retry loading after failing - attempting to load JIT provider
79  * isn't cheap.
80  */
82  return false;
84  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  snprintf(path, MAXPGPATH, "%s/%s%s", pkglib_path, jit_provider, DLSUFFIX);
92  elog(DEBUG1, "probing availability of JIT provider at %s", path);
93  if (!file_exists(path))
94  {
95  elog(DEBUG1,
96  "provider not available, disabling JIT for current session");
98  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  */
109 
110  /* and initialize */
112  load_external_function(path, "_PG_jit_provider_init", true, NULL);
113  init(&provider);
114 
116  provider_failed_loading = false;
117 
118  elog(DEBUG1, "successfully loaded JIT provider in current session");
119 
120  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
129 {
132 }
133 
134 /*
135  * Release resources required by one JIT context.
136  */
137 void
139 {
141  provider.release_context(context);
142 
143  ResourceOwnerForgetJIT(context->resowner, PointerGetDatum(context));
144  pfree(context);
145 }
146 
147 /*
148  * Ask provider to JIT compile an expression.
149  *
150  * Returns true if successful, false if not.
151  */
152 bool
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  if (!state->parent)
165  return false;
166 
167  /* if no jitting should be performed at all */
168  if (!(state->parent->state->es_jit_flags & PGJIT_PERFORM))
169  return false;
170 
171  /* or if expressions aren't JITed */
172  if (!(state->parent->state->es_jit_flags & PGJIT_EXPR))
173  return false;
174 
175  /* this also takes !jit_enabled into account */
176  if (provider_init())
177  return provider.compile_expr(state);
178 
179  return false;
180 }
181 
182 /* Aggregate JIT instrumentation information */
183 void
185 {
191 }
192 
193 static bool
194 file_exists(const char *name)
195 {
196  struct stat st;
197 
198  Assert(name != NULL);
199 
200  if (stat(name, &st) == 0)
201  return !S_ISDIR(st.st_mode);
202  else if (!(errno == ENOENT || errno == ENOTDIR))
203  ereport(ERROR,
205  errmsg("could not access file \"%s\": %m", name)));
206 
207  return false;
208 }
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:105
int errcode_for_file_access(void)
Definition: elog.c:881
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define DEBUG1
Definition: elog.h:30
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
const char * name
Definition: encode.c:571
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char pkglib_path[MAXPGPATH]
Definition: globals.c:77
#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:128
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:184
Datum pg_jit_available(PG_FUNCTION_ARGS)
Definition: jit.c:57
bool jit_compile_expr(struct ExprState *state)
Definition: jit.c:153
bool jit_tuple_deforming
Definition: jit.c:38
void jit_release_context(JitContext *context)
Definition: jit.c:138
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:68
bool jit_profiling_support
Definition: jit.c:37
bool jit_debugging_support
Definition: jit.c:34
static JitProviderCallbacks provider
Definition: jit.c:43
static bool file_exists(const char *name)
Definition: jit.c:194
#define PGJIT_EXPR
Definition: jit.h:23
void(* JitProviderInit)(JitProviderCallbacks *cb)
Definition: jit.h:67
#define PGJIT_PERFORM
Definition: jit.h:20
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1456
#define MAXPGPATH
#define snprintf
Definition: port.h:238
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
void ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle)
Definition: resowner.c:1460
Definition: jit.h:55
ResourceOwner resowner
Definition: jit.h:59
instr_time generation_counter
Definition: jit.h:33
size_t created_functions
Definition: jit.h:30
instr_time optimization_counter
Definition: jit.h:39
instr_time emission_counter
Definition: jit.h:42
instr_time inlining_counter
Definition: jit.h:36
JitProviderCompileExprCB compile_expr
Definition: jit.h:77
JitProviderResetAfterErrorCB reset_after_error
Definition: jit.h:75
JitProviderReleaseContextCB release_context
Definition: jit.h:76
unsigned short st_mode
Definition: win32_port.h:276
Definition: regguts.h:323
#define stat
Definition: win32_port.h:292
#define S_ISDIR(m)
Definition: win32_port.h:333