Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/shenandoah/shenandoahAsserts.cpp
38920 views
/*1* Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation.6*7* This code is distributed in the hope that it will be useful, but WITHOUT8* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or9* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License10* version 2 for more details (a copy is included in the LICENSE file that11* accompanied this code).12*13* You should have received a copy of the GNU General Public License version14* 2 along with this work; if not, write to the Free Software Foundation,15* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.16*17* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA18* or visit www.oracle.com if you need additional information or have any19* questions.20*21*/2223#include "precompiled.hpp"2425#include "gc_implementation/shenandoah/shenandoahAsserts.hpp"26#include "gc_implementation/shenandoah/shenandoahForwarding.hpp"27#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"28#include "gc_implementation/shenandoah/shenandoahHeapRegionSet.inline.hpp"29#include "gc_implementation/shenandoah/shenandoahMarkingContext.inline.hpp"30#include "gc_implementation/shenandoah/shenandoahUtils.hpp"31#include "memory/resourceArea.hpp"3233void print_raw_memory(ShenandoahMessageBuffer &msg, void* loc) {34// Be extra safe. Only access data that is guaranteed to be safe:35// should be in heap, in known committed region, within that region.3637ShenandoahHeap* heap = ShenandoahHeap::heap();38if (!heap->is_in(loc)) return;3940ShenandoahHeapRegion* r = heap->heap_region_containing(loc);41if (r != NULL && r->is_committed()) {42address start = MAX2((address) r->bottom(), (address) loc - 32);43address end = MIN2((address) r->end(), (address) loc + 128);44if (start >= end) return;4546stringStream ss;47os::print_hex_dump(&ss, start, end, 4);48msg.append("\n");49msg.append("Raw heap memory:\n%s", ss.as_string());50}51}5253void ShenandoahAsserts::print_obj(ShenandoahMessageBuffer& msg, oop obj) {54ShenandoahHeap* heap = ShenandoahHeap::heap();55ShenandoahHeapRegion *r = heap->heap_region_containing(obj);5657ResourceMark rm;58stringStream ss;59r->print_on(&ss);6061stringStream mw_ss;62obj->mark()->print_on(&mw_ss);6364ShenandoahMarkingContext* const ctx = heap->marking_context();6566msg.append(" " PTR_FORMAT " - klass " PTR_FORMAT " %s\n", p2i(obj), p2i(obj->klass()), obj->klass()->external_name());67msg.append(" %3s allocated after mark start\n", ctx->allocated_after_mark_start((HeapWord *) obj) ? "" : "not");68msg.append(" %3s after update watermark\n", cast_from_oop<HeapWord*>(obj) >= r->get_update_watermark() ? "" : "not");69msg.append(" %3s marked \n", ctx->is_marked(obj) ? "" : "not");70msg.append(" %3s in collection set\n", heap->in_collection_set(obj) ? "" : "not");71msg.append(" mark:%s\n", mw_ss.as_string());72msg.append(" region: %s", ss.as_string());73}7475void ShenandoahAsserts::print_non_obj(ShenandoahMessageBuffer& msg, void* loc) {76ShenandoahHeap* heap = ShenandoahHeap::heap();77if (heap->is_in(loc)) {78msg.append(" inside Java heap\n");79ShenandoahHeapRegion *r = heap->heap_region_containing(loc);80stringStream ss;81r->print_on(&ss);8283msg.append(" %3s in collection set\n", heap->in_collection_set_loc(loc) ? "" : "not");84msg.append(" region: %s", ss.as_string());85} else {86msg.append(" outside of Java heap\n");87stringStream ss;88os::print_location(&ss, (intptr_t) loc, false);89msg.append(" %s", ss.as_string());90}91}9293void ShenandoahAsserts::print_obj_safe(ShenandoahMessageBuffer& msg, void* loc) {94ShenandoahHeap* heap = ShenandoahHeap::heap();95msg.append(" " PTR_FORMAT " - safe print, no details\n", p2i(loc));96if (heap->is_in(loc)) {97ShenandoahHeapRegion* r = heap->heap_region_containing(loc);98if (r != NULL) {99stringStream ss;100r->print_on(&ss);101msg.append(" region: %s", ss.as_string());102print_raw_memory(msg, loc);103}104}105}106107void ShenandoahAsserts::print_failure(SafeLevel level, oop obj, void* interior_loc, oop loc,108const char* phase, const char* label,109const char* file, int line) {110ShenandoahHeap* heap = ShenandoahHeap::heap();111ResourceMark rm;112113bool loc_in_heap = (loc != NULL && heap->is_in(loc));114115ShenandoahMessageBuffer msg("%s; %s\n\n", phase, label);116117msg.append("Referenced from:\n");118if (interior_loc != NULL) {119msg.append(" interior location: " PTR_FORMAT "\n", p2i(interior_loc));120if (loc_in_heap) {121print_obj(msg, loc);122} else {123print_non_obj(msg, interior_loc);124}125} else {126msg.append(" no interior location recorded (probably a plain heap scan, or detached oop)\n");127}128msg.append("\n");129130msg.append("Object:\n");131if (level >= _safe_oop) {132print_obj(msg, obj);133} else {134print_obj_safe(msg, obj);135}136msg.append("\n");137138if (level >= _safe_oop) {139oop fwd = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(obj);140msg.append("Forwardee:\n");141if (obj != fwd) {142if (level >= _safe_oop_fwd) {143print_obj(msg, fwd);144} else {145print_obj_safe(msg, fwd);146}147} else {148msg.append(" (the object itself)");149}150msg.append("\n");151}152153if (level >= _safe_oop_fwd) {154oop fwd = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(obj);155oop fwd2 = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(fwd);156if (fwd != fwd2) {157msg.append("Second forwardee:\n");158print_obj_safe(msg, fwd2);159msg.append("\n");160}161}162163report_vm_error(file, line, msg.buffer());164}165166void ShenandoahAsserts::assert_in_heap(void* interior_loc, oop obj, const char *file, int line) {167ShenandoahHeap* heap = ShenandoahHeap::heap();168169if (!heap->is_in(obj)) {170print_failure(_safe_unknown, obj, interior_loc, NULL, "Shenandoah assert_in_heap failed",171"oop must point to a heap address",172file, line);173}174}175176void ShenandoahAsserts::assert_correct(void* interior_loc, oop obj, const char* file, int line) {177ShenandoahHeap* heap = ShenandoahHeap::heap();178179// Step 1. Check that obj is correct.180// After this step, it is safe to call heap_region_containing().181if (!heap->is_in(obj)) {182print_failure(_safe_unknown, obj, interior_loc, NULL, "Shenandoah assert_correct failed",183"oop must point to a heap address",184file, line);185}186187Klass* obj_klass = obj->klass_or_null();188if (obj_klass == NULL) {189print_failure(_safe_unknown, obj, interior_loc, NULL, "Shenandoah assert_correct failed",190"Object klass pointer should not be NULL",191file,line);192}193194if (!Metaspace::contains(obj_klass)) {195print_failure(_safe_unknown, obj, interior_loc, NULL, "Shenandoah assert_correct failed",196"Object klass pointer must go to metaspace",197file,line);198}199200oop fwd = oop(ShenandoahForwarding::get_forwardee_raw_unchecked(obj));201202if (obj != fwd) {203// When Full GC moves the objects, we cannot trust fwdptrs. If we got here, it means something204// tries fwdptr manipulation when Full GC is running. The only exception is using the fwdptr205// that still points to the object itself.206if (heap->is_full_gc_move_in_progress()) {207print_failure(_safe_oop, obj, interior_loc, NULL, "Shenandoah assert_correct failed",208"Non-trivial forwarding pointer during Full GC moves, probable bug.",209file, line);210}211212// Step 2. Check that forwardee is correct213if (!heap->is_in(fwd)) {214print_failure(_safe_oop, obj, interior_loc, NULL, "Shenandoah assert_correct failed",215"Forwardee must point to a heap address",216file, line);217}218219if (obj_klass != fwd->klass()) {220print_failure(_safe_oop, obj, interior_loc, NULL, "Shenandoah assert_correct failed",221"Forwardee klass disagrees with object class",222file, line);223}224225// Step 3. Check that forwardee points to correct region226if (heap->heap_region_index_containing(fwd) == heap->heap_region_index_containing(obj)) {227print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_correct failed",228"Non-trivial forwardee should in another region",229file, line);230}231232// Step 4. Check for multiple forwardings233oop fwd2 = oop(ShenandoahForwarding::get_forwardee_raw_unchecked(fwd));234if (fwd != fwd2) {235print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_correct failed",236"Multiple forwardings",237file, line);238}239}240}241242void ShenandoahAsserts::assert_in_correct_region(void* interior_loc, oop obj, const char* file, int line) {243assert_correct(interior_loc, obj, file, line);244245ShenandoahHeap* heap = ShenandoahHeap::heap();246ShenandoahHeapRegion* r = heap->heap_region_containing(obj);247if (!r->is_active()) {248print_failure(_safe_unknown, obj, interior_loc, NULL, "Shenandoah assert_in_correct_region failed",249"Object must reside in active region",250file, line);251}252253size_t alloc_size = obj->size();254if (alloc_size > ShenandoahHeapRegion::humongous_threshold_words()) {255size_t idx = r->index();256size_t num_regions = ShenandoahHeapRegion::required_regions(alloc_size * HeapWordSize);257for (size_t i = idx; i < idx + num_regions; i++) {258ShenandoahHeapRegion* chain_reg = heap->get_region(i);259if (i == idx && !chain_reg->is_humongous_start()) {260print_failure(_safe_unknown, obj, interior_loc, NULL, "Shenandoah assert_in_correct_region failed",261"Object must reside in humongous start",262file, line);263}264if (i != idx && !chain_reg->is_humongous_continuation()) {265print_failure(_safe_oop, obj, interior_loc, NULL, "Shenandoah assert_in_correct_region failed",266"Humongous continuation should be of proper size",267file, line);268}269}270}271}272273void ShenandoahAsserts::assert_forwarded(void* interior_loc, oop obj, const char* file, int line) {274assert_correct(interior_loc, obj, file, line);275oop fwd = oop(ShenandoahForwarding::get_forwardee_raw_unchecked(obj));276277if (obj == fwd) {278print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_forwarded failed",279"Object should be forwarded",280file, line);281}282}283284void ShenandoahAsserts::assert_not_forwarded(void* interior_loc, oop obj, const char* file, int line) {285assert_correct(interior_loc, obj, file, line);286oop fwd = oop(ShenandoahForwarding::get_forwardee_raw_unchecked(obj));287288if (obj != fwd) {289print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_not_forwarded failed",290"Object should not be forwarded",291file, line);292}293}294295void ShenandoahAsserts::assert_marked(void *interior_loc, oop obj, const char *file, int line) {296assert_correct(interior_loc, obj, file, line);297298ShenandoahHeap* heap = ShenandoahHeap::heap();299if (!heap->marking_context()->is_marked(obj)) {300print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_marked failed",301"Object should be marked",302file, line);303}304}305306void ShenandoahAsserts::assert_in_cset(void* interior_loc, oop obj, const char* file, int line) {307assert_correct(interior_loc, obj, file, line);308309ShenandoahHeap* heap = ShenandoahHeap::heap();310if (!heap->in_collection_set(obj)) {311print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_in_cset failed",312"Object should be in collection set",313file, line);314}315}316317void ShenandoahAsserts::assert_not_in_cset(void* interior_loc, oop obj, const char* file, int line) {318assert_correct(interior_loc, obj, file, line);319320ShenandoahHeap* heap = ShenandoahHeap::heap();321if (heap->in_collection_set(obj)) {322print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_not_in_cset failed",323"Object should not be in collection set",324file, line);325}326}327328void ShenandoahAsserts::assert_not_in_cset_loc(void* interior_loc, const char* file, int line) {329ShenandoahHeap* heap = ShenandoahHeap::heap();330if (heap->in_collection_set_loc(interior_loc)) {331print_failure(_safe_unknown, NULL, interior_loc, NULL, "Shenandoah assert_not_in_cset_loc failed",332"Interior location should not be in collection set",333file, line);334}335}336337void ShenandoahAsserts::print_rp_failure(const char *label, BoolObjectClosure* actual,338const char *file, int line) {339ShenandoahMessageBuffer msg("%s\n", label);340msg.append(" Actual: " PTR_FORMAT "\n", p2i(actual));341report_vm_error(file, line, msg.buffer());342}343344void ShenandoahAsserts::assert_heaplocked(const char* file, int line) {345ShenandoahHeap* heap = ShenandoahHeap::heap();346347if (heap->lock()->owned_by_self()) {348return;349}350351ShenandoahMessageBuffer msg("Heap lock must be owned by current thread");352report_vm_error(file, line, msg.buffer());353}354355void ShenandoahAsserts::assert_not_heaplocked(const char* file, int line) {356ShenandoahHeap* heap = ShenandoahHeap::heap();357358if (!heap->lock()->owned_by_self()) {359return;360}361362ShenandoahMessageBuffer msg("Heap lock must not be owned by current thread");363report_vm_error(file, line, msg.buffer());364}365366void ShenandoahAsserts::assert_heaplocked_or_safepoint(const char* file, int line) {367ShenandoahHeap* heap = ShenandoahHeap::heap();368369if (heap->lock()->owned_by_self()) {370return;371}372373if (ShenandoahSafepoint::is_at_shenandoah_safepoint() && Thread::current()->is_VM_thread()) {374return;375}376377ShenandoahMessageBuffer msg("Heap lock must be owned by current thread, or be at safepoint");378report_vm_error(file, line, msg.buffer());379}380381void ShenandoahAsserts::assert_rp_isalive_not_installed(const char *file, int line) {382ShenandoahHeap* heap = ShenandoahHeap::heap();383ReferenceProcessor* rp = heap->ref_processor();384if (rp->is_alive_non_header() != NULL) {385print_rp_failure("Shenandoah assert_rp_isalive_not_installed failed", rp->is_alive_non_header(),386file, line);387}388}389390void ShenandoahAsserts::assert_rp_isalive_installed(const char *file, int line) {391ShenandoahHeap* heap = ShenandoahHeap::heap();392ReferenceProcessor* rp = heap->ref_processor();393if (rp->is_alive_non_header() == NULL) {394print_rp_failure("Shenandoah assert_rp_isalive_installed failed", rp->is_alive_non_header(),395file, line);396}397}398399400