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

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

Issue 19755: Experimental: allow the virtual frame to explicitly indicate sharing... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 10 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 | « 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 stack_pointer_(original->stack_pointer_), 78 stack_pointer_(original->stack_pointer_),
79 frame_pointer_(original->frame_pointer_), 79 frame_pointer_(original->frame_pointer_),
80 frame_registers_(original->frame_registers_) { 80 frame_registers_(original->frame_registers_) {
81 // Copy all the elements from the original. 81 // Copy all the elements from the original.
82 for (int i = 0; i < original->elements_.length(); i++) { 82 for (int i = 0; i < original->elements_.length(); i++) {
83 elements_.Add(original->elements_[i]); 83 elements_.Add(original->elements_[i]);
84 } 84 }
85 } 85 }
86 86
87 87
88 FrameElement VirtualFrame::CopyElementAt(int index) {
89 ASSERT(index >= 0);
90 ASSERT(index < elements_.length());
91
92 FrameElement target = elements_[index];
93 FrameElement result;
94
95 switch (target.type()) {
96 case FrameElement::CONSTANT:
97 // We do not copy constants and instead return a fresh unsynced
98 // constant.
99 result = FrameElement::ConstantElement(target.handle(),
100 FrameElement::NOT_SYNCED);
101 break;
102
103 case FrameElement::COPY:
104 // We do not allow copies of copies, so we follow one link to
105 // the actual backing store of a copy before making a copy.
106 index = target.index();
107 ASSERT(elements_[index].is_memory() || elements_[index].is_register());
108 // Fall through.
109
110 case FrameElement::MEMORY: // Fall through.
111 case FrameElement::REGISTER:
112 // All copies are backed by memory or register locations.
113 result.type_ =
114 FrameElement::TypeField::encode(FrameElement::COPY) |
115 FrameElement::SyncField::encode(FrameElement::NOT_SYNCED);
116 result.data_.index_ = index;
117 break;
118
119 case FrameElement::INVALID:
120 // We should not try to copy invalid elements.
121 UNREACHABLE();
122 break;
123 }
124 return result;
125 }
126
127
88 // Modify the state of the virtual frame to match the actual frame by adding 128 // Modify the state of the virtual frame to match the actual frame by adding
89 // extra in-memory elements to the top of the virtual frame. The extra 129 // extra in-memory elements to the top of the virtual frame. The extra
90 // elements will be externally materialized on the actual frame (eg, by 130 // elements will be externally materialized on the actual frame (eg, by
91 // pushing an exception handler). No code is emitted. 131 // pushing an exception handler). No code is emitted.
92 void VirtualFrame::Adjust(int count) { 132 void VirtualFrame::Adjust(int count) {
93 ASSERT(count >= 0); 133 ASSERT(count >= 0);
94 ASSERT(stack_pointer_ == elements_.length() - 1); 134 ASSERT(stack_pointer_ == elements_.length() - 1);
95 135
96 for (int i = 0; i < count; i++) { 136 for (int i = 0; i < count; i++) {
97 elements_.Add(FrameElement::MemoryElement()); 137 elements_.Add(FrameElement::MemoryElement());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 200
161 Register result = { best_register_code }; 201 Register result = { best_register_code };
162 if (result.is_valid()) { 202 if (result.is_valid()) {
163 Spill(result); 203 Spill(result);
164 ASSERT(!cgen_->allocator()->is_used(result)); 204 ASSERT(!cgen_->allocator()->is_used(result));
165 } 205 }
166 return result; 206 return result;
167 } 207 }
168 208
169 209
170 // Spill an element, making its type be MEMORY.
171 // Does not decrement usage counts, if element is a register.
172 void VirtualFrame::RawSpillElementAt(int index) {
173 if (elements_[index].is_valid()) {
174 SyncElementAt(index);
175 // The element is now in memory.
176 elements_[index] = FrameElement::MemoryElement();
177 }
178 }
179
180
181 // Make the type of the element at a given index be MEMORY. 210 // Make the type of the element at a given index be MEMORY.
182 void VirtualFrame::SpillElementAt(int index) { 211 void VirtualFrame::SpillElementAt(int index) {
212 if (!elements_[index].is_valid()) return;
213
183 if (elements_[index].is_register()) { 214 if (elements_[index].is_register()) {
184 Unuse(elements_[index].reg()); 215 Unuse(elements_[index].reg());
185 } 216 }
186 RawSpillElementAt(index); 217 SyncElementAt(index);
218 // The element is now in memory.
219 elements_[index] = FrameElement::MemoryElement();
187 } 220 }
188 221
189 222
190 // Clear the dirty bit for the element at a given index. 223 // Clear the dirty bit for the element at a given index if it is a
191 // The element must be on the physical stack, or the first 224 // valid element. The stack address corresponding to the element must
192 // element below the stack pointer (created by a single push). 225 // be allocated on the physical stack, or the first element above the
226 // stack pointer so it can be allocated by a single push instruction.
193 void VirtualFrame::RawSyncElementAt(int index) { 227 void VirtualFrame::RawSyncElementAt(int index) {
194 FrameElement element = elements_[index]; 228 FrameElement element = elements_[index];
195 if (element.is_valid() && !element.is_synced()) { 229
196 if (index <= stack_pointer_) { 230 if (!element.is_valid() || element.is_synced()) return;
197 // Write elements below the stack pointer to their (already allocated) 231
198 // actual frame location. 232 if (index <= stack_pointer_) {
199 if (element.is_constant()) { 233 // Emit code to write elements below the stack pointer to their
234 // (already allocated) stack address.
235 switch (element.type()) {
236 case FrameElement::INVALID: // Fall through.
237 case FrameElement::MEMORY:
238 // There was an early bailout for invalid and synced elements
239 // (memory elements are always synced).
240 UNREACHABLE();
241 break;
242
243 case FrameElement::REGISTER:
244 __ mov(Operand(ebp, fp_relative(index)), element.reg());
245 break;
246
247 case FrameElement::CONSTANT:
200 __ Set(Operand(ebp, fp_relative(index)), Immediate(element.handle())); 248 __ Set(Operand(ebp, fp_relative(index)), Immediate(element.handle()));
201 } else { 249 break;
202 ASSERT(element.is_register()); 250
203 __ mov(Operand(ebp, fp_relative(index)), element.reg()); 251 case FrameElement::COPY: {
204 } 252 int backing_index = element.index();
205 } else { 253 FrameElement backing_element = elements_[backing_index];
206 // Push elements above the stack pointer to allocate space and sync 254 if (backing_element.is_memory()) {
207 // them. Space should have already been allocated in the actual frame 255 Result temp = cgen_->allocator()->Allocate();
208 // for all the elements below this one. 256 ASSERT(temp.is_valid());
209 ASSERT(index == stack_pointer_ + 1); 257 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index)));
210 stack_pointer_++; 258 __ mov(Operand(ebp, fp_relative(index)), temp.reg());
211 if (element.is_constant()) { 259 } else {
212 __ push(Immediate(element.handle())); 260 ASSERT(backing_element.is_register());
213 } else { 261 __ mov(Operand(ebp, fp_relative(index)), backing_element.reg());
214 ASSERT(element.is_register()); 262 }
215 __ push(element.reg()); 263 break;
216 } 264 }
217 } 265 }
218 266
219 elements_[index].set_sync(); 267 } else {
268 // Push elements above the stack pointer to allocate space and
269 // sync them. Space should have already been allocated in the
270 // actual frame for all the elements below this one.
271 ASSERT(index == stack_pointer_ + 1);
272 stack_pointer_++;
273 switch (element.type()) {
274 case FrameElement::INVALID: // Fall through.
275 case FrameElement::MEMORY:
276 // There was an early bailout for invalid and synced elements
277 // (memory elements are always synced).
278 UNREACHABLE();
279 break;
280
281 case FrameElement::REGISTER:
282 __ push(element.reg());
283 break;
284
285 case FrameElement::CONSTANT:
286 __ push(Immediate(element.handle()));
287 break;
288
289 case FrameElement::COPY: {
290 int backing_index = element.index();
291 FrameElement backing = elements_[backing_index];
292 ASSERT(backing.is_memory() || backing.is_register());
293 if (backing.is_memory()) {
294 __ push(Operand(ebp, fp_relative(backing_index)));
295 } else {
296 __ push(backing.reg());
297 }
298 break;
299 }
300 }
220 } 301 }
302
303 elements_[index].set_sync();
221 } 304 }
222 305
223 306
224 // Clear the dirty bits for the range of elements in [begin, end). 307 // Clear the dirty bits for the range of elements in [begin, end).
225 void VirtualFrame::SyncRange(int begin, int end) { 308 void VirtualFrame::SyncRange(int begin, int end) {
226 ASSERT(begin >= 0); 309 ASSERT(begin >= 0);
227 ASSERT(end <= elements_.length()); 310 ASSERT(end <= elements_.length());
228 for (int i = begin; i < end; i++) { 311 for (int i = begin; i < end; i++) {
229 RawSyncElementAt(i); 312 RawSyncElementAt(i);
230 } 313 }
(...skipping 15 matching lines...) Expand all
246 SpillElementAt(i); 329 SpillElementAt(i);
247 } 330 }
248 } 331 }
249 332
250 333
251 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { 334 void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
252 ASSERT(height() >= dropped_args); 335 ASSERT(height() >= dropped_args);
253 ASSERT(height() >= spilled_args); 336 ASSERT(height() >= spilled_args);
254 ASSERT(dropped_args <= spilled_args); 337 ASSERT(dropped_args <= spilled_args);
255 338
256 // Below the arguments to the function being called, spill all registers and
257 // make sure that locals have the right values by synching them. The synching
258 // is necessary to give the debugger a consistent view of the values of
259 // locals in the frame. Spill the arguments to the function being called.
260 int arg_base_index = elements_.length() - spilled_args; 339 int arg_base_index = elements_.length() - spilled_args;
261 for (int i = 0; i < arg_base_index; i++) { 340 // Spill the arguments. We spill from the top down so that the
341 // backing stores of register copies will be spilled only after all
342 // the copies are spilled---it is better to spill via a
343 // register-to-memory move than a memory-to-memory move.
344 for (int i = elements_.length() - 1; i >= arg_base_index; i--) {
345 SpillElementAt(i);
346 }
347
348 // Below the arguments, spill registers and sync everything else.
349 // Syncing is necessary for the locals and parameters to give the
350 // debugger a consistent view of the frame.
351 for (int i = arg_base_index - 1; i >= 0; i--) {
262 FrameElement element = elements_[i]; 352 FrameElement element = elements_[i];
263 if (element.is_register()) { 353 if (element.is_register()) {
264 SpillElementAt(i); 354 SpillElementAt(i);
265 } else if (element.is_valid()) { 355 } else if (element.is_valid()) {
266 SyncElementAt(i); 356 SyncElementAt(i);
267 } 357 }
268 } 358 }
269 // The arguments are spilled.
270 for (int i = arg_base_index; i < elements_.length(); i++) {
271 SpillElementAt(i);
272 }
273 359
274 // Forget the frame elements that will be popped by the call. 360 // Forget the frame elements that will be popped by the call.
275 Forget(dropped_args); 361 Forget(dropped_args);
276 } 362 }
277 363
278 364
279 void VirtualFrame::MakeMergable() { 365 void VirtualFrame::MakeMergable() {
280 Comment cmnt(masm_, "[ Make frame mergable"); 366 Comment cmnt(masm_, "[ Make frame mergable");
281 // We should always be merging the code generator's current frame to an 367 // We should always be merging the code generator's current frame to an
282 // expected frame. 368 // expected frame.
283 ASSERT(cgen_->frame() == this); 369 ASSERT(cgen_->frame() == this);
284 ASSERT(cgen_->HasValidEntryRegisters()); 370 ASSERT(cgen_->HasValidEntryRegisters());
285 371
286 // Remove constants from the frame and ensure that no registers are 372 // Remove constants from the frame and ensure that there are no
287 // multiply referenced within the frame. Allocate elements to their new 373 // copies. Allocate elements to their new locations from the top
288 // locations from the top down so that the topmost elements have a chance 374 // down so that the topmost elements have a chance to be in
289 // to be in registers, then fill them into memory from the bottom up. 375 // registers, then fill them into memory from the bottom up.
290 // (NB: Currently when spilling registers that are multiply referenced, it 376 //
291 // is the lowermost occurrence that gets to stay in the register.) 377 // Compute the new frame elements first. The elements of
378 // new_elements are initially invalid.
379 FrameElement* new_elements = new FrameElement[elements_.length()];
380 // Array of flags, true if we have found a the topmost copy of a
381 // register. Every element after the first is initialized to 0 (ie,
382 // false).
383 bool topmost_found[RegisterFile::kNumRegisters] = { false };
384 // "Singleton" memory element. They have no internal state.
385 FrameElement memory_element = FrameElement::MemoryElement();
292 386
293 // The elements of new_elements are initially invalid.
294 FrameElement* new_elements = new FrameElement[elements_.length()];
295 FrameElement memory_element = FrameElement::MemoryElement();
296 for (int i = elements_.length() - 1; i >= 0; i--) { 387 for (int i = elements_.length() - 1; i >= 0; i--) {
297 FrameElement element = elements_[i]; 388 FrameElement element = elements_[i];
298 if (element.is_constant() || 389
299 (element.is_register() && 390 switch (element.type()) {
300 frame_registers_.count(element.reg()) > 1)) { 391 case FrameElement::INVALID: // Fall through.
301 // A simple strategy is to locate these elements in memory if they are 392 case FrameElement::MEMORY:
302 // synced (avoiding a spill right now) and otherwise to prefer a 393 new_elements[i] = element;
303 // register for them. 394 break;
304 if (element.is_synced()) { 395
305 new_elements[i] = memory_element; 396 case FrameElement::REGISTER:
306 } else { 397 // If this is not the first (and only) register reference we
307 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); 398 // try to find a good home for it, otherwise it can stay in
308 if (fresh.is_valid()) { 399 // the register.
309 // We immediately record the frame's use of the register so that 400 if (topmost_found[element.reg().code()]) {
310 // it will not be allocated again. 401 // A simple strategy is to spill to memory if it is already
311 Use(fresh.reg()); 402 // synced (avoiding a spill now), and otherwise to prefer a
312 new_elements[i] = 403 // register if one is available.
313 FrameElement::RegisterElement(fresh.reg(), 404 if (element.is_synced()) {
314 FrameElement::NOT_SYNCED); 405 // We do not unuse this register reference because we want
406 // the register allocator to count the other one (higher
407 // up in the new frame).
408 new_elements[i] = memory_element;
409 } else {
410 Result fresh = cgen_->allocator()->AllocateWithoutSpilling();
411 if (fresh.is_valid()) {
412 // We immediately record the frame's use of the register
413 // so that the register allocator will not try to use it
414 // again.
415 Use(fresh.reg());
416 new_elements[i] =
417 FrameElement::RegisterElement(fresh.reg(),
418 FrameElement::NOT_SYNCED);
419 } else {
420 new_elements[i] = memory_element;
421 }
422 }
315 } else { 423 } else {
424 // The only occurrence can stay in the register.
425 new_elements[i] = element;
426 }
427 break;
428
429 case FrameElement::CONSTANT:
430 // Prefer spilling synced constants and registers for the rest.
431 if (element.is_synced()) {
316 new_elements[i] = memory_element; 432 new_elements[i] = memory_element;
433 } else {
434 Result fresh = cgen_->allocator()->AllocateWithoutSpilling();
435 if (fresh.is_valid()) {
436 // We immediately record the frame's use of the register
437 // so that the register allocator will not try to use it
438 // again.
439 Use(fresh.reg());
440 new_elements[i] =
441 FrameElement::RegisterElement(fresh.reg(),
442 FrameElement::NOT_SYNCED);
443 } else {
444 new_elements[i] = memory_element;
445 }
317 } 446 }
447 break;
448
449 case FrameElement::COPY: {
450 FrameElement backing = elements_[element.index()];
451 if (backing.is_memory()) {
452 new_elements[i] = memory_element;
453 } else {
454 ASSERT(backing.is_register());
455 if (topmost_found[backing.reg().code()]) {
456 if (element.is_synced()) {
457 new_elements[i] = memory_element;
458 } else {
459 Result fresh = cgen_->allocator()->AllocateWithoutSpilling();
460 if (fresh.is_valid()) {
461 // We immediately record the frame's use of the
462 // register so that the register allocator will not
463 // try to use it again.
464 Use(fresh.reg());
465 new_elements[i] =
466 FrameElement::RegisterElement(fresh.reg(),
467 FrameElement::NOT_SYNCED);
468 } else {
469 new_elements[i] = memory_element;
470 }
471 }
472 // When performing the moves (from bottom to top) later,
473 // we will need to know what register this one is a copy
474 // of and the original backing element will already be
475 // overwritten. We store that information in this
476 // elements frame slot so that it looks like this is a
477 // move from a register rather than a copy.
478 if (element.is_synced()) {
479 backing.set_sync();
480 } else {
481 backing.clear_sync();
482 }
483 Use(backing.reg());
484 elements_[i] = backing;
485
486 } else {
487 // This is the top occurrence of the register.
488 topmost_found[backing.reg().code()] = true;
489 if (element.is_synced()) {
490 backing.set_sync();
491 } else {
492 backing.clear_sync();
493 }
494 // Record the register reference immediately so that
495 // register allocator does not try to use this register as
496 // a temp register when performing the moves.
497 Use(backing.reg());
498 new_elements[i] = backing;
499 }
500 }
501 break;
318 } 502 }
319
320 // We have not moved register references, but record that we will so
321 // that we do not unnecessarily spill the last reference within the
322 // frame.
323 if (element.is_register()) {
324 Unuse(element.reg());
325 }
326 } else {
327 // The element is in memory or a singly-frame-referenced register.
328 new_elements[i] = element;
329 } 503 }
330 } 504 }
331 505
332 // Perform the moves. 506 // Perform the moves. Reference counts for register targets have
507 // already been incremented.
333 for (int i = 0; i < elements_.length(); i++) { 508 for (int i = 0; i < elements_.length(); i++) {
334 FrameElement source = elements_[i]; 509 FrameElement source = elements_[i];
335 FrameElement target = new_elements[i]; 510 FrameElement target = new_elements[i];
336 ASSERT(!target.is_valid() || target.is_register() || target.is_memory()); 511 ASSERT(!target.is_valid() || target.is_register() || target.is_memory());
337 if (target.is_register()) { 512 if (target.is_register()) {
338 if (source.is_constant()) { 513 if (source.is_constant()) {
339 __ Set(target.reg(), Immediate(source.handle())); 514 __ Set(target.reg(), Immediate(source.handle()));
340 } else if (source.is_register() && !source.reg().is(target.reg())) { 515 } else if (source.is_register() && !source.reg().is(target.reg())) {
516 Unuse(source.reg());
341 __ mov(target.reg(), source.reg()); 517 __ mov(target.reg(), source.reg());
342 } 518 }
519 // Otherwise the source and target are the same register or the
520 // source is a copy. If the source is a copy that implies that
521 // it is the same register as the target (copies that are moved
522 // to other registers appear as register-to-register moves).
343 elements_[i] = target; 523 elements_[i] = target;
524 ASSERT(target.is_synced() == source.is_synced());
344 } else if (target.is_memory()) { 525 } else if (target.is_memory()) {
345 if (!source.is_memory()) { 526 if (!source.is_memory()) {
346 // Spilling a source register would decrement its reference count, 527 SpillElementAt(i);
347 // but we have already done that when computing new target elements,
348 // so we use a raw spill.
349 RawSpillElementAt(i);
350 } 528 }
351 } 529 }
352 // Invalid elements do not need to be moved. 530 // Invalid elements do not need to be moved.
353 } 531 }
354 532
355 delete[] new_elements; 533 delete[] new_elements;
356 ASSERT(cgen_->HasValidEntryRegisters()); 534 ASSERT(cgen_->HasValidEntryRegisters());
357 } 535 }
358 536
359 537
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 ASSERT(elements_[i].handle().location() == 596 ASSERT(elements_[i].handle().location() ==
419 expect.handle().location()); 597 expect.handle().location());
420 ASSERT(elements_[i].is_synced() == expect.is_synced()); 598 ASSERT(elements_[i].is_synced() == expect.is_synced());
421 } 599 }
422 } 600 }
423 #endif 601 #endif
424 } 602 }
425 603
426 604
427 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame *expected) { 605 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame *expected) {
606 // Move registers, constants, and copies to memory.
428 for (int i = 0; i < elements_.length(); i++) { 607 for (int i = 0; i < elements_.length(); i++) {
429 FrameElement source = elements_[i]; 608 FrameElement source = elements_[i];
430 FrameElement target = expected->elements_[i]; 609 FrameElement target = expected->elements_[i];
431 if (target.is_memory() && !source.is_memory()) { 610 if (target.is_memory() && !source.is_memory()) {
432 ASSERT(source.is_register() || source.is_constant()); 611 ASSERT(source.is_register() ||
612 source.is_constant() ||
613 source.is_copy());
433 SpillElementAt(i); 614 SpillElementAt(i);
434 } 615 }
435 } 616 }
436 } 617 }
437 618
438 619
439 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame *expected) { 620 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame *expected) {
621 // Perform register-to-register moves.
440 int start = 0; 622 int start = 0;
441 int end = elements_.length() - 1; 623 int end = elements_.length() - 1;
442 bool any_moves_blocked; // Did we fail to make some moves this iteration? 624 bool any_moves_blocked; // Did we fail to make some moves this iteration?
443 bool should_break_cycles = false; 625 bool should_break_cycles = false;
444 bool any_moves_made; // Did we make any progress this iteration? 626 bool any_moves_made; // Did we make any progress this iteration?
445 do { 627 do {
446 any_moves_blocked = false; 628 any_moves_blocked = false;
447 any_moves_made = false; 629 any_moves_made = false;
448 int first_move_blocked = kIllegalIndex; 630 int first_move_blocked = kIllegalIndex;
449 int last_move_blocked = kIllegalIndex; 631 int last_move_blocked = kIllegalIndex;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 should_break_cycles = (any_moves_blocked && !any_moves_made); 673 should_break_cycles = (any_moves_blocked && !any_moves_made);
492 if (any_moves_blocked) { 674 if (any_moves_blocked) {
493 start = first_move_blocked; 675 start = first_move_blocked;
494 end = last_move_blocked; 676 end = last_move_blocked;
495 } 677 }
496 } while (any_moves_blocked); 678 } while (any_moves_blocked);
497 } 679 }
498 680
499 681
500 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { 682 void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
501 // Finally, constant-to-register and memory-to-register. We do these from 683 // Move memory, constants, and copies to registers. This is the
502 // the top down so we can use pop for memory-to-register moves above the 684 // final step and is done from the bottom up so that the backing
503 // expected stack pointer. 685 // elements of copies are in their correct locations when we
504 for (int i = elements_.length() - 1; i >= 0; i--) { 686 // encounter the copies.
687 for (int i = 0; i < elements_.length(); i++) {
505 FrameElement source = elements_[i]; 688 FrameElement source = elements_[i];
506 FrameElement target = expected->elements_[i]; 689 FrameElement target = expected->elements_[i];
507 if (target.is_register() && !source.is_register()) { 690 if (target.is_register() && !source.is_register()) {
508 ASSERT(source.is_constant() || source.is_memory()); 691 switch (source.type()) {
509 if (source.is_memory()) { 692 case FrameElement::INVALID: // Fall through.
510 ASSERT(i <= stack_pointer_); 693 case FrameElement::REGISTER:
511 if (i <= expected->stack_pointer_) { 694 UNREACHABLE();
512 // Elements below both stack pointers can just be moved. 695 break;
696
697 case FrameElement::MEMORY:
698 ASSERT(i <= stack_pointer_);
513 __ mov(target.reg(), Operand(ebp, fp_relative(i))); 699 __ mov(target.reg(), Operand(ebp, fp_relative(i)));
514 } else { 700 break;
515 // Elements below the current stack pointer but above the expected 701
516 // one can be popped, but first we may have to adjust the stack 702 case FrameElement::CONSTANT:
517 // pointer downward. 703 __ Set(target.reg(), Immediate(source.handle()));
518 if (stack_pointer_ > i) { 704 break;
519 // Sync elements between i and stack pointer, and bring 705
520 // stack pointer down to i. 706 case FrameElement::COPY: {
521 #ifdef DEBUG 707 FrameElement backing = elements_[source.index()];
522 // In debug builds check to ensure this is safe. 708 ASSERT(backing.is_memory() || backing.is_register());
523 for (int j = stack_pointer_; j > i; j--) { 709 if (backing.is_memory()) {
524 ASSERT(!elements_[j].is_memory()); 710 ASSERT(source.index() <= stack_pointer_);
525 } 711 __ mov(target.reg(), Operand(ebp, fp_relative(source.index())));
526 #endif 712 } else {
527 int difference = stack_pointer_ - i; 713 __ mov(target.reg(), backing.reg());
528 __ add(Operand(esp), Immediate(difference * kPointerSize));
529 stack_pointer_ = i;
530 } 714 }
531 stack_pointer_--;
532 __ pop(target.reg());
533 } 715 }
534 } else { 716 }
535 // Source is constant. 717 // Ensure the proper sync state. If the source was memory no
536 __ Set(target.reg(), Immediate(source.handle())); 718 // code needs to be emitted.
537 if (target.is_synced()) { 719 if (target.is_synced() && !source.is_memory()) {
538 SyncElementAt(i); 720 SyncElementAt(i);
539 }
540 } 721 }
541 Use(target.reg()); 722 Use(target.reg());
542 elements_[i] = target; 723 elements_[i] = target;
543 } 724 }
544 } 725 }
545 } 726 }
546 727
547 728
548 void VirtualFrame::DetachFromCodeGenerator() { 729 void VirtualFrame::DetachFromCodeGenerator() {
549 // Tell the global register allocator that it is free to reallocate all 730 // Tell the global register allocator that it is free to reallocate all
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 } 835 }
655 } 836 }
656 } 837 }
657 838
658 839
659 void VirtualFrame::SetElementAt(int index, Result* value) { 840 void VirtualFrame::SetElementAt(int index, Result* value) {
660 int frame_index = elements_.length() - index - 1; 841 int frame_index = elements_.length() - index - 1;
661 ASSERT(frame_index >= 0); 842 ASSERT(frame_index >= 0);
662 ASSERT(frame_index < elements_.length()); 843 ASSERT(frame_index < elements_.length());
663 ASSERT(value->is_valid()); 844 ASSERT(value->is_valid());
664 FrameElement target = elements_[frame_index]; 845 FrameElement original = elements_[frame_index];
665 846
666 if (target.is_register()) { 847 // Early exit if the element is the same as the one being set.
667 Unuse(target.reg()); 848 bool same_register = original.is_register()
849 && value->is_register()
850 && original.reg().is(value->reg());
851 bool same_constant = original.is_constant()
852 && value->is_constant()
853 && original.handle().is_identical_to(value->handle());
854 if (same_register || same_constant) {
855 value->Unuse();
856 return;
668 } 857 }
669 858
859 // If the original may be a copy, adjust to preserve the copy-on-write
860 // semantics of copied elements.
861 if (original.is_register() || original.is_memory()) {
862 FrameElement ignored = AdjustCopies(frame_index);
863 }
864
865 // If the original is a register reference, deallocate it.
866 if (original.is_register()) {
867 Unuse(original.reg());
868 }
869
870 FrameElement new_element;
670 if (value->is_register()) { 871 if (value->is_register()) {
671 Use(value->reg()); 872 // There are two cases depending no whether the register already
672 // Write the new value to the frame, if it is changed. 873 // occurs in the frame or not.
673 // Otherwise, if target equals value, keep its current sync state. 874 if (register_count(value->reg()) == 0) {
674 if (!target.is_register() || 875 Use(value->reg());
675 !value->reg().is(target.reg())) {
676 elements_[frame_index] = 876 elements_[frame_index] =
677 FrameElement::RegisterElement(value->reg(), 877 FrameElement::RegisterElement(value->reg(),
678 FrameElement::NOT_SYNCED); 878 FrameElement::NOT_SYNCED);
879 } else {
880 for (int i = 0; i < elements_.length(); i++) {
881 FrameElement element = elements_[i];
882 if (element.is_register() && element.reg().is(value->reg())) {
883 // The register backing store is lower in the frame than its
884 // copy.
885 if (i < frame_index) {
886 elements_[frame_index] = CopyElementAt(i);
887 } else {
888 // There was an early bailout for the case of setting a
889 // register element to itself.
890 ASSERT(i != frame_index);
891 element.clear_sync();
892 elements_[frame_index] = element;
893 elements_[i] = CopyElementAt(frame_index);
894 }
895 // Exit the loop once the appropriate copy is inserted.
896 break;
897 }
898 }
679 } 899 }
680 } else { 900 } else {
681 ASSERT(value->is_constant()); 901 ASSERT(value->is_constant());
682 // Write the new value to the frame element, if it is a change. 902 elements_[frame_index] =
683 // Otherwise, do nothing, and keep the current sync state. 903 FrameElement::ConstantElement(value->handle(),
684 if (!target.is_constant() || 904 FrameElement::NOT_SYNCED);
685 !value->handle().is_identical_to(target.handle())) {
686 elements_[frame_index] =
687 FrameElement::ConstantElement(value->handle(),
688 FrameElement::NOT_SYNCED);
689 }
690 } 905 }
691 value->Unuse(); 906 value->Unuse();
692 } 907 }
693 908
694 909
695 void VirtualFrame::SaveContextRegister() { 910 void VirtualFrame::SaveContextRegister() {
696 FrameElement current = elements_[context_index()]; 911 FrameElement current = elements_[context_index()];
697 ASSERT(current.is_register() || current.is_memory()); 912 ASSERT(current.is_register() || current.is_memory());
698 if (!current.is_register() || !current.reg().is(esi)) { 913 if (!current.is_register() || !current.reg().is(esi)) {
699 if (current.is_register()) { 914 if (current.is_register()) {
(...skipping 26 matching lines...) Expand all
726 941
727 void VirtualFrame::PushReceiverSlotAddress() { 942 void VirtualFrame::PushReceiverSlotAddress() {
728 Result temp = cgen_->allocator()->Allocate(); 943 Result temp = cgen_->allocator()->Allocate();
729 ASSERT(temp.is_valid()); 944 ASSERT(temp.is_valid());
730 __ lea(temp.reg(), ParameterAt(-1)); 945 __ lea(temp.reg(), ParameterAt(-1));
731 Push(&temp); 946 Push(&temp);
732 } 947 }
733 948
734 949
735 void VirtualFrame::LoadFrameSlotAt(int index) { 950 void VirtualFrame::LoadFrameSlotAt(int index) {
951 FrameElement new_element = CopyElementAt(index);
952 elements_.Add(new_element);
953 }
954
955
956 // Before changing an element which is copied, adjust so that the
957 // first copy becomes the new backing store and all the other copies
958 // are updated. If the original was in memory, the new backing store
959 // is allocated to a register. Return a copy of the new backing store
960 // or an invalid element if the original was not a copy.
961 FrameElement VirtualFrame::AdjustCopies(int index) {
962 FrameElement original = elements_[index];
963 ASSERT(original.is_memory() || original.is_register());
964
965 // Go looking for a first copy above index.
966 int i = index + 1;
967 while (i < elements_.length()) {
968 FrameElement elt = elements_[i];
969 if (elt.is_copy() && elt.index() == index) break;
970 i++;
971 }
972
973 if (i < elements_.length()) {
974 // There was a first copy. Make it the new backing element.
975 Register backing_reg;
976 if (original.is_memory()) {
977 Result fresh = cgen_->allocator()->Allocate();
978 ASSERT(fresh.is_valid());
979 backing_reg = fresh.reg();
980 __ mov(backing_reg, Operand(ebp, fp_relative(index)));
981 } else {
982 // The original was in a register.
983 backing_reg = original.reg();
984 }
985 FrameElement new_backing_element =
986 FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED);
987 if (elements_[i].is_synced()) {
988 new_backing_element.set_sync();
989 }
990 Use(backing_reg);
991 elements_[i] = new_backing_element;
992
993 // Update the other copies.
994 FrameElement copy = CopyElementAt(i);
995 for (int j = i; j < elements_.length(); j++) {
996 FrameElement elt = elements_[j];
997 if (elt.is_copy() && elt.index() == index) {
998 if (elt.is_synced()) {
999 copy.set_sync();
1000 } else {
1001 copy.clear_sync();
1002 }
1003 elements_[j] = copy;
1004 }
1005 }
1006
1007 copy.clear_sync();
1008 return copy;
1009 }
1010
1011 return FrameElement::InvalidElement();
1012 }
1013
1014
1015 void VirtualFrame::TakeFrameSlotAt(int index) {
1016 ASSERT(index >= 0);
1017 ASSERT(index <= elements_.length());
1018 FrameElement original = elements_[index];
1019
1020 switch (original.type()) {
1021 case FrameElement::INVALID:
1022 UNREACHABLE();
1023 break;
1024
1025 case FrameElement::MEMORY: {
1026 // Allocate the element to a register. If it is not copied,
1027 // push that register on top of the frame. If it is copied,
1028 // make the first copy the backing store and push a fresh copy
1029 // on top of the frame.
1030 FrameElement copy = AdjustCopies(index);
1031 if (copy.is_valid()) {
1032 // The original element was a copy. Push the copy of the new
1033 // backing store.
1034 elements_.Add(copy);
1035 } else {
1036 // The element was not a copy. Move it to a register and push
1037 // that.
1038 Result fresh = cgen_->allocator()->Allocate();
1039 ASSERT(fresh.is_valid());
1040 FrameElement new_element =
1041 FrameElement::RegisterElement(fresh.reg(),
1042 FrameElement::NOT_SYNCED);
1043 Use(fresh.reg());
1044 elements_.Add(new_element);
1045 __ mov(fresh.reg(), Operand(ebp, fp_relative(index)));
1046 }
1047 break;
1048 }
1049
1050 case FrameElement::REGISTER: {
1051 // If the element is not copied, push it on top of the frame.
1052 // If it is copied, make the first copy be the new backing store
1053 // and push a fresh copy on top of the frame.
1054 FrameElement copy = AdjustCopies(index);
1055 if (copy.is_valid()) {
1056 // The original element was a copy. Push the copy of the new
1057 // backing store.
1058 elements_.Add(copy);
1059 // This is the only case where we have to unuse the original
1060 // register. The original is still counted and so is the new
1061 // backing store of the copies.
1062 Unuse(original.reg());
1063 } else {
1064 // The element was not a copy. Push it.
1065 original.clear_sync();
1066 elements_.Add(original);
1067 }
1068 break;
1069 }
1070
1071 case FrameElement::CONSTANT:
1072 elements_.Add(original);
1073 break;
1074
1075 case FrameElement::COPY:
1076 elements_.Add(original);
1077 break;
1078 }
1079 elements_[index] = FrameElement::InvalidElement();
1080 }
1081
1082
1083 void VirtualFrame::StoreToFrameSlotAt(int index) {
1084 // Store the value on top of the frame to the virtual frame slot at
1085 // a given index. The value on top of the frame is left in place.
1086 // This is a duplicating operation, so it can create copies.
736 ASSERT(index >= 0); 1087 ASSERT(index >= 0);
737 ASSERT(index < elements_.length()); 1088 ASSERT(index < elements_.length());
738 1089
739 FrameElement element = elements_[index]; 1090 FrameElement original = elements_[index];
740 1091 // If the stored-to slot may be copied, adjust to preserve the
741 if (element.is_memory()) { 1092 // copy-on-write semantics of copied elements.
742 ASSERT(index <= stack_pointer_); 1093 if (original.is_register() || original.is_memory()) {
743 // Eagerly load memory elements into a register. The element at 1094 FrameElement ignored = AdjustCopies(index);
744 // the index and the new top of the frame are backed by the same 1095 }
745 // register location. 1096
746 Result temp = cgen_->allocator()->Allocate(); 1097 // If the stored-to slot is a register reference, deallocate it.
747 ASSERT(temp.is_valid()); 1098 if (original.is_register()) {
748 FrameElement new_element 1099 Unuse(original.reg());
749 = FrameElement::RegisterElement(temp.reg(), 1100 }
750 FrameElement::SYNCED); 1101
751 Use(temp.reg()); 1102 int top_index = elements_.length() - 1;
752 elements_[index] = new_element; 1103 FrameElement top = elements_[top_index];
753 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); 1104 ASSERT(top.is_valid());
754 1105
755 Use(temp.reg()); 1106 if (top.is_copy()) {
756 new_element.clear_sync(); 1107 // There are two cases based on the relative positions of the
757 elements_.Add(new_element); 1108 // stored-to slot and the backing slot of the top element.
758 } else { 1109 int backing_index = top.index();
759 // For constants and registers, add an (unsynced) copy of the element to 1110 ASSERT(backing_index != index);
760 // the top of the frame. 1111 if (backing_index < index) {
761 ASSERT(element.is_register() || element.is_constant()); 1112 // 1. The top element is a copy of a slot below the stored-to
762 if (element.is_register()) { 1113 // slot. The stored-to slot becomes an unsynced copy of that
763 Use(element.reg()); 1114 // same backing slot.
764 } 1115 elements_[index] = CopyElementAt(backing_index);
765 element.clear_sync(); 1116 } else {
766 elements_.Add(element); 1117 // 2. The top element is a copy of a slot above the stored-to
767 } 1118 // slot. The stored-to slot becomes the new (unsynced) backing
768 } 1119 // slot and both the top element and the element at the former
769 1120 // backing slot become copies of it. The sync state of the top
770 1121 // and former backing elements is preserved.
771 void VirtualFrame::TakeFrameSlotAt(int index) { 1122 FrameElement backing_element = elements_[backing_index];
772 LoadFrameSlotAt(index); 1123 ASSERT(backing_element.is_memory() || backing_element.is_register());
773 1124 if (backing_element.is_memory()) {
774 if (elements_[index].is_register()) { 1125 // Because sets of copies are canonicalized to be backed by
775 Unuse(elements_[index].reg()); 1126 // their lowest frame element, and because memory frame
776 } 1127 // elements are backed by the corresponding stack address, we
777 elements_[index] = FrameElement::InvalidElement(); 1128 // have to move the actual value down in the stack.
778 } 1129 //
779 1130 // TODO(209): considering allocating the stored-to slot to the
780 1131 // temp register. Alternatively, allow copies to appear in
781 void VirtualFrame::StoreToFrameSlotAt(int index) { 1132 // any order in the frame and lazily move the value down to
782 // Store the value on top of the frame to the virtual frame slot at a 1133 // the slot.
783 // given index. The value on top of the frame is left in place. 1134 Result temp = cgen_->allocator()->Allocate();
784 ASSERT(index >= 0); 1135 ASSERT(temp.is_valid());
785 ASSERT(index < elements_.length()); 1136 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index)));
786 FrameElement top = elements_[elements_.length() - 1]; 1137 __ mov(Operand (ebp, fp_relative(index)), temp.reg());
787 1138 } else if (backing_element.is_synced()) {
788 if (elements_[index].is_register()) { 1139 // If the element is a register, we will not actually move
789 Unuse(elements_[index].reg()); 1140 // anything on the stack but only update the virtual frame
790 } 1141 // element.
791 // The virtual frame slot will be of the same type and have the same value 1142 backing_element.clear_sync();
792 // as the frame top. 1143 }
1144 elements_[index] = backing_element;
1145
1146 // The old backing element becomes a copy of the new backing
1147 // element.
1148 FrameElement new_element = CopyElementAt(index);
1149 elements_[backing_index] = new_element;
1150 if (backing_element.is_synced()) {
1151 elements_[backing_index].set_sync();
1152 }
1153
1154 // All the copies of the old backing element (including the top
1155 // element) become copies of the new backing element.
1156 for (int i = backing_index + 1; i < elements_.length(); i++) {
1157 FrameElement current = elements_[i];
1158 if (current.is_copy() && current.index() == backing_index) {
1159 elements_[i] = new_element;
1160 if (current.is_synced()) {
1161 elements_[i].set_sync();
1162 }
1163 }
1164 }
1165
1166 }
1167
1168 return;
1169 }
1170
1171 // Move the top element to the stored-to slot and replace it (the
1172 // top element) with a copy.
793 elements_[index] = top; 1173 elements_[index] = top;
794
795 if (top.is_memory()) { 1174 if (top.is_memory()) {
796 // TODO(209): consider allocating the slot to a register. 1175 // TODO(209): consider allocating the stored-to slot to the temp
797 // 1176 // register. Alternatively, allow copies to appear in any order
798 // Emit code to store memory values into the required frame slot. 1177 // in the frame and lazily move the value down to the slot.
1178 FrameElement new_top = CopyElementAt(index);
1179 new_top.set_sync();
1180 elements_[top_index] = new_top;
1181
1182 // The sync state of the former top element is correct (synced).
1183 // Emit code to move the value down in the frame.
799 Result temp = cgen_->allocator()->Allocate(); 1184 Result temp = cgen_->allocator()->Allocate();
800 ASSERT(temp.is_valid()); 1185 ASSERT(temp.is_valid());
801 __ mov(temp.reg(), Top()); 1186 __ mov(temp.reg(), Top());
802 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); 1187 __ mov(Operand(ebp, fp_relative(index)), temp.reg());
1188 } else if (top.is_register()) {
1189 // The stored-to slot has the (unsynced) register reference and
1190 // the top element becomes a copy. The sync state of the top is
1191 // preserved.
1192 FrameElement new_top = CopyElementAt(index);
1193 if (top.is_synced()) {
1194 new_top.set_sync();
1195 elements_[index].clear_sync();
1196 }
1197 elements_[top_index] = new_top;
803 } else { 1198 } else {
804 // We have not actually written the value to memory. 1199 // The stored-to slot holds the same value as the top but
1200 // unsynced. (We do not have copies of constants yet.)
1201 ASSERT(top.is_constant());
805 elements_[index].clear_sync(); 1202 elements_[index].clear_sync();
806 1203 }
807 if (top.is_register()) { 1204 }
808 // Establish another frame-internal reference to the register. 1205
809 Use(top.reg());
810 }
811 }
812 }
813
814 1206
815 void VirtualFrame::PushTryHandler(HandlerType type) { 1207 void VirtualFrame::PushTryHandler(HandlerType type) {
816 ASSERT(cgen_->HasValidEntryRegisters()); 1208 ASSERT(cgen_->HasValidEntryRegisters());
817 // Grow the expression stack by handler size less two (the return address 1209 // Grow the expression stack by handler size less two (the return address
818 // is already pushed by a call instruction, and PushTryHandler from the 1210 // is already pushed by a call instruction, and PushTryHandler from the
819 // macro assembler will leave the top of stack in the eax register to be 1211 // macro assembler will leave the top of stack in the eax register to be
820 // pushed separately). 1212 // pushed separately).
821 Adjust(kHandlerSize - 2); 1213 Adjust(kHandlerSize - 2);
822 __ PushTryHandler(IN_JAVASCRIPT, type); 1214 __ PushTryHandler(IN_JAVASCRIPT, type);
823 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS 1215 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
824 EmitPush(eax); 1216 EmitPush(eax);
825 } 1217 }
826 1218
827 1219
828 Result VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { 1220 Result VirtualFrame::RawCallStub(CodeStub* stub, int frame_arg_count) {
829 ASSERT(cgen_->HasValidEntryRegisters()); 1221 ASSERT(cgen_->HasValidEntryRegisters());
830 PrepareForCall(frame_arg_count, frame_arg_count);
831 __ CallStub(stub); 1222 __ CallStub(stub);
832 Result result = cgen_->allocator()->Allocate(eax); 1223 Result result = cgen_->allocator()->Allocate(eax);
833 ASSERT(result.is_valid()); 1224 ASSERT(result.is_valid());
834 return result; 1225 return result;
835 } 1226 }
836 1227
837 1228
1229 Result VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) {
1230 PrepareForCall(frame_arg_count, frame_arg_count);
1231 return RawCallStub(stub, frame_arg_count);
1232 }
1233
1234
838 Result VirtualFrame::CallStub(CodeStub* stub, 1235 Result VirtualFrame::CallStub(CodeStub* stub,
839 Result* arg, 1236 Result* arg,
840 int frame_arg_count) { 1237 int frame_arg_count) {
1238 PrepareForCall(frame_arg_count, frame_arg_count);
841 arg->Unuse(); 1239 arg->Unuse();
842 return CallStub(stub, frame_arg_count); 1240 return RawCallStub(stub, frame_arg_count);
843 } 1241 }
844 1242
845 1243
846 Result VirtualFrame::CallStub(CodeStub* stub, 1244 Result VirtualFrame::CallStub(CodeStub* stub,
847 Result* arg0, 1245 Result* arg0,
848 Result* arg1, 1246 Result* arg1,
849 int frame_arg_count) { 1247 int frame_arg_count) {
1248 PrepareForCall(frame_arg_count, frame_arg_count);
850 arg0->Unuse(); 1249 arg0->Unuse();
851 arg1->Unuse(); 1250 arg1->Unuse();
852 return CallStub(stub, frame_arg_count); 1251 return RawCallStub(stub, frame_arg_count);
853 } 1252 }
854 1253
855 1254
856 Result VirtualFrame::CallRuntime(Runtime::Function* f, 1255 Result VirtualFrame::CallRuntime(Runtime::Function* f,
857 int frame_arg_count) { 1256 int frame_arg_count) {
1257 PrepareForCall(frame_arg_count, frame_arg_count);
858 ASSERT(cgen_->HasValidEntryRegisters()); 1258 ASSERT(cgen_->HasValidEntryRegisters());
859 PrepareForCall(frame_arg_count, frame_arg_count);
860 __ CallRuntime(f, frame_arg_count); 1259 __ CallRuntime(f, frame_arg_count);
861 Result result = cgen_->allocator()->Allocate(eax); 1260 Result result = cgen_->allocator()->Allocate(eax);
862 ASSERT(result.is_valid()); 1261 ASSERT(result.is_valid());
863 return result; 1262 return result;
864 } 1263 }
865 1264
866 1265
867 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, 1266 Result VirtualFrame::CallRuntime(Runtime::FunctionId id,
868 int frame_arg_count) { 1267 int frame_arg_count) {
1268 PrepareForCall(frame_arg_count, frame_arg_count);
869 ASSERT(cgen_->HasValidEntryRegisters()); 1269 ASSERT(cgen_->HasValidEntryRegisters());
870 PrepareForCall(frame_arg_count, frame_arg_count);
871 __ CallRuntime(id, frame_arg_count); 1270 __ CallRuntime(id, frame_arg_count);
872 Result result = cgen_->allocator()->Allocate(eax); 1271 Result result = cgen_->allocator()->Allocate(eax);
873 ASSERT(result.is_valid()); 1272 ASSERT(result.is_valid());
874 return result; 1273 return result;
875 } 1274 }
876 1275
877 1276
878 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, 1277 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
879 InvokeFlag flag, 1278 InvokeFlag flag,
880 int frame_arg_count) { 1279 int frame_arg_count) {
1280 PrepareForCall(frame_arg_count, frame_arg_count);
881 ASSERT(cgen_->HasValidEntryRegisters()); 1281 ASSERT(cgen_->HasValidEntryRegisters());
882 PrepareForCall(frame_arg_count, frame_arg_count);
883 __ InvokeBuiltin(id, flag); 1282 __ InvokeBuiltin(id, flag);
884 Result result = cgen_->allocator()->Allocate(eax); 1283 Result result = cgen_->allocator()->Allocate(eax);
885 ASSERT(result.is_valid()); 1284 ASSERT(result.is_valid());
886 return result; 1285 return result;
887 } 1286 }
888 1287
889 1288
890 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, 1289 Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
891 RelocInfo::Mode rmode, 1290 RelocInfo::Mode rmode) {
892 int spilled_args,
893 int dropped_args) {
894 ASSERT(cgen_->HasValidEntryRegisters()); 1291 ASSERT(cgen_->HasValidEntryRegisters());
895 PrepareForCall(spilled_args, dropped_args);
896 __ call(code, rmode); 1292 __ call(code, rmode);
897 Result result = cgen_->allocator()->Allocate(eax); 1293 Result result = cgen_->allocator()->Allocate(eax);
898 ASSERT(result.is_valid()); 1294 ASSERT(result.is_valid());
899 return result; 1295 return result;
900 } 1296 }
901 1297
902 1298
903 Result VirtualFrame::CallCodeObject(Handle<Code> code, 1299 Result VirtualFrame::CallCodeObject(Handle<Code> code,
904 RelocInfo::Mode rmode, 1300 RelocInfo::Mode rmode,
905 int dropped_args) { 1301 int dropped_args) {
906 int spilled_args = 0; 1302 int spilled_args = 0;
907 switch (code->kind()) { 1303 switch (code->kind()) {
908 case Code::CALL_IC: 1304 case Code::CALL_IC:
909 spilled_args = dropped_args + 1; 1305 spilled_args = dropped_args + 1;
910 break; 1306 break;
911 case Code::FUNCTION: 1307 case Code::FUNCTION:
912 spilled_args = dropped_args + 1; 1308 spilled_args = dropped_args + 1;
913 break; 1309 break;
914 case Code::KEYED_LOAD_IC: 1310 case Code::KEYED_LOAD_IC:
915 ASSERT(dropped_args == 0); 1311 ASSERT(dropped_args == 0);
916 spilled_args = 2; 1312 spilled_args = 2;
917 break; 1313 break;
918 default: 1314 default:
919 // The other types of code objects are called with values 1315 // The other types of code objects are called with values
920 // in specific registers, and are handled in functions with 1316 // in specific registers, and are handled in functions with
921 // a different signature. 1317 // a different signature.
922 UNREACHABLE(); 1318 UNREACHABLE();
923 break; 1319 break;
924 } 1320 }
925 return RawCallCodeObject(code, rmode, spilled_args, dropped_args); 1321 PrepareForCall(spilled_args, dropped_args);
1322 return RawCallCodeObject(code, rmode);
926 } 1323 }
927 1324
928 1325
929 Result VirtualFrame::CallCodeObject(Handle<Code> code, 1326 Result VirtualFrame::CallCodeObject(Handle<Code> code,
930 RelocInfo::Mode rmode, 1327 RelocInfo::Mode rmode,
931 Result* arg, 1328 Result* arg,
932 int dropped_args) { 1329 int dropped_args) {
933 int spilled_args = 0; 1330 int spilled_args = 0;
934 switch (code->kind()) { 1331 switch (code->kind()) {
935 case Code::CALL_IC: 1332 case Code::CALL_IC:
936 ASSERT(arg->reg().is(eax)); 1333 ASSERT(arg->reg().is(eax));
937 spilled_args = dropped_args + 1; 1334 spilled_args = dropped_args + 1;
938 break; 1335 break;
939 case Code::LOAD_IC: 1336 case Code::LOAD_IC:
940 ASSERT(arg->reg().is(ecx)); 1337 ASSERT(arg->reg().is(ecx));
941 ASSERT(dropped_args == 0); 1338 ASSERT(dropped_args == 0);
942 spilled_args = 1; 1339 spilled_args = 1;
943 break; 1340 break;
944 case Code::KEYED_STORE_IC: 1341 case Code::KEYED_STORE_IC:
945 ASSERT(arg->reg().is(eax)); 1342 ASSERT(arg->reg().is(eax));
946 ASSERT(dropped_args == 0); 1343 ASSERT(dropped_args == 0);
947 spilled_args = 2; 1344 spilled_args = 2;
948 break; 1345 break;
949 default: 1346 default:
950 // No other types of code objects are called with values 1347 // No other types of code objects are called with values
951 // in exactly one register. 1348 // in exactly one register.
952 UNREACHABLE(); 1349 UNREACHABLE();
953 break; 1350 break;
954 } 1351 }
1352 PrepareForCall(spilled_args, dropped_args);
955 arg->Unuse(); 1353 arg->Unuse();
956 return RawCallCodeObject(code, rmode, spilled_args, dropped_args); 1354 return RawCallCodeObject(code, rmode);
957 } 1355 }
958 1356
959 1357
960 Result VirtualFrame::CallCodeObject(Handle<Code> code, 1358 Result VirtualFrame::CallCodeObject(Handle<Code> code,
961 RelocInfo::Mode rmode, 1359 RelocInfo::Mode rmode,
962 Result* arg0, 1360 Result* arg0,
963 Result* arg1, 1361 Result* arg1,
964 int dropped_args) { 1362 int dropped_args) {
965 int spilled_args = 1; 1363 int spilled_args = 1;
966 switch (code->kind()) { 1364 switch (code->kind()) {
967 case Code::STORE_IC: 1365 case Code::STORE_IC:
968 ASSERT(arg0->reg().is(eax)); 1366 ASSERT(arg0->reg().is(eax));
969 ASSERT(arg1->reg().is(ecx)); 1367 ASSERT(arg1->reg().is(ecx));
970 ASSERT(dropped_args == 0); 1368 ASSERT(dropped_args == 0);
971 spilled_args = 1; 1369 spilled_args = 1;
972 break; 1370 break;
973 case Code::BUILTIN: 1371 case Code::BUILTIN:
974 ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall)); 1372 ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall));
975 ASSERT(arg0->reg().is(eax)); 1373 ASSERT(arg0->reg().is(eax));
976 ASSERT(arg1->reg().is(edi)); 1374 ASSERT(arg1->reg().is(edi));
977 spilled_args = dropped_args + 1; 1375 spilled_args = dropped_args + 1;
978 break; 1376 break;
979 default: 1377 default:
980 // No other types of code objects are called with values 1378 // No other types of code objects are called with values
981 // in exactly two registers. 1379 // in exactly two registers.
982 UNREACHABLE(); 1380 UNREACHABLE();
983 break; 1381 break;
984 } 1382 }
1383 PrepareForCall(spilled_args, dropped_args);
985 arg0->Unuse(); 1384 arg0->Unuse();
986 arg1->Unuse(); 1385 arg1->Unuse();
987 return RawCallCodeObject(code, rmode, spilled_args, dropped_args); 1386 return RawCallCodeObject(code, rmode);
988 } 1387 }
989 1388
990 1389
991 void VirtualFrame::Drop(int count) { 1390 void VirtualFrame::Drop(int count) {
992 ASSERT(height() >= count); 1391 ASSERT(height() >= count);
993 int num_virtual_elements = (elements_.length() - 1) - stack_pointer_; 1392 int num_virtual_elements = (elements_.length() - 1) - stack_pointer_;
994 1393
995 // Emit code to lower the stack pointer if necessary. 1394 // Emit code to lower the stack pointer if necessary.
996 if (num_virtual_elements < count) { 1395 if (num_virtual_elements < count) {
997 int num_dropped = count - num_virtual_elements; 1396 int num_dropped = count - num_virtual_elements;
998 stack_pointer_ -= num_dropped; 1397 stack_pointer_ -= num_dropped;
999 __ add(Operand(esp), Immediate(num_dropped * kPointerSize)); 1398 __ add(Operand(esp), Immediate(num_dropped * kPointerSize));
1000 } 1399 }
1001 1400
1002 // Discard elements from the virtual frame and free any registers. 1401 // Discard elements from the virtual frame and free any registers.
1003 for (int i = 0; i < count; i++) { 1402 for (int i = 0; i < count; i++) {
1004 FrameElement dropped = elements_.RemoveLast(); 1403 FrameElement dropped = elements_.RemoveLast();
1005 if (dropped.is_register()) { 1404 if (dropped.is_register()) {
1006 Unuse(dropped.reg()); 1405 Unuse(dropped.reg());
1007 } 1406 }
1008 } 1407 }
1009 } 1408 }
1010 1409
1011 1410
1012 Result VirtualFrame::Pop() { 1411 Result VirtualFrame::Pop() {
1013 FrameElement popped = elements_.RemoveLast(); 1412 FrameElement element = elements_.RemoveLast();
1014 bool pop_needed = (stack_pointer_ == elements_.length()); 1413 int index = elements_.length();
1414 ASSERT(element.is_valid());
1015 1415
1016 if (popped.is_constant()) { 1416 bool pop_needed = (stack_pointer_ == index);
1017 if (pop_needed) { 1417 if (pop_needed) {
1018 stack_pointer_--; 1418 stack_pointer_--;
1019 __ add(Operand(esp), Immediate(kPointerSize)); 1419 if (element.is_memory()) {
1420 Result temp = cgen_->allocator()->Allocate();
1421 ASSERT(temp.is_valid());
1422 __ pop(temp.reg());
1423 return temp;
1020 } 1424 }
1021 return Result(popped.handle(), cgen_); 1425
1022 } else if (popped.is_register()) { 1426 __ add(Operand(esp), Immediate(kPointerSize));
1023 Unuse(popped.reg()); 1427 }
1024 if (pop_needed) { 1428 ASSERT(!element.is_memory());
1025 stack_pointer_--; 1429
1026 __ add(Operand(esp), Immediate(kPointerSize)); 1430 // The top element is a register, constant, or a copy. Unuse
1027 } 1431 // registers and follow copies to their backing store.
1028 return Result(popped.reg(), cgen_); 1432 if (element.is_register()) {
1029 } else { 1433 Unuse(element.reg());
1030 ASSERT(popped.is_memory()); 1434 } else if (element.is_copy()) {
1435 ASSERT(element.index() < index);
1436 index = element.index();
1437 element = elements_[index];
1438 }
1439 ASSERT(!element.is_copy());
1440
1441 // The element is memory, a register, or a constant.
1442 if (element.is_memory()) {
1443 // Memory elements could only be the backing store of a copy.
1444 // Allocate the original to a register.
1445 ASSERT(index <= stack_pointer_);
1031 Result temp = cgen_->allocator()->Allocate(); 1446 Result temp = cgen_->allocator()->Allocate();
1032 ASSERT(temp.is_valid()); 1447 ASSERT(temp.is_valid());
1033 ASSERT(pop_needed); 1448 Use(temp.reg());
1034 stack_pointer_--; 1449 FrameElement new_element =
1035 __ pop(temp.reg()); 1450 FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
1036 return temp; 1451 elements_[index] = new_element;
1452 __ mov(temp.reg(), Operand(ebp, fp_relative(index)));
1453 return Result(temp.reg(), cgen_);
1454 } else if (element.is_register()) {
1455 return Result(element.reg(), cgen_);
1456 } else {
1457 ASSERT(element.is_constant());
1458 return Result(element.handle(), cgen_);
1037 } 1459 }
1038 } 1460 }
1039 1461
1040 1462
1041 void VirtualFrame::EmitPop(Register reg) { 1463 void VirtualFrame::EmitPop(Register reg) {
1042 ASSERT(stack_pointer_ == elements_.length() - 1); 1464 ASSERT(stack_pointer_ == elements_.length() - 1);
1043 stack_pointer_--; 1465 stack_pointer_--;
1044 elements_.RemoveLast(); 1466 elements_.RemoveLast();
1045 __ pop(reg); 1467 __ pop(reg);
1046 } 1468 }
(...skipping 25 matching lines...) Expand all
1072 1494
1073 void VirtualFrame::EmitPush(Immediate immediate) { 1495 void VirtualFrame::EmitPush(Immediate immediate) {
1074 ASSERT(stack_pointer_ == elements_.length() - 1); 1496 ASSERT(stack_pointer_ == elements_.length() - 1);
1075 elements_.Add(FrameElement::MemoryElement()); 1497 elements_.Add(FrameElement::MemoryElement());
1076 stack_pointer_++; 1498 stack_pointer_++;
1077 __ push(immediate); 1499 __ push(immediate);
1078 } 1500 }
1079 1501
1080 1502
1081 void VirtualFrame::Push(Register reg) { 1503 void VirtualFrame::Push(Register reg) {
1082 Use(reg); 1504 FrameElement new_element;
1083 elements_.Add(FrameElement::RegisterElement(reg, 1505 if (register_count(reg) == 0) {
1084 FrameElement::NOT_SYNCED)); 1506 Use(reg);
1507 new_element =
1508 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED);
1509 } else {
1510 for (int i = 0; i < elements_.length(); i++) {
1511 FrameElement element = elements_[i];
1512 if (element.is_register() && element.reg().is(reg)) {
1513 new_element = CopyElementAt(i);
1514 break;
1515 }
1516 }
1517 }
1518 elements_.Add(new_element);
1085 } 1519 }
1086 1520
1087 1521
1088 void VirtualFrame::Push(Handle<Object> value) { 1522 void VirtualFrame::Push(Handle<Object> value) {
1089 elements_.Add(FrameElement::ConstantElement(value, 1523 elements_.Add(FrameElement::ConstantElement(value,
1090 FrameElement::NOT_SYNCED)); 1524 FrameElement::NOT_SYNCED));
1091 } 1525 }
1092 1526
1093 1527
1094 void VirtualFrame::Push(Result* result) { 1528 void VirtualFrame::Push(Result* result) {
(...skipping 25 matching lines...) Expand all
1120 return false; 1554 return false;
1121 } 1555 }
1122 } 1556 }
1123 return true; 1557 return true;
1124 } 1558 }
1125 #endif 1559 #endif
1126 1560
1127 #undef __ 1561 #undef __
1128 1562
1129 } } // namespace v8::internal 1563 } } // 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