Skip to content

Commit 702b493

Browse files
committed
Improve footprint of unquickening data
1 parent 0cffc0d commit 702b493

File tree

6 files changed

+106
-93
lines changed

6 files changed

+106
-93
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,29 +1326,6 @@ private Source getSource() {
13261326
}
13271327
}
13281328

1329-
private void writeSparseTable(int[][] table) {
1330-
writeInt(table.length);
1331-
for (int i = 0; i < table.length; i++) {
1332-
if (table[i] != null && table[i].length > 0) {
1333-
writeInt(i);
1334-
writeIntArray(table[i]);
1335-
}
1336-
}
1337-
writeInt(-1);
1338-
}
1339-
1340-
private int[][] readSparseTable() {
1341-
int length = readInt();
1342-
int[][] table = new int[length][];
1343-
while (true) {
1344-
int i = readInt();
1345-
if (i == -1) {
1346-
return table;
1347-
}
1348-
table[i] = readIntArray();
1349-
}
1350-
}
1351-
13521329
private CodeUnit readCodeUnit() {
13531330
int codeUnitType = readByte();
13541331
return switch (codeUnitType) {
@@ -1396,12 +1373,15 @@ private BytecodeCodeUnit readBytecodeCodeUnit() {
13961373
int endColumn = readInt();
13971374
byte[] outputCanQuicken = readBytes();
13981375
byte[] variableShouldUnbox = readBytes();
1399-
int[][] generalizeInputsMap = readSparseTable();
1400-
int[][] generalizeVarsMap = readSparseTable();
1376+
int[] generalizeInputsKeys = readIntArray();
1377+
int[] generalizeInputsIndices = readIntArray();
1378+
int[] generalizeInputsValues = readIntArray();
1379+
int[] generalizeVarsIndices = readIntArray();
1380+
int[] generalizeVarsValues = readIntArray();
14011381
return new BytecodeCodeUnit(name, qualname, argCount, kwOnlyArgCount, positionalOnlyArgCount, flags, names, varnames,
14021382
cellvars, freevars, cell2arg, constants, startLine, startColumn, endLine, endColumn, code, srcOffsetTable,
14031383
primitiveConstants, exceptionHandlerRanges, stacksize, conditionProfileCount,
1404-
outputCanQuicken, variableShouldUnbox, generalizeInputsMap, generalizeVarsMap);
1384+
outputCanQuicken, variableShouldUnbox, generalizeInputsKeys, generalizeInputsIndices, generalizeInputsValues, generalizeVarsIndices, generalizeVarsValues);
14051385
}
14061386

14071387
private BytecodeDSLCodeUnit readBytecodeDSLCodeUnit() {
@@ -1478,8 +1458,11 @@ private void writeBytecodeCodeUnit(BytecodeCodeUnit code) throws IOException {
14781458
writeInt(code.endColumn);
14791459
writeBytes(code.outputCanQuicken);
14801460
writeBytes(code.variableShouldUnbox);
1481-
writeSparseTable(code.generalizeInputsMap);
1482-
writeSparseTable(code.generalizeVarsMap);
1461+
writeIntArray(code.generalizeInputsKeys);
1462+
writeIntArray(code.generalizeInputsIndices);
1463+
writeIntArray(code.generalizeInputsValues);
1464+
writeIntArray(code.generalizeVarsIndices);
1465+
writeIntArray(code.generalizeVarsValues);
14831466
}
14841467

14851468
@SuppressWarnings("unchecked")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/CodeNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ private RootCallTarget deserializeForBytecodeInterpreter(PythonLanguage language
175175
code.startColumn, code.endLine, code.endColumn, code.code, code.srcOffsetTable,
176176
code.primitiveConstants, code.exceptionHandlerRanges, code.stacksize, code.conditionProfileCount,
177177
code.outputCanQuicken, code.variableShouldUnbox,
178-
code.generalizeInputsMap, code.generalizeVarsMap);
178+
code.generalizeInputsKeys, code.generalizeInputsIndices, code.generalizeInputsValues, code.generalizeVarsIndices, code.generalizeVarsValues);
179179
}
180180
rootNode = PBytecodeRootNode.create(context.getLanguage(), code, new LazySource(PythonUtils.createFakeSource()), false);
181181
if (code.isGeneratorOrCoroutine()) {

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

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ public final class BytecodeCodeUnit extends CodeUnit {
7575
/* Quickening data. See docs in PBytecodeRootNode */
7676
@CompilationFinal(dimensions = 1) public final byte[] outputCanQuicken;
7777
@CompilationFinal(dimensions = 1) public final byte[] variableShouldUnbox;
78-
@CompilationFinal(dimensions = 1) public final int[][] generalizeInputsMap;
79-
@CompilationFinal(dimensions = 1) public final int[][] generalizeVarsMap;
78+
@CompilationFinal(dimensions = 1) public final int[] generalizeVarsIndices;
79+
@CompilationFinal(dimensions = 1) public final int[] generalizeVarsValues;
80+
// Which BCIs can trigger generalization. Used to binary search BCI index to the next array
81+
@CompilationFinal(dimensions = 1) public final int[] generalizeInputsKeys;
82+
// Start indices of generalizations in the next array. Has a sentinel value at the end
83+
@CompilationFinal(dimensions = 1) public final int[] generalizeInputsIndices;
84+
@CompilationFinal(dimensions = 1) public final int[] generalizeInputsValues;
8085

8186
/* Lazily initialized source map */
8287
@CompilationFinal SourceMap sourceMap;
@@ -88,7 +93,8 @@ public BytecodeCodeUnit(TruffleString name, TruffleString qualname,
8893
int endLine, int endColumn,
8994
byte[] code, byte[] linetable,
9095
long[] primitiveConstants, int[] exceptionHandlerRanges, int stacksize, int conditionProfileCount,
91-
byte[] outputCanQuicken, byte[] variableShouldUnbox, int[][] generalizeInputsMap, int[][] generalizeVarsMap) {
96+
byte[] outputCanQuicken, byte[] variableShouldUnbox, int[] generalizeInputsKeys, int[] generalizeInputsIndices, int[] generalizeInputsValues,
97+
int[] generalizeVarsIndices, int[] generalizeVarsValues) {
9298
super(name, qualname, argCount, kwOnlyArgCount, positionalOnlyArgCount, flags, names, varnames, cellvars, freevars, cell2arg, constants, startLine, startColumn, endLine, endColumn);
9399
this.code = code;
94100
this.srcOffsetTable = linetable;
@@ -98,8 +104,11 @@ public BytecodeCodeUnit(TruffleString name, TruffleString qualname,
98104
this.conditionProfileCount = conditionProfileCount;
99105
this.outputCanQuicken = outputCanQuicken;
100106
this.variableShouldUnbox = variableShouldUnbox;
101-
this.generalizeInputsMap = generalizeInputsMap;
102-
this.generalizeVarsMap = generalizeVarsMap;
107+
this.generalizeInputsKeys = generalizeInputsKeys;
108+
this.generalizeInputsIndices = generalizeInputsIndices;
109+
this.generalizeInputsValues = generalizeInputsValues;
110+
this.generalizeVarsIndices = generalizeVarsIndices;
111+
this.generalizeVarsValues = generalizeVarsValues;
103112
}
104113

105114
public SourceMap getSourceMap() {
@@ -124,6 +133,23 @@ public int bciToColumn(int bci) {
124133
return getSourceMap().startColumnMap[bci];
125134
}
126135

136+
public void generalizeInputs(int bci) {
137+
if (generalizeInputsKeys != null) {
138+
int key = Arrays.binarySearch(generalizeInputsKeys, bci);
139+
if (key >= 0) {
140+
int genStart = generalizeInputsIndices[key];
141+
int genEnd = generalizeInputsIndices[key + 1];
142+
for (int i = genStart; i < genEnd; i++) {
143+
int generalizeBci = generalizeInputsValues[i];
144+
OpCodes generalizeInstr = OpCodes.fromOpCode(code[generalizeBci]);
145+
if (generalizeInstr.generalizesTo != null) {
146+
code[generalizeBci] = (byte) generalizeInstr.generalizesTo.ordinal();
147+
}
148+
}
149+
}
150+
}
151+
}
152+
127153
@Override
128154
protected void dumpBytecode(StringBuilder sb, boolean quickened) {
129155
int bci = 0;
@@ -204,7 +230,7 @@ protected void dumpBytecode(StringBuilder sb, boolean quickened) {
204230
case MAKE_FUNCTION: {
205231
line[4] = String.format("% 2d", followingArgs[0]);
206232
CodeUnit codeUnit = (CodeUnit) constants[oparg];
207-
line[5] = line[5] = codeUnit.qualname.toJavaStringUncached();
233+
line[5] = codeUnit.qualname.toJavaStringUncached();
208234
break;
209235
}
210236
case MAKE_TYPE_PARAM:
@@ -345,27 +371,32 @@ protected void dumpBytecode(StringBuilder sb, boolean quickened) {
345371
}
346372
}
347373

374+
int generalizationIndex1 = 0;
348375
for (bci = 0; bci < code.length; bci++) {
349376
String[] line = lines.get(bci);
350377
if (line != null) {
351378
line[5] = line[5] == null ? "" : String.format("(%s)", line[5]);
352379
line[6] = line[6] == null ? "" : String.format("(%s)", line[6]);
353380
line[7] = "";
354-
if (outputCanQuicken != null && (outputCanQuicken[bci] != 0 || generalizeInputsMap[bci] != null)) {
381+
int generalizationIndex2 = -1;
382+
if (generalizeInputsKeys != null && generalizationIndex1 < generalizeInputsKeys.length && generalizeInputsKeys[generalizationIndex1] == bci) {
383+
generalizationIndex2 = generalizeInputsIndices[generalizationIndex1++];
384+
}
385+
if (outputCanQuicken != null && (outputCanQuicken[bci] != 0 || generalizationIndex2 >= 0)) {
355386
StringBuilder quickenSb = new StringBuilder();
356387
if (outputCanQuicken[bci] != 0) {
357388
quickenSb.append("can quicken");
358389
}
359-
if (generalizeInputsMap[bci] != null) {
360-
if (quickenSb.length() > 0) {
390+
if (generalizationIndex2 >= 0) {
391+
if (!quickenSb.isEmpty()) {
361392
quickenSb.append(", ");
362393
}
363394
quickenSb.append("generalizes: ");
364-
for (int i = 0; i < generalizeInputsMap[bci].length; i++) {
365-
if (i > 0) {
395+
for (int i = generalizationIndex2; i < generalizeInputsIndices[generalizationIndex1]; i++) {
396+
if (i > generalizationIndex2) {
366397
quickenSb.append(", ");
367398
}
368-
quickenSb.append(generalizeInputsMap[bci][i]);
399+
quickenSb.append(generalizeInputsValues[i]);
369400
}
370401
}
371402
line[7] = quickenSb.toString();

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

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,34 @@ public BytecodeCodeUnit assemble() {
275275
}
276276
}
277277

278+
int generizationListSize = 0;
279+
int totalGeneralizations = 0;
280+
for (Instruction insn : quickenedInstructions) {
281+
if (insn.quickeningGeneralizeList != null && !insn.quickeningGeneralizeList.isEmpty()) {
282+
generizationListSize++;
283+
totalGeneralizations += insn.quickeningGeneralizeList.size();
284+
}
285+
}
286+
int[] generalizeInputsKeys = generizationListSize > 0 ? new int[generizationListSize] : EMPTY_INT_ARRAY;
287+
int[] generalizeInputsIndices = generizationListSize > 0 ? new int[generizationListSize + 1] : EMPTY_INT_ARRAY;
288+
int[] generalizeInputsValues = generizationListSize > 0 ? new int[totalGeneralizations] : EMPTY_INT_ARRAY;
278289
byte[] finishedCanQuickenOutput = new byte[buf.size()];
279-
int[][] finishedGeneralizeInputsMap = new int[buf.size()][];
280-
int[][] finishedGeneralizeVarsMap = new int[varCount][];
290+
int generalizationIndex1 = 0;
291+
int generalizationIndex2 = 0;
281292
for (Instruction insn : quickenedInstructions) {
282293
int insnBodyBci = insn.bodyBci();
283294
finishedCanQuickenOutput[insnBodyBci] = insn.quickenOutput;
284-
if (insn.quickeningGeneralizeList != null && insn.quickeningGeneralizeList.size() > 0) {
285-
finishedGeneralizeInputsMap[insnBodyBci] = new int[insn.quickeningGeneralizeList.size()];
286-
for (int j = 0; j < finishedGeneralizeInputsMap[insnBodyBci].length; j++) {
295+
if (insn.quickeningGeneralizeList != null && !insn.quickeningGeneralizeList.isEmpty()) {
296+
generalizeInputsKeys[generalizationIndex1] = insnBodyBci;
297+
generalizeInputsIndices[generalizationIndex1] = generalizationIndex2;
298+
for (int j = 0; j < insn.quickeningGeneralizeList.size(); j++) {
287299
int bci = insn.quickeningGeneralizeList.get(j).bodyBci();
288300
assert bci >= 0;
289-
finishedGeneralizeInputsMap[insnBodyBci][j] = bci;
301+
generalizeInputsValues[generalizationIndex2++] = bci;
290302
}
303+
generalizationIndex1++;
291304
}
305+
generalizeInputsIndices[generizationListSize] = generalizationIndex2;
292306
}
293307
if (cell2arg != null) {
294308
for (int i = 0; i < cell2arg.length; i++) {
@@ -297,7 +311,9 @@ public BytecodeCodeUnit assemble() {
297311
}
298312
}
299313
}
300-
if (!scope.isGenerator()) {
314+
int[] generalizeVarsIndices = EMPTY_INT_ARRAY;
315+
int[] generalizeVarsValues = EMPTY_INT_ARRAY;
316+
if (!scope.isGenerator() && varCount > 0) {
301317
/*
302318
* We do an optimization in the interpreter that we don't unbox variables that would
303319
* mostly get boxed again. This helps for interpreter performance, but for compiled code
@@ -306,19 +322,26 @@ public BytecodeCodeUnit assemble() {
306322
* modes of usage (boxed vs unboxed) would be too complex, so we skip the optimization
307323
* there and unbox all variables.
308324
*/
325+
int totalVarsGeneralizations = 0;
309326
for (int i = 0; i < varCount; i++) {
310327
List<Instruction> stores = variableStores.get(i);
311-
if (!stores.isEmpty()) {
312-
finishedGeneralizeVarsMap[i] = new int[stores.size()];
328+
totalVarsGeneralizations += stores.size();
329+
}
330+
if (totalVarsGeneralizations > 0) {
331+
generalizeVarsIndices = new int[varCount + 1];
332+
generalizeVarsValues = new int[totalVarsGeneralizations];
333+
int generalizeVarsIndex = 0;
334+
for (int i = 0; i < varCount; i++) {
335+
List<Instruction> stores = variableStores.get(i);
336+
generalizeVarsIndices[i] = generalizeVarsIndex;
313337
for (int j = 0; j < stores.size(); j++) {
314-
finishedGeneralizeVarsMap[i][j] = stores.get(j).bodyBci();
338+
generalizeVarsValues[generalizeVarsIndex++] = stores.get(j).bodyBci();
339+
}
340+
if (boxingMetric[i] <= 0) {
341+
shouldUnboxVariable[i] = 0;
315342
}
316-
} else {
317-
finishedGeneralizeVarsMap[i] = EMPTY_INT_ARRAY;
318-
}
319-
if (boxingMetric[i] <= 0) {
320-
shouldUnboxVariable[i] = 0;
321343
}
344+
generalizeVarsIndices[varCount] = generalizeVarsIndex;
322345
}
323346
}
324347
return new BytecodeCodeUnit(toTruffleStringUncached(name), toTruffleStringUncached(qualName),
@@ -335,7 +358,7 @@ public BytecodeCodeUnit assemble() {
335358
buf.toByteArray(),
336359
sourceMapBuilder.build(),
337360
orderedLong(primitiveConstants), exceptionHandlerRanges, maxStackSize, conditionProfileCount,
338-
finishedCanQuickenOutput, shouldUnboxVariable, finishedGeneralizeInputsMap, finishedGeneralizeVarsMap);
361+
finishedCanQuickenOutput, shouldUnboxVariable, generalizeInputsKeys, generalizeInputsIndices, generalizeInputsValues, generalizeVarsIndices, generalizeVarsValues);
339362
}
340363

341364
private static void addExceptionRange(Collection<int[]> finishedExceptionHandlerRanges, int start, int end, int handler, int stackLevel) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@
227227
* Compiler for bytecode interpreter.
228228
*/
229229
public class Compiler implements SSTreeVisitor<Void> {
230-
public static final int BYTECODE_VERSION = 30;
230+
public static final int BYTECODE_VERSION = 31;
231231

232232
private final ParserCallbacks parserCallbacks;
233233

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -577,16 +577,6 @@ public final class PBytecodeRootNode extends PRootNode implements BytecodeOSRNod
577577
* determines the type like above.
578578
*/
579579
private final byte[] variableShouldUnbox;
580-
/**
581-
* Which instruction bci's have to be generalized when generalizing inputs of instruction at
582-
* given bci.
583-
*/
584-
private final int[][] generalizeInputsMap;
585-
/**
586-
* Which store instruction bci's have to be generalized when generalizing variable with given
587-
* index.
588-
*/
589-
private final int[][] generalizeVarsMap;
590580

591581
/*
592582
* Whether this variable should be unboxed in the interpreter. We unbox all variables in
@@ -708,8 +698,6 @@ private PBytecodeRootNode(PythonLanguage language, FrameDescriptor fd, Signature
708698
this.bytecode = co.code;
709699
this.outputCanQuicken = co.outputCanQuicken;
710700
this.variableShouldUnbox = co.variableShouldUnbox;
711-
this.generalizeInputsMap = co.generalizeInputsMap;
712-
this.generalizeVarsMap = co.generalizeVarsMap;
713701
this.consts = co.constants;
714702
this.longConsts = co.primitiveConstants;
715703
this.names = co.names;
@@ -4749,17 +4737,7 @@ private static byte stackSlotTypeToTypeId(VirtualFrame virtualFrame, int stackTo
47494737

47504738
private void generalizeInputs(int beginBci) {
47514739
CompilerAsserts.neverPartOfCompilation();
4752-
if (generalizeInputsMap != null) {
4753-
if (generalizeInputsMap[beginBci] != null) {
4754-
for (int i = 0; i < generalizeInputsMap[beginBci].length; i++) {
4755-
int generalizeBci = generalizeInputsMap[beginBci][i];
4756-
OpCodes generalizeInstr = OpCodes.fromOpCode(bytecode[generalizeBci]);
4757-
if (generalizeInstr.generalizesTo != null) {
4758-
bytecode[generalizeBci] = (byte) generalizeInstr.generalizesTo.ordinal();
4759-
}
4760-
}
4761-
}
4762-
}
4740+
co.generalizeInputs(beginBci);
47634741
}
47644742

47654743
/**
@@ -4783,18 +4761,16 @@ private void generalizeInputs(int beginBci) {
47834761
private void generalizeVariableStores(int index) {
47844762
CompilerDirectives.transferToInterpreterAndInvalidate();
47854763
variableTypes[index] = QuickeningTypes.OBJECT;
4786-
if (generalizeVarsMap != null) {
4787-
if (generalizeVarsMap[index] != null) {
4788-
for (int i = 0; i < generalizeVarsMap[index].length; i++) {
4789-
int generalizeBci = generalizeVarsMap[index][i];
4790-
/*
4791-
* Keep unadapted stores as they are because we don't know how to generalize
4792-
* their unadapted inputs. They will adapt to object once executed.
4793-
*/
4794-
if (bytecode[generalizeBci] != OpCodesConstants.STORE_FAST) {
4795-
generalizeInputs(generalizeBci);
4796-
bytecode[generalizeBci] = OpCodesConstants.STORE_FAST_O;
4797-
}
4764+
if (co.generalizeVarsIndices != null && index + 1 < co.generalizeVarsIndices.length) {
4765+
for (int i = co.generalizeVarsIndices[index]; i < co.generalizeVarsIndices[index + 1]; i++) {
4766+
int generalizeBci = co.generalizeVarsValues[i];
4767+
/*
4768+
* Keep unadapted stores as they are because we don't know how to generalize their
4769+
* unadapted inputs. They will adapt to object once executed.
4770+
*/
4771+
if (bytecode[generalizeBci] != OpCodesConstants.STORE_FAST) {
4772+
generalizeInputs(generalizeBci);
4773+
bytecode[generalizeBci] = OpCodesConstants.STORE_FAST_O;
47984774
}
47994775
}
48004776
}

0 commit comments

Comments
 (0)