Hey folks,
lately I've started extending Dynalink with support for honoring the Lookup
object passed to the bootstrap methods. Just generally making sure it's
propagated through the framework is easy enough, and I'm also taking care to
ensure that language environments that don't need this (i.e. always use only
publicLookup() and/or only care about linking to public methods) don't get
worse linking performance than what's already there.
However, actually making the changes in BeanLinker for POJO linking prove to be
quite daunting… You would think I should just rely on JLS to resolve the
issues, but unfortunately there's one really big distinction between access as
described in JLS, and access as it happens with dynamic linking: with JLS, your
callee is a compile-type declared type; with dynamic linking, it's always a
run-time concrete type.
How's that problematic?
Consider these examples:
Example 1:
class C {
private f() { }
}
class D extends C {
}
Let's assume class C has an invokedynamic call site for "obj.f()", and ends up
getting an instance of D. Should it be able to invoke C.f()? I think yes.
Okay, but how about this:
class C {
private f() { }
}
class D extends C {
private f() { }
}
If C should dynamically link its call site for method "f()" and got an instance
of D, what should it invoke? Should it invoke C.f(), or should it throw an
error because D.f() exists but is not visible to it?
Okay, how about this:
class C {
private f() { }
}
class D extends C {
public f() { }
}
Intuitively, I'd want C to invoke D.f() in this situation if it'd have a call
site for f() and got an instance of D as a callee.
You might ask, wouldn't it break encapsulation somewhere? I think not, because
if the code of C is invoking something dynamically, it will not have an
expectation of that something being an instance of C, so the code better not
rely on it always being C.f() that is invoked. Fair enough?
Oh wait, but what if the dynamic call site actually specifies C.class as the
type of the 0th argument? Then you could argue the intent of the program is to
invoke C.f()? But why would a class invoke its own private member using
invokedynamic? It probably wouldn't, so I most likely shouldn't care about the
declared type of the receiver at the call site.
I'm putting these up for debate, as I'm not sure myself either what'd be the
correct approach here.
Here's another example:
Example 2:
(I'm using p1 and p2 as package prefixes)
public class p1.Base {
f() { }
}
public class p2.Derived {
}
class p1.Caller {
...
}
Imagine p1.Caller has a dynamic call site for f(), and it gets an instance of
p2.Derived as the callee. Should it be able to link to p1.Base.f() as an
invocation of f() on p2.Derived? Intuition tells me that, yes, it should --
after all, the method is declared in the p1 package even if the p2.Derived
isn't. Again, we don't rely on declared types; the call site in p1.Caller
probably says java.lang.Object as the 0th argument.
How about if p2.Derived also declares a package-private method f()?
public class p1.Base {
f() { }
}
public class p2.Derived {
f() { }
}
class p1.Caller {
...
}
Should p1.Caller's f()-invoking dynamic call site now invoke p1.Base.f() when
we supply it a p2.Derived instance as the callee, or should it throw an error
claiming p2.Derived.f() is not visible to it? I don't know the correct answer.
I lean towards invoking p1.Base.f(), but this is not nearly clear cut.
Would it make a difference if the call site in p1.Caller declared its 0th
argument to be p1.Base? (Again, why would any call site with such a specific
knowledge of the target be emitted using invokedynamic?)
Similar issues apply to protected access.
Opinions and discussion welcome.
Thanks,
Attila.
--
You received this message because you are subscribed to the Google Groups "JVM
Languages" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/jvm-languages?hl=en.