OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 30 matching lines...) Expand all Loading... |
41 | 41 |
42 | 42 |
43 void JumpTarget::Unuse() { | 43 void JumpTarget::Unuse() { |
44 reaching_frames_.Clear(); | 44 reaching_frames_.Clear(); |
45 merge_labels_.Clear(); | 45 merge_labels_.Clear(); |
46 entry_frame_ = NULL; | 46 entry_frame_ = NULL; |
47 entry_label_.Unuse(); | 47 entry_label_.Unuse(); |
48 } | 48 } |
49 | 49 |
50 | 50 |
51 void JumpTarget::ComputeEntryFrame() { | |
52 // Given: a collection of frames reaching by forward CFG edges and | |
53 // the directionality of the block. Compute: an entry frame for the | |
54 // block. | |
55 | |
56 Counters::compute_entry_frame.Increment(); | |
57 #ifdef DEBUG | |
58 if (compiling_deferred_code_) { | |
59 ASSERT(reaching_frames_.length() > 1); | |
60 VirtualFrame* frame = reaching_frames_[0]; | |
61 bool all_identical = true; | |
62 for (int i = 1; i < reaching_frames_.length(); i++) { | |
63 if (!frame->Equals(reaching_frames_[i])) { | |
64 all_identical = false; | |
65 break; | |
66 } | |
67 } | |
68 ASSERT(!all_identical || all_identical); | |
69 } | |
70 #endif | |
71 | |
72 // Choose an initial frame. | |
73 VirtualFrame* initial_frame = reaching_frames_[0]; | |
74 | |
75 // A list of pointers to frame elements in the entry frame. NULL | |
76 // indicates that the element has not yet been determined. | |
77 int length = initial_frame->element_count(); | |
78 ZoneList<FrameElement*> elements(length); | |
79 | |
80 // Initially populate the list of elements based on the initial | |
81 // frame. | |
82 for (int i = 0; i < length; i++) { | |
83 FrameElement element = initial_frame->elements_[i]; | |
84 // We do not allow copies or constants in bidirectional frames. | |
85 if (direction_ == BIDIRECTIONAL) { | |
86 if (element.is_constant() || element.is_copy()) { | |
87 elements.Add(NULL); | |
88 continue; | |
89 } | |
90 } | |
91 elements.Add(&initial_frame->elements_[i]); | |
92 } | |
93 | |
94 // Compute elements based on the other reaching frames. | |
95 if (reaching_frames_.length() > 1) { | |
96 for (int i = 0; i < length; i++) { | |
97 FrameElement* element = elements[i]; | |
98 for (int j = 1; j < reaching_frames_.length(); j++) { | |
99 // Element computation is monotonic: new information will not | |
100 // change our decision about undetermined or invalid elements. | |
101 if (element == NULL || !element->is_valid()) break; | |
102 | |
103 FrameElement* other = &reaching_frames_[j]->elements_[i]; | |
104 element = element->Combine(other); | |
105 if (element != NULL && !element->is_copy()) { | |
106 ASSERT(other != NULL); | |
107 // We overwrite the number information of one of the incoming frames. | |
108 // This is safe because we only use the frame for emitting merge code. | |
109 // The number information of incoming frames is not used anymore. | |
110 element->set_number_info(NumberInfo::Combine(element->number_info(), | |
111 other->number_info())); | |
112 } | |
113 } | |
114 elements[i] = element; | |
115 } | |
116 } | |
117 | |
118 // Build the new frame. A freshly allocated frame has memory elements | |
119 // for the parameters and some platform-dependent elements (e.g., | |
120 // return address). Replace those first. | |
121 entry_frame_ = new VirtualFrame(); | |
122 int index = 0; | |
123 for (; index < entry_frame_->element_count(); index++) { | |
124 FrameElement* target = elements[index]; | |
125 // If the element is determined, set it now. Count registers. Mark | |
126 // elements as copied exactly when they have a copy. Undetermined | |
127 // elements are initially recorded as if in memory. | |
128 if (target != NULL) { | |
129 entry_frame_->elements_[index] = *target; | |
130 InitializeEntryElement(index, target); | |
131 } | |
132 } | |
133 // Then fill in the rest of the frame with new elements. | |
134 for (; index < length; index++) { | |
135 FrameElement* target = elements[index]; | |
136 if (target == NULL) { | |
137 entry_frame_->elements_.Add( | |
138 FrameElement::MemoryElement(NumberInfo::Uninitialized())); | |
139 } else { | |
140 entry_frame_->elements_.Add(*target); | |
141 InitializeEntryElement(index, target); | |
142 } | |
143 } | |
144 | |
145 // Allocate any still-undetermined frame elements to registers or | |
146 // memory, from the top down. | |
147 for (int i = length - 1; i >= 0; i--) { | |
148 if (elements[i] == NULL) { | |
149 // Loop over all the reaching frames to check whether the element | |
150 // is synced on all frames and to count the registers it occupies. | |
151 bool is_synced = true; | |
152 RegisterFile candidate_registers; | |
153 int best_count = kMinInt; | |
154 int best_reg_num = RegisterAllocator::kInvalidRegister; | |
155 NumberInfo info = NumberInfo::Uninitialized(); | |
156 | |
157 for (int j = 0; j < reaching_frames_.length(); j++) { | |
158 FrameElement element = reaching_frames_[j]->elements_[i]; | |
159 if (direction_ == BIDIRECTIONAL) { | |
160 info = NumberInfo::Unknown(); | |
161 } else if (!element.is_copy()) { | |
162 info = NumberInfo::Combine(info, element.number_info()); | |
163 } else { | |
164 // New elements will not be copies, so get number information from | |
165 // backing element in the reaching frame. | |
166 info = NumberInfo::Combine(info, | |
167 reaching_frames_[j]->elements_[element.index()].number_info()); | |
168 } | |
169 is_synced = is_synced && element.is_synced(); | |
170 if (element.is_register() && !entry_frame_->is_used(element.reg())) { | |
171 // Count the register occurrence and remember it if better | |
172 // than the previous best. | |
173 int num = RegisterAllocator::ToNumber(element.reg()); | |
174 candidate_registers.Use(num); | |
175 if (candidate_registers.count(num) > best_count) { | |
176 best_count = candidate_registers.count(num); | |
177 best_reg_num = num; | |
178 } | |
179 } | |
180 } | |
181 | |
182 // We must have a number type information now (not for copied elements). | |
183 ASSERT(entry_frame_->elements_[i].is_copy() | |
184 || !info.IsUninitialized()); | |
185 | |
186 // If the value is synced on all frames, put it in memory. This | |
187 // costs nothing at the merge code but will incur a | |
188 // memory-to-register move when the value is needed later. | |
189 if (is_synced) { | |
190 // Already recorded as a memory element. | |
191 // Set combined number info. | |
192 entry_frame_->elements_[i].set_number_info(info); | |
193 continue; | |
194 } | |
195 | |
196 // Try to put it in a register. If there was no best choice | |
197 // consider any free register. | |
198 if (best_reg_num == RegisterAllocator::kInvalidRegister) { | |
199 for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) { | |
200 if (!entry_frame_->is_used(j)) { | |
201 best_reg_num = j; | |
202 break; | |
203 } | |
204 } | |
205 } | |
206 | |
207 if (best_reg_num != RegisterAllocator::kInvalidRegister) { | |
208 // If there was a register choice, use it. Preserve the copied | |
209 // flag on the element. | |
210 bool is_copied = entry_frame_->elements_[i].is_copied(); | |
211 Register reg = RegisterAllocator::ToRegister(best_reg_num); | |
212 entry_frame_->elements_[i] = | |
213 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, | |
214 NumberInfo::Uninitialized()); | |
215 if (is_copied) entry_frame_->elements_[i].set_copied(); | |
216 entry_frame_->set_register_location(reg, i); | |
217 } | |
218 // Set combined number info. | |
219 entry_frame_->elements_[i].set_number_info(info); | |
220 } | |
221 } | |
222 | |
223 // If we have incoming backward edges assert we forget all number information. | |
224 #ifdef DEBUG | |
225 if (direction_ == BIDIRECTIONAL) { | |
226 for (int i = 0; i < length; ++i) { | |
227 if (!entry_frame_->elements_[i].is_copy()) { | |
228 ASSERT(entry_frame_->elements_[i].number_info().IsUnknown()); | |
229 } | |
230 } | |
231 } | |
232 #endif | |
233 | |
234 // The stack pointer is at the highest synced element or the base of | |
235 // the expression stack. | |
236 int stack_pointer = length - 1; | |
237 while (stack_pointer >= entry_frame_->expression_base_index() && | |
238 !entry_frame_->elements_[stack_pointer].is_synced()) { | |
239 stack_pointer--; | |
240 } | |
241 entry_frame_->stack_pointer_ = stack_pointer; | |
242 } | |
243 | |
244 | |
245 void JumpTarget::Jump() { | 51 void JumpTarget::Jump() { |
246 DoJump(); | 52 DoJump(); |
247 } | 53 } |
248 | 54 |
249 | 55 |
250 void JumpTarget::Jump(Result* arg) { | |
251 ASSERT(cgen()->has_valid_frame()); | |
252 | |
253 cgen()->frame()->Push(arg); | |
254 DoJump(); | |
255 } | |
256 | |
257 | |
258 void JumpTarget::Branch(Condition cc, Hint hint) { | 56 void JumpTarget::Branch(Condition cc, Hint hint) { |
259 DoBranch(cc, hint); | 57 DoBranch(cc, hint); |
260 } | 58 } |
261 | 59 |
262 | 60 |
263 #ifdef DEBUG | |
264 #define DECLARE_ARGCHECK_VARS(name) \ | |
265 Result::Type name##_type = name->type(); \ | |
266 Register name##_reg = name->is_register() ? name->reg() : no_reg | |
267 | |
268 #define ASSERT_ARGCHECK(name) \ | |
269 ASSERT(name->type() == name##_type); \ | |
270 ASSERT(!name->is_register() || name->reg().is(name##_reg)) | |
271 | |
272 #else | |
273 #define DECLARE_ARGCHECK_VARS(name) do {} while (false) | |
274 | |
275 #define ASSERT_ARGCHECK(name) do {} while (false) | |
276 #endif | |
277 | |
278 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { | |
279 ASSERT(cgen()->has_valid_frame()); | |
280 | |
281 // We want to check that non-frame registers at the call site stay in | |
282 // the same registers on the fall-through branch. | |
283 DECLARE_ARGCHECK_VARS(arg); | |
284 | |
285 cgen()->frame()->Push(arg); | |
286 DoBranch(cc, hint); | |
287 *arg = cgen()->frame()->Pop(); | |
288 | |
289 ASSERT_ARGCHECK(arg); | |
290 } | |
291 | |
292 | |
293 void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { | |
294 ASSERT(cgen()->has_valid_frame()); | |
295 | |
296 int count = cgen()->frame()->height() - expected_height_; | |
297 if (count > 0) { | |
298 // We negate and branch here rather than using DoBranch's negate | |
299 // and branch. This gives us a hook to remove statement state | |
300 // from the frame. | |
301 JumpTarget fall_through; | |
302 // Branch to fall through will not negate, because it is a | |
303 // forward-only target. | |
304 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); | |
305 Jump(arg); // May emit merge code here. | |
306 fall_through.Bind(); | |
307 } else { | |
308 DECLARE_ARGCHECK_VARS(arg); | |
309 cgen()->frame()->Push(arg); | |
310 DoBranch(cc, hint); | |
311 *arg = cgen()->frame()->Pop(); | |
312 ASSERT_ARGCHECK(arg); | |
313 } | |
314 } | |
315 | |
316 #undef DECLARE_ARGCHECK_VARS | |
317 #undef ASSERT_ARGCHECK | |
318 | |
319 | |
320 void JumpTarget::Bind() { | 61 void JumpTarget::Bind() { |
321 DoBind(); | 62 DoBind(); |
322 } | 63 } |
323 | 64 |
324 | 65 |
325 void JumpTarget::Bind(Result* arg) { | |
326 if (cgen()->has_valid_frame()) { | |
327 cgen()->frame()->Push(arg); | |
328 } | |
329 DoBind(); | |
330 *arg = cgen()->frame()->Pop(); | |
331 } | |
332 | |
333 | |
334 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { | 66 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { |
335 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 67 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
336 ASSERT(entry_frame_ == NULL); | 68 ASSERT(entry_frame_ == NULL); |
337 Label fresh; | 69 Label fresh; |
338 merge_labels_.Add(fresh); | 70 merge_labels_.Add(fresh); |
339 reaching_frames_.Add(frame); | 71 reaching_frames_.Add(frame); |
340 } | 72 } |
341 | 73 |
342 | 74 |
343 // ------------------------------------------------------------------------- | 75 // ------------------------------------------------------------------------- |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 temp.CopyTo(this); | 146 temp.CopyTo(this); |
415 temp.Unuse(); | 147 temp.Unuse(); |
416 | 148 |
417 #ifdef DEBUG | 149 #ifdef DEBUG |
418 is_shadowing_ = false; | 150 is_shadowing_ = false; |
419 #endif | 151 #endif |
420 } | 152 } |
421 | 153 |
422 | 154 |
423 } } // namespace v8::internal | 155 } } // namespace v8::internal |
OLD | NEW |