Mercurial > hg > truffle
annotate src/share/vm/c1/c1_ValueStack.hpp @ 6862:8a5ea0a9ccc4
7127708: G1: change task num types from int to uint in concurrent mark
Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich.
Reviewed-by: johnc
Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
author | johnc |
---|---|
date | Sat, 06 Oct 2012 01:17:44 -0700 |
parents | 1d7922586cf6 |
children | b9a9ed0f8eeb |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_C1_C1_VALUESTACK_HPP |
26 #define SHARE_VM_C1_C1_VALUESTACK_HPP | |
27 | |
28 #include "c1/c1_Instruction.hpp" | |
29 | |
0 | 30 class ValueStack: public CompilationResourceObj { |
1819 | 31 public: |
32 enum Kind { | |
33 Parsing, // During abstract interpretation in GraphBuilder | |
34 CallerState, // Caller state when inlining | |
35 StateBefore, // Before before execution of instruction | |
36 StateAfter, // After execution of instruction | |
37 ExceptionState, // Exception handling of instruction | |
38 EmptyExceptionState, // Exception handling of instructions not covered by an xhandler | |
39 BlockBeginState // State of BlockBegin instruction with phi functions of this block | |
40 }; | |
41 | |
0 | 42 private: |
43 IRScope* _scope; // the enclosing scope | |
1819 | 44 ValueStack* _caller_state; |
45 int _bci; | |
46 Kind _kind; | |
47 | |
0 | 48 Values _locals; // the locals |
49 Values _stack; // the expression stack | |
50 Values _locks; // the monitor stack (holding the locked values) | |
51 | |
52 Value check(ValueTag tag, Value t) { | |
53 assert(tag == t->type()->tag() || tag == objectTag && t->type()->tag() == addressTag, "types must correspond"); | |
54 return t; | |
55 } | |
56 | |
57 Value check(ValueTag tag, Value t, Value h) { | |
1819 | 58 assert(h == NULL, "hi-word of doubleword value must be NULL"); |
0 | 59 return check(tag, t); |
60 } | |
61 | |
62 // helper routine | |
1584 | 63 static void apply(Values list, ValueVisitor* f); |
0 | 64 |
1819 | 65 // for simplified copying |
66 ValueStack(ValueStack* copy_from, Kind kind, int bci); | |
67 | |
0 | 68 public: |
69 // creation | |
1819 | 70 ValueStack(IRScope* scope, ValueStack* caller_state); |
0 | 71 |
1819 | 72 ValueStack* copy() { return new ValueStack(this, _kind, _bci); } |
73 ValueStack* copy(Kind new_kind, int new_bci) { return new ValueStack(this, new_kind, new_bci); } | |
74 ValueStack* copy_for_parsing() { return new ValueStack(this, Parsing, -99); } | |
75 | |
1822
1375bc8922e4
6987763: assert(kind() == EmptyExceptionState) failed: only EmptyExceptionStates can be modified
never
parents:
1819
diff
changeset
|
76 void set_caller_state(ValueStack* s) { |
1375bc8922e4
6987763: assert(kind() == EmptyExceptionState) failed: only EmptyExceptionStates can be modified
never
parents:
1819
diff
changeset
|
77 assert(kind() == EmptyExceptionState || |
1375bc8922e4
6987763: assert(kind() == EmptyExceptionState) failed: only EmptyExceptionStates can be modified
never
parents:
1819
diff
changeset
|
78 (Compilation::current()->env()->jvmti_can_access_local_variables() && kind() == ExceptionState), |
1375bc8922e4
6987763: assert(kind() == EmptyExceptionState) failed: only EmptyExceptionStates can be modified
never
parents:
1819
diff
changeset
|
79 "only EmptyExceptionStates can be modified"); |
1375bc8922e4
6987763: assert(kind() == EmptyExceptionState) failed: only EmptyExceptionStates can be modified
never
parents:
1819
diff
changeset
|
80 _caller_state = s; |
1375bc8922e4
6987763: assert(kind() == EmptyExceptionState) failed: only EmptyExceptionStates can be modified
never
parents:
1819
diff
changeset
|
81 } |
1819 | 82 |
0 | 83 bool is_same(ValueStack* s); // returns true if this & s's types match (w/o checking locals) |
84 | |
85 // accessors | |
86 IRScope* scope() const { return _scope; } | |
1819 | 87 ValueStack* caller_state() const { return _caller_state; } |
88 int bci() const { return _bci; } | |
89 Kind kind() const { return _kind; } | |
90 | |
0 | 91 int locals_size() const { return _locals.length(); } |
92 int stack_size() const { return _stack.length(); } | |
93 int locks_size() const { return _locks.length(); } | |
94 bool stack_is_empty() const { return _stack.is_empty(); } | |
95 bool no_active_locks() const { return _locks.is_empty(); } | |
1819 | 96 int total_locks_size() const; |
0 | 97 |
98 // locals access | |
99 void clear_locals(); // sets all locals to NULL; | |
100 | |
101 void invalidate_local(int i) { | |
1819 | 102 assert(_locals.at(i)->type()->is_single_word() || |
103 _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); | |
0 | 104 _locals.at_put(i, NULL); |
105 } | |
106 | |
1819 | 107 Value local_at(int i) const { |
0 | 108 Value x = _locals.at(i); |
1819 | 109 assert(x == NULL || x->type()->is_single_word() || |
110 _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); | |
0 | 111 return x; |
112 } | |
113 | |
114 void store_local(int i, Value x) { | |
1819 | 115 // When overwriting local i, check if i - 1 was the start of a |
116 // double word local and kill it. | |
0 | 117 if (i > 0) { |
118 Value prev = _locals.at(i - 1); | |
119 if (prev != NULL && prev->type()->is_double_word()) { | |
120 _locals.at_put(i - 1, NULL); | |
121 } | |
122 } | |
1819 | 123 |
124 _locals.at_put(i, x); | |
125 if (x->type()->is_double_word()) { | |
126 // hi-word of doubleword value is always NULL | |
127 _locals.at_put(i + 1, NULL); | |
128 } | |
0 | 129 } |
130 | |
131 // stack access | |
132 Value stack_at(int i) const { | |
133 Value x = _stack.at(i); | |
134 assert(x->type()->is_single_word() || | |
1819 | 135 _stack.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); |
0 | 136 return x; |
137 } | |
138 | |
139 Value stack_at_inc(int& i) const { | |
140 Value x = stack_at(i); | |
141 i += x->type()->size(); | |
142 return x; | |
143 } | |
144 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
1972
diff
changeset
|
145 void stack_at_put(int i, Value x) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
1972
diff
changeset
|
146 _stack.at_put(i, x); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
1972
diff
changeset
|
147 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
1972
diff
changeset
|
148 |
0 | 149 // pinning support |
150 void pin_stack_for_linear_scan(); | |
151 | |
152 // iteration | |
1584 | 153 void values_do(ValueVisitor* f); |
0 | 154 |
155 // untyped manipulation (for dup_x1, etc.) | |
156 void truncate_stack(int size) { _stack.trunc_to(size); } | |
157 void raw_push(Value t) { _stack.push(t); } | |
158 Value raw_pop() { return _stack.pop(); } | |
159 | |
160 // typed manipulation | |
161 void ipush(Value t) { _stack.push(check(intTag , t)); } | |
162 void fpush(Value t) { _stack.push(check(floatTag , t)); } | |
163 void apush(Value t) { _stack.push(check(objectTag , t)); } | |
164 void rpush(Value t) { _stack.push(check(addressTag, t)); } | |
165 void lpush(Value t) { _stack.push(check(longTag , t)); _stack.push(NULL); } | |
166 void dpush(Value t) { _stack.push(check(doubleTag , t)); _stack.push(NULL); } | |
167 | |
168 void push(ValueType* type, Value t) { | |
169 switch (type->tag()) { | |
170 case intTag : ipush(t); return; | |
171 case longTag : lpush(t); return; | |
172 case floatTag : fpush(t); return; | |
173 case doubleTag : dpush(t); return; | |
174 case objectTag : apush(t); return; | |
175 case addressTag: rpush(t); return; | |
176 } | |
177 ShouldNotReachHere(); | |
178 } | |
179 | |
180 Value ipop() { return check(intTag , _stack.pop()); } | |
181 Value fpop() { return check(floatTag , _stack.pop()); } | |
182 Value apop() { return check(objectTag , _stack.pop()); } | |
183 Value rpop() { return check(addressTag, _stack.pop()); } | |
184 Value lpop() { Value h = _stack.pop(); return check(longTag , _stack.pop(), h); } | |
185 Value dpop() { Value h = _stack.pop(); return check(doubleTag, _stack.pop(), h); } | |
186 | |
187 Value pop(ValueType* type) { | |
188 switch (type->tag()) { | |
189 case intTag : return ipop(); | |
190 case longTag : return lpop(); | |
191 case floatTag : return fpop(); | |
192 case doubleTag : return dpop(); | |
193 case objectTag : return apop(); | |
194 case addressTag: return rpop(); | |
195 } | |
196 ShouldNotReachHere(); | |
197 return NULL; | |
198 } | |
199 | |
200 Values* pop_arguments(int argument_size); | |
201 | |
202 // locks access | |
1819 | 203 int lock (Value obj); |
0 | 204 int unlock(); |
205 Value lock_at(int i) const { return _locks.at(i); } | |
206 | |
207 // SSA form IR support | |
208 void setup_phi_for_stack(BlockBegin* b, int index); | |
209 void setup_phi_for_local(BlockBegin* b, int index); | |
210 | |
211 // debugging | |
212 void print() PRODUCT_RETURN; | |
213 void verify() PRODUCT_RETURN; | |
214 }; | |
215 | |
216 | |
217 | |
218 // Macro definitions for simple iteration of stack and local values of a ValueStack | |
219 // The macros can be used like a for-loop. All variables (state, index and value) | |
220 // must be defined before the loop. | |
221 // When states are nested because of inlining, the stack of the innermost state | |
222 // cumulates also the stack of the nested states. In contrast, the locals of all | |
223 // states must be iterated each. | |
224 // Use the following code pattern to iterate all stack values and all nested local values: | |
225 // | |
226 // ValueStack* state = ... // state that is iterated | |
227 // int index; // current loop index (overwritten in loop) | |
228 // Value value; // value at current loop index (overwritten in loop) | |
229 // | |
230 // for_each_stack_value(state, index, value { | |
231 // do something with value and index | |
232 // } | |
233 // | |
234 // for_each_state(state) { | |
235 // for_each_local_value(state, index, value) { | |
236 // do something with value and index | |
237 // } | |
238 // } | |
239 // as an invariant, state is NULL now | |
240 | |
241 | |
242 // construct a unique variable name with the line number where the macro is used | |
243 #define temp_var3(x) temp__ ## x | |
244 #define temp_var2(x) temp_var3(x) | |
245 #define temp_var temp_var2(__LINE__) | |
246 | |
247 #define for_each_state(state) \ | |
248 for (; state != NULL; state = state->caller_state()) | |
249 | |
250 #define for_each_local_value(state, index, value) \ | |
251 int temp_var = state->locals_size(); \ | |
252 for (index = 0; \ | |
253 index < temp_var && (value = state->local_at(index), true); \ | |
254 index += (value == NULL || value->type()->is_illegal() ? 1 : value->type()->size())) \ | |
255 if (value != NULL) | |
256 | |
257 | |
258 #define for_each_stack_value(state, index, value) \ | |
259 int temp_var = state->stack_size(); \ | |
260 for (index = 0; \ | |
261 index < temp_var && (value = state->stack_at(index), true); \ | |
262 index += value->type()->size()) | |
263 | |
264 | |
265 #define for_each_lock_value(state, index, value) \ | |
266 int temp_var = state->locks_size(); \ | |
267 for (index = 0; \ | |
268 index < temp_var && (value = state->lock_at(index), true); \ | |
269 index++) \ | |
270 if (value != NULL) | |
271 | |
272 | |
273 // Macro definition for simple iteration of all state values of a ValueStack | |
274 // Because the code cannot be executed in a single loop, the code must be passed | |
275 // as a macro parameter. | |
276 // Use the following code pattern to iterate all stack values and all nested local values: | |
277 // | |
278 // ValueStack* state = ... // state that is iterated | |
279 // for_each_state_value(state, value, | |
280 // do something with value (note that this is a macro parameter) | |
281 // ); | |
282 | |
283 #define for_each_state_value(v_state, v_value, v_code) \ | |
284 { \ | |
285 int cur_index; \ | |
286 ValueStack* cur_state = v_state; \ | |
1819 | 287 Value v_value; \ |
288 for_each_state(cur_state) { \ | |
289 { \ | |
290 for_each_local_value(cur_state, cur_index, v_value) { \ | |
291 v_code; \ | |
292 } \ | |
0 | 293 } \ |
1819 | 294 { \ |
295 for_each_stack_value(cur_state, cur_index, v_value) { \ | |
296 v_code; \ | |
297 } \ | |
298 } \ | |
0 | 299 } \ |
300 } | |
301 | |
302 | |
303 // Macro definition for simple iteration of all phif functions of a block, i.e all | |
304 // phi functions of the ValueStack where the block matches. | |
305 // Use the following code pattern to iterate all phi functions of a block: | |
306 // | |
307 // BlockBegin* block = ... // block that is iterated | |
308 // for_each_phi_function(block, phi, | |
309 // do something with the phi function phi (note that this is a macro parameter) | |
310 // ); | |
311 | |
312 #define for_each_phi_fun(v_block, v_phi, v_code) \ | |
313 { \ | |
314 int cur_index; \ | |
315 ValueStack* cur_state = v_block->state(); \ | |
316 Value value; \ | |
317 { \ | |
318 for_each_stack_value(cur_state, cur_index, value) { \ | |
319 Phi* v_phi = value->as_Phi(); \ | |
320 if (v_phi != NULL && v_phi->block() == v_block) { \ | |
321 v_code; \ | |
322 } \ | |
323 } \ | |
324 } \ | |
325 { \ | |
326 for_each_local_value(cur_state, cur_index, value) { \ | |
327 Phi* v_phi = value->as_Phi(); \ | |
328 if (v_phi != NULL && v_phi->block() == v_block) { \ | |
329 v_code; \ | |
330 } \ | |
331 } \ | |
332 } \ | |
333 } | |
1972 | 334 |
335 #endif // SHARE_VM_C1_C1_VALUESTACK_HPP |