Path: blob/master/src/hotspot/share/gc/z/zBarrier.cpp
40957 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "classfile/javaClasses.hpp"25#include "gc/z/zBarrier.inline.hpp"26#include "gc/z/zHeap.inline.hpp"27#include "gc/z/zOop.inline.hpp"28#include "gc/z/zThread.inline.hpp"29#include "memory/iterator.inline.hpp"30#include "oops/oop.inline.hpp"31#include "runtime/safepoint.hpp"32#include "utilities/debug.hpp"3334template <bool finalizable>35bool ZBarrier::should_mark_through(uintptr_t addr) {36// Finalizable marked oops can still exists on the heap after marking37// has completed, in which case we just want to convert this into a38// good oop and not push it on the mark stack.39if (!during_mark()) {40assert(ZAddress::is_marked(addr), "Should be marked");41assert(ZAddress::is_finalizable(addr), "Should be finalizable");42return false;43}4445// During marking, we mark through already marked oops to avoid having46// some large part of the object graph hidden behind a pushed, but not47// yet flushed, entry on a mutator mark stack. Always marking through48// allows the GC workers to proceed through the object graph even if a49// mutator touched an oop first, which in turn will reduce the risk of50// having to flush mark stacks multiple times to terminate marking.51//52// However, when doing finalizable marking we don't always want to mark53// through. First, marking through an already strongly marked oop would54// be wasteful, since we will then proceed to do finalizable marking on55// an object which is, or will be, marked strongly. Second, marking56// through an already finalizable marked oop would also be wasteful,57// since such oops can never end up on a mutator mark stack and can58// therefore not hide some part of the object graph from GC workers.59if (finalizable) {60return !ZAddress::is_marked(addr);61}6263// Mark through64return true;65}6667template <bool gc_thread, bool follow, bool finalizable, bool publish>68uintptr_t ZBarrier::mark(uintptr_t addr) {69uintptr_t good_addr;7071if (ZAddress::is_marked(addr)) {72// Already marked, but try to mark though anyway73good_addr = ZAddress::good(addr);74} else if (ZAddress::is_remapped(addr)) {75// Already remapped, but also needs to be marked76good_addr = ZAddress::good(addr);77} else {78// Needs to be both remapped and marked79good_addr = remap(addr);80}8182// Mark83if (should_mark_through<finalizable>(addr)) {84ZHeap::heap()->mark_object<gc_thread, follow, finalizable, publish>(good_addr);85}8687if (finalizable) {88// Make the oop finalizable marked/good, instead of normal marked/good.89// This is needed because an object might first becomes finalizable90// marked by the GC, and then loaded by a mutator thread. In this case,91// the mutator thread must be able to tell that the object needs to be92// strongly marked. The finalizable bit in the oop exists to make sure93// that a load of a finalizable marked oop will fall into the barrier94// slow path so that we can mark the object as strongly reachable.95return ZAddress::finalizable_good(good_addr);96}9798return good_addr;99}100101uintptr_t ZBarrier::remap(uintptr_t addr) {102assert(!ZAddress::is_good(addr), "Should not be good");103assert(!ZAddress::is_weak_good(addr), "Should not be weak good");104return ZHeap::heap()->remap_object(addr);105}106107uintptr_t ZBarrier::relocate(uintptr_t addr) {108assert(!ZAddress::is_good(addr), "Should not be good");109assert(!ZAddress::is_weak_good(addr), "Should not be weak good");110return ZHeap::heap()->relocate_object(addr);111}112113uintptr_t ZBarrier::relocate_or_mark(uintptr_t addr) {114return during_relocate() ? relocate(addr) : mark<AnyThread, Follow, Strong, Publish>(addr);115}116117uintptr_t ZBarrier::relocate_or_mark_no_follow(uintptr_t addr) {118return during_relocate() ? relocate(addr) : mark<AnyThread, DontFollow, Strong, Publish>(addr);119}120121uintptr_t ZBarrier::relocate_or_remap(uintptr_t addr) {122return during_relocate() ? relocate(addr) : remap(addr);123}124125//126// Load barrier127//128uintptr_t ZBarrier::load_barrier_on_oop_slow_path(uintptr_t addr) {129return relocate_or_mark(addr);130}131132uintptr_t ZBarrier::load_barrier_on_invisible_root_oop_slow_path(uintptr_t addr) {133return relocate_or_mark_no_follow(addr);134}135136void ZBarrier::load_barrier_on_oop_fields(oop o) {137assert(ZAddress::is_good(ZOop::to_address(o)), "Should be good");138ZLoadBarrierOopClosure cl;139o->oop_iterate(&cl);140}141142//143// Weak load barrier144//145uintptr_t ZBarrier::weak_load_barrier_on_oop_slow_path(uintptr_t addr) {146return ZAddress::is_weak_good(addr) ? ZAddress::good(addr) : relocate_or_remap(addr);147}148149uintptr_t ZBarrier::weak_load_barrier_on_weak_oop_slow_path(uintptr_t addr) {150const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);151if (ZHeap::heap()->is_object_strongly_live(good_addr)) {152return good_addr;153}154155// Not strongly live156return 0;157}158159uintptr_t ZBarrier::weak_load_barrier_on_phantom_oop_slow_path(uintptr_t addr) {160const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);161if (ZHeap::heap()->is_object_live(good_addr)) {162return good_addr;163}164165// Not live166return 0;167}168169//170// Keep alive barrier171//172uintptr_t ZBarrier::keep_alive_barrier_on_oop_slow_path(uintptr_t addr) {173assert(during_mark(), "Invalid phase");174175// Mark176return mark<AnyThread, Follow, Strong, Overflow>(addr);177}178179uintptr_t ZBarrier::keep_alive_barrier_on_weak_oop_slow_path(uintptr_t addr) {180const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);181assert(ZHeap::heap()->is_object_strongly_live(good_addr), "Should be live");182return good_addr;183}184185uintptr_t ZBarrier::keep_alive_barrier_on_phantom_oop_slow_path(uintptr_t addr) {186const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);187assert(ZHeap::heap()->is_object_live(good_addr), "Should be live");188return good_addr;189}190191//192// Mark barrier193//194uintptr_t ZBarrier::mark_barrier_on_oop_slow_path(uintptr_t addr) {195assert(during_mark(), "Invalid phase");196assert(ZThread::is_worker(), "Invalid thread");197198// Mark199return mark<GCThread, Follow, Strong, Overflow>(addr);200}201202uintptr_t ZBarrier::mark_barrier_on_finalizable_oop_slow_path(uintptr_t addr) {203assert(during_mark(), "Invalid phase");204assert(ZThread::is_worker(), "Invalid thread");205206// Mark207return mark<GCThread, Follow, Finalizable, Overflow>(addr);208}209210//211// Narrow oop variants, never used.212//213oop ZBarrier::load_barrier_on_oop_field(volatile narrowOop* p) {214ShouldNotReachHere();215return NULL;216}217218oop ZBarrier::load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o) {219ShouldNotReachHere();220return NULL;221}222223void ZBarrier::load_barrier_on_oop_array(volatile narrowOop* p, size_t length) {224ShouldNotReachHere();225}226227oop ZBarrier::load_barrier_on_weak_oop_field_preloaded(volatile narrowOop* p, oop o) {228ShouldNotReachHere();229return NULL;230}231232oop ZBarrier::load_barrier_on_phantom_oop_field_preloaded(volatile narrowOop* p, oop o) {233ShouldNotReachHere();234return NULL;235}236237oop ZBarrier::weak_load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o) {238ShouldNotReachHere();239return NULL;240}241242oop ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(volatile narrowOop* p, oop o) {243ShouldNotReachHere();244return NULL;245}246247oop ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(volatile narrowOop* p, oop o) {248ShouldNotReachHere();249return NULL;250}251252#ifdef ASSERT253254// ON_WEAK barriers should only ever be applied to j.l.r.Reference.referents.255void ZBarrier::verify_on_weak(volatile oop* referent_addr) {256if (referent_addr != NULL) {257uintptr_t base = (uintptr_t)referent_addr - java_lang_ref_Reference::referent_offset();258oop obj = cast_to_oop(base);259assert(oopDesc::is_oop(obj), "Verification failed for: ref " PTR_FORMAT " obj: " PTR_FORMAT, (uintptr_t)referent_addr, base);260assert(java_lang_ref_Reference::is_referent_field(obj, java_lang_ref_Reference::referent_offset()), "Sanity");261}262}263264#endif265266void ZLoadBarrierOopClosure::do_oop(oop* p) {267ZBarrier::load_barrier_on_oop_field(p);268}269270void ZLoadBarrierOopClosure::do_oop(narrowOop* p) {271ShouldNotReachHere();272}273274275