Path: blob/master/runtime/bcutil/ROMClassWriter.cpp
5985 views
/*******************************************************************************1* Copyright (c) 2001, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21/*22* ROMClassWriter.cpp23*/24#include "ROMClassWriter.hpp"2526#include "BufferManager.hpp"27#include "ClassFileOracle.hpp"28#include "ConstantPoolMap.hpp"29#include "Cursor.hpp"30#include "SRPKeyProducer.hpp"31#include "ROMClassVerbosePhase.hpp"3233#include "bcnames.h"34#include "cfreader.h"35#include "j9.h"36#include "j9protos.h"37#include "ut_j9bcu.h"3839const U_8 PARAM_VOID = 0;40const U_8 PARAM_BOOLEAN = 1;41const U_8 PARAM_BYTE = 2;42const U_8 PARAM_CHAR = 3;43const U_8 PARAM_SHORT = 4;44const U_8 PARAM_FLOAT = 5;45const U_8 PARAM_INT = 6;46const U_8 PARAM_DOUBLE = 7;47const U_8 PARAM_LONG = 8;48const U_8 PARAM_OBJECT = 9;4950class ROMClassWriter::CheckSize51{52public:53CheckSize(Cursor *cursor, UDATA expectedSize) :54_cursor(cursor),55_expectedSize(expectedSize),56_start(cursor->getCount())57{58}5960~CheckSize()61{62Trc_BCU_Assert_Equals(_cursor->getCount() - _start, _expectedSize);63}6465private:66Cursor *_cursor;67UDATA _expectedSize;68UDATA _start;69};7071class ROMClassWriter::AnnotationElementWriter : public ClassFileOracle::AnnotationElementVisitor72{73public:74AnnotationElementWriter(Cursor *cursor, ConstantPoolMap *constantPoolMap, ClassFileOracle *classFileOracle) :75_constantPoolMap(constantPoolMap),76_cursor(cursor),77_classFileOracle(classFileOracle)78{79}8081virtual void visitConstant(U_16 elementNameIndex, U_16 cpIndex, U_8 elementType)82{83_cursor->writeU8(elementType, Cursor::GENERIC);84_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForAnnotation(cpIndex), Cursor::GENERIC);85}8687virtual void visitEnum(U_16 elementNameIndex, U_16 typeNameIndex, U_16 constNameIndex)88{89_cursor->writeU8('e', Cursor::GENERIC);90_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForAnnotation(typeNameIndex), Cursor::GENERIC);91_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForAnnotation(constNameIndex), Cursor::GENERIC);92}9394virtual void visitClass(U_16 elementNameIndex, U_16 cpIndex)95{96AnnotationElementWriter::visitConstant(elementNameIndex, cpIndex, 'c');97}9899virtual void visitArray(U_16 elementNameIndex, U_16 elementCount, ClassFileOracle::ArrayAnnotationElements *arrayAnnotationElements)100{101_cursor->writeU8('[', Cursor::GENERIC);102_cursor->writeBigEndianU16(elementCount, Cursor::GENERIC);103104AnnotationElementWriter annotationElementWriter(_cursor, _constantPoolMap, _classFileOracle);105arrayAnnotationElements->elementsDo(&annotationElementWriter);106}107108virtual void visitNestedAnnotation(U_16 elementNameIndex, ClassFileOracle::NestedAnnotation *nestedAnnotation);109110protected:111ConstantPoolMap *_constantPoolMap;112Cursor *_cursor;113ClassFileOracle *_classFileOracle;114};115116class ROMClassWriter::AnnotationWriter :117public ROMClassWriter::AnnotationElementWriter,118public ClassFileOracle::AnnotationsAttributeVisitor,119public ClassFileOracle::AnnotationVisitor120{121public:122AnnotationWriter(Cursor *cursor, ConstantPoolMap *constantPoolMap, ClassFileOracle *classFileOracle) :123AnnotationElementWriter(cursor, constantPoolMap, classFileOracle)124{125}126127void visitConstant(U_16 elementNameIndex, U_16 cpIndex, U_8 elementType)128{129writeElementName(elementNameIndex);130AnnotationElementWriter::visitConstant(elementNameIndex, cpIndex, elementType);131}132133void visitEnum(U_16 elementNameIndex, U_16 typeNameIndex, U_16 constNameIndex)134{135writeElementName(elementNameIndex);136AnnotationElementWriter::visitEnum(elementNameIndex, typeNameIndex, constNameIndex);137}138139void visitClass(U_16 elementNameIndex, U_16 cpIndex)140{141writeElementName(elementNameIndex);142AnnotationElementWriter::visitClass(elementNameIndex, cpIndex);143}144145void visitArray(U_16 elementNameIndex, U_16 elementCount, ClassFileOracle::ArrayAnnotationElements *arrayAnnotationElements)146{147writeElementName(elementNameIndex);148AnnotationElementWriter::visitArray(elementNameIndex, elementCount, arrayAnnotationElements);149}150151void visitNestedAnnotation(U_16 elementNameIndex, ClassFileOracle::NestedAnnotation *nestedAnnotation)152{153writeElementName(elementNameIndex);154AnnotationElementWriter::visitNestedAnnotation(elementNameIndex, nestedAnnotation);155}156157void visitAnnotationsAttribute(U_16 fieldOrMethodIndex, U_32 length, U_16 numberOfAnnotations)158{159writeAnnotationAttribute(length);160_cursor->writeBigEndianU16(numberOfAnnotations, Cursor::GENERIC);161}162163void visitDefaultAnnotationAttribute(U_16 fieldOrMethodIndex, U_32 length)164{165writeAnnotationAttribute(length);166}167168void visitParameterAnnotationsAttribute(U_16 fieldOrMethodIndex, U_32 length, U_8 numberOfParameters)169{170writeAnnotationAttribute(length);171_cursor->writeU8(numberOfParameters, Cursor::GENERIC);172}173174void visitTypeAnnotationsAttribute(U_16 fieldOrMethodIndex, U_32 length, U_16 numberOfAnnotations)175{176writeAnnotationAttribute(length);177_cursor->writeBigEndianU16(numberOfAnnotations, Cursor::GENERIC);178}179180void visitAnnotation(U_16 typeIndex, U_16 elementValuePairCount)181{182_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForReference(typeIndex), Cursor::GENERIC);183_cursor->writeBigEndianU16(elementValuePairCount, Cursor::GENERIC);184}185186void visitTypeAnnotation(U_8 targetType, J9CfrTypeAnnotationTargetInfo *targetInfo, J9CfrTypePath *typePath)187{188_cursor->writeU8(targetType, Cursor::GENERIC);189switch (targetType) { /* use values from the JVM spec. Java SE 8 Edition, table 4.7.20-A&B */190case CFR_TARGET_TYPE_TypeParameterGenericClass:191case CFR_TARGET_TYPE_TypeParameterGenericMethod:192_cursor->writeU8(targetInfo->typeParameterTarget.typeParameterIndex, Cursor::GENERIC);193break;194case CFR_TARGET_TYPE_TypeInExtends:195_cursor->writeBigEndianU16(targetInfo->supertypeTarget.supertypeIndex, Cursor::GENERIC);196break;197198case CFR_TARGET_TYPE_TypeInBoundOfGenericClass:199case CFR_TARGET_TYPE_TypeInBoundOfGenericMethod:200_cursor->writeU8(targetInfo->typeParameterBoundTarget.typeParameterIndex, Cursor::GENERIC);201_cursor->writeU8(targetInfo->typeParameterBoundTarget.boundIndex, Cursor::GENERIC);202break;203case CFR_TARGET_TYPE_TypeInFieldDecl:204case CFR_TARGET_TYPE_ReturnType:205case CFR_TARGET_TYPE_ReceiverType: /* empty_target */206break;207208case CFR_TARGET_TYPE_TypeInFormalParam:209_cursor->writeU8(targetInfo->methodFormalParameterTarget.formalParameterIndex, Cursor::GENERIC);210break;211212case CFR_TARGET_TYPE_TypeInThrows:213_cursor->writeBigEndianU16(targetInfo->throwsTarget.throwsTypeIndex, Cursor::GENERIC);214break;215216case CFR_TARGET_TYPE_TypeInLocalVar:217case CFR_TARGET_TYPE_TypeInResourceVar: {218J9CfrLocalvarTarget *t = &(targetInfo->localvarTarget);219_cursor->writeBigEndianU16(t->tableLength, Cursor::GENERIC);220for (U_32 ti=0; ti < t->tableLength; ++ti) {221J9CfrLocalvarTargetEntry *te = &(t->table[ti]);222_cursor->writeBigEndianU16(te->startPC, Cursor::GENERIC);223_cursor->writeBigEndianU16(te->length, Cursor::GENERIC);224_cursor->writeBigEndianU16(te->index, Cursor::GENERIC);225}226};227break;228case CFR_TARGET_TYPE_TypeInExceptionParam:229_cursor->writeBigEndianU16(targetInfo->catchTarget.exceptiontableIndex, Cursor::GENERIC);230break;231232case CFR_TARGET_TYPE_TypeInInstanceof:233case CFR_TARGET_TYPE_TypeInNew:234case CFR_TARGET_TYPE_TypeInMethodrefNew:235case CFR_TARGET_TYPE_TypeInMethodrefIdentifier:236_cursor->writeBigEndianU16(targetInfo->offsetTarget.offset, Cursor::GENERIC);237break;238239case CFR_TARGET_TYPE_TypeInCast:240case CFR_TARGET_TYPE_TypeForGenericConstructorInNew:241case CFR_TARGET_TYPE_TypeForGenericMethodInvocation:242case CFR_TARGET_TYPE_TypeForGenericConstructorInMethodRef:243case CFR_TARGET_TYPE_TypeForGenericMethodInvocationInMethodRef:244_cursor->writeBigEndianU16(targetInfo->typeArgumentTarget.offset, Cursor::GENERIC);245_cursor->writeU8(targetInfo->typeArgumentTarget.typeArgumentIndex, Cursor::GENERIC);246break;247248default:249break;250}251_cursor->writeU8(typePath->pathLength, Cursor::GENERIC);252for (U_8 pathIndex = 0; pathIndex < typePath->pathLength; ++pathIndex) {253J9CfrTypePathEntry* pathEntry = &(typePath->path[pathIndex]);254_cursor->writeU8(pathEntry->typePathKind, Cursor::GENERIC);255_cursor->writeU8(pathEntry->typeArgumentIndex, Cursor::GENERIC);256}257}258259void visitMalformedAnnotationsAttribute(U_32 rawDataLength, U_8 *rawAttributeData)260{261writeAnnotationAttribute(rawDataLength);262for (U_32 byteIndex = 0; byteIndex < rawDataLength; ++byteIndex) {263_cursor->writeU8(rawAttributeData[byteIndex], Cursor::GENERIC);264}265266}267268void visitParameter(U_16 numberOfAnnotations)269{270_cursor->writeBigEndianU16(numberOfAnnotations, Cursor::GENERIC);271}272273private:274void writeElementName(U_16 elementNameIndex)275{276_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForReference(elementNameIndex), Cursor::GENERIC);277}278279void writeAnnotationAttribute(U_32 length)280{281_cursor->writeU32(length, Cursor::GENERIC); /* Native Endian */282}283};284#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)285ROMClassWriter::ROMClassWriter(BufferManager *bufferManager, ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, ConstantPoolMap *constantPoolMap, ROMClassCreationContext *context, InterfaceInjectionInfo *interfaceInjectionInfo) :286#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */287ROMClassWriter::ROMClassWriter(BufferManager *bufferManager, ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, ConstantPoolMap *constantPoolMap, ROMClassCreationContext *context) :288#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */289_bufferManager(bufferManager),290_classFileOracle(classFileOracle),291_srpKeyProducer(srpKeyProducer),292_constantPoolMap(constantPoolMap),293_srpOffsetTable(NULL),294_context(context),295#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)296_interfaceInjectionInfo(interfaceInjectionInfo),297#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */298_buildResult(OK),299_interfacesSRPKey(srpKeyProducer->generateKey()),300_methodsSRPKey(srpKeyProducer->generateKey()),301_fieldsSRPKey(srpKeyProducer->generateKey()),302_cpDescriptionShapeSRPKey(srpKeyProducer->generateKey()),303_innerClassesSRPKey(srpKeyProducer->generateKey()),304_enclosedInnerClassesSRPKey(srpKeyProducer->generateKey()),305#if JAVA_SPEC_VERSION >= 11306_nestMembersSRPKey(srpKeyProducer->generateKey()),307#endif /* JAVA_SPEC_VERSION >= 11 */308_optionalInfoSRPKey(srpKeyProducer->generateKey()),309_enclosingMethodSRPKey(srpKeyProducer->generateKey()),310_sourceDebugExtensionSRPKey(srpKeyProducer->generateKey()),311_intermediateClassDataSRPKey(srpKeyProducer->generateKey()),312_annotationInfoClassSRPKey(srpKeyProducer->generateKey()),313_typeAnnotationInfoSRPKey(srpKeyProducer->generateKey()),314_recordInfoSRPKey(srpKeyProducer->generateKey()),315_callSiteDataSRPKey(srpKeyProducer->generateKey()),316_staticSplitTableSRPKey(srpKeyProducer->generateKey()),317_specialSplitTableSRPKey(srpKeyProducer->generateKey()),318#if defined(J9VM_OPT_METHOD_HANDLE)319_varHandleMethodTypeLookupTableSRPKey(srpKeyProducer->generateKey()),320#endif /* defined(J9VM_OPT_METHOD_HANDLE) */321#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)322_injectedInterfaceInfoSRPKey(srpKeyProducer->generateKey()),323#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */324_permittedSubclassesInfoSRPKey(srpKeyProducer->generateKey())325{326_methodNotes = (MethodNotes *) _bufferManager->alloc(classFileOracle->getMethodsCount() * sizeof(MethodNotes));327if (NULL == _methodNotes) {328_buildResult = OutOfMemory;329return;330}331memset(_methodNotes, 0, classFileOracle->getMethodsCount() * sizeof(MethodNotes));332}333334ROMClassWriter::~ROMClassWriter()335{336_bufferManager->free(_methodNotes);337}338339void340ROMClassWriter::writeROMClass(Cursor *cursor,341Cursor *lineNumberCursor,342Cursor *variableInfoCursor,343Cursor *utf8Cursor,344Cursor *classDataCursor,345U_32 romSize, U_32 modifiers, U_32 extraModifiers, U_32 optionalFlags,346MarkOrWrite markOrWrite)347{348bool markAndCountOnly = (MARK_AND_COUNT_ONLY== markOrWrite);349/*350* Write the J9ROMClass structure (AKA Header).351*/352if (markAndCountOnly) {353if (!_context->isIntermediateDataAClassfile()) {354if (NULL == _context->intermediateClassData()) {355/* In case intermediate data is not explicitly provided in the _context,356* ROMClass being created can itself be used as intermediateClassData.357*/358cursor->mark(_intermediateClassDataSRPKey);359} else {360_srpOffsetTable->setInternedAt(_intermediateClassDataSRPKey, _context->intermediateClassData());361}362}363cursor->skip(sizeof(J9ROMClass));364} else {365CheckSize _(cursor, sizeof(J9ROMClass));366cursor->writeU32(romSize, Cursor::ROM_SIZE);367cursor->writeU32(_classFileOracle->getSingleScalarStaticCount(), Cursor::GENERIC);368cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getClassNameIndex()), Cursor::SRP_TO_UTF8_CLASS_NAME);369cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getSuperClassNameIndex()), Cursor::SRP_TO_UTF8);370cursor->writeU32(modifiers, Cursor::GENERIC);371cursor->writeU32(extraModifiers, Cursor::GENERIC);372#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)373cursor->writeU32(_classFileOracle->getInterfacesCount() + _interfaceInjectionInfo->numOfInterfaces, Cursor::GENERIC);374#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */375cursor->writeU32(_classFileOracle->getInterfacesCount(), Cursor::GENERIC);376#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */377cursor->writeSRP(_interfacesSRPKey, Cursor::SRP_TO_GENERIC);378cursor->writeU32(_classFileOracle->getMethodsCount(), Cursor::GENERIC);379cursor->writeSRP(_methodsSRPKey, Cursor::SRP_TO_GENERIC);380cursor->writeU32(_classFileOracle->getFieldsCount(), Cursor::GENERIC);381cursor->writeSRP(_fieldsSRPKey, Cursor::SRP_TO_GENERIC);382cursor->writeU32(_classFileOracle->getObjectStaticCount(), Cursor::GENERIC);383cursor->writeU32(_classFileOracle->getDoubleScalarStaticCount(), Cursor::GENERIC);384cursor->writeU32(_constantPoolMap->getRAMConstantPoolCount(), Cursor::GENERIC);385cursor->writeU32(_constantPoolMap->getROMConstantPoolCount(), Cursor::GENERIC);386cursor->writeWSRP(_intermediateClassDataSRPKey, Cursor::SRP_TO_INTERMEDIATE_CLASS_DATA);387if (NULL == _context->intermediateClassData()) {388/* In case intermediate data is not explicitly provided in the _context,389* ROMClass being created is itself used as intermediateClassData,390* therefore intermediateDataLength should be the ROMClass size.391*/392cursor->writeU32(romSize, Cursor::INTERMEDIATE_CLASS_DATA_LENGTH);393} else {394cursor->writeU32(_context->intermediateClassDataLength(), Cursor::INTERMEDIATE_CLASS_DATA_LENGTH);395}396cursor->writeU32(OBJECT_HEADER_SHAPE_MIXED, Cursor::GENERIC);397cursor->writeSRP(_cpDescriptionShapeSRPKey, Cursor::SRP_TO_GENERIC);398cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getOuterClassNameIndex()), Cursor::SRP_TO_UTF8);399cursor->writeU32(_classFileOracle->getMemberAccessFlags(), Cursor::GENERIC);400cursor->writeU32(_classFileOracle->getInnerClassCount(), Cursor::GENERIC);401cursor->writeSRP(_innerClassesSRPKey, Cursor::SRP_TO_GENERIC);402cursor->writeU32(_classFileOracle->getEnclosedInnerClassCount(), Cursor::GENERIC);403cursor->writeSRP(_enclosedInnerClassesSRPKey, Cursor::SRP_TO_GENERIC);404#if JAVA_SPEC_VERSION >= 11405cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getNestHostNameIndex()), Cursor::SRP_TO_UTF8);406cursor->writeU16(_classFileOracle->getNestMembersCount(), Cursor::GENERIC);407cursor->writeU16(0, Cursor::GENERIC); /* padding */408cursor->writeSRP(_nestMembersSRPKey, Cursor::SRP_TO_GENERIC);409#endif /* JAVA_SPEC_VERSION >= 11 */410cursor->writeU16(_classFileOracle->getMajorVersion(), Cursor::GENERIC);411cursor->writeU16(_classFileOracle->getMinorVersion(), Cursor::GENERIC);412cursor->writeU32(optionalFlags, Cursor::OPTIONAL_FLAGS);413cursor->writeSRP(_optionalInfoSRPKey, Cursor::SRP_TO_GENERIC);414cursor->writeU32(_classFileOracle->getMaxBranchCount(), Cursor::GENERIC);415#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)416cursor->writeU32(_constantPoolMap->getInvokeCacheCount(), Cursor::GENERIC);417#else /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */418cursor->writeU32(_constantPoolMap->getMethodTypeCount(), Cursor::GENERIC);419cursor->writeU32(_constantPoolMap->getVarHandleMethodTypeCount(), Cursor::GENERIC);420#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */421cursor->writeU32(_classFileOracle->getBootstrapMethodCount(), Cursor::GENERIC);422cursor->writeU32(_constantPoolMap->getCallSiteCount(), Cursor::GENERIC);423cursor->writeSRP(_callSiteDataSRPKey, Cursor::SRP_TO_GENERIC);424cursor->writeU32(_classFileOracle->getClassFileSize(), Cursor::CLASS_FILE_SIZE);425cursor->writeU32((U_32)_classFileOracle->getConstantPoolCount(), Cursor::GENERIC);426cursor->writeU16(_constantPoolMap->getStaticSplitEntryCount(), Cursor::GENERIC);427cursor->writeU16(_constantPoolMap->getSpecialSplitEntryCount(), Cursor::GENERIC);428cursor->writeSRP(_staticSplitTableSRPKey, Cursor::SRP_TO_GENERIC);429cursor->writeSRP(_specialSplitTableSRPKey, Cursor::SRP_TO_GENERIC);430#if defined(J9VM_OPT_METHOD_HANDLE)431cursor->writeSRP(_varHandleMethodTypeLookupTableSRPKey, Cursor::SRP_TO_GENERIC);432#endif /* defined(J9VM_OPT_METHOD_HANDLE) */433cursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);434}435436/*437* Write the rest of the contiguous portion of the ROMClass438*/439440cursor->setClassNameIndex((_classFileOracle->getClassNameIndex()));441writeConstantPool(cursor, markAndCountOnly);442writeFields(cursor, markAndCountOnly);443writeInterfaces(cursor, markAndCountOnly);444writeInnerClasses(cursor, markAndCountOnly);445writeEnclosedInnerClasses(cursor, markAndCountOnly);446#if JAVA_SPEC_VERSION >= 11447writeNestMembers(cursor, markAndCountOnly);448#endif /* JAVA_SPEC_VERSION >= 11 */449writeNameAndSignatureBlock(cursor);450writeMethods(cursor, lineNumberCursor, variableInfoCursor, markAndCountOnly);451writeConstantPoolShapeDescriptions(cursor, markAndCountOnly);452writeAnnotationInfo(cursor);453writeSourceDebugExtension(cursor);454writeRecordComponents(cursor, markAndCountOnly);455writePermittedSubclasses(cursor, markAndCountOnly);456#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)457writeInjectedInterfaces(cursor, markAndCountOnly);458#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */459writeOptionalInfo(cursor);460writeCallSiteData(cursor, markAndCountOnly);461#if defined(J9VM_OPT_METHOD_HANDLE)462writeVarHandleMethodTypeLookupTable(cursor, markAndCountOnly);463#endif /* defined(J9VM_OPT_METHOD_HANDLE) */464writeStaticSplitTable(cursor, markAndCountOnly);465writeSpecialSplitTable(cursor, markAndCountOnly);466/* aligned to U_64 required by the shared classes */467cursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);468469/*470* Write UTF8s471*/472if ( NULL != utf8Cursor ) {473ROMClassVerbosePhase v(_context, markAndCountOnly ? MarkAndCountUTF8s : WriteUTF8s);474writeUTF8s(utf8Cursor);475}476477/*478* Write Intermediate Class File bytes if479* (-Xshareclasses:enableBCI is specified and class file has not been modified by BCI agent) or480* (re-transformation is enabled and -Xshareclasses:enableBCI is not present).481*/482if ((NULL != classDataCursor)483&& !_srpOffsetTable->isInterned(_intermediateClassDataSRPKey)484) {485classDataCursor->mark(_intermediateClassDataSRPKey);486classDataCursor->writeData(_context->intermediateClassData(), _context->intermediateClassDataLength(), Cursor::INTERMEDIATE_CLASS_DATA);487/* aligned to U_64 required by the shared classes */488classDataCursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);489}490}491492/*493* Global table for ROMClassWriter::ConstantPoolWriter::visitMethodHandle().494*/495static const UDATA splitTypeMap[] = {4960, /* UNUSED */497ConstantPoolMap::GET_FIELD, /* GETFIELD */498ConstantPoolMap::GET_STATIC, /* GETSTATIC */499ConstantPoolMap::PUT_FIELD, /* PUTFIELD */500ConstantPoolMap::PUT_STATIC, /* PUTSTATIC */501ConstantPoolMap::INVOKE_VIRTUAL, /* INVOKEVIRTUAL */502ConstantPoolMap::INVOKE_STATIC, /* INVOKESTATIC */503ConstantPoolMap::INVOKE_SPECIAL, /* INVOKESPECIAL */504ConstantPoolMap::INVOKE_SPECIAL, /* NEWINVOKESPECIAL */505ConstantPoolMap::INVOKE_INTERFACE /* INVOKEINTERFACE */506};507508class ROMClassWriter::ConstantPoolWriter : public ConstantPoolMap::ConstantPoolVisitor509{510public:511ConstantPoolWriter(Cursor *cursor, SRPKeyProducer *srpKeyProducer, ConstantPoolMap *constantPoolMap) :512_cursor(cursor),513_srpKeyProducer(srpKeyProducer),514_constantPoolMap(constantPoolMap)515{516}517518void visitClass(U_16 cfrCPIndex)519{520/* if the cfrCPIndex is for the class name, the data type should be SRP_TO_UTF8_CLASS_NAME to avoid comparing lambda class names */521U_16 classNameIndex = _cursor->getClassNameIndex();522if (((U_16)-1 != classNameIndex) && (_srpKeyProducer->mapCfrConstantPoolIndexToKey(classNameIndex) == _srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex))) {523_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8_CLASS_NAME);524} else {525_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8);526}527_cursor->writeU32(BCT_J9DescriptionCpTypeClass, Cursor::GENERIC);528}529530void visitString(U_16 cfrCPIndex)531{532_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8);533_cursor->writeU32(BCT_J9DescriptionCpTypeObject, Cursor::GENERIC);534}535536void visitMethodType(U_16 cfrCPIndex, U_16 originFlags)537{538/* Assumes format: { SRP to UTF8, cpType } */539_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8);540_cursor->writeU32((originFlags << BCT_J9DescriptionCpTypeShift) | BCT_J9DescriptionCpTypeMethodType, Cursor::GENERIC);541}542543void visitMethodHandle(U_16 cfrKind, U_16 cfrCPIndex)544{545U_32 cpIndex = _constantPoolMap->getROMClassCPIndex(cfrCPIndex, splitTypeMap[cfrKind]);546547Trc_BCU_Assert_NotEquals(cpIndex, 0);548549/* assumes format: { U32 cpIndex, (cfrKind << 4) || cpType } */550_cursor->writeU32(cpIndex, Cursor::GENERIC);551_cursor->writeU32((cfrKind << BCT_J9DescriptionCpTypeShift) | BCT_J9DescriptionCpTypeMethodHandle, Cursor::GENERIC);552}553554void visitConstantDynamic(U_16 bsmIndex, U_16 cfrCPIndex, U_32 primitiveFlag)555{556/* assumes format: { SRP to NameAndSignature, primitiveFlag || (bsmIndex << 4) || cpType } */557_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_NAME_AND_SIGNATURE);558_cursor->writeU32((bsmIndex << BCT_J9DescriptionCpTypeShift) | BCT_J9DescriptionCpTypeConstantDynamic | primitiveFlag, Cursor::GENERIC);559}560561void visitSingleSlotConstant(U_32 slot1)562{563_cursor->writeU32(slot1, Cursor::GENERIC);564_cursor->writeU32(BCT_J9DescriptionCpTypeScalar, Cursor::GENERIC);565}566567void visitDoubleSlotConstant(U_32 slot1, U_32 slot2)568{569#ifdef J9VM_ENV_DATA64570_cursor->writeU64(slot1, slot2, Cursor::GENERIC);571#else572_cursor->writeU32(slot1, Cursor::GENERIC);573_cursor->writeU32(slot2, Cursor::GENERIC);574#endif575}576577void visitFieldOrMethod(U_16 classRefCPIndex, U_16 nameAndSignatureCfrCPIndex)578{579_cursor->writeU32(classRefCPIndex, Cursor::GENERIC);580_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(nameAndSignatureCfrCPIndex), Cursor::SRP_TO_NAME_AND_SIGNATURE);581}582583private:584Cursor *_cursor;585SRPKeyProducer *_srpKeyProducer;586ConstantPoolMap *_constantPoolMap;587};588589void590ROMClassWriter::writeConstantPool(Cursor *cursor, bool markAndCountOnly)591{592UDATA constantPoolSize = UDATA(_constantPoolMap->getROMConstantPoolCount()) * sizeof(J9ROMConstantPoolItem);593if (markAndCountOnly) {594cursor->skip(constantPoolSize);595} else {596CheckSize _(cursor, constantPoolSize);597598/* Write the zeroth entry */599cursor->writeU32(0, Cursor::GENERIC);600cursor->writeU32(0, Cursor::GENERIC);601602ConstantPoolWriter writer(cursor, _srpKeyProducer, _constantPoolMap);603_constantPoolMap->constantPoolDo(&writer);604}605}606607/*608* The ROM class field has the following layout:609* J9ROMFieldShape610* 4 or 8 bytes unsigned constant value if this is a static const field611* 4 bytes SRP to generic field signature if the field has a generic signature612* 4 bytes length of annotation data in bytes, followed by annotation data. Omitted if there are no field annotations.613* 4 bytes length of type annotation data in bytes followed by type annotation data. Omitted if there are no type annotations.614*/615616void617ROMClassWriter::writeFields(Cursor *cursor, bool markAndCountOnly)618{619cursor->mark(_fieldsSRPKey);620ClassFileOracle::FieldIterator iterator = _classFileOracle->getFieldIterator();621while ( iterator.isNotDone() ) {622if (markAndCountOnly) {623cursor->skip(sizeof(J9ROMFieldShape));624} else {625CheckSize _(cursor, sizeof(J9ROMFieldShape));626627cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getNameIndex()), Cursor::SRP_TO_UTF8);628cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getDescriptorIndex()), Cursor::SRP_TO_UTF8);629630U_32 fieldSignatureFlags(fieldModifiersLookupTable[iterator.getFirstByteOfDescriptor() - 'A']);631U_32 modifiers(iterator.getAccessFlags() | (fieldSignatureFlags << 16));632if (iterator.isConstant()) {633modifiers |= J9FieldFlagConstant;634}635if (iterator.hasGenericSignature()) {636modifiers |= J9FieldFlagHasGenericSignature;637}638if (iterator.isSynthetic()) {639/* handle the synthetic attribute. In java 1.5 synthetic may be specified in the access flags as well so do not unset bit here */640modifiers |= J9AccSynthetic;641}642if (iterator.isFieldContended()) {643modifiers |= J9FieldFlagIsContended;644}645if (iterator.hasAnnotation()) {646modifiers |= J9FieldFlagHasFieldAnnotations;647}648if (iterator.hasTypeAnnotation()) {649modifiers |= J9FieldFlagHasTypeAnnotations;650}651652cursor->writeU32(modifiers, Cursor::GENERIC);653}654655if (iterator.isConstant()) { // Check not absolutely necessary, but might provide small performance win656if (iterator.isConstantFloat() || iterator.isConstantInteger()) {657cursor->writeU32(iterator.getConstantValueSlot1(), Cursor::GENERIC);658} else if (iterator.isConstantDouble() || iterator.isConstantLong()) {659cursor->writeU32(iterator.getConstantValueSlot1(), Cursor::GENERIC);660cursor->writeU32(iterator.getConstantValueSlot2(), Cursor::GENERIC);661} else if (iterator.isConstantString()) {662cursor->writeU32(U_32(_constantPoolMap->getROMClassCPIndexForReference(iterator.getConstantValueConstantPoolIndex())), Cursor::GENERIC);663}664}665666if (iterator.hasGenericSignature()) {667if (markAndCountOnly) { // TODO check if this is a performance win668cursor->skip(sizeof(J9SRP));669} else {670cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);671}672}673674if (iterator.hasAnnotation()) {675/*676* u_32 length677* length * u_8678* pad to u_32 size679*/680AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);681_classFileOracle->fieldAnnotationDo(iterator.getFieldIndex(), &annotationWriter, &annotationWriter, &annotationWriter);682cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);683}684685if (iterator.hasTypeAnnotation()) {686AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);687_classFileOracle->fieldTypeAnnotationDo(iterator.getFieldIndex(), &annotationWriter, &annotationWriter, &annotationWriter);688cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);689}690691692iterator.next();693}694}695696/* mapping characters A..Z,[ */697const U_8 primitiveArrayTypeCharConversion[] = {6980, CFR_STACKMAP_TYPE_BYTE_ARRAY, CFR_STACKMAP_TYPE_CHAR_ARRAY, CFR_STACKMAP_TYPE_DOUBLE_ARRAY,6990, CFR_STACKMAP_TYPE_FLOAT_ARRAY, 0, 0,700CFR_STACKMAP_TYPE_INT_ARRAY, CFR_STACKMAP_TYPE_LONG_ARRAY, 0, 0,7010, 0, 0, 0,7020, 0, CFR_STACKMAP_TYPE_SHORT_ARRAY, 0,7030, 0, 0, 0,7040, CFR_STACKMAP_TYPE_BOOL_ARRAY, 0};705706class ROMClassWriter::CallSiteWriter : public ConstantPoolMap::CallSiteVisitor707{708public:709CallSiteWriter(Cursor *cursor) :710_cursor(cursor)711{712}713714void visitCallSite(U_16 nameAndSignatureIndex, U_16 bootstrapMethodIndex)715{716_cursor->writeU16(bootstrapMethodIndex, Cursor::GENERIC);717}718719private:720Cursor *_cursor;721};722723class ROMClassWriter::Helper :724private ClassFileOracle::ConstantPoolIndexVisitor,725private ClassFileOracle::ExceptionHandlerVisitor,726private ClassFileOracle::StackMapFrameVisitor,727private ClassFileOracle::VerificationTypeInfoVisitor,728private ClassFileOracle::BootstrapMethodVisitor,729private ClassFileOracle::MethodParametersVisitor,730private ConstantPoolMap::SplitEntryVisitor,731private ConstantPoolMap::CallSiteVisitor732{733public:734#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)735Helper(Cursor *cursor, bool markAndCountOnly,736ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, SRPOffsetTable *srpOffsetTable, ConstantPoolMap *constantPoolMap,737UDATA expectedSize, InterfaceInjectionInfo *interfaceInjectionInfo) :738#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */739Helper(Cursor *cursor, bool markAndCountOnly,740ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, SRPOffsetTable *srpOffsetTable, ConstantPoolMap *constantPoolMap,741UDATA expectedSize) :742#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */743_cursor(cursor),744_classFileOracle(classFileOracle),745_srpKeyProducer(srpKeyProducer),746_srpOffsetTable(srpOffsetTable),747_constantPoolMap(constantPoolMap),748#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)749_interfaceInjectionInfo(interfaceInjectionInfo),750#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */751_markAndCountOnly(markAndCountOnly)752{753if (_markAndCountOnly) {754_cursor->skip(expectedSize);755}756}757758void writeInnerClasses()759{760if (!_markAndCountOnly) {761_classFileOracle->innerClassesDo(this); /* visitConstantPoolIndex */762}763}764765void writeEnclosedInnerClasses()766{767if (!_markAndCountOnly) {768_classFileOracle->enclosedInnerClassesDo(this); /* visitConstantPoolIndex */769}770}771772#if JAVA_SPEC_VERSION >= 11773void writeNestMembers()774{775if (!_markAndCountOnly) {776_classFileOracle->nestMembersDo(this); /* visitConstantPoolIndex */777}778}779#endif /* JAVA_SPEC_VERSION >= 11 */780781void writeInterfaces()782{783if (!_markAndCountOnly) {784#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)785_classFileOracle->interfacesDo(this, _interfaceInjectionInfo->numOfInterfaces); /* visitConstantPoolIndex */786#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */787_classFileOracle->interfacesDo(this); /* visitConstantPoolIndex */788#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */789}790}791792void writeNameAndSignatureBlock()793{794if (!_markAndCountOnly) {795for (ClassFileOracle::NameAndTypeIterator iterator = _classFileOracle->getNameAndTypeIterator();796iterator.isNotDone();797iterator.next()) {798U_16 cpIndex = iterator.getCPIndex();799800if (_constantPoolMap->isNATConstantReferenced(cpIndex)) {801U_16 nameIndex = iterator.getNameIndex();802U_16 descriptorIndex = iterator.getDescriptorIndex();803804_cursor->mark(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex));805_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(nameIndex), Cursor::SRP_TO_UTF8);806_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(descriptorIndex), Cursor::SRP_TO_UTF8);807}808}809}810}811812void writeUTF8Block()813{814if (!_markAndCountOnly) {815for (ClassFileOracle::UTF8Iterator iterator = _classFileOracle->getUTF8Iterator();816iterator.isNotDone();817iterator.next()) {818U_16 cpIndex = iterator.getCPIndex();819820if (_constantPoolMap->isUTF8ConstantReferenced(cpIndex)) {821UDATA key = _srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex);822823if (!_srpOffsetTable->isInterned(key)) {824U_8* utf8Data = iterator.getUTF8Data();825U_16 utf8Length = iterator.getUTF8Length();826827_cursor->mark(key);828_cursor->writeUTF8(utf8Data, utf8Length, Cursor::GENERIC);829}830}831}832#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)833for (int i = 0; i < _interfaceInjectionInfo->numOfInterfaces; i++) {834/* if the class requires injected interfaces an "extra" CP slot in the key table is added for each interface */835_cursor->mark(_classFileOracle->getConstantPoolCount() + i);836_cursor->writeUTF8((U_8*)J9UTF8_DATA(_interfaceInjectionInfo->interfaces[i]), J9UTF8_LENGTH(_interfaceInjectionInfo->interfaces[i]), Cursor::GENERIC);837}838#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */839}840}841842void writeExceptionBlock(ClassFileOracle::MethodIterator *iterator)843{844if (!_markAndCountOnly) {845iterator->exceptionHandlersDo(this); /* visitExceptionHandler */846iterator->exceptionsThrownDo(this); /* visitConstantPoolIndex */847}848}849850void writeMethodParameters(ClassFileOracle::MethodIterator *iterator)851{852if (!_markAndCountOnly) {853iterator->methodParametersDo(this); /* visitMethodParameters */854}855}856857void writeStackMap(ClassFileOracle::MethodIterator *methodIterator)858{859if (!_markAndCountOnly) {860methodIterator->stackMapFramesDo(this); /* visitStackMapFrame */861}862}863864void writeCallSiteData()865{866if (!_markAndCountOnly) {867CallSiteWriter callSiteWriter(_cursor);868_constantPoolMap->callSitesDo(this); /* visitCallSite */869_constantPoolMap->callSitesDo(&callSiteWriter);870}871}872873#if defined(J9VM_OPT_METHOD_HANDLE)874void writeVarHandleMethodTypeLookupTable()875{876if (!_markAndCountOnly) {877U_16 lookupTableCount = _constantPoolMap->getVarHandleMethodTypeCount();878if (lookupTableCount > 0) {879U_16 *lookupTable = _constantPoolMap->getVarHandleMethodTypeLookupTable();880881/* The lookup table is a U_16[], so we need to pad it in order to keep the J9ROMClass alignment. */882U_16 lookupTablePaddedCount = _constantPoolMap->getVarHandleMethodTypePaddedCount();883U_16 *lookupTablePadding = lookupTable + lookupTableCount;884UDATA lookupTablePaddingLength = lookupTablePaddedCount - lookupTableCount;885886/* Write the data section of the array */887_cursor->writeData((U_8 *)lookupTable, lookupTableCount * sizeof(U_16), Cursor::GENERIC);888889/* Write the padding section of the array */890if (lookupTablePaddingLength > 0) {891_cursor->writeData((U_8 *)lookupTablePadding, lookupTablePaddingLength * sizeof(U_16), Cursor::GENERIC);892}893}894}895}896#endif /* defined(J9VM_OPT_METHOD_HANDLE) */897898void writeBootstrapMethods()899{900if (!_markAndCountOnly) {901_classFileOracle->bootstrapMethodsDo(this); /* visitBootstrapMethod */902}903}904905void writeStaticSplitTable()906{907if (!_markAndCountOnly) {908_constantPoolMap->staticSplitEntriesDo(this); /* visitSplitEntry */909}910}911912void writeSpecialSplitTable()913{914if (!_markAndCountOnly) {915_constantPoolMap->specialSplitEntriesDo(this); /* visitSplitEntry */916}917}918919private:920/*921* Implement interfaces922*/923void visitConstantPoolIndex(U_16 cpIndex)924{925_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex), Cursor::SRP_TO_UTF8);926}927928void visitMethodParameters(U_16 cpIndex, U_16 flag) {929if (0 == cpIndex) {930_cursor->writeU32(0, Cursor::GENERIC);931} else {932_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex), Cursor::SRP_TO_UTF8);933}934_cursor->writeU16(flag, Cursor::GENERIC);935}936937void visitExceptionHandler(U_32 startPC, U_32 endPC, U_32 handlerPC, U_16 exceptionClassCPIndex)938{939_cursor->writeU32(startPC, Cursor::GENERIC);940_cursor->writeU32(endPC, Cursor::GENERIC);941_cursor->writeU32(handlerPC, Cursor::GENERIC);942_cursor->writeU32(_constantPoolMap->getROMClassCPIndexForReference(exceptionClassCPIndex), Cursor::GENERIC);943}944945void visitStackMapObject(U_8 slotType, U_16 classCPIndex, U_16 classNameCPIndex)946{947U_8 *nameData = _classFileOracle->getUTF8Data(classNameCPIndex);948U_16 nameLength = _classFileOracle->getUTF8Length(classNameCPIndex);949/* special conversion of primitive array objects950* detect whether or not this is a primitive array e.g.,951* [I or [[F, etc..952* vs. an array of Objects e.g.,953* [Lcom/ibm/foo/Bar;954*/955if ((nameData[0] == '[') && (nameData[nameLength - 1] != ';')) {956/*957* This is a primitive array object.958*959* Encode the primitive array type in the tag field.960* One of:961* CFR_STACKMAP_TYPE_BYTE_ARRAY962* CFR_STACKMAP_TYPE_BOOL_ARRAY963* CFR_STACKMAP_TYPE_CHAR_ARRAY964* CFR_STACKMAP_TYPE_DOUBLE_ARRAY965* CFR_STACKMAP_TYPE_FLOAT_ARRAY966* CFR_STACKMAP_TYPE_INT_ARRAY967* CFR_STACKMAP_TYPE_LONG_ARRAY968* CFR_STACKMAP_TYPE_SHORT_ARRAY969*/970_cursor->writeU8(primitiveArrayTypeCharConversion[nameData[nameLength - 1] - 'A'], Cursor::GENERIC);971972/* Also, encode the arity beyond 1973* (i.e., number of dimensions of the array - 1)974* in the next 2 bytes in Big Endian (since we are maintaining Sun StackMapTable format).975*976* The reason for encoding arity - 1 in verification type info in Stack maps for primitive array special cases are:977* The newarray and anewarray bytecodes assume that the array has only a single dimension.978* To create a multidimension array, multianewarray must be used.979* The primitive array access bytecodes (ie: iaload) can only be used on single dimension arrays.980* aaload must be used to access every dimension prior to the base dimension in a multi-arity primitive array.981* The constants in vrfytbl.c are based off the constants for the primitive types, and can't have the arity of 1 encoded if the constant is to be used for both purposes.982* (See rtverify.c verifyBytecodes() - the RTV_ARRAY_FETCH_PUSH & RTV_ARRAY_STORE cases of the switch)983* In addition, the code all through the verifier assumes this condition.984* Notes:985* See util/vrfytbl.c for bytecode tables.986* See constant definitions in cfreader.h and oti/bytecodewalk.h.987* bcverify/bcverify.c simulateStack() is the other place that creates stack maps.988*/989_cursor->writeBigEndianU16(nameLength - 2, Cursor::GENERIC);990} else {991/*992* Object_variable_info993* u1 tag994* u2 cpIndex (ROMClass constant pool index)995*/996_cursor->writeU8(slotType, Cursor::GENERIC);997_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForReference(classCPIndex), Cursor::GENERIC);998}999}10001001void visitStackMapNewObject(U_8 slotType, U_16 offset)1002{1003/*1004* Uninitialized_variable_info1005* u1 tag1006* u2 offset (offset of the new instruction that created the object being stored in the location)1007*/1008_cursor->writeU8(slotType, Cursor::GENERIC);1009/* output the offset delta */1010_cursor->writeBigEndianU16(offset, Cursor::GENERIC);1011}10121013void visitStackMapItem(U_8 slotType)1014{1015_cursor->writeU8(slotType, Cursor::GENERIC);1016}10171018void visitStackMapFrame(U_16 localsCount, U_16 stackItemsCount, U_16 offsetDelta, U_8 frameType, ClassFileOracle::VerificationTypeInfo *typeInfo)1019{1020/*1021* Stack Map Frame:1022* consists of a 1 byte tag followed by zero or more bytes depending on the tag1023*1024* union stack_map_frame {1025* SAME1026* SAME_LOCALS_1_STACK1027* Reserved1028* SAME_LOCALS_1_STACK_EXTENDED1029* CHOP1030* SAME_EXTENDED1031* APPEND1032* FULL1033* }1034*/10351036/* output the frame tag */1037_cursor->writeU8(frameType, Cursor::GENERIC);10381039if (CFR_STACKMAP_SAME_LOCALS_1_STACK > frameType) { /* 0..63 */1040/* SAME frame - no extra data */1041} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_END > frameType) { /* 64..127 */1042/*1043* SAME_LOCALS_1_STACK {1044* TypeInfo stackItems[1]1045* };1046*/1047typeInfo->stackItemsDo(this);1048} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED > frameType) { /* 128..246 */1049/* Reserved frame types - no extra data */1050Trc_BCU_Assert_ShouldNeverHappen();1051} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED == frameType) { /* 247 */1052/*1053* SAME_LOCALS_1_STACK_EXTENDED {1054* U_16 offsetDelta1055* TypeInfo stackItems[1]1056* };1057*/1058_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);1059typeInfo->stackItemsDo(this);1060} else if (CFR_STACKMAP_SAME_EXTENDED > frameType) { /* 248..250 */1061/*1062* CHOP {1063* U_16 offsetDelta1064* };1065*/1066_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);1067} else if (CFR_STACKMAP_SAME_EXTENDED == frameType) { /* 251 */1068/*1069* SAME_EXTENDED {1070* U_16 offsetDelta1071* };1072*/1073_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);1074} else if (CFR_STACKMAP_FULL > frameType) { /* 252..254 */1075/*1076* APPEND {1077* U_16 offsetDelta1078* TypeInfo locals[frameType - CFR_STACKMAP_APPEND_BASE]1079* };1080*/1081_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);1082typeInfo->localsDo(this);1083} else if (CFR_STACKMAP_FULL == frameType) { /* 255 */1084/*1085* FULL {1086* U_16 offsetDelta1087* U_16 localsCount1088* TypeInfo locals[localsCount]1089* U_16 stackItemsCount1090* TypeInfo stackItems[stackItemsCount]1091* };1092*/10931094/* u2 offset delta */1095_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);10961097/* handle locals */1098/* u2 number of locals */1099_cursor->writeBigEndianU16(localsCount, Cursor::GENERIC);1100/* verification_type_info locals[number of locals] */1101typeInfo->localsDo(this);11021103/* handle stack */1104/* u2 number of stack items */1105_cursor->writeBigEndianU16(stackItemsCount, Cursor::GENERIC);1106/* verification_type_info stack[number of stack items] */1107typeInfo->stackItemsDo(this);1108}1109}11101111void visitBootstrapMethod(U_16 cpIndex, U_16 argumentCount)1112{1113_cursor->writeU16(_constantPoolMap->getROMClassCPIndexForReference(cpIndex), Cursor::GENERIC);1114_cursor->writeU16(argumentCount, Cursor::GENERIC);1115}11161117void visitBootstrapArgument(U_16 cpIndex)1118{1119_cursor->writeU16(_constantPoolMap->getROMClassCPIndexForReference(cpIndex), Cursor::GENERIC);1120}11211122void visitCallSite(U_16 nameAndSignatureIndex, U_16 bootstrapMethodIndex)1123{1124_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(nameAndSignatureIndex), Cursor::SRP_TO_NAME_AND_SIGNATURE);1125}11261127void visitSplitEntry(U_16 cpIndex)1128{1129_cursor->writeU16(cpIndex, Cursor::GENERIC);1130}11311132Cursor *_cursor;1133ClassFileOracle *_classFileOracle;1134SRPKeyProducer *_srpKeyProducer;1135SRPOffsetTable *_srpOffsetTable;1136ConstantPoolMap *_constantPoolMap;1137#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1138InterfaceInjectionInfo *_interfaceInjectionInfo;1139#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1140bool _markAndCountOnly;1141};11421143void1144ROMClassWriter::writeInterfaces(Cursor *cursor, bool markAndCountOnly)1145{1146cursor->mark(_interfacesSRPKey);1147UDATA size = UDATA(_classFileOracle->getInterfacesCount()) * sizeof(J9SRP);1148#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1149size += UDATA(_interfaceInjectionInfo->numOfInterfaces) * sizeof(J9SRP);1150#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1151CheckSize _(cursor, size);1152#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1153Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeInterfaces();1154#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1155Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeInterfaces();1156#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1157}11581159void1160ROMClassWriter::writeInnerClasses(Cursor *cursor, bool markAndCountOnly)1161{1162cursor->mark(_innerClassesSRPKey);1163UDATA size = UDATA(_classFileOracle->getInnerClassCount()) * sizeof(J9SRP);1164CheckSize _(cursor, size);1165#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1166Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeInnerClasses();1167#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1168Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeInnerClasses();1169#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1170}11711172void1173ROMClassWriter::writeEnclosedInnerClasses(Cursor *cursor, bool markAndCountOnly)1174{1175cursor->mark(_enclosedInnerClassesSRPKey);1176UDATA size = UDATA(_classFileOracle->getEnclosedInnerClassCount()) * sizeof(J9SRP);1177CheckSize _(cursor, size);1178#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1179Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeEnclosedInnerClasses();1180#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1181Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeEnclosedInnerClasses();1182#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1183}11841185#if JAVA_SPEC_VERSION >= 111186void1187ROMClassWriter::writeNestMembers(Cursor *cursor, bool markAndCountOnly)1188{1189cursor->mark(_nestMembersSRPKey);1190UDATA size = UDATA(_classFileOracle->getNestMembersCount()) * sizeof(J9SRP);1191CheckSize _(cursor,size);1192#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1193Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeNestMembers();1194#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1195Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeNestMembers();1196#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1197}1198#endif /* JAVA_SPEC_VERSION >= 11 */11991200void1201ROMClassWriter::writeNameAndSignatureBlock(Cursor *cursor)1202{1203#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1204Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeNameAndSignatureBlock();1205#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1206Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeNameAndSignatureBlock();1207#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1208}12091210void1211ROMClassWriter::writeUTF8s(Cursor *cursor)1212{1213#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1214Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeUTF8Block();1215#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1216Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeUTF8Block();1217#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1218/* aligned to U_64 required by the shared classes */1219cursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);1220}12211222void1223ROMClassWriter::writeMethods(Cursor *cursor, Cursor *lineNumberCursor, Cursor *variableInfoCursor, bool markAndCountOnly)1224{1225/*1226* ****************************** PLEASE READ ***********************************1227*1228* When changing the format of a ROMMethod these are places that assume ROMMethod format1229* and would need to be updated:1230* - nextROMMethod() in util/mthutil.c1231* - allSlotsInROMMethodsSectionDo() in util/romclasswalk.c1232* - dbgNextROMMethod() in dbgext/j9dbgext.c1233* - createBreakpointedMethod() in jvmti/jvmtiHelpers.c1234* All the above are involved in walking or walking over ROMMethods.1235*1236*/12371238cursor->mark(_methodsSRPKey);1239for (ClassFileOracle::MethodIterator iterator = _classFileOracle->getMethodIterator();1240iterator.isNotDone();1241iterator.next()) {1242U_8 argCount = iterator.getSendSlotCount();1243U_16 tempCount = iterator.getMaxLocals();1244U_32 modifiers = iterator.getModifiers();1245U_32 extendedModifiers = iterator.getExtendedModifiers();1246bool writeDebugInfo =1247((iterator.getLineNumbersCount() > 0) || (iterator.getLocalVariablesCount() > 0)) &&1248(_context->shouldPreserveLineNumbers() || _context->shouldPreserveLocalVariablesInfo());12491250/* If an existing method is being compared to, then calling1251* romMethodCacheCurrentRomMethod will cache the existing1252* rom method in the context. This prevents the need to constantly1253* retrieve the method from the existing rom class.1254*/1255_context->romMethodCacheCurrentRomMethod(cursor->getCount());12561257if (!markAndCountOnly) {1258if (! iterator.isStatic()) {1259++argCount;1260}1261if (tempCount >= argCount) {1262tempCount -= argCount;1263} else {1264Trc_BCU_Assert_Equals(0, tempCount);1265}12661267/*1268* ROMMethod->modifier what does each bit represent?1269*1270* Bottom 16 bits are defined by the specification and set by the call to1271* iterator.getAccessFlags() the rest are set 'by hand' below.1272*1273* NOTE: some of the bottom 16 bits are used for J9 specific flags as specified by a '*'1274*1275* 0000 0000 0000 0000 0000 0000 0000 00001276* + AccPublic1277* + AccPrivate1278* + AccProtected1279* + AccStatic1280*1281* + AccFinal1282* + AccSynchronized1283* + AccBridge1284* + AccVarArgs1285*1286* + AccNative1287* + AccGetterMethod * (Not currently used by specification)1288* + AccAbstract1289* + AccStrict1290*1291* + AccSynthetic1292* + AccForwarderMethod * (Not currently used by specification)1293* + AccEmptyMethod * (Not currently used by specification)1294* + UNUSED1295*1296* Top 16 bits are defined by J9.1297* + AccMethodVTable1298* + AccMethodHasExceptionInfo1299* + AccMethodHasDebugInfo1300* + AccMethodFrameIteratorSkip1301*1302* + AccMethodCallerSensitive (has @CallerSensitive annotation)1303* + AccMethodHasBackwardBranches1304* + AccMethodObjectConstructor1305* + AccMethodHasMethodParameters1306*1307* + AccMethodAllowFinalFieldWrites1308* + AccMethodHasGenericSignature1309* + AccMethodHasExtendedModifiers1310* + AccMethodHasMethodHandleInvokes1311*1312* + AccMethodHasStackMap1313* + AccMethodHasMethodAnnotations1314* + AccMethodHasParameterAnnotations1315* + AccMethodHasDefaultAnnotation1316*/13171318/* In class files prior to version 53, any method in the declaring class of a final field1319* may write to it. For 53 and later, only initializers (<init> for instance fields, <clinit>1320* for static fields) are allowed to write to final fields.1321*/1322if ((_classFileOracle->getMajorVersion() < 53) || ('<' == *_classFileOracle->getUTF8Data(iterator.getNameIndex()))) {1323modifiers |= J9AccMethodAllowFinalFieldWrites;1324}13251326if (iterator.hasFrameIteratorSkipAnnotation()) {1327modifiers |= J9AccMethodFrameIteratorSkip;1328}13291330if (writeDebugInfo) {1331modifiers |= J9AccMethodHasDebugInfo;1332}13331334if (iterator.hasMethodParameters()) {1335modifiers |= J9AccMethodHasMethodParameters;1336}1337}13381339U_32 byteCodeSize = 0;1340if (iterator.isAbstract()) {1341/* Do nothing */1342} else if (iterator.isNative()) {1343byteCodeSize = computeNativeSignatureSize(_classFileOracle->getUTF8Data(iterator.getDescriptorIndex()));1344} else {1345byteCodeSize = iterator.getCodeLength();1346}13471348if (markAndCountOnly) {1349cursor->skip(sizeof(J9ROMMethod));1350} else {1351CheckSize _(cursor, sizeof(J9ROMMethod));1352cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getNameIndex()), Cursor::SRP_TO_UTF8);1353cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getDescriptorIndex()), Cursor::SRP_TO_UTF8);1354if (0 != extendedModifiers) {1355modifiers |= J9AccMethodHasExtendedModifiers;1356}1357cursor->writeU32(modifiers, Cursor::ROM_CLASS_MODIFIERS);1358cursor->writeU16(iterator.getMaxStack(), Cursor::GENERIC);1359cursor->writeU16(U_16(byteCodeSize), Cursor::GENERIC);1360cursor->writeU8(U_8(byteCodeSize >> 16), Cursor::GENERIC);1361cursor->writeU8(argCount, Cursor::GENERIC);1362cursor->writeU16(tempCount, Cursor::GENERIC);1363}13641365if (iterator.isAbstract()) {1366/* Do nothing */1367} else if (markAndCountOnly) {1368cursor->skip(byteCodeSize);1369} else if (iterator.isNative()) {1370writeNativeSignature(cursor, _classFileOracle->getUTF8Data(iterator.getDescriptorIndex()), byteCodeSize - 2);1371} else {1372UDATA count = cursor->getCount();1373writeByteCodes(cursor, &iterator);1374count = cursor->getCount() - count;1375Trc_BCU_Assert_Equals(count, byteCodeSize);1376}13771378cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1379if (0 != extendedModifiers) {1380cursor->writeU32(extendedModifiers, Cursor::ROM_CLASS_MODIFIERS);1381}13821383if (iterator.hasGenericSignature()) {1384if (markAndCountOnly) { // TODO check if this is a performance win1385cursor->skip(sizeof(J9SRP));1386} else {1387cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);1388}1389}13901391if ((0 != iterator.getExceptionHandlersCount()) || (0 != iterator.getExceptionsThrownCount())) {1392/* Write exceptions info */1393cursor->writeU16(iterator.getExceptionHandlersCount(), Cursor::GENERIC);1394cursor->writeU16(iterator.getExceptionsThrownCount(), Cursor::GENERIC);1395UDATA size =1396UDATA(iterator.getExceptionHandlersCount()) * sizeof(J9ExceptionHandler) +1397UDATA(iterator.getExceptionsThrownCount()) * sizeof(J9SRP);1398CheckSize _(cursor, size);1399#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1400Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeExceptionBlock(&iterator);1401#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1402Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeExceptionBlock(&iterator);1403#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1404}14051406if (iterator.hasAnnotationsData()) {1407/*1408* u_32 length1409* length * u_81410* pad to u_32 size1411*/1412AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1413_classFileOracle->methodAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);1414cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1415}14161417if (iterator.hasParameterAnnotations()) {1418/*1419* u_32 length1420* length * u_81421* pad to u_32 size1422*/1423AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1424_classFileOracle->parameterAnnotationsDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);1425cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1426}14271428if (iterator.hasDefaultAnnotation()) {1429/*1430* u_32 length1431* length * u_81432* pad to u_32 size1433*/1434AnnotationWriter annotationWriter(cursor, _constantPoolMap,_classFileOracle);1435AnnotationElementWriter annotationElementWriter(cursor, _constantPoolMap, _classFileOracle);1436_classFileOracle->defaultAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationElementWriter);1437cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1438}14391440if (iterator.hasMethodTypeAnnotations()) {1441AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1442_classFileOracle->methodTypeAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);1443cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1444}14451446if (iterator.hasCodeTypeAnnotations()) {1447AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1448_classFileOracle->methodCodeTypeAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);1449cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1450}14511452bool existingDebugData = _context->romMethodHasDebugData();1453if (writeDebugInfo || existingDebugData) {1454/* writeMethodDebugInfo is called if there is debug data to write,1455* or if an existing method with debug data is being compared to.1456*/1457cursor->notifyDebugDataWriteStart();1458if (!_context->shouldWriteDebugDataInline()) {1459cursor->writeSRP(_srpKeyProducer->mapMethodIndexToMethodDebugInfoKey(iterator.getIndex()), Cursor::SRP_TO_DEBUG_DATA);1460}1461writeMethodDebugInfo(&iterator, lineNumberCursor, variableInfoCursor, markAndCountOnly, existingDebugData);1462cursor->notifyDebugDataWriteEnd();1463}14641465if ( iterator.hasStackMap() ) {1466/*1467* Write out Stack Map1468*1469* *** SUN format ***1470* u2 attribute_name_index1471* u4 attribute_length1472* u2 number_of_entries1473* stack_map_frame entries[number_of_entries]1474*1475* *** J9 format ***1476* u4 attribute_length (native endian)1477* u2 number_of_entries (big endian)1478* stack_map_frame entries[number_of_entries] (big endian)1479* padding for u4 alignment1480*1481*/14821483UDATA start = cursor->getCount();1484/* output the length of the stack map */1485cursor->writeU32(_methodNotes[iterator.getIndex()].stackMapSize, Cursor::GENERIC);1486/* output the number of frames */1487cursor->writeBigEndianU16(iterator.getStackMapFramesCount(), Cursor::GENERIC); /* TODO: don't write this stuff in BigEndian??? */14881489#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1490Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeStackMap(&iterator);1491#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1492Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeStackMap(&iterator);1493#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1494cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1495if (markAndCountOnly) {1496/* Following is adding PAD to stackmap size. First round is always markAndCountOnly.1497* This logic is very difficult to catch. Cause of the padded stackmapsize, we dont use padding in nextROMMethod() in mthutil.1498* Also I find this markAndCountOnly unnecessary and confusing for the following reasons1499* 1. It is used partially : See above, we dont use it for the first 6 bytes and we write them down.1500* It should be used properly, either always or never.1501* 2. Also when it is counting, it is a counting cursor and it actually do not write (see Cursor.hpp).1502* Therefore, markAndCountOnly flag is not needed at all and extra checks for it just makes it slower.1503*1504* */1505_methodNotes[iterator.getIndex()].stackMapSize = U_32(cursor->getCount() - start);1506}1507}15081509if (0 != iterator.hasMethodParameters()) {1510U_8 mthParamCount = iterator.getMethodParametersCount();1511UDATA size = UDATA(mthParamCount * sizeof(J9MethodParameter));1512if (true == markAndCountOnly) {1513cursor->skip(sizeof(U_8) + size);1514} else {1515cursor->writeU8(mthParamCount, Cursor::GENERIC);1516CheckSize _(cursor, size);1517#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1518Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeMethodParameters(&iterator);1519#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1520Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeMethodParameters(&iterator);1521#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1522}1523cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1524}15251526}1527}15281529class ROMClassWriter::ConstantPoolShapeDescriptionWriter : public ConstantPoolMap::ConstantPoolEntryTypeVisitor1530{1531public:1532ConstantPoolShapeDescriptionWriter(Cursor *cursor) :1533_cursor(cursor),1534_wordValue(0),1535_nibbleIndex(1) /* Account for zeroth entry */1536{1537}15381539void visitEntryType(U_32 entryType)1540{1541_wordValue |= entryType << (_nibbleIndex * J9_CP_BITS_PER_DESCRIPTION);1542++_nibbleIndex;1543if (0 == (_nibbleIndex % J9_CP_DESCRIPTIONS_PER_U32)) {1544_cursor->writeU32(_wordValue, Cursor::GENERIC);1545_nibbleIndex = 0;1546_wordValue = 0;1547}1548}15491550void flushAndPad()1551{1552/* Flush any remaining nibbles and pad */1553if (0 != (_nibbleIndex % J9_CP_DESCRIPTIONS_PER_U32)) {1554_cursor->writeU32(_wordValue, Cursor::GENERIC);1555}1556}15571558private:1559Cursor *_cursor;1560U_32 _wordValue;1561U_32 _nibbleIndex;1562};15631564void1565ROMClassWriter::writeConstantPoolShapeDescriptions(Cursor *cursor, bool markAndCountOnly)1566{1567cursor->mark(_cpDescriptionShapeSRPKey);1568UDATA size = ((UDATA(_constantPoolMap->getROMConstantPoolCount()) + J9_CP_DESCRIPTIONS_PER_U32 - 1) / J9_CP_DESCRIPTIONS_PER_U32) * sizeof(U_32);15691570if (markAndCountOnly) {1571cursor->skip(size);1572} else {1573CheckSize _(cursor, size);1574ConstantPoolShapeDescriptionWriter constantPoolShapeDescriptionWriter(cursor);1575_constantPoolMap->constantPoolEntryTypesDo(&constantPoolShapeDescriptionWriter);1576constantPoolShapeDescriptionWriter.flushAndPad();1577}1578}15791580void1581ROMClassWriter::writeAnnotationInfo(Cursor *cursor)1582{1583if (_classFileOracle->hasClassAnnotations()) {1584AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1585cursor->mark(_annotationInfoClassSRPKey);1586/*1587* u_32 length1588* length * u_81589* pad to u_32 size1590*/1591_classFileOracle->classAnnotationsDo(&annotationWriter, &annotationWriter, &annotationWriter);1592cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1593}1594if (_classFileOracle->hasTypeAnnotations()) {1595AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1596cursor->mark(_typeAnnotationInfoSRPKey);1597_classFileOracle->classTypeAnnotationsDo(&annotationWriter, &annotationWriter, &annotationWriter);1598}1599}1600void ROMClassWriter::AnnotationElementWriter::visitNestedAnnotation(U_16 elementNameIndex, ClassFileOracle::NestedAnnotation *nestedAnnotation)1601{1602_cursor->writeU8('@', Cursor::GENERIC);16031604AnnotationWriter annotationWriter(_cursor, _constantPoolMap, _classFileOracle);1605nestedAnnotation->annotationDo(&annotationWriter, &annotationWriter, NULL);1606}16071608void1609ROMClassWriter::writeMethodDebugInfo(ClassFileOracle::MethodIterator *methodIterator, Cursor *lineNumberCursor, Cursor *variableInfoCursor, bool markAndCountOnly, bool existHasDebugInformation)1610{1611/*1612* Method Debug Information is stored in one of two ways:1613* 1) inline with the ROMMethod1614* 2) in two separate areas of the Shared Class Cache1615*1616* When the data is inline with the ROMMethod the lineNumberCursor and variableInfoCursor will be the same Cursor.1617*1618* The J9MethodDebugInfo header structure and the J9LineNumber entries are written to the lineNumberCursor, while1619* the J9VariableInfo entries are written to the variableInfoCursor.1620*1621* The data looks like:1622*1623* written to lineNumberCursor:1624* J9MethodDebugInfo1625* SRP to J9VariableInfo -OR- size of all Method Debug Info include Line Numbers and Variable Info1626*1627* if lineNumberCount fits in 16bit and lineNumbersInfoCompressedSize fits in 15bit1628* u32 lineNumberCount << 16 | lineNumbersInfoCompressedSize << 1 | 01629* u32 variableInfoCount1630* else1631* u32 lineNumberCount | 11632* u32 variableInfoCount1633* u32 lineNumbersInfoCompressedSize1634* end if1635* U_8 * compressed buffer of pcOffset and lineNumber1636*1637* written to variableInfoCursor:1638* Block of compressed data containing the 'index', 'startPC' and length [+ gen sig flag]1639* Followed by1640* SRP to name1641* SRP to signature1642* [SRP to generic signature]1643*/1644bool preserveLineNumbers = _context->shouldPreserveLineNumbers();1645bool preserveLocalVariablesInfo = _context->shouldPreserveLocalVariablesInfo();16461647if (preserveLineNumbers || preserveLocalVariablesInfo || existHasDebugInformation) {1648U_32 lineNumbersCount = (preserveLineNumbers ? methodIterator->getLineNumbersCount() : 0);1649U_32 localVariablesCount = (preserveLocalVariablesInfo ? methodIterator->getLocalVariablesCount() : 0);1650U_32 lineNumbersInfoCompressedSize = methodIterator->getLineNumbersInfoCompressedSize();16511652lineNumberCursor->mark(_srpKeyProducer->mapMethodIndexToMethodDebugInfoKey(methodIterator->getIndex()));16531654/* Write J9MethodDebugInfo */1655UDATA start = lineNumberCursor->getCount();1656if (!(_context->shouldWriteDebugDataInline())) {1657lineNumberCursor->writeSRP(_srpKeyProducer->mapMethodIndexToVariableInfoKey(methodIterator->getIndex()), Cursor::SRP_TO_LOCAL_VARIABLE_DATA);1658} else {1659if ( !markAndCountOnly && ((lineNumbersCount > 0) || (localVariablesCount > 0))) {1660/* Only check this assert if the class being created was found to have1661* debug data during the 'mark and count phase'. This should always be the1662* case if lineNumbersCount or localVariablesCount are non zero.1663*/1664Trc_BCU_Assert_False(_methodNotes[methodIterator->getIndex()].debugInfoSize == 0);1665}1666lineNumberCursor->writeU32(_methodNotes[methodIterator->getIndex()].debugInfoSize | 1, Cursor::METHOD_DEBUG_SIZE);1667}16681669/* Encode the lineNumbersCount with the lineNumbersInfoCompressedSize1670* a = number of bytes in the compressed line number table1671* b = lineNumberCount1672* c = escape bit (0: use a and b, 1: lineNumberCount uses 31 bit and number of bytes in the compressed line number table will be stored as the next U_32)1673* aaaaaaaa aaaaaaaa bbbbbbbb bbbbbbbc1674*1675* Note: If the lineNumberCount is 0, then check the existing rom class in the context for compressed data.1676* In the case of the comparing cursor this will ensure the correct number of bytes are advanced.1677*1678* Note 2: The call to getCount relies on getCount() getting an offset into the current method, and1679* not out of line debug data. See the implementation of ComparingCursor::getCount() for more info.1680*/1681if (((0 == lineNumbersCount) && (_context->romMethodHasLineNumberCountCompressed()))1682|| ((lineNumbersInfoCompressedSize < 0xFFFF) && (lineNumbersCount < 0x7FFF))){1683/* it fits, c = 0 */1684U_32 lineNumbersCountEncoded = (lineNumbersInfoCompressedSize << 16) | ((lineNumbersCount << 1) & 0xFFFE);1685lineNumberCursor->writeU32(lineNumbersCountEncoded, Cursor::LINE_NUMBER_DATA);1686lineNumberCursor->writeU32(localVariablesCount, Cursor::LOCAL_VARIABLE_COUNT);1687} else {1688/* it does not fit, c = 1 */1689lineNumberCursor->writeU32((lineNumbersCount << 1) | 1, Cursor::LINE_NUMBER_DATA);1690lineNumberCursor->writeU32(localVariablesCount, Cursor::LOCAL_VARIABLE_COUNT);1691lineNumberCursor->writeU32(lineNumbersInfoCompressedSize, Cursor::LINE_NUMBER_DATA);1692}16931694lineNumberCursor->writeData(methodIterator->getLineNumbersInfoCompressed(), methodIterator->getLineNumbersInfoCompressedSize(), Cursor::LINE_NUMBER_DATA);16951696if (0 != localVariablesCount) {1697U_8 buffer[13];1698UDATA bufferLength;1699variableInfoCursor->mark(_srpKeyProducer->mapMethodIndexToVariableInfoKey(methodIterator->getIndex()));1700U_32 count = 0;1701U_32 lastIndex = 0;1702U_32 lastStartPC = 0;1703U_32 lastLength = 0;1704for (ClassFileOracle::LocalVariablesIterator localVariablesIterator = methodIterator->getLocalVariablesIterator();1705localVariablesIterator.isNotDone();1706localVariablesIterator.next()) {1707I_32 index = localVariablesIterator.getIndex() - lastIndex;1708I_32 startPC = localVariablesIterator.getStartPC() - lastStartPC;17091710I_32 length = localVariablesIterator.getLength();1711if (localVariablesIterator.hasGenericSignature()) {1712length |= J9_ROMCLASS_OPTINFO_VARIABLE_TABLE_HAS_GENERIC;1713}1714length = length - lastLength;17151716bufferLength = compressLocalVariableTableEntry(index, startPC, length, buffer);17171718variableInfoCursor->writeData(buffer, bufferLength, Cursor::LOCAL_VARIABLE_DATA);17191720variableInfoCursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(localVariablesIterator.getNameIndex()), Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8);1721variableInfoCursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(localVariablesIterator.getDescriptorIndex()), Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8);1722if (localVariablesIterator.hasGenericSignature()) {1723variableInfoCursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(localVariablesIterator.getGenericSignatureIndex()), Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8);1724}17251726lastIndex = localVariablesIterator.getIndex();1727lastStartPC = localVariablesIterator.getStartPC();1728lastLength = localVariablesIterator.getLength();17291730++count;1731}1732Trc_BCU_Assert_Equals(count, localVariablesCount);1733}17341735/* Once done writing the 'variable table' the cursor is notified. This is done to1736* enable special cursors like the comparing cursor to update their internal1737* information1738*/1739variableInfoCursor->notifyVariableTableWriteEnd();17401741/* Both cursors have to be padded, because the low bit is used as a tag, if the1742* addressed are unaligned, the low bit may not be free */1743if (!(_context->shouldWriteDebugDataInline())) {1744/* When out of line, a 16bit alignment is required for the tag bit */1745lineNumberCursor->padToAlignment(sizeof(U_16), Cursor::LINE_NUMBER_DATA);1746variableInfoCursor->padToAlignment(sizeof(U_16), Cursor::LOCAL_VARIABLE_DATA);1747} else {1748/* When in line, a 32bit alignment is required for the next sections1749* after the debug info section. Both cursors lineNumberCursor and1750* variableInfoCursor are identical, only one needs to be padded */1751lineNumberCursor->padToAlignment(sizeof(U_32), Cursor::LINE_NUMBER_DATA);1752}17531754if (markAndCountOnly) {1755_methodNotes[methodIterator->getIndex()].debugInfoSize = U_32(lineNumberCursor->getCount() - start);1756}1757}1758}17591760void1761ROMClassWriter::writeSourceDebugExtension(Cursor *cursor)1762{1763if ((_classFileOracle->hasSourceDebugExtension() && _context->shouldPreserveSourceDebugExtension()) || (_context->romClassHasSourceDebugExtension())) {1764cursor->mark(_sourceDebugExtensionSRPKey);1765cursor->writeU32(_classFileOracle->getSourceDebugExtensionLength(), Cursor::SOURCE_DEBUG_EXT_LENGTH);1766cursor->writeData(_classFileOracle->getSourceDebugExtensionData(), _classFileOracle->getSourceDebugExtensionLength(), Cursor::SOURCE_DEBUG_EXT_DATA);1767cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1768}1769}17701771/*1772* Records in the ROM class has the following layout:1773* 4 bytes for the number of record components in the class1774* for each record component:1775* J9ROMRecordComponentShape1776* 4 bytes SRP to record component's generic signature if the component has a signature annotation.1777* 4 bytes length of annotation data in bytes, followed by annotation data. Omitted if there are no annotations.1778* 4 bytes length of type annotation data in bytes followed by type annotation data. Omitted if there are no type annotations.1779*1780* For example, if a record component has a generic signature annotation and no other annotations the record components shape will look like:1781* J9ROMRecordComponentShape1782* 4 bytes SRP1783*/1784void1785ROMClassWriter::writeRecordComponents(Cursor *cursor, bool markAndCountOnly)1786{1787if (! _classFileOracle->isRecord()) {1788return;1789}17901791cursor->mark(_recordInfoSRPKey);17921793/* number of record components */1794if (markAndCountOnly) {1795cursor->skip(sizeof(U_32));1796} else {1797cursor->writeU32(_classFileOracle->getRecordComponentCount(), Cursor::GENERIC);1798}17991800ClassFileOracle::RecordComponentIterator iterator = _classFileOracle->getRecordComponentIterator();1801while ( iterator.isNotDone() ) {1802if (markAndCountOnly) {1803cursor->skip(sizeof(J9ROMRecordComponentShape));1804} else {1805CheckSize _(cursor, sizeof(J9ROMRecordComponentShape));18061807/* record component name and descriptor */1808cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getNameIndex()), Cursor::SRP_TO_UTF8);1809cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getDescriptorIndex()), Cursor::SRP_TO_UTF8);18101811/* attribute flags */1812U_32 attributeFlags = 0;1813if (iterator.hasGenericSignature()) {1814attributeFlags |= J9RecordComponentFlagHasGenericSignature;1815}1816if (iterator.hasAnnotation()) {1817attributeFlags |= J9RecordComponentFlagHasAnnotations;1818}1819if (iterator.hasTypeAnnotation()) {1820attributeFlags |= J9RecordComponentFlagHasTypeAnnotations;1821}1822cursor->writeU32(attributeFlags, Cursor::GENERIC);1823}18241825/* write optional attributes */1826if (iterator.hasGenericSignature()) {1827if (markAndCountOnly) {1828cursor->skip(sizeof(J9SRP));1829} else {1830cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);1831}1832}1833if (iterator.hasAnnotation()) {1834AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1835_classFileOracle->recordComponentAnnotationDo(iterator.getRecordComponentIndex(), &annotationWriter, &annotationWriter, &annotationWriter);1836cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1837}1838if (iterator.hasTypeAnnotation()) {1839AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);1840_classFileOracle->recordComponentTypeAnnotationDo(iterator.getRecordComponentIndex(), &annotationWriter, &annotationWriter, &annotationWriter);1841cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);1842}18431844iterator.next();1845}1846}18471848/*1849* PermittedSubclasses ROM class layout:1850* 4 bytes for number of classes (actually takes up two, but use 4 for alignment)1851* for number of classes:1852* 4 byte SRP to class name1853*/1854void1855ROMClassWriter::writePermittedSubclasses(Cursor *cursor, bool markAndCountOnly)1856{1857if (_classFileOracle->isSealed()) {1858cursor->mark(_permittedSubclassesInfoSRPKey);18591860U_16 classCount = _classFileOracle->getPermittedSubclassesClassCount();1861if (markAndCountOnly) {1862cursor->skip(sizeof(U_32));1863} else {1864cursor->writeU32(classCount, Cursor::GENERIC);1865}18661867for (U_16 index = 0; index < classCount; index++) {1868if (markAndCountOnly) {1869cursor->skip(sizeof(J9SRP));1870} else {1871U_16 classNameCpIndex = _classFileOracle->getPermittedSubclassesClassNameAtIndex(index);1872cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(classNameCpIndex), Cursor::SRP_TO_UTF8);1873}1874}1875}1876}18771878#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1879void1880ROMClassWriter::writeInjectedInterfaces(Cursor *cursor, bool markAndCountOnly)1881{1882if (_interfaceInjectionInfo->numOfInterfaces > 0) {1883cursor->mark(_injectedInterfaceInfoSRPKey);18841885if (markAndCountOnly) {1886cursor->skip(sizeof(U_32));1887} else {1888cursor->writeU32(_interfaceInjectionInfo->numOfInterfaces, Cursor::GENERIC);1889}1890}1891}1892#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1893void1894ROMClassWriter::writeOptionalInfo(Cursor *cursor)1895{1896// TODO check if we care about alignment of optional info1897cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);18981899/*1900* TODO The following is written in storeOptionalData, but likely needs to be a part of something else1901*1902* J9EnclosingObject:1903* U_32 classRefCPIndex1904* SRP nameAndSignature1905*/1906if (_classFileOracle->hasEnclosingMethod()) {1907cursor->mark(_enclosingMethodSRPKey);1908cursor->writeU32(_constantPoolMap->getROMClassCPIndexForReference(_classFileOracle->getEnclosingMethodClassRefIndex()), Cursor::GENERIC);1909cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getEnclosingMethodNameAndSignatureIndex()), Cursor::SRP_TO_NAME_AND_SIGNATURE);1910}19111912/*1913* OptionalInfo is made up of the following information:1914*1915* All entries are optional, present only if the appropriate data is available.1916*1917* SRP to source file name1918* SRP to generic signature1919* SRP to source debug extensions1920* SRP to annotation info1921* SRP to Method Debug Info1922* SRP to enclosing method1923* SRP to simple name1924* SRP to 'SRP' (self) if OPTINFO_VERIFY_EXCLUDE.. pretty much a flag, leaving an empty slot.1925* SRP to class annotations1926* SRP to class Type Annotations1927* SRP to record class component attributes1928* SRP to PermittedSubclasses attribute1929* SRP to injected interfaces info1930*/1931cursor->mark(_optionalInfoSRPKey);19321933if ((_classFileOracle->hasSourceFile() && _context->shouldPreserveSourceFileName())1934|| (_context->romClassHasSourceFileName())) {1935cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getSourceFileIndex()), Cursor::OPTINFO_SOURCE_FILE_NAME);1936}19371938if (_classFileOracle->hasGenericSignature()) {1939cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);1940}19411942if ((_classFileOracle->hasSourceDebugExtension() && (_context->shouldPreserveSourceDebugExtension()))1943|| (_context->romClassHasSourceDebugExtension())) {1944cursor->writeSRP(_sourceDebugExtensionSRPKey, Cursor::SRP_TO_SOURCE_DEBUG_EXT);1945}19461947if (_classFileOracle->hasEnclosingMethod()) {1948cursor->writeSRP(_enclosingMethodSRPKey, Cursor::SRP_TO_GENERIC);1949}19501951if (_classFileOracle->hasSimpleName()) {1952cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getSimpleNameIndex()), Cursor::SRP_TO_UTF8);1953}19541955if (_classFileOracle->hasVerifyExcludeAttribute()) {1956cursor->writeU32(0, Cursor::GENERIC); /* This is required for getSRPPtr in util/optinfo.c to work (counts bits in romClass->optionalFlags) */1957}19581959if (_classFileOracle->hasClassAnnotations()) {1960cursor->writeSRP(_annotationInfoClassSRPKey, Cursor::SRP_TO_GENERIC);1961}1962if (_classFileOracle->hasTypeAnnotations()) {1963cursor->writeSRP(_typeAnnotationInfoSRPKey, Cursor::SRP_TO_GENERIC);1964}1965if (_classFileOracle->isRecord()) {1966cursor->writeSRP(_recordInfoSRPKey, Cursor::SRP_TO_GENERIC);1967}1968if (_classFileOracle->isSealed()) {1969cursor->writeSRP(_permittedSubclassesInfoSRPKey, Cursor::SRP_TO_GENERIC);1970}1971#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1972if (_interfaceInjectionInfo->numOfInterfaces > 0) {1973cursor->writeSRP(_injectedInterfaceInfoSRPKey, Cursor::SRP_TO_GENERIC);1974}1975#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1976}19771978void1979ROMClassWriter::writeCallSiteData(Cursor *cursor, bool markAndCountOnly)1980{1981if (_constantPoolMap->hasCallSites() || _classFileOracle->hasBootstrapMethods()) {1982cursor->mark(_callSiteDataSRPKey);1983}1984if (_constantPoolMap->hasCallSites()) {1985UDATA size = UDATA(_constantPoolMap->getCallSiteCount()) * (sizeof(J9SRP) + sizeof(U_16));1986CheckSize _(cursor, size);1987#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1988Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeCallSiteData();1989#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1990Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeCallSiteData();1991#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1992}1993if (_classFileOracle->hasBootstrapMethods()) {1994#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1995Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeBootstrapMethods();1996#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */1997Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeBootstrapMethods();1998#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */1999}2000}20012002#if defined(J9VM_OPT_METHOD_HANDLE)2003void2004ROMClassWriter::writeVarHandleMethodTypeLookupTable(Cursor *cursor, bool markAndCountOnly)2005{2006if (_constantPoolMap->hasVarHandleMethodRefs()) {2007cursor->mark(_varHandleMethodTypeLookupTableSRPKey);2008UDATA size = _constantPoolMap->getVarHandleMethodTypePaddedCount() * sizeof(U_16);2009CheckSize _(cursor, size);2010#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)2011Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeVarHandleMethodTypeLookupTable();2012#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */2013Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeVarHandleMethodTypeLookupTable();2014#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */2015}2016}2017#endif /* defined(J9VM_OPT_METHOD_HANDLE) */20182019void2020ROMClassWriter::writeStaticSplitTable(Cursor *cursor, bool markAndCountOnly)2021{2022if (_constantPoolMap->hasStaticSplitTable()) {2023cursor->mark(_staticSplitTableSRPKey);2024UDATA size = UDATA(_constantPoolMap->getStaticSplitEntryCount()) * sizeof(U_16);2025CheckSize _(cursor, size);2026#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)2027Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeStaticSplitTable();2028#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */2029Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeStaticSplitTable();2030#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */2031}2032}20332034void2035ROMClassWriter::writeSpecialSplitTable(Cursor *cursor, bool markAndCountOnly)2036{2037if (_constantPoolMap->hasSpecialSplitTable()) {2038cursor->mark(_specialSplitTableSRPKey);2039UDATA size = UDATA(_constantPoolMap->getSpecialSplitEntryCount()) * sizeof(U_16);2040CheckSize _(cursor, size);2041#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)2042Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeSpecialSplitTable();2043#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */2044Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeSpecialSplitTable();2045#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */2046}2047}20482049void2050ROMClassWriter::writeByteCodes(Cursor* cursor, ClassFileOracle::MethodIterator *methodIterator)2051{2052U_8 *code = methodIterator->getCode();20532054if (!methodIterator->isByteCodeFixupDone()) {2055ClassFileOracle::BytecodeFixupEntry *fixupTable = methodIterator->getByteCodeFixupTable();2056ClassFileOracle::BytecodeFixupEntry *end = fixupTable + methodIterator->getByteCodeFixupCount();20572058for (ClassFileOracle::BytecodeFixupEntry *entry = fixupTable; entry != end; ++entry) {2059U_16 *dest = (U_16 *) &code[entry->codeIndex];20602061switch(entry->type) {2062case ConstantPoolMap::LDC:2063code[entry->codeIndex] = U_8(_constantPoolMap->getROMClassCPIndex(entry->cpIndex));2064break;20652066case ConstantPoolMap::INVOKE_DYNAMIC:2067/* rewrite the invokedynamic index to be the callSiteIndex */2068*dest = _constantPoolMap->getCallSiteIndex(entry->cpIndex);2069break;20702071case ConstantPoolMap::INVOKE_STATIC:2072if (_constantPoolMap->isStaticSplit(entry->cpIndex)) {2073code[entry->codeIndex - 1] = JBinvokestaticsplit;2074*dest = _constantPoolMap->getStaticSplitTableIndex(entry->cpIndex);2075} else {2076*dest = _constantPoolMap->getROMClassCPIndex(entry->cpIndex, entry->type);2077}2078break;20792080case ConstantPoolMap::INVOKE_SPECIAL:2081if (_constantPoolMap->isSpecialSplit(entry->cpIndex)) {2082code[entry->codeIndex - 1] = JBinvokespecialsplit;2083*dest = _constantPoolMap->getSpecialSplitTableIndex(entry->cpIndex);2084} else {2085*dest = _constantPoolMap->getROMClassCPIndex(entry->cpIndex, entry->type);2086}2087break;20882089default:2090*dest = _constantPoolMap->getROMClassCPIndex(entry->cpIndex, entry->type);2091break;2092}2093}2094methodIterator->setByteCodeFixupDone();2095}20962097cursor->writeData(code, methodIterator->getCodeLength(), Cursor::BYTECODE);2098}20992100U_322101ROMClassWriter::computeNativeSignatureSize(U_8 *methodDescriptor)2102{2103Cursor countingCursor(0, NULL, _context);2104writeNativeSignature(&countingCursor, methodDescriptor, 0);2105return U_32(countingCursor.getCount());2106}21072108void2109ROMClassWriter::writeNativeSignature(Cursor *cursor, U_8 *methodDescriptor, U_8 nativeArgCount)2110{2111/* mapping characters A..Z */2112static const U_8 nativeArgCharConversion[] = {21130, PARAM_BYTE, PARAM_CHAR, PARAM_DOUBLE,21140, PARAM_FLOAT, 0, 0,2115PARAM_INT, PARAM_LONG, 0, PARAM_OBJECT,21160, 0, 0, 0,21170, 0, PARAM_SHORT, 0,21180, PARAM_VOID, 0, 0,21190, PARAM_BOOLEAN};21202121UDATA index = 1;21222123cursor->writeU8(nativeArgCount, Cursor::GENERIC);21242125/* Parse and write return type */2126while (')' != methodDescriptor[index]) {2127++index;2128}2129++index;2130if ('[' == methodDescriptor[index]) {2131cursor->writeU8(PARAM_OBJECT, Cursor::GENERIC);2132} else {2133cursor->writeU8(nativeArgCharConversion[methodDescriptor[index] - 'A'], Cursor::GENERIC);2134}21352136index = 1;21372138/* Parse the signature inside the ()'s */2139while (')' != methodDescriptor[index]) {2140if ('[' == methodDescriptor[index]) {2141cursor->writeU8(PARAM_OBJECT, Cursor::GENERIC);2142while ('[' == methodDescriptor[index]) {2143++index;2144}2145} else {2146cursor->writeU8(nativeArgCharConversion[methodDescriptor[index] - 'A'], Cursor::GENERIC);2147}2148if ('L' == methodDescriptor[index]) {2149while (';' != methodDescriptor[index]) {2150++index;2151}2152}2153++index;2154}2155}215621572158