aboutsummaryrefslogtreecommitdiff
path: root/src/backend/jit/llvm/llvmjit_deform.c
diff options
context:
space:
mode:
authorDaniel Gustafsson <dgustafsson@postgresql.org>2023-11-17 10:20:51 +0100
committerDaniel Gustafsson <dgustafsson@postgresql.org>2023-11-17 10:21:34 +0100
commitaef521849b68d1eeb63c3dfbc4e92d66dc94a636 (patch)
tree9b3835cf639c57c00507a368f43c19503b509e5b /src/backend/jit/llvm/llvmjit_deform.c
parent9057ddbefe7e8a1aed8ea91fc0f98f31b8e693d7 (diff)
downloadpostgresql-aef521849b68d1eeb63c3dfbc4e92d66dc94a636.tar.gz
postgresql-aef521849b68d1eeb63c3dfbc4e92d66dc94a636.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/backend/jit/llvm/llvmjit_deform.c')
-rw-r--r--src/backend/jit/llvm/llvmjit_deform.c77
1 files changed, 40 insertions, 37 deletions
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 88a2eecd0de..489ef34ec4c 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -37,6 +37,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
char *funcname;
LLVMModuleRef mod;
+ LLVMContextRef lc;
LLVMBuilderRef b;
LLVMTypeRef deform_sig;
@@ -99,6 +100,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
return NULL;
mod = llvm_mutable_module(context);
+ lc = LLVMGetModuleContext(mod);
funcname = llvm_expand_funcname(context, "deform");
@@ -133,8 +135,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
param_types[0] = l_ptr(StructTupleTableSlot);
- deform_sig = LLVMFunctionType(LLVMVoidType(), param_types,
- lengthof(param_types), 0);
+ deform_sig = LLVMFunctionType(LLVMVoidTypeInContext(lc),
+ param_types, lengthof(param_types), 0);
}
v_deform_fn = LLVMAddFunction(mod, funcname, deform_sig);
LLVMSetLinkage(v_deform_fn, LLVMInternalLinkage);
@@ -142,17 +144,17 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
llvm_copy_attributes(AttributeTemplate, v_deform_fn);
b_entry =
- LLVMAppendBasicBlock(v_deform_fn, "entry");
+ LLVMAppendBasicBlockInContext(lc, v_deform_fn, "entry");
b_adjust_unavail_cols =
- LLVMAppendBasicBlock(v_deform_fn, "adjust_unavail_cols");
+ LLVMAppendBasicBlockInContext(lc, v_deform_fn, "adjust_unavail_cols");
b_find_start =
- LLVMAppendBasicBlock(v_deform_fn, "find_startblock");
+ LLVMAppendBasicBlockInContext(lc, v_deform_fn, "find_startblock");
b_out =
- LLVMAppendBasicBlock(v_deform_fn, "outblock");
+ LLVMAppendBasicBlockInContext(lc, v_deform_fn, "outblock");
b_dead =
- LLVMAppendBasicBlock(v_deform_fn, "deadblock");
+ LLVMAppendBasicBlockInContext(lc, v_deform_fn, "deadblock");
- b = LLVMCreateBuilder();
+ b = LLVMCreateBuilderInContext(lc);
attcheckattnoblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
attstartblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
@@ -232,7 +234,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
v_tuplep,
FIELDNO_HEAPTUPLEHEADERDATA_BITS,
""),
- l_ptr(LLVMInt8Type()),
+ l_ptr(LLVMInt8TypeInContext(lc)),
"t_bits");
v_infomask1 =
l_load_struct_gep(b,
@@ -250,14 +252,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
v_hasnulls =
LLVMBuildICmp(b, LLVMIntNE,
LLVMBuildAnd(b,
- l_int16_const(HEAP_HASNULL),
+ l_int16_const(lc, HEAP_HASNULL),
v_infomask1, ""),
- l_int16_const(0),
+ l_int16_const(lc, 0),
"hasnulls");
/* t_infomask2 & HEAP_NATTS_MASK */
v_maxatt = LLVMBuildAnd(b,
- l_int16_const(HEAP_NATTS_MASK),
+ l_int16_const(lc, HEAP_NATTS_MASK),
v_infomask2,
"maxatt");
@@ -272,13 +274,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
v_tuplep,
FIELDNO_HEAPTUPLEHEADERDATA_HOFF,
""),
- LLVMInt32Type(), "t_hoff");
+ LLVMInt32TypeInContext(lc), "t_hoff");
v_tupdata_base = l_gep(b,
- LLVMInt8Type(),
+ LLVMInt8TypeInContext(lc),
LLVMBuildBitCast(b,
v_tuplep,
- l_ptr(LLVMInt8Type()),
+ l_ptr(LLVMInt8TypeInContext(lc)),
""),
&v_hoff, 1,
"v_tupdata_base");
@@ -290,7 +292,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
{
LLVMValueRef v_off_start;
- v_off_start = l_load(b, LLVMInt32Type(), v_slotoffp, "v_slot_off");
+ v_off_start = l_load(b, LLVMInt32TypeInContext(lc), v_slotoffp, "v_slot_off");
v_off_start = LLVMBuildZExt(b, v_off_start, TypeSizeT, "");
LLVMBuildStore(b, v_off_start, v_offp);
}
@@ -336,7 +338,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntULT,
v_maxatt,
- l_int16_const(natts),
+ l_int16_const(lc, natts),
""),
b_adjust_unavail_cols,
b_find_start);
@@ -345,8 +347,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
LLVMPositionBuilderAtEnd(b, b_adjust_unavail_cols);
v_params[0] = v_slot;
- v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32Type(), "");
- v_params[2] = l_int32_const(natts);
+ v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32TypeInContext(lc), "");
+ v_params[2] = l_int32_const(lc, natts);
f = llvm_pg_func(mod, "slot_getmissingattrs");
l_call(b,
LLVMGetFunctionType(f), f,
@@ -356,7 +358,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
LLVMPositionBuilderAtEnd(b, b_find_start);
- v_nvalid = l_load(b, LLVMInt16Type(), v_nvalidp, "");
+ v_nvalid = l_load(b, LLVMInt16TypeInContext(lc), v_nvalidp, "");
/*
* Build switch to go from nvalid to the right startblock. Callers
@@ -371,7 +373,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
for (attnum = 0; attnum < natts; attnum++)
{
- LLVMValueRef v_attno = l_int16_const(attnum);
+ LLVMValueRef v_attno = l_int16_const(lc, attnum);
LLVMAddCase(v_switch, v_attno, attcheckattnoblocks[attnum]);
}
@@ -394,7 +396,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
Form_pg_attribute att = TupleDescAttr(desc, attnum);
LLVMValueRef v_incby;
int alignto;
- LLVMValueRef l_attno = l_int16_const(attnum);
+ LLVMValueRef l_attno = l_int16_const(lc, attnum);
LLVMValueRef v_attdatap;
LLVMValueRef v_resultp;
@@ -455,14 +457,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
else
b_next = attcheckattnoblocks[attnum + 1];
- v_nullbyteno = l_int32_const(attnum >> 3);
- v_nullbytemask = l_int8_const(1 << ((attnum) & 0x07));
- v_nullbyte = l_load_gep1(b, LLVMInt8Type(), v_bits, v_nullbyteno, "attnullbyte");
+ v_nullbyteno = l_int32_const(lc, attnum >> 3);
+ v_nullbytemask = l_int8_const(lc, 1 << ((attnum) & 0x07));
+ v_nullbyte = l_load_gep1(b, LLVMInt8TypeInContext(lc), v_bits, v_nullbyteno, "attnullbyte");
v_nullbit = LLVMBuildICmp(b,
LLVMIntEQ,
LLVMBuildAnd(b, v_nullbyte, v_nullbytemask, ""),
- l_int8_const(0),
+ l_int8_const(lc, 0),
"attisnull");
v_attisnull = LLVMBuildAnd(b, v_hasnulls, v_nullbit, "");
@@ -473,8 +475,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
/* store null-byte */
LLVMBuildStore(b,
- l_int8_const(1),
- l_gep(b, LLVMInt8Type(), v_tts_nulls, &l_attno, 1, ""));
+ l_int8_const(lc, 1),
+ l_gep(b, LLVMInt8TypeInContext(lc), v_tts_nulls, &l_attno, 1, ""));
/* store zero datum */
LLVMBuildStore(b,
l_sizet_const(0),
@@ -540,10 +542,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
v_off = l_load(b, TypeSizeT, v_offp, "");
v_possible_padbyte =
- l_load_gep1(b, LLVMInt8Type(), v_tupdata_base, v_off, "padbyte");
+ l_load_gep1(b, LLVMInt8TypeInContext(lc), v_tupdata_base,
+ v_off, "padbyte");
v_ispad =
LLVMBuildICmp(b, LLVMIntEQ,
- v_possible_padbyte, l_int8_const(0),
+ v_possible_padbyte, l_int8_const(lc, 0),
"ispadbyte");
LLVMBuildCondBr(b, v_ispad,
attalignblocks[attnum],
@@ -651,14 +654,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
v_attdatap =
- l_gep(b, LLVMInt8Type(), v_tupdata_base, &v_off, 1, "");
+ l_gep(b, LLVMInt8TypeInContext(lc), v_tupdata_base, &v_off, 1, "");
}
/* compute address to store value at */
v_resultp = l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, "");
/* store null-byte (false) */
- LLVMBuildStore(b, l_int8_const(0),
+ LLVMBuildStore(b, l_int8_const(lc, 0),
l_gep(b, TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
/*
@@ -668,7 +671,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
if (att->attbyval)
{
LLVMValueRef v_tmp_loaddata;
- LLVMTypeRef vartype = LLVMIntType(att->attlen * 8);
+ LLVMTypeRef vartype = LLVMIntTypeInContext(lc, att->attlen * 8);
LLVMTypeRef vartypep = LLVMPointerType(vartype, 0);
v_tmp_loaddata =
@@ -760,11 +763,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
LLVMValueRef v_flags;
- LLVMBuildStore(b, l_int16_const(natts), v_nvalidp);
- v_off = LLVMBuildTrunc(b, v_off, LLVMInt32Type(), "");
+ LLVMBuildStore(b, l_int16_const(lc, natts), v_nvalidp);
+ v_off = LLVMBuildTrunc(b, v_off, LLVMInt32TypeInContext(lc), "");
LLVMBuildStore(b, v_off, v_slotoffp);
- v_flags = l_load(b, LLVMInt16Type(), v_flagsp, "tts_flags");
- v_flags = LLVMBuildOr(b, v_flags, l_int16_const(TTS_FLAG_SLOW), "");
+ v_flags = l_load(b, LLVMInt16TypeInContext(lc), v_flagsp, "tts_flags");
+ v_flags = LLVMBuildOr(b, v_flags, l_int16_const(lc, TTS_FLAG_SLOW), "");
LLVMBuildStore(b, v_flags, v_flagsp);
LLVMBuildRetVoid(b);
}