Starting work on an Interface Injection prototype

John Rose John.Rose at Sun.COM
Mon Jan 26 15:00:38 PST 2009


On Jan 25, 2009, at 6:57 AM, Tobias Ivarsson wrote:

> I liked the way you used arrays to represent each extension record,  
> it ties in more easily with existing systems, such as garbage  
> collection. I defined a C++ structure for the extension records,  
> but I'll change that since I think your approach is more elegant  
> there.

Maybe not elegant, but workable; the choice is based on painful  
experience.  It is surprisingly difficult to introduce a  
fundamentally new heap node type; you have to cut in new code in many  
places.  (I'm working on a back burner project to make common cases  
of this a little easier; watch for "mixed arrays".)

> I have been thinking about one thing in the JITing phase, that I  
> have not implemented. If interfaces are marked as being injectable  
> or not, then we would not have to emit the code for looking up the  
> interface in the extension list if it's not injectable. To do this  
> the method that emits the instructions needs to have access to the  
> klass representing the interface. Is that possible? Is it desirable?

Customizing code like that is usually only done by the JIT's  
optimizer.  (Esp. the server JIT.)  The interpreter can usually  
afford (until proven otherwise!) to use the most generic code sequences.

There are five places where interface types must be checked by the JIT:

1. invokeinterface
2. instanceof
3. checkcast
4. checkcast implicit in aastore checks
5. reflective versions of 1, 2, or 3.

In cases 1, 3, and 4, there is no strong need to customize for non- 
injectable interfaces, because the cost of failure is always an  
expensive exception, so it doesn't matter if you did a useless check  
of the extension records.

In case 2, there is definitely a need for a negative supertype cache  
in class Klass.

In case 5, if there is a JIT intrinsic which folds the reflective  
idiom to a non-reflective one, then it can be reduced to one of the  
previous cases (1,2,3).  Otherwise, it is probably slow, and can be  
treated in full generality all the time.  A possible exception is  
that the negative supertype cache should be consulted for reflective  
instanceof.

Cases 4 and 5 are interesting in that the interface type being tested  
against is non-constant (aastore checks against a varying array  
element type).  In those cases, you either use full generality all  
the time, or use both code sequences, selected by a dynamic test for  
injectability.

Bottom line, per case:
1. always check for extension records
2. always use the negative cache (after fast positive tests), and  
customize the code in the JIT (GraphKit::gen_subtype_check)
3. customize in the JIT; negative cache buys nothing
4. customize in the JIT if possible; negative cache buys nothing
5. let the JIT do its thing for intrinsics; use the negative cache  
for Class.isInstance and Class.isAssignableFrom

-- John



More information about the mlvm-dev mailing list