From 679ae7ff3352b31fce486122f73495a46d5ed30d Mon Sep 17 00:00:00 2001 From: Wei-Sheng Chin Date: Mon, 30 Jan 2023 09:22:28 -0800 Subject: [PATCH] [Java] Fix warnings (#14076) Fix C6011, C6385, C6386 found by Visual Studio. Basically, I set the maximum number of options for every EP to 128. To my knowledge, 128 is big enough to support all EPs. For support arbitrary number of EP options, we probably need #13999 and create a "std::vector"-like struct in C language. --- .../main/java/ai/onnxruntime/OrtSession.java | 11 +++++-- ...ai_onnxruntime_OrtSession_SessionOptions.c | 31 +++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/java/src/main/java/ai/onnxruntime/OrtSession.java b/java/src/main/java/ai/onnxruntime/OrtSession.java index 2fae9af4ec..df6f27741f 100644 --- a/java/src/main/java/ai/onnxruntime/OrtSession.java +++ b/java/src/main/java/ai/onnxruntime/OrtSession.java @@ -1001,8 +1001,11 @@ public class OrtSession implements AutoCloseable { } /** - * Adds Xnnpack as an execution backend. Needs to list all options here if a new option - * supported. current supported options: {} + * Adds Xnnpack as an execution backend. Needs to list all options hereif a new option + * supported. current supported options: {} The maximum number of provider options is set to 128 + * (see addExecutionProvider's comment). This number is controlled by + * ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH in ai_onnxruntime_OrtSession_SessionOptions.c. If 128 is + * not enough, please increase it or implementing an incremental way to add more options. * * @param providerOptions options pass to XNNPACK EP for initialization. * @throws OrtException If there was an error in native code. @@ -1132,6 +1135,10 @@ public class OrtSession implements AutoCloseable { private native void addCoreML(long apiHandle, long nativeHandle, int coreMLFlags) throws OrtException; + /* + * The max length of providerOptionKey and providerOptionVal is 128, as specified by + * ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH (search ONNXRuntime PR #14067 for its location). + */ private native void addExecutionProvider( long apiHandle, long nativeHandle, diff --git a/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c b/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c index ed01b54f8a..1e00a05437 100644 --- a/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c +++ b/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c @@ -15,6 +15,7 @@ #endif // Providers +#define ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH 128 #include "onnxruntime/core/providers/cpu/cpu_provider_factory.h" #include "onnxruntime/core/providers/dnnl/dnnl_provider_factory.h" #include "onnxruntime/core/providers/nnapi/nnapi_provider_factory.h" @@ -631,29 +632,33 @@ JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addExe const char* epName = (*jniEnv)->GetStringUTFChars(jniEnv, jepName, NULL); const OrtApi* api = (const OrtApi*)apiHandle; OrtSessionOptions* options = (OrtSessionOptions*)optionsHandle; - int keyCount = (*jniEnv)->GetArrayLength(jniEnv, configKeyArr); + size_t keyCount = (*jniEnv)->GetArrayLength(jniEnv, configKeyArr); - const char** keyArray = (const char**)malloc(keyCount * sizeof(const char*)); - const char** valueArray = (const char**)malloc(keyCount * sizeof(const char*)); - jstring* jkeyArray = (jstring*)malloc(keyCount * sizeof(jstring)); - jstring* jvalueArray = (jstring*)malloc(keyCount * sizeof(jstring)); + if (keyCount > ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH) { + throwOrtException(jniEnv, ORT_INVALID_ARGUMENT, "Too many provider options."); + } - for (int i = 0; i < keyCount; i++) { - jkeyArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configKeyArr, i)); - jvalueArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configValueArr, i)); + const char* keyArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + const char* valueArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + jstring jkeyArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + jstring jvalueArray[ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH]; + + for (size_t i = 0; i < keyCount; i++) { + // In this loop, it is type-safe to call (jsize)i since i is + // upper-bounded by keyCount (type: jsize) returned by GetArrayLength. + jkeyArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configKeyArr, (jsize)i)); + jvalueArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configValueArr, (jsize)i)); keyArray[i] = (*jniEnv)->GetStringUTFChars(jniEnv, jkeyArray[i], NULL); valueArray[i] = (*jniEnv)->GetStringUTFChars(jniEnv, jvalueArray[i], NULL); } checkOrtStatus(jniEnv, api, api->SessionOptionsAppendExecutionProvider(options, epName, keyArray, valueArray, keyCount)); - for (int i = 0; i < keyCount; i++) { + for (size_t i = 0; i < keyCount; i++) { (*jniEnv)->ReleaseStringUTFChars(jniEnv, jkeyArray[i], keyArray[i]); (*jniEnv)->ReleaseStringUTFChars(jniEnv, jvalueArray[i], valueArray[i]); } (*jniEnv)->ReleaseStringUTFChars(jniEnv, jepName, epName); - free((void*)keyArray); - free((void*)valueArray); - free((void*)jkeyArray); - free((void*)jvalueArray); } + +#undef ORT_JAVA_MAX_ARGUMENT_ARRAY_LENGTH