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 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 elements_[top_index] = new_top; | 768 elements_[top_index] = new_top; |
769 } else { | 769 } else { |
770 // The stored-to slot holds the same value as the top but | 770 // The stored-to slot holds the same value as the top but |
771 // unsynced. (We do not have copies of constants yet.) | 771 // unsynced. (We do not have copies of constants yet.) |
772 ASSERT(top.is_constant()); | 772 ASSERT(top.is_constant()); |
773 elements_[index].clear_sync(); | 773 elements_[index].clear_sync(); |
774 } | 774 } |
775 } | 775 } |
776 | 776 |
777 | 777 |
| 778 void VirtualFrame::UntaggedPushFrameSlotAt(int index) { |
| 779 ASSERT(index >= 0); |
| 780 ASSERT(index <= element_count()); |
| 781 FrameElement original = elements_[index]; |
| 782 if (original.is_copy()) { |
| 783 original = elements_[original.index()]; |
| 784 index = original.index(); |
| 785 } |
| 786 |
| 787 switch (original.type()) { |
| 788 case FrameElement::MEMORY: |
| 789 case FrameElement::REGISTER: { |
| 790 Label done; |
| 791 // Emit code to load the original element's data into a register. |
| 792 // Push that register as a FrameElement on top of the frame. |
| 793 Result fresh = cgen()->allocator()->Allocate(); |
| 794 ASSERT(fresh.is_valid()); |
| 795 Register fresh_reg = fresh.reg(); |
| 796 FrameElement new_element = |
| 797 FrameElement::RegisterElement(fresh_reg, |
| 798 FrameElement::NOT_SYNCED, |
| 799 original.number_info()); |
| 800 new_element.set_untagged_int32(true); |
| 801 Use(fresh_reg, element_count()); |
| 802 fresh.Unuse(); // BreakTarget does not handle a live Result well. |
| 803 elements_.Add(new_element); |
| 804 if (original.is_register()) { |
| 805 __ mov(fresh_reg, original.reg()); |
| 806 } else { |
| 807 ASSERT(original.is_memory()); |
| 808 __ mov(fresh_reg, Operand(ebp, fp_relative(index))); |
| 809 } |
| 810 // Now convert the value to int32, or bail out. |
| 811 if (original.number_info().IsSmi()) { |
| 812 __ SmiUntag(fresh_reg); |
| 813 // Pushing the element is completely done. |
| 814 } else { |
| 815 __ test(fresh_reg, Immediate(kSmiTagMask)); |
| 816 Label not_smi; |
| 817 __ j(not_zero, ¬_smi); |
| 818 __ SmiUntag(fresh_reg); |
| 819 __ jmp(&done); |
| 820 |
| 821 __ bind(¬_smi); |
| 822 if (!original.number_info().IsNumber()) { |
| 823 __ cmp(FieldOperand(fresh_reg, HeapObject::kMapOffset), |
| 824 Factory::heap_number_map()); |
| 825 cgen()->unsafe_bailout_->Branch(not_equal); |
| 826 } |
| 827 |
| 828 if (!CpuFeatures::IsSupported(SSE2)) { |
| 829 UNREACHABLE(); |
| 830 } else { |
| 831 CpuFeatures::Scope use_sse2(SSE2); |
| 832 __ movdbl(xmm0, FieldOperand(fresh_reg, HeapNumber::kValueOffset)); |
| 833 __ cvttsd2si(fresh_reg, Operand(xmm0)); |
| 834 __ cvtsi2sd(xmm1, Operand(fresh_reg)); |
| 835 __ ucomisd(xmm0, xmm1); |
| 836 cgen()->unsafe_bailout_->Branch(not_equal); |
| 837 cgen()->unsafe_bailout_->Branch(parity_even); // NaN. |
| 838 // Test for negative zero. |
| 839 __ test(fresh_reg, Operand(fresh_reg)); |
| 840 __ j(not_zero, &done); |
| 841 __ movmskpd(fresh_reg, xmm0); |
| 842 __ and_(fresh_reg, 0x1); |
| 843 cgen()->unsafe_bailout_->Branch(not_equal); |
| 844 } |
| 845 __ bind(&done); |
| 846 } |
| 847 break; |
| 848 } |
| 849 case FrameElement::CONSTANT: |
| 850 elements_.Add(CopyElementAt(index)); |
| 851 elements_[element_count() - 1].set_untagged_int32(true); |
| 852 break; |
| 853 case FrameElement::COPY: |
| 854 case FrameElement::INVALID: |
| 855 UNREACHABLE(); |
| 856 break; |
| 857 } |
| 858 } |
| 859 |
| 860 |
778 void VirtualFrame::PushTryHandler(HandlerType type) { | 861 void VirtualFrame::PushTryHandler(HandlerType type) { |
779 ASSERT(cgen()->HasValidEntryRegisters()); | 862 ASSERT(cgen()->HasValidEntryRegisters()); |
780 // Grow the expression stack by handler size less one (the return | 863 // Grow the expression stack by handler size less one (the return |
781 // address is already pushed by a call instruction). | 864 // address is already pushed by a call instruction). |
782 Adjust(kHandlerSize - 1); | 865 Adjust(kHandlerSize - 1); |
783 __ PushTryHandler(IN_JAVASCRIPT, type); | 866 __ PushTryHandler(IN_JAVASCRIPT, type); |
784 } | 867 } |
785 | 868 |
786 | 869 |
787 Result VirtualFrame::RawCallStub(CodeStub* stub) { | 870 Result VirtualFrame::RawCallStub(CodeStub* stub) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 Unuse(dropped.reg()); | 1136 Unuse(dropped.reg()); |
1054 } | 1137 } |
1055 } | 1138 } |
1056 } | 1139 } |
1057 | 1140 |
1058 | 1141 |
1059 Result VirtualFrame::Pop() { | 1142 Result VirtualFrame::Pop() { |
1060 FrameElement element = elements_.RemoveLast(); | 1143 FrameElement element = elements_.RemoveLast(); |
1061 int index = element_count(); | 1144 int index = element_count(); |
1062 ASSERT(element.is_valid()); | 1145 ASSERT(element.is_valid()); |
| 1146 ASSERT(element.is_untagged_int32() == cgen()->in_safe_int32_mode()); |
1063 | 1147 |
1064 // Get number type information of the result. | 1148 // Get number type information of the result. |
1065 NumberInfo info; | 1149 NumberInfo info; |
1066 if (!element.is_copy()) { | 1150 if (!element.is_copy()) { |
1067 info = element.number_info(); | 1151 info = element.number_info(); |
1068 } else { | 1152 } else { |
1069 info = elements_[element.index()].number_info(); | 1153 info = elements_[element.index()].number_info(); |
1070 } | 1154 } |
1071 | 1155 |
1072 bool pop_needed = (stack_pointer_ == index); | 1156 bool pop_needed = (stack_pointer_ == index); |
1073 if (pop_needed) { | 1157 if (pop_needed) { |
1074 stack_pointer_--; | 1158 stack_pointer_--; |
1075 if (element.is_memory()) { | 1159 if (element.is_memory()) { |
1076 Result temp = cgen()->allocator()->Allocate(); | 1160 Result temp = cgen()->allocator()->Allocate(); |
1077 ASSERT(temp.is_valid()); | 1161 ASSERT(temp.is_valid()); |
1078 __ pop(temp.reg()); | 1162 __ pop(temp.reg()); |
1079 temp.set_number_info(info); | 1163 temp.set_number_info(info); |
| 1164 temp.set_untagged_int32(element.is_untagged_int32()); |
1080 return temp; | 1165 return temp; |
1081 } | 1166 } |
1082 | 1167 |
1083 __ add(Operand(esp), Immediate(kPointerSize)); | 1168 __ add(Operand(esp), Immediate(kPointerSize)); |
1084 } | 1169 } |
1085 ASSERT(!element.is_memory()); | 1170 ASSERT(!element.is_memory()); |
1086 | 1171 |
1087 // The top element is a register, constant, or a copy. Unuse | 1172 // The top element is a register, constant, or a copy. Unuse |
1088 // registers and follow copies to their backing store. | 1173 // registers and follow copies to their backing store. |
1089 if (element.is_register()) { | 1174 if (element.is_register()) { |
1090 Unuse(element.reg()); | 1175 Unuse(element.reg()); |
1091 } else if (element.is_copy()) { | 1176 } else if (element.is_copy()) { |
| 1177 ASSERT(!element.is_untagged_int32()); |
1092 ASSERT(element.index() < index); | 1178 ASSERT(element.index() < index); |
1093 index = element.index(); | 1179 index = element.index(); |
1094 element = elements_[index]; | 1180 element = elements_[index]; |
1095 } | 1181 } |
1096 ASSERT(!element.is_copy()); | 1182 ASSERT(!element.is_copy()); |
1097 | 1183 |
1098 // The element is memory, a register, or a constant. | 1184 // The element is memory, a register, or a constant. |
1099 if (element.is_memory()) { | 1185 if (element.is_memory()) { |
1100 // Memory elements could only be the backing store of a copy. | 1186 // Memory elements could only be the backing store of a copy. |
1101 // Allocate the original to a register. | 1187 // Allocate the original to a register. |
1102 ASSERT(index <= stack_pointer_); | 1188 ASSERT(index <= stack_pointer_); |
| 1189 ASSERT(!element.is_untagged_int32()); |
1103 Result temp = cgen()->allocator()->Allocate(); | 1190 Result temp = cgen()->allocator()->Allocate(); |
1104 ASSERT(temp.is_valid()); | 1191 ASSERT(temp.is_valid()); |
1105 Use(temp.reg(), index); | 1192 Use(temp.reg(), index); |
1106 FrameElement new_element = | 1193 FrameElement new_element = |
1107 FrameElement::RegisterElement(temp.reg(), | 1194 FrameElement::RegisterElement(temp.reg(), |
1108 FrameElement::SYNCED, | 1195 FrameElement::SYNCED, |
1109 element.number_info()); | 1196 element.number_info()); |
1110 // Preserve the copy flag on the element. | 1197 // Preserve the copy flag on the element. |
1111 if (element.is_copied()) new_element.set_copied(); | 1198 if (element.is_copied()) new_element.set_copied(); |
1112 elements_[index] = new_element; | 1199 elements_[index] = new_element; |
1113 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); | 1200 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); |
1114 return Result(temp.reg(), info); | 1201 return Result(temp.reg(), info); |
1115 } else if (element.is_register()) { | 1202 } else if (element.is_register()) { |
1116 return Result(element.reg(), info); | 1203 Result return_value(element.reg(), info); |
| 1204 return_value.set_untagged_int32(element.is_untagged_int32()); |
| 1205 return return_value; |
1117 } else { | 1206 } else { |
1118 ASSERT(element.is_constant()); | 1207 ASSERT(element.is_constant()); |
1119 return Result(element.handle()); | 1208 Result return_value(element.handle()); |
| 1209 return_value.set_untagged_int32(element.is_untagged_int32()); |
| 1210 return return_value; |
1120 } | 1211 } |
1121 } | 1212 } |
1122 | 1213 |
1123 | 1214 |
1124 void VirtualFrame::EmitPop(Register reg) { | 1215 void VirtualFrame::EmitPop(Register reg) { |
1125 ASSERT(stack_pointer_ == element_count() - 1); | 1216 ASSERT(stack_pointer_ == element_count() - 1); |
1126 stack_pointer_--; | 1217 stack_pointer_--; |
1127 elements_.RemoveLast(); | 1218 elements_.RemoveLast(); |
1128 __ pop(reg); | 1219 __ pop(reg); |
1129 } | 1220 } |
(...skipping 24 matching lines...) Expand all Loading... |
1154 | 1245 |
1155 | 1246 |
1156 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) { | 1247 void VirtualFrame::EmitPush(Immediate immediate, NumberInfo info) { |
1157 ASSERT(stack_pointer_ == element_count() - 1); | 1248 ASSERT(stack_pointer_ == element_count() - 1); |
1158 elements_.Add(FrameElement::MemoryElement(info)); | 1249 elements_.Add(FrameElement::MemoryElement(info)); |
1159 stack_pointer_++; | 1250 stack_pointer_++; |
1160 __ push(immediate); | 1251 __ push(immediate); |
1161 } | 1252 } |
1162 | 1253 |
1163 | 1254 |
| 1255 void VirtualFrame::PushUntaggedElement(Handle<Object> value) { |
| 1256 elements_.Add(FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED)); |
| 1257 elements_[element_count() - 1].set_untagged_int32(true); |
| 1258 } |
| 1259 |
| 1260 |
1164 void VirtualFrame::Push(Expression* expr) { | 1261 void VirtualFrame::Push(Expression* expr) { |
1165 ASSERT(expr->IsTrivial()); | 1262 ASSERT(expr->IsTrivial()); |
1166 | 1263 |
1167 Literal* lit = expr->AsLiteral(); | 1264 Literal* lit = expr->AsLiteral(); |
1168 if (lit != NULL) { | 1265 if (lit != NULL) { |
1169 Push(lit->handle()); | 1266 Push(lit->handle()); |
1170 return; | 1267 return; |
1171 } | 1268 } |
1172 | 1269 |
1173 VariableProxy* proxy = expr->AsVariableProxy(); | 1270 VariableProxy* proxy = expr->AsVariableProxy(); |
1174 if (proxy != NULL) { | 1271 if (proxy != NULL) { |
1175 Slot* slot = proxy->var()->slot(); | 1272 Slot* slot = proxy->var()->slot(); |
1176 if (slot->type() == Slot::LOCAL) { | 1273 if (slot->type() == Slot::LOCAL) { |
1177 PushLocalAt(slot->index()); | 1274 PushLocalAt(slot->index()); |
1178 return; | 1275 return; |
1179 } | 1276 } |
1180 if (slot->type() == Slot::PARAMETER) { | 1277 if (slot->type() == Slot::PARAMETER) { |
1181 PushParameterAt(slot->index()); | 1278 PushParameterAt(slot->index()); |
1182 return; | 1279 return; |
1183 } | 1280 } |
1184 } | 1281 } |
1185 UNREACHABLE(); | 1282 UNREACHABLE(); |
1186 } | 1283 } |
1187 | 1284 |
1188 | 1285 |
1189 #undef __ | 1286 #undef __ |
1190 | 1287 |
1191 } } // namespace v8::internal | 1288 } } // namespace v8::internal |
OLD | NEW |