Rejigger flushExec implementation (#8562, #8561)
authorAustin Seipp <austin@well-typed.com>
Tue, 26 Nov 2013 09:31:30 +0000 (03:31 -0600)
committerAustin Seipp <austin@well-typed.com>
Wed, 27 Nov 2013 01:29:57 +0000 (19:29 -0600)
Instead, just don't do anything on x86/amd64, and on !x86, use either A)
__clear_cache from libgcc, or B) sys_icache_invalidate for OS X (and
iOS.)

Signed-off-by: Austin Seipp <austin@well-typed.com>
rts/sm/Storage.c

index c1a1a5a..b5f3202 100644 (file)
@@ -1152,13 +1152,29 @@ AdjustorWritable allocateExec (W_ bytes, AdjustorExecutable *exec_ret)
     return (ret + 1);
 }
 
+#if defined(arm_HOST_ARCH) && defined(ios_HOST_OS)
+void sys_icache_invalidate(void *start, size_t len);
+#endif
+
+/* On ARM and other platforms, we need to flush the cache after
+   writing code into memory, so the processor reliably sees it. */
 void flushExec (W_ len, AdjustorExecutable exec_addr)
 {
-  /* On ARM and other platforms, we need to flush the cache after
-     writing code into memory, so the processor reliably sees it. */
+#if defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)
+  /* x86 doesn't need to do anything, so just suppress some warnings. */
+  (void)len;
+  (void)exec_addr;
+#elif defined(arm_HOST_ARCH) && defined(ios_HOST_OS)
+  /* On iOS we need to use the special 'sys_icache_invalidate' call. */
+  sys_icache_invalidate(exec_addr, ((unsigned char*)exec_addr)+len);
+#elif defined(__GNUC__)
+  /* For all other platforms, fall back to a libgcc builtin. */
   unsigned char* begin = (unsigned char*)exec_addr;
   unsigned char* end   = begin + len;
-  __builtin___clear_cache(begin, end);
+  __clear_cache((void*)begin, (void*)end);
+#else
+#error Missing support to flush the instruction cache
+#endif
 }
 
 // freeExec gets passed the executable address, not the writable address.