Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8dd7c7c

Browse files
Replace EEOP_DONE with special steps for return/no return
Knowing when the side-effects of an expression is the intended resultof the execution, rather than the returnvalue, is important for beingable generate more efficient JITed code. This replaces EEOP_DONE withtwo new steps: EEOP_DONE_RETURN and EEOP_DONE_NO_RETURN. Expressionswhich return a value should use the former step; expressions used fortheir side-effects which don't return value should use the latter.Author: Andres Freund <andres@anarazel.de>Co-authored-by: Daniel Gustafsson <daniel@yesql.se>Reviewed-by: Andreas Karlsson <andreas@proxel.se>Discussion:https://postgr.es/m/415721CE-7D2E-4B74-B5D9-1950083BA03E@yesql.seDiscussion:https://postgr.es/m/20191023163849.sosqbfs5yenocez3@alap3.anarazel.de
1 parentdabccf4 commit8dd7c7c

File tree

7 files changed

+98
-34
lines changed

7 files changed

+98
-34
lines changed

‎src/backend/executor/README

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,14 @@ is used by the function evaluation step, thus avoiding extra work to copy
133133
the result values around.
134134

135135
The last entry in a completed ExprState->steps array is always an
136-
EEOP_DONE step; this removes the need to test for end-of-array while
137-
iterating. Also, if the expression contains any variable references (to
138-
user columns of the ExprContext's INNER, OUTER, or SCAN tuples), the steps
136+
EEOP_DONE_RETURN or EEOP_DONE_NO_RETURN step; this removes the need to
137+
test for end-of-array while iterating. The former is used when the
138+
expression returns a value directly, the latter when side-effects of
139+
expression initialization are the goal (e.g. for projection or
140+
aggregate transition value computation).
141+
142+
Also, if the expression contains any variable references (to user
143+
columns of the ExprContext's INNER, OUTER, or SCAN tuples), the steps
139144
array begins with EEOP_*_FETCHSOME steps that ensure that the relevant
140145
tuples have been deconstructed to make the required columns directly
141146
available (cf. slot_getsomeattrs()). This allows individual Var-fetching

‎src/backend/executor/execExpr.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*using ExecInitExpr() et al. This converts the tree into a flat array
99
*of ExprEvalSteps, which may be thought of as instructions in a program.
1010
*At runtime, we'll execute steps, starting with the first, until we reach
11-
*anEEOP_DONE opcode.
11+
*anEEOP_DONE_{RETURN|NO_RETURN} opcode.
1212
*
1313
*This file contains the "compilation" logic. It is independent of the
1414
*specific execution technology we use (switch statement, computed goto,
@@ -162,7 +162,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
162162
ExecInitExprRec(node,state,&state->resvalue,&state->resnull);
163163

164164
/* Finally, append a DONE step */
165-
scratch.opcode=EEOP_DONE;
165+
scratch.opcode=EEOP_DONE_RETURN;
166166
ExprEvalPushStep(state,&scratch);
167167

168168
ExecReadyExpr(state);
@@ -199,7 +199,7 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
199199
ExecInitExprRec(node,state,&state->resvalue,&state->resnull);
200200

201201
/* Finally, append a DONE step */
202-
scratch.opcode=EEOP_DONE;
202+
scratch.opcode=EEOP_DONE_RETURN;
203203
ExprEvalPushStep(state,&scratch);
204204

205205
ExecReadyExpr(state);
@@ -291,7 +291,7 @@ ExecInitQual(List *qual, PlanState *parent)
291291
* have yielded TRUE, and since its result is stored in the desired output
292292
* location, we're done.
293293
*/
294-
scratch.opcode=EEOP_DONE;
294+
scratch.opcode=EEOP_DONE_RETURN;
295295
ExprEvalPushStep(state,&scratch);
296296

297297
ExecReadyExpr(state);
@@ -503,7 +503,7 @@ ExecBuildProjectionInfo(List *targetList,
503503
}
504504
}
505505

506-
scratch.opcode=EEOP_DONE;
506+
scratch.opcode=EEOP_DONE_NO_RETURN;
507507
ExprEvalPushStep(state,&scratch);
508508

509509
ExecReadyExpr(state);
@@ -742,7 +742,7 @@ ExecBuildUpdateProjection(List *targetList,
742742
}
743743
}
744744

745-
scratch.opcode=EEOP_DONE;
745+
scratch.opcode=EEOP_DONE_NO_RETURN;
746746
ExprEvalPushStep(state,&scratch);
747747

748748
ExecReadyExpr(state);
@@ -1714,7 +1714,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
17141714
else
17151715
{
17161716
/* Not trivial, so append a DONE step */
1717-
scratch.opcode=EEOP_DONE;
1717+
scratch.opcode=EEOP_DONE_RETURN;
17181718
ExprEvalPushStep(elemstate,&scratch);
17191719
/* and ready the subexpression */
17201720
ExecReadyExpr(elemstate);
@@ -3991,7 +3991,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
39913991

39923992
scratch.resvalue=NULL;
39933993
scratch.resnull=NULL;
3994-
scratch.opcode=EEOP_DONE;
3994+
scratch.opcode=EEOP_DONE_NO_RETURN;
39953995
ExprEvalPushStep(state,&scratch);
39963996

39973997
ExecReadyExpr(state);
@@ -4258,7 +4258,7 @@ ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops,
42584258

42594259
scratch.resvalue=NULL;
42604260
scratch.resnull=NULL;
4261-
scratch.opcode=EEOP_DONE;
4261+
scratch.opcode=EEOP_DONE_RETURN;
42624262
ExprEvalPushStep(state,&scratch);
42634263

42644264
ExecReadyExpr(state);
@@ -4431,7 +4431,7 @@ ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops,
44314431

44324432
scratch.resvalue=NULL;
44334433
scratch.resnull=NULL;
4434-
scratch.opcode=EEOP_DONE;
4434+
scratch.opcode=EEOP_DONE_RETURN;
44354435
ExprEvalPushStep(state,&scratch);
44364436

44374437
ExecReadyExpr(state);
@@ -4586,7 +4586,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
45864586

45874587
scratch.resvalue=NULL;
45884588
scratch.resnull=NULL;
4589-
scratch.opcode=EEOP_DONE;
4589+
scratch.opcode=EEOP_DONE_RETURN;
45904590
ExprEvalPushStep(state,&scratch);
45914591

45924592
ExecReadyExpr(state);
@@ -4722,7 +4722,7 @@ ExecBuildParamSetEqual(TupleDesc desc,
47224722

47234723
scratch.resvalue=NULL;
47244724
scratch.resnull=NULL;
4725-
scratch.opcode=EEOP_DONE;
4725+
scratch.opcode=EEOP_DONE_RETURN;
47264726
ExprEvalPushStep(state,&scratch);
47274727

47284728
ExecReadyExpr(state);

‎src/backend/executor/execExprInterp.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ ExecReadyInterpretedExpr(ExprState *state)
246246

247247
/* Simple validity checks on expression */
248248
Assert(state->steps_len >=1);
249-
Assert(state->steps[state->steps_len-1].opcode==EEOP_DONE);
249+
Assert(state->steps[state->steps_len-1].opcode==EEOP_DONE_RETURN||
250+
state->steps[state->steps_len-1].opcode==EEOP_DONE_NO_RETURN);
250251

251252
/*
252253
* Don't perform redundant initialization. This is unreachable in current
@@ -469,7 +470,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
469470
*/
470471
#if defined(EEO_USE_COMPUTED_GOTO)
471472
staticconstvoid*constdispatch_table[]= {
472-
&&CASE_EEOP_DONE,
473+
&&CASE_EEOP_DONE_RETURN,
474+
&&CASE_EEOP_DONE_NO_RETURN,
473475
&&CASE_EEOP_INNER_FETCHSOME,
474476
&&CASE_EEOP_OUTER_FETCHSOME,
475477
&&CASE_EEOP_SCAN_FETCHSOME,
@@ -612,9 +614,16 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
612614

613615
EEO_SWITCH()
614616
{
615-
EEO_CASE(EEOP_DONE)
617+
EEO_CASE(EEOP_DONE_RETURN)
616618
{
617-
gotoout;
619+
*isnull=state->resnull;
620+
returnstate->resvalue;
621+
}
622+
623+
EEO_CASE(EEOP_DONE_NO_RETURN)
624+
{
625+
Assert(isnull==NULL);
626+
return (Datum)0;
618627
}
619628

620629
EEO_CASE(EEOP_INNER_FETCHSOME)
@@ -2188,13 +2197,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
21882197
{
21892198
/* unreachable */
21902199
Assert(false);
2191-
gotoout;
2200+
gotoout_error;
21922201
}
21932202
}
21942203

2195-
out:
2196-
*isnull=state->resnull;
2197-
returnstate->resvalue;
2204+
out_error:
2205+
pg_unreachable();
2206+
return(Datum)0;
21982207
}
21992208

22002209
/*

‎src/backend/executor/nodeAgg.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -816,11 +816,8 @@ advance_transition_function(AggState *aggstate,
816816
staticvoid
817817
advance_aggregates(AggState*aggstate)
818818
{
819-
booldummynull;
820-
821-
ExecEvalExprSwitchContext(aggstate->phase->evaltrans,
822-
aggstate->tmpcontext,
823-
&dummynull);
819+
ExecEvalExprNoReturnSwitchContext(aggstate->phase->evaltrans,
820+
aggstate->tmpcontext);
824821
}
825822

826823
/*

‎src/backend/jit/llvm/llvmjit_expr.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ llvm_compile_expr(ExprState *state)
321321

322322
switch (opcode)
323323
{
324-
caseEEOP_DONE:
324+
caseEEOP_DONE_RETURN:
325325
{
326326
LLVMValueRefv_tmpisnull;
327327
LLVMValueRefv_tmpvalue;
@@ -335,6 +335,10 @@ llvm_compile_expr(ExprState *state)
335335
break;
336336
}
337337

338+
caseEEOP_DONE_NO_RETURN:
339+
LLVMBuildRet(b,l_sizet_const(0));
340+
break;
341+
338342
caseEEOP_INNER_FETCHSOME:
339343
caseEEOP_OUTER_FETCHSOME:
340344
caseEEOP_SCAN_FETCHSOME:

‎src/include/executor/execExpr.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,11 @@ typedef struct ExprEvalRowtypeCache
6565
*/
6666
typedefenumExprEvalOp
6767
{
68-
/* entire expression has been evaluated completely, return */
69-
EEOP_DONE,
68+
/* entire expression has been evaluated, return value */
69+
EEOP_DONE_RETURN,
70+
71+
/* entire expression has been evaluated, no return value */
72+
EEOP_DONE_NO_RETURN,
7073

7174
/* apply slot_getsomeattrs on corresponding tuple slot */
7275
EEOP_INNER_FETCHSOME,

‎src/include/executor/executor.h

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,34 @@ ExecEvalExpr(ExprState *state,
379379
}
380380
#endif
381381

382+
/*
383+
* ExecEvalExprNoReturn
384+
*
385+
* Like ExecEvalExpr(), but for cases where no return value is expected,
386+
* because the side-effects of expression evaluation are what's desired. This
387+
* is e.g. used for projection and aggregate transition computation.
388+
389+
* Evaluate expression identified by "state" in the execution context
390+
* given by "econtext".
391+
*
392+
* The caller should already have switched into the temporary memory context
393+
* econtext->ecxt_per_tuple_memory. The convenience entry point
394+
* ExecEvalExprNoReturnSwitchContext() is provided for callers who don't
395+
* prefer to do the switch in an outer loop.
396+
*/
397+
#ifndefFRONTEND
398+
staticinlinevoid
399+
ExecEvalExprNoReturn(ExprState*state,
400+
ExprContext*econtext)
401+
{
402+
PG_USED_FOR_ASSERTS_ONLYDatumretDatum;
403+
404+
retDatum=state->evalfunc(state,econtext,NULL);
405+
406+
Assert(retDatum== (Datum)0);
407+
}
408+
#endif
409+
382410
/*
383411
* ExecEvalExprSwitchContext
384412
*
@@ -400,6 +428,25 @@ ExecEvalExprSwitchContext(ExprState *state,
400428
}
401429
#endif
402430

431+
/*
432+
* ExecEvalExprNoReturnSwitchContext
433+
*
434+
* Same as ExecEvalExprNoReturn, but get into the right allocation context
435+
* explicitly.
436+
*/
437+
#ifndefFRONTEND
438+
staticinlinevoid
439+
ExecEvalExprNoReturnSwitchContext(ExprState*state,
440+
ExprContext*econtext)
441+
{
442+
MemoryContextoldContext;
443+
444+
oldContext=MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
445+
ExecEvalExprNoReturn(state,econtext);
446+
MemoryContextSwitchTo(oldContext);
447+
}
448+
#endif
449+
403450
/*
404451
* ExecProject
405452
*
@@ -419,16 +466,15 @@ ExecProject(ProjectionInfo *projInfo)
419466
ExprContext*econtext=projInfo->pi_exprContext;
420467
ExprState*state=&projInfo->pi_state;
421468
TupleTableSlot*slot=state->resultslot;
422-
boolisnull;
423469

424470
/*
425471
* Clear any former contents of the result slot. This makes it safe for
426472
* us to use the slot's Datum/isnull arrays as workspace.
427473
*/
428474
ExecClearTuple(slot);
429475

430-
/* Run the expression, discarding scalar result from the last column. */
431-
(void)ExecEvalExprSwitchContext(state,econtext,&isnull);
476+
/* Run the expression */
477+
ExecEvalExprNoReturnSwitchContext(state,econtext);
432478

433479
/*
434480
* Successfully formed a result row. Mark the result slot as containing a

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp