| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 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 #include "virtual-frame-inl.h" |
| 33 | 34 |
| 34 namespace v8 { | 35 namespace v8 { |
| 35 namespace internal { | 36 namespace internal { |
| 36 | 37 |
| 37 #define __ ACCESS_MASM(masm()) | 38 #define __ ACCESS_MASM(masm()) |
| 38 | 39 |
| 39 // ------------------------------------------------------------------------- | |
| 40 // VirtualFrame implementation. | |
| 41 | |
| 42 // On entry to a function, the virtual frame already contains the receiver, | |
| 43 // the parameters, and a return address. All frame elements are in memory. | |
| 44 VirtualFrame::VirtualFrame() | |
| 45 : elements_(parameter_count() + local_count() + kPreallocatedElements), | |
| 46 stack_pointer_(parameter_count() + 1) { // 0-based index of TOS. | |
| 47 for (int i = 0; i <= stack_pointer_; i++) { | |
| 48 elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown)); | |
| 49 } | |
| 50 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { | |
| 51 register_locations_[i] = kIllegalIndex; | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 | |
| 56 void VirtualFrame::Enter() { | 40 void VirtualFrame::Enter() { |
| 57 // Registers live on entry to a JS frame: | 41 // Registers live on entry to a JS frame: |
| 58 // rsp: stack pointer, points to return address from this function. | 42 // rsp: stack pointer, points to return address from this function. |
| 59 // rbp: base pointer, points to previous JS, ArgumentsAdaptor, or | 43 // rbp: base pointer, points to previous JS, ArgumentsAdaptor, or |
| 60 // Trampoline frame. | 44 // Trampoline frame. |
| 61 // rsi: context of this function call. | 45 // rsi: context of this function call. |
| 62 // rdi: pointer to this function object. | 46 // rdi: pointer to this function object. |
| 63 Comment cmnt(masm(), "[ Enter JS frame"); | 47 Comment cmnt(masm(), "[ Enter JS frame"); |
| 64 | 48 |
| 65 #ifdef DEBUG | 49 #ifdef DEBUG |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 | 170 |
| 187 | 171 |
| 188 void VirtualFrame::EmitPop(const Operand& operand) { | 172 void VirtualFrame::EmitPop(const Operand& operand) { |
| 189 ASSERT(stack_pointer_ == element_count() - 1); | 173 ASSERT(stack_pointer_ == element_count() - 1); |
| 190 stack_pointer_--; | 174 stack_pointer_--; |
| 191 elements_.RemoveLast(); | 175 elements_.RemoveLast(); |
| 192 __ pop(operand); | 176 __ pop(operand); |
| 193 } | 177 } |
| 194 | 178 |
| 195 | 179 |
| 196 void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { | 180 void VirtualFrame::EmitPush(Register reg, NumberInfo info) { |
| 197 ASSERT(stack_pointer_ == element_count() - 1); | 181 ASSERT(stack_pointer_ == element_count() - 1); |
| 198 elements_.Add(FrameElement::MemoryElement(info)); | 182 elements_.Add(FrameElement::MemoryElement(info)); |
| 199 stack_pointer_++; | 183 stack_pointer_++; |
| 200 __ push(reg); | 184 __ push(reg); |
| 201 } | 185 } |
| 202 | 186 |
| 203 | 187 |
| 204 void VirtualFrame::EmitPush(const Operand& operand, NumberInfo::Type info) { | 188 void VirtualFrame::EmitPush(const Operand& operand, NumberInfo info) { |
| 205 ASSERT(stack_pointer_ == element_count() - 1); | 189 ASSERT(stack_pointer_ == element_count() - 1); |
| 206 elements_.Add(FrameElement::MemoryElement(info)); | 190 elements_.Add(FrameElement::MemoryElement(info)); |
| 207 stack_pointer_++; | 191 stack_pointer_++; |
| 208 __ push(operand); | 192 __ push(operand); |
| 209 } | 193 } |
| 210 | 194 |
| 211 | 195 |
| 212 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) { | 196 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) { |
| 213 ASSERT(stack_pointer_ == element_count() - 1); | 197 ASSERT(stack_pointer_ == element_count() - 1); |
| 214 elements_.Add(FrameElement::MemoryElement(info)); | 198 elements_.Add(FrameElement::MemoryElement(info)); |
| 215 stack_pointer_++; | 199 stack_pointer_++; |
| 216 __ push(immediate); | 200 __ push(immediate); |
| 217 } | 201 } |
| 218 | 202 |
| 219 | 203 |
| 220 void VirtualFrame::EmitPush(Smi* smi_value) { | 204 void VirtualFrame::EmitPush(Smi* smi_value) { |
| 221 ASSERT(stack_pointer_ == element_count() - 1); | 205 ASSERT(stack_pointer_ == element_count() - 1); |
| 222 elements_.Add(FrameElement::MemoryElement(NumberInfo::kSmi)); | 206 elements_.Add(FrameElement::MemoryElement(NumberInfo::Smi())); |
| 223 stack_pointer_++; | 207 stack_pointer_++; |
| 224 __ Push(smi_value); | 208 __ Push(smi_value); |
| 225 } | 209 } |
| 226 | 210 |
| 227 | 211 |
| 228 void VirtualFrame::EmitPush(Handle<Object> value) { | 212 void VirtualFrame::EmitPush(Handle<Object> value) { |
| 229 ASSERT(stack_pointer_ == element_count() - 1); | 213 ASSERT(stack_pointer_ == element_count() - 1); |
| 230 NumberInfo::Type info = NumberInfo::kUnknown; | 214 NumberInfo info = NumberInfo::Unknown(); |
| 231 if (value->IsSmi()) { | 215 if (value->IsSmi()) { |
| 232 info = NumberInfo::kSmi; | 216 info = NumberInfo::Smi(); |
| 233 } else if (value->IsHeapNumber()) { | 217 } else if (value->IsHeapNumber()) { |
| 234 info = NumberInfo::kHeapNumber; | 218 info = NumberInfo::HeapNumber(); |
| 235 } | 219 } |
| 236 elements_.Add(FrameElement::MemoryElement(info)); | 220 elements_.Add(FrameElement::MemoryElement(info)); |
| 237 stack_pointer_++; | 221 stack_pointer_++; |
| 238 __ Push(value); | 222 __ Push(value); |
| 239 } | 223 } |
| 240 | 224 |
| 241 | 225 |
| 242 void VirtualFrame::EmitPush(Heap::RootListIndex index, NumberInfo::Type info) { | 226 void VirtualFrame::EmitPush(Heap::RootListIndex index, NumberInfo info) { |
| 243 ASSERT(stack_pointer_ == element_count() - 1); | 227 ASSERT(stack_pointer_ == element_count() - 1); |
| 244 elements_.Add(FrameElement::MemoryElement(info)); | 228 elements_.Add(FrameElement::MemoryElement(info)); |
| 245 stack_pointer_++; | 229 stack_pointer_++; |
| 246 __ PushRoot(index); | 230 __ PushRoot(index); |
| 247 } | 231 } |
| 248 | 232 |
| 249 | 233 |
| 250 void VirtualFrame::Drop(int count) { | 234 void VirtualFrame::Drop(int count) { |
| 251 ASSERT(count >= 0); | 235 ASSERT(count >= 0); |
| 252 ASSERT(height() >= count); | 236 ASSERT(height() >= count); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 473 |
| 490 void VirtualFrame::MakeMergable() { | 474 void VirtualFrame::MakeMergable() { |
| 491 for (int i = 0; i < element_count(); i++) { | 475 for (int i = 0; i < element_count(); i++) { |
| 492 FrameElement element = elements_[i]; | 476 FrameElement element = elements_[i]; |
| 493 | 477 |
| 494 // In all cases we have to reset the number type information | 478 // In all cases we have to reset the number type information |
| 495 // to unknown for a mergable frame because of incoming back edges. | 479 // to unknown for a mergable frame because of incoming back edges. |
| 496 if (element.is_constant() || element.is_copy()) { | 480 if (element.is_constant() || element.is_copy()) { |
| 497 if (element.is_synced()) { | 481 if (element.is_synced()) { |
| 498 // Just spill. | 482 // Just spill. |
| 499 elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown); | 483 elements_[i] = FrameElement::MemoryElement(NumberInfo::Unknown()); |
| 500 } else { | 484 } else { |
| 501 // Allocate to a register. | 485 // Allocate to a register. |
| 502 FrameElement backing_element; // Invalid if not a copy. | 486 FrameElement backing_element; // Invalid if not a copy. |
| 503 if (element.is_copy()) { | 487 if (element.is_copy()) { |
| 504 backing_element = elements_[element.index()]; | 488 backing_element = elements_[element.index()]; |
| 505 } | 489 } |
| 506 Result fresh = cgen()->allocator()->Allocate(); | 490 Result fresh = cgen()->allocator()->Allocate(); |
| 507 ASSERT(fresh.is_valid()); // A register was spilled if all were in use. | 491 ASSERT(fresh.is_valid()); // A register was spilled if all were in use. |
| 508 elements_[i] = | 492 elements_[i] = |
| 509 FrameElement::RegisterElement(fresh.reg(), | 493 FrameElement::RegisterElement(fresh.reg(), |
| 510 FrameElement::NOT_SYNCED, | 494 FrameElement::NOT_SYNCED, |
| 511 NumberInfo::kUnknown); | 495 NumberInfo::Unknown()); |
| 512 Use(fresh.reg(), i); | 496 Use(fresh.reg(), i); |
| 513 | 497 |
| 514 // Emit a move. | 498 // Emit a move. |
| 515 if (element.is_constant()) { | 499 if (element.is_constant()) { |
| 516 __ Move(fresh.reg(), element.handle()); | 500 __ Move(fresh.reg(), element.handle()); |
| 517 } else { | 501 } else { |
| 518 ASSERT(element.is_copy()); | 502 ASSERT(element.is_copy()); |
| 519 // Copies are only backed by register or memory locations. | 503 // Copies are only backed by register or memory locations. |
| 520 if (backing_element.is_register()) { | 504 if (backing_element.is_register()) { |
| 521 // The backing store may have been spilled by allocating, | 505 // The backing store may have been spilled by allocating, |
| 522 // but that's OK. If it was, the value is right where we | 506 // but that's OK. If it was, the value is right where we |
| 523 // want it. | 507 // want it. |
| 524 if (!fresh.reg().is(backing_element.reg())) { | 508 if (!fresh.reg().is(backing_element.reg())) { |
| 525 __ movq(fresh.reg(), backing_element.reg()); | 509 __ movq(fresh.reg(), backing_element.reg()); |
| 526 } | 510 } |
| 527 } else { | 511 } else { |
| 528 ASSERT(backing_element.is_memory()); | 512 ASSERT(backing_element.is_memory()); |
| 529 __ movq(fresh.reg(), Operand(rbp, fp_relative(element.index()))); | 513 __ movq(fresh.reg(), Operand(rbp, fp_relative(element.index()))); |
| 530 } | 514 } |
| 531 } | 515 } |
| 532 } | 516 } |
| 533 // No need to set the copied flag --- there are no copies. | 517 // No need to set the copied flag --- there are no copies. |
| 534 } else { | 518 } else { |
| 535 // Clear the copy flag of non-constant, non-copy elements. | 519 // Clear the copy flag of non-constant, non-copy elements. |
| 536 // They cannot be copied because copies are not allowed. | 520 // They cannot be copied because copies are not allowed. |
| 537 // The copy flag is not relied on before the end of this loop, | 521 // The copy flag is not relied on before the end of this loop, |
| 538 // including when registers are spilled. | 522 // including when registers are spilled. |
| 539 elements_[i].clear_copied(); | 523 elements_[i].clear_copied(); |
| 540 elements_[i].set_number_info(NumberInfo::kUnknown); | 524 elements_[i].set_number_info(NumberInfo::Unknown()); |
| 541 } | 525 } |
| 542 } | 526 } |
| 543 } | 527 } |
| 544 | 528 |
| 545 | 529 |
| 546 void VirtualFrame::MergeTo(VirtualFrame* expected) { | 530 void VirtualFrame::MergeTo(VirtualFrame* expected) { |
| 547 Comment cmnt(masm(), "[ Merge frame"); | 531 Comment cmnt(masm(), "[ Merge frame"); |
| 548 // We should always be merging the code generator's current frame to an | 532 // We should always be merging the code generator's current frame to an |
| 549 // expected frame. | 533 // expected frame. |
| 550 ASSERT(cgen()->frame() == this); | 534 ASSERT(cgen()->frame() == this); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 } | 721 } |
| 738 } | 722 } |
| 739 | 723 |
| 740 | 724 |
| 741 Result VirtualFrame::Pop() { | 725 Result VirtualFrame::Pop() { |
| 742 FrameElement element = elements_.RemoveLast(); | 726 FrameElement element = elements_.RemoveLast(); |
| 743 int index = element_count(); | 727 int index = element_count(); |
| 744 ASSERT(element.is_valid()); | 728 ASSERT(element.is_valid()); |
| 745 | 729 |
| 746 // Get number type information of the result. | 730 // Get number type information of the result. |
| 747 NumberInfo::Type info; | 731 NumberInfo info; |
| 748 if (!element.is_copy()) { | 732 if (!element.is_copy()) { |
| 749 info = element.number_info(); | 733 info = element.number_info(); |
| 750 } else { | 734 } else { |
| 751 info = elements_[element.index()].number_info(); | 735 info = elements_[element.index()].number_info(); |
| 752 } | 736 } |
| 753 | 737 |
| 754 bool pop_needed = (stack_pointer_ == index); | 738 bool pop_needed = (stack_pointer_ == index); |
| 755 if (pop_needed) { | 739 if (pop_needed) { |
| 756 stack_pointer_--; | 740 stack_pointer_--; |
| 757 if (element.is_memory()) { | 741 if (element.is_memory()) { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 // Grow the expression stack by handler size less one (the return | 1117 // Grow the expression stack by handler size less one (the return |
| 1134 // address is already pushed by a call instruction). | 1118 // address is already pushed by a call instruction). |
| 1135 Adjust(kHandlerSize - 1); | 1119 Adjust(kHandlerSize - 1); |
| 1136 __ PushTryHandler(IN_JAVASCRIPT, type); | 1120 __ PushTryHandler(IN_JAVASCRIPT, type); |
| 1137 } | 1121 } |
| 1138 | 1122 |
| 1139 | 1123 |
| 1140 #undef __ | 1124 #undef __ |
| 1141 | 1125 |
| 1142 } } // namespace v8::internal | 1126 } } // namespace v8::internal |
| OLD | NEW |