99package org .pytorch .executorch ;
1010
1111import android .util .Log ;
12+ import com .facebook .jni .HybridData ;
13+ import com .facebook .jni .annotations .DoNotStrip ;
1214import com .facebook .soloader .nativeloader .NativeLoader ;
1315import com .facebook .soloader .nativeloader .SystemDelegate ;
1416import java .io .File ;
2426@ Experimental
2527public class Module {
2628
29+ static {
30+ if (!NativeLoader .isInitialized ()) {
31+ NativeLoader .init (new SystemDelegate ());
32+ }
33+ // Loads libexecutorch.so from jniLibs
34+ NativeLoader .loadLibrary ("executorch" );
35+ }
36+
2737 /** Load mode for the module. Load the whole file as a buffer. */
2838 public static final int LOAD_MODE_FILE = 0 ;
2939
@@ -36,10 +46,17 @@ public class Module {
3646 /** Load mode for the module. Use memory locking and ignore errors. */
3747 public static final int LOAD_MODE_MMAP_USE_MLOCK_IGNORE_ERRORS = 3 ;
3848
39- /** Reference to the NativePeer object of this module. */
40- private NativePeer mNativePeer ;
49+ private final HybridData mHybridData ;
50+
51+ @ DoNotStrip
52+ private static native HybridData initHybrid (
53+ String moduleAbsolutePath , int loadMode , int initHybrid );
4154
42- /** Lock protecting the non-thread safe methods in NativePeer. */
55+ private Module (String moduleAbsolutePath , int loadMode , int numThreads ) {
56+ mHybridData = initHybrid (moduleAbsolutePath , loadMode , numThreads );
57+ }
58+
59+ /** Lock protecting the non-thread safe methods in mHybridData. */
4360 private Lock mLock = new ReentrantLock ();
4461
4562 /**
@@ -63,14 +80,11 @@ public static Module load(final String modelPath, int loadMode) {
6380 * @return new {@link org.pytorch.executorch.Module} object which owns the model module.
6481 */
6582 public static Module load (final String modelPath , int loadMode , int numThreads ) {
66- if (!NativeLoader .isInitialized ()) {
67- NativeLoader .init (new SystemDelegate ());
68- }
6983 File modelFile = new File (modelPath );
7084 if (!modelFile .canRead () || !modelFile .isFile ()) {
7185 throw new RuntimeException ("Cannot load model path " + modelPath );
7286 }
73- return new Module (new NativePeer ( modelPath , loadMode , numThreads ) );
87+ return new Module (modelPath , loadMode , numThreads );
7488 }
7589
7690 /**
@@ -83,10 +97,6 @@ public static Module load(final String modelPath) {
8397 return load (modelPath , LOAD_MODE_FILE );
8498 }
8599
86- Module (NativePeer nativePeer ) {
87- this .mNativePeer = nativePeer ;
88- }
89-
90100 /**
91101 * Runs the 'forward' method of this module with the specified arguments.
92102 *
@@ -96,16 +106,7 @@ public static Module load(final String modelPath) {
96106 * @return return value from the 'forward' method.
97107 */
98108 public EValue [] forward (EValue ... inputs ) {
99- try {
100- mLock .lock ();
101- if (mNativePeer == null ) {
102- Log .e ("ExecuTorch" , "Attempt to use a destroyed module" );
103- return new EValue [0 ];
104- }
105- return mNativePeer .forward (inputs );
106- } finally {
107- mLock .unlock ();
108- }
109+ return execute ("forward" , inputs );
109110 }
110111
111112 /**
@@ -118,16 +119,19 @@ public EValue[] forward(EValue... inputs) {
118119 public EValue [] execute (String methodName , EValue ... inputs ) {
119120 try {
120121 mLock .lock ();
121- if (mNativePeer == null ) {
122+ if (! mHybridData . isValid () ) {
122123 Log .e ("ExecuTorch" , "Attempt to use a destroyed module" );
123124 return new EValue [0 ];
124125 }
125- return mNativePeer . execute (methodName , inputs );
126+ return executeNative (methodName , inputs );
126127 } finally {
127128 mLock .unlock ();
128129 }
129130 }
130131
132+ @ DoNotStrip
133+ private native EValue [] executeNative (String methodName , EValue ... inputs );
134+
131135 /**
132136 * Load a method on this module. This might help with the first time inference performance,
133137 * because otherwise the method is loaded lazily when it's execute. Note: this function is
@@ -140,31 +144,36 @@ public EValue[] execute(String methodName, EValue... inputs) {
140144 public int loadMethod (String methodName ) {
141145 try {
142146 mLock .lock ();
143- if (mNativePeer == null ) {
147+ if (! mHybridData . isValid () ) {
144148 Log .e ("ExecuTorch" , "Attempt to use a destroyed module" );
145149 return 0x2 ; // InvalidState
146150 }
147- return mNativePeer . loadMethod (methodName );
151+ return loadMethodNative (methodName );
148152 } finally {
149153 mLock .unlock ();
150154 }
151155 }
152156
157+ @ DoNotStrip
158+ private native int loadMethodNative (String methodName );
159+
153160 /**
154161 * Returns the names of the methods in a certain method.
155162 *
156163 * @param methodName method name to query
157164 * @return an array of backend name
158165 */
159- public String [] getUsedBackends (String methodName ) {
160- return mNativePeer .getUsedBackends (methodName );
161- }
166+ @ DoNotStrip
167+ public native String [] getUsedBackends (String methodName );
162168
163169 /** Retrieve the in-memory log buffer, containing the most recent ExecuTorch log entries. */
164170 public String [] readLogBuffer () {
165- return mNativePeer . readLogBuffer ();
171+ return readLogBufferNative ();
166172 }
167173
174+ @ DoNotStrip
175+ private native String [] readLogBufferNative ();
176+
168177 /**
169178 * Dump the ExecuTorch ETRecord file to /data/local/tmp/result.etdump.
170179 *
@@ -173,9 +182,8 @@ public String[] readLogBuffer() {
173182 * @return true if the etdump was successfully written, false otherwise.
174183 */
175184 @ Experimental
176- public boolean etdump () {
177- return mNativePeer .etdump ();
178- }
185+ @ DoNotStrip
186+ public native boolean etdump ();
179187
180188 /**
181189 * Explicitly destroys the native Module object. Calling this method is not required, as the
@@ -186,13 +194,11 @@ public boolean etdump() {
186194 public void destroy () {
187195 if (mLock .tryLock ()) {
188196 try {
189- mNativePeer .resetNative ();
197+ mHybridData .resetNative ();
190198 } finally {
191- mNativePeer = null ;
192199 mLock .unlock ();
193200 }
194201 } else {
195- mNativePeer = null ;
196202 Log .w (
197203 "ExecuTorch" ,
198204 "Destroy was called while the module was in use. Resources will not be immediately"
0 commit comments