Skip to content

Commit fe43095

Browse files
authored
Merge pull request #19306 from ChengJin01/ffi_handle_discontigous_heap_downcall_jdk22_v0.45.0
[FFI/v0.45.0] Handle the discontiguous heap array in downcall
2 parents 04eaa4d + aca288a commit fe43095

File tree

14 files changed

+1068
-293
lines changed

14 files changed

+1068
-293
lines changed

runtime/tests/clinkerffi/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ omr_add_exports(clinkerffitests
340340
addLongsFromMultipleStructPtrs_returnStruct
341341
addFloatsFromMultipleStructPtrs_returnStruct
342342
addDoublesFromMultipleStructPtrs_returnStruct
343+
setBoolFromArrayPtrWithXor
344+
addByteFromArrayPtrByOne
345+
addCharFromArrayPtrByOne
346+
addShortFromArrayPtrByOne
347+
addIntFromArrayPtrByOne
348+
addLongFromArrayPtrByOne
349+
addFloatFromArrayPtrByOne
350+
addDoubleFromArrayPtrByOne
343351
add2BoolsWithOrByUpcallMH
344352
addBoolAndBoolFromPointerWithOrByUpcallMH
345353
addBoolAndBoolFromNativePtrWithOrByUpcallMH

runtime/tests/clinkerffi/downcall.c

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ addIntAndChar(int intArg, char charArg)
9494
*
9595
* @param intArg1 the 1st integer to add
9696
* @param intArg2 the 2nd integer to add
97-
* @return void
9897
*/
9998
void
10099
add2IntsReturnVoid(int intArg1, int intArg2)
@@ -4669,3 +4668,147 @@ addDoublesFromMultipleStructPtrs_returnStruct(stru_2_Doubles *arg1, stru_2_Doubl
46694668
doubleStruct.elem2 = arg1->elem2 + arg2->elem2 + arg3->elem2;
46704669
return doubleStruct;
46714670
}
4671+
4672+
/**
4673+
* Do xor operation on each boolean of a native array (dereferenced from a pointer to a native array)
4674+
* and assign the result to the element of a on-heap array at the same index.
4675+
*
4676+
* @param size the array size
4677+
* @param heapPtr a pointer to a on-heap array
4678+
* @param nativePtr a pointer to a native array
4679+
*/
4680+
void
4681+
setBoolFromArrayPtrWithXor(int size, char *heapPtr, char *nativePtr)
4682+
{
4683+
int index = 0;
4684+
while (index < size) {
4685+
heapPtr[index] = nativePtr[index];
4686+
index += 1;
4687+
}
4688+
}
4689+
4690+
/**
4691+
* Add each byte of a native array (dereferenced from a pointer to a native array)
4692+
* by 1 and assign the result to the element of a on-heap array at the same index.
4693+
*
4694+
* @param size the array size
4695+
* @param heapPtr a pointer to a on-heap array
4696+
* @param nativePtr a pointer to a native array
4697+
*/
4698+
void
4699+
addByteFromArrayPtrByOne(int size, char *heapPtr, char *nativePtr)
4700+
{
4701+
int index = 0;
4702+
while (index < size) {
4703+
heapPtr[index] = nativePtr[index] + 1;
4704+
index += 1;
4705+
}
4706+
}
4707+
4708+
/**
4709+
* Add each char of a native array (dereferenced from a pointer to a native array)
4710+
* by 1 and assign the result to the element of a on-heap array at the same index.
4711+
*
4712+
* @param size the array size
4713+
* @param heapPtr a pointer to a on-heap array
4714+
* @param nativePtr a pointer to a native array
4715+
*/
4716+
void
4717+
addCharFromArrayPtrByOne(int size, short *heapPtr, short *nativePtr)
4718+
{
4719+
int index = 0;
4720+
while (index < size) {
4721+
heapPtr[index] = nativePtr[index] + 1;
4722+
index += 1;
4723+
}
4724+
}
4725+
4726+
/**
4727+
* Add each short of a native array (dereferenced from a pointer to a native array)
4728+
* by 1 and assign the result to the element of a on-heap array at the same index.
4729+
*
4730+
* @param size the array size
4731+
* @param heapPtr a pointer to a on-heap array
4732+
* @param nativePtr a pointer to a native array
4733+
*/
4734+
void
4735+
addShortFromArrayPtrByOne(int size, short *heapPtr, short *nativePtr)
4736+
{
4737+
int index = 0;
4738+
while (index < size) {
4739+
heapPtr[index] = nativePtr[index] + 1;
4740+
index += 1;
4741+
}
4742+
}
4743+
4744+
/**
4745+
* Add each integer of a native array (dereferenced from a pointer to a native array)
4746+
* by 1 and assign the result to the element of a on-heap array at the same index.
4747+
*
4748+
* @param size the array size
4749+
* @param heapPtr a pointer to a on-heap array
4750+
* @param nativePtr a pointer to a native array
4751+
*/
4752+
void
4753+
addIntFromArrayPtrByOne(int size, int *heapPtr, int *nativePtr)
4754+
{
4755+
int index = 0;
4756+
while (index < size) {
4757+
heapPtr[index] = nativePtr[index] + 1;
4758+
index += 1;
4759+
}
4760+
}
4761+
4762+
/**
4763+
* Add each long of a native array (dereferenced from a pointer to a native array)
4764+
* by 1 and assign the result to the element of a on-heap array at the same index.
4765+
*
4766+
* @param size the array size
4767+
* @param heapPtr a pointer to a on-heap array
4768+
* @param nativePtr a pointer to a native array
4769+
*/
4770+
void
4771+
addLongFromArrayPtrByOne(int size, LONG *heapPtr, LONG *nativePtr)
4772+
{
4773+
int index = 0;
4774+
while (index < size) {
4775+
heapPtr[index] = nativePtr[index] + 1;
4776+
index += 1;
4777+
}
4778+
}
4779+
4780+
/**
4781+
* Add each float of a native array (dereferenced from a pointer to a native array)
4782+
* by 1 and assign the result to the element of a on-heap array at the same index.
4783+
*
4784+
* @param size the array size
4785+
* @param heapPtr a pointer to a on-heap array
4786+
* @param nativePtr a pointer to a native array
4787+
*/
4788+
void
4789+
addFloatFromArrayPtrByOne(int size, float *heapPtr, float *nativePtr)
4790+
{
4791+
int index = 0;
4792+
while (index < size) {
4793+
heapPtr[index] = nativePtr[index] + 1;
4794+
index += 1;
4795+
}
4796+
}
4797+
4798+
/**
4799+
* Add each double of a native array (dereferenced from a pointer to a native array)
4800+
* by 1 and assign the result to the element of a on-heap array at the same index.
4801+
*
4802+
* @param size the array size
4803+
* @param heapPtr a pointer to a on-heap array
4804+
* @param nativePtr a pointer to a native array
4805+
*/
4806+
void
4807+
addDoubleFromArrayPtrByOne(int size, double *heapPtr, double *nativePtr)
4808+
{
4809+
int index = 0;
4810+
while (index < size) {
4811+
heapPtr[index] = nativePtr[index] + 1;
4812+
index += 1;
4813+
}
4814+
}

runtime/tests/clinkerffi/module.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,14 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
333333
<export name="addLongsFromMultipleStructPtrs_returnStruct"/>
334334
<export name="addFloatsFromMultipleStructPtrs_returnStruct"/>
335335
<export name="addDoublesFromMultipleStructPtrs_returnStruct"/>
336+
<export name="setBoolFromArrayPtrWithXor"/>
337+
<export name="addByteFromArrayPtrByOne"/>
338+
<export name="addCharFromArrayPtrByOne"/>
339+
<export name="addShortFromArrayPtrByOne"/>
340+
<export name="addIntFromArrayPtrByOne"/>
341+
<export name="addLongFromArrayPtrByOne"/>
342+
<export name="addFloatFromArrayPtrByOne"/>
343+
<export name="addDoubleFromArrayPtrByOne"/>
336344
<export name="add2BoolsWithOrByUpcallMH"/>
337345
<export name="addBoolAndBoolFromPointerWithOrByUpcallMH"/>
338346
<export name="addBoolAndBoolFromNativePtrWithOrByUpcallMH"/>

runtime/vm/ArrayCopyHelpers.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*******************************************************************************
2+
* Copyright IBM Corp. and others 2024
3+
*
4+
* This program and the accompanying materials are made available under
5+
* the terms of the Eclipse Public License 2.0 which accompanies this
6+
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7+
* or the Apache License, Version 2.0 which accompanies this distribution and
8+
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
*
10+
* This Source Code may also be made available under the following
11+
* Secondary Licenses when the conditions for such availability set
12+
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13+
* General Public License, version 2 with the GNU Classpath
14+
* Exception [1] and GNU General Public License, version 2 with the
15+
* OpenJDK Assembly Exception [2].
16+
*
17+
* [1] https://www.gnu.org/software/classpath/license.html
18+
* [2] https://openjdk.org/legal/assembly-exception.html
19+
*
20+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
21+
*******************************************************************************/
22+
23+
#include "vm_api.h"
24+
#include "vm_internal.h"
25+
26+
#include "ArrayCopyHelpers.hpp"
27+
#include "VMAccess.hpp"
28+
29+
extern "C" {
30+
31+
void *
32+
memcpyFromHeapArray(J9VMThread *currentThread, j9object_t arrayObject, jboolean ensureMem32)
33+
{
34+
UDATA logElementSize = ((J9ROMArrayClass *)J9OBJECT_CLAZZ(currentThread, arrayObject)->romClass)->arrayShape & 0x0000FFFF;
35+
UDATA byteCount = (UDATA)J9INDEXABLEOBJECT_SIZE(currentThread, arrayObject) << logElementSize;
36+
void *elems = NULL;
37+
38+
if (ensureMem32) {
39+
elems = jniArrayAllocateMemory32FromThread(currentThread, ROUND_UP_TO_POWEROF2(byteCount, sizeof(UDATA)));
40+
} else {
41+
elems = jniArrayAllocateMemoryFromThread(currentThread, ROUND_UP_TO_POWEROF2(byteCount, sizeof(UDATA)));
42+
}
43+
if (NULL == elems) {
44+
gpCheckSetNativeOutOfMemoryError(currentThread, 0, 0);
45+
} else {
46+
JAVA_OFFLOAD_SWITCH_ON_WITH_REASON_IF_LIMIT_EXCEEDED(currentThread, J9_JNI_OFFLOAD_SWITCH_GET_ARRAY_ELEMENTS, byteCount);
47+
/* No guarantee of native memory alignment, so copy byte-wise. */
48+
VM_ArrayCopyHelpers::memcpyFromArray(currentThread, arrayObject, (UDATA)0, (UDATA)0, byteCount, elems);
49+
JAVA_OFFLOAD_SWITCH_OFF_WITH_REASON_IF_LIMIT_EXCEEDED(currentThread, J9_JNI_OFFLOAD_SWITCH_GET_ARRAY_ELEMENTS, byteCount);
50+
}
51+
52+
return elems;
53+
}
54+
55+
void
56+
memcpyToHeapArray(J9VMThread *currentThread, j9object_t arrayObject, void *elems, jint mode, jboolean ensureMem32)
57+
{
58+
/* Abort means do not copy the buffer, but do free it. */
59+
if (JNI_ABORT != mode) {
60+
UDATA logElementSize = ((J9ROMArrayClass *)J9OBJECT_CLAZZ(currentThread, arrayObject)->romClass)->arrayShape & 0x0000FFFF;
61+
UDATA byteCount = (UDATA)J9INDEXABLEOBJECT_SIZE(currentThread, arrayObject) << logElementSize;
62+
JAVA_OFFLOAD_SWITCH_ON_WITH_REASON_IF_LIMIT_EXCEEDED(currentThread, J9_JNI_OFFLOAD_SWITCH_RELEASE_ARRAY_ELEMENTS, byteCount);
63+
/* No guarantee of native memory alignment, so copy byte-wise. */
64+
VM_ArrayCopyHelpers::memcpyToArray(currentThread, arrayObject, (UDATA)0, (UDATA)0, byteCount, elems);
65+
JAVA_OFFLOAD_SWITCH_OFF_WITH_REASON_IF_LIMIT_EXCEEDED(currentThread, J9_JNI_OFFLOAD_SWITCH_RELEASE_ARRAY_ELEMENTS, byteCount);
66+
}
67+
/* Commit means copy the data but do not free the buffer - all other modes free the buffer. */
68+
if (JNI_COMMIT != mode) {
69+
if (ensureMem32) {
70+
jniArrayFreeMemory32FromThread(currentThread, elems);
71+
} else {
72+
jniArrayFreeMemoryFromThread(currentThread, elems);
73+
}
74+
}
75+
}
76+
77+
} /* extern "C" */

runtime/vm/BytecodeInterpreter.hpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5312,17 +5312,14 @@ class INTERPRETER_CLASS
53125312
if (J9ISCONTIGUOUSARRAY(_currentThread, heapBase)) {
53135313
/* The address is simply the base object plus the offset. */
53145314
pointerValues[i] = (UDATA)heapBase + heapOffset;
5315-
curHeapArgIdx += 1;
53165315
} else {
5317-
/* TODO: We will need to handle the case of a discontiguous array later. */
5318-
buildInternalNativeStackFrame(REGISTER_ARGS);
5319-
updateVMStruct(REGISTER_ARGS);
5320-
prepareForExceptionThrow(_currentThread);
5321-
setCurrentExceptionUTF(_currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);
5322-
VMStructHasBeenUpdated(REGISTER_ARGS);
5323-
rc = GOTO_THROW_CURRENT_EXCEPTION;
5324-
goto done;
5316+
/* Copy the discontiguous array to native memory to ensure
5317+
* its elements can be accessed correctly in the native function.
5318+
*/
5319+
void *elems = memcpyFromHeapArray(_currentThread, heapBase, JNI_FALSE);
5320+
pointerValues[i] = (UDATA)elems;
53255321
}
5322+
curHeapArgIdx += 1;
53265323
/* Set the flag to obtain the VMAccess so as to prevent the GC from
53275324
* updating the heap address during the critical downcall.
53285325
*/
@@ -5396,6 +5393,32 @@ class INTERPRETER_CLASS
53965393
recordJNIReturn(REGISTER_ARGS, bp);
53975394
restoreSpecialStackFrameLeavingArgs(REGISTER_ARGS, bp);
53985395

5396+
#if JAVA_SPEC_VERSION >= 22
5397+
/* For each heap argument, copy the corresponding native memory
5398+
* to the heap region in the case of the discontiguous array.
5399+
*/
5400+
if (isHeapPassed) {
5401+
curHeapArgIdx = 0;
5402+
for (U_8 i = 0; i < ffiArgCount; i++) {
5403+
U_8 argType = LayoutFFITypeHelpers::getJ9NativeTypeCodeFromFFIType(cif->arg_types[i]);
5404+
if ((J9NtcPointer == argType) && (J9_FFI_DOWNCALL_HEAP_ARGUMENT_ID == (U_64)ffiArgs[i])) {
5405+
j9object_t heapBase = (j9object_t)J9JAVAARRAYOFOBJECT_LOAD(
5406+
_currentThread,
5407+
J9_JNI_UNWRAP_REFERENCE(_sp + 11), /* The heap base array. */
5408+
curHeapArgIdx);
5409+
if (NULL == heapBase) {
5410+
rc = THROW_NPE;
5411+
goto done;
5412+
}
5413+
if (!J9ISCONTIGUOUSARRAY(_currentThread, heapBase)) {
5414+
memcpyToHeapArray(_currentThread, heapBase, (void *)(UDATA)(pointerValues[i]), 0, JNI_FALSE);
5415+
}
5416+
curHeapArgIdx += 1;
5417+
}
5418+
}
5419+
}
5420+
#endif /* JAVA_SPEC_VERSION >= 22 */
5421+
53995422
#if JAVA_SPEC_VERSION >= 21
54005423
/* Set the execution state after the downcall as required in the linker options. */
54015424
if (NULL != returnState) {

runtime/vm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ endif()
8080

8181
set(main_sources
8282
annsup.c
83+
ArrayCopyHelpers.cpp
8384
AsyncMessageHandler.cpp
8485
bchelper.c
8586
bindnatv.cpp

0 commit comments

Comments
 (0)