diff options
-rw-r--r-- | compiler/ghci/ByteCodeItbls.lhs | 23 | ||||
-rw-r--r-- | includes/rts/storage/GC.h | 1 | ||||
-rw-r--r-- | rts/Linker.c | 1 | ||||
-rw-r--r-- | rts/sm/Storage.c | 33 |
4 files changed, 53 insertions, 5 deletions
diff --git a/compiler/ghci/ByteCodeItbls.lhs b/compiler/ghci/ByteCodeItbls.lhs index 0d07be5f67..2180f87091 100644 --- a/compiler/ghci/ByteCodeItbls.lhs +++ b/compiler/ghci/ByteCodeItbls.lhs @@ -226,6 +226,20 @@ mkJumpToAddr dflags a = case platformArch (targetPlatform dflags) of , 0x47ff041f -- nop , fromIntegral (w64 .&. 0x0000FFFF) , fromIntegral ((w64 `shiftR` 32) .&. 0x0000FFFF) ] + + ArchARM { } -> + -- Generates Thumb sequence, + -- ldr r1, [pc, #0] + -- bx r1 + -- + -- which looks like: + -- 00000000 <.addr-0x8>: + -- 0: 4900 ldr r1, [pc] ; 8 <.addr> + -- 4: 4708 bx r1 + let w32 = fromIntegral (ptrToInt a) :: Word32 + in Left [ 0x49, 0x00 + , 0x47, 0x08 + , byte0 w32, byte1 w32, byte2 w32, byte3 w32] arch -> panic ("mkJumpToAddr not defined for " ++ show arch) @@ -374,11 +388,16 @@ load = do addr <- advance newExecConItbl :: DynFlags -> StgConInfoTable -> IO (FunPtr ()) newExecConItbl dflags obj = alloca $ \pcode -> do - wr_ptr <- _allocateExec (fromIntegral (sizeOfConItbl dflags obj)) pcode + let sz = fromIntegral (sizeOfConItbl dflags obj) + wr_ptr <- _allocateExec sz pcode ex_ptr <- peek pcode pokeConItbl dflags wr_ptr ex_ptr obj + _flushExec sz ex_ptr -- Cache flush (if needed) return (castPtrToFunPtr ex_ptr) foreign import ccall unsafe "allocateExec" - _allocateExec :: CUInt -> Ptr (Ptr a) -> IO (Ptr a) + _allocateExec :: CUInt -> Ptr (Ptr a) -> IO (Ptr a) + +foreign import ccall unsafe "flushExec" + _flushExec :: CUInt -> Ptr a -> IO () \end{code} diff --git a/includes/rts/storage/GC.h b/includes/rts/storage/GC.h index 813349610c..f8b8afe328 100644 --- a/includes/rts/storage/GC.h +++ b/includes/rts/storage/GC.h @@ -161,6 +161,7 @@ typedef void* AdjustorWritable; typedef void* AdjustorExecutable; AdjustorWritable allocateExec(W_ len, AdjustorExecutable *exec_addr); +void flushExec(W_ len, AdjustorExecutable exec_addr); #if defined(ios_HOST_OS) AdjustorWritable execToWritable(AdjustorExecutable exec); #endif diff --git a/rts/Linker.c b/rts/Linker.c index 77943a5402..14ebac3683 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1350,6 +1350,7 @@ typedef struct _RtsSymbolVal { SymI_HasProto(g0) \ SymI_HasProto(allocate) \ SymI_HasProto(allocateExec) \ + SymI_HasProto(flushExec) \ SymI_HasProto(freeExec) \ SymI_HasProto(getAllocations) \ SymI_HasProto(revertCAFs) \ diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index 112ad8322a..c1a1a5a248 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -1152,7 +1152,16 @@ AdjustorWritable allocateExec (W_ bytes, AdjustorExecutable *exec_ret) return (ret + 1); } -// freeExec gets passed the executable address, not the writable address. +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. */ + unsigned char* begin = (unsigned char*)exec_addr; + unsigned char* end = begin + len; + __builtin___clear_cache(begin, end); +} + +// freeExec gets passed the executable address, not the writable address. void freeExec (AdjustorExecutable addr) { AdjustorWritable writable; @@ -1198,6 +1207,15 @@ AdjustorWritable execToWritable(AdjustorExecutable exec) return writ; } +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. */ + unsigned char* begin = (unsigned char*)exec_addr; + unsigned char* end = begin + len; + __builtin___clear_cache(begin, end); +} + void freeExec(AdjustorExecutable exec) { AdjustorWritable writ; @@ -1225,7 +1243,7 @@ AdjustorWritable allocateExec (W_ bytes, AdjustorExecutable *exec_ret) barf("allocateExec: can't handle large objects"); } - if (exec_block == NULL || + if (exec_block == NULL || exec_block->free + n + 1 > exec_block->start + BLOCK_SIZE_W) { bdescr *bd; W_ pagesize = getPageSize(); @@ -1251,6 +1269,15 @@ AdjustorWritable allocateExec (W_ bytes, AdjustorExecutable *exec_ret) return ret; } +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. */ + unsigned char* begin = (unsigned char*)exec_addr; + unsigned char* end = begin + len; + __builtin___clear_cache(begin, end); +} + void freeExec (void *addr) { StgPtr p = (StgPtr)addr - 1; @@ -1283,7 +1310,7 @@ void freeExec (void *addr) } RELEASE_SM_LOCK -} +} #endif /* mingw32_HOST_OS */ |