Skip to content

Commit

Permalink
Merge pull request #10120 from theresa-m/sealedclasses
Browse files Browse the repository at this point in the history
Part 1: JEP 360 Sealed Classes
  • Loading branch information
gacholio committed Jul 14, 2020
2 parents f88d231 + 11d6161 commit 01cb796
Show file tree
Hide file tree
Showing 30 changed files with 794 additions and 147 deletions.
31 changes: 31 additions & 0 deletions jcl/src/java.base/share/classes/java/lang/Class.java
Expand Up @@ -4732,6 +4732,37 @@ public RecordComponent[] getRecordComponents() {
/*[ENDIF] Java14 */

/*[IF Java15]*/
/**
* Returns true if class or interface is sealed.
*
* @return true if class is sealed, false otherwise
*/
public native boolean isSealed();

/**
* Returns an array of permitted subclasses as ClassDesc objects related to the calling class.
*
* @return array of ClassDesc objects.
* For a class that is not sealed, an empty array is returned.
*/
@CallerSensitive
public ClassDesc[] permittedSubclasses() {
if (!isSealed()) {
return new ClassDesc[0];
}

String[] permittedSubclassesNames = permittedSubclassesImpl();
ClassDesc[] permittedSubclasses = new ClassDesc[permittedSubclassesNames.length];

for (int i = 0; i < permittedSubclassesNames.length; i++) {
String subclassName = permittedSubclassesNames[i];
permittedSubclasses[i] = ClassDesc.of(permittedSubclassesNames[i]);
}
return permittedSubclasses;
}

private native String[] permittedSubclassesImpl();

// TODO: implement support for hidden classes.
public boolean isHidden() {
return false;
Expand Down
13 changes: 12 additions & 1 deletion runtime/bcutil/ClassFileOracle.cpp
Expand Up @@ -188,7 +188,9 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
_isInnerClass(false),
_needsStaticConstantInit(false),
_isRecord(false),
_recordComponentCount(0)
_recordComponentCount(0),
_permittedSubclassesAttribute(NULL),
_isSealed(false)
{
Trc_BCU_Assert_NotEquals( classFile, NULL );

Expand Down Expand Up @@ -494,6 +496,15 @@ ClassFileOracle::walkAttributes()
walkRecordComponents((J9CfrAttributeRecord *)attrib);
break;
}
case CFR_ATTRIBUTE_PermittedSubclasses: {
_isSealed = true;
_permittedSubclassesAttribute = (J9CfrAttributePermittedSubclasses *)attrib;
for (U_16 numberOfClasses = 0; numberOfClasses < _permittedSubclassesAttribute->numberOfClasses; numberOfClasses++) {
U_16 classCpIndex = _permittedSubclassesAttribute->classes[numberOfClasses];
markClassAsReferenced(classCpIndex);
}
break;
}
#if JAVA_SPEC_VERSION >= 11
case CFR_ATTRIBUTE_NestMembers:
_nestMembers = (J9CfrAttributeNestMembers *)attrib;
Expand Down
14 changes: 14 additions & 0 deletions runtime/bcutil/ClassFileOracle.hpp
Expand Up @@ -973,6 +973,18 @@ class RecordComponentIterator
bool needsStaticConstantInit() const { return _needsStaticConstantInit; }
bool isRecord() const { return _isRecord; }
U_16 getRecordComponentCount() const { return _recordComponentCount; }
bool isSealed() const { return _isSealed; }
U_16 getPermittedSubclassesClassCount() const { return _isSealed ? _permittedSubclassesAttribute->numberOfClasses : 0; }

U_16 getPermittedSubclassesClassNameAtIndex(U_16 index) const {
U_16 result = 0;
if (_isSealed) {
U_16 classCpIndex = _permittedSubclassesAttribute->classes[index];
result = _classFile->constantPool[classCpIndex].slot1;
}
return result;
}


U_8 constantDynamicType(U_16 cpIndex) const
{
Expand Down Expand Up @@ -1050,6 +1062,7 @@ class RecordComponentIterator
bool _isInnerClass;
bool _needsStaticConstantInit;
bool _isRecord;
bool _isSealed;

FieldInfo *_fieldsInfo;
MethodInfo *_methodsInfo;
Expand All @@ -1063,6 +1076,7 @@ class RecordComponentIterator
J9CfrAttributeRuntimeVisibleTypeAnnotations *_typeAnnotationsAttribute;
J9CfrAttributeInnerClasses *_innerClasses;
J9CfrAttributeBootstrapMethods *_bootstrapMethodsAttribute;
J9CfrAttributePermittedSubclasses *_permittedSubclassesAttribute;
#if JAVA_SPEC_VERSION >= 11
J9CfrAttributeNestMembers *_nestMembers;
#endif /* JAVA_SPEC_VERSION >= 11 */
Expand Down
9 changes: 8 additions & 1 deletion runtime/bcutil/ROMClassBuilder.cpp
Expand Up @@ -1062,7 +1062,7 @@ ROMClassBuilder::finishPrepareAndLaydown(
* + UNUSED
*
* + UNUSED
* + UNUSED
* + AccSealed
* + AccRecord
* + AccClassAnonClass
*
Expand Down Expand Up @@ -1205,6 +1205,10 @@ ROMClassBuilder::computeExtraModifiers(ClassFileOracle *classFileOracle, ROMClas
modifiers |= J9AccRecord;
}

if (classFileOracle->isSealed()) {
modifiers |= J9AccSealed;
}

return modifiers;
}

Expand Down Expand Up @@ -1242,6 +1246,9 @@ ROMClassBuilder::computeOptionalFlags(ClassFileOracle *classFileOracle, ROMClass
if (classFileOracle->isRecord()) {
optionalFlags |= J9_ROMCLASS_OPTINFO_RECORD_ATTRIBUTE;
}
if (classFileOracle->isSealed()) {
optionalFlags |= J9_ROMCLASS_OPTINFO_PERMITTEDSUBCLASSES_ATTRIBUTE;
}
return optionalFlags;
}

Expand Down
38 changes: 37 additions & 1 deletion runtime/bcutil/ROMClassWriter.cpp
Expand Up @@ -309,7 +309,8 @@ ROMClassWriter::ROMClassWriter(BufferManager *bufferManager, ClassFileOracle *cl
_callSiteDataSRPKey(srpKeyProducer->generateKey()),
_staticSplitTableSRPKey(srpKeyProducer->generateKey()),
_specialSplitTableSRPKey(srpKeyProducer->generateKey()),
_varHandleMethodTypeLookupTableSRPKey(srpKeyProducer->generateKey())
_varHandleMethodTypeLookupTableSRPKey(srpKeyProducer->generateKey()),
_permittedSubclassesInfoSRPKey(srpKeyProducer->generateKey())
{
_methodNotes = (MethodNotes *) _bufferManager->alloc(classFileOracle->getMethodsCount() * sizeof(MethodNotes));
if (NULL == _methodNotes) {
Expand Down Expand Up @@ -427,6 +428,7 @@ ROMClassWriter::writeROMClass(Cursor *cursor,
writeAnnotationInfo(cursor);
writeSourceDebugExtension(cursor);
writeRecordComponents(cursor, markAndCountOnly);
writePermittedSubclasses(cursor, markAndCountOnly);
writeOptionalInfo(cursor);
writeCallSiteData(cursor, markAndCountOnly);
writeVarHandleMethodTypeLookupTable(cursor, markAndCountOnly);
Expand Down Expand Up @@ -1734,6 +1736,36 @@ ROMClassWriter::writeRecordComponents(Cursor *cursor, bool markAndCountOnly)
}
}

/*
* PermittedSubclasses ROM class layout:
* 4 bytes for number of classes (actually takes up two, but use 4 for alignment)
* for number of classes:
* 4 byte SRP to class name
*/
void
ROMClassWriter::writePermittedSubclasses(Cursor *cursor, bool markAndCountOnly)
{
if (_classFileOracle->isSealed()) {
cursor->mark(_permittedSubclassesInfoSRPKey);

U_16 classCount = _classFileOracle->getPermittedSubclassesClassCount();
if (markAndCountOnly) {
cursor->skip(sizeof(U_32));
} else {
cursor->writeU32(classCount, Cursor::GENERIC);
}

for (U_16 index = 0; index < classCount; index++) {
if (markAndCountOnly) {
cursor->skip(sizeof(J9SRP));
} else {
U_16 classNameCpIndex = _classFileOracle->getPermittedSubclassesClassNameAtIndex(index);
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(classNameCpIndex), Cursor::SRP_TO_UTF8);
}
}
}
}

void
ROMClassWriter::writeOptionalInfo(Cursor *cursor)
{
Expand Down Expand Up @@ -1769,6 +1801,7 @@ ROMClassWriter::writeOptionalInfo(Cursor *cursor)
* SRP to class annotations
* SRP to class Type Annotations
* SRP to record class component attributes
* SRP to PermittedSubclasses attribute
*/
cursor->mark(_optionalInfoSRPKey);

Expand Down Expand Up @@ -1807,6 +1840,9 @@ ROMClassWriter::writeOptionalInfo(Cursor *cursor)
if (_classFileOracle->isRecord()) {
cursor->writeSRP(_recordInfoSRPKey, Cursor::SRP_TO_GENERIC);
}
if (_classFileOracle->isSealed()) {
cursor->writeSRP(_permittedSubclassesInfoSRPKey, Cursor::SRP_TO_GENERIC);
}
}

void
Expand Down
2 changes: 2 additions & 0 deletions runtime/bcutil/ROMClassWriter.hpp
Expand Up @@ -144,6 +144,7 @@ class ROMClassWriter
void writeByteCodes(Cursor *cursor, ClassFileOracle::MethodIterator *methodIterator);
U_32 computeNativeSignatureSize(U_8 *methodDescriptor);
void writeNativeSignature(Cursor *cursor, U_8 *methodDescriptor, U_8 nativeArgCount);
void writePermittedSubclasses(Cursor *cursor, bool markAndCountOnly);

BufferManager *_bufferManager;
ClassFileOracle *_classFileOracle;
Expand Down Expand Up @@ -173,6 +174,7 @@ class ROMClassWriter
UDATA _staticSplitTableSRPKey;
UDATA _specialSplitTableSRPKey;
UDATA _recordInfoSRPKey;
UDATA _permittedSubclassesInfoSRPKey;
};

#endif /* ROMCLASSWRITER_HPP_ */
1 change: 1 addition & 0 deletions runtime/bcutil/attrlookup.gperf
Expand Up @@ -71,3 +71,4 @@ MethodParameters, CFR_ATTRIBUTE_MethodParameters, CFR_ATTRIBUTE_MethodParameters
NestMembers, CFR_ATTRIBUTE_NestMembers, CFR_ATTRIBUTE_NestMembers
NestHost, CFR_ATTRIBUTE_NestHost, CFR_ATTRIBUTE_NestHost
Record, CFR_ATTRIBUTE_Record, CFR_ATTRIBUTE_Record
PermittedSubclasses, CFR_ATTRIBUTE_PermittedSubclasses, CFR_ATTRIBUTE_PermittedSubclasses
107 changes: 55 additions & 52 deletions runtime/bcutil/attrlookup.h
Expand Up @@ -59,12 +59,12 @@ struct AttribType
U_8 strippedAttribCode;
};

#define TOTAL_KEYWORDS 27
#define TOTAL_KEYWORDS 28
#define MIN_WORD_LENGTH 4
#define MAX_WORD_LENGTH 36
#define MIN_HASH_VALUE 4
#define MAX_HASH_VALUE 37
/* maximum key range = 34, duplicates = 0 */
#define MAX_HASH_VALUE 50
/* maximum key range = 47, duplicates = 0 */

#ifdef __GNUC__
__inline
Expand All @@ -78,32 +78,32 @@ attributeHash (register const char *str, register unsigned int len)
{
static const unsigned char asso_values[] =
{
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 1, 38, 38, 38, 15, 38, 38, 38, 38,
20, 0, 38, 38, 38, 38, 15, 0, 38, 38,
5, 5, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 31, 51, 51, 51, 15, 51, 51, 51, 51,
0, 0, 51, 51, 51, 51, 15, 0, 51, 51,
25, 0, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51
};
return len + asso_values[(unsigned char)str[1]];
}
Expand All @@ -121,26 +121,20 @@ lookupKnownAttribute (register const char *str, register unsigned int len)
{
#line 47 "attrlookup.gperf"
{"Code", CFR_ATTRIBUTE_Code, CFR_ATTRIBUTE_Code},
#line 73 "attrlookup.gperf"
{"Record", CFR_ATTRIBUTE_Record, CFR_ATTRIBUTE_Record},
#line 72 "attrlookup.gperf"
{"NestHost", CFR_ATTRIBUTE_NestHost, CFR_ATTRIBUTE_NestHost},
#line 49 "attrlookup.gperf"
{"Synthetic", CFR_ATTRIBUTE_Synthetic, CFR_ATTRIBUTE_Synthetic},
#line 53 "attrlookup.gperf"
{"SourceFile", CFR_ATTRIBUTE_SourceFile, CFR_ATTRIBUTE_SourceFile},
#line 51 "attrlookup.gperf"
{"Deprecated", CFR_ATTRIBUTE_Deprecated, CFR_ATTRIBUTE_Deprecated},
#line 71 "attrlookup.gperf"
{"NestMembers", CFR_ATTRIBUTE_NestMembers, CFR_ATTRIBUTE_NestMembers},
#line 54 "attrlookup.gperf"
{"InnerClasses", CFR_ATTRIBUTE_InnerClasses, CFR_ATTRIBUTE_InnerClasses},
#line 55 "attrlookup.gperf"
{"ConstantValue", CFR_ATTRIBUTE_ConstantValue, CFR_ATTRIBUTE_ConstantValue},
#line 49 "attrlookup.gperf"
{"Synthetic", CFR_ATTRIBUTE_Synthetic, CFR_ATTRIBUTE_Synthetic},
#line 52 "attrlookup.gperf"
{"Exceptions", CFR_ATTRIBUTE_Exceptions, CFR_ATTRIBUTE_Exceptions},
#line 57 "attrlookup.gperf"
{"EnclosingMethod", CFR_ATTRIBUTE_EnclosingMethod, CFR_ATTRIBUTE_EnclosingMethod},
#line 59 "attrlookup.gperf"
{"BootstrapMethods", CFR_ATTRIBUTE_BootstrapMethods, CFR_ATTRIBUTE_BootstrapMethods},
#line 70 "attrlookup.gperf"
{"MethodParameters", CFR_ATTRIBUTE_MethodParameters, CFR_ATTRIBUTE_MethodParameters},
#line 60 "attrlookup.gperf"
{"AnnotationDefault", CFR_ATTRIBUTE_AnnotationDefault, CFR_ATTRIBUTE_AnnotationDefault},
#line 61 "attrlookup.gperf"
{"LocalVariableTable", CFR_ATTRIBUTE_LocalVariableTable, CFR_ATTRIBUTE_StrippedLocalVariableTable},
#line 62 "attrlookup.gperf"
Expand All @@ -163,23 +157,32 @@ lookupKnownAttribute (register const char *str, register unsigned int len)
{"LineNumberTable", CFR_ATTRIBUTE_LineNumberTable, CFR_ATTRIBUTE_StrippedLineNumberTable},
#line 67 "attrlookup.gperf"
{"RuntimeInvisibleTypeAnnotations", CFR_ATTRIBUTE_RuntimeInvisibleTypeAnnotations, CFR_ATTRIBUTE_RuntimeInvisibleTypeAnnotations},
#line 54 "attrlookup.gperf"
{"InnerClasses", CFR_ATTRIBUTE_InnerClasses, CFR_ATTRIBUTE_InnerClasses},
#line 68 "attrlookup.gperf"
{"RuntimeVisibleParameterAnnotations", CFR_ATTRIBUTE_RuntimeVisibleParameterAnnotations, CFR_ATTRIBUTE_RuntimeVisibleParameterAnnotations},
#line 57 "attrlookup.gperf"
{"EnclosingMethod", CFR_ATTRIBUTE_EnclosingMethod, CFR_ATTRIBUTE_EnclosingMethod},
#line 52 "attrlookup.gperf"
{"Exceptions", CFR_ATTRIBUTE_Exceptions, CFR_ATTRIBUTE_Exceptions},
#line 69 "attrlookup.gperf"
{"RuntimeInvisibleParameterAnnotations", CFR_ATTRIBUTE_RuntimeInvisibleParameterAnnotations, CFR_ATTRIBUTE_RuntimeInvisibleParameterAnnotations},
#line 60 "attrlookup.gperf"
{"AnnotationDefault", CFR_ATTRIBUTE_AnnotationDefault, CFR_ATTRIBUTE_AnnotationDefault}
#line 73 "attrlookup.gperf"
{"Record", CFR_ATTRIBUTE_Record, CFR_ATTRIBUTE_Record},
#line 72 "attrlookup.gperf"
{"NestHost", CFR_ATTRIBUTE_NestHost, CFR_ATTRIBUTE_NestHost},
#line 51 "attrlookup.gperf"
{"Deprecated", CFR_ATTRIBUTE_Deprecated, CFR_ATTRIBUTE_Deprecated},
#line 71 "attrlookup.gperf"
{"NestMembers", CFR_ATTRIBUTE_NestMembers, CFR_ATTRIBUTE_NestMembers},
#line 70 "attrlookup.gperf"
{"MethodParameters", CFR_ATTRIBUTE_MethodParameters, CFR_ATTRIBUTE_MethodParameters},
#line 74 "attrlookup.gperf"
{"PermittedSubclasses", CFR_ATTRIBUTE_PermittedSubclasses, CFR_ATTRIBUTE_PermittedSubclasses}
};

static const signed char lookup[] =
{
-1, -1, -1, -1, 0, -1, -1, 1, -1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, -1, 12, -1, 13, 14, 15, 16, -1, 17,
18, 19, 20, 21, 22, -1, 23, 24, 25, 26
-1, -1, -1, -1, 0, -1, -1, -1, -1, 1, 2, -1, 3, 4,
-1, 5, 6, 7, 8, -1, 9, -1, 10, 11, 12, 13, -1, 14,
15, 16, 17, 18, -1, -1, 19, 20, 21, 22, -1, 23, -1, 24,
25, -1, -1, -1, -1, 26, -1, -1, 27
};

if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
Expand Down

0 comments on commit 01cb796

Please sign in to comment.