mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8284880: Re-examine sun.invoke.util.Wrapper hash tables
Reviewed-by: erikj, mchung
This commit is contained in:
parent
e307bc8694
commit
5df8bd6b4e
3 changed files with 200 additions and 101 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
package sun.invoke.util;
|
||||
|
||||
import jdk.internal.vm.annotation.DontInline;
|
||||
|
||||
public enum Wrapper {
|
||||
// wrapperType simple primitiveType simple char emptyArray format
|
||||
BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0], Format.unsigned( 1)),
|
||||
|
@ -229,28 +231,17 @@ public enum Wrapper {
|
|||
* instead of no value at all.)
|
||||
*/
|
||||
public Object zero() {
|
||||
switch (this) {
|
||||
case BOOLEAN:
|
||||
return Boolean.FALSE;
|
||||
case INT:
|
||||
return (Integer)0;
|
||||
case BYTE:
|
||||
return (Byte)(byte)0;
|
||||
case CHAR:
|
||||
return (Character)(char)0;
|
||||
case SHORT:
|
||||
return (Short)(short)0;
|
||||
case LONG:
|
||||
return (Long)(long)0;
|
||||
case FLOAT:
|
||||
return FLOAT_ZERO;
|
||||
case DOUBLE:
|
||||
return DOUBLE_ZERO;
|
||||
case VOID:
|
||||
case OBJECT:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return switch (this) {
|
||||
case BOOLEAN -> Boolean.FALSE;
|
||||
case INT -> (Integer)0;
|
||||
case BYTE -> (Byte)(byte)0;
|
||||
case CHAR -> (Character)(char)0;
|
||||
case SHORT -> (Short)(short)0;
|
||||
case LONG -> (Long)(long)0;
|
||||
case FLOAT -> FLOAT_ZERO;
|
||||
case DOUBLE -> DOUBLE_ZERO;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private static final Object DOUBLE_ZERO = (Double)(double)0;
|
||||
|
@ -268,11 +259,16 @@ public enum Wrapper {
|
|||
* @throws IllegalArgumentException for unexpected types
|
||||
*/
|
||||
public static Wrapper forPrimitiveType(Class<?> type) {
|
||||
Wrapper w = findPrimitiveType(type);
|
||||
if (w != null) return w;
|
||||
if (type.isPrimitive())
|
||||
throw new InternalError(); // redo hash function
|
||||
throw newIllegalArgumentException("not primitive: "+type);
|
||||
if (type == int.class) return INT;
|
||||
if (type == long.class) return LONG;
|
||||
if (type == boolean.class) return BOOLEAN;
|
||||
if (type == short.class) return SHORT;
|
||||
if (type == byte.class) return BYTE;
|
||||
if (type == char.class) return CHAR;
|
||||
if (type == float.class) return FLOAT;
|
||||
if (type == double.class) return DOUBLE;
|
||||
if (type == void.class) return VOID;
|
||||
throw newIllegalArgumentException("not primitive: " + type);
|
||||
}
|
||||
|
||||
/** Return the wrapper that corresponds to the provided basic type char.
|
||||
|
@ -280,26 +276,14 @@ public enum Wrapper {
|
|||
* @throws IllegalArgumentException for unexpected types
|
||||
*/
|
||||
public static Wrapper forPrimitiveType(char basicTypeChar) {
|
||||
switch (basicTypeChar) {
|
||||
case 'I': return INT;
|
||||
case 'J': return LONG;
|
||||
case 'S': return SHORT;
|
||||
case 'B': return BYTE;
|
||||
case 'C': return CHAR;
|
||||
case 'F': return FLOAT;
|
||||
case 'D': return DOUBLE;
|
||||
case 'Z': return BOOLEAN;
|
||||
case 'V': return VOID;
|
||||
default: throw newIllegalArgumentException("not primitive: " + basicTypeChar);
|
||||
Wrapper w = FROM_CHAR[(basicTypeChar + (basicTypeChar >> 1)) & 0xf];
|
||||
if (w == null || w.basicTypeChar != basicTypeChar) {
|
||||
throw basicTypeError(basicTypeChar);
|
||||
}
|
||||
}
|
||||
|
||||
static Wrapper findPrimitiveType(Class<?> type) {
|
||||
Wrapper w = FROM_PRIM[hashPrim(type)];
|
||||
if (w != null && w.primitiveType == type) {
|
||||
return w;
|
||||
if (w == OBJECT) {
|
||||
throw newIllegalArgumentException("not primitive: " + basicTypeChar);
|
||||
}
|
||||
return null;
|
||||
return w;
|
||||
}
|
||||
|
||||
/** Return the wrapper that wraps values into the given wrapper type.
|
||||
|
@ -310,81 +294,80 @@ public enum Wrapper {
|
|||
*/
|
||||
public static Wrapper forWrapperType(Class<?> type) {
|
||||
Wrapper w = findWrapperType(type);
|
||||
if (w != null) return w;
|
||||
for (Wrapper x : values())
|
||||
if (x.wrapperType == type)
|
||||
throw new InternalError(); // redo hash function
|
||||
throw newIllegalArgumentException("not wrapper: "+type);
|
||||
if (w != null) {
|
||||
return w;
|
||||
}
|
||||
throw wrapperTypeError(type);
|
||||
}
|
||||
|
||||
static Wrapper findWrapperType(Class<?> type) {
|
||||
Wrapper w = FROM_WRAP[hashWrap(type)];
|
||||
if (w != null && w.wrapperType == type) {
|
||||
return w;
|
||||
}
|
||||
if (type == Object.class) return OBJECT;
|
||||
if (type == Integer.class) return INT;
|
||||
if (type == Long.class) return LONG;
|
||||
if (type == Boolean.class) return BOOLEAN;
|
||||
if (type == Short.class) return SHORT;
|
||||
if (type == Byte.class) return BYTE;
|
||||
if (type == Character.class) return CHAR;
|
||||
if (type == Float.class) return FLOAT;
|
||||
if (type == Double.class) return DOUBLE;
|
||||
if (type == Void.class) return VOID;
|
||||
return null;
|
||||
}
|
||||
|
||||
@DontInline
|
||||
private static RuntimeException wrapperTypeError(Class<?> type) {
|
||||
for (Wrapper x : values())
|
||||
if (x.wrapperType == type)
|
||||
throw new InternalError(); // missing wrapper type
|
||||
return newIllegalArgumentException("not wrapper: " + type);
|
||||
}
|
||||
|
||||
/** Return the wrapper that corresponds to the given bytecode
|
||||
* signature character. Return {@code OBJECT} for the character 'L'.
|
||||
* @throws IllegalArgumentException for any non-signature character or {@code '['}.
|
||||
*/
|
||||
public static Wrapper forBasicType(char type) {
|
||||
Wrapper w = FROM_CHAR[hashChar(type)];
|
||||
Wrapper w = FROM_CHAR[(type + (type >> 1)) & 0xf];
|
||||
if (w != null && w.basicTypeChar == type) {
|
||||
return w;
|
||||
}
|
||||
for (Wrapper x : values())
|
||||
if (w.basicTypeChar == type)
|
||||
throw basicTypeError(type);
|
||||
}
|
||||
|
||||
@DontInline
|
||||
private static RuntimeException basicTypeError(char type) {
|
||||
for (Wrapper x : values()) {
|
||||
if (x.basicTypeChar == type) {
|
||||
throw new InternalError(); // redo hash function
|
||||
throw newIllegalArgumentException("not basic type char: "+type);
|
||||
}
|
||||
}
|
||||
return newIllegalArgumentException("not basic type char: " + type);
|
||||
}
|
||||
|
||||
/** Return the wrapper for the given type, if it is
|
||||
* a primitive type, else return {@code OBJECT}.
|
||||
*/
|
||||
public static Wrapper forBasicType(Class<?> type) {
|
||||
if (type.isPrimitive())
|
||||
return forPrimitiveType(type);
|
||||
if (type == int.class) return INT;
|
||||
if (type == long.class) return LONG;
|
||||
if (type == boolean.class) return BOOLEAN;
|
||||
if (type == void.class) return VOID;
|
||||
if (type == byte.class) return BYTE;
|
||||
if (type == char.class) return CHAR;
|
||||
if (type == float.class) return FLOAT;
|
||||
if (type == double.class) return DOUBLE;
|
||||
if (type == short.class) return SHORT;
|
||||
return OBJECT; // any reference, including wrappers or arrays
|
||||
}
|
||||
|
||||
// Note on perfect hashes:
|
||||
// for signature chars c, do (c + (c >> 1)) % 16
|
||||
// for primitive type names n, do (n[0] + n[2]) % 16
|
||||
// The type name hash works for both primitive and wrapper names.
|
||||
// You can add "java/lang/Object" to the primitive names.
|
||||
// But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
|
||||
private static final Wrapper[] FROM_PRIM = new Wrapper[16];
|
||||
private static final Wrapper[] FROM_WRAP = new Wrapper[16];
|
||||
// for signature chars c, do (c + (c >> 1)) & 0xf
|
||||
private static final Wrapper[] FROM_CHAR = new Wrapper[16];
|
||||
private static int hashPrim(Class<?> x) {
|
||||
String xn = x.getName();
|
||||
if (xn.length() < 3) return 0;
|
||||
return (xn.charAt(0) + xn.charAt(2)) % 16;
|
||||
}
|
||||
private static int hashWrap(Class<?> x) {
|
||||
String xn = x.getName();
|
||||
final int offset = 10; assert(offset == "java.lang.".length());
|
||||
if (xn.length() < offset+3) return 0;
|
||||
return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
|
||||
}
|
||||
private static int hashChar(char x) {
|
||||
return (x + (x >> 1)) % 16;
|
||||
}
|
||||
|
||||
static {
|
||||
for (Wrapper w : values()) {
|
||||
int pi = hashPrim(w.primitiveType);
|
||||
int wi = hashWrap(w.wrapperType);
|
||||
int ci = hashChar(w.basicTypeChar);
|
||||
assert(FROM_PRIM[pi] == null);
|
||||
assert(FROM_WRAP[wi] == null);
|
||||
assert(FROM_CHAR[ci] == null);
|
||||
FROM_PRIM[pi] = w;
|
||||
FROM_WRAP[wi] = w;
|
||||
FROM_CHAR[ci] = w;
|
||||
FROM_CHAR[(w.basicTypeChar + (w.basicTypeChar >> 1)) & 0xf] = w;
|
||||
}
|
||||
//assert(jdk.sun.invoke.util.WrapperTest.test(false));
|
||||
}
|
||||
|
||||
/** What is the primitive type wrapped by this wrapper? */
|
||||
|
@ -474,13 +457,6 @@ public enum Wrapper {
|
|||
*/
|
||||
public String primitiveSimpleName() { return primitiveSimpleName; }
|
||||
|
||||
// /** Wrap a value in the given type, which may be either a primitive or wrapper type.
|
||||
// * Performs standard primitive conversions, including truncation and float conversions.
|
||||
// */
|
||||
// public static <T> T wrap(Object x, Class<T> type) {
|
||||
// return Wrapper.valueOf(type).cast(x, type);
|
||||
// }
|
||||
|
||||
/** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
|
||||
* The given target type must be this wrapper's primitive or wrapper type.
|
||||
* If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue