Path: blob/master/runtime/bcutil/ClassFileWriter.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* ClassFileWriter.cpp23*/2425/* Note: j9.h has to be included before bcnames.h to avoid conflict of26* J9InternalVMLabels->JBaload0getfield in j9generated.h with27* the macro JBaload0getfield in bcnames.h.28*/29#include "j9.h"30#include "bcnames.h"31#include "bcutil.h"32#include "cfr.h"33#include "cfreader.h"34#include "pcstack.h"35#include "rommeth.h"36#include "util_api.h"3738#include "ClassFileWriter.hpp"3940#define DECLARE_UTF8_ATTRIBUTE_NAME(instanceName, name) \41static const struct { \42U_16 length; \43U_8 data[sizeof(name)]; \44} instanceName = { sizeof(name) - 1, name }4546DECLARE_UTF8_ATTRIBUTE_NAME(CONSTANT_VALUE, "ConstantValue");47DECLARE_UTF8_ATTRIBUTE_NAME(CODE, "Code");48DECLARE_UTF8_ATTRIBUTE_NAME(STACK_MAP_TABLE, "StackMapTable");49DECLARE_UTF8_ATTRIBUTE_NAME(EXCEPTIONS, "Exceptions");50DECLARE_UTF8_ATTRIBUTE_NAME(METHODPARAMETERS, "MethodParameters");51DECLARE_UTF8_ATTRIBUTE_NAME(INNER_CLASSES, "InnerClasses");52DECLARE_UTF8_ATTRIBUTE_NAME(ENCLOSING_METHOD, "EnclosingMethod");53DECLARE_UTF8_ATTRIBUTE_NAME(SIGNATURE, "Signature");54DECLARE_UTF8_ATTRIBUTE_NAME(SOURCE_FILE, "SourceFile");55DECLARE_UTF8_ATTRIBUTE_NAME(SOURCE_DEBUG_EXTENSION, "SourceDebugExtension");56DECLARE_UTF8_ATTRIBUTE_NAME(LINE_NUMBER_TABLE, "LineNumberTable");57DECLARE_UTF8_ATTRIBUTE_NAME(LOCAL_VARIABLE_TABLE, "LocalVariableTable");58DECLARE_UTF8_ATTRIBUTE_NAME(LOCAL_VARIABLE_TYPE_TABLE, "LocalVariableTypeTable");59DECLARE_UTF8_ATTRIBUTE_NAME(RUNTIME_VISIBLE_ANNOTATIONS, "RuntimeVisibleAnnotations");60DECLARE_UTF8_ATTRIBUTE_NAME(RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, "RuntimeVisibleParameterAnnotations");61DECLARE_UTF8_ATTRIBUTE_NAME(RUNTIME_VISIBLE_TYPE_ANNOTATIONS, "RuntimeVisibleTypeAnnotations");62DECLARE_UTF8_ATTRIBUTE_NAME(ANNOTATION_DEFAULT, "AnnotationDefault");63DECLARE_UTF8_ATTRIBUTE_NAME(BOOTSTRAP_METHODS, "BootstrapMethods");64DECLARE_UTF8_ATTRIBUTE_NAME(RECORD, "Record");65DECLARE_UTF8_ATTRIBUTE_NAME(PERMITTED_SUBCLASSES, "PermittedSubclasses");66#if JAVA_SPEC_VERSION >= 1167DECLARE_UTF8_ATTRIBUTE_NAME(NEST_MEMBERS, "NestMembers");68DECLARE_UTF8_ATTRIBUTE_NAME(NEST_HOST, "NestHost");69#endif /* JAVA_SPEC_VERSION >= 11 */7071void72ClassFileWriter::analyzeROMClass()73{74_cpHashTable = hashTableNew(OMRPORT_FROM_J9PORT(_portLibrary), "ClassFileWriter::_cpHashTable", _romClass->classFileCPCount, sizeof(HashTableEntry), 0, 0, J9MEM_CATEGORY_JVMTI, hashFunction, equalFunction, NULL, NULL);75if (NULL == _cpHashTable) {76_buildResult = OutOfMemory;77return;78}7980#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)81if (J9_ARE_ALL_BITS_SET(_romClass->optionalFlags, J9_ROMCLASS_OPTINFO_INJECTED_INTERFACE_INFO)) {82_numOfInjectedInterfaces = getNumberOfInjectedInterfaces(_romClass);83}84#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */8586/* Walk ROM class adding hashtable entries for all referenced UTF8s and NASs, with index=0 */87analyzeConstantPool();88analyzeInterfaces();89analyzeFields();90analyzeMethods();91addClassEntry(J9ROMCLASS_CLASSNAME(_romClass), 0);9293/* Super class name is NULL only for java/lang/Object */94if (NULL != J9ROMCLASS_SUPERCLASSNAME(_romClass)) {95addClassEntry(J9ROMCLASS_SUPERCLASSNAME(_romClass), 0);96}9798if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccRecord)) {99analyzeRecordAttribute();100}101102if (J9ROMCLASS_IS_SEALED(_romClass)) {103addEntry((void*) &PERMITTED_SUBCLASSES, 0, CFR_CONSTANT_Utf8);104105U_32 *permittedSubclassesCountPtr = getNumberOfPermittedSubclassesPtr(_romClass);106for (U_32 i = 0; i < *permittedSubclassesCountPtr; i++) {107J9UTF8* permittedSubclassNameUtf8 = permittedSubclassesNameAtIndex(permittedSubclassesCountPtr, i);108addEntry(permittedSubclassNameUtf8, 0, CFR_CONSTANT_Utf8);109}110}111112J9EnclosingObject * enclosingObject = getEnclosingMethodForROMClass(_javaVM, NULL, _romClass);113J9UTF8 * genericSignature = getGenericSignatureForROMClass(_javaVM, NULL, _romClass);114J9UTF8 * sourceFileName = getSourceFileNameForROMClass(_javaVM, NULL, _romClass);115J9SourceDebugExtension * sourceDebugExtension = getSourceDebugExtensionForROMClass(_javaVM, NULL, _romClass);116U_32 * annotationsData = getClassAnnotationsDataForROMClass(_romClass);117U_32 * typeAnnotationsData = getClassTypeAnnotationsDataForROMClass(_romClass);118J9UTF8 * outerClassName = J9ROMCLASS_OUTERCLASSNAME(_romClass);119J9UTF8 * simpleName = getSimpleNameForROMClass(_javaVM, NULL, _romClass);120#if JAVA_SPEC_VERSION >= 11121J9UTF8 *nestHost = J9ROMCLASS_NESTHOSTNAME(_romClass);122#endif /* JAVA_SPEC_VERSION >= 11 */123124/* For a local class only InnerClasses.class[i].inner_name_index is preserved as simpleName in its J9ROMClass */125if ((0 != _romClass->innerClassCount)126|| (0 != _romClass->enclosedInnerClassCount)127|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)128) {129addEntry((void *) &INNER_CLASSES, 0, CFR_CONSTANT_Utf8);130131if (NULL != outerClassName) {132addClassEntry(outerClassName, 0);133}134135if (NULL != simpleName) {136addEntry(simpleName, 0, CFR_CONSTANT_Utf8);137}138139J9SRP * innerClasses = (J9SRP *) J9ROMCLASS_INNERCLASSES(_romClass);140for (UDATA i = 0; i < _romClass->innerClassCount; i++, innerClasses++) {141J9UTF8 * className = NNSRP_PTR_GET(innerClasses, J9UTF8 *);142addClassEntry(className, 0);143}144J9SRP * enclosedInnerClasses = (J9SRP *) J9ROMCLASS_ENCLOSEDINNERCLASSES(_romClass);145for (UDATA i = 0; i < _romClass->enclosedInnerClassCount; i++, enclosedInnerClasses++) {146J9UTF8 * className = NNSRP_PTR_GET(enclosedInnerClasses, J9UTF8 *);147addClassEntry(className, 0);148}149}150151#if JAVA_SPEC_VERSION >= 11152/* Class can not have both a nest members and nest host attribute */153if (0 != _romClass->nestMemberCount) {154U_16 nestMemberCount = _romClass->nestMemberCount;155J9SRP *nestMembers = (J9SRP *) J9ROMCLASS_NESTMEMBERS(_romClass);156157addEntry((void *) &NEST_MEMBERS, 0, CFR_CONSTANT_Utf8);158for (U_16 i = 0; i < nestMemberCount; i++) {159J9UTF8 * className = NNSRP_GET(nestMembers[i], J9UTF8 *);160addClassEntry(className, 0);161}162} else if (NULL != nestHost) {163addEntry((void *) &NEST_HOST, 0, CFR_CONSTANT_Utf8);164addClassEntry(nestHost, 0);165}166#endif /* JAVA_SPEC_VERSION >= 11 */167168if (NULL != enclosingObject) {169addEntry((void *) &ENCLOSING_METHOD, 0, CFR_CONSTANT_Utf8);170J9ROMNameAndSignature * nas = J9ENCLOSINGOBJECT_NAMEANDSIGNATURE(enclosingObject);171if (NULL != nas) {172addNASEntry(nas);173}174}175176if (NULL != genericSignature) {177addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);178addEntry(genericSignature, 0, CFR_CONSTANT_Utf8);179}180181if (NULL != sourceFileName) {182addEntry((void *) &SOURCE_FILE, 0, CFR_CONSTANT_Utf8);183addEntry(sourceFileName, 0, CFR_CONSTANT_Utf8);184}185186if (NULL != sourceDebugExtension) {187addEntry((void *) &SOURCE_DEBUG_EXTENSION, 0, CFR_CONSTANT_Utf8);188}189190if (NULL != annotationsData) {191addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);192}193194if (NULL != typeAnnotationsData) {195addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);196}197198if (0 != _romClass->bsmCount) {199addEntry((void *) &BOOTSTRAP_METHODS, 0, CFR_CONSTANT_Utf8);200201U_32 bsmCount = _romClass->bsmCount;202U_32 callSiteCount = _romClass->callSiteCount;203J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);204U_16 * bsmIndices = (U_16 *) (callSiteData + callSiteCount);205U_16 * bsmData = bsmIndices + callSiteCount;206U_16 * bsmCursor = bsmData;207208for (U_32 i = 0; i < bsmCount; i++) {209U_16 argCount = bsmCursor[1];210bsmCursor += argCount + 2;211}212_bsmAttributeLength = (U_32)((bsmCursor - bsmData + 1) * sizeof(U_16)); /* +1 to account for num_bootstrap_methods */213}214215/* Walk callSiteData and add InvokeDynamic CP entries.216*217* InvokeDynamic entries in J9ROMClass are stored as CallSite data.218* For every call site that refers an InvokeDynamic entry, we store its J9ROMNameAndSignature and bootstrapMethodIndex.219* First the SRPs to J9ROMNameAndSignature for each callsite are stored.220* This is followed by the bootstrapMethodIndex for each callsite.221* So the CallSite data consists of a block of SRPs to J9ROMNameAndSignature, followed by a block of bootstrapMethodIndices.222*223* If there are multiple call sites referring to same InvokeDynamic CP entry,224* then the contents get duplicated as many times.225*226* Eg: Say there are two InvokeDynamic entries in .class227*228* InvokeDynamic1229* bootstrap_method_attr_index1230* name_and_type_index1231* InvokeDynamic2232* bootstrap_method_attr_index2233* name_and_type_index2234*235* If InvokeDynamic1 is referred twice and InvokeDynamic2 is referred thrice,236* CallSite data layout in J9ROMClass will be:237*238* index: 0 1 2 3 4 0 1 2 3 4239*240* | SRP to NAS1 | SRP to NAS1 | SRP to NAS2 | SRP to NAS2 | SRP to NAS2 | bsm1 | bsm1 | bsm2 | bsm2 | bsm2 |241*242* When adding an entry in _cpHashTable for an InvokeDynamic entry,243* address of its SRP to J9ROMNameAndSignature is used as key.244* However, we need to skip the duplicate entries.245* In above example, entries at index 1, 3 and 4 are duplicate and should be skipped.246* This is achieved by checking J9ROMNameAndSignature address of callSite being considered with the247* address of J9ROMNameAndSignature of the callSite last stored in _cpHashTable.248* If they are same, it indicates a duplicate entry and can be skipped.249*/250if (0 != _romClass->callSiteCount) {251J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);252U_16 const * bsmIndices = (U_16 *) (callSiteData + _romClass->callSiteCount);253J9ROMNameAndSignature * prevNAS = NULL;254U_16 prevIndex = (U_16)-1; /* set to invalid value */255256for (UDATA i = 0; i < _romClass->callSiteCount; i++) {257J9ROMNameAndSignature * nas = SRP_PTR_GET(callSiteData + i, J9ROMNameAndSignature *);258U_16 index = bsmIndices[i];259if ((nas != prevNAS) || (index != prevIndex)) {260/* Both the index and the NAS need to be the same to be considered the same element */261addEntry(callSiteData + i, 0, CFR_CONSTANT_InvokeDynamic);262addNASEntry(nas);263prevNAS = nas;264prevIndex = index;265}266}267}268269/* Walk the hashtable assigning indexes to all entries with index==0 */270271/* romConstantPoolCount has only one slot for Long/Double CP entries,272* but they occupy two slots in .class constant pool.273*/274U_16 doubleSlotCount = _romClass->romConstantPoolCount - _romClass->ramConstantPoolCount;275_constantPoolCount = _romClass->romConstantPoolCount + doubleSlotCount;276J9HashTableState hashTableState;277HashTableEntry * entry = (HashTableEntry *) hashTableStartDo(_cpHashTable, &hashTableState);278while (NULL != entry) {279if (0 == entry->cpIndex) {280entry->cpIndex = _constantPoolCount;281_constantPoolCount += 1;282if ((CFR_CONSTANT_Long == entry->cpType) || (CFR_CONSTANT_Double == entry->cpType)) {283_constantPoolCount += 1;284}285}286entry = (HashTableEntry *) hashTableNextDo(&hashTableState);287}288}289290void291ClassFileWriter::analyzeConstantPool()292{293/* Walk ROM CP adding hashtable entries for all294* J9CPTYPE_INT, J9CPTYPE_FLOAT, J9CPTYPE_LONG, J9CPTYPE_DOUBLE CP entries, with their index,295* and all referenced UTF8s & NASs296*/297U_16 cpCount = _romClass->romConstantPoolCount;298J9ROMConstantPoolItem * constantPool = J9_ROM_CP_FROM_ROM_CLASS(_romClass);299U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(_romClass);300301for (U_16 i = 1; i < cpCount; i++) {302J9ROMConstantPoolItem * cpItem = constantPool + i;303switch (J9_CP_TYPE(cpShapeDescription, i)) {304case J9CPTYPE_CLASS:305addClassEntry(J9ROMCLASSREF_NAME((J9ROMClassRef *) cpItem), i);306break;307case J9CPTYPE_STRING:308addEntry(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem), 0, CFR_CONSTANT_Utf8);309break;310case J9CPTYPE_FIELD:311addNASEntry(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) cpItem));312break;313case J9CPTYPE_INSTANCE_METHOD:314case J9CPTYPE_STATIC_METHOD:315case J9CPTYPE_INTERFACE_METHOD:316case J9CPTYPE_INTERFACE_STATIC_METHOD:317case J9CPTYPE_INTERFACE_INSTANCE_METHOD:318case J9CPTYPE_HANDLE_METHOD:319addNASEntry(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) cpItem));320break;321case J9CPTYPE_METHOD_TYPE:322addEntry(J9ROMMETHODTYPEREF_SIGNATURE((J9ROMMethodTypeRef *) cpItem), 0, CFR_CONSTANT_Utf8);323break;324case J9CPTYPE_METHODHANDLE:325/* do nothing */326break;327case J9CPTYPE_INT:328addEntry(&((J9ROMSingleSlotConstantRef *) cpItem)->data, i, CFR_CONSTANT_Integer);329break;330case J9CPTYPE_FLOAT:331addEntry(&((J9ROMSingleSlotConstantRef *) cpItem)->data, i, CFR_CONSTANT_Float);332break;333case J9CPTYPE_LONG:334addEntry(&((J9ROMConstantRef *) cpItem)->slot1, i + (i - _romClass->ramConstantPoolCount), CFR_CONSTANT_Long);335break;336case J9CPTYPE_DOUBLE:337addEntry(&((J9ROMConstantRef *) cpItem)->slot1, i + (i - _romClass->ramConstantPoolCount), CFR_CONSTANT_Double);338break;339case J9CPTYPE_ANNOTATION_UTF8:340addEntry(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem), i, CFR_CONSTANT_Utf8);341break;342case J9CPTYPE_CONSTANT_DYNAMIC:343addNASEntry(J9ROMCONSTANTDYNAMICREF_NAMEANDSIGNATURE((J9ROMConstantDynamicRef *) cpItem));344break;345default:346Trc_BCU_Assert_ShouldNeverHappen();347break;348}349}350}351352void353ClassFileWriter::analyzeInterfaces()354{355J9SRP * interfaceNames = J9ROMCLASS_INTERFACES(_romClass);356UDATA interfaceCount = _romClass->interfaceCount;357#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)358interfaceCount -= _numOfInjectedInterfaces;359#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */360for (UDATA i = 0; i < interfaceCount; i++) {361J9UTF8 * interfaceName = NNSRP_GET(interfaceNames[i], J9UTF8*);362addClassEntry(interfaceName, 0);363}364}365366void367ClassFileWriter::analyzeFields()368{369J9ROMFieldWalkState fieldWalkState;370J9ROMFieldShape * fieldShape = romFieldsStartDo(_romClass, &fieldWalkState);371while (NULL != fieldShape) {372addEntry(J9ROMFIELDSHAPE_NAME(fieldShape), 0, CFR_CONSTANT_Utf8);373addEntry(J9ROMFIELDSHAPE_SIGNATURE(fieldShape), 0, CFR_CONSTANT_Utf8);374375J9UTF8 * genericSignature = romFieldGenericSignature(fieldShape);376if (NULL != genericSignature) {377addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);378addEntry(genericSignature, 0, CFR_CONSTANT_Utf8);379}380if (J9FieldFlagHasFieldAnnotations & fieldShape->modifiers) {381addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);382}383384if (J9FieldFlagHasTypeAnnotations & fieldShape->modifiers) {385addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);386}387388if (J9FieldFlagConstant & fieldShape->modifiers) {389addEntry((void *) &CONSTANT_VALUE, 0, CFR_CONSTANT_Utf8);390391if (0 == (J9FieldFlagObject & fieldShape->modifiers)) {392U_32 * value = romFieldInitialValueAddress(fieldShape);393U_8 cpType = 0;394switch (J9FieldTypeMask & fieldShape->modifiers) {395case J9FieldTypeDouble:396cpType = CFR_CONSTANT_Double;397break;398case J9FieldTypeLong:399cpType = CFR_CONSTANT_Long;400break;401case J9FieldTypeFloat:402cpType = CFR_CONSTANT_Float;403break;404default:405cpType = CFR_CONSTANT_Integer;406break;407}408addEntry(value, 0, cpType);409}410}411412fieldShape = romFieldsNextDo(&fieldWalkState);413}414}415416void417ClassFileWriter::analyzeMethods()418{419J9ROMMethod * method = J9ROMCLASS_ROMMETHODS(_romClass);420421for (U_32 i = 0; i < _romClass->romMethodCount; i++) {422addEntry(J9ROMMETHOD_NAME(method), 0, CFR_CONSTANT_Utf8);423addEntry(J9ROMMETHOD_SIGNATURE(method), 0, CFR_CONSTANT_Utf8);424425if (J9ROMMETHOD_HAS_GENERIC_SIGNATURE(method)) {426addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);427addEntry(J9_GENERIC_SIGNATURE_FROM_ROM_METHOD(method), 0, CFR_CONSTANT_Utf8);428}429if (0 == ((J9AccAbstract | J9AccNative) & method->modifiers)) {430addEntry((void *) &CODE, 0, CFR_CONSTANT_Utf8);431}432if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {433J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);434if (0 != exceptionInfo->throwCount) {435addEntry((void *) &EXCEPTIONS, 0, CFR_CONSTANT_Utf8);436437U_8 * address = (U_8 *) (exceptionInfo + 1);438address += sizeof(J9ExceptionHandler) * exceptionInfo->catchCount;439J9SRP * throwNames = (J9SRP *) address;440441for (U_16 i = 0; i < exceptionInfo->throwCount; i++) {442J9UTF8 * throwName = NNSRP_GET(throwNames[i], J9UTF8 *);443addClassEntry(throwName, 0);444}445}446}447if (J9ROMMETHOD_HAS_METHOD_PARAMETERS(method)) {448addEntry((void *) &METHODPARAMETERS, 0, CFR_CONSTANT_Utf8);449/*450J9MethodParametersData451__________________________452| U_8 methodParameterCount |453|__________________________|454|__________________________|455| J9MethodParameter |456|__________________________|457| J9MethodParameter | ===========> methodParameterCount * J9MethodParameter458|__________________________|459| . . . |460| . . . |461|__________________________|462463struct J9MethodParameter464---------------------------------------465|J9SRP name (J9SRP -> J9UTF8) |466|U_16 flags |467---------------------------------------468*/469J9MethodParametersData * methodParametersData = methodParametersFromROMMethod(method);470J9MethodParameter * parameters = &methodParametersData->parameters;471for (U_8 i = 0; i < methodParametersData->parameterCount; i++) {472J9UTF8 * parameterNameUTF8 = SRP_GET(parameters[i].name, J9UTF8 *);473if (NULL != parameterNameUTF8) {474addEntry(parameterNameUTF8, 0, CFR_CONSTANT_Utf8);475}476}477}478if (J9ROMMETHOD_HAS_ANNOTATIONS_DATA(method)) {479addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);480}481if (J9ROMMETHOD_HAS_PARAMETER_ANNOTATIONS(method)) {482addEntry((void *) &RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);483}484U_32 extendedModifiers = getExtendedModifiersDataFromROMMethod(method);485if (J9ROMMETHOD_HAS_METHOD_TYPE_ANNOTATIONS(extendedModifiers) || J9ROMMETHOD_HAS_CODE_TYPE_ANNOTATIONS(extendedModifiers)) {486addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);487}488if (J9ROMMETHOD_HAS_DEFAULT_ANNOTATION(method)) {489addEntry((void *) &ANNOTATION_DEFAULT, 0, CFR_CONSTANT_Utf8);490}491if (J9ROMMETHOD_HAS_STACK_MAP(method)) {492addEntry((void *) &STACK_MAP_TABLE, 0, CFR_CONSTANT_Utf8);493}494495J9MethodDebugInfo* debugInfo = getMethodDebugInfoFromROMMethod(method);496if (NULL != debugInfo) {497if (0 != debugInfo->lineNumberCount) {498addEntry((void *) &LINE_NUMBER_TABLE, 0, CFR_CONSTANT_Utf8);499}500501if (0 != debugInfo->varInfoCount) {502addEntry((void *) &LOCAL_VARIABLE_TABLE, 0, CFR_CONSTANT_Utf8);503504J9VariableInfoWalkState state;505J9VariableInfoValues *values = NULL;506bool typeTable = false;507508values = variableInfoStartDo(debugInfo, &state);509while(NULL != values) {510addEntry(values->name, 0, CFR_CONSTANT_Utf8);511addEntry(values->signature, 0, CFR_CONSTANT_Utf8);512513if (NULL != values->genericSignature) {514/* If any of the values has 'genericSignature' non-null, then it has LocalVariableTypeTable */515typeTable = true;516addEntry(values->genericSignature, 0, CFR_CONSTANT_Utf8);517}518values = variableInfoNextDo(&state);519}520if (typeTable) {521addEntry((void *) &LOCAL_VARIABLE_TYPE_TABLE, 0, CFR_CONSTANT_Utf8);522}523}524}525method = nextROMMethod(method);526}527}528529void530ClassFileWriter::analyzeRecordAttribute()531{532addEntry((void *) &RECORD, 0, CFR_CONSTANT_Utf8);533534/* first 4 bytes contains number of record components */535U_32 numberOfRecords = getNumberOfRecordComponents(_romClass);536J9ROMRecordComponentShape* recordComponent = recordComponentStartDo(_romClass);537for (U_32 i = 0; i < numberOfRecords; i++) {538539/* record component name and signature */540addEntry(J9ROMRECORDCOMPONENTSHAPE_NAME(recordComponent), 0, CFR_CONSTANT_Utf8);541addEntry(J9ROMRECORDCOMPONENTSHAPE_SIGNATURE(recordComponent), 0, CFR_CONSTANT_Utf8);542543/* analyze attributes */544if (recordComponentHasSignature(recordComponent)) {545J9UTF8* genericSignature = getRecordComponentGenericSignature(recordComponent);546addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);547addEntry(genericSignature, 0, CFR_CONSTANT_Utf8);548}549if (recordComponentHasAnnotations(recordComponent)) {550addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);551}552if (recordComponentHasTypeAnnotations(recordComponent)) {553addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);554}555556recordComponent = recordComponentNextDo(recordComponent);557}558}559560void561ClassFileWriter::writeClassFile()562{563writeU32(CFR_MAGIC);564writeU16(_romClass->minorVersion);565writeU16(_romClass->majorVersion);566writeConstantPool();567writeU16(_romClass->modifiers & CFR_CLASS_ACCESS_MASK);568writeU16(indexForClass(J9ROMCLASS_CLASSNAME(_romClass)));569/* Super class name is NULL only for java/lang/Object */570if (NULL != J9ROMCLASS_SUPERCLASSNAME(_romClass)) {571writeU16(indexForClass(J9ROMCLASS_SUPERCLASSNAME(_romClass)));572} else {573writeU16(0);574}575writeInterfaces();576writeFields();577writeMethods();578writeAttributes();579}580581void582ClassFileWriter::writeConstantPool()583{584U_16 cpCount = _romClass->romConstantPoolCount;585J9ROMConstantPoolItem * constantPool = J9_ROM_CP_FROM_ROM_CLASS(_romClass);586U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(_romClass);587588writeU16(_constantPoolCount);589590/* Expand all ROM CP entries into .class file CP entries */591for (U_16 i = 1; i < cpCount; i++) {592J9ROMConstantPoolItem * cpItem = constantPool + i;593594switch (J9_CP_TYPE(cpShapeDescription, i)) {595case J9CPTYPE_CLASS:596writeU8(CFR_CONSTANT_Class);597writeU16(indexForUTF8(J9ROMCLASSREF_NAME((J9ROMClassRef *) cpItem)));598break;599case J9CPTYPE_STRING:600writeU8(CFR_CONSTANT_String);601writeU16(indexForUTF8(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)));602break;603case J9CPTYPE_FIELD:604writeU8(CFR_CONSTANT_Fieldref);605writeU16(U_16(((J9ROMFieldRef *) cpItem)->classRefCPIndex));606writeU16(indexForNAS(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) cpItem)));607break;608case J9CPTYPE_INSTANCE_METHOD:609case J9CPTYPE_STATIC_METHOD:610case J9CPTYPE_HANDLE_METHOD:611writeU8(CFR_CONSTANT_Methodref);612writeU16(U_16(((J9ROMMethodRef *) cpItem)->classRefCPIndex));613writeU16(indexForNAS(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) cpItem)));614break;615case J9CPTYPE_INTERFACE_METHOD:616case J9CPTYPE_INTERFACE_STATIC_METHOD:617case J9CPTYPE_INTERFACE_INSTANCE_METHOD:618writeU8(CFR_CONSTANT_InterfaceMethodref);619writeU16(U_16(((J9ROMMethodRef *) cpItem)->classRefCPIndex));620writeU16(indexForNAS(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) cpItem)));621break;622case J9CPTYPE_METHOD_TYPE:623writeU8(CFR_CONSTANT_MethodType);624writeU16(indexForUTF8(J9ROMMETHODTYPEREF_SIGNATURE((J9ROMMethodTypeRef *) cpItem)));625break;626case J9CPTYPE_METHODHANDLE:627writeU8(CFR_CONSTANT_MethodHandle);628writeU8(U_8(((J9ROMMethodHandleRef *) cpItem)->handleTypeAndCpType >> BCT_J9DescriptionCpTypeShift));629writeU16(U_16(((J9ROMMethodHandleRef *) cpItem)->methodOrFieldRefIndex));630break;631case J9CPTYPE_INT:632writeU8(CFR_CONSTANT_Integer);633writeU32(((J9ROMSingleSlotConstantRef *) cpItem)->data);634break;635case J9CPTYPE_FLOAT:636writeU8(CFR_CONSTANT_Float);637writeU32(((J9ROMSingleSlotConstantRef *) cpItem)->data);638break;639case J9CPTYPE_LONG:640writeU8(CFR_CONSTANT_Long);641#ifdef J9VM_ENV_LITTLE_ENDIAN642writeU32(((J9ROMConstantRef *) cpItem)->slot2);643writeU32(((J9ROMConstantRef *) cpItem)->slot1);644#else /* J9VM_ENV_LITTLE_ENDIAN */645writeU32(((J9ROMConstantRef *) cpItem)->slot1);646writeU32(((J9ROMConstantRef *) cpItem)->slot2);647#endif /* J9VM_ENV_LITTLE_ENDIAN */648break;649case J9CPTYPE_DOUBLE:650writeU8(CFR_CONSTANT_Double);651#ifdef J9VM_ENV_LITTLE_ENDIAN652writeU32(((J9ROMConstantRef *) cpItem)->slot2);653writeU32(((J9ROMConstantRef *) cpItem)->slot1);654#else /* J9VM_ENV_LITTLE_ENDIAN */655writeU32(((J9ROMConstantRef *) cpItem)->slot1);656writeU32(((J9ROMConstantRef *) cpItem)->slot2);657#endif /* J9VM_ENV_LITTLE_ENDIAN */658break;659case J9CPTYPE_ANNOTATION_UTF8:660writeU8(CFR_CONSTANT_Utf8);661writeU16(J9UTF8_LENGTH(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)));662writeData(J9UTF8_LENGTH(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)), J9UTF8_DATA(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)));663break;664case J9CPTYPE_CONSTANT_DYNAMIC:665writeU8(CFR_CONSTANT_Dynamic);666writeU16(U_16((((J9ROMConstantDynamicRef *) cpItem)->bsmIndexAndCpType >> J9DescriptionCpTypeShift) & J9DescriptionCpBsmIndexMask));667writeU16(indexForNAS(J9ROMCONSTANTDYNAMICREF_NAMEANDSIGNATURE((J9ROMConstantDynamicRef *) cpItem)));668break;669default:670Trc_BCU_Assert_ShouldNeverHappen();671break;672}673}674675U_16 doubleSlotCount = _romClass->romConstantPoolCount - _romClass->ramConstantPoolCount;676/* Walk the hashtable and write CP entries for all hashtable entries with index >= _romClass->romConstantPoolCount */677J9HashTableState hashTableState;678HashTableEntry * entry = (HashTableEntry *) hashTableStartDo(_cpHashTable, &hashTableState);679while (NULL != entry) {680if ((_romClass->romConstantPoolCount + doubleSlotCount) <= entry->cpIndex) {681writeU8(entry->cpType);682683switch (entry->cpType) {684case CFR_CONSTANT_Utf8:685{686J9UTF8 * utf8 = (J9UTF8 *) entry->address;687/* If this is an anonClass, we must build the classData with the original name,688* not the anonClass name. There is only one copy of the className in the ROMClass,689* so replace the matching anonClassName reference with the originalClassName reference690*/691if (_isAnon) {692if (utf8 == _anonClassName) {693utf8 = _originalClassName;694}695}696writeU16(J9UTF8_LENGTH(utf8));697writeData(J9UTF8_LENGTH(utf8), J9UTF8_DATA(utf8));698break;699}700case CFR_CONSTANT_Class:701writeU16(indexForUTF8((J9UTF8 *) entry->address));702break;703case CFR_CONSTANT_Double: /* fall through */704case CFR_CONSTANT_Long:705#ifdef J9VM_ENV_LITTLE_ENDIAN706writeU32(((U_32 *) entry->address)[1]);707writeU32(((U_32 *) entry->address)[0]);708#else /* J9VM_ENV_LITTLE_ENDIAN */709writeU32(((U_32 *) entry->address)[0]);710writeU32(((U_32 *) entry->address)[1]);711#endif /* J9VM_ENV_LITTLE_ENDIAN */712break;713case CFR_CONSTANT_Float: /* fall through */714case CFR_CONSTANT_Integer:715writeU32(((U_32 *) entry->address)[0]);716break;717case CFR_CONSTANT_NameAndType: {718J9ROMNameAndSignature * nas = (J9ROMNameAndSignature *) entry->address;719writeU16(indexForUTF8(J9ROMNAMEANDSIGNATURE_NAME(nas)));720writeU16(indexForUTF8(J9ROMNAMEANDSIGNATURE_SIGNATURE(nas)));721break;722}723case CFR_CONSTANT_InvokeDynamic: {724J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);725U_16 * bsmIndices = (U_16 *) (callSiteData + _romClass->callSiteCount);726J9SRP * srp = (J9SRP *) entry->address;727UDATA index(srp - callSiteData);728U_16 bsmIndex = bsmIndices[index];729J9ROMNameAndSignature * nas = SRP_PTR_GET(srp, J9ROMNameAndSignature *);730731writeU16(bsmIndex);732writeU16(indexForNAS(nas));733break;734}735default:736Trc_BCU_Assert_ShouldNeverHappen();737break;738}739}740entry = (HashTableEntry *) hashTableNextDo(&hashTableState);741}742}743744void745ClassFileWriter::writeInterfaces()746{747J9SRP * interfaceNames = J9ROMCLASS_INTERFACES(_romClass);748UDATA interfaceCount = _romClass->interfaceCount;749#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)750interfaceCount -= _numOfInjectedInterfaces;751#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */752753writeU16(U_16(interfaceCount));754for (UDATA i = 0; i < interfaceCount; i++) {755J9UTF8 * interfaceName = NNSRP_GET(interfaceNames[i], J9UTF8 *);756writeU16(indexForClass(interfaceName));757}758}759760void761ClassFileWriter::writeField(J9ROMFieldShape * fieldShape)762{763J9UTF8 * name = J9ROMFIELDSHAPE_NAME(fieldShape);764J9UTF8 * signature = J9ROMFIELDSHAPE_SIGNATURE(fieldShape);765J9UTF8 * genericSignature = romFieldGenericSignature(fieldShape);766U_32 * annotationsData = getFieldAnnotationsDataFromROMField(fieldShape);767U_32 * typeAnnotationsData = getFieldTypeAnnotationsDataFromROMField(fieldShape);768U_16 attributesCount = 0;769770if (J9FieldFlagConstant & fieldShape->modifiers) {771attributesCount += 1;772}773if (NULL != genericSignature) {774attributesCount += 1;775}776if (NULL != annotationsData) {777attributesCount += 1;778}779if (NULL != typeAnnotationsData) {780attributesCount += 1;781}782783writeU16(U_16(fieldShape->modifiers & CFR_FIELD_ACCESS_MASK));784writeU16(indexForUTF8(name));785writeU16(indexForUTF8(signature));786writeU16(attributesCount);787788if (J9FieldFlagConstant & fieldShape->modifiers) {789U_32 * value = romFieldInitialValueAddress(fieldShape);790U_16 index = 0;791if (J9FieldFlagObject & fieldShape->modifiers) {792index = *value;793} else {794switch (J9FieldTypeMask & fieldShape->modifiers) {795case J9FieldTypeDouble:796index = indexForDouble(value);797break;798case J9FieldTypeLong:799index = indexForLong(value);800break;801case J9FieldTypeFloat:802index = indexForFloat(value);803break;804default:805index = indexForInteger(value);806break;807}808}809writeAttributeHeader((J9UTF8 *) &CONSTANT_VALUE, 2);810writeU16(index);811}812if (NULL != genericSignature) {813writeSignatureAttribute(genericSignature);814}815if (NULL != annotationsData) {816writeAnnotationsAttribute(annotationsData);817}818if (NULL != typeAnnotationsData) {819writeTypeAnnotationsAttribute(typeAnnotationsData);820}821}822823void824ClassFileWriter::writeFields()825{826writeU16(U_16(_romClass->romFieldCount));827828J9ROMFieldWalkState state;829J9ROMFieldShape * fieldShape = romFieldsStartDo(_romClass, &state);830while (NULL != fieldShape) {831writeField(fieldShape);832fieldShape = romFieldsNextDo(&state);833}834}835836void837ClassFileWriter::writeMethod(J9ROMMethod * method)838{839J9UTF8 * name = J9ROMMETHOD_NAME(method);840J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(method);841J9UTF8 * genericSignature = J9_GENERIC_SIGNATURE_FROM_ROM_METHOD(method);842U_32 * defaultAnnotationsData = getDefaultAnnotationDataFromROMMethod(method);843U_32 * parameterAnnotationsData = getParameterAnnotationsDataFromROMMethod(method);844U_32 * typeAnnotationsData = getMethodTypeAnnotationsDataFromROMMethod(method);845U_32 * annotationsData = getMethodAnnotationsDataFromROMMethod(method);846J9MethodParametersData * methodParametersData = getMethodParametersFromROMMethod(method);847848U_16 attributesCount = 0;849850/* native or abstract methods don't have Code attribute */851if (0 == ((J9AccAbstract | J9AccNative) & method->modifiers)) {852attributesCount += 1;853}854if (NULL != genericSignature) {855attributesCount += 1;856}857if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {858J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);859if (0 != exceptionInfo->throwCount) {860attributesCount += 1;861}862}863if (NULL != annotationsData) {864attributesCount += 1;865}866if (NULL != parameterAnnotationsData) {867attributesCount += 1;868}869if (NULL != typeAnnotationsData) {870attributesCount += 1;871}872if (NULL != defaultAnnotationsData) {873attributesCount += 1;874}875if (NULL != methodParametersData) {876attributesCount += 1;877}878879writeU16(U_16(method->modifiers & CFR_METHOD_ACCESS_MASK));880writeU16(indexForUTF8(name));881writeU16(indexForUTF8(signature));882writeU16(attributesCount);883884if (0 == ((J9AccAbstract | J9AccNative) & method->modifiers)) {885writeCodeAttribute(method);886}887if (NULL != genericSignature) {888writeSignatureAttribute(genericSignature);889}890if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {891J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);892if (0 != exceptionInfo->throwCount) {893U_8 * address = (U_8 *) (exceptionInfo + 1);894address += sizeof(J9ExceptionHandler) * exceptionInfo->catchCount;895J9SRP * throwNames = (J9SRP *) address;896897writeAttributeHeader((J9UTF8 *) &EXCEPTIONS, sizeof(U_16) + (sizeof(U_16) * exceptionInfo->throwCount));898writeU16(exceptionInfo->throwCount);899for (U_16 i = 0; i < exceptionInfo->throwCount; i++) {900J9UTF8 * throwName = NNSRP_GET(throwNames[i], J9UTF8 *);901writeU16(indexForClass(throwName));902}903}904}905if (NULL != annotationsData) {906writeAnnotationsAttribute(annotationsData);907}908if (NULL != parameterAnnotationsData) {909writeParameterAnnotationsAttribute(parameterAnnotationsData);910}911if (NULL != defaultAnnotationsData) {912writeAnnotationDefaultAttribute(defaultAnnotationsData);913}914if (NULL != typeAnnotationsData) {915writeTypeAnnotationsAttribute(typeAnnotationsData);916}917918if (NULL != methodParametersData) {919U_8 parameterCount = methodParametersData->parameterCount;920J9MethodParameter * parameters = &methodParametersData->parameters;921writeAttributeHeader((J9UTF8 *) &METHODPARAMETERS, sizeof(U_8) + ((sizeof(U_16)+sizeof(U_16)) * parameterCount));922923writeU8(parameterCount);924for (U_8 i = 0; i < parameterCount; i++) {925U_16 utfIndex = 0;926J9UTF8 * parameterName = SRP_GET(parameters[i].name, J9UTF8 *);927if (NULL != parameterName) {928utfIndex = indexForUTF8(parameterName);929}930writeU16(utfIndex);931writeU16(parameters[i].flags);932}933}934}935936void937ClassFileWriter::writeMethods()938{939writeU16(U_16(_romClass->romMethodCount));940J9ROMMethod * method = J9ROMCLASS_ROMMETHODS(_romClass);941for (U_32 i = 0; i < _romClass->romMethodCount; i++) {942writeMethod(method);943method = nextROMMethod(method);944}945}946947void948ClassFileWriter::writeAttributes()949{950U_16 attributesCount = 0;951J9UTF8 * outerClassName = J9ROMCLASS_OUTERCLASSNAME(_romClass);952J9UTF8 * simpleName = getSimpleNameForROMClass(_javaVM, NULL, _romClass);953J9EnclosingObject * enclosingObject = getEnclosingMethodForROMClass(_javaVM, NULL, _romClass);954J9UTF8 * signature = getGenericSignatureForROMClass(_javaVM, NULL, _romClass);955J9UTF8 * sourceFileName = getSourceFileNameForROMClass(_javaVM, NULL, _romClass);956J9SourceDebugExtension * sourceDebugExtension = getSourceDebugExtensionForROMClass(_javaVM, NULL, _romClass);957U_32 * annotationsData = getClassAnnotationsDataForROMClass(_romClass);958U_32 * typeAnnotationsData = getClassTypeAnnotationsDataForROMClass(_romClass);959#if JAVA_SPEC_VERSION >= 11960J9UTF8 *nestHost = J9ROMCLASS_NESTHOSTNAME(_romClass);961U_16 nestMemberCount = _romClass->nestMemberCount;962#endif /* JAVA_SPEC_VERSION >= 11 */963964if ((0 != _romClass->innerClassCount)965|| (0 != _romClass->enclosedInnerClassCount)966|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)967) {968attributesCount += 1;969}970if (NULL != enclosingObject) {971attributesCount += 1;972}973if (NULL != signature) {974attributesCount += 1;975}976if (NULL != sourceFileName) {977attributesCount += 1;978}979if (NULL != sourceDebugExtension) {980attributesCount += 1;981}982if (NULL != annotationsData) {983attributesCount += 1;984}985if (NULL != typeAnnotationsData) {986attributesCount += 1;987}988if (0 != _romClass->bsmCount) {989attributesCount += 1;990}991if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccRecord)) {992attributesCount += 1;993}994if (J9ROMCLASS_IS_SEALED(_romClass)) {995attributesCount += 1;996}997#if JAVA_SPEC_VERSION >= 11998/* Class can not have both a nest members and member of nest attribute */999if ((0 != _romClass->nestMemberCount) || (NULL != nestHost)) {1000attributesCount += 1;1001}1002#endif /* JAVA_SPEC_VERSION >= 11 */1003writeU16(attributesCount);10041005if ((0 != _romClass->innerClassCount)1006|| (0 != _romClass->enclosedInnerClassCount)1007|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)1008) {1009U_16 innerClassesCount(_romClass->innerClassCount + _romClass->enclosedInnerClassCount);10101011if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {1012/* This is an inner class, so we have one extra inner class attribute to allocate/write */1013innerClassesCount++;1014}10151016/* Calculate and write size of inner class attributes */1017U_32 innerClassesSize = innerClassesCount * 4 * sizeof(U_16);1018innerClassesSize += sizeof(U_16); /* innerClassesCount */1019writeAttributeHeader((J9UTF8 *) &INNER_CLASSES, innerClassesSize);1020writeU16(innerClassesCount);10211022U_16 thisClassCPIndex = indexForClass(J9ROMCLASS_CLASSNAME(_romClass));10231024/* Write inner classes of this class */1025J9SRP * innerClasses = (J9SRP *) J9ROMCLASS_INNERCLASSES(_romClass);1026/* Write inner class entries for inner classes of this class */1027for (UDATA i = 0; i < _romClass->innerClassCount; i++, innerClasses++) {1028J9UTF8 * innerClassName = NNSRP_PTR_GET(innerClasses, J9UTF8 *);10291030writeU16(indexForClass(innerClassName));1031writeU16(thisClassCPIndex);10321033/* NOTE: innerClassAccessFlags and innerNameIndex are not preserved in the ROM class - technically incorrect, but this should only matter to compilers */1034writeU16(0); /* innerNameIndex */1035writeU16(0); /* innerClassAccessFlags */1036}10371038/* Write enclosed inner classes of this class */1039J9SRP * enclosedInnerClasses = (J9SRP *) J9ROMCLASS_ENCLOSEDINNERCLASSES(_romClass);1040/* Write the enclosed inner class entries for inner classes of this class */1041for (UDATA i = 0; i < _romClass->enclosedInnerClassCount; i++, enclosedInnerClasses++) {1042J9UTF8 * enclosedInnerClassName = NNSRP_PTR_GET(enclosedInnerClasses, J9UTF8 *);10431044writeU16(indexForClass(enclosedInnerClassName));1045/* NOTE: outerClassInfoIndex (these inner class are not the declared classes of this class),1046* innerNameIndex and innerClassAccessFlags are not preserved in the ROM class1047* - technically incorrect, but this should only matter to compilers.1048*/1049writeU16(0); /* outerClassInfoIndex */1050writeU16(0); /* innerNameIndex */1051writeU16(0); /* innerClassAccessFlags */1052}10531054if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {1055/* This is an inner class. Write an inner class attribute for itself. */1056writeU16(thisClassCPIndex);1057writeU16((NULL == outerClassName) ? 0 : indexForClass(outerClassName));1058writeU16((NULL == simpleName) ? 0 : indexForUTF8(simpleName));1059writeU16(_romClass->memberAccessFlags);1060}1061}10621063#if JAVA_SPEC_VERSION >= 111064/* A class can only have one of the nest mate attributes */1065if (0 != nestMemberCount) {1066J9SRP *nestMembers = (J9SRP *) J9ROMCLASS_NESTMEMBERS(_romClass);1067U_32 nestMembersAttributeSize = (1 + nestMemberCount) * sizeof(U_16);1068writeAttributeHeader((J9UTF8 *) &NEST_MEMBERS, nestMembersAttributeSize);1069writeU16(nestMemberCount);10701071for (U_16 i = 0; i < nestMemberCount; i++) {1072J9UTF8 * nestMemberName = NNSRP_PTR_GET(nestMembers, J9UTF8 *);1073writeU16(indexForClass(nestMemberName));1074nestMembers += 1;1075}1076} else if (NULL != nestHost) {1077writeAttributeHeader((J9UTF8 *) &NEST_HOST, 2);1078writeU16(indexForClass(nestHost));1079}1080#endif /* JAVA_SPEC_VERSION >= 11 */10811082if (NULL != enclosingObject) {1083J9ROMNameAndSignature * nas = J9ENCLOSINGOBJECT_NAMEANDSIGNATURE(enclosingObject);10841085writeAttributeHeader((J9UTF8 *) &ENCLOSING_METHOD, 4);1086writeU16(U_16(enclosingObject->classRefCPIndex));1087writeU16(NULL == nas ? 0 : indexForNAS(nas));1088}10891090if (NULL != signature) {1091writeSignatureAttribute(signature);1092}10931094if (NULL != sourceFileName) {1095writeAttributeHeader((J9UTF8 *) &SOURCE_FILE, 2);1096writeU16(indexForUTF8(sourceFileName));1097}10981099if (NULL != sourceDebugExtension) {1100writeAttributeHeader((J9UTF8 *) &SOURCE_DEBUG_EXTENSION, sourceDebugExtension->size);1101writeData(sourceDebugExtension->size, sourceDebugExtension + 1);1102}11031104if (NULL != annotationsData) {1105writeAnnotationsAttribute(annotationsData);1106}11071108if (NULL != typeAnnotationsData) {1109writeTypeAnnotationsAttribute(typeAnnotationsData);1110}11111112if (0 != _romClass->bsmCount) {1113U_32 bsmCount = _romClass->bsmCount;1114U_32 callSiteCount = _romClass->callSiteCount;1115J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);1116U_16 * bsmIndices = (U_16 *) (callSiteData + callSiteCount);1117U_16 * bsmCursor = bsmIndices + callSiteCount;11181119writeAttributeHeader((J9UTF8 *) &BOOTSTRAP_METHODS, _bsmAttributeLength);1120writeU16(U_16(bsmCount)); /* num_bootstrap_methods */1121for (U_32 i = 0; i < bsmCount; i++) {1122writeU16(*bsmCursor); /* bootstrap_method_ref */1123bsmCursor += 1;1124U_16 argCount = *bsmCursor;1125writeU16(argCount); /* num_bootstrap_arguments */1126bsmCursor += 1;1127for (U_16 j = 0; j < argCount; j++) {1128U_16 cpIndex = *bsmCursor;11291130if (cpIndex >= _romClass->ramConstantPoolCount) {1131/* Adjust double slot entry index */1132cpIndex = cpIndex + (cpIndex - _romClass->ramConstantPoolCount);1133}1134writeU16(cpIndex);1135bsmCursor += 1;1136}1137}1138}11391140/* record attribute */1141if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccRecord)) {1142writeRecordAttribute();1143}11441145/* write PermittedSubclasses attribute */1146if (J9ROMCLASS_IS_SEALED(_romClass)) {1147U_32 *permittedSubclassesCountPtr = getNumberOfPermittedSubclassesPtr(_romClass);1148writeAttributeHeader((J9UTF8 *) &PERMITTED_SUBCLASSES, sizeof(U_16) + (*permittedSubclassesCountPtr * sizeof(U_16)));11491150writeU16(*permittedSubclassesCountPtr);11511152for (U_32 i = 0; i < *permittedSubclassesCountPtr; i++) {1153J9UTF8* permittedSubclassNameUtf8 = permittedSubclassesNameAtIndex(permittedSubclassesCountPtr, i);11541155/* CONSTANT_Class_info index should be written. Find class entry that references the subclass name in constant pool. */1156J9HashTableState hashTableState;1157HashTableEntry * entry = (HashTableEntry *) hashTableStartDo(_cpHashTable, &hashTableState);1158while (NULL != entry) {1159if (CFR_CONSTANT_Class == entry->cpType) {1160J9UTF8* classNameCandidate = (J9UTF8*)entry->address;1161if (J9UTF8_EQUALS(classNameCandidate, permittedSubclassNameUtf8)) {1162writeU16(entry->cpIndex);1163break;1164}1165}1166entry = (HashTableEntry *) hashTableNextDo(&hashTableState);1167}1168}1169}1170}11711172void ClassFileWriter::writeRecordAttribute()1173{1174/* Write header - size calculation will be written specially at the end.1175* Write zero as a placeholder for length.1176*/1177writeU16(indexForUTF8((J9UTF8 *) &RECORD));1178U_8* recordAttributeLengthAddr = _classFileCursor;1179writeU32(0);1180U_8* startLengthCalculationAddr = _classFileCursor;11811182/* write number of record components (components_count).1183* Stored as U32 in the ROM class, U16 in class file.1184*/1185U_32 numberOfRecords = getNumberOfRecordComponents(_romClass);1186writeU16(numberOfRecords);11871188/* write record components */1189J9ROMRecordComponentShape* recordComponent = recordComponentStartDo(_romClass);1190for (U_32 i = 0; i < numberOfRecords; i++) {1191J9UTF8 * name = J9ROMRECORDCOMPONENTSHAPE_NAME(recordComponent);1192J9UTF8 * signature = J9ROMRECORDCOMPONENTSHAPE_SIGNATURE(recordComponent);1193J9UTF8 * genericSignature = getRecordComponentGenericSignature(recordComponent);1194U_32 * annotationsData = getRecordComponentAnnotationData(recordComponent);1195U_32 * typeAnnotationsData = getRecordComponentTypeAnnotationData(recordComponent);1196U_16 attributesCount = 0;11971198writeU16(indexForUTF8(name));1199writeU16(indexForUTF8(signature));12001201if (NULL != genericSignature) {1202attributesCount += 1;1203}1204if (NULL != annotationsData) {1205attributesCount += 1;1206}1207if (NULL != typeAnnotationsData) {1208attributesCount += 1;1209}1210writeU16(attributesCount);12111212if (NULL != genericSignature) {1213writeSignatureAttribute(genericSignature);1214}1215if (NULL != annotationsData) {1216writeAnnotationsAttribute(annotationsData);1217}1218if (NULL != typeAnnotationsData) {1219writeTypeAnnotationsAttribute(typeAnnotationsData);1220}12211222recordComponent = recordComponentNextDo(recordComponent);1223}12241225/* calculate and write record attribute length */1226U_8* endLengthCalculationAddr = _classFileCursor;1227writeU32At(U_32(endLengthCalculationAddr - startLengthCalculationAddr), recordAttributeLengthAddr);1228}12291230U_81231ClassFileWriter::computeArgsCount(U_16 methodRefIndex)1232{1233J9ROMConstantPoolItem *constantPool = (J9ROMConstantPoolItem*) (_romClass + 1);1234J9ROMMethodRef *methodRef = (J9ROMMethodRef *)(constantPool + methodRefIndex);1235J9ROMNameAndSignature *nas = J9ROMMETHODREF_NAMEANDSIGNATURE(methodRef);1236J9UTF8 *sigUTF8 = J9ROMNAMEANDSIGNATURE_SIGNATURE(nas);1237U_16 count = J9UTF8_LENGTH(sigUTF8);1238U_8 *sig = J9UTF8_DATA(sigUTF8);1239U_8 argsCount = 1; /* interface method always has 'this' parameter */1240bool done = false;12411242for (U_16 index = 1; (index < count) && (!done); index++) { /* 1 to skip the opening '(' */1243switch (sig[index]) {1244case ')':1245done = true;1246break;1247case '[':1248/* skip all '['s */1249while ((index < count) && ('[' == sig[index])) {1250index += 1;1251}1252if ('L' != sig[index]) {1253break;1254}1255/* fall through */1256case 'L':1257index += 1;1258while ((index < count) && (';' != sig[index])) {1259index += 1;1260}1261break;1262case 'D':1263/* fall through */1264case 'J':1265argsCount += 1; /* double occupies 2 slots */1266break;1267default:1268/* any other primitive type */1269break;1270}1271if (!done) {1272argsCount += 1;1273}1274}12751276return argsCount;1277}12781279void1280ClassFileWriter::writeCodeAttribute(J9ROMMethod * method)1281{1282U_32 codeLength(J9_BYTECODE_SIZE_FROM_ROM_METHOD(method));1283U_8 * code(J9_BYTECODE_START_FROM_ROM_METHOD(method));1284U_16 attributesCount = 0;12851286writeU16(indexForUTF8((J9UTF8 *) &CODE));1287U_8 * attributeLenAddr = _classFileCursor;1288writeU32(0);12891290U_8 * start = _classFileCursor;1291writeU16(method->maxStack);1292writeU16(method->tempCount + method->argCount);1293writeU32(codeLength);12941295U_8 * bytecode = _classFileCursor;1296writeData(codeLength, code);1297rewriteBytecode(method, codeLength, bytecode);12981299if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {1300J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);1301J9ExceptionHandler * handlers = (J9ExceptionHandler *) (exceptionInfo + 1);13021303writeU16(exceptionInfo->catchCount);1304for (U_16 i = 0; i < exceptionInfo->catchCount; i++) {1305writeU16(U_16(handlers[i].startPC));1306writeU16(U_16(handlers[i].endPC));1307writeU16(U_16(handlers[i].handlerPC));1308writeU16(U_16(handlers[i].exceptionClassIndex));1309}1310} else {1311writeU16(0);1312}13131314U_8 * attributesCountAddr = _classFileCursor;1315writeU16(0);13161317if (J9ROMMETHOD_HAS_STACK_MAP(method)) {1318writeStackMapTableAttribute(method);1319attributesCount += 1;1320}13211322if (J9ROMMETHOD_HAS_CODE_TYPE_ANNOTATIONS(getExtendedModifiersDataFromROMMethod(method))) {1323U_32 * typeAnnotationsData = getCodeTypeAnnotationsDataFromROMMethod(method);1324writeTypeAnnotationsAttribute(typeAnnotationsData);1325attributesCount += 1;1326}13271328J9MethodDebugInfo* debugInfo = getMethodDebugInfoFromROMMethod(method);1329if (NULL != debugInfo) {1330U_16 lineNumberCount(getLineNumberCount(debugInfo));13311332if (0 != lineNumberCount) {1333writeAttributeHeader((J9UTF8 *) &LINE_NUMBER_TABLE, sizeof(U_16) + (lineNumberCount * sizeof(U_16) * 2));1334writeU16(lineNumberCount);13351336U_8 * lineNumberTable = getLineNumberTable(debugInfo);13371338J9LineNumber lineNumber;1339/* getNextLineNumberFromTable() expects initial values in lineNumber to be 0 */1340memset(&lineNumber, 0, sizeof(J9LineNumber));13411342for (U_16 i = 0; i < lineNumberCount; i++) {1343if (getNextLineNumberFromTable(&lineNumberTable, &lineNumber)) {1344writeU16(lineNumber.location);1345writeU16(lineNumber.lineNumber);1346} else {1347_buildResult = LineNumberTableDecompressFailed;1348return;1349}1350}1351attributesCount += 1;1352}13531354U_16 varInfoCount(debugInfo->varInfoCount);13551356if (0 != varInfoCount) {1357writeAttributeHeader((J9UTF8 *) &LOCAL_VARIABLE_TABLE, sizeof(U_16) + (sizeof(U_16) * 5 * varInfoCount));1358writeU16(varInfoCount);13591360J9VariableInfoWalkState state;1361J9VariableInfoValues * values = NULL;13621363U_16 varInfoWithSigCount = 0;13641365values = variableInfoStartDo(debugInfo, &state);1366while(NULL != values) {1367writeU16(values->startVisibility);1368writeU16(values->visibilityLength);1369writeU16(indexForUTF8(values->name));1370writeU16(indexForUTF8(values->signature));1371writeU16(values->slotNumber);1372if (NULL != values->genericSignature) {1373varInfoWithSigCount += 1;1374}1375values = variableInfoNextDo(&state);1376}1377attributesCount += 1;13781379if (0 != varInfoWithSigCount) {1380writeAttributeHeader((J9UTF8 *) &LOCAL_VARIABLE_TYPE_TABLE, sizeof(U_16) + (sizeof(U_16) * 5 * varInfoWithSigCount));1381writeU16(varInfoWithSigCount);13821383values = variableInfoStartDo(debugInfo, &state);13841385while(NULL != values) {1386if (NULL != values->genericSignature) {1387writeU16(values->startVisibility);1388writeU16(values->visibilityLength);1389writeU16(indexForUTF8(values->name));1390writeU16(indexForUTF8(values->genericSignature));1391writeU16(values->slotNumber);1392}1393values = variableInfoNextDo(&state);1394}1395attributesCount += 1;1396}1397}1398}13991400writeU16At(attributesCount, attributesCountAddr);14011402U_8 * end = _classFileCursor;1403writeU32At(U_32(end - start), attributeLenAddr);1404}14051406void1407ClassFileWriter::rewriteBytecode(J9ROMMethod * method, U_32 length, U_8 * code)1408{1409/*1410* This is derived from jvmtiGetBytecodes() in jvmtiMethod.c. It avoids CP index renumbering.1411* It should likely be replaced with a call to jvmtiGetBytecodes() once that function is fixed for CP unsplitting.1412*/1413U_32 index = 0;1414while (index < length) {1415U_8 bc = code[index];1416U_32 bytecodeSize = J9JavaInstructionSizeAndBranchActionTable[bc] & 7;14171418if (bytecodeSize == 0) {1419_buildResult = InvalidBytecodeSize;1420return;1421}14221423switch (bc) {1424case JBldc: /* do nothing */1425break;14261427case JBldc2dw: /* Fall-through */1428case JBldc2lw: {1429code[index] = CFR_BC_ldc2_w;1430U_16 cpIndex = *(U_16 *)(code + index + 1);1431U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(_romClass);14321433if (J9CPTYPE_CONSTANT_DYNAMIC != J9_CP_TYPE(cpShapeDescription, cpIndex)) {1434/* Adjust index of double/long CP entry. Not necessary for Constant_Dynamic as1435* its already in the RAM CP while double/long are sorted to the end.1436*/1437cpIndex = cpIndex + (cpIndex - _romClass->ramConstantPoolCount);1438}1439writeU16At(cpIndex, code + index + 1);1440}1441break;14421443case JBnewdup:1444code[index] = JBnew;1445flip16bit(code + index + 1);1446break;14471448case JBinvokehandle:1449case JBinvokehandlegeneric:1450code[index] = CFR_BC_invokevirtual;1451flip16bit(code + index + 1);1452break;14531454case JBinvokedynamic: {1455UDATA i;1456U_16 callSiteIndex = *(U_16 *) (code + index + 1);1457J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);1458U_16 *bsmIndices = (U_16 *)(callSiteData + _romClass->callSiteCount);1459J9ROMNameAndSignature * nas = SRP_PTR_GET(callSiteData + callSiteIndex, J9ROMNameAndSignature *);1460U_16 bsmIndex = bsmIndices[callSiteIndex];14611462/* Scan the data to get the first entry which has same J9ROMNameAndSignature as the 'nas'.1463* See comments in ClassFileWriter::analyzeROMClass() for the explanation.1464*/1465for (i = 0; i < _romClass->callSiteCount; i++) {1466J9ROMNameAndSignature * tempNAS = SRP_PTR_GET(callSiteData + i, J9ROMNameAndSignature *);1467U_16 tempIndex = bsmIndices[i];1468if ((nas == tempNAS) && (bsmIndex == tempIndex)) {1469break;1470}1471}1472writeU16At(indexForInvokeDynamic(callSiteData + i), code + index + 1);1473index += 2; /* Advance past the extra nops */1474break;1475}14761477case JBinvokestaticsplit: {1478U_16 cpIndex = *(U_16 *) (code + index + 1);1479/* treat cpIndex as index into static split table */1480cpIndex = *(U_16 *)(J9ROMCLASS_STATICSPLITMETHODREFINDEXES(_romClass) + cpIndex);1481/* reset bytecode to non-split version */1482*(code + index) = CFR_BC_invokestatic;1483writeU16At(cpIndex, code + index + 1);1484break;1485}14861487case JBinvokespecialsplit: {1488U_16 cpIndex = *(U_16 *) (code + index + 1);1489/* treat cpIndex as index into special split table */1490cpIndex = *(U_16 *)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(_romClass) + cpIndex);1491/* reset bytecode to non-split version */1492*(code + index) = CFR_BC_invokespecial;1493writeU16At(cpIndex, code + index + 1);1494break;1495}14961497case JBiloadw: /* Fall-through */1498case JBlloadw: /* Fall-through */1499case JBfloadw: /* Fall-through */1500case JBdloadw: /* Fall-through */1501case JBaloadw:1502bc = bc - JBiloadw + JBiload;1503readdWide:1504code[index + 0] = CFR_BC_wide;1505{1506U_8 tmp = code[index + 1];1507code[index + 1] = bc;1508#ifdef J9VM_ENV_LITTLE_ENDIAN1509/* code[index + 2] = code[index + 2]; */1510code[index + 3] = tmp;1511#else /* J9VM_ENV_LITTLE_ENDIAN */1512code[index + 3] = code[index + 2];1513code[index + 2] = tmp;1514#endif /* J9VM_ENV_LITTLE_ENDIAN */1515}1516break;15171518case JBistorew: /* Fall-through */1519case JBlstorew: /* Fall-through */1520case JBfstorew: /* Fall-through */1521case JBdstorew: /* Fall-through */1522case JBastorew:1523bc = bc - JBistorew + JBistore;1524goto readdWide;15251526case JBiincw:1527#ifdef J9VM_ENV_LITTLE_ENDIAN1528/* code[index + 4] = code[index + 4]; */1529code[index + 5] = code[index + 3];1530#else /* J9VM_ENV_LITTLE_ENDIAN */1531code[index + 5] = code[index + 4];1532code[index + 4] = code[index + 3];1533#endif /* J9VM_ENV_LITTLE_ENDIAN */1534bc = JBiinc;1535goto readdWide;15361537case JBgenericReturn: /* Fall-through */1538case JBreturnFromConstructor: /* Fall-through */1539case JBreturn0: /* Fall-through */1540case JBreturn1: /* Fall-through */1541case JBreturn2: /* Fall-through */1542case JBreturnB: /* Fall-through */1543case JBreturnC: /* Fall-through */1544case JBreturnS: /* Fall-through */1545case JBreturnZ: /* Fall-through */1546case JBsyncReturn0: /* Fall-through */1547case JBsyncReturn1: /* Fall-through */1548case JBsyncReturn2: {1549J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(method);1550U_8 * sigData = J9UTF8_DATA(signature);1551U_16 sigLength = J9UTF8_LENGTH(signature);15521553switch (sigData[sigLength - 2] == '[' ? ';' : sigData[sigLength - 1]) {1554case 'V':1555bc = CFR_BC_return;1556break;1557case 'J':1558bc = CFR_BC_lreturn;1559break;1560case 'D':1561bc = CFR_BC_dreturn;1562break;1563case 'F':1564bc = CFR_BC_freturn;1565break;1566case ';':1567bc = CFR_BC_areturn;1568break;1569default:1570bc = CFR_BC_ireturn;1571break;1572}1573code[index] = bc;1574break;1575}15761577case JBaload0getfield:1578code[index] = JBaload0;1579break;15801581case JBinvokeinterface2: {1582code[index + 0] = CFR_BC_invokeinterface;1583U_16 cpIndex = *(U_16 *)(code + index + 3);1584writeU16At(cpIndex, code + index + 1);1585code[index + 3] = computeArgsCount(cpIndex);1586code[index + 4] = 0;1587break;1588}15891590case JBlookupswitch: /* Fall-through */1591case JBtableswitch: {1592U_32 tempIndex = index + (4 - (index & 3));1593UDATA numEntries;15941595flip32bit(code + tempIndex);1596tempIndex += sizeof(U_32);15971598I_32 low = *((I_32 *) (code + tempIndex));15991600flip32bit(code + tempIndex);1601tempIndex += sizeof(U_32);16021603if (bc == JBtableswitch) {1604I_32 high = *((I_32 *) (code + tempIndex));16051606flip32bit(code + tempIndex);1607tempIndex += sizeof(U_32);1608numEntries = (UDATA) (high - low + 1);1609} else {1610numEntries = ((UDATA) low) * 2;1611}16121613while (0 != numEntries) {1614flip32bit(code + tempIndex);1615tempIndex += 4;1616numEntries -= 1;1617}16181619bytecodeSize = tempIndex - index;1620break;1621}16221623#ifdef J9VM_ENV_LITTLE_ENDIAN1624case JBgotow:1625flip32bit(code + index + 1);1626break;16271628case JBiinc:1629/* Size is 3 - avoid the default endian flip case */1630break;16311632default:1633/* Any bytecode of size 3 or more which does not have a single word parm first must be added to the switch */1634if (bytecodeSize >= 3) {1635flip16bit(code + index + 1);1636}1637break;1638#endif /* J9VM_ENV_LITTLE_ENDIAN */1639}16401641index += bytecodeSize;1642}1643}16441645void1646ClassFileWriter::writeVerificationTypeInfo(U_16 count, U_8 ** typeInfo)1647{1648U_8 * cursor = *typeInfo;16491650for (U_16 i = 0; i < count; i++) {1651U_8 tag;1652NEXT_U8(tag, cursor);16531654switch(tag) {1655case CFR_STACKMAP_TYPE_BYTE_ARRAY:1656case CFR_STACKMAP_TYPE_BOOL_ARRAY:1657case CFR_STACKMAP_TYPE_CHAR_ARRAY:1658case CFR_STACKMAP_TYPE_DOUBLE_ARRAY:1659case CFR_STACKMAP_TYPE_FLOAT_ARRAY:1660case CFR_STACKMAP_TYPE_INT_ARRAY:1661case CFR_STACKMAP_TYPE_LONG_ARRAY:1662case CFR_STACKMAP_TYPE_SHORT_ARRAY: {1663/* convert primitive array tag to corresponding class index in constant pool */1664U_8 typeInfoTagToPrimitiveArrayCharMap[] = { 'I', 'F', 'D', 'J', 'S', 'B', 'C', 'Z' };1665U_8 primitiveChar = typeInfoTagToPrimitiveArrayCharMap[tag - CFR_STACKMAP_TYPE_INT_ARRAY];1666/* An array cannot have more than 255 dimensions as per VM spec */1667U_8 classUTF8[2 + 255 + 1]; /* represents J9UTF8 for primitive class (size = length + arity + primitiveChar) */1668U_16 arity;16691670NEXT_U16(arity, cursor);1671arity += 1; /* actual arity is one more than stored in stack map table */1672*(U_16 *)classUTF8 = arity + 1; /* store UTF8 length = arity + one char for primitive type */1673memset((void *)(classUTF8 + 2), '[', arity);1674*(classUTF8 + 2 + arity) = primitiveChar;16751676/* There is no need to double-check the primitive type the in the constant pool in the case1677* of boolean arrays because CFR_STACKMAP_TYPE_BYTE_ARRAY is only used for byte arrays and1678* CFR_STACKMAP_TYPE_BOOL_ARRAY is used to represent boolean arrays.1679*/16801681writeU8(CFR_STACKMAP_TYPE_OBJECT);1682writeU16(indexForClass((J9UTF8 *)classUTF8));1683break;1684}16851686case CFR_STACKMAP_TYPE_OBJECT:1687case CFR_STACKMAP_TYPE_NEW_OBJECT: {1688U_16 data;1689NEXT_U16(data, cursor);16901691writeU8(tag);1692writeU16(data);1693break;1694}16951696default:1697writeU8(tag);1698break;1699}1700}17011702*typeInfo = cursor;1703}17041705void1706ClassFileWriter::writeStackMapTableAttribute(J9ROMMethod * romMethod)1707{1708U_16 numEntries = 0;1709U_8 * stackMap = (U_8 *)stackMapFromROMMethod(romMethod);17101711writeU16(indexForUTF8((J9UTF8 *) &STACK_MAP_TABLE));1712U_8 * attributeLenAddr = _classFileCursor;1713writeU32(0);17141715stackMap += sizeof(U_32); /* skip length */17161717U_8 * start = _classFileCursor;17181719NEXT_U16(numEntries, stackMap);1720writeU16(numEntries);17211722for (U_16 i = 0; i < numEntries; i++) {1723U_8 frameType;17241725NEXT_U8(frameType, stackMap);1726writeU8(frameType);17271728if (CFR_STACKMAP_SAME_LOCALS_1_STACK > frameType) { /* 0..63 */1729/* SAME frame - no extra data */1730} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_END > frameType) { /* 64..127 */1731/*1732* SAME_LOCALS_1_STACK {1733* TypeInfo stackItems[1]1734* };1735*/1736writeVerificationTypeInfo(1, &stackMap);1737} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED > frameType) { /* 128..246 */1738/* Reserved frame types - no extra data */1739Trc_BCU_Assert_ShouldNeverHappen();1740} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED == frameType) { /* 247 */1741/*1742* SAME_LOCALS_1_STACK_EXTENDED {1743* U_16 offsetDelta1744* TypeInfo stackItems[1]1745* };1746*/1747U_16 offsetDelta;1748NEXT_U16(offsetDelta, stackMap);1749writeU16(offsetDelta);1750writeVerificationTypeInfo(1, &stackMap);1751} else if (CFR_STACKMAP_SAME_EXTENDED > frameType) { /* 248..250 */1752/*1753* CHOP {1754* U_16 offsetDelta1755* };1756*/1757U_16 offsetDelta;1758NEXT_U16(offsetDelta, stackMap);1759writeU16(offsetDelta);1760} else if (CFR_STACKMAP_SAME_EXTENDED == frameType) { /* 251 */1761/*1762* SAME_EXTENDED {1763* U_16 offsetDelta1764* };1765*/1766U_16 offsetDelta;1767NEXT_U16(offsetDelta, stackMap);1768writeU16(offsetDelta);1769} else if (CFR_STACKMAP_FULL > frameType) { /* 252..254 */1770/*1771* APPEND {1772* U_16 offsetDelta1773* TypeInfo locals[frameType - CFR_STACKMAP_APPEND_BASE]1774* };1775*/1776U_16 offsetDelta;1777NEXT_U16(offsetDelta, stackMap);1778writeU16(offsetDelta);1779writeVerificationTypeInfo(frameType - CFR_STACKMAP_APPEND_BASE, &stackMap);1780} else if (CFR_STACKMAP_FULL == frameType) { /* 255 */1781/*1782* FULL {1783* U_16 offsetDelta1784* U_16 localsCount1785* TypeInfo locals[localsCount]1786* U_16 stackItemsCount1787* TypeInfo stackItems[stackItemsCount]1788* };1789*/1790U_16 offsetDelta;1791/* u2 offset delta */1792NEXT_U16(offsetDelta, stackMap);1793writeU16(offsetDelta);1794/* handle locals */1795/* u2 number of locals */1796U_16 localsCount;1797NEXT_U16(localsCount, stackMap);1798writeU16(localsCount);1799/* verification_type_info locals[number of locals] */1800writeVerificationTypeInfo(localsCount, &stackMap);18011802/* handle stack */1803/* u2 number of stack items */1804U_16 stackItemsCount;1805NEXT_U16(stackItemsCount, stackMap);1806writeU16(stackItemsCount);1807/* verification_type_info stack[number of stack items] */1808writeVerificationTypeInfo(stackItemsCount, &stackMap);1809}1810}18111812writeU32At((U_32)(_classFileCursor - start), attributeLenAddr);1813}18141815void1816ClassFileWriter::writeSignatureAttribute(J9UTF8 * genericSignature)1817{1818writeAttributeHeader((J9UTF8 *) &SIGNATURE, 2);1819writeU16(indexForUTF8(genericSignature));1820}18211822void1823ClassFileWriter::writeAnnotationElement(U_8 **annotationElement)1824{1825U_8 *cursor = *annotationElement;1826U_8 tag;18271828NEXT_U8(tag, cursor);1829writeU8(tag);18301831switch(tag) {1832case 'e': {1833U_16 typeNameIndex, constNameIndex;18341835NEXT_U16(typeNameIndex, cursor);1836writeU16(typeNameIndex);1837NEXT_U16(constNameIndex, cursor);1838writeU16(constNameIndex);1839}1840break;1841case 'c': {1842U_16 classInfoIndex;18431844NEXT_U16(classInfoIndex, cursor);1845writeU16(classInfoIndex);1846}1847break;1848case '@':1849writeAnnotation(&cursor);1850break;1851case '[': {1852U_16 numValues;18531854NEXT_U16(numValues, cursor);1855writeU16(numValues);1856for (U_16 i = 0; i < numValues; i++) {1857writeAnnotationElement(&cursor);1858}1859}1860break;1861default: {1862U_16 constValueIndex;18631864NEXT_U16(constValueIndex, cursor);1865if (('D' == tag) || ('J' == tag)) {1866/* Adjust index of double/long CP entry */1867constValueIndex = constValueIndex + (constValueIndex - _romClass->ramConstantPoolCount);1868}1869writeU16(constValueIndex);1870}1871break;1872}1873*annotationElement = cursor;1874}18751876void1877ClassFileWriter::writeAnnotation(U_8 **annotation)1878{1879U_8 *cursor = *annotation;1880U_16 typeIndex;18811882NEXT_U16(typeIndex, cursor);1883writeU16(typeIndex);18841885U_16 numElements;1886NEXT_U16(numElements, cursor);1887writeU16(numElements);18881889for (U_16 i = 0; i < numElements; i++) {1890U_16 elementNameIndex;18911892NEXT_U16(elementNameIndex, cursor);1893writeU16(elementNameIndex);1894writeAnnotationElement(&cursor);1895}1896*annotation = cursor;1897}18981899void1900ClassFileWriter::writeAnnotationsAttribute(U_32 * annotationsData)1901{1902writeAttributeHeader((J9UTF8 *) &RUNTIME_VISIBLE_ANNOTATIONS, *annotationsData);1903if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {1904U_8 *data = (U_8 *)(annotationsData + 1);1905U_16 numAnnotations;19061907NEXT_U16(numAnnotations, data);1908writeU16(numAnnotations);19091910for (U_16 i = 0; i < numAnnotations; i++) {1911writeAnnotation(&data);1912}1913} else {1914writeData(*annotationsData, annotationsData + 1);1915}1916}19171918void1919ClassFileWriter::writeParameterAnnotationsAttribute(U_32 *parameterAnnotationsData)1920{1921writeAttributeHeader((J9UTF8 *) &RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, *parameterAnnotationsData);1922if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {1923U_8 *data = (U_8 *)(parameterAnnotationsData + 1);1924U_8 numParameters;19251926NEXT_U8(numParameters, data);1927writeU8(numParameters);19281929for (U_8 i = 0; i < numParameters; i++) {1930U_16 numAnnotations;19311932NEXT_U16(numAnnotations, data);1933writeU16(numAnnotations);19341935for (U_16 i = 0; i < numAnnotations; i++) {1936writeAnnotation(&data);1937}1938}1939} else {1940writeData(*parameterAnnotationsData, parameterAnnotationsData + 1);1941}1942}19431944void1945ClassFileWriter::writeTypeAnnotationsAttribute(U_32 *typeAnnotationsData)1946{1947writeAttributeHeader((J9UTF8 *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, *typeAnnotationsData);1948if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {1949U_8 *data = (U_8 *)(typeAnnotationsData + 1);1950U_16 numAnnotations;1951NEXT_U16(numAnnotations, data);1952writeU16(numAnnotations);1953if (CFR_TARGET_TYPE_ErrorInAttribute == *data) {1954writeData(*typeAnnotationsData, typeAnnotationsData + 1); /* dump out the raw bytes */1955} else {1956for (U_16 i = 0; i < numAnnotations; i++) {1957U_8 u8Data = 0;1958U_16 u16Data = 0;19591960U_8 targetType;1961NEXT_U8(targetType, data);1962writeU8(targetType);1963switch (targetType) {1964case CFR_TARGET_TYPE_TypeParameterGenericClass:1965case CFR_TARGET_TYPE_TypeParameterGenericMethod:1966NEXT_U8(u8Data, data); /* typeParameterIndex */1967writeU8(u8Data);1968break;19691970case CFR_TARGET_TYPE_TypeInExtends:1971NEXT_U16(u16Data, data);1972writeU16(u16Data); /* supertypeIndex */1973break;19741975case CFR_TARGET_TYPE_TypeInBoundOfGenericClass:1976case CFR_TARGET_TYPE_TypeInBoundOfGenericMethod:1977NEXT_U8(u8Data, data);1978writeU8(u8Data); /* typeParameterIndex */1979NEXT_U8(u8Data, data);1980writeU8(u8Data); /* boundIndex */1981break;19821983case CFR_TARGET_TYPE_TypeInFieldDecl:1984case CFR_TARGET_TYPE_ReturnType:1985case CFR_TARGET_TYPE_ReceiverType: /* empty_target */1986break;19871988case CFR_TARGET_TYPE_TypeInFormalParam:1989NEXT_U8(u8Data, data);1990writeU8(u8Data); /* formalParameterIndex */1991break;19921993case CFR_TARGET_TYPE_TypeInThrows:1994NEXT_U16(u16Data, data);1995writeU16(u16Data); /* throwsTypeIndex */1996break;19971998case CFR_TARGET_TYPE_TypeInLocalVar:1999case CFR_TARGET_TYPE_TypeInResourceVar: {2000U_16 tableLength = 0;2001NEXT_U16(tableLength, data);2002writeU16(tableLength);2003for (U_32 ti=0; ti < tableLength; ++ti) {2004NEXT_U16(u16Data, data);2005writeU16(u16Data); /* startPC */2006NEXT_U16(u16Data, data);2007writeU16(u16Data); /* length */2008NEXT_U16(u16Data, data);2009writeU16(u16Data); /* index */2010}2011}2012break;2013case CFR_TARGET_TYPE_TypeInExceptionParam:2014NEXT_U16(u16Data, data);2015writeU16(u16Data); /* exceptiontableIndex */2016break;20172018case CFR_TARGET_TYPE_TypeInInstanceof:2019case CFR_TARGET_TYPE_TypeInNew:2020case CFR_TARGET_TYPE_TypeInMethodrefNew:2021case CFR_TARGET_TYPE_TypeInMethodrefIdentifier:2022NEXT_U16(u16Data, data);2023writeU16(u16Data); /* offset */2024break;20252026case CFR_TARGET_TYPE_TypeInCast:2027case CFR_TARGET_TYPE_TypeForGenericConstructorInNew:2028case CFR_TARGET_TYPE_TypeForGenericMethodInvocation:2029case CFR_TARGET_TYPE_TypeForGenericConstructorInMethodRef:2030case CFR_TARGET_TYPE_TypeForGenericMethodInvocationInMethodRef:2031NEXT_U16(u16Data, data);2032writeU16(u16Data); /* offset */2033NEXT_U8(u8Data, data);2034writeU8(u8Data); /* typeArgumentIndex */2035break;20362037default:2038break;2039}2040U_8 pathLength;2041NEXT_U8(pathLength, data);2042writeU8(pathLength);2043for (U_8 pathIndex = 0; pathIndex < pathLength; ++pathIndex) {2044NEXT_U8(u8Data, data);2045writeU8(u8Data); /* typePathKind */2046NEXT_U8(u8Data, data);2047writeU8(u8Data); /* typeArgumentIndex */2048}2049writeAnnotation(&data);2050}2051}2052} else {2053writeData(*typeAnnotationsData, typeAnnotationsData + 1);2054}2055}205620572058void2059ClassFileWriter::writeAnnotationDefaultAttribute(U_32 *annotationsDefaultData)2060{2061writeAttributeHeader((J9UTF8 *) &ANNOTATION_DEFAULT, *annotationsDefaultData);2062if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {2063U_8 *cursor = (U_8 *)(annotationsDefaultData+1);20642065writeAnnotationElement(&cursor);2066} else {2067writeData(*annotationsDefaultData, annotationsDefaultData + 1);2068}2069}20702071void2072ClassFileWriter::writeAttributeHeader(J9UTF8 * name, U_32 length)2073{2074writeU16(indexForUTF8(name));2075writeU32(length);2076}207720782079