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