Skip to content

Commit

Permalink
Merge pull request #20072 from ChengJin01/ffi_avoid_duplicating_ffi_t…
Browse files Browse the repository at this point in the history
…ype_struct_downcall_1_code_v0.48.0

[FFI/0.48] Avoid duplicating ffi_type for the same struct in downcall
  • Loading branch information
pshipton authored Aug 28, 2024
2 parents 42a10d0 + 4f0207b commit 206d542
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 129 deletions.
2 changes: 1 addition & 1 deletion runtime/libffi/z/sysvz64.s
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ BYTE8R1 DS 0H Struct goes in R1

BYTE8R2 DS 0H Struct goes in R2
CFI 0,2 is R2 available?
BH BYTE8R3
BNL BYTE8R3

LG 2,0(6,13)

Expand Down
7 changes: 7 additions & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -6101,6 +6101,7 @@ typedef struct J9JavaVM {
omrthread_monitor_t cifArgumentTypesCacheMutex;
struct J9UpcallThunkHeapList *thunkHeapHead;
omrthread_monitor_t thunkHeapListMutex;
struct J9HashTable *layoutStrFFITypeTable;
#endif /* JAVA_SPEC_VERSION >= 16 */
struct J9HashTable* ensureHashedClasses;
#if JAVA_SPEC_VERSION >= 19
Expand Down Expand Up @@ -6319,6 +6320,12 @@ typedef struct J9UpcallMetaDataEntry {
J9UpcallMetaData *upcallMetaData;
} J9UpcallMetaDataEntry;

typedef struct J9LayoutStrFFITypeEntry {
U_8 *layoutStr;
UDATA layoutStrLength;
void *structFFIType;
} J9LayoutStrFFITypeEntry;

#endif /* JAVA_SPEC_VERSION >= 16 */

/* Data block for JIT instance field watch reporting */
Expand Down
1 change: 1 addition & 0 deletions runtime/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ set(main_sources
jvmrisup.c
KeyHashTable.c
LayoutFFITypeHelpers.cpp
LayoutFFITypeTable.cpp
leconditionexceptionsup.c
linearswalk.c
lockwordconfig.c
Expand Down
129 changes: 98 additions & 31 deletions runtime/vm/LayoutFFITypeHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,21 @@ freeAllStructFFITypes(J9VMThread *currentThread, void *cifNode)
}
}

ffi_type*
LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
ffi_type *
LayoutFFITypeHelpers::getArrayFFIType(const char **layout, UDATA nElements)
{
ffi_type *typeFFI = NULL;
ffi_type *elementType = NULL;
PORT_ACCESS_FROM_JAVAVM(_vm);

/* A struct starts with "#" plus the count of struct elements,
* followed by the type of struct elements.
* followed by the types of the struct elements.
* e.g. the preprocessed layout of
* struct int_struct{
* int elem1,
* int elem2
* }int_struct[2]
* is #2[II]
* struct int_struct {
* int elem1;
* int elem2;
* };
* is "#2[II]".
*/
if ('#' == **layout) {
elementType = getStructFFIType(layout);
Expand All @@ -83,7 +84,7 @@ LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
typeFFI->size = 0;
typeFFI->alignment = 0;
typeFFI->type = FFI_TYPE_STRUCT;
typeFFI->elements = (ffi_type **) j9mem_allocate_memory(sizeof(ffi_type*) * (nElements + 1), J9MEM_CATEGORY_VM_FFI);
typeFFI->elements = (ffi_type **)j9mem_allocate_memory(sizeof(ffi_type *) * (nElements + 1), J9MEM_CATEGORY_VM_FFI);
if (NULL == typeFFI->elements) {
freeStructFFIType(elementType);
j9mem_free_memory(typeFFI);
Expand All @@ -100,51 +101,117 @@ LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
return typeFFI;
}

ffi_type*
LayoutFFITypeHelpers::getStructFFIType(char **layout)
ffi_type *
LayoutFFITypeHelpers::getStructFFIType(const char **layout)
{
const char *currentLayout = *layout;
J9LayoutStrFFITypeEntry *layoutStrFFITypeEntry = NULL;
J9LayoutStrFFITypeEntry *resultEntry = NULL;
ffi_type **structElements = NULL;
ffi_type *typeFFI = NULL;
PORT_ACCESS_FROM_JAVAVM(_vm);

if (NULL == _vm->layoutStrFFITypeTable) {
_vm->layoutStrFFITypeTable = createLayoutStrFFITypeTable(_vm);
if (NULL == _vm->layoutStrFFITypeTable) {
goto freeAllMemoryThenExit;
}
}

layoutStrFFITypeEntry = (J9LayoutStrFFITypeEntry *)j9mem_allocate_memory(sizeof(J9LayoutStrFFITypeEntry), J9MEM_CATEGORY_VM_FFI);
if (NULL == layoutStrFFITypeEntry) {
goto freeAllMemoryThenExit;
}

layoutStrFFITypeEntry->layoutStrLength = getLengthOfStructLayout(currentLayout);
if (0 == layoutStrFFITypeEntry->layoutStrLength) {
/* Malformed input. */
goto freeAllMemoryThenExit;
}
layoutStrFFITypeEntry->layoutStr = (U_8 *)j9mem_allocate_memory(layoutStrFFITypeEntry->layoutStrLength + 1, J9MEM_CATEGORY_VM_FFI);
if (NULL == layoutStrFFITypeEntry->layoutStr) {
goto freeAllMemoryThenExit;
}

memcpy(layoutStrFFITypeEntry->layoutStr, currentLayout, layoutStrFFITypeEntry->layoutStrLength);
layoutStrFFITypeEntry->layoutStr[layoutStrFFITypeEntry->layoutStrLength] = '\0';

/* Search the hashtable for the ffi_type if the same struct layout string exists. */
resultEntry = findLayoutStrFFIType(_vm->layoutStrFFITypeTable, layoutStrFFITypeEntry);
if (NULL != resultEntry) {
j9mem_free_memory(layoutStrFFITypeEntry->layoutStr);
j9mem_free_memory(layoutStrFFITypeEntry);
/* Return the duplicate ffi_type for the same struct if found in the hashtable. */
typeFFI = (ffi_type *)(resultEntry->structFFIType);
/* Reach the end of the nested struct layout string so as to move to
* the next element in getStructFFITypeElements() if exists.
*/
(*layout) += resultEntry->layoutStrLength - 1;
goto done;
}

/* Skip over the '#' case. */
(*layout) = currentLayout + 1;

/* The struct layout is incremented for the '[' case in getStructFFITypeElements(), in which case
* the remaining layout string is then traversed when getStructFFITypeElements() is called recursively.
*/
(*layout) += 1; // skip over the '#' case
ffi_type **structElements = getStructFFITypeElements(layout);
PORT_ACCESS_FROM_JAVAVM(_vm);
structElements = getStructFFITypeElements(layout);
if (NULL == structElements) {
goto freeAllMemoryThenExit;
}

typeFFI = (ffi_type *)j9mem_allocate_memory(sizeof(ffi_type), J9MEM_CATEGORY_VM_FFI);
if (NULL == typeFFI) {
setNativeOutOfMemoryError(_currentThread, 0, 0);
goto done;
goto freeAllMemoryThenExit;
}
typeFFI->size = 0;
typeFFI->alignment = 0;
typeFFI->type = FFI_TYPE_STRUCT;
typeFFI->elements = structElements;

/* Add the created ffi_type for the struct to the hashtable
* if the corresponding layout string doesn't exist.
*/
layoutStrFFITypeEntry->structFFIType = (void *)typeFFI;
resultEntry = addLayoutStrFFIType(_vm->layoutStrFFITypeTable, layoutStrFFITypeEntry);
if (NULL == resultEntry) {
freeStructFFIType(typeFFI);
typeFFI = NULL;
goto freeAllMemoryThenExit;
}

done:
return typeFFI;

freeAllMemoryThenExit:
if (NULL != layoutStrFFITypeEntry) {
j9mem_free_memory(layoutStrFFITypeEntry->layoutStr);
j9mem_free_memory(layoutStrFFITypeEntry);
}
freeStructFFITypeElements(structElements);
setNativeOutOfMemoryError(_currentThread, 0, 0);
goto done;
}

ffi_type**
LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
ffi_type **
LayoutFFITypeHelpers::getStructFFITypeElements(const char **layout)
{
PORT_ACCESS_FROM_JAVAVM(_vm);

char *currentLayout = *layout;
ffi_type **elements = NULL;
const char *currentLayout = *layout;
UDATA nElements = 0;
UDATA elementCount = getIntFromLayout(&currentLayout);

elements = (ffi_type **) j9mem_allocate_memory(sizeof(ffi_type *) * (elementCount + 1), J9MEM_CATEGORY_VM_FFI);
ffi_type **elements = (ffi_type **)j9mem_allocate_memory(sizeof(ffi_type *) * (elementCount + 1), J9MEM_CATEGORY_VM_FFI);
if (NULL == elements) {
goto done;
}
elements[elementCount] = NULL;
currentLayout += 1; // Skip over the '[' case to the struct elements
currentLayout += 1; /* Skip over the '[' case to the struct elements. */

while ('\0' != *currentLayout) {
char symb = *currentLayout;
switch (symb) {
case '#': // Start of nested struct e.g. #5[...]
case '#': /* Start of nested struct. e.g. #5[...] */
{
ffi_type *result = getStructFFIType(&currentLayout);
if (NULL == result) {
Expand All @@ -156,9 +223,9 @@ LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
nElements += 1;
break;
}
case ']': // End of struct
case ']': /* End of struct. */
*layout = currentLayout;
/* The last element of struct needs to be NULL for FFI_TYPE_STRUCT */
/* The last element of struct needs to be NULL for FFI_TYPE_STRUCT. */
elements[nElements] = NULL;
goto done;
case '0':
Expand All @@ -178,7 +245,7 @@ LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
* 2) "5:#2[II]" for a struct array with 5 struct elements (each stuct contains 2 integers).
*/
UDATA nArray = getIntFromLayout(&currentLayout);
currentLayout += 1; // Skip over the separator of an array (":") to the elements
currentLayout += 1; /* Skip over the separator of an array (":") to the elements. */
ffi_type *result = getArrayFFIType(&currentLayout, nArray);
if (NULL == result) {
freeStructFFITypeElements(elements);
Expand All @@ -204,10 +271,10 @@ void
LayoutFFITypeHelpers::freeStructFFIType(ffi_type *ffiType)
{
if ((NULL != ffiType)
&& ((FFI_TYPE_STRUCT == ffiType->type)
&& ((FFI_TYPE_STRUCT == ffiType->type)
#if defined(J9ZOS390) && defined(J9VM_ENV_DATA64)
|| (FFI_TYPE_STRUCT_FF == ffiType->type)
|| (FFI_TYPE_STRUCT_DD == ffiType->type)
|| (FFI_TYPE_STRUCT_FF == ffiType->type)
|| (FFI_TYPE_STRUCT_DD == ffiType->type)
#endif /* defined(J9ZOS390) && defined(J9VM_ENV_DATA64) */
)) {
if (NULL != ffiType->elements) {
Expand Down
Loading

0 comments on commit 206d542

Please sign in to comment.