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-2019, PostgreSQL Global Development Group
12  *
13  * IDENTIFICATION
14  * src/backend/jit/jit.c
15  *
16  *-------------------------------------------------------------------------
17  */
18 #include "postgres.h"
19 
20 
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 
26 #include "fmgr.h"
27 #include "executor/execExpr.h"
28 #include "jit/jit.h"
29 #include "miscadmin.h"
30 #include "utils/resowner_private.h"
31 #include "utils/fmgrprotos.h"
32 
33 
34 /* GUCs */
35 bool jit_enabled = true;
36 char *jit_provider = NULL;
37 bool jit_debugging_support = false;
38 bool jit_dump_bitcode = false;
39 bool jit_expressions = true;
40 bool jit_profiling_support = false;
41 bool jit_tuple_deforming = true;
42 double jit_above_cost = 100000;
43 double jit_inline_above_cost = 500000;
44 double jit_optimize_above_cost = 500000;
45 
47 static bool provider_successfully_loaded = false;
48 static bool provider_failed_loading = false;
49 
50 
51 static bool provider_init(void);
52 static bool file_exists(const char *name);
53 
54 
55 /*
56  * SQL level function returning whether JIT is available in the current
57  * backend. Will attempt to load JIT provider if necessary.
58  */
59 Datum
61 {
63 }
64 
65 
66 /*
67  * Return whether a JIT provider has successfully been loaded, caching the
68  * result.
69  */
70 static bool
72 {
73  char path[MAXPGPATH];
75 
76  /* don't even try to load if not enabled */
77  if (!jit_enabled)
78  return false;
79 
80  /*
81  * Don't retry loading after failing - attempting to load JIT provider
82  * isn't cheap.
83  */
85  return false;
87  return true;
88 
89  /*
90  * Check whether shared library exists. We do that check before actually
91  * attempting to load the shared library (via load_external_function()),
92  * because that'd error out in case the shlib isn't available.
93  */
94  snprintf(path, MAXPGPATH, "%s/%s%s", pkglib_path, jit_provider, DLSUFFIX);
95  elog(DEBUG1, "probing availability of JIT provider at %s", path);
96  if (!file_exists(path))
97  {
98  elog(DEBUG1,
99  "provider not available, disabling JIT for current session");
101  return false;
102  }
103 
104  /*
105  * If loading functions fails, signal failure. We do so because
106  * load_external_function() might error out despite the above check if
107  * e.g. the library's dependencies aren't installed. We want to signal
108  * ERROR in that case, so the user is notified, but we don't want to
109  * continually retry.
110  */
112 
113  /* and initialize */
114  init = (JitProviderInit)
115  load_external_function(path, "_PG_jit_provider_init", true, NULL);
116  init(&provider);
117 
119  provider_failed_loading = false;
120 
121  elog(DEBUG1, "successfully loaded JIT provider in current session");
122 
123  return true;
124 }
125 
126 /*
127  * Reset JIT provider's error handling. This'll be called after an error has
128  * been thrown and the main-loop has re-established control.
129  */
130 void
132 {
134  provider.reset_after_error();
135 }
136 
137 /*
138  * Release resources required by one JIT context.
139  */
140 void
142 {
144  provider.release_context(context);
145 
146  ResourceOwnerForgetJIT(context->resowner, PointerGetDatum(context));
147  pfree(context);
148 }
149 
150 /*
151  * Ask provider to JIT compile an expression.
152  *
153  * Returns true if successful, false if not.
154  */
155 bool
157 {
158  /*
159  * We can easily create a one-off context for functions without an
160  * associated PlanState (and thus EState). But because there's no executor
161  * shutdown callback that could deallocate the created function, they'd
162  * live to the end of the transactions, where they'd be cleaned up by the
163  * resowner machinery. That can lead to a noticeable amount of memory
164  * usage, and worse, trigger some quadratic behaviour in gdb. Therefore,
165  * at least for now, don't create a JITed function in those circumstances.
166  */
167  if (!state->parent)
168  return false;
169 
170  /* if no jitting should be performed at all */
171  if (!(state->parent->state->es_jit_flags & PGJIT_PERFORM))
172  return false;
173 
174  /* or if expressions aren't JITed */
175  if (!(state->parent->state->es_jit_flags & PGJIT_EXPR))
176  return false;
177 
178  /* this also takes !jit_enabled into account */
179  if (provider_init())
180  return provider.compile_expr(state);
181 
182  return false;
183 }
184 
185 /* Aggregate JIT instrumentation information */
186 void
188 {
194 }
195 
196 static bool
197 file_exists(const char *name)
198 {
199  struct stat st;
200 
201  AssertArg(name != NULL);
202 
203  if (stat(name, &st) == 0)
204  return S_ISDIR(st.st_mode) ? false : true;
205  else if (!(errno == ENOENT || errno == ENOTDIR))
206  ereport(ERROR,
208  errmsg("could not access file \"%s\": %m", name)));
209 
210  return false;
211 }
char * jit_provider
Definition: jit.c:36
JitProviderResetAfterErrorCB reset_after_error
Definition: jit.h:75
#define PGJIT_EXPR
Definition: jit.h:23
#define DEBUG1
Definition: elog.h:25
struct PlanState * parent
Definition: execnodes.h:108
#define PointerGetDatum(X)
Definition: postgres.h:556
instr_time generation_counter
Definition: jit.h:33
bool jit_debugging_support
Definition: jit.c:37
Definition: jit.h:54
static bool provider_failed_loading
Definition: jit.c:48
#define false
Definition: c.h:316
EState * state
Definition: execnodes.h:947
void jit_reset_after_error(void)
Definition: jit.c:131
void pfree(void *pointer)
Definition: mcxt.c:1031
bool jit_enabled
Definition: jit.c:35
#define ERROR
Definition: elog.h:43
static bool provider_init(void)
Definition: jit.c:71
size_t created_functions
Definition: jit.h:30
#define MAXPGPATH
static JitProviderCallbacks provider
Definition: jit.c:46
#define INSTR_TIME_ADD(x, y)
Definition: instr_time.h:158
instr_time optimization_counter
Definition: jit.h:39
int es_jit_flags
Definition: execnodes.h:600
int errcode_for_file_access(void)
Definition: elog.c:593
static bool file_exists(const char *name)
Definition: jit.c:197
ResourceOwner resowner
Definition: jit.h:59
bool jit_expressions
Definition: jit.c:39
#define init()
PGFunction load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:107
#define ereport(elevel, rest)
Definition: elog.h:141
#define AssertArg(condition)
Definition: c.h:734
#define stat(a, b)
Definition: win32_port.h:264
JitProviderCompileExprCB compile_expr
Definition: jit.h:77
instr_time inlining_counter
Definition: jit.h:36
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
double jit_above_cost
Definition: jit.c:42
void(* JitProviderInit)(JitProviderCallbacks *cb)
Definition: jit.h:67
static bool provider_successfully_loaded
Definition: jit.c:47
void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
Definition: jit.c:187
bool jit_compile_expr(struct ExprState *state)
Definition: jit.c:156
bool jit_tuple_deforming
Definition: jit.c:41
double jit_inline_above_cost
Definition: jit.c:43
void ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle)
Definition: resowner.c:1343
Definition: regguts.h:298
instr_time emission_counter
Definition: jit.h:42
#define PGJIT_PERFORM
Definition: jit.h:20
bool jit_profiling_support
Definition: jit.c:40
double jit_optimize_above_cost
Definition: jit.c:44
bool jit_dump_bitcode
Definition: jit.c:38
const char * name
Definition: encode.c:521
#define S_ISDIR(m)
Definition: win32_port.h:305
void jit_release_context(JitContext *context)
Definition: jit.c:141
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
Datum pg_jit_available(PG_FUNCTION_ARGS)
Definition: jit.c:60
JitProviderReleaseContextCB release_context
Definition: jit.h:76
#define snprintf
Definition: port.h:192
char pkglib_path[MAXPGPATH]
Definition: globals.c:73