Chris Lattner wrote:> > I don't think this is really the right way to go. Can you give an > example snippet of Java code that would need this and what you are > proposing? With a concrete example that shows how the lazy class > loading stuff works we can talk about different possibilities, > >Field operations in Java (getfield, putfield, getstatic, putstatic) do _not_ need what I'm proposing. What I'm proposing is just performance related (just like method patching in callbacks is an optimization in order to not call the callback everytime). Here's a simple example: consider class One: public class One { double a; } and class Two: public class Two { static double getDoubleFromOne(One arg) { return One.a; } } Here's the bytecode generated for the getDoubleFromOne method: ldarg 0 getfield "One", "a" return What happens in Java is that types are created lazily. Which means you can compile getDoubleFromOne without knowing the layout of the class One. Therefore, if you compile getDoubleFromOne without the layout information, the compiler will generate the code: r2 = arg0 r1 = getElementOffsetOf("One", "a"); return r1(r2); getElementOffsetOf will trigger resolution of the class "One" and return some offset for "a". My goal here is to avoid having the call to getElementOffsetOf for the next executions of getDoubleFromOne. One solution is to recompile getDoubleFromOne, now that we have the layout information, but this may not be desirable (increase of compilation time or what if we have many getElementOffsetOf calls in one method which belong to "if" statements, etc). What I would like to do is for getElementOffsetOf to dynamically patch the native code so that after the execution of getElementOffsetOf in the getDoubleFromOne method the native code looks like: r2 = arg0 nop return offset(r2) The problem is that getElementOffsetOf does not know where is the code for loading the field. The compiler may have move it after some instructions, or there may be some move instructions due to register spills, etc. Thus the introduction of the llvm.getfield* intrinsic :-)
On Tue, 6 Nov 2007, Nicolas Geoffray wrote:> Field operations in Java (getfield, putfield, getstatic, putstatic) do > _not_ need what I'm proposing. What I'm proposing is just performance > related (just like method patching in callbacks is an optimization in > order to not call the callback everytime). > > Here's a simple example: consider class One: > > public class One { > double a; > } > > and class Two: > public class Two { > static double getDoubleFromOne(One arg) { > return One.a; > } > } > What happens in Java is that types are created lazily. Which means you > can compile getDoubleFromOne without knowing the layout of the class > One. Therefore, if you compile getDoubleFromOne without the layout > information, the compiler will generate the code:I'm missing something here. If you lazily compile getDoubleFromOne the first time it is called, it seems like you are guaranteed to have layout information, as an instance of "One" is required to be passed in for this to run. I guess a better example would be: static double x() { (new One).a = 4; } or something like that. The best way (I think) to handle this is to either: 1. interpret the first time through the code, then jit compile after the class is loaded, or: 2. jit compile code that is slower than need be (using function calls to cause the lazy stuff to happen) and then replace it when the class is loaded. -Chris -- http://nondot.org/sabre/ http://llvm.org/
Chris Lattner wrote:> > I'm missing something here. If you lazily compile getDoubleFromOne the > first time it is called, it seems like you are guaranteed to have layout > information, as an instance of "One" is required to be passed in for this > to run. >Right, you got me ;) Thanks for giving a better example.> 1. interpret the first time through the code, then jit compile after the > class is loaded, or: >Not the best way to do: what if you have many field operations on many classes in one method? You'll interpret the function as long as all field operations are not resolved?> 2. jit compile code that is slower than need be (using function calls to > cause the lazy stuff to happen) and then replace it when the class is > loaded. >You mean replace the code at the IR level right? and then recompile the function. You then have the same issue than 1). By the way, this is a classic optimization in Java that all VMs with JIT do (sorry, I don't have links here). Nicolas> -Chris > >