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

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 2510553002: [turbofan] Specialize to (optimization time) known TypedArray instances. (Closed)
Patch Set: Created 4 years, 1 month 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/js-native-context-specialization.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/js-native-context-specialization.h" 5 #include "src/compiler/js-native-context-specialization.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/access-builder.h" 10 #include "src/compiler/access-builder.h"
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 // Monormorphic string access (ignoring the fact that there are multiple 164 // Monormorphic string access (ignoring the fact that there are multiple
165 // String maps). 165 // String maps).
166 receiver = effect = graph()->NewNode(simplified()->CheckString(), 166 receiver = effect = graph()->NewNode(simplified()->CheckString(),
167 receiver, effect, control); 167 receiver, effect, control);
168 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) { 168 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) {
169 // Monomorphic number access (we also deal with Smis here). 169 // Monomorphic number access (we also deal with Smis here).
170 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), 170 receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
171 receiver, effect, control); 171 receiver, effect, control);
172 } else { 172 } else {
173 // Monomorphic property access. 173 // Monomorphic property access.
174 receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(), 174 receiver = BuildCheckHeapObject(receiver, &effect, control);
175 receiver, effect, control);
176 effect = BuildCheckMaps(receiver, effect, control, 175 effect = BuildCheckMaps(receiver, effect, control,
177 access_info.receiver_maps()); 176 access_info.receiver_maps());
178 } 177 }
179 178
180 // Generate the actual property access. 179 // Generate the actual property access.
181 ValueEffectControl continuation = BuildPropertyAccess( 180 ValueEffectControl continuation = BuildPropertyAccess(
182 receiver, value, context, frame_state_lazy, effect, control, name, 181 receiver, value, context, frame_state_lazy, effect, control, name,
183 access_info, access_mode, language_mode, vector, slot); 182 access_info, access_mode, language_mode, vector, slot);
184 value = continuation.value(); 183 value = continuation.value();
185 effect = continuation.effect(); 184 effect = continuation.effect();
(...skipping 17 matching lines...) Expand all
203 // Ensure that {receiver} is a heap object. 202 // Ensure that {receiver} is a heap object.
204 Node* receiverissmi_control = nullptr; 203 Node* receiverissmi_control = nullptr;
205 Node* receiverissmi_effect = effect; 204 Node* receiverissmi_effect = effect;
206 if (receiverissmi_possible) { 205 if (receiverissmi_possible) {
207 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); 206 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
208 Node* branch = graph()->NewNode(common()->Branch(), check, control); 207 Node* branch = graph()->NewNode(common()->Branch(), check, control);
209 control = graph()->NewNode(common()->IfFalse(), branch); 208 control = graph()->NewNode(common()->IfFalse(), branch);
210 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); 209 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
211 receiverissmi_effect = effect; 210 receiverissmi_effect = effect;
212 } else { 211 } else {
213 receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(), 212 receiver = BuildCheckHeapObject(receiver, &effect, control);
214 receiver, effect, control);
215 } 213 }
216 214
217 // Load the {receiver} map. The resulting effect is the dominating effect 215 // Load the {receiver} map. The resulting effect is the dominating effect
218 // for all (polymorphic) branches. 216 // for all (polymorphic) branches.
219 Node* receiver_map = effect = 217 Node* receiver_map = effect =
220 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 218 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
221 receiver, effect, control); 219 receiver, effect, control);
222 220
223 // Generate code for the various different property access patterns. 221 // Generate code for the various different property access patterns.
224 Node* fallthrough_control = control; 222 Node* fallthrough_control = control;
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 } 511 }
514 } 512 }
515 513
516 // Install dependencies on the relevant prototype maps. 514 // Install dependencies on the relevant prototype maps.
517 for (Handle<Map> prototype_map : prototype_maps) { 515 for (Handle<Map> prototype_map : prototype_maps) {
518 dependencies()->AssumeMapStable(prototype_map); 516 dependencies()->AssumeMapStable(prototype_map);
519 } 517 }
520 } 518 }
521 519
522 // Ensure that {receiver} is a heap object. 520 // Ensure that {receiver} is a heap object.
523 receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(), 521 receiver = BuildCheckHeapObject(receiver, &effect, control);
524 receiver, effect, control);
525 522
526 // Check for the monomorphic case. 523 // Check for the monomorphic case.
527 if (access_infos.size() == 1) { 524 if (access_infos.size() == 1) {
528 ElementAccessInfo access_info = access_infos.front(); 525 ElementAccessInfo access_info = access_infos.front();
529 526
530 // Perform possible elements kind transitions. 527 // Perform possible elements kind transitions.
531 for (auto transition : access_info.transitions()) { 528 for (auto transition : access_info.transitions()) {
532 Handle<Map> const transition_source = transition.first; 529 Handle<Map> const transition_source = transition.first;
533 Handle<Map> const transition_target = transition.second; 530 Handle<Map> const transition_target = transition.second;
534 effect = graph()->NewNode( 531 effect = graph()->NewNode(
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 break; 1060 break;
1064 } 1061 }
1065 case MachineRepresentation::kTaggedSigned: { 1062 case MachineRepresentation::kTaggedSigned: {
1066 value = effect = graph()->NewNode(simplified()->CheckSmi(), value, 1063 value = effect = graph()->NewNode(simplified()->CheckSmi(), value,
1067 effect, control); 1064 effect, control);
1068 field_access.write_barrier_kind = kNoWriteBarrier; 1065 field_access.write_barrier_kind = kNoWriteBarrier;
1069 break; 1066 break;
1070 } 1067 }
1071 case MachineRepresentation::kTaggedPointer: { 1068 case MachineRepresentation::kTaggedPointer: {
1072 // Ensure that {value} is a HeapObject. 1069 // Ensure that {value} is a HeapObject.
1073 value = effect = graph()->NewNode(simplified()->CheckHeapObject(), 1070 value = BuildCheckHeapObject(value, &effect, control);
1074 value, effect, control);
1075 Handle<Map> field_map; 1071 Handle<Map> field_map;
1076 if (access_info.field_map().ToHandle(&field_map)) { 1072 if (access_info.field_map().ToHandle(&field_map)) {
1077 // Emit a map check for the value. 1073 // Emit a map check for the value.
1078 effect = graph()->NewNode(simplified()->CheckMaps(1), value, 1074 effect = graph()->NewNode(simplified()->CheckMaps(1), value,
1079 jsgraph()->HeapConstant(field_map), 1075 jsgraph()->HeapConstant(field_map),
1080 effect, control); 1076 effect, control);
1081 } 1077 }
1082 field_access.write_barrier_kind = kPointerWriteBarrier; 1078 field_access.write_barrier_kind = kPointerWriteBarrier;
1083 break; 1079 break;
1084 } 1080 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 JSNativeContextSpecialization::ValueEffectControl 1154 JSNativeContextSpecialization::ValueEffectControl
1159 JSNativeContextSpecialization::BuildElementAccess( 1155 JSNativeContextSpecialization::BuildElementAccess(
1160 Node* receiver, Node* index, Node* value, Node* effect, Node* control, 1156 Node* receiver, Node* index, Node* value, Node* effect, Node* control,
1161 ElementAccessInfo const& access_info, AccessMode access_mode, 1157 ElementAccessInfo const& access_info, AccessMode access_mode,
1162 KeyedAccessStoreMode store_mode) { 1158 KeyedAccessStoreMode store_mode) {
1163 // TODO(bmeurer): We currently specialize based on elements kind. We should 1159 // TODO(bmeurer): We currently specialize based on elements kind. We should
1164 // also be able to properly support strings and other JSObjects here. 1160 // also be able to properly support strings and other JSObjects here.
1165 ElementsKind elements_kind = access_info.elements_kind(); 1161 ElementsKind elements_kind = access_info.elements_kind();
1166 MapList const& receiver_maps = access_info.receiver_maps(); 1162 MapList const& receiver_maps = access_info.receiver_maps();
1167 1163
1168 // Load the elements for the {receiver}. 1164 if (IsFixedTypedArrayElementsKind(elements_kind)) {
1169 Node* elements = effect = graph()->NewNode( 1165 Node* buffer;
1170 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, 1166 Node* length;
1171 effect, control); 1167 Node* base_pointer;
1168 Node* external_pointer;
1172 1169
1173 // Don't try to store to a copy-on-write backing store. 1170 // Check if we can constant-fold information about the {receiver} (i.e.
1174 if (access_mode == AccessMode::kStore && 1171 // for asm.js-like code patterns).
1175 IsFastSmiOrObjectElementsKind(elements_kind) && 1172 HeapObjectMatcher m(receiver);
1176 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 1173 if (m.HasValue() && m.Value()->IsJSTypedArray()) {
1177 effect = 1174 Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(m.Value());
1178 graph()->NewNode(simplified()->CheckMaps(1), elements,
1179 jsgraph()->FixedArrayMapConstant(), effect, control);
1180 }
1181 1175
1182 if (IsFixedTypedArrayElementsKind(elements_kind)) { 1176 // Determine the {receiver}s (known) length.
1183 // Load the {receiver}s length. 1177 length = jsgraph()->Constant(typed_array->length_value());
1184 Node* length = effect = graph()->NewNode(
1185 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
1186 receiver, effect, control);
1187 1178
1188 // Check if the {receiver}s buffer was neutered. 1179 // Check if the {receiver}s buffer was neutered.
1189 Node* buffer = effect = graph()->NewNode( 1180 buffer = jsgraph()->HeapConstant(typed_array->GetBuffer());
1190 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), 1181
1191 receiver, effect, control); 1182 // Load the (known) base and external pointer for the {receiver}. The
1183 // {external_pointer} might be invalid if the {buffer} was neutered, so
1184 // we need to make sure that any access is properly guarded.
1185 base_pointer = jsgraph()->ZeroConstant();
1186 external_pointer = jsgraph()->PointerConstant(
1187 FixedTypedArrayBase::cast(typed_array->elements())
1188 ->external_pointer());
1189 } else {
1190 // Load the {receiver}s length.
1191 length = effect = graph()->NewNode(
1192 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
1193 receiver, effect, control);
1194
1195 // Load the buffer for the {receiver}.
1196 buffer = effect = graph()->NewNode(
1197 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
1198 receiver, effect, control);
1199
1200 // Load the elements for the {receiver}.
1201 Node* elements = effect = graph()->NewNode(
1202 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
1203 receiver, effect, control);
1204
1205 // Load the base and external pointer for the {receiver}s {elements}.
1206 base_pointer = effect = graph()->NewNode(
1207 simplified()->LoadField(
1208 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
1209 elements, effect, control);
1210 external_pointer = effect = graph()->NewNode(
1211 simplified()->LoadField(
1212 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
1213 elements, effect, control);
1214 }
1215
1216 // Default to zero if the {receiver}s buffer was neutered.
1192 Node* check = effect = graph()->NewNode( 1217 Node* check = effect = graph()->NewNode(
1193 simplified()->ArrayBufferWasNeutered(), buffer, effect, control); 1218 simplified()->ArrayBufferWasNeutered(), buffer, effect, control);
1194
1195 // Default to zero if the {receiver}s buffer was neutered.
1196 length = graph()->NewNode( 1219 length = graph()->NewNode(
1197 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse), 1220 common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
1198 check, jsgraph()->ZeroConstant(), length); 1221 check, jsgraph()->ZeroConstant(), length);
1199 1222
1200 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 1223 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1201 // Check that the {index} is a valid array index, we do the actual 1224 // Check that the {index} is a valid array index, we do the actual
1202 // bounds check below and just skip the store below if it's out of 1225 // bounds check below and just skip the store below if it's out of
1203 // bounds for the {receiver}. 1226 // bounds for the {receiver}.
1204 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, 1227 index = effect = graph()->NewNode(simplified()->CheckBounds(), index,
1205 jsgraph()->Constant(Smi::kMaxValue), 1228 jsgraph()->Constant(Smi::kMaxValue),
1206 effect, control); 1229 effect, control);
1207 } else { 1230 } else {
1208 // Check that the {index} is in the valid range for the {receiver}. 1231 // Check that the {index} is in the valid range for the {receiver}.
1209 DCHECK_EQ(STANDARD_STORE, store_mode); 1232 DCHECK_EQ(STANDARD_STORE, store_mode);
1210 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, 1233 index = effect = graph()->NewNode(simplified()->CheckBounds(), index,
1211 length, effect, control); 1234 length, effect, control);
1212 } 1235 }
1213 1236
1214 // Load the base and external pointer for the {receiver}.
1215 Node* base_pointer = effect = graph()->NewNode(
1216 simplified()->LoadField(
1217 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
1218 elements, effect, control);
1219 Node* external_pointer = effect = graph()->NewNode(
1220 simplified()->LoadField(
1221 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
1222 elements, effect, control);
1223
1224 // Access the actual element. 1237 // Access the actual element.
1225 ExternalArrayType external_array_type = 1238 ExternalArrayType external_array_type =
1226 GetArrayTypeFromElementsKind(elements_kind); 1239 GetArrayTypeFromElementsKind(elements_kind);
1227 switch (access_mode) { 1240 switch (access_mode) {
1228 case AccessMode::kLoad: { 1241 case AccessMode::kLoad: {
1229 value = effect = graph()->NewNode( 1242 value = effect = graph()->NewNode(
1230 simplified()->LoadTypedElement(external_array_type), buffer, 1243 simplified()->LoadTypedElement(external_array_type), buffer,
1231 base_pointer, external_pointer, index, effect, control); 1244 base_pointer, external_pointer, index, effect, control);
1232 break; 1245 break;
1233 } 1246 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 // Perform the actual store 1286 // Perform the actual store
1274 DCHECK_EQ(STANDARD_STORE, store_mode); 1287 DCHECK_EQ(STANDARD_STORE, store_mode);
1275 effect = graph()->NewNode( 1288 effect = graph()->NewNode(
1276 simplified()->StoreTypedElement(external_array_type), buffer, 1289 simplified()->StoreTypedElement(external_array_type), buffer,
1277 base_pointer, external_pointer, index, value, effect, control); 1290 base_pointer, external_pointer, index, value, effect, control);
1278 } 1291 }
1279 break; 1292 break;
1280 } 1293 }
1281 } 1294 }
1282 } else { 1295 } else {
1296 // Load the elements for the {receiver}.
1297 Node* elements = effect = graph()->NewNode(
1298 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
1299 effect, control);
1300
1301 // Don't try to store to a copy-on-write backing store.
1302 if (access_mode == AccessMode::kStore &&
1303 IsFastSmiOrObjectElementsKind(elements_kind) &&
1304 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1305 effect =
1306 graph()->NewNode(simplified()->CheckMaps(1), elements,
1307 jsgraph()->FixedArrayMapConstant(), effect, control);
1308 }
1309
1283 // Check if the {receiver} is a JSArray. 1310 // Check if the {receiver} is a JSArray.
1284 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps); 1311 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps);
1285 1312
1286 // Load the length of the {receiver}. 1313 // Load the length of the {receiver}.
1287 Node* length = effect = 1314 Node* length = effect =
1288 receiver_is_jsarray 1315 receiver_is_jsarray
1289 ? graph()->NewNode( 1316 ? graph()->NewNode(
1290 simplified()->LoadField( 1317 simplified()->LoadField(
1291 AccessBuilder::ForJSArrayLength(elements_kind)), 1318 AccessBuilder::ForJSArrayLength(elements_kind)),
1292 receiver, effect, control) 1319 receiver, effect, control)
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 inputs.push_back(control); 1488 inputs.push_back(control);
1462 1489
1463 Node* effect0; 1490 Node* effect0;
1464 Node* value0 = effect0 = 1491 Node* value0 = effect0 =
1465 graph()->NewNode(common()->Call(call_descriptor), 1492 graph()->NewNode(common()->Call(call_descriptor),
1466 static_cast<int>(inputs.size()), inputs.data()); 1493 static_cast<int>(inputs.size()), inputs.data());
1467 Node* control0 = graph()->NewNode(common()->IfSuccess(), value0); 1494 Node* control0 = graph()->NewNode(common()->IfSuccess(), value0);
1468 return ValueEffectControl(value0, effect0, control0); 1495 return ValueEffectControl(value0, effect0, control0);
1469 } 1496 }
1470 1497
1498 Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver,
1499 Node** effect,
1500 Node* control) {
1501 switch (receiver->opcode()) {
1502 case IrOpcode::kHeapConstant:
1503 case IrOpcode::kJSCreate:
1504 case IrOpcode::kJSCreateArguments:
1505 case IrOpcode::kJSCreateArray:
1506 case IrOpcode::kJSCreateClosure:
1507 case IrOpcode::kJSCreateIterResultObject:
1508 case IrOpcode::kJSCreateLiteralArray:
1509 case IrOpcode::kJSCreateLiteralObject:
1510 case IrOpcode::kJSCreateLiteralRegExp:
1511 case IrOpcode::kJSConvertReceiver:
1512 case IrOpcode::kJSToName:
1513 case IrOpcode::kJSToString:
1514 case IrOpcode::kJSToObject:
1515 case IrOpcode::kJSTypeOf: {
1516 return receiver;
1517 }
1518 default: {
1519 return *effect = graph()->NewNode(simplified()->CheckHeapObject(),
1520 receiver, *effect, control);
1521 }
1522 }
1523 }
1524
1471 Node* JSNativeContextSpecialization::BuildCheckMaps( 1525 Node* JSNativeContextSpecialization::BuildCheckMaps(
1472 Node* receiver, Node* effect, Node* control, 1526 Node* receiver, Node* effect, Node* control,
1473 std::vector<Handle<Map>> const& maps) { 1527 std::vector<Handle<Map>> const& maps) {
1474 HeapObjectMatcher m(receiver); 1528 HeapObjectMatcher m(receiver);
1475 if (m.HasValue()) { 1529 if (m.HasValue()) {
1476 Handle<Map> receiver_map(m.Value()->map(), isolate()); 1530 Handle<Map> receiver_map(m.Value()->map(), isolate());
1477 if (receiver_map->is_stable()) { 1531 if (receiver_map->is_stable()) {
1478 for (Handle<Map> map : maps) { 1532 for (Handle<Map> map : maps) {
1479 if (map.is_identical_to(receiver_map)) { 1533 if (map.is_identical_to(receiver_map)) {
1480 dependencies()->AssumeMapStable(receiver_map); 1534 dependencies()->AssumeMapStable(receiver_map);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1653 return jsgraph()->javascript(); 1707 return jsgraph()->javascript();
1654 } 1708 }
1655 1709
1656 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1710 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1657 return jsgraph()->simplified(); 1711 return jsgraph()->simplified();
1658 } 1712 }
1659 1713
1660 } // namespace compiler 1714 } // namespace compiler
1661 } // namespace internal 1715 } // namespace internal
1662 } // namespace v8 1716 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698