Skip to content

Commit b391468

Browse files
committed
wip Stable and unique Lambda and LambdaForm class names
1 parent d776a4a commit b391468

18 files changed

Lines changed: 186 additions & 193 deletions

runtime/bcutil/ComparingCursor.cpp

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -428,29 +428,10 @@ ComparingCursor::shouldCheckForEquality(DataType dataType, U_32 u32Value)
428428
}
429429

430430
switch (dataType) {
431-
case SRP_TO_UTF8_CLASS_NAME:
432-
#if JAVA_SPEC_VERSION < 21
433-
if (_context->isLambdaClass() && _romClassIsShared) {
434-
/*
435-
* If the class is a lambda class, don't compare the class names because lambda
436-
* classes might have different index numbers from run to run.
437-
*/
438-
return false;
439-
}
440-
#endif /* JAVA_SPEC_VERSION < 21 */
441-
break;
431+
case SRP_TO_UTF8_CLASS_NAME: /* fall through */
442432
case BYTECODE: /* fall through */
443433
case GENERIC: /* fall through */
444434
case CLASS_FILE_SIZE: /* fall through */
445-
#if JAVA_SPEC_VERSION < 21
446-
if ((CLASS_FILE_SIZE == dataType)
447-
&& _context->isLambdaClass()
448-
&& _romClassIsShared
449-
) {
450-
/* If comparing a lambda class from the shared cache, class file size comparison is already done in ROMClassBuilder::compareROMClassForEquality(). */
451-
return false;
452-
}
453-
#endif /* JAVA_SPEC_VERSION < 21 */
454435
case SRP_TO_DEBUG_DATA: /* fall through */
455436
case SRP_TO_GENERIC: /* fall through */
456437
case SRP_TO_UTF8: /* fall through */

runtime/bcutil/ROMClassBuilder.cpp

Lines changed: 9 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -277,16 +277,6 @@ ROMClassBuilder::handleAnonClassName(J9CfrClassFile *classfile, ROMClassCreation
277277
PORT_ACCESS_FROM_PORT(_portLibrary);
278278

279279
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
280-
/*
281-
* Prevent generated LambdaForm classes from MethodHandles to be stored to the shared cache.
282-
* When there are a large number of such classes in the shared cache, they trigger a lot of class comparisons.
283-
* Performance can be much worse (compared to shared cache turned off).
284-
*/
285-
if (isLambdaFormClassName(originalStringBytes, originalStringLength, NULL/*deterministicPrefixLength*/)) {
286-
context->addFindClassFlags(J9_FINDCLASS_FLAG_DO_NOT_SHARE);
287-
context->addFindClassFlags(J9_FINDCLASS_FLAG_LAMBDAFORM);
288-
}
289-
290280
#if JAVA_SPEC_VERSION >= 15
291281
/* InjectedInvoker is a hidden class without the strong attribute set. It
292282
* is created by MethodHandleImpl.makeInjectedInvoker on the OpenJDK side.
@@ -417,22 +407,6 @@ ROMClassBuilder::handleAnonClassName(J9CfrClassFile *classfile, ROMClassCreation
417407
j9str_printf(PORTLIB, buf, ROM_ADDRESS_LENGTH + 1, ROM_ADDRESS_FORMAT, 0);
418408
memcpy(constantPool[newUtfCPEntry].bytes + newHostPackageLength + originalStringLength + 1, buf, ROM_ADDRESS_LENGTH + 1);
419409

420-
/* Mark if the class is a Lambda class. */
421-
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
422-
if (!context->isLambdaFormClass()
423-
&& isLambdaClassName(reinterpret_cast<const char *>(_anonClassNameBuffer),
424-
newAnonClassNameLength - 1, NULL/*deterministicPrefixLength*/)
425-
) {
426-
context->addFindClassFlags(J9_FINDCLASS_FLAG_LAMBDA);
427-
}
428-
#else /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
429-
if (isLambdaClassName(reinterpret_cast<const char *>(_anonClassNameBuffer),
430-
newAnonClassNameLength - 1, NULL/*deterministicPrefixLength*/)
431-
) {
432-
context->addFindClassFlags(J9_FINDCLASS_FLAG_LAMBDA);
433-
}
434-
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
435-
436410
/* search constantpool for all other identical classRefs. We have not actually
437411
* tested this scenario as javac will not output more than one classRef or utfRef of the
438412
* same kind.
@@ -590,18 +564,6 @@ ROMClassBuilder::prepareAndLaydown( BufferManager *bufferManager, ClassFileParse
590564
getSizeInfo(context, &romClassWriter, &srpOffsetTable, &countDebugDataOutOfLine, &sizeInformation);
591565

592566
U_32 romSize = 0;
593-
#if JAVA_SPEC_VERSION < 21
594-
U_32 sizeToCompareForLambda = 0;
595-
if (context->isLambdaClass()) {
596-
/*
597-
* romSize calculated from getSizeInfo() does not involve StringInternManager. It is only accurate for string intern disabled classes.
598-
* Lambda classes in java 15 and up are strong hidden classes (defined with Option.STONG), which has the same lifecycle as its
599-
* defining class loader. It is string intern enabled. So pass classFileSize instead of romSize to sizeToCompareForLambda.
600-
*/
601-
sizeToCompareForLambda = classFileOracle.getClassFileSize();
602-
}
603-
#endif /* JAVA_SPEC_VERSION < 21 */
604-
605567
if (context->shouldCompareROMClassForEquality()) {
606568
ROMClassVerbosePhase v(context, CompareHashtableROMClass);
607569

@@ -624,9 +586,6 @@ ROMClassBuilder::prepareAndLaydown( BufferManager *bufferManager, ClassFileParse
624586
modifiers,
625587
extraModifiers,
626588
optionalFlags,
627-
#if JAVA_SPEC_VERSION < 21
628-
sizeToCompareForLambda,
629-
#endif /* JAVA_SPEC_VERSION < 21 */
630589
context)
631590
) {
632591
return OK;
@@ -720,9 +679,6 @@ ROMClassBuilder::prepareAndLaydown( BufferManager *bufferManager, ClassFileParse
720679
modifiers,
721680
extraModifiers,
722681
optionalFlags,
723-
#if JAVA_SPEC_VERSION < 21
724-
sizeToCompareForLambda,
725-
#endif /* JAVA_SPEC_VERSION < 21 */
726682
context)
727683

728684
) {
@@ -1479,55 +1435,19 @@ ROMClassBuilder::compareROMClassForEquality(
14791435
U_32 modifiers,
14801436
U_32 extraModifiers,
14811437
U_32 optionalFlags,
1482-
#if JAVA_SPEC_VERSION < 21
1483-
U_32 sizeToCompareForLambda,
1484-
#endif /* JAVA_SPEC_VERSION < 21 */
14851438
ROMClassCreationContext *context)
14861439
{
14871440
bool ret = false;
1441+
ComparingCursor compareCursor(_javaVM, srpOffsetTable, srpKeyProducer, classFileOracle, romClass, romClassIsShared, context);
1442+
romClassWriter->writeROMClass(&compareCursor,
1443+
&compareCursor,
1444+
&compareCursor,
1445+
NULL,
1446+
NULL,
1447+
0, modifiers, extraModifiers, optionalFlags,
1448+
ROMClassWriter::WRITE);
14881449

1489-
#if JAVA_SPEC_VERSION < 21
1490-
if (context->isLambdaClass()) {
1491-
/*
1492-
* Lambda class names are in the format of HostClassName$$Lambda$<IndexNumber>/<zeroed out ROM_ADDRESS>.
1493-
* When we reach this check, the host class names will be the same for both the classes because
1494-
* of the earlier hash-key check. So, the only difference in the size will be the difference
1495-
* between the number of digits of the index number. The same lambda class might have a
1496-
* different index number from run to run and when the number of digits of the index number
1497-
* increases by 1, classFileSize also increases by 1. The indexNumber is the counter for the number of
1498-
* lambda classes defined so far. It is an int in the JCL side. So the it cannot vary more than max
1499-
* integer vs 0, which is maxVariance (9 bytes). This check is different than the romSize check because
1500-
* when the number of digits of the index number increases by 1, classFileSize also increases by 1 but
1501-
* romSize increases by 2.
1502-
*/
1503-
int maxVariance = 9;
1504-
int variance = abs(static_cast<int>((sizeToCompareForLambda - reinterpret_cast<J9ROMClass *>(romClass)->classFileSize)));
1505-
if (variance <= maxVariance) {
1506-
ComparingCursor compareCursor(_javaVM, srpOffsetTable, srpKeyProducer, classFileOracle, romClass, romClassIsShared, context);
1507-
romClassWriter->writeROMClass(&compareCursor,
1508-
&compareCursor,
1509-
&compareCursor,
1510-
NULL,
1511-
NULL,
1512-
0, modifiers, extraModifiers, optionalFlags,
1513-
ROMClassWriter::WRITE);
1514-
1515-
ret = compareCursor.isEqual();
1516-
}
1517-
} else
1518-
#endif /* JAVA_SPEC_VERSION < 21 */
1519-
{
1520-
ComparingCursor compareCursor(_javaVM, srpOffsetTable, srpKeyProducer, classFileOracle, romClass, romClassIsShared, context);
1521-
romClassWriter->writeROMClass(&compareCursor,
1522-
&compareCursor,
1523-
&compareCursor,
1524-
NULL,
1525-
NULL,
1526-
0, modifiers, extraModifiers, optionalFlags,
1527-
ROMClassWriter::WRITE);
1528-
1529-
ret = compareCursor.isEqual();
1530-
}
1450+
ret = compareCursor.isEqual();
15311451
J9UTF8* name = J9ROMCLASS_CLASSNAME((J9ROMClass *)romClass);
15321452
Trc_BCU_compareROMClassForEquality_event(ret, J9UTF8_LENGTH(name), J9UTF8_DATA(name));
15331453
return ret;

runtime/bcutil/ROMClassBuilder.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,6 @@ class ROMClassBuilder
169169
U_32 modifiers,
170170
U_32 extraModifiers,
171171
U_32 optionalFlags,
172-
#if JAVA_SPEC_VERSION < 21
173-
U_32 sizeToCompareForLambda,
174-
#endif /* JAVA_SPEC_VERSION < 21 */
175172
ROMClassCreationContext *context);
176173

177174
SharedCacheRangeInfo getSharedCacheSRPRangeInfo(void *address);

runtime/bcutil/ROMClassCreationContext.hpp

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,6 @@ class ROMClassCreationContext
240240
bool isHiddenClassOptNestmateSet() const { return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_CLASS_OPTION_NESTMATE); }
241241
bool isHiddenClassOptStrongSet() const { return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_CLASS_OPTION_STRONG); }
242242
bool isDoNotShareClassFlagSet() const {return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_DO_NOT_SHARE);}
243-
bool isLambdaClass() const { return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_LAMBDA); }
244-
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
245-
bool isLambdaFormClass() const { return J9_ARE_ALL_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_LAMBDAFORM); }
246-
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
247243

