[M3devel] Target.Aligned_procedures and closure markers?

Jay K jay.krell at cornell.edu
Sun Aug 30 09:45:21 CEST 2015


The agenda remains seeing if Target variables can be made constants.
The discussion in this case is more complicated and some facts are unclear.

Background:

Nested functions are a problem.In particular, if you can take their address.Taking the address of a nested function presents a problem.You are presented with two or three solutions.

 - runtime code gen   - either on the stack
   - or somewhere more expensive, possibly with garbage collection
   - possibly "templated" instead of "arbitrary"; the meaning     of this is a lot to explain -- related to libffi and mremap, which    isn't entirely portable, but is e.g. portable to Windows 

  - or instead of runtime codegen, altering how function pointers are    called; you can only do this from Modula-3 code, not e.g. C or C++.

The solution Modula-3 has taken is to alter how funtion pointers are called.The sequence is roughly:   Check if it is a "regular" function pointer or a "closure".   If it is a "regular" function pointer, just call it.   If it is a "closure", it contains a function pointer and a "static link".     Call the function pointer, passing the static link.

  To tell if it is "regular" function pointer or a "closure", roughly  what is done is the data at the function pointer is read and compared  against a marker value. If it equals the marker value, it is a closure.

  The size of the marker is the size of an integer or pointer (4 or 8 bytes).  The value of the marker checked for is 0 or -1, I'd have to check.  The alignment of the pointer might be a factor. In particular, on most  architectures, all instructions have a certain alignment. If the pointer has  less alignment, it can't be an instruction. Or maybe on those architectures,  the bytes are read one at a time to avoid alignment faults. 

  In particular, as far as I know, the following:   x86/amd64: no alignment of instructions, but functions maybe, but Modula-3 assumes functions aren't aligned 
   ppc32/ppc64/alpha32/alpha64/mips32/mipa64/sparc32/sparc64/arm64/hppa32/hppa64 -- instructions are all    4 bytes and 4 byte aligned, so functions are at least also as much
   arm32 -- instructions are 2 or 4 bytes; if they are 2 bytes, then the instruction    pointer is actually odd as well, and the low bit is removed to really find the instructions    That is -- instruction pointer is either odd or 4-aligned, never 2-aligned.
   ia64 -- instructions come in bundles of 3, they are 41 bits each, with a 5 bit "template" in each    bundle, for a total of 128 bits per bundle, likely always 128-bit-aligned

  I could use confirmation on much of this.

  I find the use of a marker value a little dubious. It'd be good to research if there is one  value that works on all.

  I find the choice of a marker size to be pointer-sized dubious on most platforms.  In particular, most 64bit platforms have a 32bit instruction size, so using more than 32 bits  for the marker value doesn't buy much. If the marker value is actually a legal instruction,  then checking for two in a row reduces the odds of a false positive. 

  However, given that the closure is a marker and two pointers, it isn't like you are going  to pack the second and third 64bit field right up against a 32bit field. You'd want padding for alignmet.

  If we are aiming for all out target-specificity, I'd suggest marker size be a target aspect,  and set it to 4 bytes for ppc64/mips64/sparc64/alpha64/arm64/hppa64.

  However, I want less target-variation not more.

  Here are some my lingering questions:    - Is the marker value actually invalid code on every platform? Does its value need to be target-specific?    - Is a 64bit marker value actually sufficient on IA64?      The way to help here, I think, is to ensure that a 64bit marker,      not a 128bit marker, contains the "template", and an invalid "template".   - Barring the previous, a solution might be to use a 128 bit marker on all platforms.

 i believe all of these function pointers are rare. I hope/believe the object method calls do not check for closures -- though actually  that is related to a useful language construct, that I doubt we have.

  The simplest solution is likely:    - ignore IA64, or research it further     - keep marker size at integer    - for the C backend, assume no alignment of function pointers -- give up      any of the optimization, esp. x86/amd64.

 For other than the C backend, maybe dial back marker size to 4 bytes for mips64/sparc64/alpha64/arm64/hppa64. While I don't like target-specificity, notice this wouldn't check linux vs. bsd vs. solaris, etc. It isn't a cross produce thing.

Thoughts?

 - Jay
 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20150830/b14c20c5/attachment-0001.html>


More information about the M3devel mailing list