Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 763963002: [turbofan] Add checked load/store operators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Reapply fix. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/simplified-lowering.h ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/simplified-lowering.h ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698