Path: blob/master/runtime/bcutil/ROMClassCreationContext.hpp
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*******************************************************************************/2122#ifndef ROMCLASSCREATIONCONTEXT_HPP_23#define ROMCLASSCREATIONCONTEXT_HPP_2425#include "bcutil_api.h"26#include "j9.h"27#include "j9comp.h"28#include "j9port.h"29#include "jvminit.h"30#include "rommeth.h"31#include "SCQueryFunctions.h"32#include "ut_j9bcu.h"3334#include "AllocationStrategy.hpp"35#include "BuildResult.hpp"36#include "ROMClassCreationPhase.hpp"3738class ROMClassCreationContext39{40public:41ROMClassCreationContext(J9PortLibrary *portLibrary, U_8 *classFileBytes, UDATA classFileSize, UDATA bctFlags, UDATA bcuFlags, J9ROMClass *romClass) :42_portLibrary(portLibrary),43_javaVM(NULL),44_classFileBytes(classFileBytes),45_classFileSize(classFileSize),46_bctFlags(bctFlags),47_bcuFlags(bcuFlags),48_findClassFlags(0),49_allocationStrategy(NULL),50_romClass(romClass),51_clazz(NULL),52_className(NULL),53_classNameLength(0),54_hostPackageName(NULL),55_hostPackageLength(0),56_intermediateClassData(NULL),57_intermediateClassDataLength(0),58_classLoader(NULL),59_cpIndex(0),60_loadLocation(0),61_dynamicLoadStats(NULL),62_sharedStringInternTable(NULL),63_classFileBytesReplaced(false),64_retransformAllowed(false),65_interningEnabled(false),66_verboseROMClass(false),67_verboseLastBufferSizeExceeded(0),68_verboseOutOfMemoryCount(0),69_verboseCurrentPhase(ROMClassCreation),70_buildResult(OK),71_forceDebugDataInLine(false),72_doDebugCompare(false),73_existingRomMethod(NULL),74_reusingIntermediateClassData(false),75_creatingIntermediateROMClass(false),76_patchMap(NULL)77{78}7980ROMClassCreationContext(J9PortLibrary *portLibrary, U_8 *classFileBytes, UDATA classFileSize, UDATA bctFlags, UDATA bcuFlags, UDATA findClassFlags, AllocationStrategy *allocationStrategy) :81_portLibrary(portLibrary),82_javaVM(NULL),83_classFileBytes(classFileBytes),84_classFileSize(classFileSize),85_bctFlags(bctFlags),86_bcuFlags(bcuFlags),87_findClassFlags(findClassFlags),88_allocationStrategy(allocationStrategy),89_romClass(NULL),90_clazz(NULL),91_className(NULL),92_classNameLength(0),93_hostPackageName(NULL),94_hostPackageLength(0),95_intermediateClassData(NULL),96_intermediateClassDataLength(0),97_classLoader(NULL),98_cpIndex(0),99_loadLocation(0),100_dynamicLoadStats(NULL),101_sharedStringInternTable(NULL),102_classFileBytesReplaced(false),103_retransformAllowed(false),104_interningEnabled(false),105_verboseROMClass(false),106_verboseLastBufferSizeExceeded(0),107_verboseOutOfMemoryCount(0),108_verboseCurrentPhase(ROMClassCreation),109_buildResult(OK),110_forceDebugDataInLine(false),111_doDebugCompare(false),112_existingRomMethod(NULL),113_reusingIntermediateClassData(false),114_creatingIntermediateROMClass(false),115_patchMap(NULL)116{117}118119ROMClassCreationContext(120J9PortLibrary *portLibrary, J9JavaVM *javaVM, U_8 *classFileBytes, UDATA classFileSize, UDATA bctFlags, UDATA bcuFlags, UDATA findClassFlags, AllocationStrategy *allocationStrategy,121U_8 *className, UDATA classNameLength, U_8 *hostPackageName, UDATA hostPackageLength, U_8 *intermediateClassData, U_32 intermediateClassDataLength, J9ROMClass *romClass, J9Class *clazz,122J9ClassLoader *classLoader, bool classFileBytesReplaced, bool creatingIntermediateROMClass, J9TranslationLocalBuffer *localBuffer) :123_portLibrary(portLibrary),124_javaVM(javaVM),125_classFileBytes(classFileBytes),126_classFileSize(classFileSize),127_bctFlags(bctFlags),128_bcuFlags(bcuFlags),129_findClassFlags(findClassFlags),130_allocationStrategy(allocationStrategy),131_romClass(romClass),132_clazz(clazz),133_className(className),134_classNameLength(classNameLength),135_hostPackageName(hostPackageName),136_hostPackageLength(hostPackageLength),137_intermediateClassData(intermediateClassData),138_intermediateClassDataLength(intermediateClassDataLength),139_classLoader(classLoader),140_cpIndex(0),141_loadLocation(0),142_dynamicLoadStats(NULL),143_sharedStringInternTable(NULL),144_classFileBytesReplaced(classFileBytesReplaced),145#if defined(J9VM_OPT_JVMTI)146_retransformAllowed((NULL != javaVM) && (0 != (javaVM->requiredDebugAttributes & J9VM_DEBUG_ATTRIBUTE_ALLOW_RETRANSFORM))),147#else148_retransformAllowed(false),149#endif150_interningEnabled(false),151_verboseROMClass((NULL != javaVM) && (0 != (javaVM->verboseLevel & VERBOSE_ROMCLASS))),152_verboseLastBufferSizeExceeded(0),153_verboseOutOfMemoryCount(0),154_verboseCurrentPhase(ROMClassCreation),155_buildResult(OK),156_forceDebugDataInLine(false),157_doDebugCompare(false),158_existingRomMethod(NULL),159_reusingIntermediateClassData(false),160_creatingIntermediateROMClass(creatingIntermediateROMClass),161_patchMap(NULL)162{163if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers)) {164/* localBuffer should not be NULL */165Trc_BCU_Assert_True(NULL != localBuffer);166_cpIndex = localBuffer->entryIndex;167_loadLocation = localBuffer->loadLocationType;168_patchMap = localBuffer->patchMap;169_sharedStringInternTable = _javaVM->sharedInvariantInternTable;170_interningEnabled = J9_ARE_ALL_BITS_SET(_bcuFlags, BCU_ENABLE_INVARIANT_INTERNING) && J9_ARE_NO_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_ANON);171if (0 != (bcuFlags & BCU_VERBOSE)) {172_dynamicLoadStats = _javaVM->dynamicLoadBuffers->dynamicLoadStats;173}174}175if (_verboseROMClass) {176memset(&_verboseRecords[0], 0, sizeof(_verboseRecords));177}178}179180bool isCreatingIntermediateROMClass() const { return _creatingIntermediateROMClass; }181U_8 *classFileBytes() const { return _classFileBytes; }182UDATA classFileSize() const { return _classFileSize; }183UDATA findClassFlags() const {return _findClassFlags; }184U_8* className() const {return _className; }185UDATA classNameLength() const {return _classNameLength; }186U_8* hostPackageName() const {return _hostPackageName; }187UDATA hostPackageLength() const {return _hostPackageLength; }188U_32 bctFlags() const { return (U_32) _bctFlags; } /* Only use this for j9bcutil_readClassFileBytes */189AllocationStrategy *allocationStrategy() const { return _allocationStrategy; }190bool classFileBytesReplaced() const { return _classFileBytesReplaced; }191#if defined(J9VM_OPT_JVMTI)192bool isRetransformAllowed() const { return _retransformAllowed; }193#else194bool isRetransformAllowed() const { return false; }195#endif196bool isVerbose() const { return _verboseROMClass; }197J9ClassLoader *classLoader() const { return _classLoader; }198J9JavaVM *javaVM() const { return _javaVM; }199J9VMThread *currentVMThread() const { return _javaVM->internalVMFunctions->currentVMThread(_javaVM); }200J9PortLibrary *portLibrary() const { return _portLibrary; }201UDATA cpIndex() const { return _cpIndex; }202UDATA loadLocation() const {return _loadLocation; }203J9ClassPatchMap *patchMap() const { return _patchMap; }204J9SharedInvariantInternTable *sharedStringInternTable() const { return _sharedStringInternTable; }205206U_8 *intermediateClassData() const { return _intermediateClassData; }207U_32 intermediateClassDataLength() const { return _intermediateClassDataLength; }208209U_8 *getIntermediateClassDataFromPreviousROMClass() const { return (NULL != _clazz) ? WSRP_GET(_clazz->romClass->intermediateClassData, U_8*) : NULL; }210U_32 getIntermediateClassDataLengthFromPreviousROMClass() const { return (NULL != _clazz) ? _clazz->romClass->intermediateClassDataLength : 0; }211212void setReusingIntermediateClassData() { _reusingIntermediateClassData = true; }213bool isReusingIntermediateClassData() const { return _reusingIntermediateClassData; }214bool isInterningEnabled() const { return _interningEnabled; }215bool isRedefining() const { return J9_FINDCLASS_FLAG_REDEFINING == (_findClassFlags & J9_FINDCLASS_FLAG_REDEFINING); }216bool isRetransforming() const { return J9_FINDCLASS_FLAG_RETRANSFORMING == (_findClassFlags & J9_FINDCLASS_FLAG_RETRANSFORMING); }217bool isClassLoaderSharedClassesEnabled() const { return NULL != _classLoader && (_classLoader->flags & J9CLASSLOADER_SHARED_CLASSES_ENABLED); }218bool isSharedClassesEnabled() const { return (NULL != _javaVM) && (NULL != _javaVM->sharedClassConfig); }219bool isSharedClassesCacheFull() const { return (NULL != _javaVM) && j9shr_Query_IsCacheFull(_javaVM); }220221/* Note: Always call isSharedClassesEnabled() before using isSharedClassesBCIEnabled() */222bool isSharedClassesBCIEnabled() const { return (0 != _javaVM->sharedClassConfig->isBCIEnabled(_javaVM)); }223224/* Determine if this is the bootclassloader. Allow null JavaVM to get bootstrap behaviour for cfdump */225bool isBootstrapLoader() { return (NULL == _javaVM) || (_classLoader == _javaVM->systemClassLoader); }226227/* Only the bootstrap classloader can load classes in the "java" package. */228bool shouldCheckPackageName() { return (NULL != _javaVM) && (_classLoader != _javaVM->systemClassLoader); }229bool shouldCompareROMClassForEquality() const { return NULL != _romClass; }230bool shouldPreserveLineNumbers() const { return 0 == (_bctFlags & (BCT_StripDebugLines|BCT_StripDebugAttributes)); }231bool shouldPreserveLocalVariablesInfo() const { return 0 == (_bctFlags & (BCT_StripDebugVars|BCT_StripDebugAttributes)); }232bool shouldPreserveSourceFileName() const { return 0 == (_bctFlags & (BCT_StripDebugSource|BCT_StripDebugAttributes)); }233bool shouldPreserveSourceDebugExtension() const { return 0 == (_bctFlags & (BCT_StripSourceDebugExtension|BCT_StripDebugAttributes)); }234bool isClassUnsafe() const { return J9_FINDCLASS_FLAG_UNSAFE == (_findClassFlags & J9_FINDCLASS_FLAG_UNSAFE); }235bool isClassAnon() const { return J9_FINDCLASS_FLAG_ANON == (_findClassFlags & J9_FINDCLASS_FLAG_ANON); }236bool alwaysSplitBytecodes() const { return J9_ARE_ANY_BITS_SET(_bctFlags, BCT_AlwaysSplitBytecodes); }237bool isClassHidden() const { return J9_FINDCLASS_FLAG_HIDDEN == (_findClassFlags & J9_FINDCLASS_FLAG_HIDDEN);}238bool isHiddenClassOptNestmateSet() const { return J9_FINDCLASS_FLAG_CLASS_OPTION_NESTMATE == (_findClassFlags & J9_FINDCLASS_FLAG_CLASS_OPTION_NESTMATE);}239bool isHiddenClassOptStrongSet() const { return J9_FINDCLASS_FLAG_CLASS_OPTION_STRONG == (_findClassFlags & J9_FINDCLASS_FLAG_CLASS_OPTION_STRONG);}240bool isDoNotShareClassFlagSet() const {return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_DO_NOT_SHARE);}241242bool isClassUnmodifiable() const {243bool unmodifiable = false;244if (NULL != _javaVM) {245if ((J2SE_VERSION(_javaVM) >= J2SE_V11)246&& (isClassAnon() || isClassHidden())247) {248unmodifiable = true;249} else if (NULL == J9VMJAVALANGOBJECT_OR_NULL(_javaVM)) {250/* Object is currently only allowed to be redefined in fast HCR */251if (areExtensionsEnabled(_javaVM)) {252unmodifiable = true;253}254}255}256return unmodifiable;257}258259bool isIntermediateClassDataShareable() const {260bool shareable = false;261U_8 *intermediateData = getIntermediateClassDataFromPreviousROMClass();262U_32 intermediateDataLength = getIntermediateClassDataLengthFromPreviousROMClass();263if ((NULL != intermediateData)264&& (TRUE == j9shr_Query_IsAddressInReadWriteCache(_javaVM, intermediateData, intermediateDataLength))265/* J9ROMClass pointing to intermediateData using SRP, so share only when intermediateData is in readWriteCache */266) {267shareable = true;268}269return shareable;270}271272bool shouldStripIntermediateClassData() const {273return (isSharedClassesEnabled()274&& isSharedClassesBCIEnabled()275&& !classFileBytesReplaced()276&& !isRetransformAllowed());277}278279bool canRomMethodsBeSorted(UDATA threshold) const {280if (!isRedefining() && !isRetransforming()) {281if ((NULL != _javaVM) && (_javaVM->romMethodSortThreshold <= threshold)) {282return true;283}284}285return false;286}287288bool isROMClassShareable() const {289/*290* Any of the following conditions prevent the sharing of a ROMClass:291* - J9_FINDCLASS_FLAG_DO_NOT_SHARE is set for this class292* - classloader is not shared classes enabled293* - cache is full294* - the class is unsafe and isUnsafeClassSharingEnabled returns false (see the function isUnsafeClassShareable() for more details)295* - the class is a hidden class and isHiddenClassSharingEnabled() returns false (Java 15 and up, see the function isHiddenClassSharingEnabled() for more details)296* - shared cache is BCI enabled and class is modified by BCI agent297* - shared cache is BCI enabled and ROMClass being store is intermediate ROMClass298* - the class is loaded from a patch path299*/300if (isSharedClassesEnabled()301&& !isDoNotShareClassFlagSet()302&& isClassLoaderSharedClassesEnabled()303&& (!isClassUnsafe() || isUnsafeClassSharingEnabled())304&& (!isClassHidden() || isHiddenClassSharingEnabled())305&& !(isSharedClassesBCIEnabled()306&& (classFileBytesReplaced() || isCreatingIntermediateROMClass()))307&& (LOAD_LOCATION_PATCH_PATH != loadLocation())308) {309return true;310} else {311return false;312}313}314315bool isUnsafeClassSharingEnabled() const {316/*317* The command line option -XX:[+/-]ShareUnsafeClasses, combined with -XX:[+/-]ShareAnonymousClasses will have 4 different behaviours:318* 1. -XX:+ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will share all unsafe classes319* 2. -XX:+ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will only share anonymous classes and not other unsafe classes320* 3. -XX:-ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will only share unsafe classes that are not anonymous321* 4. -XX:-ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will share neither.322* The current default behavior is the 1st option.323*/324bool isEnabled = false;325326bool isAnonDefineClassSharingEnabled = J9_ARE_ALL_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_SHAREANONYMOUSCLASSES);327bool isUnsafeDefineClassSharingEnabled = J9_ARE_ALL_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_SHAREUNSAFECLASSES);328329if (isClassAnon()) {330/*331* Since the class loader shared classes enable flag is set properly and it is checked in the isClassLoaderSharedClassesEnabled() function332* before this function is called in isROMClassShareable(). Thus, we can just assert isAnonDefineClassSharingEnabled is true.333*/334Trc_BCU_Assert_True(isAnonDefineClassSharingEnabled);335isEnabled = true;336} else if (isUnsafeDefineClassSharingEnabled) {337/* Classes loaded by Unsafe.defineClass */338isEnabled = true;339}340return isEnabled;341}342343bool isHiddenClassSharingEnabled() const {344/*345* In java 15 and up, hidden class is introduced to replace unsafe anonymous class, so use existing CML options346* -XX:[+/-]ShareAnonymousClasses to control the class sharing behaviour of hidden classes.347* The command line option -XX:[+/-]ShareUnsafeClasses, combined with -XX:[+/-]ShareAnonymousClasses will have 4 different behaviours:348* 1. -XX:+ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will share all hidden classes349* 2. -XX:+ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will only share hidden classes and not other unsafe classes350* 3. -XX:-ShareAnonymousClasses -XX:+ShareUnsafeClasses, this will only share unsafe classes that are not hidden classes351* 4. -XX:-ShareAnonymousClasses -XX:-ShareUnsafeClasses, this will share neither.352* The current default behavior is the 1st option.353*/354return J9_ARE_ALL_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_SHAREANONYMOUSCLASSES);355}356357/*358* Returns true if any of the following conditions is true359* - BCT_IntermediateDataIsClassfile is set360* - class is being redefined and the previous class as J9AccClassIntermediateDataIsClassfile set.361*/362bool isIntermediateDataAClassfile() const {363if (J9_ARE_ALL_BITS_SET(_bctFlags, BCT_IntermediateDataIsClassfile)) {364return true;365} else if ((NULL != _clazz) && (J9ROMCLASS_IS_INTERMEDIATE_DATA_A_CLASSFILE(_clazz->romClass))) {366return true;367} else {368return false;369}370}371372bool canPossiblyStoreDebugInfoOutOfLine() const {373if (!shouldPreserveLineNumbers() && !shouldPreserveLocalVariablesInfo()) {374/*375* Can't store debug information out of line, if none of it is going to be stored at all376*/377return false;378}379if (isROMClassShareable() && !isSharedClassesCacheFull() ) {380/*381* shared classes is enabled, and there is the potential to store the class in the cache.382*/383return true;384}385if (_allocationStrategy && _allocationStrategy->canStoreDebugDataOutOfLine()) {386/*387* the allocation strategy permits out of line debug information storage.388*/389return true;390}391/*392* no reason to store debug information separately393*/394return false;395}396397398J9ROMClass *romClass() const { return _romClass; }399400BuildResult checkClassName(U_8 *className, U_16 classNameLength)401{402if (!isRedefining() && !isRetransforming()) {403if (NULL != _className) {404U_16 classNameLenToCompare0 = (U_16)_classNameLength;405U_16 classNameLenToCompare1 = classNameLength;406BOOLEAN misMatch = FALSE;407if (isClassHidden()) {408if (isROMClassShareable()) {409U_8* lambdaClass0 = (U_8*)getLastDollarSignOfLambdaClassName((const char*)_className, _classNameLength);410U_8* lambdaClass1 = (U_8*)getLastDollarSignOfLambdaClassName((const char*)className, classNameLength);411if ((NULL != lambdaClass0)412&& (NULL != lambdaClass1)413) {414/**415* Lambda class has class name: HostClassName$$Lambda$<IndexNumber>/0x0000000000000000.416* Do not need to compare the IndexNumber as it can be different from run to run.417*/418classNameLenToCompare0 = (U_16)(lambdaClass0 - _className + 1);419classNameLenToCompare1 = (U_16)(lambdaClass1 - className + 1);420} else if ((NULL == lambdaClass0) && (NULL == lambdaClass1)) {421/* for hidden class className has ROM address appended at the end, _className does not have that */422classNameLenToCompare1 = (U_16)_classNameLength;423} else {424misMatch = TRUE;425}426} else {427/* for hidden class className has ROM address appended at the end, _className does not have that */428classNameLenToCompare1 = (U_16)_classNameLength;429}430}431if (misMatch432|| !J9UTF8_DATA_EQUALS(_className, classNameLenToCompare0, className, classNameLenToCompare1)433) {434#define J9WRONGNAME " (wrong name: "435PORT_ACCESS_FROM_PORT(_portLibrary);436UDATA errorStringSize = _classNameLength + sizeof(J9WRONGNAME) + 1 + classNameLength;437U_8 *errorUTF = (U_8 *) j9mem_allocate_memory(errorStringSize, J9MEM_CATEGORY_CLASSES);438if (NULL != errorUTF) {439U_8 *current = errorUTF;440441memcpy(current, className, classNameLength);442current += classNameLength;443memcpy(current, J9WRONGNAME, sizeof(J9WRONGNAME) - 1);444current += sizeof(J9WRONGNAME) - 1;445memcpy(current, _className, _classNameLength);446current += _classNameLength;447*current++ = (U_8) ')';448*current = (U_8) '\0';449}450recordCFRError(errorUTF);451return ClassNameMismatch;452#undef J9WRONGNAME453}454} else if (shouldCheckPackageName() /* classname is null */455&& (classNameLength >= 5)456&& (0 == memcmp(className, "java/", 5))457&& !isClassAnon()458) {459/*460* Non-bootstrap classloaders may not load nto the "java" package.461* if classname is not null, the JCL or JNI has already checked it462*/463return IllegalPackageName;464}465466}467return OK;468}469470/**471* Report an invalid annotation error against a particular member (field or method).472* This will attempt to construct and set an error message based on the supplied473* NLS key. Regardless, an appropriate BuildResult value will be returned.474*475* @param className UTF8 data representing the class containing the member476* @param classNameLength length of UTF8 data representing the class containing the member477* @param memberName UTF8 data representing the member with the annotation478* @param memberNameLength length of UTF8 data representing the member with the annotation479* @param module_name the module portion of the NLS key480* @param message_num the message portion of the NLS key481* @return the BuildResult value482*/483BuildResult484reportInvalidAnnotation(U_8 *className, U_16 classNameLength, U_8 *memberName, U_16 memberNameLength, U_32 module_name, U_32 message_num)485{486const char* nlsMessage = NULL;487PORT_ACCESS_FROM_PORT(_portLibrary);488489/* Call direct through the port library to circumvent the macro,490* which assumes that the key is a single parameter.491*/492nlsMessage = OMRPORT_FROM_J9PORT(PORTLIB)->nls_lookup_message(OMRPORT_FROM_J9PORT(PORTLIB), J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, module_name, message_num, NULL);493if(NULL != nlsMessage) {494UDATA messageLength = j9str_printf(PORTLIB, NULL, 0, nlsMessage, memberNameLength, memberName, classNameLength, className);495U_8* message = (U_8*)j9mem_allocate_memory(messageLength, OMRMEM_CATEGORY_VM);496if(NULL != message) {497j9str_printf(PORTLIB, (char*)message, messageLength, nlsMessage, memberNameLength, memberName, classNameLength, className);498recordCFRError(message);499}500}501return InvalidAnnotation;502}503504505void recordLoadStart()506{507Trc_BCU_buildRomClass_Entry(_classNameLength, _className);508if (NULL != _dynamicLoadStats) {509PORT_ACCESS_FROM_PORT(_portLibrary);510_dynamicLoadStats->sunSize = _classFileSize;511_dynamicLoadStats->loadStartTime = j9time_usec_clock();512}513}514515void recordParseClassFileStart()516{517Trc_BCU_buildRomClass_ParseClassFileStart(_classNameLength, _className, _classLoader);518}519520void recordParseClassFileEnd()521{522Trc_BCU_buildRomClass_ParseClassFileEnd(_classNameLength, _className, _classFileSize, _classLoader);523524}525void recordTranslationStart()526{527Trc_BCU_buildRomClass_TranslateClassFileStart(_classNameLength, _className, _classLoader);528if (NULL != _dynamicLoadStats) {529PORT_ACCESS_FROM_PORT(_portLibrary);530_dynamicLoadStats->loadEndTime = _dynamicLoadStats->translateStartTime = j9time_usec_clock();531}532}533534void recordTranslationEnd()535{536J9ROMClass *romClass = this->romClass();537Trc_BCU_buildRomClass_TranslateClassFileEnd(J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)), J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)), romClass->romSize, _classLoader);538if (NULL != _dynamicLoadStats) {539PORT_ACCESS_FROM_PORT(_portLibrary);540_dynamicLoadStats->romSize = romClass->romSize;541_dynamicLoadStats->translateEndTime = j9time_usec_clock();542}543}544545void recordROMClass(J9ROMClass *romClass)546{547_romClass = romClass;548}549550void recordCFRError(U_8 *cfrError)551{552if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers)) {553_javaVM->dynamicLoadBuffers->classFileError = cfrError;554}555}556557void freeClassFileBuffer(U_8 *buffer)558{559PORT_ACCESS_FROM_PORT(_portLibrary);560/* It is possible that through the use of recordCFRError that an internally allocated buffer has been let loose561* into _javaVM->dynamicLoadBuffers->classFileError, if the internal buffer that is free'd matches the one in562* _javaVM->dynamicLoadBuffers->classFileError, then it must be set to NULL to avoid a double free in563* j9bcutil_freeTranslationBuffers()*/564if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers) && (buffer == _javaVM->dynamicLoadBuffers->classFileError)) {565_javaVM->dynamicLoadBuffers->classFileError = NULL;566}567j9mem_free_memory(buffer);568}569570void recordLoadEnd(BuildResult result)571{572Trc_BCU_buildRomClass_Exit(result);573_buildResult = result;574}575576void recordPhaseStart(ROMClassCreationPhase phase)577{578if (_verboseROMClass) {579PORT_ACCESS_FROM_PORT(_portLibrary);580_verboseRecords[phase].lastStartTime = j9time_usec_clock();581_verboseRecords[phase].parentPhase = _verboseCurrentPhase;582_verboseCurrentPhase = phase;583}584}585586void recordPhaseEnd(ROMClassCreationPhase phase, BuildResult buildResult)587{588if (_verboseROMClass) {589PORT_ACCESS_FROM_PORT(_portLibrary);590_verboseRecords[phase].accumulatedTime += j9time_usec_clock() - _verboseRecords[phase].lastStartTime;591_verboseRecords[phase].buildResult = buildResult;592_verboseCurrentPhase = _verboseRecords[phase].parentPhase;593}594}595596void recordOutOfMemory(UDATA bufferSize)597{598if (_verboseROMClass) {599_verboseLastBufferSizeExceeded = bufferSize;600_verboseOutOfMemoryCount++;601for (ROMClassCreationPhase phase = ROMClassCreation; phase != ROMClassCreationPhaseCount; ++phase) {602_verboseRecords[phase].failureTime = _verboseRecords[phase].accumulatedTime;603}604}605}606607void reportStatistics(J9TranslationLocalBuffer *localBuffer)608{609if (NULL != _dynamicLoadStats) {610if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers) && (NULL != _javaVM->dynamicLoadBuffers->reportStatisticsFunction)) {611_javaVM->dynamicLoadBuffers->reportStatisticsFunction(_javaVM, classLoader(), romClass(), localBuffer);612}613memset(&_dynamicLoadStats->nameLength, 0, sizeof(J9DynamicLoadStats) - sizeof(UDATA) - sizeof(U_8 *));614}615if (_verboseROMClass) {616reportVerboseStatistics();617}618}619620void forceDebugDataInLine()621{622_forceDebugDataInLine = true;623}624625bool shouldWriteDebugDataInline()626{627if (_doDebugCompare) {628return romMethodDebugDataIsInline();629} else {630return _forceDebugDataInLine;631}632}633634void startDebugCompare()635{636_doDebugCompare = true;637}638639void endDebugCompare()640{641_doDebugCompare = false;642}643644/*Methods that find an existing romMethod at offset in _romClass, and then query the method*/645U_32 romMethodModifiers()646{647J9ROMMethod * romMethod = romMethodGetCachedMethod();648if (NULL != romMethod) {649return romMethod->modifiers;650} else {651return 0;652}653}654655bool romMethodHasDebugData()656{657return (0 != (romMethodModifiers() & J9AccMethodHasDebugInfo));658}659660bool romMethodHasLineNumberCountCompressed()661{662bool retval = false;663J9ROMMethod * romMethod = romMethodGetCachedMethod();664if (NULL != romMethod) {665J9MethodDebugInfo * debuginfo = getMethodDebugInfoFromROMMethod(romMethod);666if (NULL != debuginfo) {667retval = (0x0 == (debuginfo->lineNumberCount & 0x1));668}669}670return retval;671}672673U_32 romMethodCompressedLineNumbersLength()674{675U_32 retval = 0;676J9ROMMethod * romMethod = romMethodGetCachedMethod();677if (NULL != romMethod) {678J9MethodDebugInfo * debuginfo = getMethodDebugInfoFromROMMethod(romMethod);679if (NULL != debuginfo) {680if (0x1 == (debuginfo->lineNumberCount & 0x1)) {681/*lineNumbersInfoCompressedSize is the U_32 following debuginfo in memory*/682retval = *(U_32 *)(debuginfo+1);683} else {684/*lineNumbersInfoCompressedSize is stored encoded in the lineNumberCount value*/685retval = ((debuginfo->lineNumberCount & 0xffff0000) >> 16);686}687}/*else there is no debug data*/688}689return retval;690}691692void * romMethodLineNumbersDataStart()693{694J9ROMMethod * romMethod = romMethodGetCachedMethod();695if (NULL != romMethod) {696return (void *)getMethodDebugInfoFromROMMethod(romMethod);697} else {698return NULL;699}700}701702bool romMethodDebugDataIsInline()703{704bool retval = true;705J9ROMMethod * romMethod = romMethodGetCachedMethod();706/* romMethodHasDebugData() is called to ensure methodDebugInfoFromROMMethod()707* will return a valid address to inspect.708*/709if ((NULL != romMethod) && (true == romMethodHasDebugData())) {710/* methodDebugInfoFromROMMethod() is called instead of getMethodDebugInfoFromROMMethod()711* because getMethodDebugInfoFromROMMethod() will follow the srp to 'out of line' debug712* data (and cause problems checking "1 ==(debugInfo->srpToVarInfo & 1)")713*/714J9MethodDebugInfo* debugInfo = methodDebugInfoFromROMMethod(romMethod);715retval = (1 ==(debugInfo->srpToVarInfo & 1));716}717return retval;718}719720void romMethodCacheCurrentRomMethod(IDATA offset)721{722_existingRomMethod = romMethodFromOffset(offset);723}724725J9ROMMethod * romMethodGetCachedMethod()726{727return _existingRomMethod;728}729730void * romMethodVariableDataStart()731{732void * retval = NULL;733J9ROMMethod * romMethod = romMethodGetCachedMethod();734if (NULL != romMethod) {735J9MethodDebugInfo* debugInfo = getMethodDebugInfoFromROMMethod(romMethod);736if (NULL != debugInfo) {737retval = (void *)getVariableTableForMethodDebugInfo(debugInfo);738}739}740return retval;741}742743/*Methods that query _romClass*/744U_32 romClassOptionalFlags()745{746if (NULL != _romClass) {747return _romClass->optionalFlags;748} else {749return 0;750}751}752753bool romClassHasSourceDebugExtension()754{755return (0 != (romClassOptionalFlags() & J9_ROMCLASS_OPTINFO_SOURCE_DEBUG_EXTENSION));756}757758bool romClassHasSourceFileName()759{760return (0 != (romClassOptionalFlags() & J9_ROMCLASS_OPTINFO_SOURCE_FILE_NAME));761}762763private:764void reportVerboseStatistics();765void verbosePrintPhase(ROMClassCreationPhase phase, bool *printedPhases, UDATA indent);766const char *buildResultString(BuildResult result);767768struct VerboseRecord769{770UDATA lastStartTime; /* last time this phase started - temporary */771UDATA accumulatedTime; /* total time spent in this phase */772UDATA failureTime; /* total time wasted in this phase due to later failure */773BuildResult buildResult; /* last build result from this phase */774ROMClassCreationPhase parentPhase; /* phase in which this phase was last nested */775};776777J9PortLibrary *_portLibrary;778J9JavaVM * _javaVM;779U_8 * _classFileBytes;780UDATA _classFileSize;781UDATA _bctFlags;782UDATA _bcuFlags;783UDATA _findClassFlags;784AllocationStrategy *_allocationStrategy;785J9ROMClass *_romClass;786J9Class *_clazz;787U_8 *_className;788UDATA _classNameLength;789U_8* _hostPackageName;790UDATA _hostPackageLength;791U_8 *_intermediateClassData;792U_32 _intermediateClassDataLength;793J9ClassLoader *_classLoader;794UDATA _cpIndex;795UDATA _loadLocation;796J9DynamicLoadStats *_dynamicLoadStats;797J9SharedInvariantInternTable *_sharedStringInternTable;798bool _classFileBytesReplaced;799bool _retransformAllowed;800bool _interningEnabled;801bool _verboseROMClass;802UDATA _verboseLastBufferSizeExceeded;803UDATA _verboseOutOfMemoryCount;804ROMClassCreationPhase _verboseCurrentPhase;805BuildResult _buildResult;806VerboseRecord _verboseRecords[ROMClassCreationPhaseCount];807bool _forceDebugDataInLine;808bool _doDebugCompare;809J9ROMMethod * _existingRomMethod;810bool _reusingIntermediateClassData;811bool _creatingIntermediateROMClass;812J9ClassPatchMap *_patchMap;813814J9ROMMethod * romMethodFromOffset(IDATA offset);815};816817#endif /* ROMCLASSCREATIONCONTEXT_HPP_ */818819820