Mercurial > hg > graal-compiler
comparison src/share/vm/c1/c1_ValueStack.hpp @ 1819:f02a8bbe6ed4
6986046: C1 valuestack cleanup
Summary: fixes an historical oddity in C1 with inlining where all of the expression stacks are kept in the topmost ValueStack instead of being in their respective ValueStacks.
Reviewed-by: never
Contributed-by: Christian Wimmer <cwimmer@uci.edu>
author | roland |
---|---|
date | Tue, 29 Dec 2009 19:08:54 +0100 |
parents | b812ff5abc73 |
children | 1375bc8922e4 |
comparison
equal
deleted
inserted
replaced
1817:c40600e85311 | 1819:f02a8bbe6ed4 |
---|---|
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 class ValueStack: public CompilationResourceObj { | 25 class ValueStack: public CompilationResourceObj { |
26 public: | |
27 enum Kind { | |
28 Parsing, // During abstract interpretation in GraphBuilder | |
29 CallerState, // Caller state when inlining | |
30 StateBefore, // Before before execution of instruction | |
31 StateAfter, // After execution of instruction | |
32 ExceptionState, // Exception handling of instruction | |
33 EmptyExceptionState, // Exception handling of instructions not covered by an xhandler | |
34 BlockBeginState // State of BlockBegin instruction with phi functions of this block | |
35 }; | |
36 | |
26 private: | 37 private: |
27 IRScope* _scope; // the enclosing scope | 38 IRScope* _scope; // the enclosing scope |
28 bool _lock_stack; // indicates that this ValueStack is for an exception site | 39 ValueStack* _caller_state; |
40 int _bci; | |
41 Kind _kind; | |
42 | |
29 Values _locals; // the locals | 43 Values _locals; // the locals |
30 Values _stack; // the expression stack | 44 Values _stack; // the expression stack |
31 Values _locks; // the monitor stack (holding the locked values) | 45 Values _locks; // the monitor stack (holding the locked values) |
32 | 46 |
33 Value check(ValueTag tag, Value t) { | 47 Value check(ValueTag tag, Value t) { |
34 assert(tag == t->type()->tag() || tag == objectTag && t->type()->tag() == addressTag, "types must correspond"); | 48 assert(tag == t->type()->tag() || tag == objectTag && t->type()->tag() == addressTag, "types must correspond"); |
35 return t; | 49 return t; |
36 } | 50 } |
37 | 51 |
38 Value check(ValueTag tag, Value t, Value h) { | 52 Value check(ValueTag tag, Value t, Value h) { |
39 assert(h->as_HiWord()->lo_word() == t, "incorrect stack pair"); | 53 assert(h == NULL, "hi-word of doubleword value must be NULL"); |
40 return check(tag, t); | 54 return check(tag, t); |
41 } | 55 } |
42 | 56 |
43 // helper routine | 57 // helper routine |
44 static void apply(Values list, ValueVisitor* f); | 58 static void apply(Values list, ValueVisitor* f); |
45 | 59 |
60 // for simplified copying | |
61 ValueStack(ValueStack* copy_from, Kind kind, int bci); | |
62 | |
46 public: | 63 public: |
47 // creation | 64 // creation |
48 ValueStack(IRScope* scope, int locals_size, int max_stack_size); | 65 ValueStack(IRScope* scope, ValueStack* caller_state); |
49 | 66 |
50 // merging | 67 ValueStack* copy() { return new ValueStack(this, _kind, _bci); } |
51 ValueStack* copy(); // returns a copy of this w/ cleared locals | 68 ValueStack* copy(Kind new_kind, int new_bci) { return new ValueStack(this, new_kind, new_bci); } |
52 ValueStack* copy_locks(); // returns a copy of this w/ cleared locals and stack | 69 ValueStack* copy_for_parsing() { return new ValueStack(this, Parsing, -99); } |
53 // Note that when inlining of methods with exception | 70 |
54 // handlers is enabled, this stack may have a | 71 void set_caller_state(ValueStack* s) { assert(kind() == EmptyExceptionState, "only EmptyExceptionStates can be modified"); _caller_state = s; } |
55 // non-empty expression stack (size defined by | 72 |
56 // scope()->lock_stack_size()) | |
57 bool is_same(ValueStack* s); // returns true if this & s's types match (w/o checking locals) | 73 bool is_same(ValueStack* s); // returns true if this & s's types match (w/o checking locals) |
58 bool is_same_across_scopes(ValueStack* s); // same as is_same but returns true even if stacks are in different scopes (used for block merging w/inlining) | |
59 | 74 |
60 // accessors | 75 // accessors |
61 IRScope* scope() const { return _scope; } | 76 IRScope* scope() const { return _scope; } |
62 bool is_lock_stack() const { return _lock_stack; } | 77 ValueStack* caller_state() const { return _caller_state; } |
78 int bci() const { return _bci; } | |
79 Kind kind() const { return _kind; } | |
80 | |
63 int locals_size() const { return _locals.length(); } | 81 int locals_size() const { return _locals.length(); } |
64 int stack_size() const { return _stack.length(); } | 82 int stack_size() const { return _stack.length(); } |
65 int locks_size() const { return _locks.length(); } | 83 int locks_size() const { return _locks.length(); } |
66 int max_stack_size() const { return _stack.capacity(); } | |
67 bool stack_is_empty() const { return _stack.is_empty(); } | 84 bool stack_is_empty() const { return _stack.is_empty(); } |
68 bool no_active_locks() const { return _locks.is_empty(); } | 85 bool no_active_locks() const { return _locks.is_empty(); } |
69 ValueStack* caller_state() const; | 86 int total_locks_size() const; |
70 | 87 |
71 // locals access | 88 // locals access |
72 void clear_locals(); // sets all locals to NULL; | 89 void clear_locals(); // sets all locals to NULL; |
73 | 90 |
74 // Kill local i. Also kill local i+1 if i was a long or double. | |
75 void invalidate_local(int i) { | 91 void invalidate_local(int i) { |
92 assert(_locals.at(i)->type()->is_single_word() || | |
93 _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); | |
94 _locals.at_put(i, NULL); | |
95 } | |
96 | |
97 Value local_at(int i) const { | |
76 Value x = _locals.at(i); | 98 Value x = _locals.at(i); |
77 if (x != NULL && x->type()->is_double_word()) { | 99 assert(x == NULL || x->type()->is_single_word() || |
78 assert(_locals.at(i + 1)->as_HiWord()->lo_word() == x, "locals inconsistent"); | 100 _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); |
79 _locals.at_put(i + 1, NULL); | |
80 } | |
81 _locals.at_put(i, NULL); | |
82 } | |
83 | |
84 | |
85 Value load_local(int i) const { | |
86 Value x = _locals.at(i); | |
87 if (x != NULL && x->type()->is_illegal()) return NULL; | |
88 assert(x == NULL || x->as_HiWord() == NULL, "index points to hi word"); | |
89 assert(x == NULL || x->type()->is_illegal() || x->type()->is_single_word() || x == _locals.at(i+1)->as_HiWord()->lo_word(), "locals inconsistent"); | |
90 return x; | 101 return x; |
91 } | 102 } |
92 | 103 |
93 Value local_at(int i) const { return _locals.at(i); } | |
94 | |
95 // Store x into local i. | |
96 void store_local(int i, Value x) { | 104 void store_local(int i, Value x) { |
97 // Kill the old value | 105 // When overwriting local i, check if i - 1 was the start of a |
98 invalidate_local(i); | 106 // double word local and kill it. |
99 _locals.at_put(i, x); | |
100 | |
101 // Writing a double word can kill other locals | |
102 if (x != NULL && x->type()->is_double_word()) { | |
103 // If x + i was the start of a double word local then kill i + 2. | |
104 Value x2 = _locals.at(i + 1); | |
105 if (x2 != NULL && x2->type()->is_double_word()) { | |
106 _locals.at_put(i + 2, NULL); | |
107 } | |
108 | |
109 // If x is a double word local, also update i + 1. | |
110 #ifdef ASSERT | |
111 _locals.at_put(i + 1, x->hi_word()); | |
112 #else | |
113 _locals.at_put(i + 1, NULL); | |
114 #endif | |
115 } | |
116 // If x - 1 was the start of a double word local then kill i - 1. | |
117 if (i > 0) { | 107 if (i > 0) { |
118 Value prev = _locals.at(i - 1); | 108 Value prev = _locals.at(i - 1); |
119 if (prev != NULL && prev->type()->is_double_word()) { | 109 if (prev != NULL && prev->type()->is_double_word()) { |
120 _locals.at_put(i - 1, NULL); | 110 _locals.at_put(i - 1, NULL); |
121 } | 111 } |
122 } | 112 } |
123 } | 113 |
124 | 114 _locals.at_put(i, x); |
125 void replace_locals(ValueStack* with); | 115 if (x->type()->is_double_word()) { |
116 // hi-word of doubleword value is always NULL | |
117 _locals.at_put(i + 1, NULL); | |
118 } | |
119 } | |
126 | 120 |
127 // stack access | 121 // stack access |
128 Value stack_at(int i) const { | 122 Value stack_at(int i) const { |
129 Value x = _stack.at(i); | 123 Value x = _stack.at(i); |
130 assert(x->as_HiWord() == NULL, "index points to hi word"); | |
131 assert(x->type()->is_single_word() || | 124 assert(x->type()->is_single_word() || |
132 x->subst() == _stack.at(i+1)->as_HiWord()->lo_word(), "stack inconsistent"); | 125 _stack.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); |
133 return x; | 126 return x; |
134 } | 127 } |
135 | 128 |
136 Value stack_at_inc(int& i) const { | 129 Value stack_at_inc(int& i) const { |
137 Value x = stack_at(i); | 130 Value x = stack_at(i); |
144 | 137 |
145 // iteration | 138 // iteration |
146 void values_do(ValueVisitor* f); | 139 void values_do(ValueVisitor* f); |
147 | 140 |
148 // untyped manipulation (for dup_x1, etc.) | 141 // untyped manipulation (for dup_x1, etc.) |
149 void clear_stack() { _stack.clear(); } | |
150 void truncate_stack(int size) { _stack.trunc_to(size); } | 142 void truncate_stack(int size) { _stack.trunc_to(size); } |
151 void raw_push(Value t) { _stack.push(t); } | 143 void raw_push(Value t) { _stack.push(t); } |
152 Value raw_pop() { return _stack.pop(); } | 144 Value raw_pop() { return _stack.pop(); } |
153 | 145 |
154 // typed manipulation | 146 // typed manipulation |
155 void ipush(Value t) { _stack.push(check(intTag , t)); } | 147 void ipush(Value t) { _stack.push(check(intTag , t)); } |
156 void fpush(Value t) { _stack.push(check(floatTag , t)); } | 148 void fpush(Value t) { _stack.push(check(floatTag , t)); } |
157 void apush(Value t) { _stack.push(check(objectTag , t)); } | 149 void apush(Value t) { _stack.push(check(objectTag , t)); } |
158 void rpush(Value t) { _stack.push(check(addressTag, t)); } | 150 void rpush(Value t) { _stack.push(check(addressTag, t)); } |
159 #ifdef ASSERT | |
160 // in debug mode, use HiWord for 2-word values | |
161 void lpush(Value t) { _stack.push(check(longTag , t)); _stack.push(new HiWord(t)); } | |
162 void dpush(Value t) { _stack.push(check(doubleTag , t)); _stack.push(new HiWord(t)); } | |
163 #else | |
164 // in optimized mode, use NULL for 2-word values | |
165 void lpush(Value t) { _stack.push(check(longTag , t)); _stack.push(NULL); } | 151 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); } | 152 void dpush(Value t) { _stack.push(check(doubleTag , t)); _stack.push(NULL); } |
167 #endif // ASSERT | |
168 | 153 |
169 void push(ValueType* type, Value t) { | 154 void push(ValueType* type, Value t) { |
170 switch (type->tag()) { | 155 switch (type->tag()) { |
171 case intTag : ipush(t); return; | 156 case intTag : ipush(t); return; |
172 case longTag : lpush(t); return; | 157 case longTag : lpush(t); return; |
180 | 165 |
181 Value ipop() { return check(intTag , _stack.pop()); } | 166 Value ipop() { return check(intTag , _stack.pop()); } |
182 Value fpop() { return check(floatTag , _stack.pop()); } | 167 Value fpop() { return check(floatTag , _stack.pop()); } |
183 Value apop() { return check(objectTag , _stack.pop()); } | 168 Value apop() { return check(objectTag , _stack.pop()); } |
184 Value rpop() { return check(addressTag, _stack.pop()); } | 169 Value rpop() { return check(addressTag, _stack.pop()); } |
185 #ifdef ASSERT | |
186 // in debug mode, check for HiWord consistency | |
187 Value lpop() { Value h = _stack.pop(); return check(longTag , _stack.pop(), h); } | 170 Value lpop() { Value h = _stack.pop(); return check(longTag , _stack.pop(), h); } |
188 Value dpop() { Value h = _stack.pop(); return check(doubleTag, _stack.pop(), h); } | 171 Value dpop() { Value h = _stack.pop(); return check(doubleTag, _stack.pop(), h); } |
189 #else | |
190 // in optimized mode, ignore HiWord since it is NULL | |
191 Value lpop() { _stack.pop(); return check(longTag , _stack.pop()); } | |
192 Value dpop() { _stack.pop(); return check(doubleTag, _stack.pop()); } | |
193 #endif // ASSERT | |
194 | 172 |
195 Value pop(ValueType* type) { | 173 Value pop(ValueType* type) { |
196 switch (type->tag()) { | 174 switch (type->tag()) { |
197 case intTag : return ipop(); | 175 case intTag : return ipop(); |
198 case longTag : return lpop(); | 176 case longTag : return lpop(); |
206 } | 184 } |
207 | 185 |
208 Values* pop_arguments(int argument_size); | 186 Values* pop_arguments(int argument_size); |
209 | 187 |
210 // locks access | 188 // locks access |
211 int lock (IRScope* scope, Value obj); | 189 int lock (Value obj); |
212 int unlock(); | 190 int unlock(); |
213 Value lock_at(int i) const { return _locks.at(i); } | 191 Value lock_at(int i) const { return _locks.at(i); } |
214 | |
215 // Inlining support | |
216 ValueStack* push_scope(IRScope* scope); // "Push" new scope, returning new resulting stack | |
217 // Preserves stack and locks, destroys locals | |
218 ValueStack* pop_scope(); // "Pop" topmost scope, returning new resulting stack | |
219 // Preserves stack and locks, destroys locals | |
220 | 192 |
221 // SSA form IR support | 193 // SSA form IR support |
222 void setup_phi_for_stack(BlockBegin* b, int index); | 194 void setup_phi_for_stack(BlockBegin* b, int index); |
223 void setup_phi_for_local(BlockBegin* b, int index); | 195 void setup_phi_for_local(BlockBegin* b, int index); |
224 | 196 |
296 | 268 |
297 #define for_each_state_value(v_state, v_value, v_code) \ | 269 #define for_each_state_value(v_state, v_value, v_code) \ |
298 { \ | 270 { \ |
299 int cur_index; \ | 271 int cur_index; \ |
300 ValueStack* cur_state = v_state; \ | 272 ValueStack* cur_state = v_state; \ |
301 Value v_value; \ | 273 Value v_value; \ |
302 { \ | 274 for_each_state(cur_state) { \ |
303 for_each_stack_value(cur_state, cur_index, v_value) { \ | 275 { \ |
304 v_code; \ | 276 for_each_local_value(cur_state, cur_index, v_value) { \ |
277 v_code; \ | |
278 } \ | |
305 } \ | 279 } \ |
306 } \ | 280 { \ |
307 for_each_state(cur_state) { \ | 281 for_each_stack_value(cur_state, cur_index, v_value) { \ |
308 for_each_local_value(cur_state, cur_index, v_value) { \ | 282 v_code; \ |
309 v_code; \ | 283 } \ |
310 } \ | 284 } \ |
311 } \ | 285 } \ |
312 } | 286 } |
313 | 287 |
314 | 288 |
315 // Macro definition for simple iteration of all phif functions of a block, i.e all | 289 // Macro definition for simple iteration of all phif functions of a block, i.e all |