Skip to content

Commit

Permalink
8315678: Classfile API ConstantPool::entryCount and ConstantPool::ent…
Browse files Browse the repository at this point in the history
…ryByIndex methods are confusing

Reviewed-by: briangoetz
  • Loading branch information
asotona committed Sep 14, 2023
1 parent 6d47fc6 commit ca747f0
Show file tree
Hide file tree
Showing 40 changed files with 120 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
/**
* Models a {@code CONSTANT_Class_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.1 The CONSTANT_Class_info Structure
*/
public sealed interface ClassEntry
extends LoadableConstantEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
/**
* Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
*/
public sealed interface ConstantDynamicEntry
extends DynamicConstantPoolEntry, LoadableConstantEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,65 @@

package jdk.internal.classfile.constantpool;

import java.util.Iterator;
import java.util.NoSuchElementException;
import jdk.internal.classfile.BootstrapMethodEntry;
import jdk.internal.classfile.ClassReader;

/**
* Provides read access to the constant pool and bootstrap method table of a
* classfile.
* @jvms 4.4 The Constant Pool
*/
public sealed interface ConstantPool
public sealed interface ConstantPool extends Iterable<PoolEntry>
permits ClassReader, ConstantPoolBuilder {

/**
* {@return the entry at the specified index}
*
* @param index the index within the pool of the desired entry
* @throws ConstantPoolException if the index is out of range of the
* constant pool, or is considered unusable
*/
PoolEntry entryByIndex(int index);

/**
* {@return the number of entries in the constant pool}
* {@return the size of the constant pool}
*/
int entryCount();
int size();

/**
* @{return an iterator over pool entries}
*/
@Override
default Iterator<PoolEntry> iterator() {
return new Iterator<>() {
int index = 1;

@Override
public boolean hasNext() {
return index < size();
}

@Override
public PoolEntry next() {
if (!hasNext()) throw new NoSuchElementException();
var e = entryByIndex(index);
index += e.width();
return e;
}
};
}


/**
* {@return the {@link BootstrapMethodEntry} at the specified index within
* the bootstrap method table}
*
* @param index the index within the bootstrap method table of the desired
* entry
* @throws ConstantPoolException if the index is out of range of the
* bootstrap methods
*/
BootstrapMethodEntry bootstrapMethodEntry(int index);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/**
* Models a {@code CONSTANT_Double_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures
*/
public sealed interface DoubleEntry
extends AnnotationConstantValueEntry, ConstantValueEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**
* Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
*/
public sealed interface FieldRefEntry extends MemberRefEntry
permits AbstractPoolEntry.FieldRefEntryImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/**
* Models a {@code CONSTANT_Float_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures
*/
public sealed interface FloatEntry
extends AnnotationConstantValueEntry, ConstantValueEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/**
* Models a {@code CONSTANT_Integer_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures
*/
public sealed interface IntegerEntry
extends AnnotationConstantValueEntry, ConstantValueEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**
* Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
*/
public sealed interface InterfaceMethodRefEntry
extends MemberRefEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

/**
* Models a constant pool entry for a dynamic call site.
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
*/
public sealed interface InvokeDynamicEntry
extends DynamicConstantPoolEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/**
* Models a {@code CONSTANT_Long_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures
*/
public sealed interface LongEntry
extends AnnotationConstantValueEntry, ConstantValueEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
/**
* Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure
*/
public sealed interface MethodHandleEntry
extends LoadableConstantEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**
* Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
*/
public sealed interface MethodRefEntry extends MemberRefEntry
permits AbstractPoolEntry.MethodRefEntryImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
/**
* Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.9 The CONSTANT_MethodType_info Structure
*/
public sealed interface MethodTypeEntry
extends LoadableConstantEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/**
* Models a {@code CONSTANT_Module_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.11 The CONSTANT_Module_info Structure
*/
public sealed interface ModuleEntry extends PoolEntry
permits AbstractPoolEntry.ModuleEntryImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**
* Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
*/
public sealed interface NameAndTypeEntry extends PoolEntry
permits AbstractPoolEntry.NameAndTypeEntryImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/**
* Models a {@code CONSTANT_Package_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.12 The CONSTANT_Package_info Structure
*/
public sealed interface PackageEntry extends PoolEntry
permits AbstractPoolEntry.PackageEntryImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**
* Models a {@code CONSTANT_String_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.3 The CONSTANT_String_info Structure
*/
public sealed interface StringEntry
extends ConstantValueEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**
* Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a
* classfile.
* @jvms 4.4.7 The CONSTANT_Utf8_info Structure
*/
public sealed interface Utf8Entry
extends CharSequence, AnnotationConstantValueEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,9 +570,8 @@ private static MapNode classToTree(ClassModel clm, Verbosity verbosity) {
private static Node[] constantPoolToTree(ConstantPool cp, Verbosity verbosity) {
if (verbosity == Verbosity.TRACE_ALL) {
var cpNode = new MapNodeImpl(BLOCK, "constant pool");
for (int i = 1; i < cp.entryCount();) {
var e = cp.entryByIndex(i);
cpNode.with(new MapNodeImpl(FLOW, i)
for (PoolEntry e : cp) {
cpNode.with(new MapNodeImpl(FLOW, e.index())
.with(leaf("tag", switch (e.tag()) {
case TAG_UTF8 -> "Utf8";
case TAG_INTEGER -> "Integer";
Expand Down Expand Up @@ -637,7 +636,6 @@ private static Node[] constantPoolToTree(ConstantPool cp, Verbosity verbosity) {
"value", String.valueOf(ve.constantValue())
);
}));
i += e.width();
}
return new Node[]{cpNode};
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public Function<Utf8Entry, AttributeMapper<?>> customAttributes() {
}

@Override
public int entryCount() {
public int size() {
return constantPoolCount;
}

Expand Down Expand Up @@ -189,6 +189,9 @@ public int bootstrapMethodCount() {

@Override
public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) {
if (index < 0 || index >= bootstrapMethodCount()) {
throw new ConstantPoolException("Bad BSM index: " + index);
}
return bsmEntries().get(index);
}

Expand Down Expand Up @@ -312,6 +315,9 @@ public PoolEntry entryByIndex(int index) {
PoolEntry info = cp[index];
if (info == null) {
int offset = cpOffset[index];
if (offset == 0) {
throw new ConstantPoolException("Unusable CP index: " + index);
}
int tag = readU1(offset);
final int q = offset + 1;
info = switch (tag) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.lang.constant.MethodTypeDesc;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.Attributes;
Expand Down Expand Up @@ -75,6 +76,7 @@
import static jdk.internal.classfile.Classfile.TAG_NAMEANDTYPE;
import static jdk.internal.classfile.Classfile.TAG_PACKAGE;
import static jdk.internal.classfile.Classfile.TAG_STRING;
import jdk.internal.classfile.constantpool.ConstantPoolException;

public final class SplitConstantPool implements ConstantPoolBuilder {

Expand All @@ -101,7 +103,7 @@ public SplitConstantPool() {

public SplitConstantPool(ClassReader parent) {
this.parent = (ClassReaderImpl) parent;
this.parentSize = parent.entryCount();
this.parentSize = parent.size();
this.parentBsmSize = parent.bootstrapMethodCount();
this.size = parentSize;
this.bsmSize = parentBsmSize;
Expand All @@ -110,7 +112,7 @@ public SplitConstantPool(ClassReader parent) {
}

@Override
public int entryCount() {
public int size() {
return size;
}

Expand All @@ -121,13 +123,23 @@ public int bootstrapMethodCount() {

@Override
public PoolEntry entryByIndex(int index) {
return (index < parentSize)
if (index <= 0 || index >= size()) {
throw new ConstantPoolException("Bad CP index: " + index);
}
PoolEntry pe = (index < parentSize)
? parent.entryByIndex(index)
: myEntries[index - parentSize];
if (pe == null) {
throw new ConstantPoolException("Unusable CP index: " + index);
}
return pe;
}

@Override
public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) {
if (index < 0 || index >= bootstrapMethodCount()) {
throw new ConstantPoolException("Bad BSM index: " + index);
}
return (index < parentBsmSize)
? parent.bootstrapMethodEntry(index)
: myBsmEntries[index - parentBsmSize];
Expand Down Expand Up @@ -170,15 +182,15 @@ public void writeBody(BufWriter b) {
@Override
public void writeTo(BufWriter buf) {
int writeFrom = 1;
if (entryCount() >= 65536) {
throw new IllegalArgumentException(String.format("Constant pool is too large %d", entryCount()));
if (size() >= 65536) {
throw new IllegalArgumentException(String.format("Constant pool is too large %d", size()));
}
buf.writeU2(entryCount());
buf.writeU2(size());
if (parent != null && buf.constantPool().canWriteDirect(this)) {
parent.writeConstantPoolEntries(buf);
writeFrom = parent.entryCount();
writeFrom = parent.size();
}
for (int i = writeFrom; i < entryCount(); ) {
for (int i = writeFrom; i < size(); ) {
PoolEntry info = entryByIndex(i);
info.writeTo(buf);
i += info.width();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public PoolEntry entryByIndex(int index) {
}

@Override
public int entryCount() {
public int size() {
throw new UnsupportedOperationException();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ static class ConstantPoolWrapper {
}

int entryCount() {
return cp.entryCount();
return cp.size();
}

String classNameAt(int index) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,19 +175,18 @@ private void scanMethods(Set<Integer> utf8Descriptors)

private void scanConstantPool(Set<Integer> utf8Descriptors)
throws Exception {
for (int i = 1; i < cm.constantPool().entryCount(); i += cm.constantPool().entryByIndex(i).width()) {
try {
PoolEntry info = cm.constantPool().entryByIndex(i);
try {
for (PoolEntry info : cm.constantPool()) {
switch (info) {
case NameAndTypeEntry nameAndType ->
utf8Descriptors.add(nameAndType.type().index());
case MethodTypeEntry mt ->
utf8Descriptors.add(mt.descriptor().index());
default -> {}
}
} catch (ConstantPoolException ex) {
throw new IOException(ex);
}
} catch (ConstantPoolException ex) {
throw new IOException(ex);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/jdk/jdk/classfile/ConstantPoolCopyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ void cloneConstantPool(ClassModel c) throws Exception {
ConstantPool cp = c.constantPool();
ConstantPoolBuilder cp2 = new SplitConstantPool((ClassReader) cp);

assertEquals(cp2.entryCount(), cp.entryCount(), "Cloned constant pool must be same size");
assertEquals(cp2.size(), cp.size(), "Cloned constant pool must be same size");

for (int i = 1; i < cp.entryCount();) {
for (int i = 1; i < cp.size();) {
PoolEntry cp1i = cp.entryByIndex(i);
PoolEntry cp2i = cp2.entryByIndex(i);
assertTrue(representsTheSame(cp1i, cp2i), cp2i + " does not represent the same constant pool entry as " + cp1i);
Expand Down

1 comment on commit ca747f0

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.