OLD | NEW |
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 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || | 419 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || |
420 node->opcode() == IrOpcode::kJSStoreProperty); | 420 node->opcode() == IrOpcode::kJSStoreProperty); |
421 Node* receiver = NodeProperties::GetValueInput(node, 0); | 421 Node* receiver = NodeProperties::GetValueInput(node, 0); |
422 Node* effect = NodeProperties::GetEffectInput(node); | 422 Node* effect = NodeProperties::GetEffectInput(node); |
423 Node* control = NodeProperties::GetControlInput(node); | 423 Node* control = NodeProperties::GetControlInput(node); |
424 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | 424 Node* frame_state = NodeProperties::FindFrameStateBefore(node); |
425 | 425 |
426 // Not much we can do if deoptimization support is disabled. | 426 // Not much we can do if deoptimization support is disabled. |
427 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 427 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
428 | 428 |
429 // TODO(bmeurer): Add support for non-standard stores. | |
430 if (store_mode != STANDARD_STORE && | |
431 store_mode != STORE_NO_TRANSITION_HANDLE_COW && | |
432 store_mode != STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | |
433 return NoChange(); | |
434 } | |
435 | |
436 // Retrieve the native context from the given {node}. | 429 // Retrieve the native context from the given {node}. |
437 Handle<Context> native_context; | 430 Handle<Context> native_context; |
438 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); | 431 if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange(); |
439 | 432 |
440 // Compute element access infos for the receiver maps. | 433 // Compute element access infos for the receiver maps. |
441 AccessInfoFactory access_info_factory(dependencies(), native_context, | 434 AccessInfoFactory access_info_factory(dependencies(), native_context, |
442 graph()->zone()); | 435 graph()->zone()); |
443 ZoneVector<ElementAccessInfo> access_infos(zone()); | 436 ZoneVector<ElementAccessInfo> access_infos(zone()); |
444 if (!access_info_factory.ComputeElementAccessInfos(receiver_maps, access_mode, | 437 if (!access_info_factory.ComputeElementAccessInfos(receiver_maps, access_mode, |
445 &access_infos)) { | 438 &access_infos)) { |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1061 // Perform the actual store | 1054 // Perform the actual store |
1062 DCHECK_EQ(STANDARD_STORE, store_mode); | 1055 DCHECK_EQ(STANDARD_STORE, store_mode); |
1063 effect = graph()->NewNode( | 1056 effect = graph()->NewNode( |
1064 simplified()->StoreTypedElement(external_array_type), buffer, | 1057 simplified()->StoreTypedElement(external_array_type), buffer, |
1065 base_pointer, external_pointer, index, value, effect, control); | 1058 base_pointer, external_pointer, index, value, effect, control); |
1066 } | 1059 } |
1067 break; | 1060 break; |
1068 } | 1061 } |
1069 } | 1062 } |
1070 } else { | 1063 } else { |
1071 // TODO(turbofan): Add support for additional store modes. | 1064 // Check if the {receiver} is a JSArray. |
1072 DCHECK(store_mode == STANDARD_STORE || | 1065 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps); |
1073 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | |
1074 | 1066 |
1075 // Load the length of the {receiver}. | 1067 // Load the length of the {receiver}. |
1076 Node* length = effect = | 1068 Node* length = effect = |
1077 HasOnlyJSArrayMaps(receiver_maps) | 1069 receiver_is_jsarray |
1078 ? graph()->NewNode( | 1070 ? graph()->NewNode( |
1079 simplified()->LoadField( | 1071 simplified()->LoadField( |
1080 AccessBuilder::ForJSArrayLength(elements_kind)), | 1072 AccessBuilder::ForJSArrayLength(elements_kind)), |
1081 receiver, effect, control) | 1073 receiver, effect, control) |
1082 : graph()->NewNode( | 1074 : graph()->NewNode( |
1083 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), | 1075 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), |
1084 elements, effect, control); | 1076 elements, effect, control); |
1085 | 1077 |
1086 // Check that the {index} is in the valid range for the {receiver}. | 1078 // Check if we might need to grow the {elements} backing store. |
1087 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, | 1079 if (IsGrowStoreMode(store_mode)) { |
1088 length, effect, control); | 1080 DCHECK_EQ(AccessMode::kStore, access_mode); |
| 1081 |
| 1082 // Check that the {index} is a valid array index; the actual checking |
| 1083 // happens below right before the element store. |
| 1084 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, |
| 1085 jsgraph()->Constant(Smi::kMaxValue), |
| 1086 effect, control); |
| 1087 } else { |
| 1088 // Check that the {index} is in the valid range for the {receiver}. |
| 1089 index = effect = graph()->NewNode(simplified()->CheckBounds(), index, |
| 1090 length, effect, control); |
| 1091 } |
1089 | 1092 |
1090 // Compute the element access. | 1093 // Compute the element access. |
1091 Type* element_type = Type::Any(); | 1094 Type* element_type = Type::Any(); |
1092 MachineType element_machine_type = MachineType::AnyTagged(); | 1095 MachineType element_machine_type = MachineType::AnyTagged(); |
1093 if (IsFastDoubleElementsKind(elements_kind)) { | 1096 if (IsFastDoubleElementsKind(elements_kind)) { |
1094 element_type = Type::Number(); | 1097 element_type = Type::Number(); |
1095 element_machine_type = MachineType::Float64(); | 1098 element_machine_type = MachineType::Float64(); |
1096 } else if (IsFastSmiElementsKind(elements_kind)) { | 1099 } else if (IsFastSmiElementsKind(elements_kind)) { |
1097 element_type = type_cache_.kSmi; | 1100 element_type = type_cache_.kSmi; |
1098 } | 1101 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 // Make sure we do not store signalling NaNs into double arrays. | 1153 // Make sure we do not store signalling NaNs into double arrays. |
1151 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); | 1154 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); |
1152 } | 1155 } |
1153 | 1156 |
1154 // Ensure that copy-on-write backing store is writable. | 1157 // Ensure that copy-on-write backing store is writable. |
1155 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 1158 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
1156 store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1159 store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
1157 elements = effect = | 1160 elements = effect = |
1158 graph()->NewNode(simplified()->EnsureWritableFastElements(), | 1161 graph()->NewNode(simplified()->EnsureWritableFastElements(), |
1159 receiver, elements, effect, control); | 1162 receiver, elements, effect, control); |
| 1163 } else if (IsGrowStoreMode(store_mode)) { |
| 1164 // Grow {elements} backing store if necessary. Also updates the |
| 1165 // "length" property for JSArray {receiver}s, hence there must |
| 1166 // not be any other check after this operation, as the write |
| 1167 // to the "length" property is observable. |
| 1168 GrowFastElementsFlags flags = GrowFastElementsFlag::kNone; |
| 1169 if (receiver_is_jsarray) { |
| 1170 flags |= GrowFastElementsFlag::kArrayObject; |
| 1171 } |
| 1172 if (IsHoleyElementsKind(elements_kind)) { |
| 1173 flags |= GrowFastElementsFlag::kHoleyElements; |
| 1174 } |
| 1175 if (IsFastDoubleElementsKind(elements_kind)) { |
| 1176 flags |= GrowFastElementsFlag::kDoubleElements; |
| 1177 } |
| 1178 elements = effect = graph()->NewNode( |
| 1179 simplified()->MaybeGrowFastElements(flags), receiver, elements, |
| 1180 index, length, effect, control); |
1160 } | 1181 } |
1161 | 1182 |
1162 // Perform the actual element access. | 1183 // Perform the actual element access. |
1163 effect = graph()->NewNode(simplified()->StoreElement(element_access), | 1184 effect = graph()->NewNode(simplified()->StoreElement(element_access), |
1164 elements, index, value, effect, control); | 1185 elements, index, value, effect, control); |
1165 } | 1186 } |
1166 } | 1187 } |
1167 | 1188 |
1168 return ValueEffectControl(value, effect, control); | 1189 return ValueEffectControl(value, effect, control); |
1169 } | 1190 } |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 } | 1417 } |
1397 | 1418 |
1398 | 1419 |
1399 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1420 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
1400 return jsgraph()->simplified(); | 1421 return jsgraph()->simplified(); |
1401 } | 1422 } |
1402 | 1423 |
1403 } // namespace compiler | 1424 } // namespace compiler |
1404 } // namespace internal | 1425 } // namespace internal |
1405 } // namespace v8 | 1426 } // namespace v8 |
OLD | NEW |