Hi,
On 12/07/2017 03:27 AM, Vitaly Davidovich wrote:
So kind of the opposite of WeakReference - a SuperStrongReference :).
Kidding aside, it seems like the way you’d want to encapsulate this at the
language level is via a type that the JVM intrinsically knows about; in
this way it’s similar to the reference types today.
An annotation probably does the trick when the value doesn’t escape from
the enclosing instance but I’ve no idea if that assumption covers enough
code to warrant this approach. AFAICT, if the value escapes into an
instance of another type that doesn’t annotate its field then all bets are
off.
Having a wrapper type would at least make it harder to leak the native
handle vs the annotation approach. But of course the wrapper comes with
footprint and indirection costs. Maybe Valhalla could allow exposing some
magic value type that’s a zero-cost wrapper but preserves the type
information the JIT can track?
There is a middle-ground. By (ab)using value types only and no special
JIT magic.
DirectBuffer(s) for example, could return the address not in a long, but
in a value type like the following (using valhalla MVT speak):
public __ByValue final class Address {
private final long address;
private final Object referent;
public _ValueFactory static Address create(long address, Object
referent) {
Address a = __MakeDefault Address();
a.address = address;
a.referent = referent;
return a;
}
}
DirectByteBuffer for example, would have the following address() method:
private long address;
public Address address() {
return Address.create(address, this);
}
Notice that 'address' field of Address value is encapsulated, so Java
code can't access it directly nor it needs to. Native / Unsafe methods
would be taking Address values instead of long(s), making sure the
embedded referent is kept reachable.
This is equivalent to passing the DirectBuffer reference to the native
method(s) together with the address value, but enforced by the API so
the programmer can not make a mistake. There's a lot of arithmetic going
on with addresses, inside and outside of DirectBuffer implementations.
Such arithmetic would have to be performed by the Address value type
itself, making sure the results of operations on Address values are
Address values that maintain the same referent. For example:
public __ByValue final class Address {
...
public _ValueFactory Address plus(long offset) {
Address a = __MakeDefault Address();
a.address = address + offset;
a.referent = referent;
return a;
}
...
So no magic here. Just API.
Regards, Peter