Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/jump-target.cc

Issue 113258: Streamline JumpTarget::ComputeEntryFrame by removing the separate loop... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 94
95 FrameElement* JumpTarget::Combine(FrameElement* left, FrameElement* right) { 95 FrameElement* JumpTarget::Combine(FrameElement* left, FrameElement* right) {
96 // Given a pair of non-null frame element pointers, return one of 96 // Given a pair of non-null frame element pointers, return one of
97 // them as an entry frame candidate or null if they are 97 // them as an entry frame candidate or null if they are
98 // incompatible. 98 // incompatible.
99 99
100 // If either is invalid, the result is. 100 // If either is invalid, the result is.
101 if (!left->is_valid()) return left; 101 if (!left->is_valid()) return left;
102 if (!right->is_valid()) return right; 102 if (!right->is_valid()) return right;
103 103
104 // If they have the same value, the result is the same. If either 104 // If they have the exact same location, the result is in that
105 // is unsynced, the result is. 105 // location, otherwise we reallocate. If either is unsynced, the
106 // result is. The result static type is the merge of the static
107 // types. It's safe to set it on one of the frame elements, and
108 // harmless too (because we are only going to merge the reaching
109 // frames and will ensure that the types are coherent, and changing
110 // the static type does not emit code).
106 111
107 if (left->is_memory() && right->is_memory()) return left; 112 StaticType type = left->static_type().merge(right->static_type());
113 if (left->is_memory() && right->is_memory()) {
114 left->set_static_type(type);
115 return left;
116 }
108 117
109 if (left->is_register() && right->is_register() && 118 if (left->is_register() && right->is_register() &&
Lasse Reichstein 2009/05/12 14:45:38 This function looks like a lot of duplicated code.
110 left->reg().is(right->reg())) { 119 left->reg().is(right->reg())) {
111 if (!left->is_synced()) { 120 if (!left->is_synced()) {
121 left->set_static_type(type);
112 return left; 122 return left;
113 } else { 123 } else {
124 right->set_static_type(type);
114 return right; 125 return right;
115 } 126 }
116 } 127 }
117 128
118 if (left->is_constant() && 129 if (left->is_constant() &&
119 right->is_constant() && 130 right->is_constant() &&
120 left->handle().is_identical_to(right->handle())) { 131 left->handle().is_identical_to(right->handle())) {
121 if (!left->is_synced()) { 132 if (!left->is_synced()) {
133 left->set_static_type(type);
122 return left; 134 return left;
123 } else { 135 } else {
136 right->set_static_type(type);
124 return right; 137 return right;
125 } 138 }
126 } 139 }
127 140
128 if (left->is_copy() && 141 if (left->is_copy() &&
129 right->is_copy() && 142 right->is_copy() &&
130 left->index() == right->index()) { 143 left->index() == right->index()) {
131 if (!left->is_synced()) { 144 if (!left->is_synced()) {
145 left->set_static_type(type);
132 return left; 146 return left;
133 } else { 147 } else {
148 right->set_static_type(type);
134 return right; 149 return right;
135 } 150 }
136 } 151 }
137 152
138 // Otherwise they are incompatible and we will reallocate them. 153 // Otherwise they are incompatible and we will reallocate them.
139 return NULL; 154 return NULL;
140 } 155 }
141 156
142 157
143 void JumpTarget::ComputeEntryFrame(int mergable_elements) { 158 void JumpTarget::ComputeEntryFrame(int mergable_elements) {
(...skipping 13 matching lines...) Expand all
157 // down) to a frame high-water mark (counted from the bottom up). 172 // down) to a frame high-water mark (counted from the bottom up).
158 // Elements strictly above the high-water index will be mergable in 173 // Elements strictly above the high-water index will be mergable in
159 // entry frames for bidirectional jump targets. 174 // entry frames for bidirectional jump targets.
160 int high_water_mark = (mergable_elements == kAllElements) 175 int high_water_mark = (mergable_elements == kAllElements)
161 ? VirtualFrame::kIllegalIndex // All frame indices are above this. 176 ? VirtualFrame::kIllegalIndex // All frame indices are above this.
162 : length - mergable_elements - 1; // Top index if m_e == 0. 177 : length - mergable_elements - 1; // Top index if m_e == 0.
163 178
164 // Initially populate the list of elements based on the initial 179 // Initially populate the list of elements based on the initial
165 // frame. 180 // frame.
166 for (int i = 0; i < length; i++) { 181 for (int i = 0; i < length; i++) {
167 FrameElement element = initial_frame->elements_[i]; 182 FrameElement element = initial_frame->elements_[i];
Lasse Reichstein 2009/05/12 14:45:38 If we look this element up again later, would it p
168 // We do not allow copies or constants in bidirectional frames. 183 // We do not allow copies or constants in bidirectional frames. All
169 if (direction_ == BIDIRECTIONAL && i > high_water_mark && 184 // elements above the water mark on bidirectional frames have
170 (element.is_constant() || element.is_copy())) { 185 // unknown static types.
171 elements.Add(NULL); 186 if (direction_ == BIDIRECTIONAL && i > high_water_mark) {
172 } else { 187 if (element.is_constant() || element.is_copy()) {
173 elements.Add(&initial_frame->elements_[i]); 188 elements.Add(NULL);
189 continue;
190 }
191 // It's safe to change the static type on the initial frame
192 // element, see comment in JumpTarget::Combine.
193 initial_frame->elements_[i].set_static_type(StaticType::unknown());
174 } 194 }
195 elements.Add(&initial_frame->elements_[i]);
175 } 196 }
176 197
177 // Compute elements based on the other reaching frames. 198 // Compute elements based on the other reaching frames.
178 if (reaching_frames_.length() > 1) { 199 if (reaching_frames_.length() > 1) {
179 for (int i = 0; i < length; i++) { 200 for (int i = 0; i < length; i++) {
180 for (int j = 1; j < reaching_frames_.length(); j++) { 201 for (int j = 1; j < reaching_frames_.length(); j++) {
181 FrameElement* element = elements[i]; 202 FrameElement* element = elements[i];
182 203
183 // Element computation is monotonic: new information will not 204 // Element computation is monotonic: new information will not
184 // change our decision about undetermined or invalid elements. 205 // change our decision about undetermined or invalid elements.
185 if (element == NULL || !element->is_valid()) break; 206 if (element == NULL || !element->is_valid()) break;
186 207
187 elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]); 208 elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]);
Lasse Reichstein 2009/05/12 14:45:38 Why do we read the element on each round of the in
188 } 209 }
189 } 210 }
190 } 211 }
191 212
192 // Build the new frame. A freshly allocated frame has memory elements 213 // Build the new frame. A freshly allocated frame has memory elements
193 // for the parameters and some platform-dependent elements (e.g., 214 // for the parameters and some platform-dependent elements (e.g.,
194 // return address). Replace those first. 215 // return address). Replace those first.
195 entry_frame_ = new VirtualFrame(cgen_); 216 entry_frame_ = new VirtualFrame(cgen_);
196 int index = 0; 217 int index = 0;
197 for (; index < entry_frame_->elements_.length(); index++) { 218 for (; index < entry_frame_->elements_.length(); index++) {
(...skipping 24 matching lines...) Expand all
222 } else if (elements[index]->is_copy()) { 243 } else if (elements[index]->is_copy()) {
223 entry_frame_->elements_[elements[index]->index()].set_copied(); 244 entry_frame_->elements_[elements[index]->index()].set_copied();
224 } 245 }
225 } 246 }
226 } 247 }
227 248
228 // Allocate any still-undetermined frame elements to registers or 249 // Allocate any still-undetermined frame elements to registers or
229 // memory, from the top down. 250 // memory, from the top down.
230 for (int i = length - 1; i >= 0; i--) { 251 for (int i = length - 1; i >= 0; i--) {
231 if (elements[i] == NULL) { 252 if (elements[i] == NULL) {
253 // Loop over all the reaching frames to check whether the element
254 // is synced on all frames, to count the registers it occupies,
255 // and to compute a merged static type.
256 bool is_synced = true;
257 RegisterFile candidate_registers;
258 int best_count = kMinInt;
259 int best_reg_code = no_reg.code_;
260
261 StaticType type; // Initially invalid.
262 if (direction_ != BIDIRECTIONAL || i < high_water_mark) {
263 type = reaching_frames_[0]->elements_[i].static_type();
264 }
265
266 for (int j = 0; j < reaching_frames_.length(); j++) {
267 FrameElement element = reaching_frames_[j]->elements_[i];
268 is_synced = is_synced && element.is_synced();
269 if (element.is_register() && !entry_frame_->is_used(element.reg())) {
270 // Count the register occurrence and remember it if better
271 // than the previous best.
272 candidate_registers.Use(element.reg());
273 if (candidate_registers.count(element.reg()) > best_count) {
274 best_count = candidate_registers.count(element.reg());
275 best_reg_code = element.reg().code();
276 }
277 }
278 type = type.merge(element.static_type());
279 }
280
232 // If the value is synced on all frames, put it in memory. This 281 // If the value is synced on all frames, put it in memory. This
233 // costs nothing at the merge code but will incur a 282 // costs nothing at the merge code but will incur a
234 // memory-to-register move when the value is needed later. 283 // memory-to-register move when the value is needed later.
235 bool is_synced = true; 284 if (is_synced) {
236 for (int j = 0; is_synced && j < reaching_frames_.length(); j++) { 285 // Already recorded as a memory element.
237 is_synced = reaching_frames_[j]->elements_[i].is_synced(); 286 entry_frame_->elements_[i].set_static_type(type);
287 continue;
238 } 288 }
239 289
240 // There is nothing to be done if the elements are all synced. 290 // Try to put it in a register. If there was no best choice
241 // It is already recorded as a memory element. 291 // consider any free register.
242 if (is_synced) continue;
243
244 // Choose an available register. Prefer ones that the element
245 // is already occupying on some reaching frame.
246 RegisterFile candidate_registers;
247 int max_count = kMinInt;
248 int best_reg_code = no_reg.code_;
249
250 for (int j = 0; j < reaching_frames_.length(); j++) {
251 FrameElement element = reaching_frames_[j]->elements_[i];
252 if (element.is_register() &&
253 !entry_frame_->is_used(element.reg())) {
254 candidate_registers.Use(element.reg());
255 if (candidate_registers.count(element.reg()) > max_count) {
256 max_count = candidate_registers.count(element.reg());
257 best_reg_code = element.reg().code();
258 }
259 }
260 }
261 // If there was no preferred choice consider any free register.
262 if (best_reg_code == no_reg.code_) { 292 if (best_reg_code == no_reg.code_) {
263 for (int j = 0; j < kNumRegisters; j++) { 293 for (int j = 0; j < kNumRegisters; j++) {
264 if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) { 294 if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) {
265 best_reg_code = j; 295 best_reg_code = j;
266 break; 296 break;
267 } 297 }
268 } 298 }
269 } 299 }
270 300
271 if (best_reg_code != no_reg.code_) { 301 if (best_reg_code == no_reg.code_) {
302 // If there was no register found, the element is already
303 // recorded as in memory.
304 entry_frame_->elements_[i].set_static_type(type);
305 } else {
272 // If there was a register choice, use it. Preserve the copied 306 // If there was a register choice, use it. Preserve the copied
273 // flag on the element. 307 // flag on the element. Set the static type as computed.
274 bool is_copied = entry_frame_->elements_[i].is_copied(); 308 bool is_copied = entry_frame_->elements_[i].is_copied();
275 Register reg = { best_reg_code }; 309 Register reg = { best_reg_code };
276 entry_frame_->elements_[i] = 310 entry_frame_->elements_[i] =
277 FrameElement::RegisterElement(reg, 311 FrameElement::RegisterElement(reg,
278 FrameElement::NOT_SYNCED); 312 FrameElement::NOT_SYNCED);
279 if (is_copied) entry_frame_->elements_[i].set_copied(); 313 if (is_copied) entry_frame_->elements_[i].set_copied();
314 entry_frame_->elements_[i].set_static_type(type);
280 entry_frame_->register_locations_[best_reg_code] = i; 315 entry_frame_->register_locations_[best_reg_code] = i;
281 } 316 }
282 // If there was no register found, the element is already
283 // recorded as in memory.
284 }
285 }
286
287 // Set the static type of frame elements.
288 for (int i = 0; i < length; i++) {
289 FrameElement* current = &entry_frame_->elements_[i];
290 if (direction_ == BIDIRECTIONAL && i >= high_water_mark) {
291 current->set_static_type(StaticType::unknown());
292 } else {
293 StaticType merged_type = reaching_frames_[0]->elements_[i].static_type();
294 for (int j = 1, n = reaching_frames_.length();
295 !merged_type.is_unknown() && j < n;
296 j++) {
297 merged_type =
298 merged_type.merge(reaching_frames_[j]->elements_[i].static_type());
299 }
300 current->set_static_type(merged_type);
301 } 317 }
302 } 318 }
303 319
304 // Fill in the other fields of the entry frame. 320 // Fill in the other fields of the entry frame.
305 entry_frame_->local_count_ = initial_frame->local_count_; 321 entry_frame_->local_count_ = initial_frame->local_count_;
306 entry_frame_->frame_pointer_ = initial_frame->frame_pointer_; 322 entry_frame_->frame_pointer_ = initial_frame->frame_pointer_;
307 323
308 // The stack pointer is at the highest synced element or the base of 324 // The stack pointer is at the highest synced element or the base of
309 // the expression stack. 325 // the expression stack.
310 int stack_pointer = length - 1; 326 int stack_pointer = length - 1;
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 temp.CopyTo(this); 746 temp.CopyTo(this);
731 temp.Reset(); // So the destructor does not deallocate virtual frames. 747 temp.Reset(); // So the destructor does not deallocate virtual frames.
732 748
733 #ifdef DEBUG 749 #ifdef DEBUG
734 is_shadowing_ = false; 750 is_shadowing_ = false;
735 #endif 751 #endif
736 } 752 }
737 753
738 754
739 } } // namespace v8::internal 755 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698