Skip to content

Commit 206d542

Browse files
authored
Merge pull request #20072 from ChengJin01/ffi_avoid_duplicating_ffi_type_struct_downcall_1_code_v0.48.0
[FFI/0.48] Avoid duplicating ffi_type for the same struct in downcall
2 parents 42a10d0 + 4f0207b commit 206d542

File tree

8 files changed

+441
-129
lines changed

8 files changed

+441
-129
lines changed

runtime/libffi/z/sysvz64.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ BYTE8R1 DS 0H Struct goes in R1
649649

650650
BYTE8R2 DS 0H Struct goes in R2
651651
CFI 0,2 is R2 available?
652-
BH BYTE8R3
652+
BNL BYTE8R3
653653

654654
LG 2,0(6,13)
655655

runtime/oti/j9nonbuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6101,6 +6101,7 @@ typedef struct J9JavaVM {
61016101
omrthread_monitor_t cifArgumentTypesCacheMutex;
61026102
struct J9UpcallThunkHeapList *thunkHeapHead;
61036103
omrthread_monitor_t thunkHeapListMutex;
6104+
struct J9HashTable *layoutStrFFITypeTable;
61046105
#endif /* JAVA_SPEC_VERSION >= 16 */
61056106
struct J9HashTable* ensureHashedClasses;
61066107
#if JAVA_SPEC_VERSION >= 19
@@ -6319,6 +6320,12 @@ typedef struct J9UpcallMetaDataEntry {
63196320
J9UpcallMetaData *upcallMetaData;
63206321
} J9UpcallMetaDataEntry;
63216322

6323+
typedef struct J9LayoutStrFFITypeEntry {
6324+
U_8 *layoutStr;
6325+
UDATA layoutStrLength;
6326+
void *structFFIType;
6327+
} J9LayoutStrFFITypeEntry;
6328+
63226329
#endif /* JAVA_SPEC_VERSION >= 16 */
63236330

63246331
/* Data block for JIT instance field watch reporting */

runtime/vm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ set(main_sources
136136
jvmrisup.c
137137
KeyHashTable.c
138138
LayoutFFITypeHelpers.cpp
139+
LayoutFFITypeTable.cpp
139140
leconditionexceptionsup.c
140141
linearswalk.c
141142
lockwordconfig.c

runtime/vm/LayoutFFITypeHelpers.cpp

Lines changed: 98 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,21 @@ freeAllStructFFITypes(J9VMThread *currentThread, void *cifNode)
4949
}
5050
}
5151

