RFR: JDK-8199801: Finer grained primitive arrays bulk access barriers
rkennke at redhat.com
Tue Mar 20 08:57:42 UTC 2018
Currently, for any bulk access on primitive arrays (e.g. *_at_addr()
family of methods, arraycopy, and the like), we do Access::resolve() on
the base arrayOop (via arrayOopDesc::base() ). This is safe and does the
right thing, but it is overly broad. In a garbage collector like
Shenandoah, Access::resolve() would have to do a write-barrier, which is
a copy-on-write. This could lead to double-copying of potentially large
arrays, i.e. resolving the src array would copy it from from-space to
to-space, and then it needs to be copied again from src to dst. This
adds unnecessary latency to Java threads. Most of the accesses via
_at_addr() are read-accesses, and they could use a weaker read-barrier,
which only chases the forwarding pointer.
This change splits Access<>::resolve() into resolve_for_read() and
resolve_for_write(). This is then used in all the relevant places. In
- typeArrayOop::*_at_addr() accessors now differentiate between
get_*_at_addr() and put_*_at_addr(), with the get_* accessors returning
a const T* to prevent/discourage writing to them. This percolates a
little bit through the code base, but in a positive sense (i.e. can use
all the utf8 methods with const arrays now).
- The part in c1_Runtime1.cpp will have to be rebased/eliminated once
Erik's patch goes in.
- arrayOopDesc::base_raw() and objArrayOopDesc::base_raw() go away, and
(remaining) uses replaced by ::base().
- The arraycopy stuff now calls obj_at_addr_raw() instead of
obj_at_addr(). The reason for this is that the actual objects are better
resolved in HeapAccess<>::arraycopy() methods, and the pointer passed
into it must really be within the array that's also passed in, and not
in another copy.
- objArrayOopDesc::atomic_compare_exchange_oop() now uses
oop_atomic_cmpxchg_at() ... the existing version does not allow to
resolve the target object. (this is only related in that it eliminates a
last remaining use of obj_at_addr()).
- oopDesc::field_addr() is only used in one place (DependencyContext)
which should be refactored to use proper oopDesc accessors, and then
field_addr() can be eliminated too. For now it uses resolve_for_write(),
b/c DependencyContext may write to the field.
- I noticed a bunch of memcpy() around the _at_addr() calls (e.g. in
jni.cpp).. I wonder if they should be replaced by corresponding Copy::
- jvmtiTagMap.cpp has an odd one:
- // Don't use char_at_addr(0) if length is 0
- value = (jchar*) s_value->base(T_CHAR);
+ value = s_value->get_char_at_addr(0);
In my mind, base(T_CHAR) should be equivalent to get_char_at_addr(0),
both return the address of the first element. I don't see the point. I
can see why we are not going into possible latin1 inflation for length==0.
- I refactored some stuff in heapDumper to accept const void* instead of
void* in write_raw().
Tests: build fastdebug/release (with+w/o PCH), passes hotspot/tier1
What do you think? Can I please get reviews?
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 836 bytes
Desc: OpenPGP digital signature
More information about the hotspot-gc-dev