dotgnu-general
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [DotGNU]CVM to machine code


From: Gopal V
Subject: Re: [DotGNU]CVM to machine code
Date: Sat, 26 Jul 2003 14:42:17 +0530
User-agent: Mutt/1.2.5i

If memory serves me right, Gnanavel S wrote:
> I am a newbie to PNet.

With the speed new stuff gets added ... only the authors aren't :)

Like when I had finished understanding the original VM, rhys added CVM 
and when I finished getting a hold of it , he pushed token threading ...
and when I got a hang of what token/direct threading was , the unroller
was thrown in :)

> I did not understand clearly why should the IL instructions be converted to
> a form CVM can understand and then later CVM does the conversion to machine
> code? 

IL is polymorphic and object based , both of which add special overhead for
execution ... some opcodes are a single name for multiple operations, ie
the "add" instruction does short/integer/float/double addition, so a direct
interpreter has to check the stack to figure this out. These operations are
more CPU consuming than the actual addition operation. Also the object 
part of the problem is that storing a field to an object has to check if
the field is accessible (ie visibility) , to find the offset of the field
inside the object and finally store the stuff .

Thanks to verifiability , we already know what types are on the stack for
each instruction , so we avoid this extra overhead by generating the 
COP_IADD or COP_FADD etc... instructions . The verifiability also checks
for the field accessibility and finds the offset of the field and generates
a p_load method (ie pointer load) . This makes static fields directly
loaded off memory and instance fields loaded indirectly off the object.

Also verifier is run on the code and converts to CVM on the fly , so 
there is no extra overhead of conversion unlike JIT'ing ..

To add an extra bit of speed ,we convert some opcodes to native code
and let them pass operands via registers using the unroller.... So
this produces a huge performance gain and is relatively simple to port
as all that's needed is a list of instructions ,storing them to a
buffer accordingly and an order of register priority. It should take
less than a week of a single developer to port this to a new CPU .

http://symonds.net/~gopalv82/code/pnet-engine-2.jpg

> Will it not be in-effcient in terms of speed (comparing with JIT)?

If you are talking about a tight loop, yes ... but a JIT takes a lot
more time to convert IL  to native code. Thus in total execution time
the CVM/unroller wins out . I have some code that mono takes 3 minutes
to execute that pnet does in under 250 msec ... So real life apps will
notice little difference between this and a JIT. But find me a benchmark
that's not a tight loop ;-)

> What are benefits do we acheive here?

CVM is fast on all platforms rather than on the JIT target ... ie
the advantages of CVM are usable even in PPC or Alpha 

Speed of conversion (ie O(n) JIT)  -- also no memory is wasted to build 
a tree or any other stuff like that ..

Allows tough opcodes to be implemented in C and the easy/common ones 
are unrolled ... lets people develop a JIT incrementally from the 
unroller moving up to unrolling all instructions. Normal JITs are 
an "all or nothing" approach not suited for community development.

Speed of development -- it took rhys less than 2 weeks to do up this 
entire x86 unroller and 4 days (?) for the ARM stuff. Compare that
to the 5 months it will take for a team of 4 to get even HelloWorld 
working on a traditional design JIT (you know ;) and still not be
able to double our performance (we're almost 70% of JIT performance).

Inlining common methods into new CVM opcodes (eg COP_PREFIX_STRING_EQUALS)

Generic unroller allows a developer to simply write a new md_<cpu>.h
and get an unroller working ... rather than go through the hellishly
difficult JIT development ...

Gopal
-- 
The difference between insanity and genius is measured by success


reply via email to

[Prev in Thread] Current Thread [Next in Thread]