248244
bool isClassUnmodifiable() const {
249245
bool unmodifiable = false;
@@ -406,33 +402,11 @@ class ROMClassCreationContext
406402
if (NULL != _className) {
407403
U_16 classNameLenToCompare0 = static_cast<U_16>(_classNameLength);
408404
U_16 classNameLenToCompare1 = classNameLength;
409-
BOOLEAN misMatch = FALSE;
410405
if (isClassHidden()) {
411406
/* For hidden classes, className has the ROM address appended, _className does not. */
412407
classNameLenToCompare1 = static_cast<U_16>(_classNameLength);
413-
#if JAVA_SPEC_VERSION < 21
414-
if (isROMClassShareable()) {
415-
/*
416-
* Before JDK21, Lambda class names are in the format:
417-
* HostClassName$$Lambda$<IndexNumber>/<zeroed out ROM_ADDRESS>
418-
* Do not compare the IndexNumber as it can be different from run to run.
419-
*/
420-
U_8 *lambdaClass0 = reinterpret_cast<U_8 *>(getLastDollarSignOfLambdaClassName(
421-
reinterpret_cast<const char *>(_className), _classNameLength));
422-
U_8 *lambdaClass1 = reinterpret_cast<U_8 *>(getLastDollarSignOfLambdaClassName(
423-
reinterpret_cast<const char *>(className), classNameLength));
424-
if ((NULL != lambdaClass0) && (NULL != lambdaClass1)) {
425-
classNameLenToCompare0 = static_cast<U_16>(lambdaClass0 - _className + 1);
426-
classNameLenToCompare1 = static_cast<U_16>(lambdaClass1 - className + 1);
427-
} else if ((NULL == lambdaClass0) != (NULL == lambdaClass1)) {
428-
misMatch = TRUE;
429-
}
430-
}
431-
#endif /* JAVA_SPEC_VERSION < 21 */
432408
}
433-
if (misMatch
434-
|| !J9UTF8_DATA_EQUALS(_className, classNameLenToCompare0, className, classNameLenToCompare1)
435-
) {
409+
if (!J9UTF8_DATA_EQUALS(_className, classNameLenToCompare0, className, classNameLenToCompare1)) {
436410
#define J9WRONGNAME " (wrong name: "
437411
PORT_ACCESS_FROM_PORT(_portLibrary);
438412
UDATA errorStringSize = _classNameLength + sizeof(J9WRONGNAME) + 1 + classNameLength;

runtime/jcl/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ target_link_libraries(jclse
9292
j9vm_interface
9393
j9vm_gc_includes
9494

95+
j9shrcommon
96+
j9shrutil
97+
j9zip
9598
omrsig
9699
j9hookable
97100
j9zlib

runtime/jcl/common/java_lang_invoke_MethodHandleNatives.cpp

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@
3232
#include "j9vmconstantpool.h"
3333
#include "ObjectAccessBarrierAPI.hpp"
3434
#include "objhelp.h"
35+
#include "SCAbstractAPI.h"
3536

3637
#include <string.h>
3738
#include <assert.h>
3839

40+
#undef UT_MODULE_LOADED
41+
#undef UT_MODULE_UNLOADED
42+
#include "CacheMap.hpp"
3943
#include "VMHelpers.hpp"
4044

4145
extern "C" {
@@ -945,6 +949,118 @@ Java_java_lang_invoke_MethodHandleNatives_expand(JNIEnv *env, jclass clazz, jobj
945949
vmFuncs->internalExitVMToJNI(currentThread);
946950
}
947951

952+
/**
953+
* Find a Lambda or customized LambdaForm class in the SCC.
954+
* Requires non-null input arguments.
955+
* If found, returns a pointer to a RAMClass of the SCC-cached class, otherwise nullptr.
956+
*
957+
* Throws OutOfMemoryError if lookup key memory allocation fails.
958+
*/
959+
jobject
960+
findLambdaOrLambdaFormInSCC(JNIEnv *env, jclass clazz, jstring classnameObject, jclass lookupClass, UDATA options)
961+
{
962+
jobject result = nullptr;
963+
964+
#if defined(J9VM_OPT_SHARED_CLASSES)
965+
J9VMThread *currentThread = reinterpret_cast<J9VMThread*>(env);
966+
J9JavaVM *vm = currentThread->javaVM;
967+
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
968+
PORT_ACCESS_FROM_JAVAVM(vm);
969+
vmFuncs->internalEnterVMFromJNI(currentThread);
970+
Trc_JCL_java_lang_invoke_MethodHandleNatives_findLambdaOrLambdaFormInSCC_Entry(env, classnameObject, lookupClass, options);
971+
972+
#if defined(J9VM_ENV_DATA64)
973+
#define J9_ROM_ADDRESS_SUFFIX "/0x0000000000000000"
974+
#else /* defined(J9VM_ENV_DATA64) */
975+
#define J9_ROM_ADDRESS_SUFFIX "/0x00000000"
976+
#endif /* defined(J9VM_ENV_DATA64) */
977+
j9object_t classname = J9_JNI_UNWRAP_REFERENCE(classnameObject);
978+
IDATA classnameLength = vmFuncs->getStringUTF8Length(currentThread, classname);
979+
UDATA romAddressSuffixLength = LITERAL_STRLEN(J9_ROM_ADDRESS_SUFFIX);
980+
UDATA lookupKeyLength = classnameLength + romAddressSuffixLength + 1; /* +1 for null terminator. */
981+
char *lookupKey = static_cast<char *>(j9mem_allocate_memory(lookupKeyLength, OMRMEM_CATEGORY_VM));
982+
983+
if (nullptr == lookupKey) {
984+
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
985+
} else {
986+
vmFuncs->copyStringToUTF8Helper(currentThread, classname, J9_STR_NONE, 0, classnameLength, reinterpret_cast<U_8 *>(lookupKey), classnameLength);
987+
memcpy(lookupKey + classnameLength, J9_ROM_ADDRESS_SUFFIX, romAddressSuffixLength);
988+
lookupKey[lookupKeyLength - 1] = '\0';
989+
990+
SCAbstractAPI *sharedapi = static_cast<SCAbstractAPI *>(vm->sharedClassConfig->sharedAPIObject);
991+
J9ROMClass *romClass = sharedapi->jclFindOrphanROMClassByUniqueID(currentThread, lookupKey, lookupKeyLength - 1);
992+
if (nullptr != romClass) {
993+
J9Class *hostClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(lookupClass));
994+
J9ClassLoader *classloader = hostClass->classLoader;
995+
if (nullptr != hostClass) {
996+
omrthread_monitor_enter(vm->classTableMutex);
997+
/* internalCreateRAMClassFromROMClass will release the classTableMutex. */
998+
J9Class *ramClass = vmFuncs->internalCreateRAMClassFromROMClass(
999+
currentThread,
1000+
classloader,
1001+
romClass,
1002+
options,
1003+
nullptr /* elementClass */,
1004+
nullptr /* protectionDomain */,
1005+
nullptr /* methodRemapArray */,
1006+
J9_CP_INDEX_NONE,
1007+
LOAD_LOCATION_UNKNOWN,
1008+
nullptr /* classBeingRedefined */,
1009+
hostClass);
1010+
if (nullptr != ramClass && nullptr == currentThread->currentException) {
1011+
result = vmFuncs->j9jni_createLocalRef(env, J9VM_J9CLASS_TO_HEAPCLASS(ramClass));
1012+
}
1013+
}
1014+
}
1015+
}
1016+
1017+
if (nullptr != lookupKey) {
1018+
j9mem_free_memory(lookupKey);
1019+
}
1020+
Trc_JCL_java_lang_invoke_MethodHandleNatives_findLambdaOrLambdaFormInSCC_Exit(env);
1021+
vmFuncs->internalExitVMToJNI(currentThread);
1022+
#undef J9_ROM_ADDRESS_SUFFIX
1023+
#endif /* J9VM_OPT_SHARED_CLASSES */
1024+
return result;
1025+
}
1026+
1027+
/**
1028+
* static native Class<?> findLambdaInSCC(String classname, Class<?> hostClass);
1029+
*
1030+
* Find a Lambda class in the SCC.
1031+
* Requires non-null input arguments.
1032+
* If found, returns a pointer to a RAMClass of the SCC-cached, otherwise nullptr.
1033+
*/
1034+
jobject JNICALL
1035+
Java_java_lang_invoke_MethodHandleNatives_findLambdaInSCC(JNIEnv *env, jclass clazz, jstring classnameObject, jclass lookupClass)
1036+
{
1037+
UDATA options = J9_FINDCLASS_FLAG_NO_CHECK_FOR_EXISTING_CLASS
1038+
| J9_FINDCLASS_FLAG_THROW_ON_FAIL
1039+
| J9_FINDCLASS_FLAG_UNSAFE
1040+
| J9_FINDCLASS_FLAG_HIDDEN
1041+
| J9_FINDCLASS_FLAG_CLASS_OPTION_NESTMATE
1042+
| J9_FINDCLASS_FLAG_CLASS_OPTION_STRONG;
1043+
return findLambdaOrLambdaFormInSCC(env, clazz, classnameObject, lookupClass, options);
1044+
}
1045+
1046+
/**
1047+
* static native Class<?> findLambdaFormInSCC(String classname, Class<?> hostClass);
1048+
*
1049+
* Find a customized LambdaForm class in the SCC.
1050+
* Requires non-null input arguments.
1051+
* If found, returns a pointer to a RAMClass of the SCC-cached class, otherwise nullptr.
1052+
*/
1053+
jobject JNICALL
1054+
Java_java_lang_invoke_MethodHandleNatives_findLambdaFormInSCC(JNIEnv *env, jclass clazz, jstring classnameObject, jclass lookupClass)
1055+
{
1056+
UDATA options = J9_FINDCLASS_FLAG_NO_CHECK_FOR_EXISTING_CLASS
1057+
| J9_FINDCLASS_FLAG_THROW_ON_FAIL
1058+
| J9_FINDCLASS_FLAG_UNSAFE
1059+
| J9_FINDCLASS_FLAG_HIDDEN
1060+
| J9_FINDCLASS_FLAG_ANON;
1061+
return findLambdaOrLambdaFormInSCC(env, clazz, classnameObject, lookupClass, options);
1062+
}
1063+
9481064
/**
9491065
* [JDK8] static native MemberName resolve(MemberName self, Class<?> caller)
9501066
* throws LinkageError, ClassNotFoundException;
@@ -987,7 +1103,7 @@ Java_java_lang_invoke_MethodHandleNatives_resolve(
9871103
char nameBuffer[256];
9881104
nameBuffer[0] = 0;
9891105
J9UTF8 *signature = NULL;
990-
char signatureBuffer[256];
1106+
char signatureBuffer[512];
9911107
signatureBuffer[0] = 0;
9921108
PORT_ACCESS_FROM_JAVAVM(vm);
9931109
vmFuncs->internalEnterVMFromJNI(currentThread);
@@ -1419,7 +1535,7 @@ Java_java_lang_invoke_MethodHandleNatives_getMembers(
14191535
char nameBuffer[256];
14201536
nameBuffer[0] = 0;
14211537
J9UTF8 *signature = NULL;
1422-
char signatureBuffer[256];
1538+
char signatureBuffer[512];
14231539
signatureBuffer[0] = 0;
14241540
j9object_t callerObject = ((NULL == caller) ? NULL : J9_JNI_UNWRAP_REFERENCE(caller));
14251541

0 commit comments

Comments
 (0)