Skip to content

Commit 4fd1847

Browse files
committed
Fragment size calculator
1 parent aa3dd30 commit 4fd1847

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

src/vm/jvm/runtime/org/perl6/nqp/jast2bc/AutosplitMethodWriter.java

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ public void visitEnd() {
9393
getTypes();
9494
getBaselineSize();
9595

96+
if (DEBUG_CONTROL) {
97+
for (int i = 1; i <= insnList.length; i++)
98+
System.out.printf("from=%d to=%d frag=%d\n", 0,i,calcFragmentSize(0, i));
99+
}
100+
96101
System.exit(1);
97102
}
98103

@@ -872,4 +877,183 @@ private void getBaselineSize() {
872877

873878
if (DEBUG_CONTROL) System.out.println(Arrays.toString(baselineSize));
874879
}
880+
881+
private int calcFragmentSize(int from, int to) {
882+
// we have to include the instructions
883+
int size = baselineSize[to] - baselineSize[from];
884+
885+
// need to include entry trampolines and exit trampolines
886+
int[] entryPts = new int[to-from];
887+
int entryCt = 0;
888+
boolean[] entryDedup = new boolean[to-from];
889+
int[] exitPts = new int[insnList.length];
890+
int exitCt = 0;
891+
boolean[] exitDedup = new boolean[insnList.length];
892+
893+
for (ControlEdge ce : controlEdges) {
894+
boolean from_this = (ce.from >= from && ce.from < to);
895+
boolean to_this = (ce.to >= from && ce.to < to);
896+
if (!from_this && to_this && !entryDedup[ce.to-from]) {
897+
entryDedup[ce.to-from] = true;
898+
entryPts[entryCt++] = ce.to;
899+
}
900+
if (from_this && !to_this && !exitDedup[ce.to]) {
901+
exitDedup[ce.to] = true;
902+
exitPts[exitCt++] = ce.to;
903+
}
904+
}
905+
906+
if (from == 0 && !entryDedup[0]) {
907+
entryPts[entryCt++] = 0;
908+
}
909+
910+
if (DEBUG_CONTROL) {
911+
System.out.printf("NONLOCAL ENTRY: %s\n", Arrays.toString(Arrays.copyOfRange(entryPts,0,entryCt)));
912+
System.out.printf("NONLOCAL EXIT: %s\n", Arrays.toString(Arrays.copyOfRange(exitPts,0,exitCt)));
913+
}
914+
915+
// factor out commonalities from the trampolines
916+
String[] commonEntry = commonTrampoline(entryPts, entryCt);
917+
String[] commonExit = commonTrampoline(exitPts, exitCt);
918+
919+
// common entry code
920+
// aload; {dup; ipush; aaload; UNBOX; xstore; }; iload; tableswitch
921+
922+
size++;
923+
for (int i = 0; i < commonEntry.length; i++) {
924+
size += localEntrySize(i, commonEntry[i]);
925+
}
926+
size += 13; // iload+tswitch
927+
928+
// uncommon entry code
929+
930+
for (int i = 0; i < entryCt; i++) {
931+
size += 4; // dispatch vector
932+
Frame f = types[entryPts[i]];
933+
for (int j = 0; j < f.sp; j++) {
934+
if (j < commonEntry.length && commonEntry[j].equals(f.stack[j])) {
935+
/* no action */
936+
} else if (j < nlocal) {
937+
size += localEntrySize(j, f.stack[j]);
938+
} else {
939+
size += stackEntrySize(j, f.stack[j]);
940+
}
941+
}
942+
size += 4; // astore
943+
size += 5; // final jump
944+
}
945+
946+
// jump insertion
947+
size += 3;
948+
949+
// uncommon exit code
950+
for (int i = 0; i < exitCt; i++) {
951+
Frame f = types[exitPts[i]];
952+
for (int j = 0; j < f.sp; j++) {
953+
if (j < commonExit.length && commonExit[j].equals(f.stack[j])) {
954+
/* no action */
955+
} else if (j < nlocal) {
956+
size += localExitSize(j, f.stack[j]);
957+
} else {
958+
size += stackExitSize(j, f.stack[j]);
959+
}
960+
}
961+
size += 3; // ipush
962+
size += 5; // jump to combiner
963+
}
964+
965+
// common exit code
966+
size += 4; // aload
967+
for (int i = 0; i < commonExit.length; i++) {
968+
size += localExitSize(i, commonExit[i]);
969+
}
970+
size += 2; // pop; ireturn
971+
972+
return size;
973+
}
974+
975+
private int localEntrySize(int loc, String desc) {
976+
char c0 = desc.charAt(0);
977+
if (c0 == 'T') return 0; // not loaded
978+
int sz;
979+
switch (c0) {
980+
case '0':
981+
case 'U':
982+
// just load as a null
983+
sz = 1;
984+
break;
985+
case 'L':
986+
case '[':
987+
// dup, ipush, aaload, checkcast
988+
sz = (loc < 128) ? 7 : 8;
989+
break;
990+
default:
991+
// dup, ipush, aaload, checkcast, fooValue
992+
sz = (loc < 128) ? 10 : 11;
993+
break;
994+
}
995+
return sz + ((loc < 256) ? 2 : 4);
996+
}
997+
998+
private int localExitSize(int loc, String desc) {
999+
char c0 = desc.charAt(0);
1000+
if (c0 == 'T' || c0 == '0' || c0 == 'U') return 0; // not saved
1001+
int sz = (loc < 256) ? 2 : 4;
1002+
switch (c0) {
1003+
case 'L':
1004+
case '[':
1005+
// dup, ipush, xload, aastore
1006+
return sz + ((loc < 128) ? 4 : 5);
1007+
default:
1008+
// dup, ipush, new, dup, xload, invokespecial, aastore
1009+
return sz + ((loc < 128) ? 11 : 12);
1010+
}
1011+
}
1012+
1013+
private int stackEntrySize(int loc, String desc) {
1014+
char c0 = desc.charAt(0);
1015+
switch (c0) {
1016+
case '0':
1017+
case 'U':
1018+
// just load as a null
1019+
return 1;
1020+
case 'L':
1021+
case '[':
1022+
// aload, ipush, aaload, checkcast
1023+
return (loc < 128) ? 10 : 11;
1024+
default:
1025+
// aload, ipush, aaload, checkcast, fooValue
1026+
return (loc < 128) ? 13 : 14;
1027+
}
1028+
}
1029+
1030+
private int stackExitSize(int loc, String desc) {
1031+
char c0 = desc.charAt(0);
1032+
if (c0 == 'T' || c0 == '0' || c0 == 'U') return 1; // not saved
1033+
switch (c0) {
1034+
case 'L':
1035+
case '[':
1036+
// xstore, aload, ipush, xload, aastore
1037+
return (loc < 128) ? 15 : 16;
1038+
default:
1039+
// xstore, aload, ipush, new, dup, xload, invokespecial, aastore
1040+
return (loc < 128) ? 22 : 23;
1041+
}
1042+
}
1043+
1044+
private String[] commonTrampoline(int[] points, int ct) {
1045+
String[] common = null;
1046+
for (int i = 0; i < ct; i++) {
1047+
Frame f = types[points[i]];
1048+
if (common == null) {
1049+
common = Arrays.copyOf(f.stack, nlocal);
1050+
} else {
1051+
for (int j = 0; j < common.length; j++) {
1052+
if (j >= f.sp || !f.stack[j].equals(common[j]))
1053+
common[j] = "T";
1054+
}
1055+
}
1056+
}
1057+
return common == null ? new String[] { } : common;
1058+
}
8751059
}

0 commit comments

Comments
 (0)