Skip to content

Commit

Permalink
implemented proposed simpler solution with lower and upper bound tags
Browse files Browse the repository at this point in the history
  • Loading branch information
asotona committed Apr 26, 2024
1 parent ce3bd20 commit e706346
Showing 1 changed file with 38 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ void writeConstantPoolEntries(BufWriter buf) {
// Constantpool
@Override
public PoolEntry entryByIndex(int index) {
return entryByIndex(index, 0, 0xff);
}

private PoolEntry entryByIndex(int index, int lowerBoundTag, int upperBoundTag) {
if (index <= 0 || index >= constantPoolCount) {
throw new ConstantPoolException("Bad CP index: " + index);
}
Expand All @@ -349,25 +353,34 @@ public PoolEntry entryByIndex(int index) {
throw new ConstantPoolException("Unusable CP index: " + index);
}
int tag = readU1(offset);
if (tag < lowerBoundTag || tag > upperBoundTag) {
throw new ConstantPoolException(
"Bad tag (" + tag + ") at index (" + index + ") position (" + offset + ")");
}
final int q = offset + 1;
info = switch (tag) {
case TAG_UTF8 -> new AbstractPoolEntry.Utf8EntryImpl(this, index, buffer, q + 2, readU2(q));
case TAG_INTEGER -> new AbstractPoolEntry.IntegerEntryImpl(this, index, readInt(q));
case TAG_FLOAT -> new AbstractPoolEntry.FloatEntryImpl(this, index, readFloat(q));
case TAG_LONG -> new AbstractPoolEntry.LongEntryImpl(this, index, readLong(q));
case TAG_DOUBLE -> new AbstractPoolEntry.DoubleEntryImpl(this, index, readDouble(q));
case TAG_CLASS -> new AbstractPoolEntry.ClassEntryImpl(this, index, readUtf8Entry(q));
case TAG_STRING -> new AbstractPoolEntry.StringEntryImpl(this, index, readUtf8Entry(q));
case TAG_FIELDREF -> new AbstractPoolEntry.FieldRefEntryImpl(this, index, readClassEntry(q), readNameAndTypeEntry(q + 2));
case TAG_METHODREF -> new AbstractPoolEntry.MethodRefEntryImpl(this, index, readClassEntry(q), readNameAndTypeEntry(q + 2));
case TAG_INTERFACEMETHODREF -> new AbstractPoolEntry.InterfaceMethodRefEntryImpl(this, index, readClassEntry(q), readNameAndTypeEntry(q + 2));
case TAG_NAMEANDTYPE -> new AbstractPoolEntry.NameAndTypeEntryImpl(this, index, readUtf8Entry(q), readUtf8Entry(q + 2));
case TAG_METHODHANDLE -> new AbstractPoolEntry.MethodHandleEntryImpl(this, index, readU1(q), readAbstractMemberRefEntry(q + 1));
case TAG_METHODTYPE -> new AbstractPoolEntry.MethodTypeEntryImpl(this, index, readUtf8Entry(q));
case TAG_CONSTANTDYNAMIC -> new AbstractPoolEntry.ConstantDynamicEntryImpl(this, index, readU2(q), readNameAndTypeEntry(q + 2));
case TAG_INVOKEDYNAMIC -> new AbstractPoolEntry.InvokeDynamicEntryImpl(this, index, readU2(q), readNameAndTypeEntry(q + 2));
case TAG_MODULE -> new AbstractPoolEntry.ModuleEntryImpl(this, index, readUtf8Entry(q));
case TAG_PACKAGE -> new AbstractPoolEntry.PackageEntryImpl(this, index, readUtf8Entry(q));
case TAG_CLASS -> new AbstractPoolEntry.ClassEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
case TAG_STRING -> new AbstractPoolEntry.StringEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
case TAG_FIELDREF -> new AbstractPoolEntry.FieldRefEntryImpl(this, index, (AbstractPoolEntry.ClassEntryImpl) readClassEntry(q),
(AbstractPoolEntry.NameAndTypeEntryImpl) readNameAndTypeEntry(q + 2));
case TAG_METHODREF -> new AbstractPoolEntry.MethodRefEntryImpl(this, index, (AbstractPoolEntry.ClassEntryImpl) readClassEntry(q),
(AbstractPoolEntry.NameAndTypeEntryImpl) readNameAndTypeEntry(q + 2));
case TAG_INTERFACEMETHODREF -> new AbstractPoolEntry.InterfaceMethodRefEntryImpl(this, index, (AbstractPoolEntry.ClassEntryImpl) readClassEntry(q),
(AbstractPoolEntry.NameAndTypeEntryImpl) readNameAndTypeEntry(q + 2));
case TAG_NAMEANDTYPE -> new AbstractPoolEntry.NameAndTypeEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q),
(AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q + 2));
case TAG_METHODHANDLE -> new AbstractPoolEntry.MethodHandleEntryImpl(this, index, readU1(q),
readEntry(q + 1, AbstractPoolEntry.AbstractMemberRefEntry.class, TAG_FIELDREF, TAG_INTERFACEMETHODREF));
case TAG_METHODTYPE -> new AbstractPoolEntry.MethodTypeEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
case TAG_CONSTANTDYNAMIC -> new AbstractPoolEntry.ConstantDynamicEntryImpl(this, index, readU2(q), (AbstractPoolEntry.NameAndTypeEntryImpl) readNameAndTypeEntry(q + 2));
case TAG_INVOKEDYNAMIC -> new AbstractPoolEntry.InvokeDynamicEntryImpl(this, index, readU2(q), (AbstractPoolEntry.NameAndTypeEntryImpl) readNameAndTypeEntry(q + 2));
case TAG_MODULE -> new AbstractPoolEntry.ModuleEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
case TAG_PACKAGE -> new AbstractPoolEntry.PackageEntryImpl(this, index, (AbstractPoolEntry.Utf8EntryImpl) readUtf8Entry(q));
default -> throw new ConstantPoolException(
"Bad tag (" + tag + ") at index (" + index + ") position (" + offset + ")");
};
Expand Down Expand Up @@ -418,7 +431,11 @@ public PoolEntry readEntry(int pos) {

@Override
public <T extends PoolEntry> T readEntry(int pos, Class<T> cls) {
var e = readEntry(pos);
return readEntry(pos, cls, 0, 0xff);
}

private <T extends PoolEntry> T readEntry(int pos, Class<T> cls, int lowerBoundTag, int upperBoundTag) {
var e = entryByIndex(readU2(pos), lowerBoundTag, upperBoundTag);
if (cls.isInstance(e)) return cls.cast(e);
throw new ConstantPoolException("Not a " + cls.getSimpleName() + " at index: " + readU2(pos));
}
Expand All @@ -433,7 +450,7 @@ public PoolEntry readEntryOrNull(int pos) {
}

@Override
public AbstractPoolEntry.Utf8EntryImpl readUtf8Entry(int pos) {
public Utf8Entry readUtf8Entry(int pos) {
int index = readU2(pos);
return utf8EntryByIndex(index);
}
Expand All @@ -449,80 +466,27 @@ public Utf8Entry readUtf8EntryOrNull(int pos) {

@Override
public ModuleEntry readModuleEntry(int pos) {
return readEntry(pos, ModuleEntry.class);
return readEntry(pos, ModuleEntry.class, TAG_MODULE, TAG_MODULE);
}

@Override
public PackageEntry readPackageEntry(int pos) {
return readEntry(pos, PackageEntry.class);
}

private int readIndex(int pos) {
int index = readU2(pos);
if (index <= 0 || index >= constantPoolCount) {
throw new ConstantPoolException("Bad CP index: " + index);
}
return index;
}

private int getOffset(int index) {
int offset = cpOffset[index];
if (offset == 0) {
throw new ConstantPoolException("Unusable CP index: " + index);
}
return offset;
return readEntry(pos, PackageEntry.class, TAG_PACKAGE, TAG_PACKAGE);
}

@Override
public AbstractPoolEntry.ClassEntryImpl readClassEntry(int pos) {
int index = readIndex(pos);
PoolEntry info = cp[index];
if (info == null) {
int offset = getOffset(index);
if (readU1(offset) == TAG_CLASS) {
info = new AbstractPoolEntry.ClassEntryImpl(this, index, readUtf8Entry(offset + 1));
cp[index] = info;
}
}
if (info instanceof AbstractPoolEntry.ClassEntryImpl ce) return ce;
throw new ConstantPoolException("Not a ClassEntry at index: " + index);
public ClassEntry readClassEntry(int pos) {
return readEntry(pos, ClassEntry.class, TAG_CLASS, TAG_CLASS);
}

@Override
public AbstractPoolEntry.NameAndTypeEntryImpl readNameAndTypeEntry(int pos) {
int index = readIndex(pos);
PoolEntry info = cp[index];
if (info == null) {
int offset = getOffset(index);
if (readU1(offset) == TAG_NAMEANDTYPE) {
info = new AbstractPoolEntry.NameAndTypeEntryImpl(this, index, readUtf8Entry(offset + 1), readUtf8Entry(offset + 3));
cp[index] = info;
}
}
if (info instanceof AbstractPoolEntry.NameAndTypeEntryImpl nte) return nte;
throw new ConstantPoolException("Not a NameAndTypeEntry at index: " + index);
}

private AbstractPoolEntry.AbstractMemberRefEntry readAbstractMemberRefEntry(int pos) {
int index = readIndex(pos);
PoolEntry info = cp[index];
if (info == null) {
int offset = getOffset(index);
info = switch (readU1(offset)) {
case TAG_FIELDREF -> new AbstractPoolEntry.FieldRefEntryImpl(this, index, readClassEntry(offset + 1), readNameAndTypeEntry(offset + 3));
case TAG_METHODREF -> new AbstractPoolEntry.MethodRefEntryImpl(this, index, readClassEntry(offset + 1), readNameAndTypeEntry(offset + 3));
case TAG_INTERFACEMETHODREF -> new AbstractPoolEntry.InterfaceMethodRefEntryImpl(this, index, readClassEntry(offset + 1), readNameAndTypeEntry(offset + 3));
default -> null;
};
cp[index] = info;
}
if (info instanceof AbstractPoolEntry.AbstractMemberRefEntry amre) return amre;
throw new ConstantPoolException("Not a MemberRefEntry at index: " + index);
public NameAndTypeEntry readNameAndTypeEntry(int pos) {
return readEntry(pos, NameAndTypeEntry.class, TAG_NAMEANDTYPE, TAG_NAMEANDTYPE);
}

@Override
public MethodHandleEntry readMethodHandleEntry(int pos) {
return readEntry(pos, MethodHandleEntry.class);
return readEntry(pos, MethodHandleEntry.class, TAG_METHODHANDLE, TAG_METHODHANDLE);
}

@Override
Expand Down

0 comments on commit e706346

Please sign in to comment.