Skip to content

Commit 7b35e4f

Browse files
Optimize BytecodeTranslator for barebone C methods
- Implemented `checkBarebone` to identify simple methods (no sync, native, exceptions, allocations). - Modified `BytecodeMethod` to skip `DEFINE_METHOD_STACK` and other VM overhead for barebone methods. - Updated variable generation to use `olocals_`/`ilocals_` directly. - Updated `BasicInstruction` to use direct C `return` instead of `releaseForReturn` macros. - Added safety check to prevent optimization if internal locals exist but debug info is missing.
1 parent bd5b84c commit 7b35e4f

File tree

4 files changed

+252
-37
lines changed

4 files changed

+252
-37
lines changed

vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java

Lines changed: 190 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public static void setDependencyGraph(MethodDependencyGraph dependencyGraph) {
106106
private final static Set<String> virtualMethodsInvoked = new TreeSet<String>();
107107
private String desc;
108108
private boolean eliminated;
109+
private boolean barebone;
109110

110111

111112
static boolean optimizerOn;
@@ -115,6 +116,150 @@ public static void setDependencyGraph(MethodDependencyGraph dependencyGraph) {
115116
optimizerOn = op == null || op.equalsIgnoreCase("on");
116117
//optimizerOn = false;
117118
}
119+
120+
public boolean isBarebone() {
121+
return barebone;
122+
}
123+
124+
private boolean checkBarebone() {
125+
if(synchronizedMethod || nativeMethod || hasExceptionHandlingOrMethodCalls() || localVariables.size() > 0) {
126+
return false;
127+
}
128+
int argSlots = 0;
129+
if(!staticMethod) {
130+
argSlots++;
131+
}
132+
for(ByteCodeMethodArg arg : arguments) {
133+
argSlots++;
134+
if(arg.isDoubleOrLong()) {
135+
argSlots++;
136+
}
137+
}
138+
if(maxLocals > argSlots) {
139+
return false;
140+
}
141+
for(Instruction i : instructions) {
142+
if(i instanceof LabelInstruction || i instanceof LineNumber || i instanceof IInc ||
143+
i instanceof Jump || i instanceof CustomJump || i instanceof LocalVariable) {
144+
continue;
145+
}
146+
if(i instanceof BasicInstruction) {
147+
int op = i.getOpcode();
148+
switch(op) {
149+
case Opcodes.SIPUSH:
150+
case Opcodes.BIPUSH:
151+
case Opcodes.ICONST_0:
152+
case Opcodes.ICONST_1:
153+
case Opcodes.ICONST_2:
154+
case Opcodes.ICONST_3:
155+
case Opcodes.ICONST_4:
156+
case Opcodes.ICONST_5:
157+
case Opcodes.ICONST_M1:
158+
case Opcodes.LCONST_0:
159+
case Opcodes.LCONST_1:
160+
case Opcodes.FCONST_0:
161+
case Opcodes.FCONST_1:
162+
case Opcodes.FCONST_2:
163+
case Opcodes.DCONST_0:
164+
case Opcodes.DCONST_1:
165+
case Opcodes.RETURN:
166+
case Opcodes.IRETURN:
167+
case Opcodes.LRETURN:
168+
case Opcodes.FRETURN:
169+
case Opcodes.DRETURN:
170+
case Opcodes.ARETURN:
171+
case Opcodes.NOP:
172+
case Opcodes.POP:
173+
case Opcodes.POP2:
174+
case Opcodes.DUP:
175+
case Opcodes.DUP2:
176+
case Opcodes.DUP_X1:
177+
case Opcodes.DUP2_X1:
178+
case Opcodes.DUP_X2:
179+
case Opcodes.DUP2_X2:
180+
case Opcodes.SWAP:
181+
case Opcodes.IADD:
182+
case Opcodes.LADD:
183+
case Opcodes.FADD:
184+
case Opcodes.DADD:
185+
case Opcodes.ISUB:
186+
case Opcodes.LSUB:
187+
case Opcodes.FSUB:
188+
case Opcodes.DSUB:
189+
case Opcodes.IMUL:
190+
case Opcodes.LMUL:
191+
case Opcodes.FMUL:
192+
case Opcodes.DMUL:
193+
case Opcodes.IDIV:
194+
case Opcodes.LDIV:
195+
case Opcodes.FDIV:
196+
case Opcodes.DDIV:
197+
case Opcodes.IREM:
198+
case Opcodes.LREM:
199+
case Opcodes.FREM:
200+
case Opcodes.DREM:
201+
case Opcodes.INEG:
202+
case Opcodes.LNEG:
203+
case Opcodes.FNEG:
204+
case Opcodes.DNEG:
205+
case Opcodes.ISHL:
206+
case Opcodes.LSHL:
207+
case Opcodes.ISHR:
208+
case Opcodes.LSHR:
209+
case Opcodes.IUSHR:
210+
case Opcodes.LUSHR:
211+
case Opcodes.IAND:
212+
case Opcodes.LAND:
213+
case Opcodes.IOR:
214+
case Opcodes.LOR:
215+
case Opcodes.IXOR:
216+
case Opcodes.LXOR:
217+
case Opcodes.I2L:
218+
case Opcodes.I2F:
219+
case Opcodes.I2D:
220+
case Opcodes.L2I:
221+
case Opcodes.L2F:
222+
case Opcodes.L2D:
223+
case Opcodes.F2I:
224+
case Opcodes.F2L:
225+
case Opcodes.F2D:
226+
case Opcodes.D2I:
227+
case Opcodes.D2L:
228+
case Opcodes.D2F:
229+
case Opcodes.I2B:
230+
case Opcodes.I2C:
231+
case Opcodes.I2S:
232+
case Opcodes.LCMP:
233+
case Opcodes.FCMPG:
234+
case Opcodes.FCMPL:
235+
case Opcodes.DCMPL:
236+
case Opcodes.DCMPG:
237+
continue;
238+
}
239+
return false;
240+
}
241+
if(i instanceof VarOp) {
242+
continue;
243+
}
244+
if(i instanceof ArithmeticExpression) {
245+
continue;
246+
}
247+
if(i instanceof Field) {
248+
int op = i.getOpcode();
249+
if(op == Opcodes.GETFIELD) {
250+
continue;
251+
}
252+
if(op == Opcodes.PUTFIELD) {
253+
if(((Field)i).isObject()) {
254+
return false;
255+
}
256+
continue;
257+
}
258+
}
259+
return false;
260+
}
261+
return true;
262+
}
118263

119264
public BytecodeMethod(String clsName, int access, String name, String desc, String signature, String[] exceptions) {
120265
methodName = name;
@@ -626,10 +771,11 @@ public void appendMethodC(StringBuilder b) {
626771
}
627772

628773
if(hasInstructions) {
774+
barebone = checkBarebone();
629775
Set<String> added = new HashSet<String>();
630776
for (LocalVariable lv : localVariables) {
631777
String variableName = lv.getQualifier() + "locals_"+lv.getIndex()+"_";
632-
if (!added.contains(variableName) && lv.getQualifier() != 'o') {
778+
if (!added.contains(variableName) && (barebone || lv.getQualifier() != 'o')) {
633779
added.add(variableName);
634780
b.append(" volatile ");
635781
switch (lv.getQualifier()) {
@@ -641,30 +787,36 @@ public void appendMethodC(StringBuilder b) {
641787
b.append("JAVA_FLOAT"); break;
642788
case 'd' :
643789
b.append("JAVA_DOUBLE"); break;
790+
case 'o' :
791+
b.append("JAVA_OBJECT"); break;
644792
}
645793
b.append(" ").append(lv.getQualifier()).append("locals_").append(lv.getIndex()).append("_ = 0; /* ").append(lv.getOrigName()).append(" */\n");
646794
}
647795
}
648796

649-
if(staticMethod) {
650-
if(methodName.equals("__CLINIT__")) {
651-
b.append(" DEFINE_METHOD_STACK(");
797+
if(!barebone) {
798+
if(staticMethod) {
799+
if(methodName.equals("__CLINIT__")) {
800+
b.append(" DEFINE_METHOD_STACK(");
801+
} else {
802+
b.append(" __STATIC_INITIALIZER_");
803+
b.append(clsName.replace('/', '_').replace('$', '_'));
804+
b.append("(threadStateData);\n DEFINE_METHOD_STACK(");
805+
}
652806
} else {
653-
b.append(" __STATIC_INITIALIZER_");
654-
b.append(clsName.replace('/', '_').replace('$', '_'));
655-
b.append("(threadStateData);\n DEFINE_METHOD_STACK(");
807+
b.append(" DEFINE_INSTANCE_METHOD_STACK(");
656808
}
809+
b.append(maxStack);
810+
b.append(", ");
811+
b.append(maxLocals);
812+
b.append(", 0, ");
813+
b.append(Parser.addToConstantPool(clsName));
814+
b.append(", ");
815+
b.append(Parser.addToConstantPool(methodName));
816+
b.append(");\n");
657817
} else {
658-
b.append(" DEFINE_INSTANCE_METHOD_STACK(");
818+
b.append(" struct elementStruct* SP = &threadStateData->threadObjectStack[threadStateData->threadObjectStackOffset];\n");
659819
}
660-
b.append(maxStack);
661-
b.append(", ");
662-
b.append(maxLocals);
663-
b.append(", 0, ");
664-
b.append(Parser.addToConstantPool(clsName));
665-
b.append(", ");
666-
b.append(Parser.addToConstantPool(methodName));
667-
b.append(");\n");
668820
int startOffset = 0;
669821
if(synchronizedMethod) {
670822
if(staticMethod) {
@@ -676,25 +828,34 @@ public void appendMethodC(StringBuilder b) {
676828
}
677829
}
678830
if(!staticMethod) {
679-
b.append(" locals[0].data.o = __cn1ThisObject; locals[0].type = CN1_TYPE_OBJECT; ");
831+
if(!barebone) {
832+
b.append(" locals[0].data.o = __cn1ThisObject; locals[0].type = CN1_TYPE_OBJECT; ");
833+
}
680834
startOffset++;
681835
}
682836
int localsOffset = startOffset;
683837
for(int iter = 0 ; iter < arguments.size() ; iter++) {
684838
ByteCodeMethodArg arg = arguments.get(iter);
685839
if (arg.getQualifier() == 'o') {
686-
b.append(" locals[");
687-
b.append(localsOffset);
688-
b.append("].data.");
840+
if(barebone) {
841+
b.append(" JAVA_OBJECT olocals_");
842+
b.append(localsOffset);
843+
b.append("_ = __cn1Arg");
844+
b.append(iter + 1);
845+
b.append(";\n");
846+
} else {
847+
b.append(" locals[");
848+
b.append(localsOffset);
849+
b.append("].data.");
689850

690-
b.append(arg.getQualifier());
691-
b.append(" = __cn1Arg");
692-
b.append(iter + 1);
693-
b.append(";\n");
694-
b.append(" locals[");
695-
b.append(localsOffset);
696-
b.append("].type = CN1_TYPE_OBJECT;\n");
697-
851+
b.append(arg.getQualifier());
852+
b.append(" = __cn1Arg");
853+
b.append(iter + 1);
854+
b.append(";\n");
855+
b.append(" locals[");
856+
b.append(localsOffset);
857+
b.append("].type = CN1_TYPE_OBJECT;\n");
858+
}
698859
} else {
699860
b.append(" ");
700861
if (!hasLocalVariableWithIndex(arg.getQualifier(), localsOffset)) {
@@ -739,6 +900,7 @@ public void appendMethodC(StringBuilder b) {
739900
TryCatch.reset();
740901
BasicInstruction.setHasInstructions(hasInstructions);
741902
for(Instruction i : instructions) {
903+
i.setMethod(this);
742904
i.setMaxes(maxStack, maxLocals);
743905
i.appendInstruction(b, instructions);
744906
}

vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/BasicInstruction.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,13 @@ public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
532532
// b.append(maxLocals);
533533
// b.append(", stack, locals, methodBlockOffset); \n return SP[-1].data.i;\n");
534534
} else {
535-
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); return SP[-1].data.i;\n");
535+
if(getMethod() != null && getMethod().isBarebone()) {
536+
b.append(" return SP[-1].data.i;\n");
537+
} else {
538+
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); return SP[-1].data.i;\n");
536539
// b.append(maxLocals);
537540
// b.append(", stack, locals); \n return SP[-1].data.i;\n");
541+
}
538542
}
539543
break;
540544

@@ -544,7 +548,11 @@ public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
544548
if(TryCatch.isTryCatchInMethod()) {
545549
b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_LONG();\n");
546550
} else {
547-
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_LONG();\n");
551+
if(getMethod() != null && getMethod().isBarebone()) {
552+
b.append(" return POP_LONG();\n");
553+
} else {
554+
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_LONG();\n");
555+
}
548556
}
549557
break;
550558

@@ -554,7 +562,11 @@ public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
554562
if(TryCatch.isTryCatchInMethod()) {
555563
b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_FLOAT();\n");
556564
} else {
557-
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_FLOAT();\n");
565+
if(getMethod() != null && getMethod().isBarebone()) {
566+
b.append(" return POP_FLOAT();\n");
567+
} else {
568+
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_FLOAT();\n");
569+
}
558570
}
559571
break;
560572

@@ -564,7 +576,11 @@ public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
564576
if(TryCatch.isTryCatchInMethod()) {
565577
b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_DOUBLE();\n");
566578
} else {
567-
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_DOUBLE();\n");
579+
if(getMethod() != null && getMethod().isBarebone()) {
580+
b.append(" return POP_DOUBLE();\n");
581+
} else {
582+
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_DOUBLE();\n");
583+
}
568584
}
569585
break;
570586

@@ -574,7 +590,11 @@ public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
574590
if(TryCatch.isTryCatchInMethod()) {
575591
b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_OBJ();\n");
576592
} else {
577-
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_OBJ();\n");
593+
if(getMethod() != null && getMethod().isBarebone()) {
594+
b.append(" return POP_OBJ();\n");
595+
} else {
596+
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_OBJ();\n");
597+
}
578598
}
579599
break;
580600

@@ -588,7 +608,11 @@ public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
588608
if(TryCatch.isTryCatchInMethod()) {
589609
b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return;\n");
590610
} else {
591-
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return;\n");
611+
if(getMethod() != null && getMethod().isBarebone()) {
612+
b.append(" return;\n");
613+
} else {
614+
b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return;\n");
615+
}
592616
}
593617
break;
594618

vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/IInc.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ public IInc(int var, int num) {
4141

4242
@Override
4343
public void appendInstruction(StringBuilder b) {
44+
if(getMethod() != null && getMethod().isBarebone()) {
45+
b.append(" ilocals_");
46+
b.append(var);
47+
b.append("_ += ");
48+
b.append(num);
49+
b.append(";\n");
50+
return;
51+
}
4452
b.append(" BC_IINC(");
4553
b.append(var);
4654
b.append(", ");

0 commit comments

Comments
 (0)