8341664: ReferenceClassDescImpl cache internalName
Reviewed-by: liach
This commit is contained in:
parent
c51a086ce3
commit
0963b9e891
@ -382,38 +382,6 @@ public abstract sealed class AbstractPoolEntry {
|
|||||||
return stringValue().equals(u.stringValue());
|
return stringValue().equals(u.stringValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if this utf8 entry's content equals a substring
|
|
||||||
* of {@code s} obtained as {@code s.substring(start, end - start)}.
|
|
||||||
* This check avoids a substring allocation.
|
|
||||||
*/
|
|
||||||
public boolean equalsRegion(String s, int start, int end) {
|
|
||||||
// start and end values trusted
|
|
||||||
if (state == State.RAW)
|
|
||||||
inflate();
|
|
||||||
int len = charLen;
|
|
||||||
if (len != end - start)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var sv = stringValue;
|
|
||||||
if (sv != null) {
|
|
||||||
return sv.regionMatches(0, s, start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
var chars = this.chars;
|
|
||||||
if (chars != null) {
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
if (chars[i] != s.charAt(start + i))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
var bytes = this.rawBytes;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
if (bytes[offset + i] != s.charAt(start + i))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equalsString(String s) {
|
public boolean equalsString(String s) {
|
||||||
if (state == State.RAW)
|
if (state == State.RAW)
|
||||||
|
@ -394,24 +394,6 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AbstractPoolEntry.Utf8EntryImpl tryFindUtf8OfRegion(int hash, String target, int start, int end) {
|
|
||||||
EntryMap map = map();
|
|
||||||
while (true) {
|
|
||||||
for (int token = map.firstToken(hash); token != -1; token = map.nextToken(hash, token)) {
|
|
||||||
PoolEntry e = entryByIndex(map.getIndexByToken(token));
|
|
||||||
if (e.tag() == TAG_UTF8
|
|
||||||
&& e instanceof AbstractPoolEntry.Utf8EntryImpl ce
|
|
||||||
&& ce.equalsRegion(target, start, end))
|
|
||||||
return ce;
|
|
||||||
}
|
|
||||||
if (!doneFullScan) {
|
|
||||||
fullScan();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private AbstractPoolEntry.ClassEntryImpl tryFindClassOrInterface(int hash, ClassDesc cd) {
|
private AbstractPoolEntry.ClassEntryImpl tryFindClassOrInterface(int hash, ClassDesc cd) {
|
||||||
while (true) {
|
while (true) {
|
||||||
EntryMap map = map();
|
EntryMap map = map();
|
||||||
@ -429,8 +411,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no symbol available
|
// no symbol available
|
||||||
var desc = cd.descriptorString();
|
if (ce.ref1.equalsString(Util.toInternalName(cd))) {
|
||||||
if (ce.ref1.equalsRegion(desc, 1, desc.length() - 1)) {
|
|
||||||
// definite match, propagate symbol
|
// definite match, propagate symbol
|
||||||
ce.sym = cd;
|
ce.sym = cd;
|
||||||
return ce;
|
return ce;
|
||||||
@ -454,10 +435,11 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
|
|||||||
if (ce != null)
|
if (ce != null)
|
||||||
return ce;
|
return ce;
|
||||||
|
|
||||||
var utfHash = Util.internalNameHash(desc);
|
String internalName = Util.toInternalName(cd);
|
||||||
var utf = tryFindUtf8OfRegion(AbstractPoolEntry.hashString(utfHash), desc, 1, desc.length() - 1);
|
var utfHash = internalName.hashCode();
|
||||||
|
var utf = tryFindUtf8(AbstractPoolEntry.hashString(utfHash), internalName);
|
||||||
if (utf == null)
|
if (utf == null)
|
||||||
utf = internalAdd(new AbstractPoolEntry.Utf8EntryImpl(this, size, ConstantUtils.dropFirstAndLastChar(desc), utfHash));
|
utf = internalAdd(new AbstractPoolEntry.Utf8EntryImpl(this, size, internalName, utfHash));
|
||||||
|
|
||||||
return internalAdd(new AbstractPoolEntry.ClassEntryImpl(this, size, utf, hash, cd));
|
return internalAdd(new AbstractPoolEntry.ClassEntryImpl(this, size, utf, hash, cd));
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
|
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
import jdk.internal.vm.annotation.Stable;
|
import jdk.internal.vm.annotation.Stable;
|
||||||
|
|
||||||
@ -133,10 +134,10 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String toInternalName(ClassDesc cd) {
|
public static String toInternalName(ClassDesc cd) {
|
||||||
var desc = cd.descriptorString();
|
if (cd instanceof ReferenceClassDescImpl rcd) {
|
||||||
if (desc.charAt(0) == 'L')
|
return rcd.internalName();
|
||||||
return desc.substring(1, desc.length() - 1);
|
}
|
||||||
throw new IllegalArgumentException(desc);
|
throw new IllegalArgumentException(cd.descriptorString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClassDesc toClassDesc(String classInternalNameOrArrayDesc) {
|
public static ClassDesc toClassDesc(String classInternalNameOrArrayDesc) {
|
||||||
@ -321,15 +322,6 @@ public class Util {
|
|||||||
boolean writeLocalTo(BufWriterImpl buf);
|
boolean writeLocalTo(BufWriterImpl buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the hash code of an internal name given the class or interface L descriptor.
|
|
||||||
*/
|
|
||||||
public static int internalNameHash(String desc) {
|
|
||||||
if (desc.length() > 0xffff)
|
|
||||||
throw new IllegalArgumentException("String too long: ".concat(Integer.toString(desc.length())));
|
|
||||||
return (desc.hashCode() - pow31(desc.length() - 1) * 'L' - ';') * INVERSE_31;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hash code of a class or interface L descriptor given the internal name.
|
* Returns the hash code of a class or interface L descriptor given the internal name.
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +27,7 @@ package jdk.internal.constant;
|
|||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
|
||||||
|
import jdk.internal.vm.annotation.Stable;
|
||||||
import static jdk.internal.constant.ConstantUtils.*;
|
import static jdk.internal.constant.ConstantUtils.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,6 +37,7 @@ import static jdk.internal.constant.ConstantUtils.*;
|
|||||||
*/
|
*/
|
||||||
public final class ReferenceClassDescImpl implements ClassDesc {
|
public final class ReferenceClassDescImpl implements ClassDesc {
|
||||||
private final String descriptor;
|
private final String descriptor;
|
||||||
|
private @Stable String internalName;
|
||||||
|
|
||||||
private ReferenceClassDescImpl(String descriptor) {
|
private ReferenceClassDescImpl(String descriptor) {
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
@ -76,6 +78,16 @@ public final class ReferenceClassDescImpl implements ClassDesc {
|
|||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String internalName() {
|
||||||
|
var internalName = this.internalName;
|
||||||
|
if (internalName == null) {
|
||||||
|
var desc = this.descriptor;
|
||||||
|
this.internalName = internalName = desc.charAt(0) == 'L' ? dropFirstAndLastChar(desc) : desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return internalName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
|
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
|
||||||
throws ReflectiveOperationException {
|
throws ReflectiveOperationException {
|
||||||
@ -90,7 +102,7 @@ public final class ReferenceClassDescImpl implements ClassDesc {
|
|||||||
clazz = clazz.arrayType();
|
clazz = clazz.arrayType();
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
return lookup.findClass(internalToBinary(dropFirstAndLastChar(descriptor)));
|
return lookup.findClass(internalToBinary(internalName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,20 +103,6 @@ class UtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@ValueSource(classes = {
|
|
||||||
Long.class,
|
|
||||||
Object.class,
|
|
||||||
Util.class,
|
|
||||||
Test.class,
|
|
||||||
CopyOnWriteArrayList.class,
|
|
||||||
AtomicReferenceFieldUpdater.class
|
|
||||||
})
|
|
||||||
void testInternalNameHash(Class<?> type) {
|
|
||||||
var cd = type.describeConstable().orElseThrow();
|
|
||||||
assertEquals(ConstantUtils.binaryToInternal(type.getName()).hashCode(), Util.internalNameHash(cd.descriptorString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensures the initialization statement of the powers array is filling in the right values
|
// Ensures the initialization statement of the powers array is filling in the right values
|
||||||
@Test
|
@Test
|
||||||
void testPowersArray() {
|
void testPowersArray() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user