* Prepare ExprState for interpreted execution. */
| 232 | * Prepare ExprState for interpreted execution. |
| 233 | */ |
| 234 | void |
| 235 | ExecReadyInterpretedExpr(ExprState *state) |
| 236 | { |
| 237 | /* Ensure one-time interpreter setup has been done */ |
| 238 | ExecInitInterpreter(); |
| 239 | |
| 240 | /* Simple validity checks on expression */ |
| 241 | Assert(state->steps_len >= 1); |
| 242 | Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE); |
| 243 | |
| 244 | /* |
| 245 | * Don't perform redundant initialization. This is unreachable in current |
| 246 | * cases, but might be hit if there's additional expression evaluation |
| 247 | * methods that rely on interpreted execution to work. |
| 248 | */ |
| 249 | if (state->flags & EEO_FLAG_INTERPRETER_INITIALIZED) |
| 250 | return; |
| 251 | |
| 252 | /* |
| 253 | * First time through, check whether attribute matches Var. Might not be |
| 254 | * ok anymore, due to schema changes. We do that by setting up a callback |
| 255 | * that does checking on the first call, which then sets the evalfunc |
| 256 | * callback to the actual method of execution. |
| 257 | */ |
| 258 | state->evalfunc = ExecInterpExprStillValid; |
| 259 | |
| 260 | /* DIRECT_THREADED should not already be set */ |
| 261 | Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0); |
| 262 | |
| 263 | /* |
| 264 | * There shouldn't be any errors before the expression is fully |
| 265 | * initialized, and even if so, it'd lead to the expression being |
| 266 | * abandoned. So we can set the flag now and save some code. |
| 267 | */ |
| 268 | state->flags |= EEO_FLAG_INTERPRETER_INITIALIZED; |
| 269 | |
| 270 | /* |
| 271 | * Select fast-path evalfuncs for very simple expressions. "Starting up" |
| 272 | * the full interpreter is a measurable overhead for these, and these |
| 273 | * patterns occur often enough to be worth optimizing. |
| 274 | */ |
| 275 | if (state->steps_len == 3) |
| 276 | { |
| 277 | ExprEvalOp step0 = state->steps[0].opcode; |
| 278 | ExprEvalOp step1 = state->steps[1].opcode; |
| 279 | |
| 280 | if (step0 == EEOP_INNER_FETCHSOME && |
| 281 | step1 == EEOP_INNER_VAR) |
| 282 | { |
| 283 | state->evalfunc_private = (void *) ExecJustInnerVar; |
| 284 | return; |
| 285 | } |
| 286 | else if (step0 == EEOP_OUTER_FETCHSOME && |
| 287 | step1 == EEOP_OUTER_VAR) |
| 288 | { |
| 289 | state->evalfunc_private = (void *) ExecJustOuterVar; |
| 290 | return; |
| 291 | } |
no test coverage detected