Skip to content

Commit

Permalink
Merge pull request #8061 from theresa-m/records_isrecord
Browse files Browse the repository at this point in the history
JEP 359 part1: attribute & isRecord support
  • Loading branch information
DanHeidinga committed Feb 8, 2020
2 parents e84b6f0 + 36e92bf commit 6a356f9
Show file tree
Hide file tree
Showing 25 changed files with 693 additions and 94 deletions.
9 changes: 2 additions & 7 deletions jcl/src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*[INCLUDE-IF Sidecar18-SE]*/
/*******************************************************************************
* Copyright (c) 1998, 2019 IBM Corp. and others
* Copyright (c) 1998, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -4694,14 +4694,9 @@ public String descriptorString() {
/**
* Returns true if the class instance is a record.
*
* Note: current implementation is a stub and always returns false.
* For JEP 359 support see https://github.com/eclipse/openj9/pull/7946
*
* @return true for a record class, false otherwise
*/
public boolean isRecord() {
return false;
}
public native boolean isRecord();

/**
* Returns an array of RecordComponent objects for a record class.
Expand Down
66 changes: 64 additions & 2 deletions runtime/bcutil/ClassFileOracle.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2019 IBM Corp. and others
* Copyright (c) 2001, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -171,6 +171,7 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
_annotationRefersDoubleSlotEntry(false),
_fieldsInfo(NULL),
_methodsInfo(NULL),
_recordComponentsInfo(NULL),
_genericSignature(NULL),
_enclosingMethod(NULL),
_sourceFile(NULL),
Expand All @@ -185,7 +186,9 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
_isClassContended(false),
_isClassUnmodifiable(context->isClassUnmodifiable()),
_isInnerClass(false),
_needsStaticConstantInit(false)
_needsStaticConstantInit(false),
_isRecord(false),
_recordComponentCount(0)
{
Trc_BCU_Assert_NotEquals( classFile, NULL );

Expand Down Expand Up @@ -486,6 +489,11 @@ ClassFileOracle::walkAttributes()
}
break;
}
case CFR_ATTRIBUTE_Record: {
_isRecord = true;
walkRecordComponents((J9CfrAttributeRecord *)attrib);
break;
}
#if defined(J9VM_OPT_VALHALLA_NESTMATES)
case CFR_ATTRIBUTE_NestMembers:
_nestMembers = (J9CfrAttributeNestMembers *)attrib;
Expand Down Expand Up @@ -521,6 +529,60 @@ ClassFileOracle::walkAttributes()
}
}

void
ClassFileOracle::walkRecordComponents(J9CfrAttributeRecord *attrib)
{
ROMClassVerbosePhase v(_context, ClassFileAttributesRecordAnalysis);

if (0 == attrib->numberOfRecordComponents) {
return;
}

_recordComponentCount = attrib->numberOfRecordComponents;

_recordComponentsInfo = (RecordComponentInfo *) _bufferManager->alloc(_recordComponentCount * sizeof(RecordComponentInfo));
if (NULL == _recordComponentsInfo) {
Trc_BCU_ClassFileOracle_OutOfMemory((U_32)getUTF8Length(getClassNameIndex()), getUTF8Data(getClassNameIndex()));
_buildResult = OutOfMemory;
return;
}
memset(_recordComponentsInfo, 0, _recordComponentCount * sizeof(RecordComponentInfo));

for (U_16 i = 0; i < _recordComponentCount; i++) {
J9CfrRecordComponent* recordComponent = &attrib->recordComponents[i];

markConstantUTF8AsReferenced(recordComponent->nameIndex);
_recordComponentsInfo[i].nameIndex = recordComponent->nameIndex;
markConstantUTF8AsReferenced(recordComponent->descriptorIndex);
_recordComponentsInfo[i].descriptorIndex = recordComponent->descriptorIndex;

/* track record component attributes */
for (U_16 j = 0; j < recordComponent->attributesCount; j++) {
J9CfrAttribute* recordComponentAttr = recordComponent->attributes[j];
switch(recordComponentAttr->tag) {
case CFR_ATTRIBUTE_Signature: {
J9CfrAttributeSignature *signature = (J9CfrAttributeSignature *) recordComponentAttr;
markConstantUTF8AsReferenced(signature->signatureIndex);
_recordComponentsInfo[i].hasGenericSignature = true;
_recordComponentsInfo[i].genericSignatureIndex = signature->signatureIndex;
break;
}
case CFR_ATTRIBUTE_RuntimeVisibleAnnotations: {
_recordComponentsInfo[i].annotationsAttribute = (J9CfrAttributeRuntimeVisibleAnnotations *) recordComponentAttr;
break;
}
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
_recordComponentsInfo[i].typeAnnotationsAttribute = (J9CfrAttributeRuntimeVisibleTypeAnnotations *) recordComponentAttr;
break;
}
default:
Trc_BCU_ClassFileOracle_walkRecordComponents_UnknownAttribute((U_32)attrib->tag, (U_32)getUTF8Length(attrib->nameIndex), getUTF8Data(attrib->nameIndex), attrib->length);
break;
}
}
}
}

