interface dispatch

Godmar Back gback@cs.utah.edu
Sun Oct 24 13:03:00 GMT 1999


 This discussion is getting kind of long, but I'm still going to
reply because I think there's still some interesting subtleties to discuss;
and who knows, at the end of the day, maybe I and other people interested
in this topic will actually learn something.
Hopefully, this may be especially true for whomever will implement interface
dispatch in gcj.
>> Godmar Back <gback@cs.utah.edu> writes:
> > > > interface A {}
> > > > f(A x) {
> > > > 	x.equals(...)
> > > > }
>> > This follows from the JLS 15.11.3:
> > 
> > 15.11.3 Compile-Time Step 3: Is the Chosen Method Appropriate?
> > ...
> > The following compile-time information is then associated with the 
> > method invocation for use at run time:
> > 	...
> > 	+ Otherwise, if the compile-time declaration is in an interface, 
> > 	 then the invocation mode is interface. 
> > 
> > Here, the compile-time declaration of x is A,
>> I believe you're misreading it. The "compile-time declaration" as
> defined at the beginning of section 15.11.3 is "the most specific
> method declaration for a method invocation". The "compile-time
> declaration of x" is not relevant to the issue at all.
>> > which is an interface,
> > hence the invocation mode is interface, which is expressed by choosing
> > the invokeinterface bytecode instruction.
>> The "most specific method" is java.lang.Object.equals(Object).
> That is the "compile-time declaration" for the method invocation.
> The compile-time declaration is "in" java.lang.Object, which is a
> class, not an interface. Thus the invocation mode is virtual,
> not interface.

I believe you're right on this one. I did misread the compile-time
declaration as that of the object being invoked, while it is in fact
the compile-time declaration of the method.
Jikes produces code according to your interpretation. 
I think the following program sums it up:
public class I {
	interface A {}
	interface B {
		boolean equals(Object _);
	}
	void f(A x) {
		x.equals(null);	// compile this into invokevirtual
	}
	void g(B x) {
		x.equals(null);	// compile this into invokeinterface
	}
}
This is btw not a far-fetched example: java.util.Map, for instance,
declares an .equals() method.
Unfortunately, I think there's still more questions:
If we leave the invocation mode aside for a second, what should the
symbolic reference contained in the bytecode instruction be in 
the function "f"?
jikes produces this
	invokevirtual MethodRef(class = "java.lang.Object"
			 NameAndType(name = "equals",
				 descriptor = "(Ljava/lang/Object;)Z"))
however, the corrected JLS says:
http://java.sun.com/docs/books/jls/clarify.html
...
 Similarly, the fourth bullet of JLS 13.1 should be corrected as follows: 
	Given a method invocation expression in a class C referencing a 
	method m declared in another class: 
	If the expression is of the form 
	 Primary.m 
	then let T be the type of Primary. T must be some reference type 
	denoting a class or interface. 
	...
-> The reference to a method or constructor must be resolved at compile 
-> time to a symbolic reference to T, plus the signature of the method or 
 constructor. A reference to a method must also include either a 
 symbolic reference to the return type of the denoted method or an 
 indication that the denoted method is declared void and does not 
 return a value.
 Here is an explanation why these corrections are necessary. 
 http://java.sun.com/docs/books/jls/public-symref-compilation-rules.html
 Obviously, much of JLS 13.4.5 must change in light of the changes 
 to JLS 13.1 and 12.3.3. 
In this case, the "type of the Primary" is the type of "x" in "f" and "g",
is it not?
It seems inconsistent to me that the invocation mode depends on the
compile-time declaration of m found in another class, while the compiler 
is obliged to insert a symbolic reference to the type of the Primary "T"
in order to avoid the problems mentioned in their rationale?
	- Godmar


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /