8337939: ZGC: Make assertions and checks less convoluted and explicit

Reviewed-by: stefank, ayang, eosterlund
This commit is contained in:
Joel Sikström 2024-08-09 07:29:56 +00:00
parent 82d5768c1b
commit f74109bd17
10 changed files with 55 additions and 31 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -93,9 +93,7 @@ static void initialize_check_oop_function() {
#ifdef CHECK_UNHANDLED_OOPS
if (ZVerifyOops) {
// Enable extra verification of usages of oops in oopsHierarchy.hpp
check_oop_function = [](oopDesc* obj) {
(void)to_zaddress(obj);
};
check_oop_function = &check_is_valid_zaddress;
}
#endif
}

@ -333,10 +333,22 @@ inline void dereferenceable_test(zaddress addr) {
}
#endif
inline zaddress to_zaddress(uintptr_t value) {
const zaddress addr = zaddress(value);
inline void check_is_valid_zaddress(zaddress addr) {
assert_is_valid(addr);
DEBUG_ONLY(dereferenceable_test(addr));
}
inline void check_is_valid_zaddress(uintptr_t value) {
check_is_valid_zaddress(zaddress(value));
}
inline void check_is_valid_zaddress(oopDesc* o) {
check_is_valid_zaddress(uintptr_t(o));
}
inline zaddress to_zaddress(uintptr_t value) {
const zaddress addr = zaddress(value);
check_is_valid_zaddress(addr);
return addr;
}
@ -344,7 +356,7 @@ inline zaddress to_zaddress(oopDesc* o) {
return to_zaddress(uintptr_t(o));
}
inline oop to_oop(zaddress addr) {
inline void assert_is_oop_or_null(zaddress addr) {
const oop obj = cast_to_oop(addr);
assert(!ZVerifyOops || oopDesc::is_oop_or_null(obj), "Broken oop: " PTR_FORMAT " [" PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT "]",
p2i(obj),
@ -352,7 +364,16 @@ inline oop to_oop(zaddress addr) {
*(uintptr_t*)(untype(addr) + 0x08),
*(uintptr_t*)(untype(addr) + 0x10),
*(uintptr_t*)(untype(addr) + 0x18));
return obj;
}
inline void assert_is_oop(zaddress addr) {
assert(!is_null(addr), "Should not be null");
assert_is_oop_or_null(addr);
}
inline oop to_oop(zaddress addr) {
assert_is_oop_or_null(addr);
return cast_to_oop(addr);
}
inline zaddress operator+(zaddress addr, size_t size) {
@ -378,7 +399,6 @@ inline void assert_is_valid(zaddress_unsafe addr) {
DEBUG_ONLY(is_valid(addr, true /* assert_on_failure */);)
}
inline uintptr_t untype(zaddress_unsafe addr) {
return static_cast<uintptr_t>(addr);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -745,7 +745,7 @@ inline void ZBarrier::mark_and_remember(volatile zpointer* p, zaddress addr) {
template <bool resurrect, bool gc_thread, bool follow, bool finalizable>
inline void ZBarrier::mark(zaddress addr) {
assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop");
assert_is_oop(addr);
if (ZHeap::heap()->is_old(addr)) {
ZGeneration::old()->mark_object_if_active<resurrect, gc_thread, follow, finalizable>(addr);
@ -757,7 +757,7 @@ inline void ZBarrier::mark(zaddress addr) {
template <bool resurrect, bool gc_thread, bool follow>
inline void ZBarrier::mark_young(zaddress addr) {
assert(ZGeneration::young()->is_phase_mark(), "Should only be called during marking");
assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop");
assert_is_oop(addr);
assert(ZHeap::heap()->is_young(addr), "Must be young");
ZGeneration::young()->mark_object<resurrect, gc_thread, follow, ZMark::Strong>(addr);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -430,7 +430,7 @@ public:
template <DecoratorSet decorators, typename BarrierSetT>
inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) {
assert_is_valid(to_zaddress(src));
check_is_valid_zaddress(src);
if (dst->is_objArray()) {
// Cloning an object array is similar to performing array copy.

@ -146,7 +146,7 @@ private:
oop load_oop(oop* p) {
const oop o = Atomic::load(p);
assert_is_valid(to_zaddress(o));
check_is_valid_zaddress(o);
return RawAccess<>::oop_load(p);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -365,7 +365,7 @@ void ZMark::follow_array_object(objArrayOop obj, bool finalizable) {
}
// Should be convertible to colorless oop
assert_is_valid(to_zaddress(obj));
check_is_valid_zaddress(obj);
zpointer* const addr = (zpointer*)obj->base();
const size_t length = (size_t)obj->length();

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,7 +47,7 @@
template <bool resurrect, bool gc_thread, bool follow, bool finalizable>
inline void ZMark::mark_object(zaddress addr) {
assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr)), "Should be oop");
assert_is_oop(addr);
ZPage* const page = _page_table->get(addr);
if (page->is_allocating()) {

@ -311,7 +311,7 @@ inline bool ZPage::mark_object(zaddress addr, bool finalizable, bool& inc_live)
assert(is_in(addr), "Invalid address");
// Verify oop
(void)to_oop(addr);
assert_is_oop(addr);
// Set mark bit
const BitMap::idx_t index = bit_index(addr);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -143,7 +143,7 @@ bool ZReferenceProcessor::is_inactive(zaddress reference, oop referent, Referenc
return !is_null(reference_next(reference));
} else {
// Verification
(void)to_zaddress(referent);
check_is_valid_zaddress(referent);
// A non-FinalReference is inactive if the referent is null. The referent can only
// be null if the application called Reference.enqueue() or Reference.clear().

@ -111,6 +111,16 @@ static bool z_is_null_relaxed(zpointer o) {
return (untype(o) & ~color_mask) == 0;
}
static void z_verify_oop_object(zaddress addr, zpointer o, void* p) {
const oop obj = cast_to_oop(addr);
guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(o, p));
}
static void z_verify_root_oop_object(zaddress addr, void* p) {
const oop obj = cast_to_oop(addr);
guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(addr, p));
}
static void z_verify_old_oop(zpointer* p) {
const zpointer o = *p;
assert(o != zpointer::null, "Old should not contain raw null");
@ -121,7 +131,7 @@ static void z_verify_old_oop(zpointer* p) {
// safepoint after reference processing, where we hold the driver lock and
// know there is no concurrent remembered set processing in the young generation.
const zaddress addr = ZPointer::uncolor(o);
guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p));
z_verify_oop_object(addr, o, p);
} else {
const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o);
// Old to young pointers might not be mark good if the young
@ -143,15 +153,11 @@ static void z_verify_young_oop(zpointer* p) {
guarantee(ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p));
if (ZPointer::is_load_good(o)) {
guarantee(oopDesc::is_oop(to_oop(ZPointer::uncolor(o))), BAD_OOP_ARG(o, p));
z_verify_oop_object(ZPointer::uncolor(o), o, p);
}
}
}
static void z_verify_root_oop_object(zaddress o, void* p) {
guarantee(oopDesc::is_oop(to_oop(o)), BAD_OOP_ARG(o, p));
}
static void z_verify_uncolored_root_oop(zaddress* p) {
assert(!ZHeap::heap()->is_in((uintptr_t)p), "Roots shouldn't be in heap");
const zaddress o = *p;
@ -168,7 +174,7 @@ static void z_verify_possibly_weak_oop(zpointer* p) {
const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o);
guarantee(ZHeap::heap()->is_old(addr) || ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p));
guarantee(ZHeap::heap()->is_young(addr) || ZHeap::heap()->is_object_live(addr), BAD_OOP_ARG(o, p));
guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p));
z_verify_oop_object(addr, o, p);
// Verify no missing remset entries. We are holding the driver lock here and that
// allows us to more precisely verify the remembered set, as there is no concurrent
@ -211,14 +217,14 @@ public:
// Minor collections could have relocated the object;
// use load barrier to find correct object.
const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o);
z_verify_root_oop_object(addr, p);
z_verify_oop_object(addr, o, p);
} else {
// Don't know the state of the oop
if (is_valid(o)) {
// it looks like a valid colored oop;
// use load barrier to find correct object.
const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o);
z_verify_root_oop_object(addr, p);
z_verify_oop_object(addr, o, p);
}
}
}