class ClassFileOracle::InterfaceVisitor : public ClassFileOracle::ConstantPoolIndexVisitor
{
public:
Expand Down
55 changes: 54 additions & 1 deletion runtime/bcutil/ClassFileOracle.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2019 IBM Corp. and others
* Copyright (c) 2001, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -113,6 +113,16 @@ class ClassFileOracle
bool isByteCodeFixupDone;
};

struct RecordComponentInfo
{
bool hasGenericSignature;
U_16 nameIndex;
U_16 descriptorIndex;
U_16 genericSignatureIndex;
J9CfrAttributeRuntimeVisibleAnnotations *annotationsAttribute;
J9CfrAttributeRuntimeVisibleTypeAnnotations *typeAnnotationsAttribute;
};

/*
* Interfaces.
*/
Expand Down Expand Up @@ -587,6 +597,34 @@ class NameAndTypeIterator
J9CfrConstantPoolInfo *_entry;
};

class RecordComponentIterator
{
public:
RecordComponentIterator(RecordComponentInfo *recordComponentsInfo, U_16 recordComponentCount) :
_recordComponentsInfo(recordComponentsInfo),
_recordComponentCount(recordComponentCount),
_index(0)
{
}

U_16 getNameIndex() const { return _recordComponentsInfo[_index].nameIndex; }
U_16 getDescriptorIndex() const { return _recordComponentsInfo[_index].descriptorIndex; }
U_16 getGenericSignatureIndex() const { return _recordComponentsInfo[_index].genericSignatureIndex; }
U_16 getRecordComponentIndex() const { return _index; }

bool hasGenericSignature() const { return _recordComponentsInfo[_index].hasGenericSignature; }
bool hasAnnotation() const { return _recordComponentsInfo[_index].annotationsAttribute != NULL; }
bool hasTypeAnnotation() const { return _recordComponentsInfo[_index].typeAnnotationsAttribute != NULL; }

bool isNotDone() const { return _index < _recordComponentCount; }
void next() { _index++; }

private:
RecordComponentInfo *_recordComponentsInfo;
U_16 _recordComponentCount;
U_16 _index;
};

/*
* Iteration functions.
*/
Expand Down Expand Up @@ -701,6 +739,14 @@ class NameAndTypeIterator
typeAnnotationsDo(methodIndex, _methodsInfo[methodIndex].codeTypeAnnotationsAttribute, annotationsAttributeVisitor, annotationVisitor, annotationElementVisitor);
}

void recordComponentAnnotationDo(U_16 recordComponentIndex, AnnotationsAttributeVisitor *annotationsAttributeVisitor, AnnotationVisitor *annotationVisitor, AnnotationElementVisitor *annotationElementVisitor) {
annotationsDo(recordComponentIndex, _recordComponentsInfo[recordComponentIndex].annotationsAttribute, annotationsAttributeVisitor, annotationVisitor, annotationElementVisitor);
}

void recordComponentTypeAnnotationDo(U_16 recordComponentIndex, AnnotationsAttributeVisitor *annotationsAttributeVisitor, AnnotationVisitor *annotationVisitor, AnnotationElementVisitor *annotationElementVisitor) {
typeAnnotationsDo(recordComponentIndex, _recordComponentsInfo[recordComponentIndex].typeAnnotationsAttribute, annotationsAttributeVisitor, annotationVisitor, annotationElementVisitor);
}

void parameterAnnotationsDo(U_16 methodIndex, AnnotationsAttributeVisitor *annotationsAttributeVisitor, AnnotationVisitor *annotationVisitor, AnnotationElementVisitor *annotationElementVisitor)
{
J9CfrAttributeRuntimeVisibleParameterAnnotations *parameterAnnotationsAttribute = _methodsInfo[methodIndex].parameterAnnotationsAttribute;
Expand Down Expand Up @@ -830,6 +876,7 @@ class NameAndTypeIterator
NameAndTypeIterator getNameAndTypeIterator() const { return NameAndTypeIterator(_classFile); }
FieldIterator getFieldIterator() { return FieldIterator(_fieldsInfo, _classFile); }
MethodIterator getMethodIterator() { return MethodIterator(_methodsInfo, _classFile); }
RecordComponentIterator getRecordComponentIterator() { return RecordComponentIterator(_recordComponentsInfo, _recordComponentCount); }

ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *classFile, ConstantPoolMap *constantPoolMap, U_8 * verifyExcludeAttribute, U_8 * romBuilderClassFileBuffer, ROMClassCreationContext *context);
~ClassFileOracle();
Expand Down Expand Up @@ -924,6 +971,8 @@ class NameAndTypeIterator
bool annotationRefersDoubleSlotEntry() const { return _annotationRefersDoubleSlotEntry; }
bool isInnerClass() const { return _isInnerClass; }
bool needsStaticConstantInit() const { return _needsStaticConstantInit; }
bool isRecord() const { return _isRecord; }
U_16 getRecordComponentCount() const { return _recordComponentCount; }

U_8 constantDynamicType(U_16 cpIndex) const
{
Expand Down Expand Up @@ -983,6 +1032,7 @@ class NameAndTypeIterator
U_32 _maxBranchCount;
U_16 _outerClassNameIndex;
U_16 _simpleNameIndex;
U_16 _recordComponentCount;

bool _hasEmptyFinalizeMethod;
bool _hasFinalFields;
Expand All @@ -999,9 +1049,11 @@ class NameAndTypeIterator
bool _annotationRefersDoubleSlotEntry;
bool _isInnerClass;
bool _needsStaticConstantInit;
bool _isRecord;

FieldInfo *_fieldsInfo;
MethodInfo *_methodsInfo;
RecordComponentInfo *_recordComponentsInfo;

J9CfrAttributeSignature *_genericSignature;
J9CfrAttributeEnclosingMethod *_enclosingMethod;
Expand All @@ -1020,6 +1072,7 @@ class NameAndTypeIterator
void walkAttributes();
void walkInterfaces();
void walkMethods();
void walkRecordComponents(J9CfrAttributeRecord *attrib);

UDATA walkAnnotations(U_16 annotationsCount, J9CfrAnnotation *annotations, UDATA knownAnnotationSet);
void walkTypeAnnotations(U_16 annotationsCount, J9CfrTypeAnnotation *annotations);
Expand Down
11 changes: 8 additions & 3 deletions runtime/bcutil/ROMClassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ ROMClassBuilder::finishPrepareAndLaydown(
*
* + UNUSED
* + UNUSED
* + UNUSED
* + AccRecord
* + AccClassAnonClass
*
* + AccSynthetic (matches Oracle modifier position)
Expand Down Expand Up @@ -1174,8 +1174,6 @@ ROMClassBuilder::computeExtraModifiers(ClassFileOracle *classFileOracle, ROMClas
}
}



if ( classFileOracle->isSynthetic() ) {
/* handle the synthetic attribute. In java 1.5 synthetic may be specified in the access flags as well so do not unset bit here */
// Trc_BCU_createRomClassEndian_Synthetic(romClass);
Expand Down Expand Up @@ -1206,6 +1204,10 @@ ROMClassBuilder::computeExtraModifiers(ClassFileOracle *classFileOracle, ROMClas
modifiers |= J9AccClassNeedsStaticConstantInit;
}

if (classFileOracle->isRecord()) {
modifiers |= J9AccRecord;
}

return modifiers;
}

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

Expand Down
3 changes: 2 additions & 1 deletion runtime/bcutil/ROMClassCreationContext.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2014 IBM Corp. and others
* Copyright (c) 2001, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -59,6 +59,7 @@ ROMClassCreationContext::verbosePrintPhase(ROMClassCreationPhase phase, bool *pr
"ClassFileHeaderAnalysis",
"ClassFileFieldsAnalysis",
"ClassFileAttributesAnalysis",
"ClassFileAttributesRecordAnalysis",
"ClassFileInterfacesAnalysis",
"ClassFileMethodsAnalysis",
"ClassFileMethodAttributesAnalysis",
Expand Down

0 comments on commit 6a356f9

Please sign in to comment.