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

Side by Side Diff: src/virtual-frame.cc

Issue 113837: Change the register allocator so that it no longer tracks references... (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
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 20 matching lines...) Expand all
31 #include "register-allocator-inl.h" 31 #include "register-allocator-inl.h"
32 32
33 namespace v8 { 33 namespace v8 {
34 namespace internal { 34 namespace internal {
35 35
36 // ------------------------------------------------------------------------- 36 // -------------------------------------------------------------------------
37 // VirtualFrame implementation. 37 // VirtualFrame implementation.
38 38
39 // When cloned, a frame is a deep copy of the original. 39 // When cloned, a frame is a deep copy of the original.
40 VirtualFrame::VirtualFrame(VirtualFrame* original) 40 VirtualFrame::VirtualFrame(VirtualFrame* original)
41 : elements_(original->elements_.length()), 41 : elements_(original->element_count()),
42 stack_pointer_(original->stack_pointer_) { 42 stack_pointer_(original->stack_pointer_) {
43 elements_.AddAll(original->elements_); 43 elements_.AddAll(original->elements_);
44 // Copy register locations from original. 44 // Copy register locations from original.
45 memcpy(&register_locations_, 45 memcpy(&register_locations_,
46 original->register_locations_, 46 original->register_locations_,
47 sizeof(register_locations_)); 47 sizeof(register_locations_));
48 } 48 }
49 49
50 50
51 FrameElement VirtualFrame::CopyElementAt(int index) { 51 FrameElement VirtualFrame::CopyElementAt(int index) {
52 ASSERT(index >= 0); 52 ASSERT(index >= 0);
53 ASSERT(index < elements_.length()); 53 ASSERT(index < element_count());
54 54
55 FrameElement target = elements_[index]; 55 FrameElement target = elements_[index];
56 FrameElement result; 56 FrameElement result;
57 57
58 switch (target.type()) { 58 switch (target.type()) {
59 case FrameElement::CONSTANT: 59 case FrameElement::CONSTANT:
60 // We do not copy constants and instead return a fresh unsynced 60 // We do not copy constants and instead return a fresh unsynced
61 // constant. 61 // constant.
62 result = FrameElement::ConstantElement(target.handle(), 62 result = FrameElement::ConstantElement(target.handle(),
63 FrameElement::NOT_SYNCED); 63 FrameElement::NOT_SYNCED);
(...skipping 25 matching lines...) Expand all
89 return result; 89 return result;
90 } 90 }
91 91
92 92
93 // Modify the state of the virtual frame to match the actual frame by adding 93 // Modify the state of the virtual frame to match the actual frame by adding
94 // extra in-memory elements to the top of the virtual frame. The extra 94 // extra in-memory elements to the top of the virtual frame. The extra
95 // elements will be externally materialized on the actual frame (eg, by 95 // elements will be externally materialized on the actual frame (eg, by
96 // pushing an exception handler). No code is emitted. 96 // pushing an exception handler). No code is emitted.
97 void VirtualFrame::Adjust(int count) { 97 void VirtualFrame::Adjust(int count) {
98 ASSERT(count >= 0); 98 ASSERT(count >= 0);
99 ASSERT(stack_pointer_ == elements_.length() - 1); 99 ASSERT(stack_pointer_ == element_count() - 1);
100 100
101 for (int i = 0; i < count; i++) { 101 for (int i = 0; i < count; i++) {
102 elements_.Add(FrameElement::MemoryElement()); 102 elements_.Add(FrameElement::MemoryElement());
103 } 103 }
104 stack_pointer_ += count; 104 stack_pointer_ += count;
105 } 105 }
106 106
107 107
108 void VirtualFrame::ForgetElements(int count) { 108 void VirtualFrame::ForgetElements(int count) {
109 ASSERT(count >= 0); 109 ASSERT(count >= 0);
110 ASSERT(elements_.length() >= count); 110 ASSERT(element_count() >= count);
111 111
112 for (int i = 0; i < count; i++) { 112 for (int i = 0; i < count; i++) {
113 FrameElement last = elements_.RemoveLast(); 113 FrameElement last = elements_.RemoveLast();
114 if (last.is_register()) { 114 if (last.is_register()) {
115 // A hack to properly count register references for the code 115 // A hack to properly count register references for the code
116 // generator's current frame and also for other frames. The 116 // generator's current frame and also for other frames. The
117 // same code appears in PrepareMergeTo. 117 // same code appears in PrepareMergeTo.
118 if (cgen()->frame() == this) { 118 if (cgen()->frame() == this) {
119 Unuse(last.reg()); 119 Unuse(last.reg());
120 } else { 120 } else {
121 register_locations_[last.reg().code()] = kIllegalIndex; 121 set_register_location(last.reg(), kIllegalIndex);
122 } 122 }
123 } 123 }
124 } 124 }
125 } 125 }
126 126
127 127
128 // If there are any registers referenced only by the frame, spill one. 128 // If there are any registers referenced only by the frame, spill one.
129 Register VirtualFrame::SpillAnyRegister() { 129 Register VirtualFrame::SpillAnyRegister() {
130 // Find the leftmost (ordered by register code) register whose only 130 // Find the leftmost (ordered by register number) register whose only
131 // reference is in the frame. 131 // reference is in the frame.
132 for (int i = 0; i < kNumRegisters; i++) { 132 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
133 if (is_used(i) && cgen()->allocator()->count(i) == 1) { 133 if (is_used(i) && cgen()->allocator()->count(i) == 1) {
134 Register result = { i }; 134 SpillElementAt(register_location(i));
135 Spill(result); 135 ASSERT(!cgen()->allocator()->is_used(i));
136 ASSERT(!cgen()->allocator()->is_used(result)); 136 return RegisterAllocator::ToRegister(i);
137 return result;
138 } 137 }
139 } 138 }
140 return no_reg; 139 return no_reg;
141 } 140 }
142 141
143 142
144 // Make the type of the element at a given index be MEMORY. 143 // Make the type of the element at a given index be MEMORY.
145 void VirtualFrame::SpillElementAt(int index) { 144 void VirtualFrame::SpillElementAt(int index) {
146 if (!elements_[index].is_valid()) return; 145 if (!elements_[index].is_valid()) return;
147 146
(...skipping 18 matching lines...) Expand all
166 } else if (index == stack_pointer_ + 1) { 165 } else if (index == stack_pointer_ + 1) {
167 SyncElementByPushing(index); 166 SyncElementByPushing(index);
168 } else { 167 } else {
169 SyncRange(stack_pointer_ + 1, index); 168 SyncRange(stack_pointer_ + 1, index);
170 } 169 }
171 } 170 }
172 171
173 172
174 // Make the type of all elements be MEMORY. 173 // Make the type of all elements be MEMORY.
175 void VirtualFrame::SpillAll() { 174 void VirtualFrame::SpillAll() {
176 for (int i = 0; i < elements_.length(); i++) { 175 for (int i = 0; i < element_count(); i++) {
177 SpillElementAt(i); 176 SpillElementAt(i);
178 } 177 }
179 } 178 }
180 179
181 180
182 void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { 181 void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
183 // Perform state changes on this frame that will make merge to the 182 // Perform state changes on this frame that will make merge to the
184 // expected frame simpler or else increase the likelihood that his 183 // expected frame simpler or else increase the likelihood that his
185 // frame will match another. 184 // frame will match another.
186 for (int i = 0; i < elements_.length(); i++) { 185 for (int i = 0; i < element_count(); i++) {
187 FrameElement source = elements_[i]; 186 FrameElement source = elements_[i];
188 FrameElement target = expected->elements_[i]; 187 FrameElement target = expected->elements_[i];
189 188
190 if (!target.is_valid() || 189 if (!target.is_valid() ||
191 (target.is_memory() && !source.is_memory() && source.is_synced())) { 190 (target.is_memory() && !source.is_memory() && source.is_synced())) {
192 // No code needs to be generated to invalidate valid elements. 191 // No code needs to be generated to invalidate valid elements.
193 // No code needs to be generated to move values to memory if 192 // No code needs to be generated to move values to memory if
194 // they are already synced. We perform those moves here, before 193 // they are already synced. We perform those moves here, before
195 // merging. 194 // merging.
196 if (source.is_register()) { 195 if (source.is_register()) {
197 // If the frame is the code generator's current frame, we have 196 // If the frame is the code generator's current frame, we have
198 // to decrement both the frame-internal and global register 197 // to decrement both the frame-internal and global register
199 // counts. 198 // counts.
200 if (cgen()->frame() == this) { 199 if (cgen()->frame() == this) {
201 Unuse(source.reg()); 200 Unuse(source.reg());
202 } else { 201 } else {
203 register_locations_[source.reg().code()] = kIllegalIndex; 202 set_register_location(source.reg(), kIllegalIndex);
204 } 203 }
205 } 204 }
206 elements_[i] = target; 205 elements_[i] = target;
207 } else if (target.is_register() && !target.is_synced() && 206 } else if (target.is_register() && !target.is_synced() &&
208 !source.is_memory()) { 207 !source.is_memory()) {
209 // If an element's target is a register that doesn't need to be 208 // If an element's target is a register that doesn't need to be
210 // synced, and the element is not in memory, then the sync state 209 // synced, and the element is not in memory, then the sync state
211 // of the element is irrelevant. We clear the sync bit. 210 // of the element is irrelevant. We clear the sync bit.
212 ASSERT(source.is_valid()); 211 ASSERT(source.is_valid());
213 elements_[i].clear_sync(); 212 elements_[i].clear_sync();
214 } 213 }
215 // No code needs to be generated to change the static type of an 214 // No code needs to be generated to change the static type of an
216 // element. 215 // element.
217 elements_[i].set_static_type(target.static_type()); 216 elements_[i].set_static_type(target.static_type());
218 } 217 }
219 } 218 }
220 219
221 220
222 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { 221 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
223 ASSERT(height() >= dropped_args); 222 ASSERT(height() >= dropped_args);
224 ASSERT(height() >= spilled_args); 223 ASSERT(height() >= spilled_args);
225 ASSERT(dropped_args <= spilled_args); 224 ASSERT(dropped_args <= spilled_args);
226 225
227 SyncRange(0, elements_.length() - 1); 226 SyncRange(0, element_count() - 1);
228 // Spill registers. 227 // Spill registers.
229 for (int i = 0; i < kNumRegisters; i++) { 228 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
230 if (is_used(i)) { 229 if (is_used(i)) {
231 SpillElementAt(register_locations_[i]); 230 SpillElementAt(register_location(i));
232 } 231 }
233 } 232 }
234 233
235 // Spill the arguments. 234 // Spill the arguments.
236 for (int i = elements_.length() - spilled_args; i < elements_.length(); i++) { 235 for (int i = element_count() - spilled_args; i < element_count(); i++) {
237 if (!elements_[i].is_memory()) { 236 if (!elements_[i].is_memory()) {
238 SpillElementAt(i); 237 SpillElementAt(i);
239 } 238 }
240 } 239 }
241 240
242 // Forget the frame elements that will be popped by the call. 241 // Forget the frame elements that will be popped by the call.
243 Forget(dropped_args); 242 Forget(dropped_args);
244 } 243 }
245 244
246 245
247 void VirtualFrame::PrepareForReturn() { 246 void VirtualFrame::PrepareForReturn() {
248 // Spill all locals. This is necessary to make sure all locals have 247 // Spill all locals. This is necessary to make sure all locals have
249 // the right value when breaking at the return site in the debugger. 248 // the right value when breaking at the return site in the debugger.
250 // Set their static type to unknown so that they will match the known 249 // Set their static type to unknown so that they will match the known
251 // return frame. 250 // return frame.
252 for (int i = 0; i < expression_base_index(); i++) { 251 for (int i = 0; i < expression_base_index(); i++) {
253 SpillElementAt(i); 252 SpillElementAt(i);
254 elements_[i].set_static_type(StaticType::unknown()); 253 elements_[i].set_static_type(StaticType::unknown());
255 } 254 }
256 } 255 }
257 256
258 257
259 void VirtualFrame::SetElementAt(int index, Result* value) { 258 void VirtualFrame::SetElementAt(int index, Result* value) {
260 int frame_index = elements_.length() - index - 1; 259 int frame_index = element_count() - index - 1;
261 ASSERT(frame_index >= 0); 260 ASSERT(frame_index >= 0);
262 ASSERT(frame_index < elements_.length()); 261 ASSERT(frame_index < element_count());
263 ASSERT(value->is_valid()); 262 ASSERT(value->is_valid());
264 FrameElement original = elements_[frame_index]; 263 FrameElement original = elements_[frame_index];
265 264
266 // Early exit if the element is the same as the one being set. 265 // Early exit if the element is the same as the one being set.
267 bool same_register = original.is_register() 266 bool same_register = original.is_register()
268 && value->is_register() 267 && value->is_register()
269 && original.reg().is(value->reg()); 268 && original.reg().is(value->reg());
270 bool same_constant = original.is_constant() 269 bool same_constant = original.is_constant()
271 && value->is_constant() 270 && value->is_constant()
272 && original.handle().is_identical_to(value->handle()); 271 && original.handle().is_identical_to(value->handle());
273 if (same_register || same_constant) { 272 if (same_register || same_constant) {
274 value->Unuse(); 273 value->Unuse();
275 return; 274 return;
276 } 275 }
277 276
278 InvalidateFrameSlotAt(frame_index); 277 InvalidateFrameSlotAt(frame_index);
279 278
280 FrameElement new_element; 279 FrameElement new_element;
281 if (value->is_register()) { 280 if (value->is_register()) {
282 if (is_used(value->reg())) { 281 if (is_used(value->reg())) {
283 // The register already appears on the frame. Either the existing 282 // The register already appears on the frame. Either the existing
284 // register element, or the new element at frame_index, must be made 283 // register element, or the new element at frame_index, must be made
285 // a copy. 284 // a copy.
286 int i = register_index(value->reg()); 285 int i = register_location(value->reg());
287 ASSERT(value->static_type() == elements_[i].static_type()); 286 ASSERT(value->static_type() == elements_[i].static_type());
288 287
289 if (i < frame_index) { 288 if (i < frame_index) {
290 // The register FrameElement is lower in the frame than the new copy. 289 // The register FrameElement is lower in the frame than the new copy.
291 elements_[frame_index] = CopyElementAt(i); 290 elements_[frame_index] = CopyElementAt(i);
292 } else { 291 } else {
293 // There was an early bailout for the case of setting a 292 // There was an early bailout for the case of setting a
294 // register element to itself. 293 // register element to itself.
295 ASSERT(i != frame_index); 294 ASSERT(i != frame_index);
296 elements_[frame_index] = elements_[i]; 295 elements_[frame_index] = elements_[i];
297 elements_[i] = CopyElementAt(frame_index); 296 elements_[i] = CopyElementAt(frame_index);
298 if (elements_[frame_index].is_synced()) { 297 if (elements_[frame_index].is_synced()) {
299 elements_[i].set_sync(); 298 elements_[i].set_sync();
300 } 299 }
301 elements_[frame_index].clear_sync(); 300 elements_[frame_index].clear_sync();
302 register_locations_[value->reg().code()] = frame_index; 301 set_register_location(value->reg(), frame_index);
303 for (int j = i + 1; j < elements_.length(); j++) { 302 for (int j = i + 1; j < element_count(); j++) {
304 if (elements_[j].is_copy() && elements_[j].index() == i) { 303 if (elements_[j].is_copy() && elements_[j].index() == i) {
305 elements_[j].set_index(frame_index); 304 elements_[j].set_index(frame_index);
306 } 305 }
307 } 306 }
308 } 307 }
309 } else { 308 } else {
310 // The register value->reg() was not already used on the frame. 309 // The register value->reg() was not already used on the frame.
311 Use(value->reg(), frame_index); 310 Use(value->reg(), frame_index);
312 elements_[frame_index] = 311 elements_[frame_index] =
313 FrameElement::RegisterElement(value->reg(), 312 FrameElement::RegisterElement(value->reg(),
(...skipping 10 matching lines...) Expand all
324 } 323 }
325 324
326 325
327 void VirtualFrame::PushFrameSlotAt(int index) { 326 void VirtualFrame::PushFrameSlotAt(int index) {
328 elements_.Add(CopyElementAt(index)); 327 elements_.Add(CopyElementAt(index));
329 } 328 }
330 329
331 330
332 void VirtualFrame::Push(Register reg, StaticType static_type) { 331 void VirtualFrame::Push(Register reg, StaticType static_type) {
333 if (is_used(reg)) { 332 if (is_used(reg)) {
334 int index = register_index(reg); 333 int index = register_location(reg);
335 FrameElement element = CopyElementAt(index); 334 FrameElement element = CopyElementAt(index);
336 ASSERT(static_type.merge(element.static_type()) == element.static_type()); 335 ASSERT(static_type.merge(element.static_type()) == element.static_type());
337 elements_.Add(element); 336 elements_.Add(element);
338 } else { 337 } else {
339 Use(reg, elements_.length()); 338 Use(reg, element_count());
340 FrameElement element = 339 FrameElement element =
341 FrameElement::RegisterElement(reg, 340 FrameElement::RegisterElement(reg,
342 FrameElement::NOT_SYNCED, 341 FrameElement::NOT_SYNCED,
343 static_type); 342 static_type);
344 elements_.Add(element); 343 elements_.Add(element);
345 } 344 }
346 } 345 }
347 346
348 347
349 void VirtualFrame::Push(Handle<Object> value) { 348 void VirtualFrame::Push(Handle<Object> value) {
350 FrameElement element = 349 FrameElement element =
351 FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED); 350 FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
352 elements_.Add(element); 351 elements_.Add(element);
353 } 352 }
354 353
355 354
356 void VirtualFrame::Nip(int num_dropped) { 355 void VirtualFrame::Nip(int num_dropped) {
357 ASSERT(num_dropped >= 0); 356 ASSERT(num_dropped >= 0);
358 if (num_dropped == 0) return; 357 if (num_dropped == 0) return;
359 Result tos = Pop(); 358 Result tos = Pop();
360 if (num_dropped > 1) { 359 if (num_dropped > 1) {
361 Drop(num_dropped - 1); 360 Drop(num_dropped - 1);
362 } 361 }
363 SetElementAt(0, &tos); 362 SetElementAt(0, &tos);
364 } 363 }
365 364
366 365
367 bool VirtualFrame::Equals(VirtualFrame* other) { 366 bool VirtualFrame::Equals(VirtualFrame* other) {
368 #ifdef DEBUG 367 #ifdef DEBUG
369 for (int i = 0; i < kNumRegisters; i++) { 368 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
370 if (register_locations_[i] != other->register_locations_[i]) { 369 if (register_location(i) != other->register_location(i)) {
371 return false; 370 return false;
372 } 371 }
373 } 372 }
374 if (elements_.length() != other->elements_.length()) return false; 373 if (element_count() != other->element_count()) return false;
375 #endif 374 #endif
376 if (stack_pointer_ != other->stack_pointer_) return false; 375 if (stack_pointer_ != other->stack_pointer_) return false;
377 for (int i = 0; i < elements_.length(); i++) { 376 for (int i = 0; i < element_count(); i++) {
378 if (!elements_[i].Equals(other->elements_[i])) return false; 377 if (!elements_[i].Equals(other->elements_[i])) return false;
379 } 378 }
380 379
381 return true; 380 return true;
382 } 381 }
383 382
384 383
385 // Specialization of List::ResizeAdd to non-inlined version for FrameElements. 384 // Specialization of List::ResizeAdd to non-inlined version for FrameElements.
386 // The function ResizeAdd becomes a real function, whose implementation is the 385 // The function ResizeAdd becomes a real function, whose implementation is the
387 // inlined ResizeAddInternal. 386 // inlined ResizeAddInternal.
388 template <> 387 template <>
389 void List<FrameElement, 388 void List<FrameElement,
390 FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element) { 389 FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element) {
391 ResizeAddInternal(element); 390 ResizeAddInternal(element);
392 } 391 }
393 392
394 } } // namespace v8::internal 393 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698