1 /*
  2  * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_GC_SHARED_C1_BARRIERSETC1_HPP
 26 #define SHARE_GC_SHARED_C1_BARRIERSETC1_HPP
 27 
 28 #include "c1/c1_Decorators.hpp"
 29 #include "c1/c1_LIRGenerator.hpp"
 30 #include "c1/c1_Instruction.hpp"
 31 #include "c1/c1_LIR.hpp"
 32 #include "memory/allocation.hpp"
 33 
 34 class LIRGenerator;
 35 class LIRItem;
 36 
 37 // The LIRAddressOpr comprises either a LIRItem or a LIR_Opr to describe elements
 38 // of an access in the C1 Access API. Both of them allow asking for the opr() which
 39 // will correspond to either _item.result() or _opr if there is no _item.
 40 class LIRAddressOpr: public StackObj {
 41   LIRItem* _item;
 42   LIR_Opr  _opr;
 43 public:
 44   LIRAddressOpr(LIRItem& item) : _item(&item), _opr() {}
 45   LIRAddressOpr(LIR_Opr opr) : _item(nullptr), _opr(opr) {}
 46   LIRAddressOpr(const LIRAddressOpr& other) : _item(other._item), _opr(other._opr) {}
 47 
 48   LIRItem& item() const {
 49     assert(_item != nullptr, "sanity");
 50     return *_item;
 51   }
 52 
 53   LIR_Opr opr() const {
 54     if (_item == nullptr) {
 55       return _opr;
 56     } else {
 57       return _item->result();
 58     }
 59   }
 60 };
 61 
 62 // The LIRAccess class wraps shared context parameters required for performing
 63 // the right access in C1. This includes the address of the offset and the decorators.
 64 class LIRAccess: public StackObj {
 65   LIRGenerator* _gen;
 66   DecoratorSet  _decorators;
 67   LIRAddressOpr _base;
 68   LIRAddressOpr _offset;
 69   BasicType     _type;
 70   LIR_Opr       _resolved_addr;
 71   CodeEmitInfo* _patch_emit_info;
 72   CodeEmitInfo* _access_emit_info;
 73   ciInlineKlass* _vk; // For flat, atomic accesses that might require GC barriers on oop fields
 74 
 75 public:
 76   LIRAccess(LIRGenerator* gen, DecoratorSet decorators,
 77             LIRAddressOpr base, LIRAddressOpr offset, BasicType type,
 78             CodeEmitInfo* patch_emit_info = nullptr, CodeEmitInfo* access_emit_info = nullptr, ciInlineKlass* vk = nullptr) :
 79     _gen(gen),
 80     _decorators(AccessInternal::decorator_fixup(decorators, type)),
 81     _base(base),
 82     _offset(offset),
 83     _type(type),
 84     _resolved_addr(),
 85     _patch_emit_info(patch_emit_info),
 86     _access_emit_info(access_emit_info),
 87     _vk(vk) {}
 88 
 89   void load_base()   { _base.item().load_item(); }
 90   void load_offset() { _offset.item().load_nonconstant(); }
 91 
 92   void load_address() {
 93     load_base();
 94     load_offset();
 95   }
 96 
 97   LIRGenerator* gen() const              { return _gen; }
 98   CodeEmitInfo*& patch_emit_info()       { return _patch_emit_info; }
 99   CodeEmitInfo*& access_emit_info()      { return _access_emit_info; }
100   LIRAddressOpr& base()                  { return _base; }
101   LIRAddressOpr& offset()                { return _offset; }
102   BasicType type() const                 { return _type; }
103   LIR_Opr resolved_addr() const          { return _resolved_addr; }
104   void set_resolved_addr(LIR_Opr addr)   { _resolved_addr = addr; }
105   bool is_oop() const                    { return is_reference_type(_type); }
106   DecoratorSet decorators() const        { return _decorators; }
107   void clear_decorators(DecoratorSet ds) { _decorators &= ~ds; }
108   bool is_raw() const                    { return (_decorators & AS_RAW) != 0; }
109   ciInlineKlass* vk() const              { return _vk; }
110 };
111 
112 // The BarrierSetC1 class is the main entry point for the GC backend of the Access API in C1.
113 // It is called by the LIRGenerator::access_* functions, which is the main entry point for
114 // access calls in C1.
115 
116 class BarrierSetC1: public CHeapObj<mtGC> {
117 protected:
118   virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register);
119 
120   virtual void generate_referent_check(LIRAccess& access, LabelObj* cont);
121 
122   // Accesses with resolved address
123   virtual void store_at_resolved(LIRAccess& access, LIR_Opr value);
124   virtual void load_at_resolved(LIRAccess& access, LIR_Opr result);
125 
126   virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
127 
128   virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value);
129   virtual LIR_Opr atomic_add_at_resolved(LIRAccess& access, LIRItem& value);
130 
131 public:
132   virtual void store_at(LIRAccess& access, LIR_Opr value);
133   virtual void load_at(LIRAccess& access, LIR_Opr result);
134   virtual void load(LIRAccess& access, LIR_Opr result);
135 
136   virtual LIR_Opr atomic_cmpxchg_at(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
137 
138   virtual LIR_Opr atomic_xchg_at(LIRAccess& access, LIRItem& value);
139   virtual LIR_Opr atomic_add_at(LIRAccess& access, LIRItem& value);
140 
141   virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob) {}
142 };
143 
144 #endif // SHARE_GC_SHARED_C1_BARRIERSETC1_HPP