|
1 /* |
|
2 * Copyright (c) 2018, 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_G1_C1_G1BARRIERSETC1_HPP |
|
26 #define SHARE_GC_G1_C1_G1BARRIERSETC1_HPP |
|
27 |
|
28 #include "c1/c1_CodeStubs.hpp" |
|
29 #include "gc/shared/c1/modRefBarrierSetC1.hpp" |
|
30 |
|
31 class G1PreBarrierStub: public CodeStub { |
|
32 friend class G1BarrierSetC1; |
|
33 private: |
|
34 bool _do_load; |
|
35 LIR_Opr _addr; |
|
36 LIR_Opr _pre_val; |
|
37 LIR_PatchCode _patch_code; |
|
38 CodeEmitInfo* _info; |
|
39 |
|
40 public: |
|
41 // Version that _does_ generate a load of the previous value from addr. |
|
42 // addr (the address of the field to be read) must be a LIR_Address |
|
43 // pre_val (a temporary register) must be a register; |
|
44 G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : |
|
45 _addr(addr), _pre_val(pre_val), _do_load(true), |
|
46 _patch_code(patch_code), _info(info) |
|
47 { |
|
48 assert(_pre_val->is_register(), "should be temporary register"); |
|
49 assert(_addr->is_address(), "should be the address of the field"); |
|
50 } |
|
51 |
|
52 // Version that _does not_ generate load of the previous value; the |
|
53 // previous value is assumed to have already been loaded into pre_val. |
|
54 G1PreBarrierStub(LIR_Opr pre_val) : |
|
55 _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false), |
|
56 _patch_code(lir_patch_none), _info(NULL) |
|
57 { |
|
58 assert(_pre_val->is_register(), "should be a register"); |
|
59 } |
|
60 |
|
61 LIR_Opr addr() const { return _addr; } |
|
62 LIR_Opr pre_val() const { return _pre_val; } |
|
63 LIR_PatchCode patch_code() const { return _patch_code; } |
|
64 CodeEmitInfo* info() const { return _info; } |
|
65 bool do_load() const { return _do_load; } |
|
66 |
|
67 virtual void emit_code(LIR_Assembler* e); |
|
68 virtual void visit(LIR_OpVisitState* visitor) { |
|
69 if (_do_load) { |
|
70 // don't pass in the code emit info since it's processed in the fast |
|
71 // path |
|
72 if (_info != NULL) |
|
73 visitor->do_slow_case(_info); |
|
74 else |
|
75 visitor->do_slow_case(); |
|
76 |
|
77 visitor->do_input(_addr); |
|
78 visitor->do_temp(_pre_val); |
|
79 } else { |
|
80 visitor->do_slow_case(); |
|
81 visitor->do_input(_pre_val); |
|
82 } |
|
83 } |
|
84 #ifndef PRODUCT |
|
85 virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); } |
|
86 #endif // PRODUCT |
|
87 }; |
|
88 |
|
89 class G1PostBarrierStub: public CodeStub { |
|
90 friend class G1BarrierSetC1; |
|
91 private: |
|
92 LIR_Opr _addr; |
|
93 LIR_Opr _new_val; |
|
94 |
|
95 public: |
|
96 // addr (the address of the object head) and new_val must be registers. |
|
97 G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { } |
|
98 |
|
99 LIR_Opr addr() const { return _addr; } |
|
100 LIR_Opr new_val() const { return _new_val; } |
|
101 |
|
102 virtual void emit_code(LIR_Assembler* e); |
|
103 virtual void visit(LIR_OpVisitState* visitor) { |
|
104 // don't pass in the code emit info since it's processed in the fast path |
|
105 visitor->do_slow_case(); |
|
106 visitor->do_input(_addr); |
|
107 visitor->do_input(_new_val); |
|
108 } |
|
109 #ifndef PRODUCT |
|
110 virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); } |
|
111 #endif // PRODUCT |
|
112 }; |
|
113 |
|
114 class CodeBlob; |
|
115 |
|
116 class G1BarrierSetC1 : public ModRefBarrierSetC1 { |
|
117 protected: |
|
118 CodeBlob* _pre_barrier_c1_runtime_code_blob; |
|
119 CodeBlob* _post_barrier_c1_runtime_code_blob; |
|
120 |
|
121 virtual void pre_barrier(LIRAccess& access, LIR_Opr addr_opr, |
|
122 LIR_Opr pre_val, CodeEmitInfo* info); |
|
123 virtual void post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprDesc* new_val); |
|
124 |
|
125 virtual void load_at_resolved(LIRAccess& access, LIR_Opr result); |
|
126 |
|
127 public: |
|
128 G1BarrierSetC1() |
|
129 : _pre_barrier_c1_runtime_code_blob(NULL), |
|
130 _post_barrier_c1_runtime_code_blob(NULL) {} |
|
131 |
|
132 CodeBlob* pre_barrier_c1_runtime_code_blob() { return _pre_barrier_c1_runtime_code_blob; } |
|
133 CodeBlob* post_barrier_c1_runtime_code_blob() { return _post_barrier_c1_runtime_code_blob; } |
|
134 |
|
135 virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob); |
|
136 }; |
|
137 |
|
138 #endif // SHARE_GC_G1_C1_G1BARRIERSETC1_HPP |