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

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

Issue 11396: Begin counting references to registers, both in the frame and out.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years 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 | « src/virtual-frame-ia32.h ('k') | 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 2008 the V8 project authors. All rights reserved. 1 // Copyright 2008 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 23 matching lines...) Expand all
34 namespace v8 { namespace internal { 34 namespace v8 { namespace internal {
35 35
36 #define __ masm_-> 36 #define __ masm_->
37 37
38 // ------------------------------------------------------------------------- 38 // -------------------------------------------------------------------------
39 // VirtualFrame implementation. 39 // VirtualFrame implementation.
40 40
41 // On entry to a function, the virtual frame already contains the receiver, 41 // On entry to a function, the virtual frame already contains the receiver,
42 // the parameters, and a return address. All frame elements are in memory. 42 // the parameters, and a return address. All frame elements are in memory.
43 VirtualFrame::VirtualFrame(CodeGenerator* cgen) 43 VirtualFrame::VirtualFrame(CodeGenerator* cgen)
44 : masm_(cgen->masm()), 44 : cgen_(cgen),
45 masm_(cgen->masm()),
45 elements_(0), 46 elements_(0),
46 parameter_count_(cgen->scope()->num_parameters()), 47 parameter_count_(cgen->scope()->num_parameters()),
47 local_count_(0), 48 local_count_(0),
48 stack_pointer_(parameter_count_ + 1), // 0-based index of TOS. 49 stack_pointer_(parameter_count_ + 1), // 0-based index of TOS.
49 frame_pointer_(kIllegalIndex) { 50 frame_pointer_(kIllegalIndex) {
51 FrameElement memory_element;
50 for (int i = 0; i < parameter_count_ + 2; i++) { 52 for (int i = 0; i < parameter_count_ + 2; i++) {
51 elements_.Add(FrameElement()); 53 elements_.Add(memory_element);
52 } 54 }
53 } 55 }
54 56
55 57
56 // When cloned, a frame is a deep copy of the original. 58 // When cloned, a frame is a deep copy of the original.
57 VirtualFrame::VirtualFrame(VirtualFrame* original) 59 VirtualFrame::VirtualFrame(VirtualFrame* original)
58 : masm_(original->masm_), 60 : cgen_(original->cgen_),
61 masm_(original->masm_),
59 elements_(original->elements_.length()), 62 elements_(original->elements_.length()),
60 parameter_count_(original->parameter_count_), 63 parameter_count_(original->parameter_count_),
61 local_count_(original->local_count_), 64 local_count_(original->local_count_),
62 stack_pointer_(original->stack_pointer_), 65 stack_pointer_(original->stack_pointer_),
63 frame_pointer_(original->frame_pointer_) { 66 frame_pointer_(original->frame_pointer_),
67 frame_registers_(original->frame_registers_) {
64 // Copy all the elements from the original. 68 // Copy all the elements from the original.
65 for (int i = 0; i < original->elements_.length(); i++) { 69 for (int i = 0; i < original->elements_.length(); i++) {
66 elements_.Add(original->elements_[i]); 70 elements_.Add(original->elements_[i]);
67 } 71 }
68 } 72 }
69 73
70 74
71 // Modify the state of the virtual frame to match the actual frame by adding 75 // Modify the state of the virtual frame to match the actual frame by adding
72 // extra in-memory elements to the top of the virtual frame. The extra 76 // extra in-memory elements to the top of the virtual frame. The extra
73 // elements will be externally materialized on the actual frame (eg, by 77 // elements will be externally materialized on the actual frame (eg, by
(...skipping 13 matching lines...) Expand all
87 // removing elements from the top of the virtual frame. The elements will 91 // removing elements from the top of the virtual frame. The elements will
88 // be externally popped from the actual frame (eg, by a runtime call). No 92 // be externally popped from the actual frame (eg, by a runtime call). No
89 // code is emitted. 93 // code is emitted.
90 void VirtualFrame::Forget(int count) { 94 void VirtualFrame::Forget(int count) {
91 ASSERT(count >= 0); 95 ASSERT(count >= 0);
92 ASSERT(stack_pointer_ == elements_.length() - 1); 96 ASSERT(stack_pointer_ == elements_.length() - 1);
93 ASSERT(elements_.length() >= count); 97 ASSERT(elements_.length() >= count);
94 98
95 stack_pointer_ -= count; 99 stack_pointer_ -= count;
96 for (int i = 0; i < count; i++) { 100 for (int i = 0; i < count; i++) {
97 elements_.RemoveLast(); 101 FrameElement last = elements_.RemoveLast();
102 if (last.is_register()) {
103 Unuse(last.reg());
104 }
98 } 105 }
99 } 106 }
100 107
101 108
109 void VirtualFrame::Use(Register reg) {
110 frame_registers_.Use(reg);
111 cgen_->allocator()->Use(reg);
112 }
113
114
115 void VirtualFrame::Unuse(Register reg) {
116 frame_registers_.Unuse(reg);
117 cgen_->allocator()->Unuse(reg);
118 }
119
120
102 // Clear the dirty bit for the element at a given index. We can only 121 // Clear the dirty bit for the element at a given index. We can only
103 // allocate space in the actual frame for the virtual element immediately 122 // allocate space in the actual frame for the virtual element immediately
104 // above the stack pointer. 123 // above the stack pointer.
105 void VirtualFrame::SyncElementAt(int index) { 124 void VirtualFrame::SyncElementAt(int index) {
106 FrameElement element = elements_[index]; 125 FrameElement element = elements_[index];
107 126
108 if (element.is_dirty()) { 127 if (!element.is_synced()) {
109 if (index <= stack_pointer_) { 128 if (index <= stack_pointer_) {
110 // Write elements below the stack pointer to their (already allocated) 129 // Write elements below the stack pointer to their (already allocated)
111 // actual frame location. 130 // actual frame location.
112 if (element.is_constant()) { 131 if (element.is_constant()) {
113 __ Set(Operand(ebp, fp_relative(index)), Immediate(element.handle())); 132 __ Set(Operand(ebp, fp_relative(index)), Immediate(element.handle()));
114 } else { 133 } else {
115 ASSERT(element.is_register()); 134 ASSERT(element.is_register());
116 __ mov(Operand(ebp, fp_relative(index)), element.reg()); 135 __ mov(Operand(ebp, fp_relative(index)), element.reg());
117 } 136 }
118 } else { 137 } else {
119 // Push elements above the stack pointer to allocate space and sync 138 // Push elements above the stack pointer to allocate space and sync
120 // them. Space should have already been allocated in the actual frame 139 // them. Space should have already been allocated in the actual frame
121 // for all the elements below this one. 140 // for all the elements below this one.
122 ASSERT(index == stack_pointer_ + 1); 141 ASSERT(index == stack_pointer_ + 1);
123 stack_pointer_++; 142 stack_pointer_++;
124 if (element.is_constant()) { 143 if (element.is_constant()) {
125 __ push(Immediate(element.handle())); 144 __ push(Immediate(element.handle()));
126 } else { 145 } else {
127 ASSERT(element.is_register()); 146 ASSERT(element.is_register());
128 __ push(element.reg()); 147 __ push(element.reg());
129 } 148 }
130 } 149 }
150
151 elements_[index].set_sync();
131 } 152 }
132 } 153 }
133 154
134 155
156 // Spill any register if possible, making its reference count zero.
157 Register VirtualFrame::SpillAnyRegister() {
158 // Find the leftmost (ordered by register code), least
159 // internally-referenced register whose internal reference count matches
160 // its external reference count (so that spilling it from the frame frees
161 // it for use).
162 int min_count = kMaxInt;
163 int best_register_code = no_reg.code();
164
165 for (int i = 0; i < RegisterFile::kNumRegisters; i++) {
166 int count = frame_registers_.count(i);
167 if (count < min_count && count == cgen_->allocator()->count(i)) {
168 min_count = count;
169 best_register_code = i;
170 }
171 }
172
173 if (best_register_code != no_reg.code()) {
174 // Spill all occurrences of the register. There are min_count
175 // occurrences, stop when we've spilled them all to avoid syncing
176 // elements unnecessarily.
177 int i = 0;
178 while (min_count > 0) {
179 ASSERT(i < elements_.length());
180 if (elements_[i].is_register() &&
181 elements_[i].reg().code() == best_register_code) {
182 // Found an instance of the best_register being used in the frame.
183 // Spill it.
184 SpillElementAt(i);
185 min_count--;
186 } else {
187 if (i > stack_pointer_) {
188 // Make sure to materialize elements on the virtual frame in
189 // memory. We rely on this to spill occurrences of the register
190 // lying above the current virtual stack pointer.
191 SyncElementAt(i);
192 }
193 }
194 }
195 }
196
197 Register result = { best_register_code };
198 return result;
199 }
200
201
135 // Make the type of the element at a given index be MEMORY. We can only 202 // Make the type of the element at a given index be MEMORY. We can only
136 // allocate space in the actual frame for the virtual element immediately 203 // allocate space in the actual frame for the virtual element immediately
137 // above the stack pointer. 204 // above the stack pointer.
138 void VirtualFrame::SpillElementAt(int index) { 205 void VirtualFrame::SpillElementAt(int index) {
139 SyncElementAt(index); 206 SyncElementAt(index);
140 // The element is now in memory. 207 // The element is now in memory.
208 if (elements_[index].is_register()) {
209 Unuse(elements_[index].reg());
210 }
141 elements_[index] = FrameElement(); 211 elements_[index] = FrameElement();
142 } 212 }
143 213
144 214
215 // Clear the dirty bits for all elements.
216 void VirtualFrame::SyncAll() {
217 for (int i = 0; i < elements_.length(); i++) {
218 SyncElementAt(i);
219 }
220 }
221
222
145 // Make the type of all elements be MEMORY. 223 // Make the type of all elements be MEMORY.
146 void VirtualFrame::SpillAll() { 224 void VirtualFrame::SpillAll() {
147 for (int i = 0; i < elements_.length(); i++) { 225 for (int i = 0; i < elements_.length(); i++) {
148 SpillElementAt(i); 226 SpillElementAt(i);
149 } 227 }
150 } 228 }
151 229
152 230
153 void VirtualFrame::PrepareForCall(int frame_arg_count) { 231 void VirtualFrame::PrepareForCall(int frame_arg_count) {
154 ASSERT(height() >= frame_arg_count); 232 ASSERT(height() >= frame_arg_count);
(...skipping 24 matching lines...) Expand all
179 // We cannot merge to a frame that has constants as elements, because an 257 // We cannot merge to a frame that has constants as elements, because an
180 // arbitrary frame might not have constants in those locations. 258 // arbitrary frame might not have constants in those locations.
181 // 259 //
182 // We cannot merge to a frame that has registers as elements because we 260 // We cannot merge to a frame that has registers as elements because we
183 // haven't implemented merging for such frames yet. 261 // haven't implemented merging for such frames yet.
184 SpillAll(); 262 SpillAll();
185 } 263 }
186 264
187 265
188 void VirtualFrame::MergeTo(VirtualFrame* expected) { 266 void VirtualFrame::MergeTo(VirtualFrame* expected) {
267 ASSERT(cgen_ == expected->cgen_);
189 ASSERT(masm_ == expected->masm_); 268 ASSERT(masm_ == expected->masm_);
190 ASSERT(elements_.length() == expected->elements_.length()); 269 ASSERT(elements_.length() == expected->elements_.length());
191 ASSERT(parameter_count_ == expected->parameter_count_); 270 ASSERT(parameter_count_ == expected->parameter_count_);
192 ASSERT(local_count_ == expected->local_count_); 271 ASSERT(local_count_ == expected->local_count_);
193 ASSERT(frame_pointer_ == expected->frame_pointer_); 272 ASSERT(frame_pointer_ == expected->frame_pointer_);
194 273
195 // Mergable frames do not have constants and they do not (currently) have 274 // Mergable frames do not have constants and they do not (currently) have
196 // registers. They are always fully spilled, so the only thing needed to 275 // registers. They are always fully spilled, so the only thing needed to
197 // make this frame match the expected one is to spill everything. 276 // make this frame match the expected one is to spill everything.
198 // 277 //
199 // TODO(): Implement a non-stupid way of merging frames. 278 // TODO(): Implement a non-stupid way of merging frames.
200 SpillAll(); 279 SpillAll();
201 280
202 ASSERT(stack_pointer_ == expected->stack_pointer_); 281 ASSERT(stack_pointer_ == expected->stack_pointer_);
203 } 282 }
204 283
205 284
206 void VirtualFrame::Enter() { 285 void VirtualFrame::Enter() {
286 // Registers live on entry: esp, ebp, esi, edi.
207 Comment cmnt(masm_, "[ Enter JS frame"); 287 Comment cmnt(masm_, "[ Enter JS frame");
208 EmitPush(ebp); 288 EmitPush(ebp);
209 289
210 frame_pointer_ = stack_pointer_; 290 frame_pointer_ = stack_pointer_;
211 __ mov(ebp, Operand(esp)); 291 __ mov(ebp, Operand(esp));
212 292
213 // Store the context and the function in the frame. 293 // Store the context and the function in the frame.
214 FrameElement context(esi); 294 Push(esi);
215 context.clear_dirty(); 295 // The frame owns the register reference now.
216 elements_.Add(context); 296 cgen_->allocator()->Unuse(esi);
217 stack_pointer_++;
218 __ push(esi);
219 297
220 FrameElement function(edi); 298 Push(edi);
221 function.clear_dirty(); 299 cgen_->allocator()->Unuse(edi);
222 elements_.Add(function);
223 stack_pointer_++;
224 __ push(edi);
225
226 // Clear the function slot when generating debug code.
227 if (FLAG_debug_code) {
228 SpillElementAt(stack_pointer_);
229 __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue)));
230 }
231 } 300 }
232 301
233 302
234 void VirtualFrame::Exit() { 303 void VirtualFrame::Exit() {
235 Comment cmnt(masm_, "[ Exit JS frame"); 304 Comment cmnt(masm_, "[ Exit JS frame");
236 // Record the location of the JS exit code for patching when setting 305 // Record the location of the JS exit code for patching when setting
237 // break point. 306 // break point.
238 __ RecordJSReturn(); 307 __ RecordJSReturn();
239 308
240 // Avoid using the leave instruction here, because it is too 309 // Avoid using the leave instruction here, because it is too
241 // short. We need the return sequence to be a least the size of a 310 // short. We need the return sequence to be a least the size of a
242 // call instruction to support patching the exit code in the 311 // call instruction to support patching the exit code in the
243 // debugger. See VisitReturnStatement for the full return sequence. 312 // debugger. See VisitReturnStatement for the full return sequence.
244 __ mov(esp, Operand(ebp)); 313 __ mov(esp, Operand(ebp));
245 stack_pointer_ = frame_pointer_; 314 stack_pointer_ = frame_pointer_;
246 for (int i = elements_.length() - 1; i > stack_pointer_; i--) { 315 for (int i = elements_.length() - 1; i > stack_pointer_; i--) {
247 elements_.RemoveLast(); 316 FrameElement last = elements_.RemoveLast();
317 if (last.is_register()) {
318 Unuse(last.reg());
319 }
248 } 320 }
249 321
250 frame_pointer_ = kIllegalIndex; 322 frame_pointer_ = kIllegalIndex;
251 EmitPop(ebp); 323 EmitPop(ebp);
252 } 324 }
253 325
254 326
255 void VirtualFrame::AllocateStackSlots(int count) { 327 void VirtualFrame::AllocateStackSlots(int count) {
256 ASSERT(height() == 0); 328 ASSERT(height() == 0);
257 local_count_ = count; 329 local_count_ = count;
258 330
259 if (count > 0) { 331 if (count > 0) {
260 Comment cmnt(masm_, "[ Allocate space for locals"); 332 Comment cmnt(masm_, "[ Allocate space for locals");
261 // The locals are constants (the undefined value), but we sync them with 333 // The locals are constants (the undefined value), but we sync them with
262 // the actual frame to allocate space for spilling them. 334 // the actual frame to allocate space for spilling them.
263 FrameElement initial_value(Factory::undefined_value()); 335 SyncAll();
264 initial_value.clear_dirty(); 336 Handle<Object> undefined = Factory::undefined_value();
265 __ Set(eax, Immediate(Factory::undefined_value())); 337 FrameElement initial_value(undefined, FrameElement::SYNCED);
338 Register tmp = cgen_->allocator()->Allocate();
339 __ Set(tmp, Immediate(undefined));
266 for (int i = 0; i < count; i++) { 340 for (int i = 0; i < count; i++) {
267 elements_.Add(initial_value); 341 elements_.Add(initial_value);
268 stack_pointer_++; 342 stack_pointer_++;
269 __ push(eax); 343 __ push(tmp);
270 } 344 }
345 cgen_->allocator()->Unuse(tmp);
271 } 346 }
272 } 347 }
273 348
274 349
275 void VirtualFrame::PushTryHandler(HandlerType type) { 350 void VirtualFrame::PushTryHandler(HandlerType type) {
276 // Grow the expression stack by handler size less two (the return address 351 // Grow the expression stack by handler size less two (the return address
277 // is already pushed by a call instruction, and PushTryHandler from the 352 // is already pushed by a call instruction, and PushTryHandler from the
278 // macro assembler will leave the top of stack in the eax register to be 353 // macro assembler will leave the top of stack in the eax register to be
279 // pushed separately). 354 // pushed separately).
280 Adjust(kHandlerSize - 2); 355 Adjust(kHandlerSize - 2);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 PrepareForCall(frame_arg_count); 391 PrepareForCall(frame_arg_count);
317 __ call(code, rmode); 392 __ call(code, rmode);
318 } 393 }
319 394
320 395
321 void VirtualFrame::Drop(int count) { 396 void VirtualFrame::Drop(int count) {
322 ASSERT(height() >= count); 397 ASSERT(height() >= count);
323 398
324 // Discard elements above the stack pointer. 399 // Discard elements above the stack pointer.
325 while (count > 0 && stack_pointer_ < elements_.length() - 1) { 400 while (count > 0 && stack_pointer_ < elements_.length() - 1) {
326 elements_.RemoveLast(); 401 FrameElement last = elements_.RemoveLast();
402 if (last.is_register()) {
403 Unuse(last.reg());
404 }
327 } 405 }
328 406
329 // Discard the rest of the elements and lower the stack pointer. 407 // Discard the rest of the elements and lower the stack pointer.
330 Forget(count); 408 Forget(count);
331 if (count > 0) { 409 if (count > 0) {
332 __ add(Operand(esp), Immediate(count * kPointerSize)); 410 __ add(Operand(esp), Immediate(count * kPointerSize));
333 } 411 }
334 } 412 }
335 413
336 414
(...skipping 27 matching lines...) Expand all
364 void VirtualFrame::EmitPush(Operand operand) { 442 void VirtualFrame::EmitPush(Operand operand) {
365 ASSERT(stack_pointer_ == elements_.length() - 1); 443 ASSERT(stack_pointer_ == elements_.length() - 1);
366 elements_.Add(FrameElement()); 444 elements_.Add(FrameElement());
367 stack_pointer_++; 445 stack_pointer_++;
368 __ push(operand); 446 __ push(operand);
369 } 447 }
370 448
371 449
372 void VirtualFrame::EmitPush(Immediate immediate) { 450 void VirtualFrame::EmitPush(Immediate immediate) {
373 ASSERT(stack_pointer_ == elements_.length() - 1); 451 ASSERT(stack_pointer_ == elements_.length() - 1);
374 elements_.Add(FrameElement()); 452 FrameElement memory_element;
453 elements_.Add(memory_element);
375 stack_pointer_++; 454 stack_pointer_++;
376 __ push(immediate); 455 __ push(immediate);
377 } 456 }
378 457
379 458
459 void VirtualFrame::Push(Register reg) {
460 FrameElement register_element(reg, FrameElement::NOT_SYNCED);
461 Use(reg);
462 elements_.Add(register_element);
463 }
464
465
466 void VirtualFrame::Push(Handle<Object> value) {
467 FrameElement constant_element(value, FrameElement::NOT_SYNCED);
468 elements_.Add(constant_element);
469 }
470
471
380 #undef __ 472 #undef __
381 473
382 } } // namespace v8::internal 474 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698