access modes for pointers and memory regions
John Rose
john.r.rose at oracle.com
Tue Jan 22 22:45:18 UTC 2019
On Jan 22, 2019, at 1:56 PM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>
> Thanks for the great analysis.
>
> I have few questions...
>
> You say that we have AccessFlags on both Pointer and MemoryRegion, but in reality pointer does not really have such a flag. When you do Pointer::asReadOnly, all you get is a new pointer which points to a memory region that is the copy of the existing one, but with read-only access.
>
> So, I'd say the current model is essentially that of having a single access flag on memory region. The fact that memory region is not exposed in the API is one of the reasons as to why the 'asReadOnly' methods ended up in pointer.
Yes, the mode is (a) exposed only indirectly, and (b) deferred
to the memory region by a BoundedPointer. If the pointer
exposed its MR as a first-class entity, then it would be clear
that the mode is on the MR only. As it is, the AM type is
coupled to both APIs, even though it appears in only one
implementation.
The more important point is that AMs are always relative
to a capability, never absolute on a memory segment,
and this is where the disconnect is when we try to reason
about safe immutability. In terms of C-like languages,
"immutable" is not the same as "const".
> I agree that, in principle, we might have R/W/RW on pointers too - where perhaps what happens is that they affect dereference operations (e.g. Pointer::set will fail on a R pointer, regardless of the underlying memory being RW).
I'm not proposing that; what I really want is a way to make
and check immutable copies. And that seems to require
a fourth access type, when you do the math. I could see
painting that bikeshed several ways: IMMUTABLE,
GLOBAL_READ, ABSOLUTE_READ, READ_ONLY, etc.
Also there could be (as I suggested) a relative R/W/RW
mode flag on view objects as distinct from the absolute R/RW
mode flag on content objects. But the concept of content
object is surprisingly slippery, so I prefer (at the moment)
the idea of folding the immutable state into the views.
It also allows the owner of a view to query that view,
asking whether the view is immutable. This query is
(as we all know) a key building block for efficiently
managing defensive copies.
> To be honest, I don't like where the code is right now, and I'm also not a fan of the 'immutable' access flag.
Yeah, I'm not surprised. It's certainly different from
how we think about file or virtual memory permissions.
But see the D language, which uses this concept pretty
well, by distinguishing between immutable and const
pointers. We are not bound to primarily C or C++, but
rather to the goal of making foreign code and data
interoperate with VM code and data. And immutability
is growing to be a first-class concept in Java, even if
it is second-class in C.
You might try to put immutability "behind" the view
objects and see how that factors out. I did try that
in my present sketch, since it seemed more principled.
I ended up with the webrev code, which surfaces it
in the view access bits. But maybe you can find a
better way to submerge it again.
> The problem being that I think access mode should be a property of the pointer, as you say in the very first line of your email. So, getting a read-only view of a pointer should, I believe, _have no effects_ on the underlying memory region - it should just return a new pointer with the new capability.
I agree. A pointer is a capability to do stuff on a
segment of memory. As an eventual value type,
it has no state, and must be recopied (not modified)
to get related capabilities.
> That is, we should stop this business of recreating the memory region only to update an access flag - this is, I think, what gets in the way of offering a truly 'non-writeable' memory region (which you attempt to solve with the 'immutable' flag).
I don't see that this point follows from the previous one.
The real issue here is what is an MR and whether we
need it. I think it's a view, and we need it as distinct
from Pointers and Arrays.
>
> If memory regions had a _non-upgradeable_ R/W/RW property, then you could really allocate a memory region that is read-only, if you wanted to. Any attempt to get a write-capable pointer out of that will fail. (in other words,, you can get a pointer with access X on a memory region with access Y only if X is equal or less strict than Y).
So you want MR to "pull its weight" by serving as a descriptor of
a unique (unaliasable) segment of memory, not a view.
If it says READ_ONLY, nobody will ever write anything into
it, ever, even via tricky pointer aliases. Maybe that can
work, but I'm dubious at present; like I said, the concept
of a content object is very slippery. My money is on views,
and the question is whether P+A+MR is too many different
views or not. Can we get away with two or even one?
If so, how does it all factor out?
> So, I think that, of the two options you consider, I'm more for the quasi-independent access queries for pointer/memory region, as that seems a cleaner cut to me.
>
> But I agree with your line of reasoning - having some support for immutable memory regions seems required in order to support things like returning struct as value in the heap from native functions.
Yes, that's what prompted me to do the deep dive on these
issues. I don't want us to get caught with our hands empty
when we need something like that, because the alternatives
(user-managed returned values, mutable return values,
explicit return buffers) are known to be buggy and unpleasant.
— John
More information about the panama-dev
mailing list