Skip to content

Commit 675af5c

Browse files
committed
Compute information about EEOP_*_FETCHSOME at expression init time.
Previously this information was computed when JIT compiling an expression. But the information is useful for assertions in the non-JIT case too (for assertions), therefore it makes sense to move it. This will, in a followup commit, allow to treat different slot types differently. E.g. for virtual slots there's no need to generate a JIT function to deform the slot. Author: Andres Freund Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
1 parent 1a0586d commit 675af5c

File tree

3 files changed

+124
-29
lines changed

3 files changed

+124
-29
lines changed

src/backend/executor/execExpr.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
6565
static void ExecInitExprSlots(ExprState *state, Node *node);
6666
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info);
6767
static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
68+
static void ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op);
6869
static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
6970
ExprState *state);
7071
static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
@@ -2288,21 +2289,30 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
22882289
{
22892290
scratch.opcode = EEOP_INNER_FETCHSOME;
22902291
scratch.d.fetch.last_var = info->last_inner;
2292+
scratch.d.fetch.fixed = false;
2293+
scratch.d.fetch.kind = NULL;
22912294
scratch.d.fetch.known_desc = NULL;
2295+
ExecComputeSlotInfo(state, &scratch);
22922296
ExprEvalPushStep(state, &scratch);
22932297
}
22942298
if (info->last_outer > 0)
22952299
{
22962300
scratch.opcode = EEOP_OUTER_FETCHSOME;
22972301
scratch.d.fetch.last_var = info->last_outer;
2302+
scratch.d.fetch.fixed = false;
2303+
scratch.d.fetch.kind = NULL;
22982304
scratch.d.fetch.known_desc = NULL;
2305+
ExecComputeSlotInfo(state, &scratch);
22992306
ExprEvalPushStep(state, &scratch);
23002307
}
23012308
if (info->last_scan > 0)
23022309
{
23032310
scratch.opcode = EEOP_SCAN_FETCHSOME;
23042311
scratch.d.fetch.last_var = info->last_scan;
2312+
scratch.d.fetch.fixed = false;
2313+
scratch.d.fetch.kind = NULL;
23052314
scratch.d.fetch.known_desc = NULL;
2315+
ExecComputeSlotInfo(state, &scratch);
23062316
ExprEvalPushStep(state, &scratch);
23072317
}
23082318
}
@@ -2355,6 +2365,94 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
23552365
(void *) info);
23562366
}
23572367

2368+
/*
2369+
* Compute additional information for EEOP_*_FETCHSOME ops.
2370+
*
2371+
* The goal is to determine whether a slot is 'fixed', that is, every
2372+
* evaluation of the the expression will have the same type of slot, with an
2373+
* equivalent descriptor.
2374+
*/
2375+
static void
2376+
ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
2377+
{
2378+
PlanState *parent = state->parent;
2379+
TupleDesc desc = NULL;
2380+
const TupleTableSlotOps *tts_ops = NULL;
2381+
bool isfixed = false;
2382+
2383+
if (op->d.fetch.known_desc != NULL)
2384+
{
2385+
desc = op->d.fetch.known_desc;
2386+
tts_ops = op->d.fetch.kind;
2387+
isfixed = op->d.fetch.kind != NULL;
2388+
}
2389+
else if (!parent)
2390+
{
2391+
isfixed = false;
2392+
}
2393+
else if (op->opcode == EEOP_INNER_FETCHSOME)
2394+
{
2395+
PlanState *is = innerPlanState(parent);
2396+
2397+
if (parent->inneropsset && !parent->inneropsfixed)
2398+
{
2399+
isfixed = false;
2400+
}
2401+
else if (parent->inneropsset && parent->innerops)
2402+
{
2403+
isfixed = true;
2404+
tts_ops = parent->innerops;
2405+
}
2406+
else if (is)
2407+
{
2408+
tts_ops = ExecGetResultSlotOps(is, &isfixed);
2409+
desc = ExecGetResultType(is);
2410+
}
2411+
}
2412+
else if (op->opcode == EEOP_OUTER_FETCHSOME)
2413+
{
2414+
PlanState *os = outerPlanState(parent);
2415+
2416+
if (parent->outeropsset && !parent->outeropsfixed)
2417+
{
2418+
isfixed = false;
2419+
}
2420+
else if (parent->outeropsset && parent->outerops)
2421+
{
2422+
isfixed = true;
2423+
tts_ops = parent->outerops;
2424+
}
2425+
else if (os)
2426+
{
2427+
tts_ops = ExecGetResultSlotOps(os, &isfixed);
2428+
desc = ExecGetResultType(os);
2429+
}
2430+
}
2431+
else if (op->opcode == EEOP_SCAN_FETCHSOME)
2432+
{
2433+
desc = parent->scandesc;
2434+
2435+
if (parent && parent->scanops)
2436+
tts_ops = parent->scanops;
2437+
2438+
if (parent->scanopsset)
2439+
isfixed = parent->scanopsfixed;
2440+
}
2441+
2442+
if (isfixed && desc != NULL && tts_ops != NULL)
2443+
{
2444+
op->d.fetch.fixed = true;
2445+
op->d.fetch.kind = tts_ops;
2446+
op->d.fetch.known_desc = desc;
2447+
}
2448+
else
2449+
{
2450+
op->d.fetch.fixed = false;
2451+
op->d.fetch.kind = NULL;
2452+
op->d.fetch.known_desc = NULL;
2453+
}
2454+
}
2455+
23582456
/*
23592457
* Prepare step for the evaluation of a whole-row variable.
23602458
* The caller still has to push the step.
@@ -3255,12 +3353,18 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
32553353
/* push deform steps */
32563354
scratch.opcode = EEOP_INNER_FETCHSOME;
32573355
scratch.d.fetch.last_var = maxatt;
3356+
scratch.d.fetch.fixed = false;
32583357
scratch.d.fetch.known_desc = ldesc;
3358+
scratch.d.fetch.kind = lops;
3359+
ExecComputeSlotInfo(state, &scratch);
32593360
ExprEvalPushStep(state, &scratch);
32603361

