In the following code in MutableNUMASpace::ensure_parsability:
size_t touched_words = ... pointer_delta(s->end(), s->top()) ...; // where end() and top() are HeapWords.
[...]
0 HeapWord *crossing_start = align_up((HeapWord*)cur_top, os::vm_page_size());
1 HeapWord *crossing_end = align_down((HeapWord*)(cur_top + touched_words), os::vm_page_size());
2 if (crossing_start != crossing_end) {
3 // If object header crossed a small page boundary we mark the area
4 // as invalid rounding it to a page_size().
5 HeapWord *start = MAX2(align_down((HeapWord*)cur_top, page_size()), s->bottom());
6 HeapWord *end = MIN2(align_up((HeapWord*)(cur_top + touched_words), page_size()), s->end());
7 invalid = MemRegion(start, end);
cur_top is an intptr_t that gets added something in word_granularity in lines 1 and 6. That looks wrong, particularly because in the other uses of align_up and align_down cur_top is cast to HeapWord* first.
I.e. cur_top + touched_words doesn't use pointer arithmetic, so the the resulting values are too small.
This was found while working on JDK-8178489.