[Mono-list] Announce: A .NET assembly -> native codegenerationtool (ala ngen for MONO)

Dietmar Maurer dietmar@ximian.com
29 Jul 2002 12:59:44 +0200


On Mon, 2002-07-29 at 12:40, Zoltan.2.Varga@nokia.com wrote:
> 
> 					Hi,
> 
> > -----Original Message-----
> > From: ext Dietmar Maurer [mailto:dietmar@ximian.com]
> > Sent: 29. July 2002 12:10
> > To: Varga Zoltan.2 (NMP/Budapest)
> > Cc: Miguel de Icaza; Mono List
> > Subject: RE: [Mono-list] Announce: A .NET assembly -> native
> > codegenerationtool (ala ngen for MONO)
> > 
> > 
> > On Mon, 2002-07-29 at 11:12, Zoltan.2.Varga@nokia.com wrote:
> > > > 
> > > >         1. It does not work with exceptions: The current code is
> > > >            incorrect because it does not save/restore the LMF when
> > > >            calling precompiled methods - but 
> > saving/restoring the LMF
> > > >            would lead to serious performance problems.
> > > 
> > > Can you explain what the LMF is? I looked at the code, but 
> > I can't understand what it is.
> > 
> > Sure. The Problem is that unmanaged code can raise exception, and we
> > must be able to recover from such exception and print a stack 
> > trace for
> > example (you can find some docu in mono/docs/exceptions). One 
> > (compiler
> > independent) way to do that is to save a data structure with all
> > necessary info on the stack each time you call an unmanaged 
> > method - we
> > call that info Last Managed Frame (MonoLMF).
> > 
> > If a exception occurs in unmanaged code we simply use the data in the
> > LMF to unwind the stack.
> > 
> 
> Since the precompiled code does not contain exception handlers, it only needs to propagate exceptions, which means restoring
> callee saved registers. This is done by examining the prelude of the function to determine which registers are saved and
> in which order, then restoring these registers from stack counting back from EBP. This works because the prelude generated
> by gcc has a simple structure (after you turn off certain optimizations). So the current code can handle exceptions without
> saving/restoring an LMF.

How do you know what code raised the exception without an LMF? Also you
cant rely on unmanaged code.

> > > 
> > > BTW: I started this as a hobby project to learn about 
> > .NET/compilers etc. I wouldn't be suprised if it turned to be unusable
> > > due to problems such as the one above...
> > 
> > Such code is always usable. If it turns out that we cant solve all
> > problems we simply need to find another Solution. But I 
> > imagine you have
> > learned a lot about mono when you wrote that code!
> > 
> > > >         2. Array bound checking: There is no array bound 
> > > > checking at the
> > > >            moment and maybe that is the only reason why 
> > it speeds up
> > > >            pnetmark? gcc is unable to do bound check 
> > removal, so array
> > > >            access will be slow (or you have to remove that 
> > > > checks before
> > > >            you emit C code).
> > > 
> > > You are right. I somehow throught that mono does not do 
> > bound checking (perhaps an earlier version didn't) so I put that
> > > on the TODO list instead of implementing it right away.
> > > 
> > > 
> > > >         3. I wonder if gcc is really able to optimize the 
> > emitted C#
> > > >            very much.
> > > > 
> > > 
> > > gcc is designed to optimize procedural code, so of course 
> > it has problems with virtual calls, bound checks, delegates etc. 
> > > But every program contains a mix of high level and low 
> > level code, so some performance gains can be expected ever for
> > > programs written in an object-oriented style such as mcs.
> > 
> > Is it difficult to implement array bound checking? If not I would like
> > to have some real benchmark results (including bound checking).
> 
> Not at all. I added bound checking to the latest snapshot and put it onto the web. I re-ran pnetmark and the mcs self
> compiling tests, but there was no noticable slowdown.

So why is it that much faster? Maybe we can improve the JIT?

- Dietmar