Skip to content

Commit

Permalink
[jit] Add support for flushing the instruction cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
bmeurer committed Nov 30, 2011
1 parent 3142c75 commit a77c03e
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/jitcomp/jitaux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ struct
external alignment: unit -> int = "camlnat_mem_alignment" "noalloc"
external reserve: int -> t = "camlnat_mem_reserve"
external prepare: t -> string -> int -> unit = "camlnat_mem_prepare" "noalloc"
external commit: t -> int -> unit = "camlnat_mem_commit"
external cacheflush: t -> int -> unit = "camlnat_mem_cacheflush" "noalloc"
external commit: t -> int -> unit = "camlnat_mem_commit" "noalloc"

let mask = alignment() - 1

Expand Down Expand Up @@ -402,6 +403,8 @@ let end_assembly() =
(* Prepare section content *)
Memory.prepare text_sec.sec_addr text_sec.sec_buf text_sec.sec_pos;
Memory.prepare data_sec.sec_addr data_sec.sec_buf data_sec.sec_pos;
(* Flush the instruction cache *)
Memory.cacheflush text_sec.sec_addr text_sec.sec_pos;
(* Register global symbols *)
List.iter
(fun sym -> Symbol.add sym (addr_of_symbol sym))
Expand Down
3 changes: 3 additions & 0 deletions src/jitrun/camlnat.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <caml/callback.h>
#include <caml/fail.h>
#include <caml/memory.h>
#ifdef __APPLE__
#include <libkern/OSCacheControl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down
55 changes: 46 additions & 9 deletions src/jitrun/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ static inline unsigned chunk_alignment()
and data on a single (64-byte) cache line (cf. "Software
Optimization Guide for the AMD64 Processor"). */
return 64;
#elif defined(__ppc__) || defined(__powerpc__)
#elif defined(_ARCH_PPC) || defined(_POWER) \
|| defined(__POWERPC__) || defined(__ppc__)
return 32;
#else
return sizeof(void *);
Expand Down Expand Up @@ -103,8 +104,8 @@ static struct chunk *chunk_alloc(intnat size)

value camlnat_mem_alignment(value dummy)
{
dummy = Val_long(chunk_alignment());
return dummy;
(void)dummy;
return Val_long(chunk_alignment());
}

value camlnat_mem_reserve(value size)
Expand Down Expand Up @@ -218,10 +219,49 @@ value camlnat_mem_prepare(value addr, value data, value size)
return Val_unit;
}

value camlnat_mem_cacheflush(value addr, value size)
{
const char *beg;
const char *end;

assert(Is_long(size));
assert(Is_block(addr));
assert(Long_val(size) >= 0);
assert((Long_val(size) % chunk_alignment()) == 0);
assert((chunklist->size % chunk_alignment()) == 0);
assert(Tag_val(addr) == Custom_tag);
assert((Nativeint_val(addr) % chunk_alignment()) == 0);

beg = (const char *)Nativeint_val(addr);
end = beg + Long_val(size);

#if defined(__APPLE__)
sys_icache_invalidate((void *)beg, end - beg);
#elif defined(_WIN32)
FlushInstructionCache(GetCurrentProcess(), beg, end - beg);
#elif (defined(_ARCH_PPC) || defined(_POWER) \
|| defined(__POWERPC__) || defined(__ppc__)) \
&& defined(__GNUC__)
assert(((uintptr_t)beg % chunk_alignment()) == 0);
assert(((uintptr_t)end % chunk_alignment()) == 0);
for (const char *ptr = beg; ptr < end; ptr += chunk_alignment())
asm volatile("dcbf 0, %0" :: "r"(ptr));
asm volatile("sync");
for (const char *ptr = beg; ptr < end; ptr += chunk_alignment())
asm volatile("icbi 0, %0" :: "r"(ptr));
asm volatile("isync");
#elif defined(__arm__) && defined(__GNUC__)
__clear_cache(beg, end);
#else
(void)beg;
(void)end;
#endif
return Val_unit;
}

value camlnat_mem_commit(value addr, value size)
{
struct chunk *chunk;
mlsize_t len;

assert(Is_long(size));
assert(Is_block(addr));
Expand All @@ -235,15 +275,12 @@ value camlnat_mem_commit(value addr, value size)
assert(chunklist->addr == Nativeint_val(addr));

chunk = chunklist;
len = Long_val(size);
// TODO - Flush icache
chunk->addr += len;
chunk->size -= len;
chunk->addr += Long_val(size);
chunk->size -= Long_val(size);
if (chunk->size < 2 * chunk_alignment()) {
/* Drop empty chunks from the list */
chunklist = chunk->next;
free(chunk);
}
return Val_unit;
}

0 comments on commit a77c03e

Please sign in to comment.