Skip to content

Commit 88eeb49

Browse files
committed
OptimizeTempVarsPass is now just a collection of static methods and not inheriting from CompilerPass.
clonedInstrs is no longer a field in IRScope and is a local in prepareFullBuildCommon.
1 parent 0dbe1b2 commit 88eeb49

File tree

3 files changed

+32
-58
lines changed

3 files changed

+32
-58
lines changed

core/src/main/java/org/jruby/ir/IRManager.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.EnumSet;
44
import org.jruby.RubyInstanceConfig;
5+
import org.jruby.ir.instructions.Instr;
56
import org.jruby.ir.listeners.IRScopeListener;
67
import org.jruby.ir.listeners.InstructionsListener;
78
import org.jruby.ir.operands.*;
@@ -31,7 +32,6 @@ public class IRManager {
3132

3233
private final CompilerPass deadCodeEliminationPass = new DeadCodeElimination();
3334
private final CompilerPass optimizeDynScopesPass = new OptimizeDynScopesPass();
34-
private final CompilerPass optimizeTempVarsPass = new OptimizeTempVarsPass();
3535
private final CompilerPass optimizeDelegationPass = new OptimizeDelegationPass();
3636

3737
private int dummyMetaClassCount = 0;
@@ -219,9 +219,9 @@ public TemporaryLocalVariable newTemporaryLocalVariable(int index) {
219219
return tempVar;
220220
}
221221

222-
public void optimizeTemporaryVariablesIfEnabled(IRScope scope) {
222+
public Instr[] optimizeTemporaryVariablesIfEnabled(IRScope scope, Instr[] instrs) {
223223
// FIXME: Make this check ir.passes and not run if ir.passes is set and does not contain opttempvars.
224-
optimizeTempVarsPass.run(scope);
224+
return OptimizeTempVarsPass.optimizeTmpVars(scope, instrs);
225225
}
226226

227227
/**

core/src/main/java/org/jruby/ir/IRScope.java

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ public abstract class IRScope implements ParseResult {
9696
/** -X-C full interpretation OR JIT depends on this */
9797
protected FullInterpreterContext fullInterpreterContext;
9898

99-
private Instr[] clonedInstrs = null;
100-
10199
protected int temporaryVariableIndex;
102100
protected int floatVariableIndex;
103101
protected int fixnumVariableIndex;
@@ -447,40 +445,31 @@ public InterpreterContext allocateInterpreterContext(List<Instr> instructions) {
447445
return interpreterContext;
448446
}
449447

450-
protected void cloneInstrs() {
451-
cloneInstrs(new SimpleCloneInfo(this, false));
452-
}
448+
private Instr[] cloneInstrs() {
449+
SimpleCloneInfo cloneInfo = new SimpleCloneInfo(this, false);
453450

454-
public void cloneInstrs(SimpleCloneInfo cloneInfo) {
455451
Instr[] instructions = interpreterContext.getInstructions();
456452
int length = instructions.length;
457-
setClonedInstrs(new Instr[length]);
453+
Instr[] newInstructions = new Instr[length];
458454

459455
for (int i = 0; i < length; i++) {
460-
clonedInstrs[i] = instructions[i].clone(cloneInfo);
456+
newInstructions[i] = instructions[i].clone(cloneInfo);
461457
}
462458

463-
for (IRClosure cl: getClosures()) {
464-
// Closure may have independently been promoted to full build already
465-
if (cl.fullInterpreterContext == null) {
466-
cl.cloneInstrs(cloneInfo.cloneForCloningClosure(cl));
467-
}
468-
}
459+
return newInstructions;
469460
}
470461

471462
protected void prepareFullBuildCommon() {
472463
// Clone instrs from startup interpreter so we do not swap out instrs out from under the
473464
// startup interpreter as we are building the full interpreter.
474-
cloneInstrs();
465+
Instr[] instrs = cloneInstrs();
475466

476467
// This is a complicating pseudo-pass which needs to be run before CFG is generated. This
477468
// necessitates us needing a clonedInstrs field on IRScope. If we can rewrite this to a full
478469
// CFG using pass we can eliminate this intermediate save and field.
479-
getManager().optimizeTemporaryVariablesIfEnabled(this);
470+
instrs = getManager().optimizeTemporaryVariablesIfEnabled(this, instrs);
480471

481-
fullInterpreterContext = new FullInterpreterContext(this, clonedInstrs);
482-
483-
setClonedInstrs(null); // boo. vestigial temporal field...because of opt tmp vars pass.
472+
fullInterpreterContext = new FullInterpreterContext(this, instrs);
484473
}
485474
/**
486475
* This initializes a more complete(full) InterpreterContext which if used in mixed mode will be
@@ -1036,12 +1025,4 @@ public void savePersistenceInfo(int offset, IRReaderDecoder file) {
10361025
// instructionsOffsetInfoPersistenceBuffer = offset;
10371026
// persistenceStore = file;
10381027
}
1039-
1040-
public Instr[] getClonedInstrs() {
1041-
return clonedInstrs;
1042-
}
1043-
1044-
public void setClonedInstrs(Instr[] clonedInstrs) {
1045-
this.clonedInstrs = clonedInstrs;
1046-
}
10471028
}

core/src/main/java/org/jruby/ir/passes/OptimizeTempVarsPass.java

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,28 @@
11
package org.jruby.ir.passes;
22

3-
import org.jruby.ir.IRClosure;
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.ListIterator;
8+
import java.util.Map;
49
import org.jruby.ir.IRScope;
510
import org.jruby.ir.instructions.*;
611
import org.jruby.ir.operands.ImmutableLiteral;
712
import org.jruby.ir.operands.Operand;
813
import org.jruby.ir.operands.TemporaryVariable;
914
import org.jruby.ir.operands.Variable;
1015

11-
import java.util.*;
12-
13-
public class OptimizeTempVarsPass extends CompilerPass {
14-
@Override
15-
public String getLabel() {
16-
return "Temporary Variable Reduction";
17-
}
18-
19-
@Override
20-
public Object execute(IRScope s, Object... data) {
21-
optimizeTmpVars(s);
22-
23-
return null;
24-
}
25-
26-
@Override
27-
public boolean invalidate(IRScope s) {
28-
// This runs after IR is built and before CFG is built.
29-
// Not reversible in the form it is written right now.
30-
return false;
31-
}
3216

17+
/**
18+
* Takes multiple single def-use temporary variables and reduces them to share the same temp variable.
19+
* This ends up reducing the amount of allocation and most likely helps hotspot warm up in some way quicker.
20+
*
21+
* This traditionally was a compiler pass (extends CompilerPass) but it is special in that it is the only
22+
* pass which does not require any supplementary datastructures. In fact, it cannot be run by the time
23+
* a CFG is created. So it was de-CompilerPassed and called directly.
24+
*/
25+
public class OptimizeTempVarsPass {
3326
private static void allocVar(Operand oldVar, IRScope s, List<TemporaryVariable> freeVarsList, Map<Operand, Operand> newVarMap) {
3427
// If we dont have a var mapping, get a new var -- try the free list first
3528
// and if none available, allocate a fresh one
@@ -43,8 +36,8 @@ private static void freeVar(TemporaryVariable newVar, List<TemporaryVariable> fr
4336
if (!freeVarsList.contains(newVar)) freeVarsList.add(0, newVar);
4437
}
4538

46-
private static void optimizeTmpVars(IRScope s) {
47-
List<Instr> instructions = new ArrayList<>(Arrays.asList(s.getClonedInstrs()));
39+
public static Instr[] optimizeTmpVars(IRScope s, Instr[] initialInstrs) {
40+
List<Instr> instructions = new ArrayList<>(Arrays.asList(initialInstrs));
4841

4942
// Pass 1: Analyze instructions and find use and def count of temporary variables
5043
Map<TemporaryVariable, Instr> tmpVarUses = new HashMap<>();
@@ -208,7 +201,7 @@ else if (i instanceof CopyInstr) {
208201
//
209202
// NOTE: It is sufficient to just track last use for renaming purposes.
210203
// At the first definition, we allocate a variable which then starts the live range
211-
Map<TemporaryVariable, Integer> lastVarUseOrDef = new HashMap<TemporaryVariable, Integer>();
204+
Map<TemporaryVariable, Integer> lastVarUseOrDef = new HashMap<>();
212205
int iCount = -1;
213206
for (Instr i: instructions) {
214207
iCount++;
@@ -238,8 +231,8 @@ else if (i instanceof CopyInstr) {
238231
// Pass 4: Reallocate temporaries based on last uses to minimize # of unique vars.
239232
// Replace all single use operands with constants they were assigned to.
240233
// Using operand -> operand signature because simplifyOperands works on operands
241-
Map<Operand, Operand> newVarMap = new HashMap<Operand, Operand>();
242-
List<TemporaryVariable> freeVarsList = new ArrayList<TemporaryVariable>();
234+
Map<Operand, Operand> newVarMap = new HashMap<>();
235+
List<TemporaryVariable> freeVarsList = new ArrayList<>();
243236
iCount = -1;
244237
s.resetTemporaryVariables();
245238

@@ -273,6 +266,6 @@ else if (i instanceof CopyInstr) {
273266

274267
Instr[] newInstrs = new Instr[instructions.size()];
275268
instructions.toArray(newInstrs);
276-
s.setClonedInstrs(newInstrs);
269+
return newInstrs;
277270
}
278271
}

0 commit comments

Comments
 (0)