Skip to content

Commit

Permalink
Improve Painless compilation performance for nested conditionals (#52056
Browse files Browse the repository at this point in the history
)

This PR changes how conditional expression is handled in `PainlessParser`
in a way that avoids the need for backtracking, which led to exponential
compilation times in case of nested conditionals.

The test was added ensures that we can compile deeply nested conditionals.

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
probakowski and elasticmachine authored Feb 7, 2020
1 parent 4ea1b06 commit aec932a
Show file tree
Hide file tree
Showing 7 changed files with 919 additions and 848 deletions.
40 changes: 22 additions & 18 deletions modules/lang-painless/src/main/antlr/PainlessParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,29 @@ trap
: CATCH LP TYPE ID RP block
;

noncondexpression
: unary # single
| noncondexpression ( MUL | DIV | REM ) noncondexpression # binary
| noncondexpression ( ADD | SUB ) noncondexpression # binary
| noncondexpression ( FIND | MATCH ) noncondexpression # binary
| noncondexpression ( LSH | RSH | USH ) noncondexpression # binary
| noncondexpression ( LT | LTE | GT | GTE ) noncondexpression # comp
| noncondexpression INSTANCEOF decltype # instanceof
| noncondexpression ( EQ | EQR | NE | NER ) noncondexpression # comp
| noncondexpression BWAND noncondexpression # binary
| noncondexpression XOR noncondexpression # binary
| noncondexpression BWOR noncondexpression # binary
| noncondexpression BOOLAND noncondexpression # bool
| noncondexpression BOOLOR noncondexpression # bool
| <assoc=right> noncondexpression ELVIS noncondexpression # elvis
;

expression
: unary # single
| expression ( MUL | DIV | REM ) expression # binary
| expression ( ADD | SUB ) expression # binary
| expression ( FIND | MATCH ) expression # binary
| expression ( LSH | RSH | USH ) expression # binary
| expression ( LT | LTE | GT | GTE ) expression # comp
| expression INSTANCEOF decltype # instanceof
| expression ( EQ | EQR | NE | NER ) expression # comp
| expression BWAND expression # binary
| expression XOR expression # binary
| expression BWOR expression # binary
| expression BOOLAND expression # bool
| expression BOOLOR expression # bool
| <assoc=right> expression COND expression COLON expression # conditional
| <assoc=right> expression ELVIS expression # elvis
| <assoc=right> expression ( ASSIGN | AADD | ASUB | AMUL |
ADIV | AREM | AAND | AXOR |
AOR | ALSH | ARSH | AUSH ) expression # assignment
: noncondexpression # nonconditional
| <assoc=right> noncondexpression COND expression COLON expression # conditional
| <assoc=right> noncondexpression ( ASSIGN | AADD | ASUB | AMUL |
ADIV | AREM | AAND | AXOR |
AOR | ALSH | ARSH | AUSH ) expression # assignment
;

unary
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
// ANTLR GENERATED CODE: DO NOT EDIT
package org.elasticsearch.painless.antlr;

import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.RuntimeMetaData;
import org.antlr.v4.runtime.Vocabulary;
import org.antlr.v4.runtime.VocabularyImpl;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;

@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
abstract class PainlessLexer extends Lexer {
Expand Down
Loading

0 comments on commit aec932a

Please sign in to comment.