Skip to content

Commit 0d9f7e9

Browse files
authored
Split ir nodes for variable/field access into load/store (elastic#60976)
This change splits the ir nodes for variable/field accesses into two separate nodes, one for load and one for store. This removes the need for an assignment node as the store nodes replace it as the root. It also means all nodes simply have a write method instead of having separate methods for load and store to support the different types of bytecode required for this. This also means that compound assignment is no longer specialized on the assignment node which had to be overly coupled with the previous version of the variable/field accessor nodes. Store nodes now have two children. The first child is the prefix chain. The second child is the value to store. The prefix chain is the set of nodes that represent a.b in the accessor chain of a.b.c. The value node can be any value that is legally castable to type of the store node. Compound assignments are now setup where the value node of a store node is a binary math node. The left side of the binary math node is a dup node with a prefix root node as a child. The right side of the binary math node is the value node.
1 parent 3250ea4 commit 0d9f7e9

37 files changed

+1447
-948
lines changed

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

Lines changed: 0 additions & 215 deletions
This file was deleted.

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

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

2222
import org.elasticsearch.painless.ClassWriter;
23-
import org.elasticsearch.painless.DefBootstrap;
24-
import org.elasticsearch.painless.Location;
2523
import org.elasticsearch.painless.MethodWriter;
2624
import org.elasticsearch.painless.Operation;
2725
import org.elasticsearch.painless.WriterConstants;
@@ -40,8 +38,8 @@ public class BinaryMathNode extends BinaryNode {
4038
private Operation operation;
4139
private Class<?> binaryType;
4240
private Class<?> shiftType;
43-
private boolean cat; // set to true for a String concatenation
44-
private boolean originallyExplicit; // record whether there was originally an explicit cast
41+
private boolean cat;
42+
private int flags;
4543

4644
public void setOperation(Operation operation) {
4745
this.operation = operation;
@@ -83,17 +81,12 @@ public boolean getCat() {
8381
return cat;
8482
}
8583

86-
public void setOriginallyExplicit(boolean originallyExplicit) {
87-
this.originallyExplicit = originallyExplicit;
84+
public void setFlags(int flags) {
85+
this.flags = flags;
8886
}
8987

90-
public boolean getOriginallyExplicit() {
91-
return originallyExplicit;
92-
}
93-
94-
@Override
95-
public void setLocation(Location location) {
96-
super.setLocation(location);
88+
public int getFlags() {
89+
return flags;
9790
}
9891

9992
/* ---- end node data, begin visitor ---- */
@@ -147,12 +140,6 @@ protected void write(ClassWriter classWriter, MethodWriter methodWriter, WriteSc
147140
getRightNode().write(classWriter, methodWriter, writeScope);
148141

149142
if (binaryType == def.class || (shiftType != null && shiftType == def.class)) {
150-
// def calls adopt the wanted return value. if there was a narrowing cast,
151-
// we need to flag that so that its done at runtime.
152-
int flags = 0;
153-
if (originallyExplicit) {
154-
flags |= DefBootstrap.OPERATOR_EXPLICIT_CAST;
155-
}
156143
methodWriter.writeDynamicBinaryInstruction(location,
157144
getExpressionType(), getLeftNode().getExpressionType(), getRightNode().getExpressionType(), operation, flags);
158145
} else {

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919

2020
package org.elasticsearch.painless.ir;
2121

22-
public abstract class BinaryNode extends ExpressionNode {
22+
import org.elasticsearch.painless.ClassWriter;
23+
import org.elasticsearch.painless.MethodWriter;
24+
import org.elasticsearch.painless.symbol.WriteScope;
25+
26+
public class BinaryNode extends ExpressionNode {
2327

2428
/* ---- begin tree structure ---- */
2529

@@ -44,4 +48,9 @@ public ExpressionNode getRightNode() {
4448

4549
/* ---- end tree structure ---- */
4650

51+
@Override
52+
protected void write(ClassWriter classWriter, MethodWriter methodWriter, WriteScope writeScope) {
53+
leftNode.write(classWriter, methodWriter, writeScope);
54+
rightNode.write(classWriter, methodWriter, writeScope);
55+
}
4756
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.painless.ir;
21+
22+
import org.elasticsearch.painless.ClassWriter;
23+
import org.elasticsearch.painless.MethodWriter;
24+
import org.elasticsearch.painless.phase.IRTreeVisitor;
25+
import org.elasticsearch.painless.symbol.WriteScope;
26+
27+
public class DupNode extends UnaryNode {
28+
29+
/* ---- begin node data ---- */
30+
31+
private int size;
32+
private int depth;
33+
34+
public void setSize(int size) {
35+
this.size = size;
36+
}
37+
38+
public int getSize() {
39+
return size;
40+
}
41+
42+
public void setDepth(int depth) {
43+
this.depth = depth;
44+
}
45+
46+
public int getDepth() {
47+
return depth;
48+
}
49+
50+
/* ---- end node data, begin visitor ---- */
51+
52+
@Override
53+
public <Input, Output> Output visit(IRTreeVisitor<Input, Output> irTreeVisitor, Input input) {
54+
return irTreeVisitor.visitDup(this, input);
55+
}
56+
57+
/* ---- end visitor ---- */
58+
59+
@Override
60+
protected void write(ClassWriter classWriter, MethodWriter methodWriter, WriteScope writeScope) {
61+
getChildNode().write(classWriter, methodWriter, writeScope);
62+
methodWriter.writeDup(size, depth);
63+
}
64+
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/FlipArrayIndex.java renamed to modules/lang-painless/src/main/java/org/elasticsearch/painless/ir/FlipArrayIndexNode.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,25 @@
2121

2222
import org.elasticsearch.painless.ClassWriter;
2323
import org.elasticsearch.painless.MethodWriter;
24+
import org.elasticsearch.painless.phase.IRTreeVisitor;
2425
import org.elasticsearch.painless.symbol.WriteScope;
2526
import org.objectweb.asm.Label;
2627
import org.objectweb.asm.Opcodes;
2728

28-
public class FlipArrayIndex extends IndexNode {
29+
public class FlipArrayIndexNode extends UnaryNode {
30+
31+
/* ---- begin visitor ---- */
32+
33+
@Override
34+
public <Input, Output> Output visit(IRTreeVisitor<Input, Output> irTreeVisitor, Input input) {
35+
return irTreeVisitor.visitFlipArrayIndex(this, input);
36+
}
37+
38+
/* ---- end visitor ---- */
2939

3040
@Override
3141
protected void write(ClassWriter classWriter, MethodWriter methodWriter, WriteScope writeScope) {
32-
getIndexNode().write(classWriter, methodWriter, writeScope);
42+
getChildNode().write(classWriter, methodWriter, writeScope);
3343

3444
Label noFlip = new Label();
3545
methodWriter.dup();

0 commit comments

Comments
 (0)