Skip to content

Commit 6dfdb30

Browse files
authored
Pass locals as arguments in endpoint rules (#6131)
* Pass locals as arguments in endpoint rules * Add change log entry * Ensure we always return from a tree method
1 parent 1a730d6 commit 6dfdb30

File tree

11 files changed

+568
-706
lines changed

11 files changed

+568
-706
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "AWS SDK for Java v2",
3+
"contributor": "",
4+
"type": "feature",
5+
"description": "Improve the endpoint rules performance by directly passing the needed params instead of using a POJO to keep track of them."
6+
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java

Lines changed: 80 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Arrays;
2222
import java.util.List;
2323
import java.util.Map;
24+
import java.util.stream.Collectors;
2425
import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
2526
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
2627
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
@@ -32,14 +33,17 @@ public class CodeGeneratorVisitor extends WalkRuleExpressionVisitor {
3233
private final RuleRuntimeTypeMirror typeMirror;
3334
private final SymbolTable symbolTable;
3435
private final Map<String, KeyTypePair> knownEndpointAttributes;
36+
private final Map<String, ComputeScopeTree.Scope> ruleIdToScope;
3537

3638
public CodeGeneratorVisitor(RuleRuntimeTypeMirror typeMirror,
3739
SymbolTable symbolTable,
3840
Map<String, KeyTypePair> knownEndpointAttributes,
41+
Map<String, ComputeScopeTree.Scope> ruleIdToScope,
3942
CodeBlock.Builder builder) {
4043
this.builder = builder;
4144
this.symbolTable = symbolTable;
4245
this.knownEndpointAttributes = knownEndpointAttributes;
46+
this.ruleIdToScope = ruleIdToScope;
4347
this.typeMirror = typeMirror;
4448
}
4549

@@ -196,28 +200,14 @@ public Void visitRuleSetExpression(RuleSetExpression e) {
196200

197201
@Override
198202
public Void visitLetExpression(LetExpression expr) {
199-
for (String key : expr.bindings().keySet()) {
200-
RuleType type = symbolTable.locals().get(key);
201-
builder.addStatement("$T $L = null", type.javaType(), key);
202-
}
203-
204-
int count = 0;
205203
for (Map.Entry<String, RuleExpression> kvp : expr.bindings().entrySet()) {
206204
String k = kvp.getKey();
207205
RuleExpression v = kvp.getValue();
208-
builder.add("if (");
209-
builder.add("($L = ", k);
206+
RuleType type = symbolTable.locals().get(k);
207+
builder.add("$T $L = ", type.javaType(), k);
210208
v.accept(this);
211-
builder.add(") != null");
212-
213-
builder.beginControlFlow(")");
214-
builder.addStatement("locals = locals.toBuilder().$1L($1L).build()", k);
215-
216-
if (++count < expr.bindings().size()) {
217-
builder.nextControlFlow("else");
218-
builder.addStatement("return RuleResult.carryOn()");
219-
builder.endControlFlow();
220-
}
209+
builder.addStatement("");
210+
builder.beginControlFlow("if ($L != null)", k);
221211
}
222212
return null;
223213
}
@@ -235,40 +225,101 @@ private void conditionsPreamble(RuleSetExpression expr) {
235225
}
236226

237227
private void conditionsEpilogue(RuleSetExpression expr) {
238-
int blocksToClose = expr.conditions().size();
239-
for (int idx = 0; idx < blocksToClose; ++idx) {
240-
builder.endControlFlow();
228+
for (RuleExpression condition : expr.conditions()) {
229+
if (condition.kind() == RuleExpression.RuleExpressionKind.LET) {
230+
LetExpression let = (LetExpression) condition;
231+
for (int x = 0; x < let.bindings().size(); x++) {
232+
builder.endControlFlow();
233+
}
234+
} else {
235+
builder.endControlFlow();
236+
}
241237
}
242-
if (!expr.conditions().isEmpty()) {
238+
if (needsReturn(expr)) {
243239
builder.addStatement("return $T.carryOn()", typeMirror.rulesResult().type());
244240
}
245241
}
246242

243+
private boolean needsReturn(RuleSetExpression expr) {
244+
// If the expression can be inlined, then it doesn't live in
245+
// its own method, no return at the end required
246+
if (canBeInlined(expr)) {
247+
return false;
248+
}
249+
// If the expression has conditions all be be wrapped in
250+
// if-blocks, thus at the end of the method we need to return
251+
// carryOn()
252+
if (!expr.conditions().isEmpty()) {
253+
return true;
254+
}
255+
// If the expression doesn't have any conditions, and doesn't
256+
// have any children then we need to return carryOn(). This
257+
// case SHOULD NOT happen but we assume below that there are
258+
// children, thus adding the test here.
259+
if (expr.children().isEmpty()) {
260+
return true;
261+
}
262+
// We have children, check the last one.
263+
int size = expr.children().size();
264+
RuleSetExpression child = expr.children().get(size - 1);
265+
// If a tree then we don't need a return.
266+
if (child.isTree()) {
267+
return false;
268+
}
269+
// The child is not a tree, so it was inlined. Check if it
270+
// does have any conditions, if it so, its body will be inside
271+
// a block already so we need to return after it.
272+
return !child.conditions().isEmpty();
273+
}
274+
247275
private void codegenTreeBody(RuleSetExpression expr) {
248276
List<RuleSetExpression> children = expr.children();
249277
int size = children.size();
278+
boolean isFirst = true;
250279
for (int idx = 0; idx < size; ++idx) {
251280
RuleSetExpression child = children.get(idx);
281+
if (canBeInlined(child)) {
282+
child.accept(this);
283+
continue;
284+
}
252285
boolean isLast = idx == size - 1;
253286
if (isLast) {
254-
builder.addStatement("return $L(params, locals)",
255-
child.ruleId());
287+
builder.addStatement("return $L($L)",
288+
child.ruleId(),
289+
callParams(child.ruleId()));
256290
continue;
257291
}
258-
boolean isFirst = idx == 0;
292+
259293
if (isFirst) {
260-
builder.addStatement("$T result = $L(params, locals)",
294+
isFirst = false;
295+
builder.addStatement("$T result = $L($L)",
261296
typeMirror.rulesResult().type(),
262-
child.ruleId());
297+
child.ruleId(),
298+
callParams(child.ruleId()));
263299
} else {
264-
builder.addStatement("result = $L(params, locals)",
265-
child.ruleId());
300+
builder.addStatement("result = $L($L)",
301+
child.ruleId(),
302+
callParams(child.ruleId()));
266303
}
267304
builder.beginControlFlow("if (result.isResolved())")
268305
.addStatement("return result")
269306
.endControlFlow();
270307
}
308+
}
271309

310+
private boolean canBeInlined(RuleSetExpression child) {
311+
return !child.isTree();
312+
}
313+
314+
private String callParams(String ruleId) {
315+
ComputeScopeTree.Scope scope = ruleIdToScope.get(ruleId);
316+
String args = scope.usesLocals().stream()
317+
.filter(a -> !scope.defines().contains(a))
318+
.collect(Collectors.joining(", "));
319+
if (args.isEmpty()) {
320+
return "params";
321+
}
322+
return "params, " + args;
272323
}
273324

274325
@Override
@@ -381,7 +432,6 @@ private void addAttributeBlock(String k, RuleExpression v) {
381432
builder.add(")");
382433
}
383434

384-
385435
public CodeBlock.Builder builder() {
386436
return builder;
387437
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@
2121
public final class CodegenExpressionBuidler {
2222
private final RuleSetExpression root;
2323
private final SymbolTable symbolTable;
24+
private final Map<String, ComputeScopeTree.Scope> scopesByName;
2425

25-
public CodegenExpressionBuidler(RuleSetExpression root, SymbolTable symbolTable) {
26+
public CodegenExpressionBuidler(
27+
RuleSetExpression root,
28+
SymbolTable symbolTable,
29+
Map<String, ComputeScopeTree.Scope> scopesByName
30+
) {
2631
this.root = root;
2732
this.symbolTable = symbolTable;
33+
this.scopesByName = scopesByName;
2834
}
2935

3036
public static CodegenExpressionBuidler from(RuleSetExpression root, RuleRuntimeTypeMirror typeMirror, SymbolTable table) {
@@ -36,10 +42,17 @@ public static CodegenExpressionBuidler from(RuleSetExpression root, RuleRuntimeT
3642
}
3743
table = assignTypesVisitor.symbolTable();
3844
root = assignIdentifier(root);
39-
PrepareForCodegenVisitor prepareForCodegenVisitor = new PrepareForCodegenVisitor(table);
40-
root = (RuleSetExpression) root.accept(prepareForCodegenVisitor);
41-
table = prepareForCodegenVisitor.symbolTable();
42-
return new CodegenExpressionBuidler(root, table);
45+
46+
RenameForCodegenVisitor renameForCodegenVisitor = new RenameForCodegenVisitor(table);
47+
root = (RuleSetExpression) root.accept(renameForCodegenVisitor);
48+
table = renameForCodegenVisitor.symbolTable();
49+
50+
ComputeScopeTree computeScopeTree = new ComputeScopeTree(table);
51+
root.accept(computeScopeTree);
52+
53+
PrepareForCodegenVisitor prepareForCodegenVisitor = new PrepareForCodegenVisitor();
54+
RuleSetExpression newRoot = (RuleSetExpression) root.accept(prepareForCodegenVisitor);
55+
return new CodegenExpressionBuidler(newRoot, table, computeScopeTree.scopesByName());
4356
}
4457

4558
private static RuleSetExpression assignIdentifier(RuleSetExpression root) {
@@ -51,27 +64,15 @@ public RuleSetExpression root() {
5164
return root;
5265
}
5366

54-
public boolean isParam(String name) {
55-
return symbolTable.isParam(name);
56-
}
57-
58-
public boolean isLocal(String name) {
59-
return symbolTable.isLocal(name);
60-
}
61-
6267
public String regionParamName() {
6368
return symbolTable.regionParamName();
6469
}
6570

66-
public Map<String, RuleType> locals() {
67-
return symbolTable.locals();
68-
}
69-
70-
public Map<String, RuleType> params() {
71-
return symbolTable.params();
72-
}
73-
7471
public SymbolTable symbolTable() {
7572
return symbolTable;
7673
}
74+
75+
public Map<String, ComputeScopeTree.Scope> scopesByName() {
76+
return scopesByName;
77+
}
7778
}

0 commit comments

Comments
 (0)