Skip to content

Commit 31e9792

Browse files
committed
Add decorations to ir nodes in Painless (#63894)
This change starts to switch all ir nodes to use decorations instead of specific member data. For this specific change, we add only an expression type decoration to begin with to keep the change smaller. Other members of the ir nodes will be converted to decorations in future changes. The decoration system has two important advantages: - The first is it's consistent with the user nodes as generated data is attached to them as a decoration, so we have a clear, consistent model for how to use both trees. - This allows additionally generated data to be attached as necessary for optimization phases making the ir tree extendable which is one of our primary, long-term goals.
1 parent 3bc250c commit 31e9792

File tree

7 files changed

+363
-212
lines changed

7 files changed

+363
-212
lines changed

modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/ExpressionNode.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,9 @@
2020
package org.elasticsearch.painless.ir;
2121

2222
import org.elasticsearch.painless.Location;
23-
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
2423

2524
public abstract class ExpressionNode extends IRNode {
2625

27-
/* ---- begin node data ---- */
28-
29-
private Class<?> expressionType;
30-
31-
public void setExpressionType(Class<?> expressionType) {
32-
this.expressionType = expressionType;
33-
}
34-
35-
public Class<?> getExpressionType() {
36-
return expressionType;
37-
}
38-
39-
public String getExpressionCanonicalTypeName() {
40-
return PainlessLookupUtility.typeToCanonicalTypeName(expressionType);
41-
}
42-
43-
/* ---- end node data ---- */
44-
4526
public ExpressionNode(Location location) {
4627
super(location);
4728
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/IRNode.java

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,82 @@
2222
import org.elasticsearch.painless.Location;
2323
import org.elasticsearch.painless.phase.IRTreeVisitor;
2424

25+
import java.util.HashMap;
26+
import java.util.HashSet;
27+
import java.util.Map;
28+
import java.util.Set;
29+
2530
public abstract class IRNode {
2631

27-
/* ---- begin node data ---- */
32+
/* ---- begin decorations ---- */
33+
34+
public interface IRDecoration {
35+
36+
}
37+
38+
private final Map<Class<? extends IRDecoration>, IRDecoration> decorations = new HashMap<>();
39+
40+
@SuppressWarnings("unchecked")
41+
public <T extends IRDecoration> T attachDecoration(T decoration) {
42+
return (T)decorations.put(decoration.getClass(), decoration);
43+
}
44+
45+
public <T extends IRDecoration> T removeDecoration(Class<T> type) {
46+
return type.cast(decorations.remove(type));
47+
}
48+
49+
public <T extends IRDecoration> T getDecoration(Class<T> type) {
50+
return type.cast(decorations.get(type));
51+
}
52+
53+
public boolean hasDecoration(Class<? extends IRDecoration> type) {
54+
return decorations.containsKey(type);
55+
}
56+
57+
public <T extends IRDecoration> boolean copyDecorationFrom(IRNode copyFromIRNode, Class<T> type) {
58+
T decoration = copyFromIRNode.getDecoration(type);
59+
60+
61+
if (decoration != null) {
62+
attachDecoration(decoration);
63+
64+
return true;
65+
}
66+
67+
return false;
68+
}
69+
70+
/* ---- end decorations, begin conditions ---- */
71+
72+
public interface IRCondition {
73+
74+
}
75+
76+
private final Set<Class<? extends IRCondition>> conditions = new HashSet<>();
77+
78+
public boolean attachCondition(Class<? extends IRCondition> type) {
79+
return conditions.add(type);
80+
}
81+
82+
public boolean removeCondition(Class<? extends IRCondition> type) {
83+
return conditions.remove(type);
84+
}
85+
86+
public boolean hasCondition(Class<? extends IRCondition> type) {
87+
return conditions.contains(type);
88+
}
89+
90+
public boolean copyConditionFrom(IRNode copyFromIRNode, Class<? extends IRCondition> type) {
91+
if (copyFromIRNode.hasCondition(type)) {
92+
attachCondition(type);
93+
94+
return true;
95+
}
96+
97+
return false;
98+
}
99+
100+
/* ---- end conditions, begin node data ---- */
28101

29102
private final Location location;
30103

modules/lang-painless/src/main/java/org/elasticsearch/painless/phase/DefaultConstantFoldingOptimizationPhase.java

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.elasticsearch.painless.ir.UnaryMathNode;
6868
import org.elasticsearch.painless.ir.WhileLoopNode;
6969
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
70+
import org.elasticsearch.painless.symbol.IRDecorations.IRDExpressionType;
7071

7172
import java.util.function.Consumer;
7273

@@ -180,7 +181,7 @@ public void visitUnaryMath(UnaryMathNode irUnaryMathNode, Consumer<ExpressionNod
180181
if (irUnaryMathNode.getChildNode() instanceof ConstantNode) {
181182
ConstantNode irConstantNode = (ConstantNode)irUnaryMathNode.getChildNode();
182183
Operation operation = irUnaryMathNode.getOperation();
183-
Class<?> type = irUnaryMathNode.getExpressionType();
184+
Class<?> type = irUnaryMathNode.getDecoration(IRDExpressionType.class).getType();
184185

185186
if (operation == Operation.SUB) {
186187
if (type == int.class) {
@@ -238,7 +239,7 @@ public void visitBinaryMath(BinaryMathNode irBinaryMathNode, Consumer<Expression
238239
ConstantNode irLeftConstantNode = (ConstantNode)irBinaryMathNode.getLeftNode();
239240
ConstantNode irRightConstantNode = (ConstantNode)irBinaryMathNode.getRightNode();
240241
Operation operation = irBinaryMathNode.getOperation();
241-
Class<?> type = irBinaryMathNode.getExpressionType();
242+
Class<?> type = irBinaryMathNode.getDecoration(IRDExpressionType.class).getType();
242243

243244
if (operation == Operation.MUL) {
244245
if (type == int.class) {
@@ -435,22 +436,22 @@ public void visitStringConcatenation(StringConcatenationNode irStringConcatenati
435436
if (irLeftNode instanceof ConstantNode && irRightNode instanceof ConstantNode) {
436437
ConstantNode irConstantNode = (ConstantNode)irLeftNode;
437438
irConstantNode.setConstant("" + irConstantNode.getConstant() + ((ConstantNode)irRightNode).getConstant());
438-
irConstantNode.setExpressionType(String.class);
439+
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
439440
irStringConcatenationNode.getArgumentNodes().remove(i + 1);
440441
} else if (irLeftNode instanceof NullNode && irRightNode instanceof ConstantNode) {
441442
ConstantNode irConstantNode = (ConstantNode)irRightNode;
442443
irConstantNode.setConstant("" + null + ((ConstantNode)irRightNode).getConstant());
443-
irConstantNode.setExpressionType(String.class);
444+
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
444445
irStringConcatenationNode.getArgumentNodes().remove(i);
445446
} else if (irLeftNode instanceof ConstantNode && irRightNode instanceof NullNode) {
446447
ConstantNode irConstantNode = (ConstantNode)irLeftNode;
447448
irConstantNode.setConstant("" + ((ConstantNode)irLeftNode).getConstant() + null);
448-
irConstantNode.setExpressionType(String.class);
449+
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
449450
irStringConcatenationNode.getArgumentNodes().remove(i + 1);
450451
} else if (irLeftNode instanceof NullNode && irRightNode instanceof NullNode) {
451452
ConstantNode irConstantNode = new ConstantNode(irLeftNode.getLocation());
452453
irConstantNode.setConstant("" + null + null);
453-
irConstantNode.setExpressionType(String.class);
454+
irConstantNode.attachDecoration(new IRDExpressionType(String.class));
454455
irStringConcatenationNode.getArgumentNodes().set(i, irConstantNode);
455456
irStringConcatenationNode.getArgumentNodes().remove(i + 1);
456457
} else {
@@ -476,7 +477,7 @@ public void visitBoolean(BooleanNode irBooleanNode, Consumer<ExpressionNode> sco
476477
ConstantNode irLeftConstantNode = (ConstantNode)irBooleanNode.getLeftNode();
477478
ConstantNode irRightConstantNode = (ConstantNode)irBooleanNode.getRightNode();
478479
Operation operation = irBooleanNode.getOperation();
479-
Class<?> type = irBooleanNode.getExpressionType();
480+
Class<?> type = irBooleanNode.getDecoration(IRDExpressionType.class).getType();
480481

481482
if (operation == Operation.AND) {
482483
if (type == boolean.class) {
@@ -544,7 +545,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
544545
}
545546
}
546547

547-
irLeftConstantNode.setExpressionType(boolean.class);
548+
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
548549
scope.accept(irLeftConstantNode);
549550
} else if (operation == Operation.NE || operation == Operation.NER) {
550551
if (type == boolean.class) {
@@ -571,7 +572,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
571572
}
572573
}
573574

574-
irLeftConstantNode.setExpressionType(boolean.class);
575+
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
575576
scope.accept(irLeftConstantNode);
576577
} else if (irLeftConstantNode != null && irRightConstantNode != null) {
577578
if (operation == Operation.GT) {
@@ -591,7 +592,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
591592
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
592593
}
593594

594-
irLeftConstantNode.setExpressionType(boolean.class);
595+
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
595596
scope.accept(irLeftConstantNode);
596597
} else if (operation == Operation.GTE) {
597598
if (type == int.class) {
@@ -610,7 +611,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
610611
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
611612
}
612613

613-
irLeftConstantNode.setExpressionType(boolean.class);
614+
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
614615
scope.accept(irLeftConstantNode);
615616
} else if (operation == Operation.LT) {
616617
if (type == int.class) {
@@ -629,7 +630,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
629630
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
630631
}
631632

632-
irLeftConstantNode.setExpressionType(boolean.class);
633+
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
633634
scope.accept(irLeftConstantNode);
634635
} else if (operation == Operation.LTE) {
635636
if (type == int.class) {
@@ -648,7 +649,7 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
648649
"constants [" + irLeftConstantNode.getConstant() + "] and [" + irRightConstantNode.getConstant() + "]"));
649650
}
650651

651-
irLeftConstantNode.setExpressionType(boolean.class);
652+
irLeftConstantNode.attachDecoration(new IRDExpressionType(boolean.class));
652653
scope.accept(irLeftConstantNode);
653654
}
654655
}
@@ -659,11 +660,12 @@ public void visitComparison(ComparisonNode irComparisonNode, Consumer<Expression
659660
public void visitCast(CastNode irCastNode, Consumer<ExpressionNode> scope) {
660661
irCastNode.getChildNode().visit(this, irCastNode::setChildNode);
661662

662-
if (irCastNode.getChildNode() instanceof ConstantNode && PainlessLookupUtility.isConstantType(irCastNode.getExpressionType())) {
663+
if (irCastNode.getChildNode() instanceof ConstantNode &&
664+
PainlessLookupUtility.isConstantType(irCastNode.getDecoration(IRDExpressionType.class).getType())) {
663665
ConstantNode irConstantNode = (ConstantNode)irCastNode.getChildNode();
664666
irConstantNode.setConstant(
665667
AnalyzerCaster.constCast(irCastNode.getLocation(), irConstantNode.getConstant(), irCastNode.getCast()));
666-
irConstantNode.setExpressionType(irCastNode.getExpressionType());
668+
irConstantNode.copyDecorationFrom(irCastNode, IRDExpressionType.class);
667669
scope.accept(irConstantNode);
668670
}
669671
}

0 commit comments

Comments
 (0)