@@ -49,20 +49,21 @@ freeAllStructFFITypes(J9VMThread *currentThread, void *cifNode)
49
49
}
50
50
}
51
51
52
- ffi_type*
53
- LayoutFFITypeHelpers::getArrayFFIType (char **layout, UDATA nElements) {
52
+ ffi_type *
53
+ LayoutFFITypeHelpers::getArrayFFIType (const char **layout, UDATA nElements)
54
+ {
54
55
ffi_type *typeFFI = NULL ;
55
56
ffi_type *elementType = NULL ;
56
57
PORT_ACCESS_FROM_JAVAVM (_vm);
57
58
58
59
/* 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.
60
61
* 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]".
66
67
*/
67
68
if (' #' == **layout) {
68
69
elementType = getStructFFIType (layout);
@@ -83,7 +84,7 @@ LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
83
84
typeFFI->size = 0 ;
84
85
typeFFI->alignment = 0 ;
85
86
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);
87
88
if (NULL == typeFFI->elements ) {
88
89
freeStructFFIType (elementType);
89
90
j9mem_free_memory (typeFFI);
@@ -100,51 +101,117 @@ LayoutFFITypeHelpers::getArrayFFIType(char **layout, UDATA nElements) {
100
101
return typeFFI;
101
102
}
102
103
103
- ffi_type*
104
- LayoutFFITypeHelpers::getStructFFIType (char **layout)
104
+ ffi_type *
105
+ LayoutFFITypeHelpers::getStructFFIType (const char **layout)
105
106
{
107
+ const char *currentLayout = *layout;
108
+ J9LayoutStrFFITypeEntry *layoutStrFFITypeEntry = NULL ;
109
+ J9LayoutStrFFITypeEntry *resultEntry = NULL ;
110
+ ffi_type **structElements = NULL ;
106
111
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
+
107
156
/* The struct layout is incremented for the '[' case in getStructFFITypeElements(), in which case
108
157
* the remaining layout string is then traversed when getStructFFITypeElements() is called recursively.
109
158
*/
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
+
113
164
typeFFI = (ffi_type *)j9mem_allocate_memory (sizeof (ffi_type), J9MEM_CATEGORY_VM_FFI);
114
165
if (NULL == typeFFI) {
115
- setNativeOutOfMemoryError (_currentThread, 0 , 0 );
116
- goto done;
166
+ goto freeAllMemoryThenExit;
117
167
}
118
168
typeFFI->size = 0 ;
119
169
typeFFI->alignment = 0 ;
120
170
typeFFI->type = FFI_TYPE_STRUCT;
121
171
typeFFI->elements = structElements;
122
172
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
+
123
184
done:
124
185
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;
125
195
}
126
196
127
- ffi_type**
128
- LayoutFFITypeHelpers::getStructFFITypeElements (char **layout)
197
+ ffi_type **
198
+ LayoutFFITypeHelpers::getStructFFITypeElements (const char **layout)
129
199
{
130
200
PORT_ACCESS_FROM_JAVAVM (_vm);
131
-
132
- char *currentLayout = *layout;
133
- ffi_type **elements = NULL ;
201
+ const char *currentLayout = *layout;
134
202
UDATA nElements = 0 ;
135
203
UDATA elementCount = getIntFromLayout (¤tLayout);
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);
138
205
if (NULL == elements) {
139
206
goto done;
140
207
}
141
208
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. */
143
210
144
211
while (' \0 ' != *currentLayout) {
145
212
char symb = *currentLayout;
146
213
switch (symb) {
147
- case ' #' : // Start of nested struct e.g. #5[...]
214
+ case ' #' : /* Start of nested struct. e.g. #5[...] */
148
215
{
149
216
ffi_type *result = getStructFFIType (¤tLayout);
150
217
if (NULL == result) {
@@ -156,9 +223,9 @@ LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
156
223
nElements += 1 ;
157
224
break ;
158
225
}
159
- case ' ]' : // End of struct
226
+ case ' ]' : /* End of struct. */
160
227
*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. */
162
229
elements[nElements] = NULL ;
163
230
goto done;
164
231
case ' 0' :
@@ -178,7 +245,7 @@ LayoutFFITypeHelpers::getStructFFITypeElements(char **layout)
178
245
* 2) "5:#2[II]" for a struct array with 5 struct elements (each stuct contains 2 integers).
179
246
*/
180
247
UDATA nArray = getIntFromLayout (¤tLayout);
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. */
182
249
ffi_type *result = getArrayFFIType (¤tLayout, nArray);
183
250
if (NULL == result) {
184
251
freeStructFFITypeElements (elements);
@@ -204,10 +271,10 @@ void
204
271
LayoutFFITypeHelpers::freeStructFFIType (ffi_type *ffiType)
205
272
{
206
273
if ((NULL != ffiType)
207
- && ((FFI_TYPE_STRUCT == ffiType->type )
274
+ && ((FFI_TYPE_STRUCT == ffiType->type )
208
275
#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 )
211
278
#endif /* defined(J9ZOS390) && defined(J9VM_ENV_DATA64) */
212
279
)) {
213
280
if (NULL != ffiType->elements ) {
0 commit comments