8341664: ReferenceClassDescImpl cache internalName

Reviewed-by: liach
This commit is contained in:
Shaojin Wen 2024-10-18 08:06:09 +00:00
parent c51a086ce3
commit 0963b9e891
5 changed files with 23 additions and 83 deletions

View File

@ -382,38 +382,6 @@ public abstract sealed class AbstractPoolEntry {
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
public boolean equalsString(String s) {
if (state == State.RAW)

View File

@ -394,24 +394,6 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
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) {
while (true) {
EntryMap map = map();
@ -429,8 +411,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
}
// no symbol available
var desc = cd.descriptorString();
if (ce.ref1.equalsRegion(desc, 1, desc.length() - 1)) {
if (ce.ref1.equalsString(Util.toInternalName(cd))) {
// definite match, propagate symbol
ce.sym = cd;
return ce;
@ -454,10 +435,11 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
if (ce != null)
return ce;
var utfHash = Util.internalNameHash(desc);
var utf = tryFindUtf8OfRegion(AbstractPoolEntry.hashString(utfHash), desc, 1, desc.length() - 1);
String internalName = Util.toInternalName(cd);
var utfHash = internalName.hashCode();
var utf = tryFindUtf8(AbstractPoolEntry.hashString(utfHash), internalName);
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));
}

View File

@ -42,6 +42,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import jdk.internal.access.SharedSecrets;
import jdk.internal.constant.ReferenceClassDescImpl;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
@ -133,10 +134,10 @@ public class Util {
}
public static String toInternalName(ClassDesc cd) {
var desc = cd.descriptorString();
if (desc.charAt(0) == 'L')
return desc.substring(1, desc.length() - 1);
throw new IllegalArgumentException(desc);
if (cd instanceof ReferenceClassDescImpl rcd) {
return rcd.internalName();
}
throw new IllegalArgumentException(cd.descriptorString());
}
public static ClassDesc toClassDesc(String classInternalNameOrArrayDesc) {
@ -321,15 +322,6 @@ public class Util {
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.
*/

View File

@ -27,6 +27,7 @@ package jdk.internal.constant;
import java.lang.constant.ClassDesc;
import java.lang.invoke.MethodHandles;
import jdk.internal.vm.annotation.Stable;
import static jdk.internal.constant.ConstantUtils.*;
/**
@ -36,6 +37,7 @@ import static jdk.internal.constant.ConstantUtils.*;
*/
public final class ReferenceClassDescImpl implements ClassDesc {
private final String descriptor;
private @Stable String internalName;
private ReferenceClassDescImpl(String descriptor) {
this.descriptor = descriptor;
@ -76,6 +78,16 @@ public final class ReferenceClassDescImpl implements ClassDesc {
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
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
throws ReflectiveOperationException {
@ -90,7 +102,7 @@ public final class ReferenceClassDescImpl implements ClassDesc {
clazz = clazz.arrayType();
return clazz;
}
return lookup.findClass(internalToBinary(dropFirstAndLastChar(descriptor)));
return lookup.findClass(internalToBinary(internalName()));
}
/**

View File

@ -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
@Test
void testPowersArray() {