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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user