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 27 matching lines...) Expand all Loading... |
38 | 38 |
39 // ------------------------------------------------------------------------- | 39 // ------------------------------------------------------------------------- |
40 // VirtualFrame implementation. | 40 // VirtualFrame implementation. |
41 | 41 |
42 // On entry to a function, the virtual frame already contains the receiver, | 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. | 43 // the parameters, and a return address. All frame elements are in memory. |
44 VirtualFrame::VirtualFrame() | 44 VirtualFrame::VirtualFrame() |
45 : elements_(parameter_count() + local_count() + kPreallocatedElements), | 45 : elements_(parameter_count() + local_count() + kPreallocatedElements), |
46 stack_pointer_(parameter_count() + 1) { // 0-based index of TOS. | 46 stack_pointer_(parameter_count() + 1) { // 0-based index of TOS. |
47 for (int i = 0; i <= stack_pointer_; i++) { | 47 for (int i = 0; i <= stack_pointer_; i++) { |
48 elements_.Add(FrameElement::MemoryElement()); | 48 elements_.Add(FrameElement::MemoryElement(NumberInfo::kUnknown)); |
49 } | 49 } |
50 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { | 50 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
51 register_locations_[i] = kIllegalIndex; | 51 register_locations_[i] = kIllegalIndex; |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 | 55 |
56 void VirtualFrame::SyncElementBelowStackPointer(int index) { | 56 void VirtualFrame::SyncElementBelowStackPointer(int index) { |
57 // Emit code to write elements below the stack pointer to their | 57 // Emit code to write elements below the stack pointer to their |
58 // (already allocated) stack address. | 58 // (already allocated) stack address. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 } | 166 } |
167 } | 167 } |
168 } | 168 } |
169 } | 169 } |
170 | 170 |
171 | 171 |
172 void VirtualFrame::MakeMergable() { | 172 void VirtualFrame::MakeMergable() { |
173 for (int i = 0; i < element_count(); i++) { | 173 for (int i = 0; i < element_count(); i++) { |
174 FrameElement element = elements_[i]; | 174 FrameElement element = elements_[i]; |
175 | 175 |
| 176 // All number type information is reset to unknown for a mergable frame |
| 177 // because of incoming back edges. |
176 if (element.is_constant() || element.is_copy()) { | 178 if (element.is_constant() || element.is_copy()) { |
177 if (element.is_synced()) { | 179 if (element.is_synced()) { |
178 // Just spill. | 180 // Just spill. |
179 elements_[i] = FrameElement::MemoryElement(); | 181 elements_[i] = FrameElement::MemoryElement(NumberInfo::kUnknown); |
180 } else { | 182 } else { |
181 // Allocate to a register. | 183 // Allocate to a register. |
182 FrameElement backing_element; // Invalid if not a copy. | 184 FrameElement backing_element; // Invalid if not a copy. |
183 if (element.is_copy()) { | 185 if (element.is_copy()) { |
184 backing_element = elements_[element.index()]; | 186 backing_element = elements_[element.index()]; |
185 } | 187 } |
186 Result fresh = cgen()->allocator()->Allocate(); | 188 Result fresh = cgen()->allocator()->Allocate(); |
187 ASSERT(fresh.is_valid()); // A register was spilled if all were in use. | 189 ASSERT(fresh.is_valid()); // A register was spilled if all were in use. |
188 elements_[i] = | 190 elements_[i] = |
189 FrameElement::RegisterElement(fresh.reg(), | 191 FrameElement::RegisterElement(fresh.reg(), |
190 FrameElement::NOT_SYNCED); | 192 FrameElement::NOT_SYNCED, |
| 193 NumberInfo::kUnknown); |
191 Use(fresh.reg(), i); | 194 Use(fresh.reg(), i); |
192 | 195 |
193 // Emit a move. | 196 // Emit a move. |
194 if (element.is_constant()) { | 197 if (element.is_constant()) { |
195 if (cgen()->IsUnsafeSmi(element.handle())) { | 198 if (cgen()->IsUnsafeSmi(element.handle())) { |
196 cgen()->MoveUnsafeSmi(fresh.reg(), element.handle()); | 199 cgen()->MoveUnsafeSmi(fresh.reg(), element.handle()); |
197 } else { | 200 } else { |
198 __ Set(fresh.reg(), Immediate(element.handle())); | 201 __ Set(fresh.reg(), Immediate(element.handle())); |
199 } | 202 } |
200 } else { | 203 } else { |
(...skipping 12 matching lines...) Expand all Loading... |
213 } | 216 } |
214 } | 217 } |
215 } | 218 } |
216 // No need to set the copied flag --- there are no copies. | 219 // No need to set the copied flag --- there are no copies. |
217 } else { | 220 } else { |
218 // Clear the copy flag of non-constant, non-copy elements. | 221 // Clear the copy flag of non-constant, non-copy elements. |
219 // They cannot be copied because copies are not allowed. | 222 // They cannot be copied because copies are not allowed. |
220 // The copy flag is not relied on before the end of this loop, | 223 // The copy flag is not relied on before the end of this loop, |
221 // including when registers are spilled. | 224 // including when registers are spilled. |
222 elements_[i].clear_copied(); | 225 elements_[i].clear_copied(); |
| 226 elements_[i].set_number_info(NumberInfo::kUnknown); |
223 } | 227 } |
224 } | 228 } |
225 } | 229 } |
226 | 230 |
227 | 231 |
228 void VirtualFrame::MergeTo(VirtualFrame* expected) { | 232 void VirtualFrame::MergeTo(VirtualFrame* expected) { |
229 Comment cmnt(masm(), "[ Merge frame"); | 233 Comment cmnt(masm(), "[ Merge frame"); |
230 // We should always be merging the code generator's current frame to an | 234 // We should always be merging the code generator's current frame to an |
231 // expected frame. | 235 // expected frame. |
232 ASSERT(cgen()->frame() == this); | 236 ASSERT(cgen()->frame() == this); |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 } else { | 604 } else { |
601 // The original was in a register. | 605 // The original was in a register. |
602 backing_reg = original.reg(); | 606 backing_reg = original.reg(); |
603 set_register_location(backing_reg, new_backing_index); | 607 set_register_location(backing_reg, new_backing_index); |
604 } | 608 } |
605 // Invalidate the element at index. | 609 // Invalidate the element at index. |
606 elements_[index] = FrameElement::InvalidElement(); | 610 elements_[index] = FrameElement::InvalidElement(); |
607 // Set the new backing element. | 611 // Set the new backing element. |
608 if (elements_[new_backing_index].is_synced()) { | 612 if (elements_[new_backing_index].is_synced()) { |
609 elements_[new_backing_index] = | 613 elements_[new_backing_index] = |
610 FrameElement::RegisterElement(backing_reg, FrameElement::SYNCED); | 614 FrameElement::RegisterElement(backing_reg, |
| 615 FrameElement::SYNCED, |
| 616 original.number_info()); |
611 } else { | 617 } else { |
612 elements_[new_backing_index] = | 618 elements_[new_backing_index] = |
613 FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED); | 619 FrameElement::RegisterElement(backing_reg, |
| 620 FrameElement::NOT_SYNCED, |
| 621 original.number_info()); |
614 } | 622 } |
615 // Update the other copies. | 623 // Update the other copies. |
616 for (int i = new_backing_index + 1; i < element_count(); i++) { | 624 for (int i = new_backing_index + 1; i < element_count(); i++) { |
617 if (elements_[i].is_copy() && elements_[i].index() == index) { | 625 if (elements_[i].is_copy() && elements_[i].index() == index) { |
618 elements_[i].set_index(new_backing_index); | 626 elements_[i].set_index(new_backing_index); |
619 elements_[new_backing_index].set_copied(); | 627 elements_[new_backing_index].set_copied(); |
620 } | 628 } |
621 } | 629 } |
622 return new_backing_index; | 630 return new_backing_index; |
623 } | 631 } |
(...skipping 10 matching lines...) Expand all Loading... |
634 } | 642 } |
635 | 643 |
636 switch (original.type()) { | 644 switch (original.type()) { |
637 case FrameElement::MEMORY: { | 645 case FrameElement::MEMORY: { |
638 // Emit code to load the original element's data into a register. | 646 // Emit code to load the original element's data into a register. |
639 // Push that register as a FrameElement on top of the frame. | 647 // Push that register as a FrameElement on top of the frame. |
640 Result fresh = cgen()->allocator()->Allocate(); | 648 Result fresh = cgen()->allocator()->Allocate(); |
641 ASSERT(fresh.is_valid()); | 649 ASSERT(fresh.is_valid()); |
642 FrameElement new_element = | 650 FrameElement new_element = |
643 FrameElement::RegisterElement(fresh.reg(), | 651 FrameElement::RegisterElement(fresh.reg(), |
644 FrameElement::NOT_SYNCED); | 652 FrameElement::NOT_SYNCED, |
| 653 original.number_info()); |
645 Use(fresh.reg(), element_count()); | 654 Use(fresh.reg(), element_count()); |
646 elements_.Add(new_element); | 655 elements_.Add(new_element); |
647 __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); | 656 __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); |
648 break; | 657 break; |
649 } | 658 } |
650 case FrameElement::REGISTER: | 659 case FrameElement::REGISTER: |
651 Use(original.reg(), element_count()); | 660 Use(original.reg(), element_count()); |
652 // Fall through. | 661 // Fall through. |
653 case FrameElement::CONSTANT: | 662 case FrameElement::CONSTANT: |
654 case FrameElement::COPY: | 663 case FrameElement::COPY: |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 } | 1053 } |
1045 } | 1054 } |
1046 } | 1055 } |
1047 | 1056 |
1048 | 1057 |
1049 Result VirtualFrame::Pop() { | 1058 Result VirtualFrame::Pop() { |
1050 FrameElement element = elements_.RemoveLast(); | 1059 FrameElement element = elements_.RemoveLast(); |
1051 int index = element_count(); | 1060 int index = element_count(); |
1052 ASSERT(element.is_valid()); | 1061 ASSERT(element.is_valid()); |
1053 | 1062 |
| 1063 // Get number type information of the result. |
| 1064 NumberInfo::Type info; |
| 1065 if (!element.is_copy()) { |
| 1066 info = element.number_info(); |
| 1067 } else { |
| 1068 info = elements_[element.index()].number_info(); |
| 1069 } |
| 1070 |
1054 bool pop_needed = (stack_pointer_ == index); | 1071 bool pop_needed = (stack_pointer_ == index); |
1055 if (pop_needed) { | 1072 if (pop_needed) { |
1056 stack_pointer_--; | 1073 stack_pointer_--; |
1057 if (element.is_memory()) { | 1074 if (element.is_memory()) { |
1058 Result temp = cgen()->allocator()->Allocate(); | 1075 Result temp = cgen()->allocator()->Allocate(); |
1059 ASSERT(temp.is_valid()); | 1076 ASSERT(temp.is_valid()); |
1060 __ pop(temp.reg()); | 1077 __ pop(temp.reg()); |
| 1078 temp.set_number_info(info); |
1061 return temp; | 1079 return temp; |
1062 } | 1080 } |
1063 | 1081 |
1064 __ add(Operand(esp), Immediate(kPointerSize)); | 1082 __ add(Operand(esp), Immediate(kPointerSize)); |
1065 } | 1083 } |
1066 ASSERT(!element.is_memory()); | 1084 ASSERT(!element.is_memory()); |
1067 | 1085 |
1068 // The top element is a register, constant, or a copy. Unuse | 1086 // The top element is a register, constant, or a copy. Unuse |
1069 // registers and follow copies to their backing store. | 1087 // registers and follow copies to their backing store. |
1070 if (element.is_register()) { | 1088 if (element.is_register()) { |
1071 Unuse(element.reg()); | 1089 Unuse(element.reg()); |
1072 } else if (element.is_copy()) { | 1090 } else if (element.is_copy()) { |
1073 ASSERT(element.index() < index); | 1091 ASSERT(element.index() < index); |
1074 index = element.index(); | 1092 index = element.index(); |
1075 element = elements_[index]; | 1093 element = elements_[index]; |
1076 } | 1094 } |
1077 ASSERT(!element.is_copy()); | 1095 ASSERT(!element.is_copy()); |
1078 | 1096 |
1079 // The element is memory, a register, or a constant. | 1097 // The element is memory, a register, or a constant. |
1080 if (element.is_memory()) { | 1098 if (element.is_memory()) { |
1081 // Memory elements could only be the backing store of a copy. | 1099 // Memory elements could only be the backing store of a copy. |
1082 // Allocate the original to a register. | 1100 // Allocate the original to a register. |
1083 ASSERT(index <= stack_pointer_); | 1101 ASSERT(index <= stack_pointer_); |
1084 Result temp = cgen()->allocator()->Allocate(); | 1102 Result temp = cgen()->allocator()->Allocate(); |
1085 ASSERT(temp.is_valid()); | 1103 ASSERT(temp.is_valid()); |
1086 Use(temp.reg(), index); | 1104 Use(temp.reg(), index); |
1087 FrameElement new_element = | 1105 FrameElement new_element = |
1088 FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED); | 1106 FrameElement::RegisterElement(temp.reg(), |
| 1107 FrameElement::SYNCED, |
| 1108 element.number_info()); |
1089 // Preserve the copy flag on the element. | 1109 // Preserve the copy flag on the element. |
1090 if (element.is_copied()) new_element.set_copied(); | 1110 if (element.is_copied()) new_element.set_copied(); |
1091 elements_[index] = new_element; | 1111 elements_[index] = new_element; |
1092 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); | 1112 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); |
1093 return Result(temp.reg()); | 1113 return Result(temp.reg(), info); |
1094 } else if (element.is_register()) { | 1114 } else if (element.is_register()) { |
1095 return Result(element.reg()); | 1115 return Result(element.reg(), info); |
1096 } else { | 1116 } else { |
1097 ASSERT(element.is_constant()); | 1117 ASSERT(element.is_constant()); |
1098 return Result(element.handle()); | 1118 return Result(element.handle()); |
1099 } | 1119 } |
1100 } | 1120 } |
1101 | 1121 |
1102 | 1122 |
1103 void VirtualFrame::EmitPop(Register reg) { | 1123 void VirtualFrame::EmitPop(Register reg) { |
1104 ASSERT(stack_pointer_ == element_count() - 1); | 1124 ASSERT(stack_pointer_ == element_count() - 1); |
1105 stack_pointer_--; | 1125 stack_pointer_--; |
1106 elements_.RemoveLast(); | 1126 elements_.RemoveLast(); |
1107 __ pop(reg); | 1127 __ pop(reg); |
1108 } | 1128 } |
1109 | 1129 |
1110 | 1130 |
1111 void VirtualFrame::EmitPop(Operand operand) { | 1131 void VirtualFrame::EmitPop(Operand operand) { |
1112 ASSERT(stack_pointer_ == element_count() - 1); | 1132 ASSERT(stack_pointer_ == element_count() - 1); |
1113 stack_pointer_--; | 1133 stack_pointer_--; |
1114 elements_.RemoveLast(); | 1134 elements_.RemoveLast(); |
1115 __ pop(operand); | 1135 __ pop(operand); |
1116 } | 1136 } |
1117 | 1137 |
1118 | 1138 |
1119 void VirtualFrame::EmitPush(Register reg) { | 1139 void VirtualFrame::EmitPush(Register reg, NumberInfo::Type info) { |
1120 ASSERT(stack_pointer_ == element_count() - 1); | 1140 ASSERT(stack_pointer_ == element_count() - 1); |
1121 elements_.Add(FrameElement::MemoryElement()); | 1141 elements_.Add(FrameElement::MemoryElement(info)); |
1122 stack_pointer_++; | 1142 stack_pointer_++; |
1123 __ push(reg); | 1143 __ push(reg); |
1124 } | 1144 } |
1125 | 1145 |
1126 | 1146 |
1127 void VirtualFrame::EmitPush(Operand operand) { | 1147 void VirtualFrame::EmitPush(Operand operand, NumberInfo::Type info) { |
1128 ASSERT(stack_pointer_ == element_count() - 1); | 1148 ASSERT(stack_pointer_ == element_count() - 1); |
1129 elements_.Add(FrameElement::MemoryElement()); | 1149 elements_.Add(FrameElement::MemoryElement(info)); |
1130 stack_pointer_++; | 1150 stack_pointer_++; |
1131 __ push(operand); | 1151 __ push(operand); |
1132 } | 1152 } |
1133 | 1153 |
1134 | 1154 |
1135 void VirtualFrame::EmitPush(Immediate immediate) { | 1155 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) { |
1136 ASSERT(stack_pointer_ == element_count() - 1); | 1156 ASSERT(stack_pointer_ == element_count() - 1); |
1137 elements_.Add(FrameElement::MemoryElement()); | 1157 elements_.Add(FrameElement::MemoryElement(info)); |
1138 stack_pointer_++; | 1158 stack_pointer_++; |
1139 __ push(immediate); | 1159 __ push(immediate); |
1140 } | 1160 } |
1141 | 1161 |
1142 | 1162 |
1143 #undef __ | 1163 #undef __ |
1144 | 1164 |
1145 } } // namespace v8::internal | 1165 } } // namespace v8::internal |
OLD | NEW |