interface dispatch

Godmar Back gback@cs.utah.edu
Sun Oct 24 09:38:00 GMT 1999


> 
> Godmar Back <gback@cs.utah.edu> writes:
> 
> > In an earlier discussion, I pointed out that the correct way to compile
> > 
> > interface A {}
> > f(A x) {
> > 	x.equals(...)
> > }
> > 
> > is by using "invokeinterface" as opposed to "invokevirtual", and that the
> > correct run-time semantics is
> > 
> > 	checkcast A
> > 	invokevirtual "equals"
> 
> Yes, you said that, but I really want to see an explanation
> before I buy it.  My understanding is that checkcast are
> only needed when a source cast is needed.

There's two parts to it:

- an explanation that you must compile the above construct using
  invokeinterface and not invokevirtual in your .java -> .class compiler.
  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, which is an interface,
hence the invocation mode is interface, which is expressed by choosing
the invokeinterface bytecode instruction.

Or,
- an explanation that you can treat the invokeinterface as a sequence
  of checkcast/invokevirtual.  See JLS

  15.11.4 Runtime Evaluation of Method Invocation
  ...
  15.11.4.1 Compute Target Reference (If Necessary)
  ...	(this is "this" in this case)
  15.11.4.3 Check Accessibility of Type and Method
  ...
  If the invocation mode is interface, then the virtual machine must also 
  check that the target reference type still implements the specified 
  interface.  If the target reference type does not still implement the 
  interface, then an IncompatibleClassChangeError occurs.
  ...
  15.11.4.4 Locate Method to Invoke
  ... 
  If the invocation mode is interface or virtual...
  [ just note that it's the same for interface as it is for virtual ]


So, I actually think we're back to the verifier implementation here.

If your verifier can prove that "f(_)" is never invoked with *any* object
that does not implement A, you may omit the type check.
If you cannot, you must check at run-time and you cannot simply invoke 
the "equals" method.

[Obviously,] *any* checkcast that a verifier/analyser can prove to always 
succeed is unnecessary and can be eliminated.

I prefer to look at it such that replacing this invokeinterface
with checkcast/invokevirtual preserves the semantics as demanded by the JLS---
then being able to omit the run-time type check in the checkcast is a
clever optimization that would be enabled by a more sophisticated verifier
design.

	- Godmar



More information about the Java mailing list