-
Bug
-
Resolution: Fixed
-
P4
-
6
A DESCRIPTION OF THE FIX :
Bug Description : javac does not use iinc opcode for postfix decrement of local variable.
Generally, javac produces code that evaluates postfix decrement correctly. But looking to the sources I found some asymmetry and I think it was not made intentionally.
Subset of Releases affected : 1.4.2, 1.5.0, Mustang b65.
Platforms affected : all
Test case : See Test case section.
Diff baseline : Mustang b65
Diff :
--- j2se/src/share/classes/com/sun/tools/javac/jvm/Gen.java.prev Tue Dec 27 20:43:22 2005
+++ j2se/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Jan 06 21:42:42 2006
@@ -1783,41 +1783,42 @@
case JCTree.PREINC: case JCTree.PREDEC:
od.duplicate();
if (od instanceof LocalItem &&
(operator.opcode == iadd || operator.opcode == isub)) {
((LocalItem)od).incr(tree.tag == JCTree.PREINC ? 1 : -1);
result = od;
} else {
od.load();
code.emitop0(one(od.typecode));
code.emitop0(operator.opcode);
// Perform narrowing primitive conversion if byte,
// char, or short. Fix for 4304655.
if (od.typecode != INTcode &&
Code.truncate(od.typecode) == INTcode)
code.emitop0(int2byte + od.typecode - BYTEcode);
result = items.makeAssignItem(od);
}
break;
case JCTree.POSTINC: case JCTree.POSTDEC:
od.duplicate();
- if (od instanceof LocalItem && operator.opcode == iadd) {
+ if (od instanceof LocalItem &&
+ (operator.opcode == iadd || operator.opcode == isub)) {
Item res = od.load();
((LocalItem)od).incr(tree.tag == JCTree.POSTINC ? 1 : -1);
result = res;
} else {
Item res = od.load();
od.stash(od.typecode);
code.emitop0(one(od.typecode));
code.emitop0(operator.opcode);
// Perform narrowing primitive conversion if byte,
// char, or short. Fix for 4304655.
if (od.typecode != INTcode &&
Code.truncate(od.typecode) == INTcode)
code.emitop0(int2byte + od.typecode - BYTEcode);
od.store();
result = res;
}
break;
case JCTree.NULLCHK:
result = od.load();
code.emitop0(dup);
JUnit TESTCASE :
This is not JUnit style test. This is just a proof that patch focuses on the problem.
Here is sample class:
// Main.java
public class Main {
private static boolean test() {
int x = 10;
int y = x--;
// check whether generated code still works correctly
return (x == 9) && (y == 10);
}
public static void main(String[] args) {
boolean ok = test();
System.out.println("ok = " + ok);
System.exit(ok? 0: 1);
}
}
And generated code for method "test()" differs in such a way:
private static boolean test();
Code:
- Stack=3, Locals=2, Args_size=0
+ Stack=2, Locals=2, Args_size=0
bipush 10
istore_0
iload_0
- dup
- iconst_1
- isub
- istore_0
+ iinc 0, -1
istore_1
iload_0
bipush 9
if_icmpne @else
iload_1
bipush 10
if_icmpne @else
iconst_1
goto @end
@else:
iconst_0
@end:
ireturn
Bug Description : javac does not use iinc opcode for postfix decrement of local variable.
Generally, javac produces code that evaluates postfix decrement correctly. But looking to the sources I found some asymmetry and I think it was not made intentionally.
Subset of Releases affected : 1.4.2, 1.5.0, Mustang b65.
Platforms affected : all
Test case : See Test case section.
Diff baseline : Mustang b65
Diff :
--- j2se/src/share/classes/com/sun/tools/javac/jvm/Gen.java.prev Tue Dec 27 20:43:22 2005
+++ j2se/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Jan 06 21:42:42 2006
@@ -1783,41 +1783,42 @@
case JCTree.PREINC: case JCTree.PREDEC:
od.duplicate();
if (od instanceof LocalItem &&
(operator.opcode == iadd || operator.opcode == isub)) {
((LocalItem)od).incr(tree.tag == JCTree.PREINC ? 1 : -1);
result = od;
} else {
od.load();
code.emitop0(one(od.typecode));
code.emitop0(operator.opcode);
// Perform narrowing primitive conversion if byte,
// char, or short. Fix for 4304655.
if (od.typecode != INTcode &&
Code.truncate(od.typecode) == INTcode)
code.emitop0(int2byte + od.typecode - BYTEcode);
result = items.makeAssignItem(od);
}
break;
case JCTree.POSTINC: case JCTree.POSTDEC:
od.duplicate();
- if (od instanceof LocalItem && operator.opcode == iadd) {
+ if (od instanceof LocalItem &&
+ (operator.opcode == iadd || operator.opcode == isub)) {
Item res = od.load();
((LocalItem)od).incr(tree.tag == JCTree.POSTINC ? 1 : -1);
result = res;
} else {
Item res = od.load();
od.stash(od.typecode);
code.emitop0(one(od.typecode));
code.emitop0(operator.opcode);
// Perform narrowing primitive conversion if byte,
// char, or short. Fix for 4304655.
if (od.typecode != INTcode &&
Code.truncate(od.typecode) == INTcode)
code.emitop0(int2byte + od.typecode - BYTEcode);
od.store();
result = res;
}
break;
case JCTree.NULLCHK:
result = od.load();
code.emitop0(dup);
JUnit TESTCASE :
This is not JUnit style test. This is just a proof that patch focuses on the problem.
Here is sample class:
// Main.java
public class Main {
private static boolean test() {
int x = 10;
int y = x--;
// check whether generated code still works correctly
return (x == 9) && (y == 10);
}
public static void main(String[] args) {
boolean ok = test();
System.out.println("ok = " + ok);
System.exit(ok? 0: 1);
}
}
And generated code for method "test()" differs in such a way:
private static boolean test();
Code:
- Stack=3, Locals=2, Args_size=0
+ Stack=2, Locals=2, Args_size=0
bipush 10
istore_0
iload_0
- dup
- iconst_1
- isub
- istore_0
+ iinc 0, -1
istore_1
iload_0
bipush 9
if_icmpne @else
iload_1
bipush 10
if_icmpne @else
iconst_1
goto @end
@else:
iconst_0
@end:
ireturn