1 /*
2 * Copyright (c) 2018, 2025, 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 *
244 // Registers that are live-in/live-out of the entire memory access
245 // implementation (possibly including multiple barriers). Whether live-in or
246 // live-out registers are returned depends on
247 // BarrierSetC2State::needs_livein_data().
248 RegMask& live() const;
249
250 public:
251 BarrierStubC2(const MachNode* node);
252
253 // Entry point to the stub.
254 Label* entry();
255 // Return point from the stub (typically end of barrier).
256 Label* continuation();
257 // High-level, GC-specific barrier flags.
258 uint8_t barrier_data() const;
259
260 // Preserve the value in reg across runtime calls in this barrier.
261 void preserve(Register reg);
262 // Do not preserve the value in reg across runtime calls in this barrier.
263 void dont_preserve(Register reg);
264 // Set of registers whose value needs to be preserved across runtime calls in this barrier.
265 const RegMask& preserve_set() const;
266 };
267
268 // This is the top-level class for the backend of the Access API in C2.
269 // The top-level class is responsible for performing raw accesses. The
270 // various GC barrier sets inherit from the BarrierSetC2 class to sprinkle
271 // barriers into the accesses.
272 class BarrierSetC2: public CHeapObj<mtGC> {
273 private:
274 static const TypeFunc* _clone_type_Type;
275
276 protected:
277 virtual void resolve_address(C2Access& access) const;
278 virtual Node* store_at_resolved(C2Access& access, C2AccessValue& val) const;
279 virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const;
280
281 virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
282 Node* new_val, const Type* val_type) const;
283 virtual Node* atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
322 // Support for GC barriers emitted during parsing
323 virtual bool has_load_barrier_nodes() const { return false; }
324 virtual bool is_gc_pre_barrier_node(Node* node) const { return false; }
325 virtual bool is_gc_barrier_node(Node* node) const { return false; }
326 virtual Node* step_over_gc_barrier(Node* c) const { return c; }
327
328 // Support for macro expanded GC barriers
329 virtual void register_potential_barrier_node(Node* node) const { }
330 virtual void unregister_potential_barrier_node(Node* node) const { }
331 virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { }
332 virtual void eliminate_gc_barrier_data(Node* node) const { }
333 virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const {}
334 virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const {}
335
336 // Allow barrier sets to have shared state that is preserved across a compilation unit.
337 // This could for example comprise macro nodes to be expanded during macro expansion.
338 virtual void* create_barrier_state(Arena* comp_arena) const { return nullptr; }
339 // If the BarrierSetC2 state has barrier nodes in its compilation
340 // unit state to be expanded later, then now is the time to do so.
341 virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const { return false; }
342 virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const { return false; }
343 virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return false; }
344 virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return false; }
345 // Estimated size of the node barrier in number of C2 Ideal nodes.
346 // This is used to guide heuristics in C2, e.g. whether to unroll a loop.
347 virtual uint estimated_barrier_size(const Node* node) const { return 0; }
348 // Whether the given store can be used to initialize a newly allocated object.
349 virtual bool can_initialize_object(const StoreNode* store) const { return true; }
350
351 enum CompilePhase {
352 BeforeOptimize,
353 BeforeMacroExpand,
354 BeforeCodeGen
355 };
356
357 #ifdef ASSERT
358 virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const {}
359 #endif
360
361 virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode, Unique_Node_List& dead_nodes) const { return false; }
362
363 virtual bool escape_add_to_con_graph(ConnectionGraph* conn_graph, PhaseGVN* gvn, Unique_Node_List* delayed_worklist, Node* n, uint opcode) const { return false; }
364 virtual bool escape_add_final_edges(ConnectionGraph* conn_graph, PhaseGVN* gvn, Node* n, uint opcode) const { return false; }
365 virtual bool escape_has_out_with_unsafe_object(Node* n) const { return false; }
366
367 virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const { return false; };
368 virtual bool matcher_is_store_load_barrier(Node* x, uint xop) const { return false; }
369
370 // Whether the given phi node joins OOPs from fast and slow allocation paths.
371 static bool is_allocation(const Node* node);
372 // Elide GC barriers from a Mach node according to elide_dominated_barriers().
373 virtual void elide_dominated_barrier(MachNode* mach) const { }
374 // Elide GC barriers from instructions in 'accesses' if they are dominated by
375 // instructions in 'access_dominators' (according to elide_mach_barrier()) and
376 // there is no safepoint poll in between.
377 void elide_dominated_barriers(Node_List& accesses, Node_List& access_dominators) const;
378 virtual void late_barrier_analysis() const { }
379 virtual void compute_liveness_at_stubs() const;
380 virtual int estimate_stub_size() const { return 0; }
381 virtual void emit_stubs(CodeBuffer& cb) const { }
382
383 static int arraycopy_payload_base_offset(bool is_array);
384
385 static void make_clone_type();
386 static const TypeFunc* clone_type();
387
388 #ifndef PRODUCT
389 virtual void dump_barrier_data(const MachNode* mach, outputStream* st) const {
390 st->print("%x", mach->barrier_data());
391 };
392 #endif
393 };
|
1 /*
2 * Copyright (c) 2018, 2026, 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 *
244 // Registers that are live-in/live-out of the entire memory access
245 // implementation (possibly including multiple barriers). Whether live-in or
246 // live-out registers are returned depends on
247 // BarrierSetC2State::needs_livein_data().
248 RegMask& live() const;
249
250 public:
251 BarrierStubC2(const MachNode* node);
252
253 // Entry point to the stub.
254 Label* entry();
255 // Return point from the stub (typically end of barrier).
256 Label* continuation();
257 // High-level, GC-specific barrier flags.
258 uint8_t barrier_data() const;
259
260 // Preserve the value in reg across runtime calls in this barrier.
261 void preserve(Register reg);
262 // Do not preserve the value in reg across runtime calls in this barrier.
263 void dont_preserve(Register reg);
264 // Check if register is in preserved set
265 bool is_preserved(Register reg) const;
266 // Set of registers whose value needs to be preserved across runtime calls in this barrier.
267 const RegMask& preserve_set() const;
268 };
269
270 // This is the top-level class for the backend of the Access API in C2.
271 // The top-level class is responsible for performing raw accesses. The
272 // various GC barrier sets inherit from the BarrierSetC2 class to sprinkle
273 // barriers into the accesses.
274 class BarrierSetC2: public CHeapObj<mtGC> {
275 private:
276 static const TypeFunc* _clone_type_Type;
277
278 protected:
279 virtual void resolve_address(C2Access& access) const;
280 virtual Node* store_at_resolved(C2Access& access, C2AccessValue& val) const;
281 virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const;
282
283 virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
284 Node* new_val, const Type* val_type) const;
285 virtual Node* atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
324 // Support for GC barriers emitted during parsing
325 virtual bool has_load_barrier_nodes() const { return false; }
326 virtual bool is_gc_pre_barrier_node(Node* node) const { return false; }
327 virtual bool is_gc_barrier_node(Node* node) const { return false; }
328 virtual Node* step_over_gc_barrier(Node* c) const { return c; }
329
330 // Support for macro expanded GC barriers
331 virtual void register_potential_barrier_node(Node* node) const { }
332 virtual void unregister_potential_barrier_node(Node* node) const { }
333 virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { }
334 virtual void eliminate_gc_barrier_data(Node* node) const { }
335 virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const {}
336 virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const {}
337
338 // Allow barrier sets to have shared state that is preserved across a compilation unit.
339 // This could for example comprise macro nodes to be expanded during macro expansion.
340 virtual void* create_barrier_state(Arena* comp_arena) const { return nullptr; }
341 // If the BarrierSetC2 state has barrier nodes in its compilation
342 // unit state to be expanded later, then now is the time to do so.
343 virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const { return false; }
344 virtual void final_refinement(Compile* C) const { }
345 virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const { return false; }
346 virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return false; }
347 virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return false; }
348 // Estimated size of the node barrier in number of C2 Ideal nodes.
349 // This is used to guide heuristics in C2, e.g. whether to unroll a loop.
350 virtual uint estimated_barrier_size(const Node* node) const { return 0; }
351 // Whether the given store can be used to initialize a newly allocated object.
352 virtual bool can_initialize_object(const StoreNode* store) const { return true; }
353
354 enum CompilePhase {
355 BeforeOptimize,
356 BeforeMacroExpand,
357 BeforeCodeGen
358 };
359
360 #ifdef ASSERT
361 virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const {}
362 #endif
363
364 virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode, Unique_Node_List& dead_nodes) const { return false; }
365
366 virtual bool escape_add_to_con_graph(ConnectionGraph* conn_graph, PhaseGVN* gvn, Unique_Node_List* delayed_worklist, Node* n, uint opcode) const { return false; }
367 virtual bool escape_add_final_edges(ConnectionGraph* conn_graph, PhaseGVN* gvn, Node* n, uint opcode) const { return false; }
368 virtual bool escape_has_out_with_unsafe_object(Node* n) const { return false; }
369
370 virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const { return false; };
371 virtual bool matcher_is_store_load_barrier(Node* x, uint xop) const { return false; }
372
373 // Whether the given phi node joins OOPs from fast and slow allocation paths.
374 static bool is_allocation(const Node* node);
375 // Elide GC barriers from a Mach node according to elide_dominated_barriers().
376 virtual void elide_dominated_barrier(MachNode* mach, MachNode* dominator) const { }
377 // Elide GC barriers from instructions in 'accesses' if they are dominated by
378 // instructions in 'access_dominators' (according to elide_mach_barrier()) and
379 // there is no safepoint poll in between.
380 void elide_dominated_barriers(Node_List& accesses, Node_List& access_dominators) const;
381 virtual void late_barrier_analysis() const { }
382 virtual void compute_liveness_at_stubs() const;
383 virtual int estimate_stub_size() const { return 0; }
384 virtual void emit_stubs(CodeBuffer& cb) const { }
385
386 static int arraycopy_payload_base_offset(bool is_array);
387
388 static void make_clone_type();
389 static const TypeFunc* clone_type();
390
391 #ifndef PRODUCT
392 virtual void dump_barrier_data(const MachNode* mach, outputStream* st) const {
393 st->print("%x", mach->barrier_data());
394 };
395 #endif
396 };
|