32613362
scratch.opcode = EEOP_OUTER_FETCHSOME;
32623363
scratch.d.fetch.last_var = maxatt;
3364+
scratch.d.fetch.fixed = false;
32633365
scratch.d.fetch.known_desc = rdesc;
3366+
scratch.d.fetch.kind = rops;
3367+
ExecComputeSlotInfo(state, &scratch);
32643368
ExprEvalPushStep(state, &scratch);
32653369

32663370
/*

src/backend/jit/llvm/llvmjit_expr.c

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -276,47 +276,31 @@ llvm_compile_expr(ExprState *state)
276276
LLVMValueRef v_slot;
277277
LLVMBasicBlockRef b_fetch;
278278
LLVMValueRef v_nvalid;
279+
LLVMValueRef l_jit_deform = NULL;
280+
const TupleTableSlotOps *tts_ops = NULL;
279281

280282
b_fetch = l_bb_before_v(opblocks[i + 1],
281283
"op.%d.fetch", i);
282284

283285
if (op->d.fetch.known_desc)
284286
desc = op->d.fetch.known_desc;
285287

286-
if (opcode == EEOP_INNER_FETCHSOME)
287-
{
288-
PlanState *is = innerPlanState(parent);
288+
if (op->d.fetch.fixed)
289+
tts_ops = op->d.fetch.kind;
289290

291+
if (opcode == EEOP_INNER_FETCHSOME)
290292
v_slot = v_innerslot;
291-
292-
if (!desc &&
293-
is &&
294-
is->ps_ResultTupleSlot &&
295-
TTS_FIXED(is->ps_ResultTupleSlot))
296-
desc = is->ps_ResultTupleSlot->tts_tupleDescriptor;
297-
}
298293
else if (opcode == EEOP_OUTER_FETCHSOME)
299-
{
300-
PlanState *os = outerPlanState(parent);
301-
302294
v_slot = v_outerslot;
303-
304-
if (!desc &&
305-
os &&
306-
os->ps_ResultTupleSlot &&
307-
TTS_FIXED(os->ps_ResultTupleSlot))
308-
desc = os->ps_ResultTupleSlot->tts_tupleDescriptor;
309-
}
310295
else
311-
{
312296
v_slot = v_scanslot;
313-
if (!desc && parent)
314-
desc = parent->scandesc;
315-
}
316297

317298
/*
318299
* Check if all required attributes are available, or
319300
* whether deforming is required.
301+
*
302+
* TODO: skip nvalid check if slot is fixed and known to
303+
* be a virtual slot.
320304
*/
321305
v_nvalid =
322306
l_load_struct_gep(b, v_slot,
@@ -336,19 +320,21 @@ llvm_compile_expr(ExprState *state)
336320
* function specific to tupledesc and the exact number of
337321
* to-be-extracted attributes.
338322
*/
339-
if (desc && (context->base.flags & PGJIT_DEFORM))
323+
if (tts_ops && desc && (context->base.flags & PGJIT_DEFORM))
340324
{
341-
LLVMValueRef params[1];
342-
LLVMValueRef l_jit_deform;
343-
344325
l_jit_deform =
345326
slot_compile_deform(context, desc,
346327
op->d.fetch.last_var);
328+
}
329+
330+
if (l_jit_deform)
331+
{
332+
LLVMValueRef params[1];
333+
347334
params[0] = v_slot;
348335

349336
LLVMBuildCall(b, l_jit_deform,
350337
params, lengthof(params), "");
351-
352338
}
353339
else
354340
{

src/include/executor/execExpr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,12 @@ typedef struct ExprEvalStep
262262
{
263263
/* attribute number up to which to fetch (inclusive) */
264264
int last_var;
265+
/* will the type of slot be the same for every invocation */
266+
bool fixed;
267+
/* tuple descriptor, if known */
265268
TupleDesc known_desc;
269+
/* type of slot, can only be relied upon if fixed is set */
270+
const TupleTableSlotOps *kind;
266271
} fetch;
267272

268273
/* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy