Skip to content

Commit 911d1db

Browse files
committed
8314078: HotSpotConstantPool.lookupField() asserts due to field changes in ConstantPool.cpp
Reviewed-by: dnsimon, coleenp
1 parent 6574dd7 commit 911d1db

File tree

5 files changed

+123
-61
lines changed

5 files changed

+123
-61
lines changed

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,14 @@ C2V_VMENTRY_0(int, decodeIndyIndexToCPIndex, (JNIEnv* env, jobject, ARGUMENT_PAI
16201620
return cp->resolved_indy_entry_at(indy_index)->constant_pool_index();
16211621
C2V_END
16221622

1623+
C2V_VMENTRY_0(int, decodeFieldIndexToCPIndex, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint field_index))
1624+
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
1625+
if (field_index < 0 || field_index >= cp->resolved_field_entries_length()) {
1626+
JVMCI_THROW_MSG_0(IllegalStateException, err_msg("invalid field index %d", field_index));
1627+
}
1628+
return cp->resolved_field_entry_at(field_index)->constant_pool_index();
1629+
C2V_END
1630+
16231631
C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
16241632
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
16251633
Klass* holder = cp->klass_ref_at(index, Bytecodes::_invokehandle, CHECK);
@@ -3143,6 +3151,7 @@ JNINativeMethod CompilerToVM::methods[] = {
31433151
{CC "getUncachedStringInPool", CC "(" HS_CONSTANT_POOL2 "I)" JAVACONSTANT, FN_PTR(getUncachedStringInPool)},
31443152
{CC "resolveTypeInPool", CC "(" HS_CONSTANT_POOL2 "I)" HS_KLASS, FN_PTR(resolveTypeInPool)},
31453153
{CC "resolveFieldInPool", CC "(" HS_CONSTANT_POOL2 "I" HS_METHOD2 "B[I)" HS_KLASS, FN_PTR(resolveFieldInPool)},
3154+
{CC "decodeFieldIndexToCPIndex", CC "(" HS_CONSTANT_POOL2 "I)I", FN_PTR(decodeFieldIndexToCPIndex)},
31463155
{CC "decodeIndyIndexToCPIndex", CC "(" HS_CONSTANT_POOL2 "IZ)I", FN_PTR(decodeIndyIndexToCPIndex)},
31473156
{CC "resolveInvokeHandleInPool", CC "(" HS_CONSTANT_POOL2 "I)V", FN_PTR(resolveInvokeHandleInPool)},
31483157
{CC "isResolvedInvokeHandleInPool", CC "(" HS_CONSTANT_POOL2 "I)I", FN_PTR(isResolvedInvokeHandleInPool)},

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,19 @@ int decodeIndyIndexToCPIndex(HotSpotConstantPool constantPool, int encoded_indy_
435435

436436
private native int decodeIndyIndexToCPIndex(HotSpotConstantPool constantPool, long constantPoolPointer, int encoded_indy_index, boolean resolve);
437437

438+
/**
439+
* Converts the {@code rawIndex} operand of a rewritten getfield/putfield/getstatic/putstatic instruction
440+
* to an index directly into {@code constantPool}.
441+
*
442+
* @throws IllegalArgumentException if {@code rawIndex} is out of range.
443+
* @return {@code JVM_CONSTANT_FieldRef} constant pool entry index for the invokedynamic
444+
*/
445+
int decodeFieldIndexToCPIndex(HotSpotConstantPool constantPool, int rawIndex) {
446+
return decodeFieldIndexToCPIndex(constantPool, constantPool.getConstantPoolPointer(), rawIndex);
447+
}
448+
449+
private native int decodeFieldIndexToCPIndex(HotSpotConstantPool constantPool, long constantPoolPointer, int rawIndex);
450+
438451
/**
439452
* Resolves the details for invoking the bootstrap method associated with the
440453
* {@code CONSTANT_Dynamic_info} or @{code CONSTANT_InvokeDynamic_info} entry at {@code cpi} in
@@ -507,8 +520,8 @@ HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool
507520
private native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, long constantPoolPointer, int cpi) throws LinkageError;
508521

509522
/**
510-
* Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index
511-
* {@code cpi} in {@code constantPool}. For some opcodes, checks are performed that require the
523+
* Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry denoted by
524+
* {@code rawIndex}. For some opcodes, checks are performed that require the
512525
* {@code method} that contains {@code opcode} to be specified. The values returned in
513526
* {@code info} are:
514527
*
@@ -520,19 +533,18 @@ HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool
520533
* ]
521534
* </pre>
522535
*
523-
* The behavior of this method is undefined if {@code cpi} does not denote a
524-
* {@code JVM_CONSTANT_Field} entry.
536+
* The behavior of this method is undefined if {@code rawIndex} is invalid.
525537
*
526538
* @param info an array in which the details of the field are returned
527539
* @return the type defining the field if resolution is successful, null otherwise
528540
*/
529-
HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info) {
541+
HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int rawIndex, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info) {
530542
long methodPointer = method != null ? method.getMethodPointer() : 0L;
531-
return resolveFieldInPool(constantPool, constantPool.getConstantPoolPointer(), cpi, method, methodPointer, opcode, info);
543+
return resolveFieldInPool(constantPool, constantPool.getConstantPoolPointer(), rawIndex, method, methodPointer, opcode, info);
532544
}
533545

534546
private native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, long constantPoolPointer,
535-
int cpi, HotSpotResolvedJavaMethodImpl method, long methodPointer, byte opcode, int[] info);
547+
int rawIndex, HotSpotResolvedJavaMethodImpl method, long methodPointer, byte opcode, int[] info);
536548

537549
/**
538550
* Converts {@code cpci} from an index into the cache for {@code constantPool} to an index

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -260,14 +260,10 @@ private static int rawIndexToConstantPoolCacheIndex(int rawIndex, int opcode) {
260260
throw new IllegalArgumentException("not an invokedynamic constant pool index " + index);
261261
}
262262
} else {
263-
if (opcode == Bytecodes.GETFIELD ||
264-
opcode == Bytecodes.PUTFIELD ||
265-
opcode == Bytecodes.GETSTATIC ||
266-
opcode == Bytecodes.PUTSTATIC ||
267-
opcode == Bytecodes.INVOKEINTERFACE ||
268-
opcode == Bytecodes.INVOKEVIRTUAL ||
269-
opcode == Bytecodes.INVOKESPECIAL ||
270-
opcode == Bytecodes.INVOKESTATIC) {
263+
if (opcode == Bytecodes.INVOKEINTERFACE ||
264+
opcode == Bytecodes.INVOKEVIRTUAL ||
265+
opcode == Bytecodes.INVOKESPECIAL ||
266+
opcode == Bytecodes.INVOKESTATIC) {
271267
index = rawIndex + config().constantPoolCpCacheIndexTag;
272268
} else {
273269
throw new IllegalArgumentException("unexpected opcode " + opcode);
@@ -748,8 +744,8 @@ public JavaType lookupType(int cpi, int opcode) {
748744
}
749745

750746
@Override
751-
public JavaType lookupReferencedType(int cpi, int opcode) {
752-
int index;
747+
public JavaType lookupReferencedType(int rawIndex, int opcode) {
748+
int cpi;
753749
switch (opcode) {
754750
case Bytecodes.CHECKCAST:
755751
case Bytecodes.INSTANCEOF:
@@ -759,43 +755,45 @@ public JavaType lookupReferencedType(int cpi, int opcode) {
759755
case Bytecodes.LDC:
760756
case Bytecodes.LDC_W:
761757
case Bytecodes.LDC2_W:
762-
index = cpi;
758+
cpi = rawIndex;
763759
break;
764760
case Bytecodes.GETSTATIC:
765761
case Bytecodes.PUTSTATIC:
766762
case Bytecodes.GETFIELD:
767763
case Bytecodes.PUTFIELD:
764+
cpi = getKlassRefIndexAt(rawIndex, opcode);
765+
break;
768766
case Bytecodes.INVOKEVIRTUAL:
769767
case Bytecodes.INVOKESPECIAL:
770768
case Bytecodes.INVOKESTATIC:
771769
case Bytecodes.INVOKEINTERFACE: {
772-
index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
773-
index = getKlassRefIndexAt(index, opcode);
770+
int cpci = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
771+
cpi = getKlassRefIndexAt(cpci, opcode);
774772
break;
775773
}
776774
default:
777775
throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
778776
}
779-
final Object type = compilerToVM().lookupKlassInPool(this, index);
777+
final Object type = compilerToVM().lookupKlassInPool(this, cpi);
780778
return getJavaType(type);
781779
}
782780

783781
@Override
784-
public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
785-
final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
786-
final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index, opcode);
782+
public JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode) {
783+
final int cpi = compilerToVM().decodeFieldIndexToCPIndex(this, rawIndex);
784+
final int nameAndTypeIndex = getNameAndTypeRefIndexAt(rawIndex, opcode);
787785
final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
788786
String typeName = lookupUtf8(typeIndex);
789787
JavaType type = runtime().lookupType(typeName, getHolder(), false);
790788

791-
final int holderIndex = getKlassRefIndexAt(index, opcode);
789+
final int holderIndex = getKlassRefIndexAt(rawIndex, opcode);
792790
JavaType fieldHolder = lookupType(holderIndex, opcode);
793791

794792
if (fieldHolder instanceof HotSpotResolvedObjectTypeImpl) {
795793
int[] info = new int[4];
796794
HotSpotResolvedObjectTypeImpl resolvedHolder;
797795
try {
798-
resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
796+
resolvedHolder = compilerToVM().resolveFieldInPool(this, rawIndex, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
799797
} catch (Throwable t) {
800798
/*
801799
* If there was an exception resolving the field we give up and return an unresolved
@@ -833,19 +831,25 @@ public int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
833831
if (opcode == Bytecodes.INVOKEDYNAMIC) {
834832
throw new IllegalArgumentException("unexpected INVOKEDYNAMIC at " + rawIndex);
835833
}
834+
if (opcode == Bytecodes.GETSTATIC ||
835+
opcode == Bytecodes.PUTSTATIC ||
836+
opcode == Bytecodes.GETFIELD ||
837+
opcode == Bytecodes.PUTFIELD) {
838+
return compilerToVM().decodeFieldIndexToCPIndex(this, rawIndex);
839+
}
836840
int index = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
837841
return compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
838842
}
839843

840844
@Override
841-
public void loadReferencedType(int cpi, int opcode) {
842-
loadReferencedType(cpi, opcode, true /* initialize */);
845+
public void loadReferencedType(int rawIndex, int opcode) {
846+
loadReferencedType(rawIndex, opcode, true /* initialize */);
843847
}
844848

845849
@Override
846850
@SuppressWarnings("fallthrough")
847-
public void loadReferencedType(int cpi, int opcode, boolean initialize) {
848-
int index;
851+
public void loadReferencedType(int rawIndex, int opcode, boolean initialize) {
852+
int cpi;
849853
switch (opcode) {
850854
case Bytecodes.CHECKCAST:
851855
case Bytecodes.INSTANCEOF:
@@ -855,57 +859,59 @@ public void loadReferencedType(int cpi, int opcode, boolean initialize) {
855859
case Bytecodes.LDC:
856860
case Bytecodes.LDC_W:
857861
case Bytecodes.LDC2_W:
858-
index = cpi;
862+
cpi = rawIndex;
859863
break;
860864
case Bytecodes.INVOKEDYNAMIC: {
861865
// invokedynamic indices are different from constant pool cache indices
862-
if (!isInvokedynamicIndex(cpi)) {
863-
throw new IllegalArgumentException("must use invokedynamic index but got " + cpi);
866+
if (!isInvokedynamicIndex(rawIndex)) {
867+
throw new IllegalArgumentException("must use invokedynamic index but got " + rawIndex);
864868
}
865-
index = compilerToVM().decodeIndyIndexToCPIndex(this, cpi, true);
869+
cpi = compilerToVM().decodeIndyIndexToCPIndex(this, rawIndex, true);
866870
break;
867871
}
868872
case Bytecodes.GETSTATIC:
869873
case Bytecodes.PUTSTATIC:
870874
case Bytecodes.GETFIELD:
871875
case Bytecodes.PUTFIELD:
876+
cpi = compilerToVM().decodeFieldIndexToCPIndex(this, rawIndex);
877+
break;
872878
case Bytecodes.INVOKEVIRTUAL:
873879
case Bytecodes.INVOKESPECIAL:
874880
case Bytecodes.INVOKESTATIC:
875881
case Bytecodes.INVOKEINTERFACE: {
876882
// invoke and field instructions point to a constant pool cache entry.
877-
index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
878-
index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
883+
int cpci = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
884+
cpi = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, cpci);
879885
break;
880886
}
881887
default:
882888
throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
883889
}
884890

885-
final JvmConstant tag = getTagAt(index);
891+
final JvmConstant tag = getTagAt(cpi);
886892
if (tag == null) {
887-
assert getTagAt(index - 1) == constants.jvmDouble || getTagAt(index - 1) == constants.jvmLong;
893+
assert getTagAt(cpi - 1) == constants.jvmDouble || getTagAt(cpi - 1) == constants.jvmLong;
888894
return;
889895
}
890896
switch (tag.name) {
891897
case "Methodref":
892898
case "Fieldref":
893899
case "InterfaceMethodref":
894-
index = getUncachedKlassRefIndexAt(index);
900+
cpi = getUncachedKlassRefIndexAt(cpi);
895901
// Read the tag only once because it could change between multiple reads.
896-
final JvmConstant klassTag = getTagAt(index);
902+
final JvmConstant klassTag = getTagAt(cpi);
897903
assert klassTag == constants.jvmClass || klassTag == constants.jvmUnresolvedClass || klassTag == constants.jvmUnresolvedClassInError : klassTag;
898904
// fall through
899905
case "Class":
900906
case "UnresolvedClass":
901907
case "UnresolvedClassInError":
902-
final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index);
908+
final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, cpi);
903909
if (initialize && !type.isPrimitive() && !type.isArray()) {
904910
type.ensureInitialized();
905911
}
906912
if (tag == constants.jvmMethodref) {
907913
if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
908-
final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
914+
final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
909915
checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
910916
compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
911917
}

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ConstantPool.java

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,14 @@
2929
* Represents the runtime representation of the constant pool that is used by the compiler when
3030
* parsing bytecode. Provides methods to look up a constant pool entry without performing
3131
* resolution. They are used during compilation.
32+
*
33+
* The following convention is used when accessing the ConstantPool with an index:
34+
* <ul>
35+
* <li>rawIndex - index in the bytecode stream after the opcode (could be rewritten for some opcodes)</li>
36+
* <li>cpi - the constant pool index (as specified in JVM Spec)</li>
37+
* </ul>
38+
*
39+
* Some of the methods are currently not using the convention correctly. That will be addressed in JDK-8314172.
3240
*/
3341
public interface ConstantPool {
3442

@@ -44,53 +52,50 @@ public interface ConstantPool {
4452
* initialized. This can be used to compile time resolve a type. It works for field, method, or
4553
* type constant pool entries.
4654
*
47-
* @param cpi the index of the constant pool entry that references the type
55+
* @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
4856
* @param opcode the opcode of the instruction that references the type
4957
*/
50-
void loadReferencedType(int cpi, int opcode);
58+
void loadReferencedType(int rawIndex, int opcode);
5159

5260
/**
5361
* Ensures that the type referenced by the specified constant pool entry is loaded. This can be
5462
* used to compile time resolve a type. It works for field, method, or type constant pool
5563
* entries.
5664
*
57-
* @param cpi the index of the constant pool entry that references the type
65+
* @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
5866
* @param opcode the opcode of the instruction that references the type
5967
* @param initialize if {@code true}, the referenced type is either guaranteed to be initialized
6068
* upon return or an initialization exception is thrown
6169
*/
62-
default void loadReferencedType(int cpi, int opcode, boolean initialize) {
70+
default void loadReferencedType(int rawIndex, int opcode, boolean initialize) {
6371
if (initialize) {
64-
loadReferencedType(cpi, opcode);
72+
loadReferencedType(rawIndex, opcode);
6573
} else {
6674
throw new UnsupportedOperationException();
6775
}
6876
}
6977

7078
/**
71-
* Looks up the type referenced by the constant pool entry at {@code cpi} as referenced by the
72-
* {@code opcode} bytecode instruction.
79+
* Looks up the type referenced by the {@code rawIndex}.
7380
*
74-
* @param cpi the index of a constant pool entry that references a type
75-
* @param opcode the opcode of the instruction with {@code cpi} as an operand
81+
* @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
82+
* @param opcode the opcode of the instruction with {@code rawIndex} as an operand
7683
* @return a reference to the compiler interface type
7784
*/
78-
JavaType lookupReferencedType(int cpi, int opcode);
85+
JavaType lookupReferencedType(int rawIndex, int opcode);
7986

8087
/**
81-
* Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks
88+
* Looks up a reference to a field. Resolution checks
8289
* specific to the bytecode it denotes are performed if the field is already resolved. Checks
8390
* for some bytecodes require the method that contains the bytecode to be specified. Should any
8491
* of these checks fail, an unresolved field reference is returned.
8592
*
86-
* @param cpi the constant pool index
87-
* @param opcode the opcode of the instruction for which the lookup is being performed or
88-
* {@code -1}
93+
* @param rawIndex rewritten index in the bytecode stream after the {@code opcode}
94+
* @param opcode the opcode of the instruction for which the lookup is being performed
8995
* @param method the method for which the lookup is being performed
90-
* @return a reference to the field at {@code cpi} in this pool
91-
* @throws ClassFormatError if the entry at {@code cpi} is not a field
96+
* @return a reference to the field at {@code rawIndex} in this pool
9297
*/
93-
JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode);
98+
JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode);
9499

95100
/**
96101
* Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks

0 commit comments

Comments
 (0)