From 00052416994c53efdce31c181d3536c83dec28ef Mon Sep 17 00:00:00 2001 From: Anthony Shoumikhin Date: Thu, 24 Apr 2025 20:54:32 -0700 Subject: [PATCH 1/6] Use a strong NSError when returning from methods with nested autoreleasepool Otherwise, the output NSError arg get assigned an autoreleasing NSError object that gets deallocated when the nested autorelease pool is drained and no error is reported --- .../runtime/delegate/ETCoreMLModelManager.mm | 86 ++++++++++--------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm b/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm index c6da7750a11..346d63bea99 100644 --- a/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm +++ b/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm @@ -728,6 +728,8 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle args.count); return NO; } + NSError *localError = nil; + NSArray *modelOutputs = nil; @autoreleasepool { NSArray *inputs = [args subarrayWithRange:NSMakeRange(0, model.orderedInputNames.count)]; NSArray *outputs = [args subarrayWithRange:NSMakeRange(model.orderedInputNames.count, args.count - model.orderedInputNames.count)]; @@ -736,19 +738,22 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle outputBackings = outputs; } - NSArray *modelOutputs = [self executeModelUsingExecutor:executor - inputs:inputs - outputBackings:outputBackings - loggingOptions:loggingOptions - eventLogger:eventLogger - error:error]; - if (!modelOutputs) { - return NO; + modelOutputs = [self executeModelUsingExecutor:executor + inputs:inputs + outputBackings:outputBackings + loggingOptions:loggingOptions + eventLogger:eventLogger + error:error]; + if (modelOutputs) { + ::set_outputs(outputs, modelOutputs); } - - ::set_outputs(outputs, modelOutputs); } - + if (!modelOutputs) { + if (error) { + *error = localError; + } + return NO; + } return YES; } @@ -777,40 +782,41 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle std::vector inputArgs(argsVec.begin(), argsVec.begin() + model.orderedInputNames.count); std::vector outputArgs(argsVec.begin() + model.orderedInputNames.count, argsVec.end()); + NSError *localError = nil; + NSArray *modelOutputs = nil; @autoreleasepool { NSArray *inputs = [model prepareInputs:inputArgs error:error]; - if (!inputs) { - return NO; - } - - NSArray *outputBackings = @[]; - if (executor.ignoreOutputBackings == NO) { - outputBackings = [model prepareOutputBackings:outputArgs error:error]; - } - - if (!outputBackings) { - return NO; - } - - NSArray *modelOutputs = [self executeModelUsingExecutor:executor - inputs:inputs - outputBackings:outputBackings - loggingOptions:loggingOptions - eventLogger:eventLogger - error:error]; - if (!modelOutputs) { - return NO; + if (inputs) { + NSArray *outputBackings = @[]; + if (executor.ignoreOutputBackings == NO) { + outputBackings = [model prepareOutputBackings:outputArgs error:error]; + } + if (outputBackings) { + modelOutputs = [self executeModelUsingExecutor:executor + inputs:inputs + outputBackings:outputBackings + loggingOptions:loggingOptions + eventLogger:eventLogger + error:error]; + if (!modelOutputs) { + // Resize for dynamic shapes + for (int i = 0; i < outputArgs.size(); i++) { + auto new_size = to_vector(modelOutputs[i].shape); + outputArgs[i].resize(new_size); + argsVec[model.orderedInputNames.count + i].resize(new_size); + } + ::set_outputs(outputArgs, modelOutputs); + } + } } - - // Resize for dynamic shapes - for (int i = 0; i < outputArgs.size(); i++) { - auto new_size = to_vector(modelOutputs[i].shape); - outputArgs[i].resize(new_size); - argsVec[model.orderedInputNames.count + i].resize(new_size); + } + if (!modelOutputs) { + if (error) { + *error = localError; } - ::set_outputs(outputArgs, modelOutputs); - return YES; + return NO; } + return YES; } - (BOOL)unloadModelWithHandle:(ModelHandle *)handle { From 89e7490e4fa5693b50155f054eb412cb2cd37020 Mon Sep 17 00:00:00 2001 From: Anthony Shoumikhin Date: Thu, 24 Apr 2025 23:00:05 -0700 Subject: [PATCH 2/6] Update MLModel_Prewarm.mm --- .../runtime/delegate/MLModel_Prewarm.mm | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/backends/apple/coreml/runtime/delegate/MLModel_Prewarm.mm b/backends/apple/coreml/runtime/delegate/MLModel_Prewarm.mm index 6a737d1e82b..45b82bd52fc 100644 --- a/backends/apple/coreml/runtime/delegate/MLModel_Prewarm.mm +++ b/backends/apple/coreml/runtime/delegate/MLModel_Prewarm.mm @@ -107,26 +107,29 @@ + (MLMultiArray *)zeroedMultiArrayWithShape:(NSArray *)shape @implementation MLModel (Prewarm) - (BOOL)prewarmUsingState:(nullable id)state error:(NSError * __autoreleasing *)error { + NSError *localError = nil; + BOOL result = NO; @autoreleasepool { - id inputs = ::get_zeroed_inputs(self, error); - if (!inputs) { - return NO; - } - - - id outputs = nil; - if (state != nil) { + id inputs = ::get_zeroed_inputs(self, &localError); + if (inputs) { + id outputs = nil; + if (state) { #if MODEL_STATE_IS_SUPPORTED - if (@available(macOS 15.0, iOS 18.0, tvOS 18.0, watchOS 11.0, *)) { - outputs = [self predictionFromFeatures:inputs usingState:(MLState *)state error:error]; - return outputs != nil; - } + if (@available(macOS 15.0, iOS 18.0, tvOS 18.0, watchOS 11.0, *)) { + outputs = [self predictionFromFeatures:inputs usingState:(MLState *)state error:&localError]; + } #endif + } + if (!outputs) { + outputs = [self predictionFromFeatures:inputs error:&localError]; + } + result = outputs != nil; } - - outputs = [self predictionFromFeatures:inputs error:error]; - return outputs != nil; } + if (!result && error) { + *error = localError; + } + return result; } From 21cd453968c2457bf96e552e68722c298b75b714 Mon Sep 17 00:00:00 2001 From: Anthony Shoumikhin Date: Thu, 24 Apr 2025 23:03:47 -0700 Subject: [PATCH 3/6] Update ETCoreMLModelAnalyzer.mm --- .../apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.mm b/backends/apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.mm index 87e086c5bbd..7d9a51fdffc 100644 --- a/backends/apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.mm +++ b/backends/apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.mm @@ -138,7 +138,8 @@ - (nullable instancetype)initWithCompiledModelAsset:(ETCoreMLAsset *)compiledMod if (!self.debugger) { return nil; } - + + NSError *localError = nil; NSArray *modelOutputs = nil; NSArray *operationPaths = self.debugger.operationPaths; NSDictionary *operationPathToDebugSymbolMap = self.debugger.operationPathToDebugSymbolMap; @@ -150,8 +151,11 @@ - (nullable instancetype)initWithCompiledModelAsset:(ETCoreMLAsset *)compiledMod options:predictionOptions inputs:inputs modelOutputs:&modelOutputs - error:error]; + error:&localError]; if (!outputs) { + if (error) { + *error = localError; + } return nil; } From 63d40b93236ac4985b2b9daa27f24df444d64e8c Mon Sep 17 00:00:00 2001 From: Anthony Shoumikhin Date: Thu, 24 Apr 2025 23:18:21 -0700 Subject: [PATCH 4/6] Update ETCoreMLModelDebugger.mm --- .../runtime/sdk/ETCoreMLModelDebugger.mm | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/backends/apple/coreml/runtime/sdk/ETCoreMLModelDebugger.mm b/backends/apple/coreml/runtime/sdk/ETCoreMLModelDebugger.mm index 1cac0de40f3..91a0b1a63fa 100644 --- a/backends/apple/coreml/runtime/sdk/ETCoreMLModelDebugger.mm +++ b/backends/apple/coreml/runtime/sdk/ETCoreMLModelDebugger.mm @@ -661,9 +661,15 @@ - (nullable ETCoreMLAsset *)compiledModelAssetWithOutputsAtPaths:(NSArray *)modelsWithOutputsOfOperationsAtPath:(NSArray *)paths error:(NSError* __autoreleasing *)error { + NSError *localError = nil; + NSArray *result = nil; @autoreleasepool { - return [self _modelsWithOutputsOfOperationsAtPath:paths error:error]; + result = [self _modelsWithOutputsOfOperationsAtPath:paths error:&localError]; + } + if (!result && error) { + *error = localError; } + return result; } - (nullable ETCoreMLModelOutputs *)outputsOfOperationsAtPaths:(NSArray *)paths @@ -671,27 +677,30 @@ - (nullable ETCoreMLModelOutputs *)outputsOfOperationsAtPaths:(NSArray)inputs modelOutputs:(NSArray *_Nullable __autoreleasing *_Nonnull)modelOutputs error:(NSError* __autoreleasing *)error { - NSArray *lModelOutputs = nil; - NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:paths.count]; + NSError *localError = nil; + BOOL success = NO; + NSArray *localModelOutputs = nil; + ETCoreMLModelOutputs *result = [NSMutableDictionary dictionaryWithCapacity:paths.count]; @autoreleasepool { - NSArray *models = [self modelsWithOutputsOfOperationsAtPath:paths error:error]; - if (!models) { - return nil; - } - - for (DebuggableModel *pair in models) { - id outputFeatures = [pair.first predictionFromFeatures:inputs options:options error:error]; - set_intermediate_outputs(outputFeatures, paths, result); - if (modelOutputs) { - set_model_outputs(outputFeatures, self.outputNames, &lModelOutputs); - } + NSArray *models = [self modelsWithOutputsOfOperationsAtPath:paths error:&localError]; + success = models != nil; + if (success) { + for (DebuggableModel *pair in models) { + id outputFeatures = [pair.first predictionFromFeatures:inputs options:options error:&localError]; + set_intermediate_outputs(outputFeatures, paths, result); + if (modelOutputs) { + set_model_outputs(outputFeatures, self.outputNames, &localModelOutputs); + } + } } } - + if (!success && error) { + *error = localError; + return nil; + } if (modelOutputs) { - *modelOutputs = lModelOutputs; + *modelOutputs = localModelOutputs; } - return result; } From c4b029d1a31223c4cc05334d91e953ed49f1328f Mon Sep 17 00:00:00 2001 From: Anthony Shoumikhin Date: Fri, 25 Apr 2025 00:09:15 -0700 Subject: [PATCH 5/6] Update ETCoreMLModelManager.mm --- .../runtime/delegate/ETCoreMLModelManager.mm | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm b/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm index 346d63bea99..567d71ffb2f 100644 --- a/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm +++ b/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm @@ -711,25 +711,27 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle loggingOptions:(const executorchcoreml::ModelLoggingOptions&)loggingOptions eventLogger:(const executorchcoreml::ModelEventLogger* _Nullable)eventLogger error:(NSError * __autoreleasing *)error { + BOOL result = NO; id executor = [self executorWithHandle:handle]; if (!executor) { ETCoreMLLogErrorAndSetNSError(error, - ETCoreMLErrorInternalError, - "Model is already unloaded."); - return NO; + 0, + "%@: Model is already unloaded.", + NSStringFromClass(self.class)); + return result; } - + ETCoreMLModel *model = executor.model; if (args.count != model.orderedInputNames.count + model.orderedOutputNames.count) { ETCoreMLLogErrorAndSetNSError(error, ETCoreMLErrorCorruptedModel, - "Model is invalid, expected args count to be %lu but got %lu.", + "%@: Model is invalid, expected args count to be %lu but got %lu.", + NSStringFromClass(self.class), static_cast(model.orderedInputNames.count + model.orderedOutputNames.count), args.count); - return NO; + return result; } NSError *localError = nil; - NSArray *modelOutputs = nil; @autoreleasepool { NSArray *inputs = [args subarrayWithRange:NSMakeRange(0, model.orderedInputNames.count)]; NSArray *outputs = [args subarrayWithRange:NSMakeRange(model.orderedInputNames.count, args.count - model.orderedInputNames.count)]; @@ -737,24 +739,23 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle if (executor.ignoreOutputBackings == NO) { outputBackings = outputs; } - - modelOutputs = [self executeModelUsingExecutor:executor - inputs:inputs - outputBackings:outputBackings - loggingOptions:loggingOptions - eventLogger:eventLogger - error:error]; + NSArray *modelOutputs = [self executeModelUsingExecutor:executor + inputs:inputs + outputBackings:outputBackings + loggingOptions:loggingOptions + eventLogger:eventLogger + error:&localError]; if (modelOutputs) { ::set_outputs(outputs, modelOutputs); + result = YES; } } - if (!modelOutputs) { + if (!result) { if (error) { *error = localError; } - return NO; } - return YES; + return result; } - (BOOL)executeModelWithHandle:(ModelHandle *)handle @@ -762,43 +763,43 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle loggingOptions:(const executorchcoreml::ModelLoggingOptions&)loggingOptions eventLogger:(const executorchcoreml::ModelEventLogger* _Nullable)eventLogger error:(NSError * __autoreleasing *)error { + BOOL result = NO; id executor = [self executorWithHandle:handle]; if (!executor) { ETCoreMLLogErrorAndSetNSError(error, - ETCoreMLErrorInternalError, - "Model is already unloaded."); - return NO; + 0, + "%@: Model is already unloaded.", + NSStringFromClass(self.class)); + return result; } - ETCoreMLModel *model = executor.model; if (argsVec.size() != model.orderedInputNames.count + model.orderedOutputNames.count) { ETCoreMLLogErrorAndSetNSError(error, ETCoreMLErrorCorruptedModel, - "Model is invalid, expected args count to be %lu but got %lu.", + "%@: Model is invalid, expected args count to be %lu but got %lu.", + NSStringFromClass(self.class), static_cast(model.orderedInputNames.count + model.orderedOutputNames.count), argsVec.size()); - return NO; + return result; } - std::vector inputArgs(argsVec.begin(), argsVec.begin() + model.orderedInputNames.count); std::vector outputArgs(argsVec.begin() + model.orderedInputNames.count, argsVec.end()); NSError *localError = nil; - NSArray *modelOutputs = nil; @autoreleasepool { - NSArray *inputs = [model prepareInputs:inputArgs error:error]; + NSArray *inputs = [model prepareInputs:inputArgs error:&localError]; if (inputs) { NSArray *outputBackings = @[]; if (executor.ignoreOutputBackings == NO) { - outputBackings = [model prepareOutputBackings:outputArgs error:error]; + outputBackings = [model prepareOutputBackings:outputArgs error:&localError]; } if (outputBackings) { - modelOutputs = [self executeModelUsingExecutor:executor - inputs:inputs - outputBackings:outputBackings - loggingOptions:loggingOptions - eventLogger:eventLogger - error:error]; - if (!modelOutputs) { + NSArray *modelOutputs = [self executeModelUsingExecutor:executor + inputs:inputs + outputBackings:outputBackings + loggingOptions:loggingOptions + eventLogger:eventLogger + error:&localError]; + if (modelOutputs) { // Resize for dynamic shapes for (int i = 0; i < outputArgs.size(); i++) { auto new_size = to_vector(modelOutputs[i].shape); @@ -806,17 +807,17 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle argsVec[model.orderedInputNames.count + i].resize(new_size); } ::set_outputs(outputArgs, modelOutputs); + result = YES; } } } } - if (!modelOutputs) { + if (!result) { if (error) { *error = localError; } - return NO; } - return YES; + return result; } - (BOOL)unloadModelWithHandle:(ModelHandle *)handle { From a825597a4e7a41a68e679dfafbb19dfdfb972e00 Mon Sep 17 00:00:00 2001 From: Anthony Shoumikhin Date: Fri, 25 Apr 2025 00:13:45 -0700 Subject: [PATCH 6/6] Update ETCoreMLModelManager.mm --- .../runtime/delegate/ETCoreMLModelManager.mm | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm b/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm index 567d71ffb2f..a64d977bb26 100644 --- a/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm +++ b/backends/apple/coreml/runtime/delegate/ETCoreMLModelManager.mm @@ -715,9 +715,8 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle id executor = [self executorWithHandle:handle]; if (!executor) { ETCoreMLLogErrorAndSetNSError(error, - 0, - "%@: Model is already unloaded.", - NSStringFromClass(self.class)); + ETCoreMLErrorInternalError, + "Model is already unloaded."); return result; } @@ -725,8 +724,7 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle if (args.count != model.orderedInputNames.count + model.orderedOutputNames.count) { ETCoreMLLogErrorAndSetNSError(error, ETCoreMLErrorCorruptedModel, - "%@: Model is invalid, expected args count to be %lu but got %lu.", - NSStringFromClass(self.class), + "Model is invalid, expected args count to be %lu but got %lu.", static_cast(model.orderedInputNames.count + model.orderedOutputNames.count), args.count); return result; @@ -767,17 +765,15 @@ - (BOOL)executeModelWithHandle:(ModelHandle *)handle id executor = [self executorWithHandle:handle]; if (!executor) { ETCoreMLLogErrorAndSetNSError(error, - 0, - "%@: Model is already unloaded.", - NSStringFromClass(self.class)); + ETCoreMLErrorInternalError, + "Model is already unloaded."); return result; } ETCoreMLModel *model = executor.model; if (argsVec.size() != model.orderedInputNames.count + model.orderedOutputNames.count) { ETCoreMLLogErrorAndSetNSError(error, ETCoreMLErrorCorruptedModel, - "%@: Model is invalid, expected args count to be %lu but got %lu.", - NSStringFromClass(self.class), + "Model is invalid, expected args count to be %lu but got %lu.", static_cast(model.orderedInputNames.count + model.orderedOutputNames.count), argsVec.size()); return result;