aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorDaniel Gustafsson <dgustafsson@postgresql.org>2023-11-17 11:46:31 +0100
committerDaniel Gustafsson <dgustafsson@postgresql.org>2023-11-17 11:46:31 +0100
commit10912f7d4ff0e343e714a1703752c0d8c5b71306 (patch)
tree3e189ea981db2806a65ce685bc99b038d9be03a1 /src/include
parent2db84c25df199db605942bde5c17bc7134e79e2b (diff)
downloadpostgresql-10912f7d4ff0e343e714a1703752c0d8c5b71306.tar.gz
postgresql-10912f7d4ff0e343e714a1703752c0d8c5b71306.zip
llvmjit: Use explicit LLVMContextRef for inlining
When performing inlining LLVM unfortunately "leaks" types (the types survive and are usable, but a new round of inlining will recreate new structurally equivalent types). This accumulation will over time amount to a memory leak which for some queries can be large enough to trigger the OOM process killer. To avoid accumulation of types, all IR related data is stored in an LLVMContextRef which is dropped and recreated in order to release all types. Dropping and recreating incurs overhead, so it will be done only after 100 queries. This is a heuristic which might be revisited, but until we can get the size of the context from LLVM we are flying a bit blind. This issue has been reported several times, there may be more references to it in the archives on top of the threads linked below. This is a backpatch of 9dce22033d5 to all supported branches. Reported-By: Justin Pryzby <pryzby@telsasoft.com> Reported-By: Kurt Roeckx <kurt@roeckx.be> Reported-By: Jaime Casanova <jcasanov@systemguards.com.ec> Reported-By: Lauri Laanmets <pcspets@gmail.com> Author: Andres Freund and Daniel Gustafsson Discussion: https://postgr.es/m/7acc8678-df5f-4923-9cf6-e843131ae89d@www.fastmail.com Discussion: https://postgr.es/m/20201218235607.GC30237@telsasoft.com Discussion: https://postgr.es/m/CAPH-tTxLf44s3CvUUtQpkDr1D8Hxqc2NGDzGXS1ODsfiJ6WSqA@mail.gmail.com Backpatch-through: v12
Diffstat (limited to 'src/include')
-rw-r--r--src/include/jit/llvmjit.h8
-rw-r--r--src/include/jit/llvmjit_emit.h30
2 files changed, 26 insertions, 12 deletions
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index 7d3f8b358fc..ccdbd56801c 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -42,6 +42,13 @@ typedef struct LLVMJitContext
/* number of modules created */
size_t module_generation;
+ /*
+ * The LLVM Context used by this JIT context. An LLVM context is reused
+ * across many compilations, but occasionally reset to prevent it using
+ * too much memory due to more and more types accumulating.
+ */
+ LLVMContextRef llvm_context;
+
/* current, "open for write", module */
LLVMModuleRef module;
@@ -105,6 +112,7 @@ extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
LLVMModuleRef mod,
FunctionCallInfo fcinfo);
+extern void llvm_inline_reset_caches(void);
extern void llvm_inline(LLVMModuleRef mod);
/*
diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h
index e5e4d63decf..84133ed21f4 100644
--- a/src/include/jit/llvmjit_emit.h
+++ b/src/include/jit/llvmjit_emit.h
@@ -45,36 +45,36 @@ l_ptr(LLVMTypeRef t)
* Emit constant integer.
*/
static inline LLVMValueRef
-l_int8_const(int8 i)
+l_int8_const(LLVMContextRef lc, int8 i)
{
- return LLVMConstInt(LLVMInt8Type(), i, false);
+ return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
}
/*
* Emit constant integer.
*/
static inline LLVMValueRef
-l_int16_const(int16 i)
+l_int16_const(LLVMContextRef lc, int16 i)
{
- return LLVMConstInt(LLVMInt16Type(), i, false);
+ return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
}
/*
* Emit constant integer.
*/
static inline LLVMValueRef
-l_int32_const(int32 i)
+l_int32_const(LLVMContextRef lc, int32 i)
{
- return LLVMConstInt(LLVMInt32Type(), i, false);
+ return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
}
/*
* Emit constant integer.
*/
static inline LLVMValueRef
-l_int64_const(int64 i)
+l_int64_const(LLVMContextRef lc, int64 i)
{
- return LLVMConstInt(LLVMInt64Type(), i, false);
+ return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
}
/*
@@ -177,12 +177,15 @@ l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
{
char buf[512];
va_list args;
+ LLVMContextRef lc;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- return LLVMInsertBasicBlock(r, buf);
+ lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
+
+ return LLVMInsertBasicBlockInContext(lc, r, buf);
}
/* separate, because pg_attribute_printf(2, 3) can't appear in definition */
@@ -197,12 +200,15 @@ l_bb_append_v(LLVMValueRef f, const char *fmt,...)
{
char buf[512];
va_list args;
+ LLVMContextRef lc;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- return LLVMAppendBasicBlock(f, buf);
+ lc = LLVMGetTypeContext(LLVMTypeOf(f));
+
+ return LLVMAppendBasicBlockInContext(lc, f, buf);
}
/*
@@ -214,7 +220,7 @@ l_callsite_ro(LLVMValueRef f)
const char argname[] = "readonly";
LLVMAttributeRef ref;
- ref = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
+ ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
argname,
sizeof(argname) - 1,
NULL, 0);
@@ -234,7 +240,7 @@ l_callsite_alwaysinline(LLVMValueRef f)
id = LLVMGetEnumAttributeKindForName(argname,
sizeof(argname) - 1);
- attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), id, 0);
+ attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
}