8267421: j.l.constant.DirectMethodHandleDesc.Kind.valueOf(int) implementation doesn't conform to the spec regarding REF_invokeInterface handling

Reviewed-by: mchung
This commit is contained in:
Vicente Romero 2021-06-22 02:08:15 +00:00
parent ef4ba224c4
commit 6b14c8a1e5
2 changed files with 28 additions and 13 deletions
src/java.base/share/classes/java/lang/constant
test/jdk/java/lang/constant

@ -105,7 +105,7 @@ public sealed interface DirectMethodHandleDesc
* @throws IllegalArgumentException if there is no such member
*/
public static Kind valueOf(int refKind) {
return valueOf(refKind, false);
return valueOf(refKind, refKind == REF_invokeInterface);
}
/**
@ -134,16 +134,10 @@ public sealed interface DirectMethodHandleDesc
*/
public static Kind valueOf(int refKind, boolean isInterface) {
int i = tableIndex(refKind, isInterface);
if (i >= 0 && i < TABLE.length) {
Kind kind = TABLE[i];
if (kind == null) {
throw new IllegalArgumentException(String.format("refKind=%d", refKind));
}
if (kind.refKind == refKind && kind.isInterface == isInterface) {
return kind;
}
if (i >= 2 && i < TABLE.length) {
return TABLE[i];
}
throw new IllegalArgumentException(String.format("refKind=%d", refKind));
throw new IllegalArgumentException(String.format("refKind=%d isInterface=%s", refKind, isInterface));
}
private static int tableIndex(int refKind, boolean isInterface) {
@ -180,9 +174,7 @@ public sealed interface DirectMethodHandleDesc
// for either truth value of X.
int i = tableIndex(kind.refKind, true);
if (TABLE[i] == null) {
// There is not a specific Kind for interfaces
if (kind == VIRTUAL) kind = INTERFACE_VIRTUAL;
if (TABLE[i] == null) TABLE[i] = kind;
TABLE[i] = kind;
}
}
}

@ -53,7 +53,9 @@ import static java.lang.constant.ConstantDescs.CD_Object;
import static java.lang.constant.ConstantDescs.CD_String;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.CD_void;
import static java.lang.invoke.MethodHandleInfo.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotSame;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
@ -359,7 +361,28 @@ public class MethodHandleDescTest extends SymbolicDescTest {
public void testKind() {
for (Kind k : Kind.values()) {
assertEquals(Kind.valueOf(k.refKind), Kind.valueOf(k.refKind, k.refKind == MethodHandleInfo.REF_invokeInterface));
assertEquals(Kind.valueOf(k.refKind, k.isInterface), k);
}
// let's now verify those cases for which the value of the isInterface parameter is ignored
int[] isInterfaceIgnored = new int[] {
REF_getField,
REF_getStatic,
REF_putField,
REF_putStatic,
REF_newInvokeSpecial,
REF_invokeInterface
};
for (int refKind : isInterfaceIgnored) {
assertEquals(Kind.valueOf(refKind, false), Kind.valueOf(refKind, true));
}
// some explicit tests for REF_invokeStatic and REF_invokeSpecial
assertNotEquals(Kind.valueOf(REF_invokeStatic, false), Kind.valueOf(REF_invokeStatic, true));
assertNotEquals(Kind.valueOf(REF_invokeSpecial, false), Kind.valueOf(REF_invokeSpecial, true));
assertEquals(Kind.valueOf(REF_invokeStatic, false), Kind.STATIC);
assertEquals(Kind.valueOf(REF_invokeStatic, true), Kind.INTERFACE_STATIC);
assertEquals(Kind.valueOf(REF_invokeSpecial, false), Kind.SPECIAL);
assertEquals(Kind.valueOf(REF_invokeSpecial, true), Kind.INTERFACE_SPECIAL);
}
}