| 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> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 ProcessInput(node, 1, access.machine_type); | 757 ProcessInput(node, 1, access.machine_type); |
| 758 ProcessRemainingInputs(node, 2); | 758 ProcessRemainingInputs(node, 2); |
| 759 SetOutput(node, 0); | 759 SetOutput(node, 0); |
| 760 if (lower()) lowering->DoStoreField(node); | 760 if (lower()) lowering->DoStoreField(node); |
| 761 break; | 761 break; |
| 762 } | 762 } |
| 763 case IrOpcode::kLoadElement: { | 763 case IrOpcode::kLoadElement: { |
| 764 ElementAccess access = ElementAccessOf(node->op()); | 764 ElementAccess access = ElementAccessOf(node->op()); |
| 765 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 765 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); |
| 766 ProcessInput(node, 1, kMachInt32); // element index | 766 ProcessInput(node, 1, kMachInt32); // element index |
| 767 ProcessInput(node, 2, kMachInt32); // length | 767 ProcessRemainingInputs(node, 2); |
| 768 ProcessRemainingInputs(node, 3); | 768 SetOutput(node, access.machine_type); |
| 769 // Tagged overrides everything if we have to do a typed array bounds | 769 if (lower()) lowering->DoLoadElement(node); |
| 770 // check, because we may need to return undefined then. | |
| 771 MachineType output_type = | |
| 772 (access.bounds_check == kTypedArrayBoundsCheck && | |
| 773 (use & kRepTagged)) | |
| 774 ? kMachAnyTagged | |
| 775 : access.machine_type; | |
| 776 SetOutput(node, output_type); | |
| 777 if (lower()) lowering->DoLoadElement(node, output_type); | |
| 778 break; | 770 break; |
| 779 } | 771 } |
| 780 case IrOpcode::kStoreElement: { | 772 case IrOpcode::kStoreElement: { |
| 781 ElementAccess access = ElementAccessOf(node->op()); | 773 ElementAccess access = ElementAccessOf(node->op()); |
| 782 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); | 774 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); |
| 783 ProcessInput(node, 1, kMachInt32); // element index | 775 ProcessInput(node, 1, kMachInt32); // element index |
| 784 ProcessInput(node, 2, kMachInt32); // length | 776 ProcessInput(node, 2, access.machine_type); |
| 785 ProcessInput(node, 3, access.machine_type); | 777 ProcessRemainingInputs(node, 3); |
| 778 SetOutput(node, 0); |
| 779 if (lower()) lowering->DoStoreElement(node); |
| 780 break; |
| 781 } |
| 782 case IrOpcode::kLoadBuffer: { |
| 783 BufferAccess const access = BufferAccessOf(node->op()); |
| 784 ProcessInput(node, 0, kMachPtr); // buffer |
| 785 ProcessInput(node, 1, kMachInt32); // offset |
| 786 ProcessInput(node, 2, kMachUint32); // length |
| 787 ProcessRemainingInputs(node, 3); |
| 788 // Tagged overrides everything, because we may need to return undefined. |
| 789 MachineType const output_type = |
| 790 (use & kRepTagged) ? kMachAnyTagged : access.machine_type(); |
| 791 SetOutput(node, output_type); |
| 792 if (lower()) lowering->DoLoadBuffer(node, output_type); |
| 793 break; |
| 794 } |
| 795 case IrOpcode::kStoreBuffer: { |
| 796 BufferAccess const access = BufferAccessOf(node->op()); |
| 797 ProcessInput(node, 0, kMachPtr); // buffer |
| 798 ProcessInput(node, 1, kMachInt32); // offset |
| 799 ProcessInput(node, 2, kMachUint32); // length |
| 800 ProcessInput(node, 3, access.machine_type()); // value |
| 786 ProcessRemainingInputs(node, 4); | 801 ProcessRemainingInputs(node, 4); |
| 787 SetOutput(node, 0); | 802 SetOutput(node, 0); |
| 788 if (lower()) lowering->DoStoreElement(node); | 803 if (lower()) lowering->DoStoreBuffer(node); |
| 804 break; |
| 805 } |
| 806 case IrOpcode::kBoundsCheck: { |
| 807 ProcessInput(node, 0, kRepWord32); |
| 808 ProcessInput(node, 1, kMachUint32); |
| 809 SetOutput(node, kMachUint32); |
| 789 break; | 810 break; |
| 790 } | 811 } |
| 791 case IrOpcode::kObjectIsSmi: { | 812 case IrOpcode::kObjectIsSmi: { |
| 792 ProcessInput(node, 0, kMachAnyTagged); | 813 ProcessInput(node, 0, kMachAnyTagged); |
| 793 SetOutput(node, kRepBit | kTypeBool); | 814 SetOutput(node, kRepBit | kTypeBool); |
| 794 if (lower()) { | 815 if (lower()) { |
| 795 Node* is_tagged = jsgraph_->graph()->NewNode( | 816 Node* is_tagged = jsgraph_->graph()->NewNode( |
| 796 jsgraph_->machine()->WordAnd(), node->InputAt(0), | 817 jsgraph_->machine()->WordAnd(), node->InputAt(0), |
| 797 jsgraph_->Int32Constant(static_cast<int>(kSmiTagMask))); | 818 jsgraph_->Int32Constant(static_cast<int>(kSmiTagMask))); |
| 798 Node* is_smi = jsgraph_->graph()->NewNode( | 819 Node* is_smi = jsgraph_->graph()->NewNode( |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 | 1045 |
| 1025 Node* SimplifiedLowering::IsTagged(Node* node) { | 1046 Node* SimplifiedLowering::IsTagged(Node* node) { |
| 1026 // TODO(titzer): factor this out to a TaggingScheme abstraction. | 1047 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 1027 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. | 1048 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. |
| 1028 return graph()->NewNode(machine()->WordAnd(), node, | 1049 return graph()->NewNode(machine()->WordAnd(), node, |
| 1029 jsgraph()->Int32Constant(kSmiTagMask)); | 1050 jsgraph()->Int32Constant(kSmiTagMask)); |
| 1030 } | 1051 } |
| 1031 | 1052 |
| 1032 | 1053 |
| 1033 void SimplifiedLowering::LowerAllNodes() { | 1054 void SimplifiedLowering::LowerAllNodes() { |
| 1034 SimplifiedOperatorBuilder simplified(graph()->zone()); | 1055 RepresentationChanger changer(jsgraph(), simplified(), |
| 1035 RepresentationChanger changer(jsgraph(), &simplified, | |
| 1036 graph()->zone()->isolate()); | 1056 graph()->zone()->isolate()); |
| 1037 RepresentationSelector selector(jsgraph(), zone(), &changer); | 1057 RepresentationSelector selector(jsgraph(), zone(), &changer); |
| 1038 selector.Run(this); | 1058 selector.Run(this); |
| 1039 } | 1059 } |
| 1040 | 1060 |
| 1041 | 1061 |
| 1042 Node* SimplifiedLowering::Untag(Node* node) { | 1062 Node* SimplifiedLowering::Untag(Node* node) { |
| 1043 // TODO(titzer): factor this out to a TaggingScheme abstraction. | 1063 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 1044 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); | 1064 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); |
| 1045 return graph()->NewNode(machine()->WordSar(), node, shift_amount); | 1065 return graph()->NewNode(machine()->WordSar(), node, shift_amount); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 WriteBarrierKind kind = ComputeWriteBarrierKind( | 1104 WriteBarrierKind kind = ComputeWriteBarrierKind( |
| 1085 access.base_is_tagged, access.machine_type, access.type); | 1105 access.base_is_tagged, access.machine_type, access.type); |
| 1086 node->set_op( | 1106 node->set_op( |
| 1087 machine()->Store(StoreRepresentation(access.machine_type, kind))); | 1107 machine()->Store(StoreRepresentation(access.machine_type, kind))); |
| 1088 Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); | 1108 Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); |
| 1089 node->InsertInput(graph()->zone(), 1, offset); | 1109 node->InsertInput(graph()->zone(), 1, offset); |
| 1090 } | 1110 } |
| 1091 | 1111 |
| 1092 | 1112 |
| 1093 Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, | 1113 Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, |
| 1094 Node* const key) { | 1114 Node* key) { |
| 1095 Node* index = key; | 1115 Node* index = key; |
| 1096 const int element_size_shift = ElementSizeLog2Of(access.machine_type); | 1116 const int element_size_shift = ElementSizeLog2Of(access.machine_type); |
| 1097 if (element_size_shift) { | 1117 if (element_size_shift) { |
| 1098 index = graph()->NewNode(machine()->Word32Shl(), index, | 1118 index = graph()->NewNode(machine()->Word32Shl(), index, |
| 1099 jsgraph()->Int32Constant(element_size_shift)); | 1119 jsgraph()->Int32Constant(element_size_shift)); |
| 1100 } | 1120 } |
| 1101 const int fixed_offset = access.header_size - access.tag(); | 1121 const int fixed_offset = access.header_size - access.tag(); |
| 1102 if (fixed_offset) { | 1122 if (fixed_offset) { |
| 1103 index = graph()->NewNode(machine()->Int32Add(), index, | 1123 index = graph()->NewNode(machine()->Int32Add(), index, |
| 1104 jsgraph()->Int32Constant(fixed_offset)); | 1124 jsgraph()->Int32Constant(fixed_offset)); |
| 1105 } | 1125 } |
| 1106 if (machine()->Is64()) { | 1126 if (machine()->Is64()) { |
| 1127 index = graph()->NewNode(machine()->ChangeInt32ToInt64(), index); |
| 1128 } |
| 1129 return index; |
| 1130 } |
| 1131 |
| 1132 |
| 1133 Node* SimplifiedLowering::ComputeOffset(const BufferAccess& access, |
| 1134 Node* offset) { |
| 1135 int const element_size = ElementSizeOf(access.machine_type()); |
| 1136 DCHECK_LE(1, element_size); |
| 1137 if (element_size > 1) { |
| 1138 offset = graph()->NewNode(machine()->Word32And(), offset, |
| 1139 jsgraph()->Int32Constant(~(element_size - 1))); |
| 1140 } |
| 1141 if (machine()->Is64()) { |
| 1107 // TODO(turbofan): This is probably only correct for typed arrays, and only | 1142 // 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 | 1143 // if the typed arrays are at most 2GiB in size, which happens to match |
| 1109 // exactly our current situation. | 1144 // exactly our current situation. |
| 1110 index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index); | 1145 offset = graph()->NewNode(machine()->ChangeUint32ToUint64(), offset); |
| 1111 } | 1146 } |
| 1112 return index; | 1147 return offset; |
| 1113 } | 1148 } |
| 1114 | 1149 |
| 1115 | 1150 |
| 1116 namespace { | 1151 void SimplifiedLowering::DoLoadElement(Node* node) { |
| 1117 | |
| 1118 intptr_t AddressForOutOfBoundsLoad(MachineType type) { | |
| 1119 switch (RepresentationOf(type)) { | |
| 1120 case kRepFloat32: { | |
| 1121 static const float dummy = std::numeric_limits<float>::quiet_NaN(); | |
| 1122 return bit_cast<intptr_t>(&dummy); | |
| 1123 } | |
| 1124 case kRepFloat64: { | |
| 1125 static const double dummy = std::numeric_limits<double>::quiet_NaN(); | |
| 1126 return bit_cast<intptr_t>(&dummy); | |
| 1127 } | |
| 1128 case kRepBit: | |
| 1129 case kRepWord8: | |
| 1130 case kRepWord16: | |
| 1131 case kRepWord32: { | |
| 1132 static const int32_t dummy = 0; | |
| 1133 return bit_cast<intptr_t>(&dummy); | |
| 1134 } | |
| 1135 default: | |
| 1136 break; | |
| 1137 } | |
| 1138 UNREACHABLE(); | |
| 1139 return 0; | |
| 1140 } | |
| 1141 | |
| 1142 | |
| 1143 intptr_t AddressForOutOfBoundsStore() { | |
| 1144 static volatile double dummy = 0; | |
| 1145 return bit_cast<intptr_t>(&dummy); | |
| 1146 } | |
| 1147 | |
| 1148 } // namespace | |
| 1149 | |
| 1150 | |
| 1151 void SimplifiedLowering::DoLoadElement(Node* node, MachineType output_type) { | |
| 1152 const ElementAccess& access = ElementAccessOf(node->op()); | 1152 const ElementAccess& access = ElementAccessOf(node->op()); |
| 1153 const Operator* op = machine()->Load(access.machine_type); | |
| 1154 Node* key = node->InputAt(1); | 1153 Node* key = node->InputAt(1); |
| 1155 Node* index = ComputeIndex(access, key); | 1154 Node* index = ComputeIndex(access, key); |
| 1156 Node* effect = node->InputAt(3); | 1155 node->set_op(machine()->Load(access.machine_type)); |
| 1157 if (access.bounds_check == kNoBoundsCheck) { | 1156 node->ReplaceInput(1, index); |
| 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 } | 1157 } |
| 1216 | 1158 |
| 1217 | 1159 |
| 1218 void SimplifiedLowering::DoStoreElement(Node* node) { | 1160 void SimplifiedLowering::DoStoreElement(Node* node) { |
| 1219 const ElementAccess& access = ElementAccessOf(node->op()); | 1161 const ElementAccess& access = ElementAccessOf(node->op()); |
| 1220 const Operator* op = machine()->Store(StoreRepresentation( | 1162 Node* key = node->InputAt(1); |
| 1163 Node* index = ComputeIndex(access, key); |
| 1164 node->set_op(machine()->Store(StoreRepresentation( |
| 1221 access.machine_type, | 1165 access.machine_type, |
| 1222 ComputeWriteBarrierKind(access.base_is_tagged, access.machine_type, | 1166 ComputeWriteBarrierKind(access.base_is_tagged, access.machine_type, |
| 1223 access.type))); | 1167 access.type)))); |
| 1224 Node* key = node->InputAt(1); | 1168 node->ReplaceInput(1, index); |
| 1225 Node* index = ComputeIndex(access, key); | 1169 } |
| 1226 if (access.bounds_check == kNoBoundsCheck) { | 1170 |
| 1227 node->set_op(op); | 1171 |
| 1228 node->ReplaceInput(1, index); | 1172 void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type) { |
| 1173 BufferAccess const access = BufferAccessOf(node->op()); |
| 1174 Node* buffer = node->InputAt(0); |
| 1175 Node* offset = node->InputAt(1); |
| 1176 Node* length = node->InputAt(2); |
| 1177 Node* effect = node->InputAt(3); |
| 1178 Node* control = node->InputAt(4); |
| 1179 size_t const element_size = ElementSizeOf(access.machine_type()); |
| 1180 if (output_type & kRepTagged || access.guard_size() < element_size) { |
| 1181 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); |
| 1182 Node* branch = |
| 1183 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
| 1184 |
| 1185 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 1186 Node* vtrue = |
| 1187 graph()->NewNode(machine()->Load(access.machine_type()), buffer, |
| 1188 ComputeOffset(access, offset), effect, if_true); |
| 1189 Node* etrue = vtrue; |
| 1190 if (output_type & kRepTagged) { |
| 1191 // TODO(turbofan): This is ugly as hell! |
| 1192 RepresentationChanger changer(jsgraph(), simplified(), |
| 1193 graph()->zone()->isolate()); |
| 1194 vtrue = changer.GetTaggedRepresentationFor(vtrue, access.machine_type()); |
| 1195 } |
| 1196 |
| 1197 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 1198 Node* vfalse; |
| 1199 // TODO(bmeurer): Refactor this into a separate method. |
| 1200 if (output_type & kRepTagged) { |
| 1201 DCHECK_EQ(0, access.machine_type() & kRepTagged); |
| 1202 vfalse = jsgraph()->UndefinedConstant(); |
| 1203 } else if (output_type & kRepFloat32) { |
| 1204 vfalse = |
| 1205 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN()); |
| 1206 } else if (output_type & kRepFloat64) { |
| 1207 vfalse = |
| 1208 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); |
| 1209 } else { |
| 1210 vfalse = jsgraph()->Int32Constant(0); |
| 1211 } |
| 1212 Node* efalse = effect; |
| 1213 |
| 1214 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 1215 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); |
| 1216 |
| 1217 // Replace effect uses of {node} with the EffectPhi {ephi}. |
| 1218 NodeProperties::ReplaceWithValue(node, node, ephi); |
| 1219 |
| 1220 // Turn the {node} into a Phi. |
| 1221 node->set_op(common()->Phi(output_type, 2)); |
| 1222 node->ReplaceInput(0, vtrue); |
| 1223 node->ReplaceInput(1, vfalse); |
| 1224 node->ReplaceInput(2, merge); |
| 1225 node->TrimInputCount(3); |
| 1226 } else { |
| 1227 offset = graph()->NewNode( |
| 1228 simplified()->BoundsCheck(access.guard_size() - element_size), offset, |
| 1229 length); |
| 1230 node->set_op(machine()->Load(access.machine_type())); |
| 1231 DCHECK_EQ(buffer, node->InputAt(0)); |
| 1232 node->ReplaceInput(1, ComputeOffset(access, offset)); |
| 1229 node->RemoveInput(2); | 1233 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 } | 1234 } |
| 1257 } | 1235 } |
| 1258 | 1236 |
| 1237 |
| 1238 void SimplifiedLowering::DoStoreBuffer(Node* node) { |
| 1239 BufferAccess const access = BufferAccessOf(node->op()); |
| 1240 Node* buffer = node->InputAt(0); |
| 1241 Node* offset = node->InputAt(1); |
| 1242 Node* length = node->InputAt(2); |
| 1243 Node* value = node->InputAt(3); |
| 1244 Node* effect = node->InputAt(4); |
| 1245 Node* control = node->InputAt(5); |
| 1246 size_t const element_size = ElementSizeOf(access.machine_type()); |
| 1247 if (access.guard_size() < element_size) { |
| 1248 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); |
| 1249 Node* branch = |
| 1250 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
| 1251 |
| 1252 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| 1253 Node* etrue = graph()->NewNode(machine()->Store(StoreRepresentation( |
| 1254 access.machine_type(), kNoWriteBarrier)), |
| 1255 buffer, ComputeOffset(access, offset), value, |
| 1256 effect, if_true); |
| 1257 |
| 1258 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 1259 Node* efalse = effect; |
| 1260 |
| 1261 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 1262 |
| 1263 // Turn the {node} into an EffectPhi. |
| 1264 node->set_op(common()->EffectPhi(2)); |
| 1265 node->ReplaceInput(0, etrue); |
| 1266 node->ReplaceInput(1, efalse); |
| 1267 node->ReplaceInput(2, merge); |
| 1268 node->TrimInputCount(3); |
| 1269 } else { |
| 1270 offset = graph()->NewNode( |
| 1271 simplified()->BoundsCheck(access.guard_size() - element_size), offset, |
| 1272 length); |
| 1273 node->set_op(machine()->Store( |
| 1274 StoreRepresentation(access.machine_type(), kNoWriteBarrier))); |
| 1275 node->ReplaceInput(1, ComputeOffset(access, offset)); |
| 1276 node->RemoveInput(2); |
| 1277 } |
| 1278 } |
| 1279 |
| 1259 | 1280 |
| 1260 void SimplifiedLowering::DoStringAdd(Node* node) { | 1281 void SimplifiedLowering::DoStringAdd(Node* node) { |
| 1261 Callable callable = CodeFactory::StringAdd( | 1282 Callable callable = CodeFactory::StringAdd( |
| 1262 zone()->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); | 1283 zone()->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); |
| 1263 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1284 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 1264 CallDescriptor* desc = | 1285 CallDescriptor* desc = |
| 1265 Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone()); | 1286 Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone()); |
| 1266 node->set_op(common()->Call(desc)); | 1287 node->set_op(common()->Call(desc)); |
| 1267 node->InsertInput(graph()->zone(), 0, | 1288 node->InsertInput(graph()->zone(), 0, |
| 1268 jsgraph()->HeapConstant(callable.code())); | 1289 jsgraph()->HeapConstant(callable.code())); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 | 1535 |
| 1515 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1536 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
| 1516 node->set_op(machine()->IntLessThanOrEqual()); | 1537 node->set_op(machine()->IntLessThanOrEqual()); |
| 1517 node->ReplaceInput(0, StringComparison(node, true)); | 1538 node->ReplaceInput(0, StringComparison(node, true)); |
| 1518 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1539 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 1519 } | 1540 } |
| 1520 | 1541 |
| 1521 } // namespace compiler | 1542 } // namespace compiler |
| 1522 } // namespace internal | 1543 } // namespace internal |
| 1523 } // namespace v8 | 1544 } // namespace v8 |
| OLD | NEW |