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