Skip to content

Commit 4735f7f

Browse files
committed
up
1 parent 78a1494 commit 4735f7f

4 files changed

Lines changed: 25 additions & 25 deletions

File tree

extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,8 @@ @implementation ExecuTorchModule {
259259
//
260260
// INVARIANT: this ivar is only ever overwritten with another non-nil
261261
// BackendOptionsMap, and never reset to nil while `_module` is alive.
262-
// Resetting to nil would release the C++ map underneath `_module`'s
263-
// borrowed pointer, causing a dangling-pointer crash.
262+
// Resetting to nil would release the C++ map while `_module` still holds
263+
// a borrowed pointer into it.
264264
//
265265
// THREAD SAFETY: like the rest of `ExecuTorchModule`, write access here
266266
// is not thread-safe. The ARC retain/release on assignment is non-atomic
@@ -375,12 +375,12 @@ - (BOOL)loadMethod:(NSString *)methodName
375375
options:(ExecuTorchBackendOptionsMap *)options
376376
error:(NSError **)error {
377377
NSParameterAssert(options);
378-
// Defensively retain the options for the Module's lifetime, matching
379-
// -loadWithOptions:. Today Module::load_method consumes the pointer
380-
// synchronously and does not cache it, so retention is not strictly
381-
// required for this call. We retain anyway so that a future change to
382-
// the C++ API that caches the pointer cannot silently introduce a
383-
// dangling-pointer bug in this wrapper.
378+
// Retain the options for the Module's lifetime, matching -loadWithOptions:.
379+
// Today Module::load_method consumes the pointer synchronously and does
380+
// not cache it, so retention is not strictly required for this call.
381+
// We retain uniformly so the ObjC ownership rule is the same for both
382+
// entry points: any BackendOptionsMap handed to the Module stays alive
383+
// as long as the Module does.
384384
_loadedBackendOptions = options;
385385
const auto errorCode = _module->load_method(methodName.UTF8String,
386386
/*planned_memory=*/nullptr,

extension/apple/ExecuTorch/__tests__/ModuleTest.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ class ModuleTest: XCTestCase {
263263
XCTAssertFalse(desc.contains("0x"), "description should not include a pointer: \(desc)")
264264
}
265265

266-
// Regression test for the lazy load_method path: after load(options),
267-
// forward() triggers load_method which must still see valid backend
268-
// options. Requires a delegated model — the plain add.pte has no
269-
// delegates and so does not exercise the code path.
266+
// Exercises the full feature end-to-end against a delegated model:
267+
// load(options) installs backend options, then forward() triggers lazy
268+
// load_method which consumes them. A delegated fixture is required so
269+
// the per-delegate option lookup actually runs.
270270
func testLoadWithBackendOptionsThenExecuteOnCoreMLDelegatedModel() throws {
271271
let modelPath = try requireFixture("add_coreml", ofType: "pte")
272272
let module = Module(filePath: modelPath)
@@ -278,17 +278,17 @@ class ModuleTest: XCTestCase {
278278
])
279279
XCTAssertNoThrow(try module.load(options))
280280
// No explicit load("forward") here — exercise the lazy load_method path
281-
// that previously dereferenced a dangling LoadBackendOptionsMap.
281+
// that consumes the retained LoadBackendOptionsMap.
282282
let inputs: [Tensor<Float>] = [Tensor([1]), Tensor([1])]
283283
var outputs: [Value]?
284284
XCTAssertNoThrow(outputs = try module.forward(inputs))
285285
XCTAssertEqual(outputs?.first?.tensor(), Tensor([Float(2)]))
286286
}
287287

288-
// Regression test: calling load(_:BackendOptionsMap) twice on the same
289-
// Module must remain safe. The Module retains the most recently passed
290-
// map via ARC; the previous one is released only after the new one is
291-
// installed, so the C++ pointer it stored is always valid.
288+
// Calling load(_:BackendOptionsMap) repeatedly replaces the installed
289+
// options. The Module retains the most recently passed map via ARC; the
290+
// previous one is released only after the new one is installed, so the
291+
// C++ pointer it stored is always valid.
292292
func testRepeatedLoadWithBackendOptionsThenExecuteOnCoreMLDelegatedModel() throws {
293293
let modelPath = try requireFixture("add_coreml", ofType: "pte")
294294
let module = Module(filePath: modelPath)

extension/apple/ExecuTorch/__tests__/ObjC/ModuleTestObjC.m

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ - (nullable NSString *)requireFixture:(NSString *)name ofType:(NSString *)type {
4545
return nil;
4646
}
4747

48-
// Mirror of the Swift testLoadWithBackendOptionsThenExecuteOnCoreMLDelegatedModel
49-
// regression test, exercising the ObjC API surface directly so we don't lose
50-
// coverage if Swift overlays change. See ModuleTest.swift for the full
51-
// description of the bug class this protects against.
48+
// Mirrors the Swift testLoadWithBackendOptionsThenExecuteOnCoreMLDelegatedModel,
49+
// exercising the ObjC API surface directly so coverage does not depend on
50+
// the Swift overlays.
5251
- (void)testLoadWithOptionsThenExecuteOnCoreMLDelegatedModel {
5352
NSString *modelPath = [self requireFixture:@"add_coreml" ofType:@"pte"];
5453
if (!modelPath) return;
@@ -64,8 +63,8 @@ - (void)testLoadWithOptionsThenExecuteOnCoreMLDelegatedModel {
6463
ExecuTorchModule *module = [[ExecuTorchModule alloc] initWithFilePath:modelPath];
6564
XCTAssertTrue([module loadWithOptions:options error:&error], @"%@", error);
6665

67-
// No explicit -loadMethod: — exercise the lazy load_method path that was
68-
// the original regression site.
66+
// No explicit -loadMethod: — exercise the lazy load_method path that
67+
// consumes the retained backend options map.
6968
ExecuTorchTensor *one =
7069
[[ExecuTorchTensor alloc] initWithScalars:@[@1.0f] dataType:ExecuTorchDataTypeFloat];
7170
NSArray<ExecuTorchValue *> *outputs =

extension/apple/ExecuTorch/__tests__/resources/generate_coreml_test_models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
Currently produces:
44
- add_coreml.pte: a CoreML-delegated tensor-add model whose forward(x, y)
55
returns x + y. Used by ModuleTest.testLoadWithBackendOptionsThenExecuteOnCoreML
6-
as a regression fixture for the LoadBackendOptionsMap lifetime fix in the
7-
ObjC wrapper.
6+
to exercise the BackendOptionsMap lifetime path end-to-end against a
7+
delegated model (add.pte has no delegates, so the per-delegate option
8+
lookup path is only exercised with a delegated fixture like this one).
89
910
Usage:
1011
python extension/apple/ExecuTorch/__tests__/resources/generate_coreml_test_models.py

0 commit comments

Comments
 (0)