Hi Paulo,
Thanks for your attention. That helps a lot. But it would be nice if lightning could just "do the right thing". There is a fairly clear notion of a JIT compilation state, and these states should be completely independent. So actions on one state should affect that state only - the other states may be in different threads. Any interconnections between the states complicates the semantics, and should be avoided. For example, if the user decides to change the memory management functions, these changes should affect only subsequent states that are created. That is what one expects, in the absence of any indication otherwise. And any such exceptions to the rule should have semantic reasons: there are too many aspects of the lightning interface which have no semantic justification, they are only accidents of the implementation, That's not good design.
Another example of where the implementation is driving the semantics is the function call setup. There is no semantic reason why one cannot compose function application, in the sense that one calls other functions in the process of stacking up the arguments to a function which will operate on the results they return. So one should be able to nest calls to prepare/finish.
It would also be nice of lightning could be more intelligent about its heap use. At the moment it allocates over 50KB to compile a 50 byte function. That is 1,000 times more memory than it strictly needs. We need to refine this. The allocation block size should be configurable on a state-by-state basis. So if the user expects to compile 50k blocks of code, then they can set the block-size to 4KB, but if they are compiling small routines they can set it to 256 bytes. Another aspect of JIT that the library doesn't address is code size. I want to be able to decide for a given loop whether to unroll it. I want to unroll it to fit one cache line. So I need to know the exact size of the generated code for the body of the loop and the increment operation, _before_ I commit to emitting the code.
I think what would help is using a higher-level language. C is not suited to the kinds of list processing that you need to do to get this right. A few years ago I would have said look at GNU guile, which can be dynamically linked in to applications as a library. But guile is now so fat and sluggish it's unusable. I can't even compile it - it crashes byte-code compiling it's modules! PLT Racket is a much better scheme implementation Another possibility is to make more use of glib functions. This would give you a nice slab allocator, and a lot of portable system functions as well as the basic structures like hash tables, doubly-linked lists etc. Glib is very well written and fairly well-designed. It's definitely worth studying.
I am working on Moscow ML (see
http://livelogic.blogspot.com/) and have got a lightning interface, but Moscow ML doesn't currently link with another application as a library: it compiles only stand-alone programs with the CAML run-time. This will change, but I need lightning to do it!
Lightning is incredibly important for the whole GNU project, more important then GCC I think, and so we need to get the details right because it's going to affect hundreds of projects.