| 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 |