52-
ffi_type*
53-
LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
52+
ffi_type *
53+
LayoutFFITypeHelpers::getArrayFFIType(const char **layout, UDATA nElements)
54+
{
5455
ffi_type *typeFFI = NULL;
5556
ffi_type *elementType = NULL;
5657
PORT_ACCESS_FROM_JAVAVM(_vm);
5758

5859
/* A struct starts with "#" plus the count of struct elements,
59-
* followed by the type of struct elements.
60+
* followed by the types of the struct elements.
6061
* e.g. the preprocessed layout of
61-
* struct int_struct{
62-
* int elem1,
63-
* int elem2
64-
* }int_struct[2]
65-
* is #2[II]
62+
* struct int_struct {
63+
* int elem1;
64+
* int elem2;
65+
* };
66+
* is "#2[II]".
6667
*/
6768
if ('#' == **layout) {
6869
elementType = getStructFFIType(layout);
@@ -83,7 +84,7 @@ LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
8384
typeFFI->size = 0;
8485
typeFFI->alignment = 0;
8586
typeFFI->type = FFI_TYPE_STRUCT;
86-
typeFFI->elements = (ffi_type **) j9mem_allocate_memory(sizeof(ffi_type*) * (nElements + 1), J9MEM_CATEGORY_VM_FFI);
87+
typeFFI->elements = (ffi_type **)j9mem_allocate_memory(sizeof(ffi_type *) * (nElements + 1), J9MEM_CATEGORY_VM_FFI);
8788
if (NULL == typeFFI->elements) {
8889
freeStructFFIType(elementType);
8990
j9mem_free_memory(typeFFI);
@@ -100,51 +101,117 @@ LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
100101
return typeFFI;
101102
}
102103

103-
ffi_type*
104-
LayoutFFITypeHelpers::getStructFFIType(char **layout)
104+
ffi_type *
105+
LayoutFFITypeHelpers::getStructFFIType(const char **layout)
105106
{
107+
const char *currentLayout = *layout;
108+
J9LayoutStrFFITypeEntry *layoutStrFFITypeEntry = NULL;
109+
J9LayoutStrFFITypeEntry *resultEntry = NULL;
110+
ffi_type **structElements = NULL;
106111
ffi_type *typeFFI = NULL;
112+
PORT_ACCESS_FROM_JAVAVM(_vm);
113+
114+
if (NULL == _vm->layoutStrFFITypeTable) {
115+
_vm->layoutStrFFITypeTable = createLayoutStrFFITypeTable(_vm);
116+
if (NULL == _vm->layoutStrFFITypeTable) {
117+
goto freeAllMemoryThenExit;
118+
}
119+
}
120+
121+
layoutStrFFITypeEntry = (J9LayoutStrFFITypeEntry *)j9mem_allocate_memory(sizeof(J9LayoutStrFFITypeEntry), J9MEM_CATEGORY_VM_FFI);
122+
if (NULL == layoutStrFFITypeEntry) {
123+
goto freeAllMemoryThenExit;
124+
}
125+
126+
layoutStrFFITypeEntry->layoutStrLength = getLengthOfStructLayout(currentLayout);
127+
if (0 == layoutStrFFITypeEntry->layoutStrLength) {
128+
/* Malformed input. */
129+
goto freeAllMemoryThenExit;
130+
}
131+
layoutStrFFITypeEntry->layoutStr = (U_8 *)j9mem_allocate_memory(layoutStrFFITypeEntry->layoutStrLength + 1, J9MEM_CATEGORY_VM_FFI);
132+
if (NULL == layoutStrFFITypeEntry->layoutStr) {
133+
goto freeAllMemoryThenExit;
134+
}
135+
136+
memcpy(layoutStrFFITypeEntry->layoutStr, currentLayout, layoutStrFFITypeEntry->layoutStrLength);
137+
layoutStrFFITypeEntry->layoutStr[layoutStrFFITypeEntry->layoutStrLength] = '\0';
138+
139+
/* Search the hashtable for the ffi_type if the same struct layout string exists. */
140+
resultEntry = findLayoutStrFFIType(_vm->layoutStrFFITypeTable, layoutStrFFITypeEntry);
141+
if (NULL != resultEntry) {
142+
j9mem_free_memory(layoutStrFFITypeEntry->layoutStr);
143+
j9mem_free_memory(layoutStrFFITypeEntry);
144+
/* Return the duplicate ffi_type for the same struct if found in the hashtable. */
145+
typeFFI = (ffi_type *)(resultEntry->structFFIType);
146+
/* Reach the end of the nested struct layout string so as to move to
147+
* the next element in getStructFFITypeElements() if exists.
148+
*/
149+
(*layout) += resultEntry->layoutStrLength - 1;
150+
goto done;
151+
}
152+
153+
/* Skip over the '#' case. */
154+
(*layout) = currentLayout + 1;
155+
107156
/* The struct layout is incremented for the '[' case in getStructFFITypeElements(), in which case
108157
* the remaining layout string is then traversed when getStructFFITypeElements() is called recursively.
109158
*/
110-
(*layout) += 1; // skip over the '#' case
111-
ffi_type **structElements = getStructFFITypeElements(layout);
112-
PORT_ACCESS_FROM_JAVAVM(_vm);
159+
structElements = getStructFFITypeElements(layout);
160+
if (NULL == structElements) {
161+
goto freeAllMemoryThenExit;
162+
}
163+
113164
typeFFI = (ffi_type *)j9mem_allocate_memory(sizeof(ffi_type), J9MEM_CATEGORY_VM_FFI);
114165
if (NULL == typeFFI) {
115-
setNativeOutOfMemoryError(_currentThread, 0, 0);
116-
goto done;
166+
goto freeAllMemoryThenExit;
117167
}
118168
typeFFI->size = 0;
119169
typeFFI->alignment = 0;
120170
typeFFI->type = FFI_TYPE_STRUCT;
121171
typeFFI->elements = structElements;
122172

173+
/* Add the created ffi_type for the struct to the hashtable
174+
* if the corresponding layout string doesn't exist.
175+
*/
176+
layoutStrFFITypeEntry->structFFIType = (void *)typeFFI;
177+
resultEntry = addLayoutStrFFIType(_vm->layoutStrFFITypeTable, layoutStrFFITypeEntry);
178+
if (NULL == resultEntry) {
179+
freeStructFFIType(typeFFI);
180+
typeFFI = NULL;
181+
goto freeAllMemoryThenExit;
182+
}
183+
123184
done:
124185
return typeFFI;
186+
187+
freeAllMemoryThenExit:
188+
if (NULL != layoutStrFFITypeEntry) {
189+
j9mem_free_memory(layoutStrFFITypeEntry->layoutStr);
190+
j9mem_free_memory(layoutStrFFITypeEntry);
191+
}
192+
freeStructFFITypeElements(structElements);
193+
setNativeOutOfMemoryError(_currentThread, 0, 0);
194+
goto done;
125195
}
126196

127-
ffi_type**
128-
LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
197+
ffi_type **
198+
LayoutFFITypeHelpers::getStructFFITypeElements(const char **layout)
129199
{
130200
PORT_ACCESS_FROM_JAVAVM(_vm);
131-
132-
char *currentLayout = *layout;
133-
ffi_type **elements = NULL;
201+
const char *currentLayout = *layout;
134202
UDATA nElements = 0;
135203
UDATA elementCount = getIntFromLayout(&currentLayout);
136-
137-
elements = (ffi_type **) j9mem_allocate_memory(sizeof(ffi_type *) * (elementCount + 1), J9MEM_CATEGORY_VM_FFI);
204+
ffi_type **elements = (ffi_type **)j9mem_allocate_memory(sizeof(ffi_type *) * (elementCount + 1), J9MEM_CATEGORY_VM_FFI);
138205
if (NULL == elements) {
139206
goto done;
140207
}
141208
elements[elementCount] = NULL;
142-
currentLayout += 1; // Skip over the '[' case to the struct elements
209+
currentLayout += 1; /* Skip over the '[' case to the struct elements. */
143210

144211
while ('\0' != *currentLayout) {
145212
char symb = *currentLayout;
146213
switch (symb) {
147-
case '#': // Start of nested struct e.g. #5[...]
214+
case '#': /* Start of nested struct. e.g. #5[...] */
148215
{
149216
ffi_type *result = getStructFFIType(&currentLayout);
150217
if (NULL == result) {
@@ -156,9 +223,9 @@ LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
156223
nElements += 1;
157224
break;
158225
}
159-
case ']': // End of struct
226+
case ']': /* End of struct. */
160227
*layout = currentLayout;
161-
/* The last element of struct needs to be NULL for FFI_TYPE_STRUCT */
228+
/* The last element of struct needs to be NULL for FFI_TYPE_STRUCT. */
162229
elements[nElements] = NULL;
163230
goto done;
164231
case '0':
@@ -178,7 +245,7 @@ LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
178245
* 2) "5:#2[II]" for a struct array with 5 struct elements (each stuct contains 2 integers).
179246
*/
180247
UDATA nArray = getIntFromLayout(&currentLayout);
181-
currentLayout += 1; // Skip over the separator of an array (":") to the elements
248+
currentLayout += 1; /* Skip over the separator of an array (":") to the elements. */
182249
ffi_type *result = getArrayFFIType(&currentLayout, nArray);
183250
if (NULL == result) {
184251
freeStructFFITypeElements(elements);
@@ -204,10 +271,10 @@ void
204271
LayoutFFITypeHelpers::freeStructFFIType(ffi_type *ffiType)
205272
{
206273
if ((NULL != ffiType)
207-
&& ((FFI_TYPE_STRUCT == ffiType->type)
274+
&& ((FFI_TYPE_STRUCT == ffiType->type)
208275
#if defined(J9ZOS390) && defined(J9VM_ENV_DATA64)
209-
|| (FFI_TYPE_STRUCT_FF == ffiType->type)
210-
|| (FFI_TYPE_STRUCT_DD == ffiType->type)
276+
|| (FFI_TYPE_STRUCT_FF == ffiType->type)
277+
|| (FFI_TYPE_STRUCT_DD == ffiType->type)
211278
#endif /* defined(J9ZOS390) && defined(J9VM_ENV_DATA64) */
212279
)) {
213280
if (NULL != ffiType->elements) {

0 commit comments

Comments
 (0)