Commit b84a6daf authored by Andres Freund's avatar Andres Freund

Move EEOP_*_SYSVAR evaluation out of line.

This mainly de-duplicates code. As evaluating a system variable isn't
the hottest path and the current inline implementation ends up calling
out to an external function anyway, this is OK from a performance POV.

The main motivation for de-duplicating is the upcoming slot
abstraction work, after which there's not guaranteed to be a HeapTuple
backing the slot.

Author: Andres Freund, Amit Khandekar
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
parent 517b0d0b
...@@ -490,55 +490,19 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) ...@@ -490,55 +490,19 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_INNER_SYSVAR) EEO_CASE(EEOP_INNER_SYSVAR)
{ {
int attnum = op->d.var.attnum; ExecEvalSysVar(state, op, econtext, innerslot);
Datum d;
/* these asserts must match defenses in slot_getattr */
Assert(innerslot->tts_tuple != NULL);
Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
/* heap_getsysattr has sufficient defenses against bad attnums */
d = heap_getsysattr(innerslot->tts_tuple, attnum,
innerslot->tts_tupleDescriptor,
op->resnull);
*op->resvalue = d;
EEO_NEXT(); EEO_NEXT();
} }
EEO_CASE(EEOP_OUTER_SYSVAR) EEO_CASE(EEOP_OUTER_SYSVAR)
{ {
int attnum = op->d.var.attnum; ExecEvalSysVar(state, op, econtext, outerslot);
Datum d;
/* these asserts must match defenses in slot_getattr */
Assert(outerslot->tts_tuple != NULL);
Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
/* heap_getsysattr has sufficient defenses against bad attnums */
d = heap_getsysattr(outerslot->tts_tuple, attnum,
outerslot->tts_tupleDescriptor,
op->resnull);
*op->resvalue = d;
EEO_NEXT(); EEO_NEXT();
} }
EEO_CASE(EEOP_SCAN_SYSVAR) EEO_CASE(EEOP_SCAN_SYSVAR)
{ {
int attnum = op->d.var.attnum; ExecEvalSysVar(state, op, econtext, scanslot);
Datum d;
/* these asserts must match defenses in slot_getattr */
Assert(scanslot->tts_tuple != NULL);
Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
/* heap_getsysattr has sufficient defenses against bad attnums */
d = heap_getsysattr(scanslot->tts_tuple, attnum,
scanslot->tts_tupleDescriptor,
op->resnull);
*op->resvalue = d;
EEO_NEXT(); EEO_NEXT();
} }
...@@ -4006,6 +3970,22 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) ...@@ -4006,6 +3970,22 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
*op->resnull = false; *op->resnull = false;
} }
void
ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
TupleTableSlot *slot)
{
bool success;
/* slot_getsysattr has sufficient defenses against bad attnums */
success = slot_getsysattr(slot,
op->d.var.attnum,
op->resvalue,
op->resnull);
/* this ought to be unreachable, but it's cheap enough to check */
if (unlikely(!success))
elog(ERROR, "failed to fetch attribute from slot");
}
/* /*
* Transition value has not been initialized. This is the first non-NULL input * Transition value has not been initialized. This is the first non-NULL input
* value for a group. We use it as the initial value for transValue. * value for a group. We use it as the initial value for transValue.
......
...@@ -81,9 +81,9 @@ LLVMValueRef FuncStrlen; ...@@ -81,9 +81,9 @@ LLVMValueRef FuncStrlen;
LLVMValueRef FuncVarsizeAny; LLVMValueRef FuncVarsizeAny;
LLVMValueRef FuncSlotGetsomeattrs; LLVMValueRef FuncSlotGetsomeattrs;
LLVMValueRef FuncSlotGetmissingattrs; LLVMValueRef FuncSlotGetmissingattrs;
LLVMValueRef FuncHeapGetsysattr;
LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
LLVMValueRef FuncExecEvalArrayRefSubscript; LLVMValueRef FuncExecEvalArrayRefSubscript;
LLVMValueRef FuncExecEvalSysVar;
LLVMValueRef FuncExecAggTransReparent; LLVMValueRef FuncExecAggTransReparent;
LLVMValueRef FuncExecAggInitGroup; LLVMValueRef FuncExecAggInitGroup;
...@@ -822,9 +822,9 @@ llvm_create_types(void) ...@@ -822,9 +822,9 @@ llvm_create_types(void)
FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any"); FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any");
FuncSlotGetsomeattrs = LLVMGetNamedFunction(mod, "slot_getsomeattrs"); FuncSlotGetsomeattrs = LLVMGetNamedFunction(mod, "slot_getsomeattrs");
FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs"); FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs");
FuncHeapGetsysattr = LLVMGetNamedFunction(mod, "heap_getsysattr");
FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal"); FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal");
FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript"); FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript");
FuncExecEvalSysVar = LLVMGetNamedFunction(mod, "ExecEvalSysVar");
FuncExecAggTransReparent = LLVMGetNamedFunction(mod, "ExecAggTransReparent"); FuncExecAggTransReparent = LLVMGetNamedFunction(mod, "ExecAggTransReparent");
FuncExecAggInitGroup = LLVMGetNamedFunction(mod, "ExecAggInitGroup"); FuncExecAggInitGroup = LLVMGetNamedFunction(mod, "ExecAggInitGroup");
......
...@@ -406,13 +406,8 @@ llvm_compile_expr(ExprState *state) ...@@ -406,13 +406,8 @@ llvm_compile_expr(ExprState *state)
case EEOP_OUTER_SYSVAR: case EEOP_OUTER_SYSVAR:
case EEOP_SCAN_SYSVAR: case EEOP_SCAN_SYSVAR:
{ {
int attnum = op->d.var.attnum;
LLVMValueRef v_attnum;
LLVMValueRef v_tuple;
LLVMValueRef v_tupleDescriptor;
LLVMValueRef v_params[4];
LLVMValueRef v_syscol;
LLVMValueRef v_slot; LLVMValueRef v_slot;
LLVMValueRef v_params[4];
if (opcode == EEOP_INNER_SYSVAR) if (opcode == EEOP_INNER_SYSVAR)
v_slot = v_innerslot; v_slot = v_innerslot;
...@@ -421,31 +416,14 @@ llvm_compile_expr(ExprState *state) ...@@ -421,31 +416,14 @@ llvm_compile_expr(ExprState *state)
else else
v_slot = v_scanslot; v_slot = v_scanslot;
Assert(op->d.var.attnum < 0); v_params[0] = v_state;
v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
v_tuple = l_load_struct_gep(b, v_slot, v_params[2] = v_econtext;
FIELDNO_TUPLETABLESLOT_TUPLE, v_params[3] = v_slot;
"v.tuple");
/* LLVMBuildCall(b,
* Could optimize this a bit for fixed descriptors, but FuncExecEvalSysVar,
* this shouldn't be that critical a path. v_params, lengthof(v_params), "");
*/
v_tupleDescriptor =
l_load_struct_gep(b, v_slot,
FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR,
"v.tupledesc");
v_attnum = l_int32_const(attnum);
v_params[0] = v_tuple;
v_params[1] = v_attnum;
v_params[2] = v_tupleDescriptor;
v_params[3] = v_resnullp;
v_syscol = LLVMBuildCall(b,
llvm_get_decl(mod, FuncHeapGetsysattr),
v_params, lengthof(v_params),
"");
LLVMBuildStore(b, v_syscol, v_resvaluep);
LLVMBuildBr(b, opblocks[i + 1]); LLVMBuildBr(b, opblocks[i + 1]);
break; break;
......
...@@ -99,9 +99,9 @@ void *referenced_functions[] = ...@@ -99,9 +99,9 @@ void *referenced_functions[] =
varsize_any, varsize_any,
slot_getsomeattrs, slot_getsomeattrs,
slot_getmissingattrs, slot_getmissingattrs,
heap_getsysattr,
MakeExpandedObjectReadOnlyInternal, MakeExpandedObjectReadOnlyInternal,
ExecEvalArrayRefSubscript, ExecEvalArrayRefSubscript,
ExecEvalSysVar,
ExecAggTransReparent, ExecAggTransReparent,
ExecAggInitGroup ExecAggInitGroup
}; };
...@@ -734,6 +734,8 @@ extern void ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op, ...@@ -734,6 +734,8 @@ extern void ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op,
ExprContext *econtext); ExprContext *econtext);
extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
ExprContext *econtext); ExprContext *econtext);
extern void ExecEvalSysVar(ExprState *state, ExprEvalStep *op,
ExprContext *econtext, TupleTableSlot *slot);
extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup); extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup);
extern Datum ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans, extern Datum ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
......
...@@ -79,9 +79,9 @@ extern LLVMValueRef FuncStrlen; ...@@ -79,9 +79,9 @@ extern LLVMValueRef FuncStrlen;
extern LLVMValueRef FuncVarsizeAny; extern LLVMValueRef FuncVarsizeAny;
extern LLVMValueRef FuncSlotGetsomeattrs; extern LLVMValueRef FuncSlotGetsomeattrs;
extern LLVMValueRef FuncSlotGetmissingattrs; extern LLVMValueRef FuncSlotGetmissingattrs;
extern LLVMValueRef FuncHeapGetsysattr;
extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
extern LLVMValueRef FuncExecEvalArrayRefSubscript; extern LLVMValueRef FuncExecEvalArrayRefSubscript;
extern LLVMValueRef FuncExecEvalSysVar;
extern LLVMValueRef FuncExecAggTransReparent; extern LLVMValueRef FuncExecAggTransReparent;
extern LLVMValueRef FuncExecAggInitGroup; extern LLVMValueRef FuncExecAggInitGroup;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment