OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | |
8 | |
9 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
11 #include "src/compiler/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
12 #include "src/compiler/diamond.h" | 10 #include "src/compiler/diamond.h" |
13 #include "src/compiler/graph-inl.h" | 11 #include "src/compiler/graph-inl.h" |
14 #include "src/compiler/node-matchers.h" | 12 #include "src/compiler/node-matchers.h" |
15 #include "src/compiler/node-properties-inl.h" | 13 #include "src/compiler/node-properties-inl.h" |
16 #include "src/compiler/representation-change.h" | 14 #include "src/compiler/representation-change.h" |
17 #include "src/compiler/simplified-lowering.h" | 15 #include "src/compiler/simplified-lowering.h" |
18 #include "src/compiler/simplified-operator.h" | 16 #include "src/compiler/simplified-operator.h" |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 } | 751 } |
754 case IrOpcode::kStoreField: { | 752 case IrOpcode::kStoreField: { |
755 FieldAccess access = FieldAccessOf(node->op()); | 753 FieldAccess access = FieldAccessOf(node->op()); |
756 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 754 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); |
757 ProcessInput(node, 1, access.machine_type); | 755 ProcessInput(node, 1, access.machine_type); |
758 ProcessRemainingInputs(node, 2); | 756 ProcessRemainingInputs(node, 2); |
759 SetOutput(node, 0); | 757 SetOutput(node, 0); |
760 if (lower()) lowering->DoStoreField(node); | 758 if (lower()) lowering->DoStoreField(node); |
761 break; | 759 break; |
762 } | 760 } |
763 case IrOpcode::kLoadElement: { | 761 case IrOpcode::kLoadBuffer: { |
764 ElementAccess access = ElementAccessOf(node->op()); | 762 BufferAccess access = BufferAccessOf(node->op()); |
765 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 763 ProcessInput(node, 0, kMachPtr); // buffer |
766 ProcessInput(node, 1, kMachInt32); // element index | 764 ProcessInput(node, 1, kMachInt32); // offset |
767 ProcessInput(node, 2, kMachInt32); // length | 765 ProcessInput(node, 2, kMachInt32); // length |
768 ProcessRemainingInputs(node, 3); | 766 ProcessRemainingInputs(node, 3); |
769 // Tagged overrides everything if we have to do a typed array bounds | 767 // Tagged overrides everything if we have to do a typed array bounds |
770 // check, because we may need to return undefined then. | 768 // check, because we may need to return undefined then. |
771 MachineType output_type = | 769 MachineType output_type = |
772 (access.bounds_check == kTypedArrayBoundsCheck && | 770 (use & kRepTagged) ? kMachAnyTagged : access.machine_type(); |
773 (use & kRepTagged)) | |
774 ? kMachAnyTagged | |
775 : access.machine_type; | |
776 SetOutput(node, output_type); | 771 SetOutput(node, output_type); |
777 if (lower()) lowering->DoLoadElement(node, output_type); | 772 if (lower()) lowering->DoLoadBuffer(node, output_type, changer_); |
| 773 break; |
| 774 } |
| 775 case IrOpcode::kStoreBuffer: { |
| 776 BufferAccess access = BufferAccessOf(node->op()); |
| 777 ProcessInput(node, 0, kMachPtr); // buffer |
| 778 ProcessInput(node, 1, kMachInt32); // offset |
| 779 ProcessInput(node, 2, kMachInt32); // length |
| 780 ProcessInput(node, 3, access.machine_type()); // value |
| 781 ProcessRemainingInputs(node, 4); |
| 782 SetOutput(node, 0); |
| 783 if (lower()) lowering->DoStoreBuffer(node); |
| 784 break; |
| 785 } |
| 786 case IrOpcode::kLoadElement: { |
| 787 ElementAccess access = ElementAccessOf(node->op()); |
| 788 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base |
| 789 ProcessInput(node, 1, kMachInt32); // index |
| 790 ProcessRemainingInputs(node, 2); |
| 791 SetOutput(node, access.machine_type); |
| 792 if (lower()) lowering->DoLoadElement(node); |
778 break; | 793 break; |
779 } | 794 } |
780 case IrOpcode::kStoreElement: { | 795 case IrOpcode::kStoreElement: { |
781 ElementAccess access = ElementAccessOf(node->op()); | 796 ElementAccess access = ElementAccessOf(node->op()); |
782 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 797 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); // base |
783 ProcessInput(node, 1, kMachInt32); // element index | 798 ProcessInput(node, 1, kMachInt32); // index |
784 ProcessInput(node, 2, kMachInt32); // length | 799 ProcessInput(node, 2, access.machine_type); // value |
785 ProcessInput(node, 3, access.machine_type); | 800 ProcessRemainingInputs(node, 3); |
786 ProcessRemainingInputs(node, 4); | |
787 SetOutput(node, 0); | 801 SetOutput(node, 0); |
788 if (lower()) lowering->DoStoreElement(node); | 802 if (lower()) lowering->DoStoreElement(node); |
789 break; | 803 break; |
790 } | 804 } |
791 case IrOpcode::kObjectIsSmi: { | 805 case IrOpcode::kObjectIsSmi: { |
792 ProcessInput(node, 0, kMachAnyTagged); | 806 ProcessInput(node, 0, kMachAnyTagged); |
793 SetOutput(node, kRepBit | kTypeBool); | 807 SetOutput(node, kRepBit | kTypeBool); |
794 if (lower()) { | 808 if (lower()) { |
795 Node* is_tagged = jsgraph_->graph()->NewNode( | 809 Node* is_tagged = jsgraph_->graph()->NewNode( |
796 jsgraph_->machine()->WordAnd(), node->InputAt(0), | 810 jsgraph_->machine()->WordAnd(), node->InputAt(0), |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 if (machine()->Is64()) { | 1120 if (machine()->Is64()) { |
1107 // TODO(turbofan): This is probably only correct for typed arrays, and only | 1121 // TODO(turbofan): This is probably only correct for typed arrays, and only |
1108 // if the typed arrays are at most 2GiB in size, which happens to match | 1122 // if the typed arrays are at most 2GiB in size, which happens to match |
1109 // exactly our current situation. | 1123 // exactly our current situation. |
1110 index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index); | 1124 index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index); |
1111 } | 1125 } |
1112 return index; | 1126 return index; |
1113 } | 1127 } |
1114 | 1128 |
1115 | 1129 |
1116 namespace { | 1130 void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type, |
| 1131 RepresentationChanger* changer) { |
| 1132 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode()); |
| 1133 DCHECK_NE(kMachNone, RepresentationOf(output_type)); |
| 1134 MachineType const type = BufferAccessOf(node->op()).machine_type(); |
| 1135 if (output_type & kRepTagged) { |
| 1136 Node* const buffer = node->InputAt(0); |
| 1137 Node* const offset = node->InputAt(1); |
| 1138 Node* const length = node->InputAt(2); |
| 1139 Node* const effect = node->InputAt(3); |
| 1140 Node* const control = node->InputAt(4); |
1117 | 1141 |
1118 intptr_t AddressForOutOfBoundsLoad(MachineType type) { | 1142 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); |
1119 switch (RepresentationOf(type)) { | 1143 Node* branch = |
1120 case kRepFloat32: { | 1144 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
1121 static const float dummy = std::numeric_limits<float>::quiet_NaN(); | 1145 |
1122 return bit_cast<intptr_t>(&dummy); | 1146 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
1123 } | 1147 Node* etrue = graph()->NewNode(machine()->Load(type), buffer, offset, |
1124 case kRepFloat64: { | 1148 effect, if_true); |
1125 static const double dummy = std::numeric_limits<double>::quiet_NaN(); | 1149 Node* vtrue = changer->GetTaggedRepresentationFor(etrue, type); |
1126 return bit_cast<intptr_t>(&dummy); | 1150 |
1127 } | 1151 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
1128 case kRepBit: | 1152 Node* vfalse = jsgraph()->UndefinedConstant(); |
1129 case kRepWord8: | 1153 Node* efalse = effect; |
1130 case kRepWord16: | 1154 |
1131 case kRepWord32: { | 1155 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
1132 static const int32_t dummy = 0; | 1156 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); |
1133 return bit_cast<intptr_t>(&dummy); | 1157 |
1134 } | 1158 // Replace effect uses of {node} with the {ephi}. |
1135 default: | 1159 NodeProperties::ReplaceWithValue(node, node, ephi); |
1136 break; | 1160 |
| 1161 // Turn the {node} into a Phi. |
| 1162 node->set_op(common()->Phi(kMachAnyTagged, 2)); |
| 1163 node->ReplaceInput(0, vtrue); |
| 1164 node->ReplaceInput(1, vfalse); |
| 1165 node->ReplaceInput(2, merge); |
| 1166 node->TrimInputCount(3); |
| 1167 } else { |
| 1168 node->set_op(machine()->CheckedLoad(type)); |
1137 } | 1169 } |
1138 UNREACHABLE(); | |
1139 return 0; | |
1140 } | 1170 } |
1141 | 1171 |
1142 | 1172 |
1143 intptr_t AddressForOutOfBoundsStore() { | 1173 void SimplifiedLowering::DoStoreBuffer(Node* node) { |
1144 static volatile double dummy = 0; | 1174 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode()); |
1145 return bit_cast<intptr_t>(&dummy); | 1175 MachineType const type = BufferAccessOf(node->op()).machine_type(); |
| 1176 node->set_op(machine()->CheckedStore(type)); |
1146 } | 1177 } |
1147 | 1178 |
1148 } // namespace | |
1149 | 1179 |
1150 | 1180 void SimplifiedLowering::DoLoadElement(Node* node) { |
1151 void SimplifiedLowering::DoLoadElement(Node* node, MachineType output_type) { | |
1152 const ElementAccess& access = ElementAccessOf(node->op()); | 1181 const ElementAccess& access = ElementAccessOf(node->op()); |
1153 const Operator* op = machine()->Load(access.machine_type); | 1182 node->set_op(machine()->Load(access.machine_type)); |
1154 Node* key = node->InputAt(1); | 1183 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
1155 Node* index = ComputeIndex(access, key); | |
1156 Node* effect = node->InputAt(3); | |
1157 if (access.bounds_check == kNoBoundsCheck) { | |
1158 DCHECK_EQ(access.machine_type, output_type); | |
1159 node->set_op(op); | |
1160 node->ReplaceInput(1, index); | |
1161 node->ReplaceInput(2, effect); | |
1162 node->ReplaceInput(3, graph()->start()); | |
1163 } else { | |
1164 DCHECK_EQ(kTypedArrayBoundsCheck, access.bounds_check); | |
1165 | |
1166 Node* base = node->InputAt(0); | |
1167 Node* length = node->InputAt(2); | |
1168 Node* check = graph()->NewNode(machine()->Uint32LessThan(), key, length); | |
1169 | |
1170 IntPtrMatcher mbase(base); | |
1171 if (mbase.HasValue() && (output_type & kRepTagged) == 0) { | |
1172 Node* select = graph()->NewNode( | |
1173 common()->Select(kMachIntPtr, BranchHint::kTrue), check, index, | |
1174 jsgraph()->IntPtrConstant(AddressForOutOfBoundsLoad(output_type) - | |
1175 mbase.Value())); | |
1176 | |
1177 node->set_op(op); | |
1178 node->ReplaceInput(1, select); | |
1179 node->ReplaceInput(2, effect); | |
1180 node->ReplaceInput(3, graph()->start()); | |
1181 } else { | |
1182 Diamond d(graph(), common(), check, BranchHint::kTrue); | |
1183 | |
1184 Node* load = graph()->NewNode(op, base, index, effect, d.if_true); | |
1185 Node* result = load; | |
1186 if (output_type & kRepTagged) { | |
1187 // TODO(turbofan): This is ugly as hell! | |
1188 SimplifiedOperatorBuilder simplified(graph()->zone()); | |
1189 RepresentationChanger changer(jsgraph(), &simplified, | |
1190 graph()->zone()->isolate()); | |
1191 result = | |
1192 changer.GetTaggedRepresentationFor(result, access.machine_type); | |
1193 } | |
1194 | |
1195 Node* undefined; | |
1196 if (output_type & kRepTagged) { | |
1197 DCHECK_EQ(0, access.machine_type & kRepTagged); | |
1198 undefined = jsgraph()->UndefinedConstant(); | |
1199 } else if (output_type & kRepFloat32) { | |
1200 undefined = | |
1201 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN()); | |
1202 } else if (output_type & kRepFloat64) { | |
1203 undefined = jsgraph()->Float64Constant( | |
1204 std::numeric_limits<double>::quiet_NaN()); | |
1205 } else { | |
1206 undefined = jsgraph()->Int32Constant(0); | |
1207 } | |
1208 | |
1209 // Replace effect uses of node with the effect phi. | |
1210 NodeProperties::ReplaceWithValue(node, node, d.EffectPhi(load, effect)); | |
1211 | |
1212 d.OverwriteWithPhi(node, output_type, result, undefined); | |
1213 } | |
1214 } | |
1215 } | 1184 } |
1216 | 1185 |
1217 | 1186 |
1218 void SimplifiedLowering::DoStoreElement(Node* node) { | 1187 void SimplifiedLowering::DoStoreElement(Node* node) { |
1219 const ElementAccess& access = ElementAccessOf(node->op()); | 1188 const ElementAccess& access = ElementAccessOf(node->op()); |
1220 const Operator* op = machine()->Store(StoreRepresentation( | 1189 node->set_op(machine()->Store(StoreRepresentation( |
1221 access.machine_type, | 1190 access.machine_type, |
1222 ComputeWriteBarrierKind(access.base_is_tagged, access.machine_type, | 1191 ComputeWriteBarrierKind(access.base_is_tagged, access.machine_type, |
1223 access.type))); | 1192 access.type)))); |
1224 Node* key = node->InputAt(1); | 1193 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
1225 Node* index = ComputeIndex(access, key); | |
1226 if (access.bounds_check == kNoBoundsCheck) { | |
1227 node->set_op(op); | |
1228 node->ReplaceInput(1, index); | |
1229 node->RemoveInput(2); | |
1230 } else { | |
1231 DCHECK_EQ(kTypedArrayBoundsCheck, access.bounds_check); | |
1232 | |
1233 Node* base = node->InputAt(0); | |
1234 Node* length = node->InputAt(2); | |
1235 Node* value = node->InputAt(3); | |
1236 Node* effect = node->InputAt(4); | |
1237 Node* control = node->InputAt(5); | |
1238 Node* check = graph()->NewNode(machine()->Uint32LessThan(), key, length); | |
1239 | |
1240 IntPtrMatcher mbase(base); | |
1241 if (mbase.HasValue()) { | |
1242 Node* select = graph()->NewNode( | |
1243 common()->Select(kMachIntPtr, BranchHint::kTrue), check, index, | |
1244 jsgraph()->IntPtrConstant(AddressForOutOfBoundsStore() - | |
1245 mbase.Value())); | |
1246 | |
1247 node->set_op(op); | |
1248 node->ReplaceInput(1, select); | |
1249 node->RemoveInput(2); | |
1250 } else { | |
1251 Diamond d(graph(), common(), check, BranchHint::kTrue); | |
1252 d.Chain(control); | |
1253 Node* store = graph()->NewNode(op, base, index, value, effect, d.if_true); | |
1254 d.OverwriteWithEffectPhi(node, store, effect); | |
1255 } | |
1256 } | |
1257 } | 1194 } |
1258 | 1195 |
1259 | 1196 |
1260 void SimplifiedLowering::DoStringAdd(Node* node) { | 1197 void SimplifiedLowering::DoStringAdd(Node* node) { |
1261 Callable callable = CodeFactory::StringAdd( | 1198 Callable callable = CodeFactory::StringAdd( |
1262 zone()->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); | 1199 zone()->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); |
1263 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1200 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
1264 CallDescriptor* desc = | 1201 CallDescriptor* desc = |
1265 Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone()); | 1202 Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone()); |
1266 node->set_op(common()->Call(desc)); | 1203 node->set_op(common()->Call(desc)); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 | 1451 |
1515 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1452 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
1516 node->set_op(machine()->IntLessThanOrEqual()); | 1453 node->set_op(machine()->IntLessThanOrEqual()); |
1517 node->ReplaceInput(0, StringComparison(node, true)); | 1454 node->ReplaceInput(0, StringComparison(node, true)); |
1518 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1455 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
1519 } | 1456 } |
1520 | 1457 |
1521 } // namespace compiler | 1458 } // namespace compiler |
1522 } // namespace internal | 1459 } // namespace internal |
1523 } // namespace v8 | 1460 } // namespace v8 |
OLD | NEW |