@@ -185,6 +185,18 @@ struct trampoline_api_st {
185185
186186typedef struct trampoline_api_st trampoline_api_t ;
187187
188+ #if defined(__clang__ ) || defined(__GNUC__ )
189+ extern void __clear_cache (void * , void * );
190+ #endif
191+
192+ static void invalidate_icache (char * begin , char * end ) {
193+ #if defined(__clang__ ) || defined(__GNUC__ )
194+ return __clear_cache (begin , end );
195+ #else
196+ return ;
197+ #endif
198+ }
199+
188200static perf_status_t perf_status = PERF_STATUS_NO_INIT ;
189201static Py_ssize_t extra_code_index = -1 ;
190202static code_arena_t * code_arena ;
@@ -297,10 +309,6 @@ new_code_arena(void)
297309 memcpy (memory + i * code_size , start , code_size * sizeof (char ));
298310 }
299311 // Some systems may prevent us from creating executable code on the fly.
300- // TODO: Call icache invalidation intrinsics if available:
301- // __builtin___clear_cache/__clear_cache (depending if clang/gcc). This is
302- // technically not necessary but we could be missing something so better be
303- // safe.
304312 int res = mprotect (memory , mem_size , PROT_READ | PROT_EXEC );
305313 if (res == -1 ) {
306314 PyErr_SetFromErrno (PyExc_OSError );
@@ -311,6 +319,12 @@ new_code_arena(void)
311319 return -1 ;
312320 }
313321
322+ #if defined(__arm__ ) || defined(__arm64__ ) || defined(__aarch64__ )
323+ // Before the JIT can run a block of code that has been emitted it must invalidate
324+ // the instruction cache on some platforms like arm and aarch64.
325+ invalidate_icache (memory , memory + mem_size );
326+ #endif
327+
314328 code_arena_t * new_arena = PyMem_RawCalloc (1 , sizeof (code_arena_t ));
315329 if (new_arena == NULL ) {
316330 PyErr_NoMemory ();
0 commit comments