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

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

Issue 115564: Size reduction of VirtualFrame objects. Remove the code generator and... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/virtual-frame-ia32.h ('k') | src/jump-target.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 15 matching lines...) Expand all
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "codegen-inl.h" 30 #include "codegen-inl.h"
31 #include "register-allocator-inl.h" 31 #include "register-allocator-inl.h"
32 #include "scopes.h" 32 #include "scopes.h"
33 33
34 namespace v8 { namespace internal { 34 namespace v8 { namespace internal {
35 35
36 #define __ ACCESS_MASM(masm_) 36 #define __ ACCESS_MASM(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()
44 : cgen_(cgen), 44 : elements_(parameter_count() + local_count() + kPreallocatedElements),
45 masm_(cgen->masm()), 45 stack_pointer_(parameter_count() + 1) { // 0-based index of TOS.
46 elements_(cgen->scope()->num_parameters() 46 for (int i = 0; i <= stack_pointer_; i++) {
47 + cgen->scope()->num_stack_slots()
48 + kPreallocatedElements),
49 parameter_count_(cgen->scope()->num_parameters()),
50 local_count_(0),
51 stack_pointer_(parameter_count_ + 1), // 0-based index of TOS.
52 frame_pointer_(kIllegalIndex) {
53 for (int i = 0; i < parameter_count_ + 2; i++) {
54 elements_.Add(FrameElement::MemoryElement()); 47 elements_.Add(FrameElement::MemoryElement());
55 } 48 }
56 for (int i = 0; i < kNumRegisters; i++) { 49 for (int i = 0; i < kNumRegisters; i++) {
57 register_locations_[i] = kIllegalIndex; 50 register_locations_[i] = kIllegalIndex;
58 } 51 }
59 } 52 }
60 53
61 54
62 void VirtualFrame::SyncElementBelowStackPointer(int index) { 55 void VirtualFrame::SyncElementBelowStackPointer(int index) {
63 // Emit code to write elements below the stack pointer to their 56 // Emit code to write elements below the stack pointer to their
64 // (already allocated) stack address. 57 // (already allocated) stack address.
65 ASSERT(index <= stack_pointer_); 58 ASSERT(index <= stack_pointer_);
66 FrameElement element = elements_[index]; 59 FrameElement element = elements_[index];
67 ASSERT(!element.is_synced()); 60 ASSERT(!element.is_synced());
68 switch (element.type()) { 61 switch (element.type()) {
69 case FrameElement::INVALID: 62 case FrameElement::INVALID:
70 break; 63 break;
71 64
72 case FrameElement::MEMORY: 65 case FrameElement::MEMORY:
73 // This function should not be called with synced elements. 66 // This function should not be called with synced elements.
74 // (memory elements are always synced). 67 // (memory elements are always synced).
75 UNREACHABLE(); 68 UNREACHABLE();
76 break; 69 break;
77 70
78 case FrameElement::REGISTER: 71 case FrameElement::REGISTER:
79 __ mov(Operand(ebp, fp_relative(index)), element.reg()); 72 __ mov(Operand(ebp, fp_relative(index)), element.reg());
80 break; 73 break;
81 74
82 case FrameElement::CONSTANT: 75 case FrameElement::CONSTANT:
83 if (cgen_->IsUnsafeSmi(element.handle())) { 76 if (cgen()->IsUnsafeSmi(element.handle())) {
84 Result temp = cgen_->allocator()->Allocate(); 77 Result temp = cgen()->allocator()->Allocate();
85 ASSERT(temp.is_valid()); 78 ASSERT(temp.is_valid());
86 cgen_->LoadUnsafeSmi(temp.reg(), element.handle()); 79 cgen()->LoadUnsafeSmi(temp.reg(), element.handle());
87 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); 80 __ mov(Operand(ebp, fp_relative(index)), temp.reg());
88 } else { 81 } else {
89 __ Set(Operand(ebp, fp_relative(index)), 82 __ Set(Operand(ebp, fp_relative(index)),
90 Immediate(element.handle())); 83 Immediate(element.handle()));
91 } 84 }
92 break; 85 break;
93 86
94 case FrameElement::COPY: { 87 case FrameElement::COPY: {
95 int backing_index = element.index(); 88 int backing_index = element.index();
96 FrameElement backing_element = elements_[backing_index]; 89 FrameElement backing_element = elements_[backing_index];
97 if (backing_element.is_memory()) { 90 if (backing_element.is_memory()) {
98 Result temp = cgen_->allocator()->Allocate(); 91 Result temp = cgen()->allocator()->Allocate();
99 ASSERT(temp.is_valid()); 92 ASSERT(temp.is_valid());
100 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index))); 93 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index)));
101 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); 94 __ mov(Operand(ebp, fp_relative(index)), temp.reg());
102 } else { 95 } else {
103 ASSERT(backing_element.is_register()); 96 ASSERT(backing_element.is_register());
104 __ mov(Operand(ebp, fp_relative(index)), backing_element.reg()); 97 __ mov(Operand(ebp, fp_relative(index)), backing_element.reg());
105 } 98 }
106 break; 99 break;
107 } 100 }
108 } 101 }
(...skipping 16 matching lines...) Expand all
125 case FrameElement::MEMORY: 118 case FrameElement::MEMORY:
126 // No memory elements exist above the stack pointer. 119 // No memory elements exist above the stack pointer.
127 UNREACHABLE(); 120 UNREACHABLE();
128 break; 121 break;
129 122
130 case FrameElement::REGISTER: 123 case FrameElement::REGISTER:
131 __ push(element.reg()); 124 __ push(element.reg());
132 break; 125 break;
133 126
134 case FrameElement::CONSTANT: 127 case FrameElement::CONSTANT:
135 if (cgen_->IsUnsafeSmi(element.handle())) { 128 if (cgen()->IsUnsafeSmi(element.handle())) {
136 Result temp = cgen_->allocator()->Allocate(); 129 Result temp = cgen()->allocator()->Allocate();
137 ASSERT(temp.is_valid()); 130 ASSERT(temp.is_valid());
138 cgen_->LoadUnsafeSmi(temp.reg(), element.handle()); 131 cgen()->LoadUnsafeSmi(temp.reg(), element.handle());
139 __ push(temp.reg()); 132 __ push(temp.reg());
140 } else { 133 } else {
141 __ push(Immediate(element.handle())); 134 __ push(Immediate(element.handle()));
142 } 135 }
143 break; 136 break;
144 137
145 case FrameElement::COPY: { 138 case FrameElement::COPY: {
146 int backing_index = element.index(); 139 int backing_index = element.index();
147 FrameElement backing = elements_[backing_index]; 140 FrameElement backing = elements_[backing_index];
148 ASSERT(backing.is_memory() || backing.is_register()); 141 ASSERT(backing.is_memory() || backing.is_register());
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 if (element.is_constant() || element.is_copy()) { 186 if (element.is_constant() || element.is_copy()) {
194 if (element.is_synced()) { 187 if (element.is_synced()) {
195 // Just spill. 188 // Just spill.
196 elements_[i] = FrameElement::MemoryElement(); 189 elements_[i] = FrameElement::MemoryElement();
197 } else { 190 } else {
198 // Allocate to a register. 191 // Allocate to a register.
199 FrameElement backing_element; // Invalid if not a copy. 192 FrameElement backing_element; // Invalid if not a copy.
200 if (element.is_copy()) { 193 if (element.is_copy()) {
201 backing_element = elements_[element.index()]; 194 backing_element = elements_[element.index()];
202 } 195 }
203 Result fresh = cgen_->allocator()->Allocate(); 196 Result fresh = cgen()->allocator()->Allocate();
204 ASSERT(fresh.is_valid()); 197 ASSERT(fresh.is_valid());
205 elements_[i] = 198 elements_[i] =
206 FrameElement::RegisterElement(fresh.reg(), 199 FrameElement::RegisterElement(fresh.reg(),
207 FrameElement::NOT_SYNCED); 200 FrameElement::NOT_SYNCED);
208 Use(fresh.reg(), i); 201 Use(fresh.reg(), i);
209 202
210 // Emit a move. 203 // Emit a move.
211 if (element.is_constant()) { 204 if (element.is_constant()) {
212 if (cgen_->IsUnsafeSmi(element.handle())) { 205 if (cgen()->IsUnsafeSmi(element.handle())) {
213 cgen_->LoadUnsafeSmi(fresh.reg(), element.handle()); 206 cgen()->LoadUnsafeSmi(fresh.reg(), element.handle());
214 } else { 207 } else {
215 __ Set(fresh.reg(), Immediate(element.handle())); 208 __ Set(fresh.reg(), Immediate(element.handle()));
216 } 209 }
217 } else { 210 } else {
218 ASSERT(element.is_copy()); 211 ASSERT(element.is_copy());
219 // Copies are only backed by register or memory locations. 212 // Copies are only backed by register or memory locations.
220 if (backing_element.is_register()) { 213 if (backing_element.is_register()) {
221 // The backing store may have been spilled by allocating, 214 // The backing store may have been spilled by allocating,
222 // but that's OK. If it was, the value is right where we 215 // but that's OK. If it was, the value is right where we
223 // want it. 216 // want it.
(...skipping 14 matching lines...) Expand all
238 // the high water mark. They cannot be copied because copes are 231 // the high water mark. They cannot be copied because copes are
239 // always higher than their backing store and copies are not 232 // always higher than their backing store and copies are not
240 // allowed above the water mark. 233 // allowed above the water mark.
241 elements_[i].clear_copied(); 234 elements_[i].clear_copied();
242 } 235 }
243 } 236 }
244 } 237 }
245 238
246 239
247 void VirtualFrame::MergeTo(VirtualFrame* expected) { 240 void VirtualFrame::MergeTo(VirtualFrame* expected) {
248 Comment cmnt(masm_, "[ Merge frame"); 241 Comment cmnt(masm(), "[ Merge frame");
249 // We should always be merging the code generator's current frame to an 242 // We should always be merging the code generator's current frame to an
250 // expected frame. 243 // expected frame.
251 ASSERT(cgen_->frame() == this); 244 ASSERT(cgen()->frame() == this);
252 245
253 // Adjust the stack pointer upward (toward the top of the virtual 246 // Adjust the stack pointer upward (toward the top of the virtual
254 // frame) if necessary. 247 // frame) if necessary.
255 if (stack_pointer_ < expected->stack_pointer_) { 248 if (stack_pointer_ < expected->stack_pointer_) {
256 int difference = expected->stack_pointer_ - stack_pointer_; 249 int difference = expected->stack_pointer_ - stack_pointer_;
257 stack_pointer_ = expected->stack_pointer_; 250 stack_pointer_ = expected->stack_pointer_;
258 __ sub(Operand(esp), Immediate(difference * kPointerSize)); 251 __ sub(Operand(esp), Immediate(difference * kPointerSize));
259 } 252 }
260 253
261 MergeMoveRegistersToMemory(expected); 254 MergeMoveRegistersToMemory(expected);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 297
305 case FrameElement::REGISTER: 298 case FrameElement::REGISTER:
306 Unuse(source.reg()); 299 Unuse(source.reg());
307 if (!source.is_synced()) { 300 if (!source.is_synced()) {
308 __ mov(Operand(ebp, fp_relative(i)), source.reg()); 301 __ mov(Operand(ebp, fp_relative(i)), source.reg());
309 } 302 }
310 break; 303 break;
311 304
312 case FrameElement::CONSTANT: 305 case FrameElement::CONSTANT:
313 if (!source.is_synced()) { 306 if (!source.is_synced()) {
314 if (cgen_->IsUnsafeSmi(source.handle())) { 307 if (cgen()->IsUnsafeSmi(source.handle())) {
315 esi_caches = i; 308 esi_caches = i;
316 cgen_->LoadUnsafeSmi(esi, source.handle()); 309 cgen()->LoadUnsafeSmi(esi, source.handle());
317 __ mov(Operand(ebp, fp_relative(i)), esi); 310 __ mov(Operand(ebp, fp_relative(i)), esi);
318 } else { 311 } else {
319 __ Set(Operand(ebp, fp_relative(i)), Immediate(source.handle())); 312 __ Set(Operand(ebp, fp_relative(i)), Immediate(source.handle()));
320 } 313 }
321 } 314 }
322 break; 315 break;
323 316
324 case FrameElement::COPY: 317 case FrameElement::COPY:
325 if (!source.is_synced()) { 318 if (!source.is_synced()) {
326 int backing_index = source.index(); 319 int backing_index = source.index();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 case FrameElement::REGISTER: 403 case FrameElement::REGISTER:
411 ASSERT(source.reg().is(target_reg)); 404 ASSERT(source.reg().is(target_reg));
412 continue; // Go to next iteration. Skips Use(target_reg) below. 405 continue; // Go to next iteration. Skips Use(target_reg) below.
413 break; 406 break;
414 case FrameElement::MEMORY: 407 case FrameElement::MEMORY:
415 ASSERT(index <= stack_pointer_); 408 ASSERT(index <= stack_pointer_);
416 __ mov(target_reg, Operand(ebp, fp_relative(index))); 409 __ mov(target_reg, Operand(ebp, fp_relative(index)));
417 break; 410 break;
418 411
419 case FrameElement::CONSTANT: 412 case FrameElement::CONSTANT:
420 if (cgen_->IsUnsafeSmi(source.handle())) { 413 if (cgen()->IsUnsafeSmi(source.handle())) {
421 cgen_->LoadUnsafeSmi(target_reg, source.handle()); 414 cgen()->LoadUnsafeSmi(target_reg, source.handle());
422 } else { 415 } else {
423 __ Set(target_reg, Immediate(source.handle())); 416 __ Set(target_reg, Immediate(source.handle()));
424 } 417 }
425 break; 418 break;
426 419
427 case FrameElement::COPY: { 420 case FrameElement::COPY: {
428 int backing_index = source.index(); 421 int backing_index = source.index();
429 FrameElement backing = elements_[backing_index]; 422 FrameElement backing = elements_[backing_index];
430 ASSERT(backing.is_memory() || backing.is_register()); 423 ASSERT(backing.is_memory() || backing.is_register());
431 if (backing.is_memory()) { 424 if (backing.is_memory()) {
(...skipping 24 matching lines...) Expand all
456 } 449 }
457 Use(target_reg, index); 450 Use(target_reg, index);
458 elements_[index] = target; 451 elements_[index] = target;
459 } 452 }
460 } 453 }
461 } 454 }
462 455
463 456
464 void VirtualFrame::Enter() { 457 void VirtualFrame::Enter() {
465 // Registers live on entry: esp, ebp, esi, edi. 458 // Registers live on entry: esp, ebp, esi, edi.
466 Comment cmnt(masm_, "[ Enter JS frame"); 459 Comment cmnt(masm(), "[ Enter JS frame");
467 460
468 #ifdef DEBUG 461 #ifdef DEBUG
469 // Verify that edi contains a JS function. The following code 462 // Verify that edi contains a JS function. The following code
470 // relies on eax being available for use. 463 // relies on eax being available for use.
471 __ test(edi, Immediate(kSmiTagMask)); 464 __ test(edi, Immediate(kSmiTagMask));
472 __ Check(not_zero, 465 __ Check(not_zero,
473 "VirtualFrame::Enter - edi is not a function (smi check)."); 466 "VirtualFrame::Enter - edi is not a function (smi check).");
474 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 467 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
475 __ Check(equal, 468 __ Check(equal,
476 "VirtualFrame::Enter - edi is not a function (map check)."); 469 "VirtualFrame::Enter - edi is not a function (map check).");
477 #endif 470 #endif
478 471
479 EmitPush(ebp); 472 EmitPush(ebp);
480 473
481 frame_pointer_ = stack_pointer_;
482 __ mov(ebp, Operand(esp)); 474 __ mov(ebp, Operand(esp));
483 475
484 // Store the context in the frame. The context is kept in esi and a 476 // Store the context in the frame. The context is kept in esi and a
485 // copy is stored in the frame. The external reference to esi 477 // copy is stored in the frame. The external reference to esi
486 // remains. 478 // remains.
487 EmitPush(esi); 479 EmitPush(esi);
488 480
489 // Store the function in the frame. The frame owns the register 481 // Store the function in the frame. The frame owns the register
490 // reference now (ie, it can keep it in edi or spill it later). 482 // reference now (ie, it can keep it in edi or spill it later).
491 Push(edi); 483 Push(edi);
492 SyncElementAt(elements_.length() - 1); 484 SyncElementAt(elements_.length() - 1);
493 cgen_->allocator()->Unuse(edi); 485 cgen()->allocator()->Unuse(edi);
494 } 486 }
495 487
496 488
497 void VirtualFrame::Exit() { 489 void VirtualFrame::Exit() {
498 Comment cmnt(masm_, "[ Exit JS frame"); 490 Comment cmnt(masm(), "[ Exit JS frame");
499 // Record the location of the JS exit code for patching when setting 491 // Record the location of the JS exit code for patching when setting
500 // break point. 492 // break point.
501 __ RecordJSReturn(); 493 __ RecordJSReturn();
502 494
503 // Avoid using the leave instruction here, because it is too 495 // Avoid using the leave instruction here, because it is too
504 // short. We need the return sequence to be a least the size of a 496 // short. We need the return sequence to be a least the size of a
505 // call instruction to support patching the exit code in the 497 // call instruction to support patching the exit code in the
506 // debugger. See VisitReturnStatement for the full return sequence. 498 // debugger. See VisitReturnStatement for the full return sequence.
507 __ mov(esp, Operand(ebp)); 499 __ mov(esp, Operand(ebp));
508 stack_pointer_ = frame_pointer_; 500 stack_pointer_ = frame_pointer();
509 for (int i = elements_.length() - 1; i > stack_pointer_; i--) { 501 for (int i = elements_.length() - 1; i > stack_pointer_; i--) {
510 FrameElement last = elements_.RemoveLast(); 502 FrameElement last = elements_.RemoveLast();
511 if (last.is_register()) { 503 if (last.is_register()) {
512 Unuse(last.reg()); 504 Unuse(last.reg());
513 } 505 }
514 } 506 }
515 507
516 frame_pointer_ = kIllegalIndex;
517 EmitPop(ebp); 508 EmitPop(ebp);
518 } 509 }
519 510
520 511
521 void VirtualFrame::AllocateStackSlots(int count) { 512 void VirtualFrame::AllocateStackSlots() {
522 ASSERT(height() == 0); 513 ASSERT(height() == 0);
523 local_count_ = count;
524 514
515 int count = local_count();
525 if (count > 0) { 516 if (count > 0) {
526 Comment cmnt(masm_, "[ Allocate space for locals"); 517 Comment cmnt(masm(), "[ Allocate space for locals");
527 // The locals are initialized to a constant (the undefined value), but 518 // The locals are initialized to a constant (the undefined value), but
528 // we sync them with the actual frame to allocate space for spilling 519 // we sync them with the actual frame to allocate space for spilling
529 // them later. First sync everything above the stack pointer so we can 520 // them later. First sync everything above the stack pointer so we can
530 // use pushes to allocate and initialize the locals. 521 // use pushes to allocate and initialize the locals.
531 SyncRange(stack_pointer_ + 1, elements_.length() - 1); 522 SyncRange(stack_pointer_ + 1, elements_.length() - 1);
532 Handle<Object> undefined = Factory::undefined_value(); 523 Handle<Object> undefined = Factory::undefined_value();
533 FrameElement initial_value = 524 FrameElement initial_value =
534 FrameElement::ConstantElement(undefined, FrameElement::SYNCED); 525 FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
535 Result temp = cgen_->allocator()->Allocate(); 526 Result temp = cgen()->allocator()->Allocate();
536 ASSERT(temp.is_valid()); 527 ASSERT(temp.is_valid());
537 __ Set(temp.reg(), Immediate(undefined)); 528 __ Set(temp.reg(), Immediate(undefined));
538 for (int i = 0; i < count; i++) { 529 for (int i = 0; i < count; i++) {
539 elements_.Add(initial_value); 530 elements_.Add(initial_value);
540 stack_pointer_++; 531 stack_pointer_++;
541 __ push(temp.reg()); 532 __ push(temp.reg());
542 } 533 }
543 } 534 }
544 } 535 }
545 536
546 537
547 void VirtualFrame::SaveContextRegister() { 538 void VirtualFrame::SaveContextRegister() {
548 ASSERT(elements_[context_index()].is_memory()); 539 ASSERT(elements_[context_index()].is_memory());
549 __ mov(Operand(ebp, fp_relative(context_index())), esi); 540 __ mov(Operand(ebp, fp_relative(context_index())), esi);
550 } 541 }
551 542
552 543
553 void VirtualFrame::RestoreContextRegister() { 544 void VirtualFrame::RestoreContextRegister() {
554 ASSERT(elements_[context_index()].is_memory()); 545 ASSERT(elements_[context_index()].is_memory());
555 __ mov(esi, Operand(ebp, fp_relative(context_index()))); 546 __ mov(esi, Operand(ebp, fp_relative(context_index())));
556 } 547 }
557 548
558 549
559 void VirtualFrame::PushReceiverSlotAddress() { 550 void VirtualFrame::PushReceiverSlotAddress() {
560 Result temp = cgen_->allocator()->Allocate(); 551 Result temp = cgen()->allocator()->Allocate();
561 ASSERT(temp.is_valid()); 552 ASSERT(temp.is_valid());
562 __ lea(temp.reg(), ParameterAt(-1)); 553 __ lea(temp.reg(), ParameterAt(-1));
563 Push(&temp); 554 Push(&temp);
564 } 555 }
565 556
566 557
567 int VirtualFrame::InvalidateFrameSlotAt(int index) { 558 int VirtualFrame::InvalidateFrameSlotAt(int index) {
568 FrameElement original = elements_[index]; 559 FrameElement original = elements_[index];
569 560
570 // Is this element the backing store of any copies? 561 // Is this element the backing store of any copies?
(...skipping 13 matching lines...) Expand all
584 if (original.is_register()) { 575 if (original.is_register()) {
585 Unuse(original.reg()); 576 Unuse(original.reg());
586 } 577 }
587 elements_[index] = FrameElement::InvalidElement(); 578 elements_[index] = FrameElement::InvalidElement();
588 return kIllegalIndex; 579 return kIllegalIndex;
589 } 580 }
590 581
591 // This is the backing store of copies. 582 // This is the backing store of copies.
592 Register backing_reg; 583 Register backing_reg;
593 if (original.is_memory()) { 584 if (original.is_memory()) {
594 Result fresh = cgen_->allocator()->Allocate(); 585 Result fresh = cgen()->allocator()->Allocate();
595 ASSERT(fresh.is_valid()); 586 ASSERT(fresh.is_valid());
596 Use(fresh.reg(), new_backing_index); 587 Use(fresh.reg(), new_backing_index);
597 backing_reg = fresh.reg(); 588 backing_reg = fresh.reg();
598 __ mov(backing_reg, Operand(ebp, fp_relative(index))); 589 __ mov(backing_reg, Operand(ebp, fp_relative(index)));
599 } else { 590 } else {
600 // The original was in a register. 591 // The original was in a register.
601 backing_reg = original.reg(); 592 backing_reg = original.reg();
602 register_locations_[backing_reg.code()] = new_backing_index; 593 register_locations_[backing_reg.code()] = new_backing_index;
603 } 594 }
604 // Invalidate the element at index. 595 // Invalidate the element at index.
(...skipping 24 matching lines...) Expand all
629 int new_backing_store_index = InvalidateFrameSlotAt(index); 620 int new_backing_store_index = InvalidateFrameSlotAt(index);
630 if (new_backing_store_index != kIllegalIndex) { 621 if (new_backing_store_index != kIllegalIndex) {
631 elements_.Add(CopyElementAt(new_backing_store_index)); 622 elements_.Add(CopyElementAt(new_backing_store_index));
632 return; 623 return;
633 } 624 }
634 625
635 switch (original.type()) { 626 switch (original.type()) {
636 case FrameElement::MEMORY: { 627 case FrameElement::MEMORY: {
637 // Emit code to load the original element's data into a register. 628 // Emit code to load the original element's data into a register.
638 // Push that register as a FrameElement on top of the frame. 629 // Push that register as a FrameElement on top of the frame.
639 Result fresh = cgen_->allocator()->Allocate(); 630 Result fresh = cgen()->allocator()->Allocate();
640 ASSERT(fresh.is_valid()); 631 ASSERT(fresh.is_valid());
641 FrameElement new_element = 632 FrameElement new_element =
642 FrameElement::RegisterElement(fresh.reg(), 633 FrameElement::RegisterElement(fresh.reg(),
643 FrameElement::NOT_SYNCED); 634 FrameElement::NOT_SYNCED);
644 Use(fresh.reg(), elements_.length()); 635 Use(fresh.reg(), elements_.length());
645 elements_.Add(new_element); 636 elements_.Add(new_element);
646 __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); 637 __ mov(fresh.reg(), Operand(ebp, fp_relative(index)));
647 break; 638 break;
648 } 639 }
649 case FrameElement::REGISTER: 640 case FrameElement::REGISTER:
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 if (backing_element.is_memory()) { 694 if (backing_element.is_memory()) {
704 // Because sets of copies are canonicalized to be backed by 695 // Because sets of copies are canonicalized to be backed by
705 // their lowest frame element, and because memory frame 696 // their lowest frame element, and because memory frame
706 // elements are backed by the corresponding stack address, we 697 // elements are backed by the corresponding stack address, we
707 // have to move the actual value down in the stack. 698 // have to move the actual value down in the stack.
708 // 699 //
709 // TODO(209): considering allocating the stored-to slot to the 700 // TODO(209): considering allocating the stored-to slot to the
710 // temp register. Alternatively, allow copies to appear in 701 // temp register. Alternatively, allow copies to appear in
711 // any order in the frame and lazily move the value down to 702 // any order in the frame and lazily move the value down to
712 // the slot. 703 // the slot.
713 Result temp = cgen_->allocator()->Allocate(); 704 Result temp = cgen()->allocator()->Allocate();
714 ASSERT(temp.is_valid()); 705 ASSERT(temp.is_valid());
715 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index))); 706 __ mov(temp.reg(), Operand(ebp, fp_relative(backing_index)));
716 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); 707 __ mov(Operand(ebp, fp_relative(index)), temp.reg());
717 } else { 708 } else {
718 register_locations_[backing_element.reg().code()] = index; 709 register_locations_[backing_element.reg().code()] = index;
719 if (backing_element.is_synced()) { 710 if (backing_element.is_synced()) {
720 // If the element is a register, we will not actually move 711 // If the element is a register, we will not actually move
721 // anything on the stack but only update the virtual frame 712 // anything on the stack but only update the virtual frame
722 // element. 713 // element.
723 backing_element.clear_sync(); 714 backing_element.clear_sync();
(...skipping 26 matching lines...) Expand all
750 if (top.is_memory()) { 741 if (top.is_memory()) {
751 // TODO(209): consider allocating the stored-to slot to the temp 742 // TODO(209): consider allocating the stored-to slot to the temp
752 // register. Alternatively, allow copies to appear in any order 743 // register. Alternatively, allow copies to appear in any order
753 // in the frame and lazily move the value down to the slot. 744 // in the frame and lazily move the value down to the slot.
754 FrameElement new_top = CopyElementAt(index); 745 FrameElement new_top = CopyElementAt(index);
755 new_top.set_sync(); 746 new_top.set_sync();
756 elements_[top_index] = new_top; 747 elements_[top_index] = new_top;
757 748
758 // The sync state of the former top element is correct (synced). 749 // The sync state of the former top element is correct (synced).
759 // Emit code to move the value down in the frame. 750 // Emit code to move the value down in the frame.
760 Result temp = cgen_->allocator()->Allocate(); 751 Result temp = cgen()->allocator()->Allocate();
761 ASSERT(temp.is_valid()); 752 ASSERT(temp.is_valid());
762 __ mov(temp.reg(), Operand(esp, 0)); 753 __ mov(temp.reg(), Operand(esp, 0));
763 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); 754 __ mov(Operand(ebp, fp_relative(index)), temp.reg());
764 } else if (top.is_register()) { 755 } else if (top.is_register()) {
765 register_locations_[top.reg().code()] = index; 756 register_locations_[top.reg().code()] = index;
766 // The stored-to slot has the (unsynced) register reference and 757 // The stored-to slot has the (unsynced) register reference and
767 // the top element becomes a copy. The sync state of the top is 758 // the top element becomes a copy. The sync state of the top is
768 // preserved. 759 // preserved.
769 FrameElement new_top = CopyElementAt(index); 760 FrameElement new_top = CopyElementAt(index);
770 if (top.is_synced()) { 761 if (top.is_synced()) {
771 new_top.set_sync(); 762 new_top.set_sync();
772 elements_[index].clear_sync(); 763 elements_[index].clear_sync();
773 } 764 }
774 elements_[top_index] = new_top; 765 elements_[top_index] = new_top;
775 } else { 766 } else {
776 // The stored-to slot holds the same value as the top but 767 // The stored-to slot holds the same value as the top but
777 // unsynced. (We do not have copies of constants yet.) 768 // unsynced. (We do not have copies of constants yet.)
778 ASSERT(top.is_constant()); 769 ASSERT(top.is_constant());
779 elements_[index].clear_sync(); 770 elements_[index].clear_sync();
780 } 771 }
781 } 772 }
782 773
783 774
784 void VirtualFrame::PushTryHandler(HandlerType type) { 775 void VirtualFrame::PushTryHandler(HandlerType type) {
785 ASSERT(cgen_->HasValidEntryRegisters()); 776 ASSERT(cgen()->HasValidEntryRegisters());
786 // Grow the expression stack by handler size less two (the return address 777 // Grow the expression stack by handler size less two (the return address
787 // is already pushed by a call instruction, and PushTryHandler from the 778 // is already pushed by a call instruction, and PushTryHandler from the
788 // macro assembler will leave the top of stack in the eax register to be 779 // macro assembler will leave the top of stack in the eax register to be
789 // pushed separately). 780 // pushed separately).
790 Adjust(kHandlerSize - 2); 781 Adjust(kHandlerSize - 2);
791 __ PushTryHandler(IN_JAVASCRIPT, type); 782 __ PushTryHandler(IN_JAVASCRIPT, type);
792 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS 783 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
793 EmitPush(eax); 784 EmitPush(eax);
794 } 785 }
795 786
796 787
797 Result VirtualFrame::RawCallStub(CodeStub* stub) { 788 Result VirtualFrame::RawCallStub(CodeStub* stub) {
798 ASSERT(cgen_->HasValidEntryRegisters()); 789 ASSERT(cgen()->HasValidEntryRegisters());
799 __ CallStub(stub); 790 __ CallStub(stub);
800 Result result = cgen_->allocator()->Allocate(eax); 791 Result result = cgen()->allocator()->Allocate(eax);
801 ASSERT(result.is_valid()); 792 ASSERT(result.is_valid());
802 return result; 793 return result;
803 } 794 }
804 795
805 796
806 Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) { 797 Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) {
807 PrepareForCall(0, 0); 798 PrepareForCall(0, 0);
808 arg->ToRegister(eax); 799 arg->ToRegister(eax);
809 arg->Unuse(); 800 arg->Unuse();
810 return RawCallStub(stub); 801 return RawCallStub(stub);
(...skipping 20 matching lines...) Expand all
831 } 822 }
832 823
833 arg0->Unuse(); 824 arg0->Unuse();
834 arg1->Unuse(); 825 arg1->Unuse();
835 return RawCallStub(stub); 826 return RawCallStub(stub);
836 } 827 }
837 828
838 829
839 Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { 830 Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
840 PrepareForCall(arg_count, arg_count); 831 PrepareForCall(arg_count, arg_count);
841 ASSERT(cgen_->HasValidEntryRegisters()); 832 ASSERT(cgen()->HasValidEntryRegisters());
842 __ CallRuntime(f, arg_count); 833 __ CallRuntime(f, arg_count);
843 Result result = cgen_->allocator()->Allocate(eax); 834 Result result = cgen()->allocator()->Allocate(eax);
844 ASSERT(result.is_valid()); 835 ASSERT(result.is_valid());
845 return result; 836 return result;
846 } 837 }
847 838
848 839
849 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) { 840 Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
850 PrepareForCall(arg_count, arg_count); 841 PrepareForCall(arg_count, arg_count);
851 ASSERT(cgen_->HasValidEntryRegisters()); 842 ASSERT(cgen()->HasValidEntryRegisters());
852 __ CallRuntime(id, arg_count); 843 __ CallRuntime(id, arg_count);
853 Result result = cgen_->allocator()->Allocate(eax); 844 Result result = cgen()->allocator()->Allocate(eax);
854 ASSERT(result.is_valid()); 845 ASSERT(result.is_valid());
855 return result; 846 return result;
856 } 847 }
857 848
858 849
859 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, 850 Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
860 InvokeFlag flag, 851 InvokeFlag flag,
861 int arg_count) { 852 int arg_count) {
862 PrepareForCall(arg_count, arg_count); 853 PrepareForCall(arg_count, arg_count);
863 ASSERT(cgen_->HasValidEntryRegisters()); 854 ASSERT(cgen()->HasValidEntryRegisters());
864 __ InvokeBuiltin(id, flag); 855 __ InvokeBuiltin(id, flag);
865 Result result = cgen_->allocator()->Allocate(eax); 856 Result result = cgen()->allocator()->Allocate(eax);
866 ASSERT(result.is_valid()); 857 ASSERT(result.is_valid());
867 return result; 858 return result;
868 } 859 }
869 860
870 861
871 Result VirtualFrame::RawCallCodeObject(Handle<Code> code, 862 Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
872 RelocInfo::Mode rmode) { 863 RelocInfo::Mode rmode) {
873 ASSERT(cgen_->HasValidEntryRegisters()); 864 ASSERT(cgen()->HasValidEntryRegisters());
874 __ call(code, rmode); 865 __ call(code, rmode);
875 Result result = cgen_->allocator()->Allocate(eax); 866 Result result = cgen()->allocator()->Allocate(eax);
876 ASSERT(result.is_valid()); 867 ASSERT(result.is_valid());
877 return result; 868 return result;
878 } 869 }
879 870
880 871
881 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { 872 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
882 // Name and receiver are on the top of the frame. The IC expects 873 // Name and receiver are on the top of the frame. The IC expects
883 // name in ecx and receiver on the stack. It does not drop the 874 // name in ecx and receiver on the stack. It does not drop the
884 // receiver. 875 // receiver.
885 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 876 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 } 936 }
946 937
947 938
948 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, 939 Result VirtualFrame::CallCallIC(RelocInfo::Mode mode,
949 int arg_count, 940 int arg_count,
950 int loop_nesting) { 941 int loop_nesting) {
951 // Arguments, receiver, and function name are on top of the frame. 942 // Arguments, receiver, and function name are on top of the frame.
952 // The IC expects them on the stack. It does not drop the function 943 // The IC expects them on the stack. It does not drop the function
953 // name slot (but it does drop the rest). 944 // name slot (but it does drop the rest).
954 Handle<Code> ic = (loop_nesting > 0) 945 Handle<Code> ic = (loop_nesting > 0)
955 ? cgen_->ComputeCallInitializeInLoop(arg_count) 946 ? cgen()->ComputeCallInitializeInLoop(arg_count)
956 : cgen_->ComputeCallInitialize(arg_count); 947 : cgen()->ComputeCallInitialize(arg_count);
957 // Spill args, receiver, and function. The call will drop args and 948 // Spill args, receiver, and function. The call will drop args and
958 // receiver. 949 // receiver.
959 PrepareForCall(arg_count + 2, arg_count + 1); 950 PrepareForCall(arg_count + 2, arg_count + 1);
960 return RawCallCodeObject(ic, mode); 951 return RawCallCodeObject(ic, mode);
961 } 952 }
962 953
963 954
964 Result VirtualFrame::CallConstructor(int arg_count) { 955 Result VirtualFrame::CallConstructor(int arg_count) {
965 // Arguments, receiver, and function are on top of the frame. The 956 // Arguments, receiver, and function are on top of the frame. The
966 // IC expects arg count in eax, function in edi, and the arguments 957 // IC expects arg count in eax, function in edi, and the arguments
967 // and receiver on the stack. 958 // and receiver on the stack.
968 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 959 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
969 // Duplicate the function before preparing the frame. 960 // Duplicate the function before preparing the frame.
970 PushElementAt(arg_count + 1); 961 PushElementAt(arg_count + 1);
971 Result function = Pop(); 962 Result function = Pop();
972 PrepareForCall(arg_count + 1, arg_count + 1); // Spill args and receiver. 963 PrepareForCall(arg_count + 1, arg_count + 1); // Spill args and receiver.
973 function.ToRegister(edi); 964 function.ToRegister(edi);
974 965
975 // Constructors are called with the number of arguments in register 966 // Constructors are called with the number of arguments in register
976 // eax for now. Another option would be to have separate construct 967 // eax for now. Another option would be to have separate construct
977 // call trampolines per different arguments counts encountered. 968 // call trampolines per different arguments counts encountered.
978 Result num_args = cgen_->allocator()->Allocate(eax); 969 Result num_args = cgen()->allocator()->Allocate(eax);
979 ASSERT(num_args.is_valid()); 970 ASSERT(num_args.is_valid());
980 __ Set(num_args.reg(), Immediate(arg_count)); 971 __ Set(num_args.reg(), Immediate(arg_count));
981 972
982 function.Unuse(); 973 function.Unuse();
983 num_args.Unuse(); 974 num_args.Unuse();
984 return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL); 975 return RawCallCodeObject(ic, RelocInfo::CONSTRUCT_CALL);
985 } 976 }
986 977
987 978
988 void VirtualFrame::Drop(int count) { 979 void VirtualFrame::Drop(int count) {
(...skipping 19 matching lines...) Expand all
1008 999
1009 Result VirtualFrame::Pop() { 1000 Result VirtualFrame::Pop() {
1010 FrameElement element = elements_.RemoveLast(); 1001 FrameElement element = elements_.RemoveLast();
1011 int index = elements_.length(); 1002 int index = elements_.length();
1012 ASSERT(element.is_valid()); 1003 ASSERT(element.is_valid());
1013 1004
1014 bool pop_needed = (stack_pointer_ == index); 1005 bool pop_needed = (stack_pointer_ == index);
1015 if (pop_needed) { 1006 if (pop_needed) {
1016 stack_pointer_--; 1007 stack_pointer_--;
1017 if (element.is_memory()) { 1008 if (element.is_memory()) {
1018 Result temp = cgen_->allocator()->Allocate(); 1009 Result temp = cgen()->allocator()->Allocate();
1019 ASSERT(temp.is_valid()); 1010 ASSERT(temp.is_valid());
1020 temp.set_static_type(element.static_type()); 1011 temp.set_static_type(element.static_type());
1021 __ pop(temp.reg()); 1012 __ pop(temp.reg());
1022 return temp; 1013 return temp;
1023 } 1014 }
1024 1015
1025 __ add(Operand(esp), Immediate(kPointerSize)); 1016 __ add(Operand(esp), Immediate(kPointerSize));
1026 } 1017 }
1027 ASSERT(!element.is_memory()); 1018 ASSERT(!element.is_memory());
1028 1019
1029 // The top element is a register, constant, or a copy. Unuse 1020 // The top element is a register, constant, or a copy. Unuse
1030 // registers and follow copies to their backing store. 1021 // registers and follow copies to their backing store.
1031 if (element.is_register()) { 1022 if (element.is_register()) {
1032 Unuse(element.reg()); 1023 Unuse(element.reg());
1033 } else if (element.is_copy()) { 1024 } else if (element.is_copy()) {
1034 ASSERT(element.index() < index); 1025 ASSERT(element.index() < index);
1035 index = element.index(); 1026 index = element.index();
1036 element = elements_[index]; 1027 element = elements_[index];
1037 } 1028 }
1038 ASSERT(!element.is_copy()); 1029 ASSERT(!element.is_copy());
1039 1030
1040 // The element is memory, a register, or a constant. 1031 // The element is memory, a register, or a constant.
1041 if (element.is_memory()) { 1032 if (element.is_memory()) {
1042 // Memory elements could only be the backing store of a copy. 1033 // Memory elements could only be the backing store of a copy.
1043 // Allocate the original to a register. 1034 // Allocate the original to a register.
1044 ASSERT(index <= stack_pointer_); 1035 ASSERT(index <= stack_pointer_);
1045 Result temp = cgen_->allocator()->Allocate(); 1036 Result temp = cgen()->allocator()->Allocate();
1046 ASSERT(temp.is_valid()); 1037 ASSERT(temp.is_valid());
1047 Use(temp.reg(), index); 1038 Use(temp.reg(), index);
1048 FrameElement new_element = 1039 FrameElement new_element =
1049 FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED); 1040 FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
1050 // Preserve the copy flag on the element. 1041 // Preserve the copy flag on the element.
1051 if (element.is_copied()) new_element.set_copied(); 1042 if (element.is_copied()) new_element.set_copied();
1052 new_element.set_static_type(element.static_type()); 1043 new_element.set_static_type(element.static_type());
1053 elements_[index] = new_element; 1044 elements_[index] = new_element;
1054 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); 1045 __ mov(temp.reg(), Operand(ebp, fp_relative(index)));
1055 return Result(temp.reg(), element.static_type()); 1046 return Result(temp.reg(), element.static_type());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1098 ASSERT(stack_pointer_ == elements_.length() - 1); 1089 ASSERT(stack_pointer_ == elements_.length() - 1);
1099 elements_.Add(FrameElement::MemoryElement()); 1090 elements_.Add(FrameElement::MemoryElement());
1100 stack_pointer_++; 1091 stack_pointer_++;
1101 __ push(immediate); 1092 __ push(immediate);
1102 } 1093 }
1103 1094
1104 1095
1105 #undef __ 1096 #undef __
1106 1097
1107 } } // namespace v8::internal 1098 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/virtual-frame-ia32.h ('k') | src/jump-target.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698