Skip to content

Commit

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

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 <elasticmachine@users.noreply.github.com>
  • Loading branch information
probakowski and elasticmachine committed Feb 7, 2020
1 parent 282e919 commit d522956
Show file tree
Hide file tree
Showing 7 changed files with 961 additions and 890 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 d522956

Please sign in to comment.