summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorAustin Seipp <austin@well-typed.com>2013-11-26 03:31:30 -0600
committerAustin Seipp <austin@well-typed.com>2013-11-26 19:29:57 -0600
commit9fbb8c788d4bdf091709778b42a1294bbdabef95 (patch)
treef5c3db21adb0f0003809c64afee1438421fbdc16 /rts
parent6279a01173152753e792674bfb30ef2f7474ef09 (diff)
downloadhaskell-9fbb8c788d4bdf091709778b42a1294bbdabef95.tar.gz
Rejigger flushExec implementation (#8562, #8561)
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>
Diffstat (limited to 'rts')
-rw-r--r--rts/sm/Storage.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index c1a1a5a248..b5f3202887 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -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.