8318837: javac generates wrong ldc instruction for dynamic constant loads

Reviewed-by: vromero, jlahoda
This commit is contained in:
Maurizio Cimadamore 2023-10-27 13:47:24 +00:00
parent ddd071617e
commit 2915d74a10
3 changed files with 28 additions and 29 deletions

View File

@ -35,7 +35,9 @@ import java.util.function.ToIntBiFunction;
import java.util.function.ToIntFunction;
import static com.sun.tools.javac.code.TypeTag.BOT;
import static com.sun.tools.javac.code.TypeTag.DOUBLE;
import static com.sun.tools.javac.code.TypeTag.INT;
import static com.sun.tools.javac.code.TypeTag.LONG;
import static com.sun.tools.javac.jvm.ByteCodes.*;
import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
@ -401,10 +403,12 @@ public class Code {
*/
public void emitLdc(LoadableConstant constant) {
int od = poolWriter.putConstant(constant);
if (od <= 255) {
Type constantType = types.constantType(constant);
if (constantType.hasTag(LONG) || constantType.hasTag(DOUBLE)) {
emitop2(ldc2w, od, constant);
} else if (od <= 255) {
emitop1(ldc1, od, constant);
}
else {
} else {
emitop2(ldc2, od, constant);
}
}
@ -1062,6 +1066,7 @@ public class Code {
Type t = types.erasure((Type)data);
state.push(t);
break; }
case ldc2:
case ldc2w:
state.push(types.constantType((LoadableConstant)data));
break;
@ -1069,9 +1074,6 @@ public class Code {
state.pop(1);
state.push(syms.intType);
break;
case ldc2:
state.push(types.constantType((LoadableConstant)data));
break;
case jsr:
break;
default:

View File

@ -590,15 +590,6 @@ public class Items {
throw new UnsupportedOperationException("unsupported tag: " + typecode);
}
}
private void ldc() {
if (typecode == LONGcode || typecode == DOUBLEcode) {
code.emitop2(ldc2w, value, PoolWriter::putConstant);
} else {
code.emitLdc(value);
}
}
private Number numericValue() {
return (Number)((BasicConstant)value).data;
}
@ -614,21 +605,21 @@ public class Items {
else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
code.emitop2(sipush, ival);
else
ldc();
code.emitLdc(value);
break;
case LONGcode:
long lval = numericValue().longValue();
if (lval == 0 || lval == 1)
code.emitop0(lconst_0 + (int)lval);
else
ldc();
code.emitLdc(value);
break;
case FLOATcode:
float fval = numericValue().floatValue();
if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
code.emitop0(fconst_0 + (int)fval);
else {
ldc();
code.emitLdc(value);
}
break;
case DOUBLEcode:
@ -636,10 +627,10 @@ public class Items {
if (isPosZero(dval) || dval == 1.0)
code.emitop0(dconst_0 + (int)dval);
else
ldc();
code.emitLdc(value);
break;
case OBJECTcode:
ldc();
code.emitLdc(value);
break;
default:
Assert.error();

View File

@ -81,21 +81,23 @@ import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
public class TestConstantDynamic extends ComboInstance<TestConstantDynamic> {
enum ConstantType implements ComboParameter {
STRING("String", "Ljava/lang/String;"),
CLASS("Class<?>", "Ljava/lang/Class;"),
INTEGER("int", "I"),
LONG("long", "J"),
FLOAT("float", "F"),
DOUBLE("double", "D"),
METHOD_HANDLE("MethodHandle", "Ljava/lang/invoke/MethodHandle;"),
METHOD_TYPE("MethodType", "Ljava/lang/invoke/MethodType;");
STRING("String", "Ljava/lang/String;", Opcode.LDC),
CLASS("Class<?>", "Ljava/lang/Class;", Opcode.LDC),
INTEGER("int", "I", Opcode.LDC),
LONG("long", "J", Opcode.LDC2_W),
FLOAT("float", "F", Opcode.LDC),
DOUBLE("double", "D", Opcode.LDC2_W),
METHOD_HANDLE("MethodHandle", "Ljava/lang/invoke/MethodHandle;", Opcode.LDC),
METHOD_TYPE("MethodType", "Ljava/lang/invoke/MethodType;", Opcode.LDC);
String sourceTypeStr;
String bytecodeTypeStr;
Opcode opcode;
ConstantType(String sourceTypeStr, String bytecodeTypeStr) {
ConstantType(String sourceTypeStr, String bytecodeTypeStr, Opcode opcode) {
this.sourceTypeStr = sourceTypeStr;
this.bytecodeTypeStr = bytecodeTypeStr;
this.opcode = opcode;
}
@Override
@ -205,6 +207,10 @@ public class TestConstantDynamic extends ComboInstance<TestConstantDynamic> {
fail("type mismatch for ConstantDynamicEntry");
return;
}
if (lci.opcode() != type.opcode) {
fail("unexpected opcode for constant value: " + lci.opcode());
return;
}
}
}