RFR: JDK-8213199: GC abstraction for Assembler::needs_explicit_null_check()
Roman Kennke
rkennke at redhat.com
Wed Nov 7 14:51:58 UTC 2018
Hi Erik,
> The approach looks great! :p
Ha! :-)
> Looks like "you" forgot to call the new function in os_solaris_sparc.cpp
> though, he he. With that fixed, we pass tier1-3 on our platforms.
> Oh and the cast in the following line is unnecessary: intptr_t start =
> (intptr_t)-cell_header_size;
Both fixed here (solaris/sparc stuff blindly though):
Incremental:
http://cr.openjdk.java.net/~rkennke/JDK-8213199/webrev.03.diff
Full:
http://cr.openjdk.java.net/~rkennke/JDK-8213199/webrev.03/
Good now?
Thanks for reviewing and helping!
Roman
> Thanks,
> /Erik
>
> On 2018-11-07 09:52, Roman Kennke wrote:
>> Alright! thanks Erik! So here I'd like to propose your version plus my
>> little fixes for review:
>>
>> http://cr.openjdk.java.net/~rkennke/JDK-8213199/webrev.02/
>>
>> It passes hotspot/jtreg:tier1 locally on x86 and aarch64 and works with
>> Shenandoah too (and passes the Shenandoah testsuites)
>>
>> Good?
>>
>> Roman
>>
>>
>>> Hi Roman,
>>>
>>> Glad you liked the idea!
>>>
>>> On 2018-11-06 22:37, Roman Kennke wrote:
>>>> Hi Erik,
>>>>
>>>> I also like it. I needed to change a little bit to make it work with
>>>> Shenandoah:
>>>>
>>>> http://cr.openjdk.java.net/~rkennke/JDK-8213199/JDK-8213199-eosterlund.patch
>>>>
>>>>
>>>>
>>>> I will give it a spin on aarch64 as soon as I get access to the
>>>> machine.
>>>>
>>>> Do you want to take the bug and finish it, or do you want me to take it
>>>> from here?
>>> You can take it from here. I just wanted to show a possible direction.
>>>
>>> Thanks,
>>> /Erik
>>>
>>>> Roman
>>>>
>>>>> Hi Andrew,
>>>>>
>>>>> On 2018-11-06 17:46, Andrew Dinn wrote:
>>>>>> On 06/11/18 16:04, Erik Österlund wrote:
>>>>>>> New webrev:
>>>>>>> http://cr.openjdk.java.net/~eosterlund/8213199/webrev.01/
>>>>>> Thanks for the updated version.
>>>>>>
>>>>>>> On 2018-11-06 16:13, Andrew Dinn wrote:
>>>>>>>> In that case, I hear you ask, why does the old code check for
>>>>>>>> values in
>>>>>>>> the range [heap_base - cell_header_size, heap_base +
>>>>>>>> os::vm_page_size)?
>>>>>>>> Good question. I don't know the answer. I think that test is bogus
>>>>>>>> with
>>>>>>>> no Shenandoah GC present.
>>>>>>> Interesting. It turns out that both ranges are relevant
>>>>>>> [-cell_header_size, os::vm_page_size) and [heap_base -
>>>>>>> cell_header_size,
>>>>>>> heap_base + os::vm_page_size). Looks like we both missed that
>>>>>>> from the
>>>>>>> original check.
>>>>>>> I updated my webrev to explicitly reflect those two ranges, as two
>>>>>>> different checks.
>>>>>> Well, you say that but -- as I said before -- I am not sure why
>>>>>> *both*
>>>>>> are relevant to the non-Shenandoah case. And, given Roman's
>>>>>> correction
>>>>>> (doh, yes of course! the space for the Brooks pointer field had
>>>>>> better
>>>>>> lie in RW-mapped memory :-) I don't see why it is relevant to the
>>>>>> Shenandoah case either.
>>>>> The reason it is needed is because there may or may not be null checks
>>>>> in both the decode() step to get the base pointer of an access, and
>>>>> the
>>>>> access itself, given some base pointer. This results in two ranges for
>>>>> those two cases correspondingly. If the decoding uses decode_not_null,
>>>>> with an implicit null check in the decoding itself that blindly
>>>>> adds the
>>>>> heap base without checking for null, we will crash into the first page
>>>>> of the heap which is protected when performing accesses into that. But
>>>>> sometimes we have a decode()ed base pointer (with null check), that
>>>>> has
>>>>> already been fixed up to NULL, and then perform an access at an offset
>>>>> into that with an implicit null check. This results in a trap at the
>>>>> first page. So in summary, both ranges are needed because the
>>>>> implicitness of the null check may be both in the access and the
>>>>> narrowOop decoding.
>>>>>
>>>>> But as I pointed out, this (seemingly incorrectly) assumes there
>>>>> may not
>>>>> be any offset values in the (heap_base, heap_base + os::vm_page_size)
>>>>> range. If you hit such an offset, we will generate incorrect code, due
>>>>> to the lack of distinction between addresses and offsets.
>>>>>
>>>>>> I'd be very glad to hear from someone who knows about the history of
>>>>>> the
>>>>>> original function as to why the extra test for addresses above
>>>>>> heap_base
>>>>>> is included [hint: John Rose? David Holmes? Coleen? anyone else who
>>>>>> might have been around when it was added?]
>>>>>>
>>>>>> If that check is not actually needed then getting rid of it would
>>>>>> make
>>>>>> the whole thing a lot simpler.
>>>>> It would indeed. But unfortunately we need it.
>>>>>
>>>>>>>>> Just expressing these trivial ranges separately would have been
>>>>>>>>> very
>>>>>>>>> easy to understand.
>>>>>>>> Except it's not that easy. Also, with Shenandoah there is a new
>>>>>>>> wrinkle.
>>>>>>>> It is possible for an object to be allocated at the first
>>>>>>>> non-guarded
>>>>>>>> address in the heap area i.e. heap_base + os::vm_page_size. I that
>>>>>>>> case
>>>>>>>> a dereference of its Brooks pointer will lie in the protected page.
>>>>>>> Looks like Roman just said that's not possible.
>>>>>> Yes, my dumb!
>>>>>>
>>>>>>> Fixed. Might need some help testing this on AArch64 though if we
>>>>>>> decide
>>>>>>> to go with it.
>>>>>> I am sure Roman and Aleksey can do that but if needed I will.
>>>>>>
>>>>>>> Do you agree though, that the current version that merges the
>>>>>>> address
>>>>>>> and offset case relies on offsets being smaller than the heap
>>>>>>> base for
>>>>>>> its magic check to work, and that we actually do not have such a
>>>>>>> guarantee in the VM? Apart from readability preferences, this seems
>>>>>>> like
>>>>>>> it is broken in the current form, unless there are seat belts I
>>>>>>> am not
>>>>>>> aware of. In particular, if you have an offset value that is in the
>>>>>>> virtual address range (heap_base, heap_base + os::vm_page_size()),
>>>>>>> which
>>>>>>> I argue can happen, then it looks like we will normalize that as
>>>>>>> if it
>>>>>>> was an address (even though it is not), and incorrectly say that
>>>>>>> this
>>>>>>> offset does not need explicit null checks, despite needing explicit
>>>>>>> null
>>>>>>> checks.
>>>>>> Well, without the answer as to whether the check against heap_base is
>>>>>> needed I am not sure. Assuming it is then then ...
>>>>>>
>>>>>> Yes, it is possible, in theory, that an oop offset could turn out to
>>>>>> have value (heap_base + D) where 0 <= D < os_page_size(). In that
>>>>>> case
>>>>>> the offset might wrongly be classified as *not* needing a null check
>>>>>> even though it really does. I suspect it is unlikely in practice
>>>>>> given
>>>>>> how mmap hands out addresses but you never know.
>>>>>>
>>>>>> As for readibility, I think the two functions are probably clearer --
>>>>>> expecially if they stay adjacent in the source code.
>>>>> Okay, sounds like we are on the same page. I agree it is unlikely that
>>>>> this will crash the VM (as evidenced by the lack of crashes observed).
>>>>> But I don't like relying on luck for correctness.
>>>>>
>>>>> Thanks,
>>>>> /Erik
>>>>>
>>>>>> regards,
>>>>>>
>>>>>>
>>>>>> Andrew Dinn
>>>>>> -----------
>>>>>> Senior Principal Software Engineer
>>>>>> Red Hat UK Ltd
>>>>>> Registered in England and Wales under Company Registration No.
>>>>>> 03798903
>>>>>> Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander
>>>>>>
>
More information about the hotspot-dev
mailing list