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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 // Monormorphic string access (ignoring the fact that there are multiple | 161 // Monormorphic string access (ignoring the fact that there are multiple |
162 // String maps). | 162 // String maps). |
163 receiver = effect = graph()->NewNode(simplified()->CheckString(), | 163 receiver = effect = graph()->NewNode(simplified()->CheckString(), |
164 receiver, effect, control); | 164 receiver, effect, control); |
165 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) { | 165 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) { |
166 // Monomorphic number access (we also deal with Smis here). | 166 // Monomorphic number access (we also deal with Smis here). |
167 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), | 167 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), |
168 receiver, effect, control); | 168 receiver, effect, control); |
169 } else { | 169 } else { |
170 // Monomorphic property access. | 170 // Monomorphic property access. |
171 effect = BuildCheckTaggedPointer(receiver, effect, control); | 171 effect = BuildCheckHeapObject(receiver, effect, control); |
172 effect = BuildCheckMaps(receiver, effect, control, | 172 effect = BuildCheckMaps(receiver, effect, control, |
173 access_info.receiver_maps()); | 173 access_info.receiver_maps()); |
174 } | 174 } |
175 | 175 |
176 // Generate the actual property access. | 176 // Generate the actual property access. |
177 ValueEffectControl continuation = BuildPropertyAccess( | 177 ValueEffectControl continuation = BuildPropertyAccess( |
178 receiver, value, context, frame_state_lazy, effect, control, name, | 178 receiver, value, context, frame_state_lazy, effect, control, name, |
179 native_context, access_info, access_mode); | 179 native_context, access_info, access_mode); |
180 value = continuation.value(); | 180 value = continuation.value(); |
181 effect = continuation.effect(); | 181 effect = continuation.effect(); |
(...skipping 17 matching lines...) Expand all Loading... |
199 // Ensure that {receiver} is a heap object. | 199 // Ensure that {receiver} is a heap object. |
200 Node* receiverissmi_control = nullptr; | 200 Node* receiverissmi_control = nullptr; |
201 Node* receiverissmi_effect = effect; | 201 Node* receiverissmi_effect = effect; |
202 if (receiverissmi_possible) { | 202 if (receiverissmi_possible) { |
203 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); | 203 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); |
204 Node* branch = graph()->NewNode(common()->Branch(), check, control); | 204 Node* branch = graph()->NewNode(common()->Branch(), check, control); |
205 control = graph()->NewNode(common()->IfFalse(), branch); | 205 control = graph()->NewNode(common()->IfFalse(), branch); |
206 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); | 206 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); |
207 receiverissmi_effect = effect; | 207 receiverissmi_effect = effect; |
208 } else { | 208 } else { |
209 effect = BuildCheckTaggedPointer(receiver, effect, control); | 209 effect = BuildCheckHeapObject(receiver, effect, control); |
210 } | 210 } |
211 | 211 |
212 // Load the {receiver} map. The resulting effect is the dominating effect | 212 // Load the {receiver} map. The resulting effect is the dominating effect |
213 // for all (polymorphic) branches. | 213 // for all (polymorphic) branches. |
214 Node* receiver_map = effect = | 214 Node* receiver_map = effect = |
215 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 215 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
216 receiver, effect, control); | 216 receiver, effect, control); |
217 | 217 |
218 // Generate code for the various different property access patterns. | 218 // Generate code for the various different property access patterns. |
219 Node* fallthrough_control = control; | 219 Node* fallthrough_control = control; |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 503 } |
504 } | 504 } |
505 | 505 |
506 // Install dependencies on the relevant prototype maps. | 506 // Install dependencies on the relevant prototype maps. |
507 for (Handle<Map> prototype_map : prototype_maps) { | 507 for (Handle<Map> prototype_map : prototype_maps) { |
508 dependencies()->AssumeMapStable(prototype_map); | 508 dependencies()->AssumeMapStable(prototype_map); |
509 } | 509 } |
510 } | 510 } |
511 | 511 |
512 // Ensure that {receiver} is a heap object. | 512 // Ensure that {receiver} is a heap object. |
513 effect = BuildCheckTaggedPointer(receiver, effect, control); | 513 effect = BuildCheckHeapObject(receiver, effect, control); |
514 | 514 |
515 // Check for the monomorphic case. | 515 // Check for the monomorphic case. |
516 if (access_infos.size() == 1) { | 516 if (access_infos.size() == 1) { |
517 ElementAccessInfo access_info = access_infos.front(); | 517 ElementAccessInfo access_info = access_infos.front(); |
518 | 518 |
519 // Perform possible elements kind transitions. | 519 // Perform possible elements kind transitions. |
520 for (auto transition : access_info.transitions()) { | 520 for (auto transition : access_info.transitions()) { |
521 Handle<Map> const transition_source = transition.first; | 521 Handle<Map> const transition_source = transition.first; |
522 Handle<Map> const transition_target = transition.second; | 522 Handle<Map> const transition_target = transition.second; |
523 effect = graph()->NewNode( | 523 effect = graph()->NewNode( |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 graph()->NewNode(simplified()->LoadField(storage_access), | 964 graph()->NewNode(simplified()->LoadField(storage_access), |
965 storage, effect, control); | 965 storage, effect, control); |
966 field_access.offset = HeapNumber::kValueOffset; | 966 field_access.offset = HeapNumber::kValueOffset; |
967 field_access.name = MaybeHandle<Name>(); | 967 field_access.name = MaybeHandle<Name>(); |
968 field_access.machine_type = MachineType::Float64(); | 968 field_access.machine_type = MachineType::Float64(); |
969 } | 969 } |
970 } | 970 } |
971 break; | 971 break; |
972 } | 972 } |
973 case MachineRepresentation::kTaggedSigned: { | 973 case MachineRepresentation::kTaggedSigned: { |
974 value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(), | 974 value = effect = graph()->NewNode(simplified()->CheckSmi(), value, |
975 value, effect, control); | 975 effect, control); |
976 field_access.write_barrier_kind = kNoWriteBarrier; | 976 field_access.write_barrier_kind = kNoWriteBarrier; |
977 break; | 977 break; |
978 } | 978 } |
979 case MachineRepresentation::kTaggedPointer: { | 979 case MachineRepresentation::kTaggedPointer: { |
980 // Ensure that {value} is a HeapObject. | 980 // Ensure that {value} is a HeapObject. |
981 value = effect = graph()->NewNode(simplified()->CheckTaggedPointer(), | 981 value = effect = graph()->NewNode(simplified()->CheckHeapObject(), |
982 value, effect, control); | 982 value, effect, control); |
983 Handle<Map> field_map; | 983 Handle<Map> field_map; |
984 if (access_info.field_map().ToHandle(&field_map)) { | 984 if (access_info.field_map().ToHandle(&field_map)) { |
985 // Emit a map check for the value. | 985 // Emit a map check for the value. |
986 effect = graph()->NewNode(simplified()->CheckMaps(1), value, | 986 effect = graph()->NewNode(simplified()->CheckMaps(1), value, |
987 jsgraph()->HeapConstant(field_map), | 987 jsgraph()->HeapConstant(field_map), |
988 effect, control); | 988 effect, control); |
989 } | 989 } |
990 field_access.write_barrier_kind = kPointerWriteBarrier; | 990 field_access.write_barrier_kind = kPointerWriteBarrier; |
991 break; | 991 break; |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 if (CanTreatHoleAsUndefined(receiver_maps, native_context)) { | 1236 if (CanTreatHoleAsUndefined(receiver_maps, native_context)) { |
1237 // Return the signaling NaN hole directly if all uses are truncating. | 1237 // Return the signaling NaN hole directly if all uses are truncating. |
1238 mode = CheckFloat64HoleMode::kAllowReturnHole; | 1238 mode = CheckFloat64HoleMode::kAllowReturnHole; |
1239 } | 1239 } |
1240 value = effect = graph()->NewNode(simplified()->CheckFloat64Hole(mode), | 1240 value = effect = graph()->NewNode(simplified()->CheckFloat64Hole(mode), |
1241 value, effect, control); | 1241 value, effect, control); |
1242 } | 1242 } |
1243 } else { | 1243 } else { |
1244 DCHECK_EQ(AccessMode::kStore, access_mode); | 1244 DCHECK_EQ(AccessMode::kStore, access_mode); |
1245 if (IsFastSmiElementsKind(elements_kind)) { | 1245 if (IsFastSmiElementsKind(elements_kind)) { |
1246 value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(), | 1246 value = effect = |
1247 value, effect, control); | 1247 graph()->NewNode(simplified()->CheckSmi(), value, effect, control); |
1248 } else if (IsFastDoubleElementsKind(elements_kind)) { | 1248 } else if (IsFastDoubleElementsKind(elements_kind)) { |
1249 value = effect = graph()->NewNode(simplified()->CheckNumber(), value, | 1249 value = effect = graph()->NewNode(simplified()->CheckNumber(), value, |
1250 effect, control); | 1250 effect, control); |
1251 // Make sure we do not store signalling NaNs into double arrays. | 1251 // Make sure we do not store signalling NaNs into double arrays. |
1252 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); | 1252 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); |
1253 } | 1253 } |
1254 | 1254 |
1255 // Ensure that copy-on-write backing store is writable. | 1255 // Ensure that copy-on-write backing store is writable. |
1256 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 1256 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
1257 store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1257 store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 inputs[0] = receiver; | 1308 inputs[0] = receiver; |
1309 for (int i = 0; i < map_input_count; ++i) { | 1309 for (int i = 0; i < map_input_count; ++i) { |
1310 inputs[1 + i] = jsgraph()->HeapConstant(maps[i]); | 1310 inputs[1 + i] = jsgraph()->HeapConstant(maps[i]); |
1311 } | 1311 } |
1312 inputs[input_count - 2] = effect; | 1312 inputs[input_count - 2] = effect; |
1313 inputs[input_count - 1] = control; | 1313 inputs[input_count - 1] = control; |
1314 return graph()->NewNode(simplified()->CheckMaps(map_input_count), input_count, | 1314 return graph()->NewNode(simplified()->CheckMaps(map_input_count), input_count, |
1315 inputs); | 1315 inputs); |
1316 } | 1316 } |
1317 | 1317 |
1318 Node* JSNativeContextSpecialization::BuildCheckTaggedPointer(Node* receiver, | 1318 Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver, |
1319 Node* effect, | 1319 Node* effect, |
1320 Node* control) { | 1320 Node* control) { |
1321 switch (receiver->opcode()) { | 1321 switch (receiver->opcode()) { |
1322 case IrOpcode::kHeapConstant: | 1322 case IrOpcode::kHeapConstant: |
1323 case IrOpcode::kJSCreate: | 1323 case IrOpcode::kJSCreate: |
1324 case IrOpcode::kJSCreateArguments: | 1324 case IrOpcode::kJSCreateArguments: |
1325 case IrOpcode::kJSCreateArray: | 1325 case IrOpcode::kJSCreateArray: |
1326 case IrOpcode::kJSCreateClosure: | 1326 case IrOpcode::kJSCreateClosure: |
1327 case IrOpcode::kJSCreateIterResultObject: | 1327 case IrOpcode::kJSCreateIterResultObject: |
1328 case IrOpcode::kJSCreateLiteralArray: | 1328 case IrOpcode::kJSCreateLiteralArray: |
1329 case IrOpcode::kJSCreateLiteralObject: | 1329 case IrOpcode::kJSCreateLiteralObject: |
1330 case IrOpcode::kJSCreateLiteralRegExp: | 1330 case IrOpcode::kJSCreateLiteralRegExp: |
1331 case IrOpcode::kJSConvertReceiver: | 1331 case IrOpcode::kJSConvertReceiver: |
1332 case IrOpcode::kJSToName: | 1332 case IrOpcode::kJSToName: |
1333 case IrOpcode::kJSToString: | 1333 case IrOpcode::kJSToString: |
1334 case IrOpcode::kJSToObject: | 1334 case IrOpcode::kJSToObject: |
1335 case IrOpcode::kJSTypeOf: { | 1335 case IrOpcode::kJSTypeOf: { |
1336 return effect; | 1336 return effect; |
1337 } | 1337 } |
1338 default: { | 1338 default: { |
1339 return graph()->NewNode(simplified()->CheckTaggedPointer(), receiver, | 1339 return graph()->NewNode(simplified()->CheckHeapObject(), receiver, effect, |
1340 effect, control); | 1340 control); |
1341 } | 1341 } |
1342 } | 1342 } |
1343 } | 1343 } |
1344 | 1344 |
1345 void JSNativeContextSpecialization::AssumePrototypesStable( | 1345 void JSNativeContextSpecialization::AssumePrototypesStable( |
1346 std::vector<Handle<Map>> const& receiver_maps, | 1346 std::vector<Handle<Map>> const& receiver_maps, |
1347 Handle<Context> native_context, Handle<JSObject> holder) { | 1347 Handle<Context> native_context, Handle<JSObject> holder) { |
1348 // Determine actual holder and perform prototype chain checks. | 1348 // Determine actual holder and perform prototype chain checks. |
1349 for (auto map : receiver_maps) { | 1349 for (auto map : receiver_maps) { |
1350 // Perform the implicit ToObject for primitives here. | 1350 // Perform the implicit ToObject for primitives here. |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1515 } | 1515 } |
1516 | 1516 |
1517 | 1517 |
1518 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1518 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
1519 return jsgraph()->simplified(); | 1519 return jsgraph()->simplified(); |
1520 } | 1520 } |
1521 | 1521 |
1522 } // namespace compiler | 1522 } // namespace compiler |
1523 } // namespace internal | 1523 } // namespace internal |
1524 } // namespace v8 | 1524 } // namespace v8 |
OLD | NEW |