Skip to content

Commit fd7647d

Browse files
committed
Compile simple kwargs as a direct operand of call
This confirms and compiles symbol-only, simple keyword arguments as a direct operand of the call, to allow downstream optimizations to prepare those keyword arguments in an appropriate way. Normal literal hashes and any keyword-like hashes with splats are compiled as before, with the Hash being built and stored and then loaded when the argument list is being built. Keyword hashes that are simple avoid the copy so they are associated directly with the call. Order continues to be preserved for the values of the simple kwargs hash, but the hash itself with its literal keys and any literal values are now both an operand of and metadata for the call.
1 parent a322ab5 commit fd7647d

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

core/src/main/java/org/jruby/ir/builder/IRBuilderAST.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,8 +2320,19 @@ Operand buildGlobalVar(Variable result, GlobalVarNode node) {
23202320
}
23212321

23222322
public Operand buildHash(HashNode hashNode) {
2323+
if (hashNode.isLiteral() || hashNode.hasRestKwarg()) {
2324+
// not kwargs or non-simple kwargs, build as a normal Hash
2325+
return buildLiteralHash(hashNode);
2326+
}
2327+
2328+
// simple kwargs, build as KeywordHash
2329+
return buildKeywordHash(hashNode);
2330+
}
2331+
2332+
private Variable buildLiteralHash(HashNode hashNode) {
23232333
List<KeyValuePair<Operand, Operand>> args = new ArrayList<>(1);
23242334
boolean hasAssignments = hashNode.containsVariableAssignment();
2335+
23252336
Variable hash = null;
23262337
// Duplication checks happen when **{} are literals and not **h variable references.
23272338
Operand duplicateCheck = fals();
@@ -2360,6 +2371,20 @@ public Operand buildHash(HashNode hashNode) {
23602371
return hash;
23612372
}
23622373

2374+
public Operand buildKeywordHash(HashNode hashNode) {
2375+
List<KeyValuePair<Operand, Operand>> args = new ArrayList<>(1);
2376+
boolean hasAssignments = hashNode.containsVariableAssignment();
2377+
2378+
for (KeyValuePair<Node, Node> pair: hashNode.getPairs()) {
2379+
Node key = pair.getKey();
2380+
assert key instanceof SymbolNode : "simple kwargs should only have symbol keys";
2381+
2382+
args.add(new KeyValuePair<>(buildSymbol((SymbolNode) key), buildWithOrder(pair.getValue(), hasAssignments)));
2383+
}
2384+
2385+
return new Hash(args, true);
2386+
}
2387+
23632388
public Operand buildIf(Variable result, final IfNode ifNode) {
23642389
return buildConditional(result, ifNode.getCondition(), ifNode.getThenBody(), ifNode.getElseBody());
23652390
}

core/src/main/java/org/jruby/ir/operands/Hash.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,25 @@
2828
// that actually build the hash
2929
public class Hash extends Operand {
3030
public final KeyValuePair<Operand, Operand>[] pairs;
31+
public final boolean keywords;
3132

3233
public Hash(List<KeyValuePair<Operand, Operand>> pairs) {
33-
this(pairs.toArray(new KeyValuePair[pairs.size()]));
34+
this(pairs, false);
35+
}
36+
37+
public Hash(List<KeyValuePair<Operand, Operand>> pairs, boolean keywords) {
38+
this(pairs.toArray(new KeyValuePair[pairs.size()]), keywords);
3439
}
3540

3641
protected Hash(KeyValuePair<Operand, Operand>[] pairs) {
42+
this(pairs, false);
43+
}
44+
45+
protected Hash(KeyValuePair<Operand, Operand>[] pairs, boolean keywords) {
3746
super();
3847

3948
this.pairs = pairs;
49+
this.keywords = keywords;
4050
}
4151

4252
@Override

0 commit comments

Comments
 (0)