Version française
Home     About     Download     Resources     Contact us    
Browse thread
Internals details for cmmgen.ml
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Xavier Leroy <Xavier.Leroy@i...>
Subject: Re: Internals details for cmmgen.ml
> My main focus has been on adding small bits of code to
> asmcomp/cmmgen.ml for the new functionality.  Two of the new
> primitives (Pregionrefs and Pregionsets) need to check the protection
> bits recorded for the region before trying to access it, and somehow
> raise an exception if the access check fails.
> 
> I'm currently using the following kludge to make bad region access
> checks fail:
> 
> let region_checkaccess exp = function
>   | Reg_Read ->
>     Cifthenelse(
>       Cop(Cand, [region_prot exp; Cconst_int 1]),
>       Cconst_pointer 1,
>       Cop(Ccheckbound, [Cconst_int 0; Cconst_int 0]))
>   | Reg_Write ->
>     Cifthenelse(
>       Cop(Cand, [region_prot exp; Cconst_int 2]),
>       Cconst_pointer 1,
>       Cop(Ccheckbound, [Cconst_int 0; Cconst_int 0]))
> (* XXX Bounds check on 0 is a kludge to force exception *)
> 
> Is there a better way for me to cause an exception to be thrown at
> this point?  Do I need to fall back to a Cextcall to ask someone to
> throw an exception for me?  Or could (and should) I actually use
> Craise with arcane knowledge that a certain exception maps to a
> certain integer value?

Using a "checkbound" is perhaps the simplest solution.  Otherwise,
some system-wide exceptions such as Invalid_argument are assigned
global symbols and you don't need to guess their integer index inside
their defining module: just emit the C-- code corresponding to

        (raise (symbol "Invalid_argument") (string "my message"))

If you're really into high-performance stuff, you could fold the
permission check and the bounds check in one "checkbound" instruction.
Just arrange the "write enable" flag to be (the Caml integer) 0 if
write is allowed, and -1 if it is not.  Then, generate something like

        (checkbound (or index (write_enable_flag region) (size region)))

Although hacking cmmgen.ml is fun, you could get a more portable
implementation by writing it in ML using unsafe string accesses.
Those will happily work on any char *, not necessarily on well-formed
Caml strings.  Something like:

        external mmap : ... -> string
        type t = { data: string; length: int }

        let read_char reg idx =
          if idx < 0 || idx >= reg.length
          then raise (Invalid_argument "Region.read_char")
          else String.unsafe_get reg.data idx

It will be a bit slower, but maybe not too much.

- Xavier Leroy