1 /*
  2  * Copyright (c) 2018, 2021, Red Hat, Inc. 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_SHENANDOAH_C2_SHENANDOAHBARRIERSETC2_HPP
 26 #define SHARE_GC_SHENANDOAH_C2_SHENANDOAHBARRIERSETC2_HPP
 27 
 28 #include "gc/shared/c2/barrierSetC2.hpp"
 29 #include "gc/shared/gc_globals.hpp"
 30 #include "utilities/growableArray.hpp"
 31 
 32 static const uint8_t ShenandoahBarrierStrong          = 1 << 0;
 33 static const uint8_t ShenandoahBarrierWeak            = 1 << 1;
 34 static const uint8_t ShenandoahBarrierPhantom         = 1 << 2;
 35 static const uint8_t ShenandoahBarrierNative          = 1 << 3;
 36 static const uint8_t ShenandoahBarrierElided          = 1 << 4;
 37 static const uint8_t ShenandoahBarrierSATB            = 1 << 5;
 38 static const uint8_t ShenandoahBarrierCardMark        = 1 << 6;
 39 static const uint8_t ShenandoahBarrierNotNull         = 1 << 7;
 40 
 41 // Barrier data that implies real barriers, not additional metadata.
 42 static const uint8_t ShenandoahBarriersReal =
 43   ShenandoahBarrierStrong   | // LRB strong
 44   ShenandoahBarrierWeak     | // LRB weak
 45   ShenandoahBarrierPhantom  | // LRB phantom
 46   ShenandoahBarrierSATB     | // SATB
 47   ShenandoahBarrierCardMark;  // Card Mark
 48 
 49 class ShenandoahBarrierStubC2;
 50 
 51 class ShenandoahBarrierSetC2State : public BarrierSetC2State {
 52   GrowableArray<ShenandoahBarrierStubC2*>* _stubs;
 53   int _stubs_start_offset;
 54 
 55 public:
 56   explicit ShenandoahBarrierSetC2State(Arena* comp_arena);
 57 
 58   bool needs_liveness_data(const MachNode* mach) const override;
 59   bool needs_livein_data() const override;
 60 
 61   GrowableArray<ShenandoahBarrierStubC2*>* stubs() {
 62     return _stubs;
 63   }
 64 
 65   void set_stubs_start_offset(int offset) {
 66     _stubs_start_offset = offset;
 67   }
 68 
 69   int stubs_start_offset() {
 70     return _stubs_start_offset;
 71   }};
 72 
 73 class ShenandoahBarrierSetC2 : public BarrierSetC2 {
 74 
 75   static bool clone_needs_barrier(const TypeOopPtr* src_type, bool& is_oop_array);
 76 
 77   static bool can_remove_load_barrier(Node* node);
 78 
 79   static void refine_load(Node* node);
 80   static void refine_store(const Node* node);































 81 
 82 protected:
 83   virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const;
 84   virtual Node* store_at_resolved(C2Access& access, C2AccessValue& val) const;
 85   virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
 86                                                Node* new_val, const Type* val_type) const;
 87   virtual Node* atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
 88                                                 Node* new_val, const Type* value_type) const;
 89   virtual Node* atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* val_type) const;
 90 
 91 public:
 92   static ShenandoahBarrierSetC2* bsc2();
 93 







 94   ShenandoahBarrierSetC2State* state() const;
 95 





 96   // This is the entry-point for the backend to perform accesses through the Access API.
 97   virtual void clone(GraphKit* kit, Node* src_base, Node* dst_base, Node* size, bool is_array) const;
 98   virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const;
 99 
100   // These are general helper methods used by C2
101   virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const;
102 
103   // Support for GC barriers emitted during parsing



104   virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const;
105   virtual void final_refinement(Compile* C) const;


106 
107   // Support for macro expanded GC barriers


108   virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const;
109   virtual void eliminate_gc_barrier_data(Node* node) const;

110 
111   // Allow barrier sets to have shared state that is preserved across a compilation unit.
112   // This could for example comprise macro nodes to be expanded during macro expansion.
113   virtual void* create_barrier_state(Arena* comp_arena) const;



114 
115 #ifdef ASSERT
116   virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const;
117   static void verify_gc_barrier_assert(bool cond, const char* msg, uint8_t bd, Node* n);
118 #endif
119 
120   int estimate_stub_size() const /* override */;
121   void emit_stubs(CodeBuffer& cb) const /* override */;
122   void late_barrier_analysis() const /* override*/ {
123     compute_liveness_at_stubs();
124   }
125 
126   static void print_barrier_data(outputStream* os, uint8_t data);
127 };
128 
129 class ShenandoahBarrierStubC2 : public BarrierStubC2 {
130 protected:
131   explicit ShenandoahBarrierStubC2(const MachNode* node) : BarrierStubC2(node) {
132     assert(!ShenandoahSkipBarrierStubs, "Do not touch stubs when disabled");
133   }
134   void register_stub();
135 public:
136   virtual void emit_code(MacroAssembler& masm) = 0;
137 };
138 
139 class ShenandoahLoadBarrierStubC2 : public ShenandoahBarrierStubC2 {
140   Register const _dst;
141   Address  const _src;
142   Register const _tmp;
143   const bool _narrow;
144   const bool _needs_load_ref_barrier;
145   const bool _needs_satb_barrier;
146 
147   ShenandoahLoadBarrierStubC2(const MachNode* node, Register dst, Address src, bool narrow, Register tmp) :
148     ShenandoahBarrierStubC2(node), _dst(dst), _src(src), _tmp(tmp), _narrow(narrow),
149     _needs_load_ref_barrier(needs_load_ref_barrier(node)), _needs_satb_barrier(needs_satb_barrier(node)) {}
150 
151 public:
152   static bool needs_barrier(const MachNode* node) {
153     return needs_load_ref_barrier(node) || needs_satb_barrier(node);
154   }
155   static bool needs_satb_barrier(const MachNode* node) {
156     return (node->barrier_data() & ShenandoahBarrierSATB) != 0;
157   }
158   static bool needs_load_ref_barrier(const MachNode* node) {
159     return (node->barrier_data() & (ShenandoahBarrierStrong | ShenandoahBarrierWeak | ShenandoahBarrierPhantom)) != 0;
160   }
161   static bool needs_load_ref_barrier_weak(const MachNode* node) {
162     return (node->barrier_data() & (ShenandoahBarrierWeak | ShenandoahBarrierPhantom)) != 0;
163   }
164   static bool src_not_null(const MachNode* node) {
165     return (node->barrier_data() & ShenandoahBarrierNotNull) != 0;
166   }
167 
168   static ShenandoahLoadBarrierStubC2* create(const MachNode* node, Register dst, Address src, bool narrow, Register tmp);


169 
170   void emit_code(MacroAssembler& masm) override;

171 };
172 
173 
174 class ShenandoahStoreBarrierStubC2 : public ShenandoahBarrierStubC2 {
175   Address const _dst;
176   Register const _src;
177   Register const _tmp;
178   const bool _dst_narrow;
179   const bool _src_narrow;
180 
181   ShenandoahStoreBarrierStubC2(const MachNode* node, Address dst, bool dst_narrow, Register src, bool src_narrow, Register tmp) :
182     ShenandoahBarrierStubC2(node), _dst(dst), _src(src), _tmp(tmp), _dst_narrow(dst_narrow), _src_narrow(src_narrow) {}
183 
184 public:
185   static bool needs_barrier(const MachNode* node) {
186     return needs_card_barrier(node) || needs_satb_barrier(node);
187   }
188   static bool needs_satb_barrier(const MachNode* node) {
189     return (node->barrier_data() & ShenandoahBarrierSATB) != 0;
190   }
191   static bool needs_card_barrier(const MachNode* node) {
192     return (node->barrier_data() & ShenandoahBarrierCardMark) != 0;
193   }
194   static bool src_not_null(const MachNode* node) {
195     return (node->barrier_data() & ShenandoahBarrierNotNull) != 0;
196   }
197 
198   static ShenandoahStoreBarrierStubC2* create(const MachNode* node, Address dst, bool dst_narrow, Register src, bool src_narrow, Register tmp);
199 
200   void emit_code(MacroAssembler& masm) override;
201 };
202 
203 
204 class ShenandoahLoadRefBarrierStubC2 : public ShenandoahBarrierStubC2 {
205   Register _obj;
206   Register _addr;
207   Register _tmp1;
208   Register _tmp2;
209   Register _tmp3;
210   bool _narrow;
211   ShenandoahLoadRefBarrierStubC2(const MachNode* node, Register obj, Register addr, Register tmp1, Register tmp2, Register tmp3, bool narrow) :
212     ShenandoahBarrierStubC2(node), _obj(obj), _addr(addr), _tmp1(tmp1), _tmp2(tmp2), _tmp3(tmp3), _narrow(narrow) {}
213 public:
214   static bool needs_barrier(const MachNode* node) {
215     return (node->barrier_data() & (ShenandoahBarrierStrong | ShenandoahBarrierWeak | ShenandoahBarrierPhantom | ShenandoahBarrierNative)) != 0;
216   }
217   static ShenandoahLoadRefBarrierStubC2* create(const MachNode* node, Register obj, Register addr, Register tmp1, Register tmp2, Register tmp3, bool narrow);
218   void emit_code(MacroAssembler& masm) override;
219 };
220 
221 class ShenandoahSATBBarrierStubC2 : public ShenandoahBarrierStubC2 {
222   Register _addr;
223   Register _preval;
224   Register _tmp;
225   bool _encoded_preval;
226   ShenandoahSATBBarrierStubC2(const MachNode* node, Register addr, Register preval, Register tmp, bool encoded_preval) :
227     ShenandoahBarrierStubC2(node), _addr(addr), _preval(preval), _tmp(tmp), _encoded_preval(encoded_preval) {}
228 
229 public:
230   static bool needs_barrier(const MachNode* node) {
231     return (node->barrier_data() & ShenandoahBarrierSATB) != 0;
232   }
233   static ShenandoahSATBBarrierStubC2* create(const MachNode* node, Register addr, Register preval, Register tmp, bool encoded_preval);
234 
235   void emit_code(MacroAssembler& masm) override;
236 };
237 
238 class ShenandoahCASBarrierSlowStubC2 : public ShenandoahBarrierStubC2 {
239   Register _addr_reg;
240   Address  _addr;
241   Register _expected;
242   Register _new_val;
243   Register _result;
244   Register _tmp1;
245   Register _tmp2;
246   bool     const _narrow;
247   bool     const _cae;
248   bool     const _acquire;
249   bool     const _release;
250   bool     const _weak;
251 
252   explicit ShenandoahCASBarrierSlowStubC2(const MachNode* node, Register addr_reg, Address addr, Register expected, Register new_val, Register result, Register tmp1, Register tmp2, bool narrow, bool cae, bool acquire, bool release, bool weak) :
253     ShenandoahBarrierStubC2(node),
254     _addr_reg(addr_reg), _addr(addr), _expected(expected), _new_val(new_val), _result(result), _tmp1(tmp1), _tmp2(tmp2), _narrow(narrow), _cae(cae), _acquire(acquire), _release(release),  _weak(weak) {}
255 
256 public:
257   static ShenandoahCASBarrierSlowStubC2* create(const MachNode* node, Register addr, Register expected, Register new_val, Register result, Register tmp1, Register tmp2, bool narrow, bool cae, bool acquire, bool release, bool weak);
258   static ShenandoahCASBarrierSlowStubC2* create(const MachNode* node, Address addr, Register expected, Register new_val, Register result, Register tmp1, Register tmp2, bool narrow, bool cae);
259   void emit_code(MacroAssembler& masm) override;
260 };
261 #endif // SHARE_GC_SHENANDOAH_C2_SHENANDOAHBARRIERSETC2_HPP
--- EOF ---