/* * Copyright (c) 2000, 2015, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_GC_SHARED_BARRIERSET_HPP #define SHARE_VM_GC_SHARED_BARRIERSET_HPP #include "gc/shared/barrierSetConfig.hpp" #include "runtime/access.hpp" #include "runtime/accessBackend.hpp" #include "utilities/fakeRttiSupport.hpp" class JavaThread; class BarrierSetCodeGen; class C1BarrierSetCodeGen; class C2BarrierSetCodeGen; // This class provides the interface between a barrier implementation and // the rest of the system. class BarrierSet: public CHeapObj { friend class VMStructs; public: enum Name { #define BARRIER_SET_DECLARE_BS_ENUM(bs_name) bs_name , FOR_EACH_BARRIER_SET_DO(BARRIER_SET_DECLARE_BS_ENUM) #undef BARRIER_SET_DECLARE_BS_ENUM UnknownBS }; protected: // Fake RTTI support. For a derived class T to participate // - T must have a corresponding Name entry. // - GetName must be specialized to return the corresponding Name // entry. // - If T is a base class, the constructor must have a FakeRtti // parameter and pass it up to its base class, with the tag set // augmented with the corresponding Name entry. // - If T is a concrete class, the constructor must create a // FakeRtti object whose tag set includes the corresponding Name // entry, and pass it up to its base class. typedef FakeRttiSupport FakeRtti; private: FakeRtti _fake_rtti; // Downcast argument to a derived barrier set type. // The cast is checked in a debug build. // T must have a specialization for BarrierSet::GetName. template friend T* barrier_set_cast(BarrierSet* bs); public: // Note: This is not presently the Name corresponding to the // concrete class of this object. BarrierSet::Name kind() const { return _fake_rtti.concrete_tag(); } // Test whether this object is of the type corresponding to bsn. bool is_a(BarrierSet::Name bsn) const { return _fake_rtti.has_tag(bsn); } // End of fake RTTI support. protected: BarrierSet(const FakeRtti& fake_rtti) : _fake_rtti(fake_rtti), _code_gen(NULL), _c1_code_gen(NULL), _c2_code_gen(NULL) { } ~BarrierSet() { } static BarrierSet* _bs; BarrierSetCodeGen* _code_gen; C1BarrierSetCodeGen* _c1_code_gen; C2BarrierSetCodeGen* _c2_code_gen; virtual BarrierSetCodeGen* make_code_gen() = 0; virtual C1BarrierSetCodeGen* make_c1_code_gen() = 0; virtual C2BarrierSetCodeGen* make_c2_code_gen() = 0; public: static BarrierSet* barrier_set() { return _bs; } // Print a description of the memory for the barrier set virtual void print_on(outputStream* st) const = 0; virtual void initialize(); BarrierSetCodeGen* code_gen() { assert(_code_gen != NULL, "should be set"); return _code_gen; } C1BarrierSetCodeGen* c1_code_gen() { assert(_c1_code_gen != NULL, "should be set"); return _c1_code_gen; } C2BarrierSetCodeGen* c2_code_gen() { assert(_c2_code_gen != NULL, "should be set"); return _c2_code_gen; } // The AccessBarrier of a BarrierSet subclass is called by the Access API // to perform decorated accesses. template class AccessBarrier: public BasicAccessBarrier { typedef BasicAccessBarrier Basic; public: static void oop_store(void* addr, oop value); static void oop_store_at(oop base, ptrdiff_t offset, oop value); static void oop_store_at(nmethod* base, ptrdiff_t offset, oop value); static void oop_store_at(Klass* base, ptrdiff_t offset, oop value); static oop oop_load(void* addr); static oop oop_load_at(oop base, ptrdiff_t offset); static oop oop_cas(oop new_value, void* addr, oop compare_value); static oop oop_cas_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value); static oop oop_swap(oop new_value, void* addr); static oop oop_swap_at(oop new_value, oop base, ptrdiff_t offset); }; // Support for optimizing compilers to call the barrier set on slow path allocations // that did not enter a TLAB. Used for e.g. ReduceInitialCardMarks virtual void on_slowpath_allocation(JavaThread* thread, oop new_obj) {} virtual void on_add_thread(JavaThread* thread) {} virtual void on_destroy_thread(JavaThread* thread) {} virtual void make_parsable(JavaThread* thread) {} // Resolve runtime paths for GC barriers accessible through the Access interface // in runtime/access.hpp template void* resolve_barrier(); template void* resolve_clone_barrier(); }; // Metafunction mapping a class derived from BarrierSet to the // corresponding Name enum tag. template struct BSTypeToName; template struct BSNameToType; template inline T* barrier_set_cast(BarrierSet* bs) { assert(bs->is_a(BSTypeToName::value), "wrong type of barrier set"); return static_cast(bs); } #endif // SHARE_VM_GC_SHARED_BARRIERSET_HPP