1 /* 2 * Copyright (c) 2015, 2019, 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 #ifndef SHARE_GC_Z_C2_ZBARRIERSETC2_HPP 25 #define SHARE_GC_Z_C2_ZBARRIERSETC2_HPP 26 27 #include "gc/shared/c2/barrierSetC2.hpp" 28 #include "memory/allocation.hpp" 29 #include "opto/node.hpp" 30 #include "utilities/growableArray.hpp" 31 32 class ZCompareAndSwapPNode : public CompareAndSwapPNode { 33 public: 34 ZCompareAndSwapPNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapPNode(c, mem, adr, val, ex, mem_ord) { } 35 virtual int Opcode() const; 36 }; 37 38 class ZWeakCompareAndSwapPNode : public WeakCompareAndSwapPNode { 39 public: 40 ZWeakCompareAndSwapPNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : WeakCompareAndSwapPNode(c, mem, adr, val, ex, mem_ord) { } 41 virtual int Opcode() const; 42 }; 43 44 class ZCompareAndExchangePNode : public CompareAndExchangePNode { 45 public: 46 ZCompareAndExchangePNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangePNode(c, mem, adr, val, ex, at, t, mem_ord) { } 47 virtual int Opcode() const; 48 }; 49 50 class ZGetAndSetPNode : public GetAndSetPNode { 51 public: 52 ZGetAndSetPNode(Node* c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* t) : GetAndSetPNode(c, mem, adr, val, at, t) { } 53 virtual int Opcode() const; 54 }; 55 56 class LoadBarrierNode : public MultiNode { 57 private: 58 bool _weak; // On strong or weak oop reference 59 static bool is_dominator(PhaseIdealLoop* phase, bool linear_only, Node *d, Node *n); 60 void push_dominated_barriers(PhaseIterGVN* igvn) const; 61 62 public: 63 enum { 64 Control, 65 Memory, 66 Oop, 67 Address, 68 Number_of_Outputs = Address, 69 Similar, 70 Number_of_Inputs 71 }; 72 73 LoadBarrierNode(Compile* C, 74 Node* c, 75 Node* mem, 76 Node* val, 77 Node* adr, 78 bool weak); 79 80 virtual int Opcode() const; 81 virtual uint size_of() const; 82 virtual bool cmp(const Node& n) const; 83 virtual const Type *bottom_type() const; 84 virtual const TypePtr* adr_type() const; 85 virtual const Type *Value(PhaseGVN *phase) const; 86 virtual Node *Identity(PhaseGVN *phase); 87 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 88 virtual uint match_edge(uint idx) const; 89 90 LoadBarrierNode* has_dominating_barrier(PhaseIdealLoop* phase, 91 bool linear_only, 92 bool look_for_similar); 93 94 void fix_similar_in_uses(PhaseIterGVN* igvn); 95 96 bool has_true_uses() const; 97 98 bool can_be_eliminated() const { 99 return !in(Similar)->is_top(); 100 } 101 102 bool is_weak() const { 103 return _weak; 104 } 105 }; 106 107 class LoadBarrierSlowRegNode : public LoadPNode { 108 private: 109 bool _is_weak; 110 public: 111 LoadBarrierSlowRegNode(Node *c, 112 Node *mem, 113 Node *adr, 114 const TypePtr *at, 115 const TypePtr* t, 116 MemOrd mo, 117 bool weak = false, 118 ControlDependency control_dependency = DependsOnlyOnTest) : 119 LoadPNode(c, mem, adr, at, t, mo, control_dependency), _is_weak(weak) { 120 init_class_id(Class_LoadBarrierSlowReg); 121 } 122 123 virtual const char * name() { 124 return "LoadBarrierSlowRegNode"; 125 } 126 127 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { 128 return NULL; 129 } 130 131 virtual int Opcode() const; 132 133 bool is_weak() { return _is_weak; } 134 }; 135 136 class ZBarrierSetC2State : public ResourceObj { 137 private: 138 // List of load barrier nodes which need to be expanded before matching 139 GrowableArray<LoadBarrierNode*>* _load_barrier_nodes; 140 141 public: 142 ZBarrierSetC2State(Arena* comp_arena); 143 int load_barrier_count() const; 144 void add_load_barrier_node(LoadBarrierNode* n); 145 void remove_load_barrier_node(LoadBarrierNode* n); 146 LoadBarrierNode* load_barrier_node(int idx) const; 147 }; 148 149 class ZBarrierSetC2 : public BarrierSetC2 { 150 private: 151 ZBarrierSetC2State* state() const; 152 void expand_loadbarrier_node(PhaseMacroExpand* phase, LoadBarrierNode* barrier) const; 153 154 #ifdef ASSERT 155 void verify_gc_barriers(bool post_parse) const; 156 #endif 157 158 protected: 159 virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const; 160 virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, 161 Node* expected_val, 162 Node* new_val, 163 const Type* val_type) const; 164 virtual Node* atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, 165 Node* expected_val, 166 Node* new_val, 167 const Type* value_type) const; 168 virtual Node* atomic_xchg_at_resolved(C2AtomicParseAccess& access, 169 Node* new_val, 170 const Type* val_type) const; 171 172 public: 173 virtual void* create_barrier_state(Arena* comp_arena) const; 174 175 virtual bool has_load_barriers() const { return true; } 176 virtual bool is_gc_barrier_node(Node* node) const; 177 virtual Node* step_over_gc_barrier(Node* c) const; 178 179 virtual void register_potential_barrier_node(Node* node) const; 180 virtual void unregister_potential_barrier_node(Node* node) const; 181 virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { } 182 virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const; 183 virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const; 184 185 virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const; 186 187 virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const; 188 virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode) const; 189 virtual bool matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const; 190 virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const; 191 virtual bool needs_anti_dependence_check(const Node* node) const; 192 193 #ifdef ASSERT 194 virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const; 195 #endif 196 197 // Load barrier insertion and expansion external 198 virtual void barrier_insertion_phase(PhaseIterGVN &igvn) const; 199 virtual void barrier_insertion(PhaseIdealLoop* phase) const; 200 201 private: 202 // Load barrier insertion and expansion internal 203 void insert_barriers_on_unsafe(PhaseIdealLoop* phase) const; 204 void clean_catch_blocks(PhaseIdealLoop* phase) const; 205 void insert_load_barriers(PhaseIdealLoop* phase) const; 206 LoadNode* insert_one_loadbarrier(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl) const; 207 void insert_one_loadbarrier_inner(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl, VectorSet visited) const; 208 }; 209 210 #endif // SHARE_GC_Z_C2_ZBARRIERSETC2_HPP