faster-eval-comments.patch
application/x-download
Filename: faster-eval-comments.patch
Type: application/x-download
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/execExpr.c | 7 | 7 |
| src/backend/executor/execInterpExpr.c | 115 | 146 |
| src/include/executor/execExpr.h | 10 | 2 |
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 4cf0883435..ba129948ef 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -3,26 +3,26 @@
* execExpr.c
* Expression evaluation infrastructure.
*
- * Expression evaluation now works by first converting expression trees
+ * Expression evaluation works by first converting the expression tree
* (which went through planning first) into an ExprState using ExecInitExpr()
* et al. This converts the tree into a opcode based program (ExprEvalStep
- * representing individual instructions); allocated as a flat array of
+ * representing individual instructions), allocated as a flat array of
* steps.
*
* This flat representation has the big advantage that it can be implemented
* non-recursively, within a single function. This allows to interpret
* larger expressions from largely within a single function, keeping state
- * between them. In contrast to that, tree-walk based approaches in contrast
+ * between them. In contrast to that, tree-walk based approaches
* often run into performance issues due to function call / stack
* manipulation overhead.
*
* The ExprEvalStep representation is designed to be usable for interpreting
- * the expression, as well as compiling into native code. Thus, if possible,
- * as much complexity as possible should be handed by ExecInitExpr() (and
- * helpers), instead of handled at execution time where both interpreted and
+ * the expression, as well as compiling into native code. As much complexity
+ * as possible should be handled by ExecInitExpr() (and
+ * helpers), instead of execution time where both interpreted and
* compiled versions would need to deal with the complexity. Additionally
* checks for initialization at run time have a small but noticeable cost at
- * every execution.
+ * every execution. (HEIKKI: What does this last sentence refer to?)
*
* The next step is preparing the ExprState for execution, using
* ExecInstantiateExpr(). This is internally done by ExecInitExpr() and other
diff --git a/src/backend/executor/execInterpExpr.c b/src/backend/executor/execInterpExpr.c
index 21388f4086..2386fc898f 100644
--- a/src/backend/executor/execInterpExpr.c
+++ b/src/backend/executor/execInterpExpr.c
@@ -1,3 +1,7 @@
+/*
+ * HEIKKI: "Interp" is quite a mouthful. How about execExprInterpreter.c or
+ * just exprInterpreter.c?
+ */
/*-------------------------------------------------------------------------
*
* execInterpExpr.c
@@ -5,19 +9,19 @@
*
* This file provides a "switch threaded" (all compilers) and "direct
* threaded" (gcc, clang and compatible) implementation of expression
- * evaluation. The former is among st the fastest known methods of
+ * evaluation. The former is amongst the fastest known methods of
* interpreting programs without resorting to assembly level work, or
* just-in-time compilation, but requires support for computed gotos. The
* latter is amongst the fastest approaches doable in standard C.
*
* Both work by using ExprEvalStep->opcode to dispatch into code blocks
- * implementing the specific method. Switch based uses a plain switch()
+ * implementing the specific method. Switch-based uses a plain switch()
* statement to perform the dispatch. This has the advantages of being plain C
* and allowing to warn if implementation of a specific opcode has been
* forgotten. The disadvantage is that dispatches will, as commonly
* implemented by compilers, happen from a single location, causing bad branch
* prediction. Direct dispatch uses the label-as-values gcc extension - also
- * adopted by some other compilers - to replace ExprEvalStep-> opcode with the
+ * adopted by some other compilers - to replace ExprEvalStep->opcode with the
* address of the block implementing the instruction. This allows for better
* branch prediction (the jumps are happening from different locations) and
* fewer jumps (no jumps to common dispatch location needed).
@@ -84,26 +88,31 @@
*/
#if defined(EEO_USE_COMPUTED_GOTO)
static void **dispatch_table = NULL;
-#define EEO_SWITCH(d)
-#define EEO_DISPATCH_DIRECT(op) goto *((void *) op->opcode)
+#define EEO_DISPATCH() goto *((void *) op->opcode)
#define EEO_CASE(name) CASE_##name:
#else
-#define EEO_SWITCH(d) switch ((ExprEvalOp) d)
-#define EEO_DISPATCH_DIRECT(op) goto starteval
+#define EEO_DISPATCH() goto starteval
#define EEO_CASE(name) case name:
#endif /* EEO_USE_COMPUTED_GOTO */
-#define EEO_DISPATCH(op) \
+#define EEO_JUMP(stepno) \
+ do \
+ { \
+ op = &state->steps[stepno]; \
+ EEO_DISPATCH(); \
+ } while (0)
+
+#define EEO_NEXT() \
do \
{ \
op++; \
- EEO_DISPATCH_DIRECT(op); \
+ EEO_DISPATCH(); \
} \
while (0)
static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull);
-static void ExecPrepareInterp(void);
+static void ExecInitInterpreter(void);
/* support functions */
static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, bool checkisnull);
@@ -127,10 +136,11 @@ static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool
void
ExecInstantiateInterpretedExpr(ExprState *state)
{
- ExecPrepareInterp();
+ ExecInitInterpreter();
Assert(state->steps_len >= 1);
- Assert(ExecEvalStepOp(state, &state->steps[state->steps_len - 1]) == EEO_DONE);
+ Assert(state->steps[state->steps_len - 1].opcode == EEO_DONE);
+ Assert(state->flags & EEO_FLAG_JUMP_THREADED == 0);
/*
* Fast-path for very simple expressions. "starting up" the full
@@ -141,8 +151,8 @@ ExecInstantiateInterpretedExpr(ExprState *state)
*/
if (state->steps_len == 3)
{
- ExprEvalOp step0 = ExecEvalStepOp(state, &state->steps[0]);
- ExprEvalOp step1 = ExecEvalStepOp(state, &state->steps[1]);
+ ExprEvalOp step0 = state->steps[0].opcode;
+ ExprEvalOp step1 = state->steps[1].opcode;
if (step0 == EEO_INNER_FETCHSOME && step1 == EEO_INNER_VAR)
{
@@ -176,7 +186,7 @@ ExecInstantiateInterpretedExpr(ExprState *state)
}
}
else if (state->steps_len == 2 &&
- ExecEvalStepOp(state, &state->steps[0]) == EEO_CONST)
+ state->steps[0].opcode == EEO_CONST)
{
state->evalfunc = ExecJustConst;
return;
@@ -319,11 +329,11 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
scanslot = econtext->ecxt_scantuple;
#if defined(EEO_USE_COMPUTED_GOTO)
- EEO_DISPATCH_DIRECT(op);
+ EEO_DISPATCH();
#else
starteval:
+ switch ((ExprEvalOp) op->opcode)
#endif
- EEO_SWITCH(op->opcode)
{
EEO_CASE(EEO_DONE)
{
@@ -335,21 +345,21 @@ starteval:
/* XXX: worthwhile to check tts_nvalid inline first? */
slot_getsomeattrs(innerslot, op->d.fetch.last_var);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_OUTER_FETCHSOME)
{
slot_getsomeattrs(outerslot, op->d.fetch.last_var);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_SCAN_FETCHSOME)
{
slot_getsomeattrs(scanslot, op->d.fetch.last_var);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_INNER_VAR)
@@ -365,7 +375,7 @@ starteval:
*op->resnull = innerslot->tts_isnull[attnum];
*op->resvalue = innerslot->tts_values[attnum];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_OUTER_VAR)
@@ -377,7 +387,7 @@ starteval:
*op->resnull = outerslot->tts_isnull[attnum];
*op->resvalue = outerslot->tts_values[attnum];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_SCAN_VAR)
@@ -389,7 +399,7 @@ starteval:
*op->resnull = scanslot->tts_isnull[attnum];
*op->resvalue = scanslot->tts_values[attnum];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ASSIGN_INNER_VAR)
@@ -400,7 +410,7 @@ starteval:
resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ASSIGN_OUTER_VAR)
@@ -411,7 +421,7 @@ starteval:
resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ASSIGN_SCAN_VAR)
@@ -422,7 +432,7 @@ starteval:
resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ASSIGN_TMP)
@@ -432,7 +442,7 @@ starteval:
resultslot->tts_values[resultnum] = state->resvalue;
resultslot->tts_isnull[resultnum] = state->resnull;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ASSIGN_TMP_UNEXPAND)
@@ -447,7 +457,7 @@ starteval:
else
resultslot->tts_values[resultnum] = state->resvalue;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_INNER_SYSVAR)
@@ -459,7 +469,7 @@ starteval:
innerslot->tts_tupleDescriptor,
op->resnull);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_OUTER_SYSVAR)
@@ -471,7 +481,7 @@ starteval:
scanslot->tts_tupleDescriptor,
op->resnull);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_SCAN_SYSVAR)
@@ -483,7 +493,7 @@ starteval:
scanslot->tts_tupleDescriptor,
op->resnull);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_CONST)
@@ -491,7 +501,7 @@ starteval:
*op->resnull = op->d.constval.isnull;
*op->resvalue = op->d.constval.value;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -510,7 +520,7 @@ starteval:
*op->resvalue = (op->d.func.fn_addr) (fcinfo);
*op->resnull = fcinfo->isnull;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_FUNCEXPR_STRICT)
@@ -533,7 +543,7 @@ starteval:
*op->resnull = fcinfo->isnull;
strictfail:
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_FUNCEXPR_FUSAGE)
@@ -549,7 +559,7 @@ starteval:
pgstat_end_function_usage(&fcusage, true);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_FUNCEXPR_STRICT_FUSAGE)
@@ -577,7 +587,7 @@ starteval:
strictfail_fusage:
pgstat_end_function_usage(&fcusage, true);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -608,12 +618,10 @@ starteval:
*op->resnull = false;
*op->resvalue = BoolGetDatum(false);
/* bail out early */
- op = &state->steps[op->d.boolexpr.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.boolexpr.jumpdone);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOL_AND_STEP_LAST)
@@ -645,7 +653,7 @@ starteval:
*op->resvalue = BoolGetDatum(true);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -683,12 +691,10 @@ starteval:
*op->resvalue = BoolGetDatum(true);
/* bail out early */
- op = &state->steps[op->d.boolexpr.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.boolexpr.jumpdone);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOL_OR_STEP_LAST)
@@ -720,7 +726,7 @@ starteval:
*op->resvalue = BoolGetDatum(false);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOL_NOT_STEP)
@@ -737,7 +743,7 @@ starteval:
*/
*op->resvalue = BoolGetDatum(!DatumGetBool(*op->d.boolexpr.value));
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_QUAL)
@@ -750,12 +756,10 @@ starteval:
/* bail out early */
*op->resnull = false;
*op->resvalue = BoolGetDatum(false);
- op = &state->steps[op->d.qualexpr.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.qualexpr.jumpdone);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_NULLTEST_ISNULL)
@@ -763,7 +767,7 @@ starteval:
*op->resvalue = BoolGetDatum(*op->resnull);
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_NULLTEST_ISNOTNULL)
@@ -771,7 +775,7 @@ starteval:
*op->resvalue = BoolGetDatum(!*op->resnull);
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_NULLTEST_ROWISNULL)
@@ -779,7 +783,7 @@ starteval:
/* out of line implementation: too large */
ExecEvalRowNull(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_NULLTEST_ROWISNOTNULL)
@@ -787,7 +791,7 @@ starteval:
/* out of line implementation: too large */
ExecEvalRowNotNull(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_PARAM_EXEC)
@@ -795,14 +799,14 @@ starteval:
/* out of line implementation: too large */
ExecEvalParamExec(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_PARAM_EXTERN)
{
/* out of line implementation: too large */
ExecEvalParamExtern(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_CASE_WHEN_STEP)
@@ -810,22 +814,18 @@ starteval:
if (!*op->d.casewhen.isnull
&& DatumGetBool(*op->d.casewhen.value))
{
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
else
{
- op = &state->steps[op->d.casewhen.jumpfalse];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.casewhen.jumpfalse);
}
}
EEO_CASE(EEO_CASE_THEN_STEP)
{
/* results already placed in correct place during preceding steps */
- op = &state->steps[op->d.casethen.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.casethen.jumpdone);
}
EEO_CASE(EEO_CASE_TESTVAL)
@@ -850,7 +850,7 @@ starteval:
*op->resnull = econtext->caseValue_isNull;
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_CASE_TESTVAL_UNEXPAND)
@@ -876,7 +876,7 @@ starteval:
MakeExpandedObjectReadOnlyInternal(*op->resvalue);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_DOMAIN_TESTVAL)
@@ -895,7 +895,7 @@ starteval:
*op->resnull = econtext->domainValue_isNull;
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_DOMAIN_TESTVAL_UNEXPAND)
@@ -924,7 +924,7 @@ starteval:
MakeExpandedObjectReadOnlyInternal(*op->resvalue);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -935,12 +935,10 @@ starteval:
{
if (!*op->resnull)
{
- op = &state->steps[op->d.coalesce.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.coalesce.jumpdone);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/* BooleanTest implementations for all booltesttypes */
@@ -952,7 +950,7 @@ starteval:
*op->resvalue = *op->resvalue;
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOLTEST_IS_NOT_FALSE)
@@ -963,7 +961,7 @@ starteval:
*op->resvalue = *op->resvalue;
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOLTEST_IS_FALSE)
@@ -974,7 +972,7 @@ starteval:
*op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOLTEST_IS_NOT_TRUE)
@@ -985,7 +983,7 @@ starteval:
*op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOLTEST_IS_UNKNOWN)
@@ -993,7 +991,7 @@ starteval:
*op->resvalue = BoolGetDatum(*op->resnull);
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_BOOLTEST_IS_NOT_UNKNOWN)
@@ -1001,7 +999,7 @@ starteval:
*op->resvalue = BoolGetDatum(!*op->resnull);
*op->resnull = false;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_WHOLEROW)
@@ -1009,7 +1007,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalWholeRowVar(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1068,7 +1066,7 @@ starteval:
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1106,7 +1104,7 @@ starteval:
*op->resnull = fcinfo->isnull;
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_NULLIF)
@@ -1127,13 +1125,13 @@ starteval:
*op->resnull = true;
*op->resvalue = true;
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
}
*op->resnull = fcinfo->argnull[0];
*op->resvalue = fcinfo->arg[0];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_SQLVALUEFUNCTION)
@@ -1144,7 +1142,7 @@ starteval:
*/
ExecEvalSQLValueFunction(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_CURRENTOFEXPR)
@@ -1152,7 +1150,7 @@ starteval:
/* error invocation uses space, and shouldn't ever occur */
ExecEvalCurrentOfExpr(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ARRAYEXPR)
@@ -1160,7 +1158,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalArrayExpr(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ARRAYCOERCE)
@@ -1168,7 +1166,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalArrayCoerce(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ROW)
@@ -1176,7 +1174,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalRow(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ROWCOMPARE_STEP)
@@ -1188,9 +1186,7 @@ starteval:
(fcinfo->argnull[0] || fcinfo->argnull[1]))
{
*op->resnull = true;
- op = &state->steps[op->d.rowcompare_step.jumpnull];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.rowcompare_step.jumpnull);
}
fcinfo->isnull = false;
@@ -1200,20 +1196,16 @@ starteval:
if (fcinfo->isnull)
{
*op->resnull = true;
- op = &state->steps[op->d.rowcompare_step.jumpnull];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.rowcompare_step.jumpnull);
}
/* no need to compare remaining columns */
if (DatumGetInt32(*op->resvalue) != 0)
{
- op = &state->steps[op->d.rowcompare_step.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.rowcompare_step.jumpdone);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ROWCOMPARE_FINAL)
@@ -1242,7 +1234,7 @@ starteval:
break;
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_MINMAX)
@@ -1250,7 +1242,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalMinMax(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_FIELDSELECT)
@@ -1258,7 +1250,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalFieldSelect(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_FIELDSTORE_DEFORM)
@@ -1266,7 +1258,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalFieldStoreDeForm(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_FIELDSTORE_FORM)
@@ -1274,7 +1266,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalFieldStoreForm(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1291,12 +1283,10 @@ starteval:
if (*op->resnull &&
!op->d.arrayref.state->isassignment)
{
- op = &state->steps[op->d.arrayref.jumpdone];
-
- EEO_DISPATCH_DIRECT(op);
+ EEO_JUMP(op->d.arrayref.jumpdone);
}
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1307,14 +1297,12 @@ starteval:
/* too complex for an inline implementation */
if (ExecEvalArrayRefCheckSubscript(state, op))
{
- op++;
+ EEO_NEXT();
}
else
{
- op = &state->steps[op->d.arrayref_checksubscript.jumpdone];
+ EEO_JUMP(op->d.arrayref_checksubscript.jumpdone);
}
-
- EEO_DISPATCH_DIRECT(op);
}
/*
@@ -1326,7 +1314,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalArrayRefOld(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1337,7 +1325,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalArrayRefAssign(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1348,7 +1336,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalArrayRefFetch(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_CONVERT_ROWTYPE)
@@ -1356,7 +1344,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalConvertRowtype(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_SCALARARRAYOP)
@@ -1364,14 +1352,14 @@ starteval:
/* too complex for an inline implementation */
ExecEvalScalarArrayOp(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_DOMAIN_NOTNULL)
{
/* too complex for an inline implementation */
ExecEvalConstraintNotNull(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_DOMAIN_CHECK)
@@ -1379,7 +1367,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalConstraintCheck(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_XMLEXPR)
@@ -1387,7 +1375,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalXmlExpr(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
/*
@@ -1403,7 +1391,7 @@ starteval:
*op->resnull = econtext->ecxt_aggnulls[aggref->aggno];
*op->resvalue = econtext->ecxt_aggvalues[aggref->aggno];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_GROUPING_FUNC)
@@ -1411,7 +1399,7 @@ starteval:
/* too complex/uncommon for an inline implementation */
ExecEvalGroupingFunc(state, op);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_WINDOW_FUNC)
@@ -1423,7 +1411,7 @@ starteval:
*op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
*op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_SUBPLAN)
@@ -1431,7 +1419,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalSubPlan(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_ALTERNATIVE_SUBPLAN)
@@ -1439,7 +1427,7 @@ starteval:
/* too complex for an inline implementation */
ExecEvalAlternativeSubPlan(state, op, econtext);
- EEO_DISPATCH(op);
+ EEO_NEXT();
}
EEO_CASE(EEO_LAST)
@@ -1454,6 +1442,8 @@ out:
return state->resvalue;
}
+/* Fast-path functions, for very simple expressions */
+
static Datum
ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
{
@@ -1536,7 +1526,7 @@ ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
}
static void
-ExecPrepareInterp(void)
+ExecInitInterpreter(void)
{
static bool prepared = false;
@@ -1551,27 +1541,6 @@ ExecPrepareInterp(void)
prepared = true;
}
-ExprEvalOp
-ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
-{
-#if defined(EEO_USE_COMPUTED_GOTO)
- if (state->flags & EEO_FLAG_JUMP_THREADED)
- {
- int i;
-
- for (i = 0; i < EEO_LAST; i++)
- {
- if ((void *) op->opcode == dispatch_table[i])
- {
- return (ExprEvalOp) i;
- }
- }
- elog(ERROR, "unknown opcode");
- }
-#endif
- return (ExprEvalOp) op->opcode;
-}
-
/*
* Computes the value for a PARAM_EXEC parameter.
*/
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 003f4faede..e28bb2a85e 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -22,6 +22,11 @@ struct ArrayRefState;
typedef enum ExprEvalOp
{
+ /*
+ * HEIKKI: How about renaming these to EEOP_* ? I think it'd be a
+ * good mnemonic to remember that these are opcodes, and just one
+ * extra letter.
+ */
EEO_DONE,
EEO_INNER_FETCHSOME,
EEO_OUTER_FETCHSOME,
@@ -110,6 +115,11 @@ typedef struct ExprEvalStep
* ExprEvalOp, but during execution it can be swapped out to some other
* type, e.g. a pointer for computed goto (that's why it's a size_t).
*/
+ /* HEIKKI: Is it safe to assume that sizeof(size_t) >= sizeof(void *) ? */
+ /* HEIKKI: How tight are we with space in this union? It'd be nice to keep
+ * the original opcode, and have a separate field for the computed goto ptr.
+ * For debugging purposes if nothing else.
+ */
size_t opcode;
/* target for the result of the current instruction */
@@ -419,8 +429,6 @@ typedef struct ArrayRefState
extern void ExecInstantiateInterpretedExpr(ExprState *state);
-extern ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op);
-
/*
* Non fast-path execution functions. These are externs instead of static in
* execInterpExpr.c, because that allows them to be used by other methods of