On 12/07/2017 07:22 PM, Peter Levart wrote:
On 12/07/2017 06:46 PM, Vitaly Davidovich wrote:
So no magic here. Just API.
This is an API version of Hans’s #3 approach. As he said, there’s
performance overhead and nothing guarantees that the referent is kept
alive - that’s an implementation artifact.
I think without the VM knowing about these things intrinsically it’s
not a 100% reliable solution because it’s not concretely requesting a
certain behavior.
I would say that for JNI "there’s performance overhead XOR nothing
guarantees that the referent is kept alive", because the overhead is
caused by reference parameter management that guarantees that the
referents are kept alive while the native method executes and may
access them. Can we live with such overhead? I don't know. Would have
to measure if it really presents a problem.
The magic would have to be performed by intrinsified method(s) (Unsafe
for example), but they are just few and developed by select group of
developers.
The main problem I think is not the overhead of passing referents
together with addresses to JNI functions and their overheads, but lack
of enforcement for this to be performed consistently. It's just too
easy to split the native resource from the referent that keeps it into
two parts with each having separate lifetime. API with value types
could enforce such pairs (address, referent) to be kept together until
they hit the final leaf operation which is typically a native method
where the referent(s) are either automatically kept alive or would
have to be manually, but such methods are in minority.
Regards, Peter
There's a quick solution to get rid of that overhead. Each native method
(or intrinsified leaf method such as those on Unsafe) can have a java
front end. They are in minority and kept under control. Similar to
argument validation front-ends for intrinsified methods. For example:
public class Unsafe {
public Address allocateMemory(long bytes, Object referent) {
return Address.create(allocateMemory(bytes), referent);
}
public void setMemory(Address address, long bytes, byte value) {
setMemory(/* access check absent equivalent of */
address.address, bytes, value);
Reference.reachabilityFence(/* access check absent equivalent
of */ address.referent);
}
...
Regards, Peter