[Mono-list] Announce: A .NET assembly -> native
codegenerationtool (ala ngen for MONO)
29 Jul 2002 12:59:44 +0200
On Mon, 2002-07-29 at 12:40, Zoltan.2.Varga@nokia.com wrote:
> > -----Original Message-----
> > From: ext Dietmar Maurer [mailto:email@example.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?