Skip to content

Commit da2dcd1

Browse files
committed
Unbox boxed variables in compiled code
1 parent 2f01c2e commit da2dcd1

File tree

3 files changed

+225
-50
lines changed

3 files changed

+225
-50
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/CompilationUnit.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ public CodeUnit assemble() {
206206
}
207207
int[] boxingMetric = new int[varCount];
208208
byte[] shouldUnboxVariable = new byte[varCount];
209+
Arrays.fill(shouldUnboxVariable, (byte) 0xff);
209210

210211
SortedSet<int[]> finishedExceptionHandlerRanges = new TreeSet<>(Comparator.comparingInt(a -> a[0]));
211212

@@ -243,7 +244,6 @@ public CodeUnit assemble() {
243244
if (i.opcode == OpCodes.STORE_FAST) {
244245
variableStores.get(i.arg).add(i);
245246
} else if (i.opcode == OpCodes.LOAD_FAST) {
246-
shouldUnboxVariable[i.arg] |= i.quickenOutput;
247247
boxingMetric[i.arg] += i.quickenOutput != 0 ? 1 : -1;
248248
}
249249
i.bci = buf.size();
@@ -296,14 +296,24 @@ public CodeUnit assemble() {
296296
}
297297
}
298298
}
299-
for (int i = 0; i < varCount; i++) {
300-
List<Instruction> stores = variableStores.get(i);
301-
finishedGeneralizeVarsMap[i] = new int[stores.size()];
302-
for (int j = 0; j < stores.size(); j++) {
303-
finishedGeneralizeVarsMap[i][j] = stores.get(j).bci;
304-
}
305-
if (boxingMetric[i] <= 0) {
306-
shouldUnboxVariable[i] = 0;
299+
if (!scope.isGenerator()) {
300+
/*
301+
* We do an optimization in the interpreter that we don't unbox variables that would
302+
* mostly get boxed again. This helps for interpreter performance, but for compiled code
303+
* we have to unbox all variables otherwise the compiler is not always able to prove the
304+
* variable was initialized. In generators, transferring the variables between the two
305+
* modes of usage (boxed vs unboxed) would be too complex, so we skip the optimization
306+
* there and unbox all variables.
307+
*/
308+
for (int i = 0; i < varCount; i++) {
309+
List<Instruction> stores = variableStores.get(i);
310+
finishedGeneralizeVarsMap[i] = new int[stores.size()];
311+
for (int j = 0; j < stores.size(); j++) {
312+
finishedGeneralizeVarsMap[i][j] = stores.get(j).bci;
313+
}
314+
if (boxingMetric[i] <= 0) {
315+
shouldUnboxVariable[i] = 0;
316+
}
307317
}
308318
}
309319
return new CodeUnit(toTruffleStringUncached(name), toTruffleStringUncached(qualName),

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/OpCodes.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,10 @@ public enum OpCodes {
681681
LOAD_FAST_B(LOAD_FAST, 0, QuickeningTypes.BOOLEAN, LOAD_FAST_B_BOX),
682682
STORE_FAST_O(STORE_FAST, QuickeningTypes.OBJECT, 0),
683683
STORE_FAST_UNBOX_I(STORE_FAST, QuickeningTypes.OBJECT, 0),
684+
STORE_FAST_BOXED_I(STORE_FAST, QuickeningTypes.OBJECT, 0),
684685
STORE_FAST_I(STORE_FAST, QuickeningTypes.INT, 0),
685686
STORE_FAST_UNBOX_B(STORE_FAST, QuickeningTypes.OBJECT, 0),
687+
STORE_FAST_BOXED_B(STORE_FAST, QuickeningTypes.OBJECT, 0),
686688
STORE_FAST_B(STORE_FAST, QuickeningTypes.BOOLEAN, 0),
687689
UNARY_OP_O_O(UNARY_OP, QuickeningTypes.OBJECT, QuickeningTypes.OBJECT),
688690
UNARY_OP_I_O(UNARY_OP, QuickeningTypes.INT, QuickeningTypes.OBJECT),

0 commit comments

Comments
 (0)