| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |