OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import '../closure.dart'; | 5 import '../closure.dart'; |
6 import '../common.dart'; | 6 import '../common.dart'; |
7 import '../common/backend_api.dart' show BackendClasses; | 7 import '../common/backend_api.dart' show BackendClasses; |
8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
811 } else { | 811 } else { |
812 bool res = dominatesCache[other]; | 812 bool res = dominatesCache[other]; |
813 if (res != null) return res; | 813 if (res != null) return res; |
814 } | 814 } |
815 do { | 815 do { |
816 if (identical(this, other)) return dominatesCache[other] = true; | 816 if (identical(this, other)) return dominatesCache[other] = true; |
817 other = other.dominator; | 817 other = other.dominator; |
818 } while (other != null && other.id >= id); | 818 } while (other != null && other.id >= id); |
819 return dominatesCache[other] = false; | 819 return dominatesCache[other] = false; |
820 } | 820 } |
821 | |
822 toString() => 'HBasicBlock($id)'; | |
821 } | 823 } |
822 | 824 |
823 abstract class HInstruction implements Spannable { | 825 abstract class HInstruction implements Spannable { |
824 Entity sourceElement; | 826 Entity sourceElement; |
825 SourceInformation sourceInformation; | 827 SourceInformation sourceInformation; |
826 | 828 |
827 final int id; | 829 final int id; |
828 static int idCounter; | 830 static int idCounter; |
829 | 831 |
830 final List<HInstruction> inputs; | 832 final List<HInstruction> inputs; |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1222 assert(newInput != null && !identical(oldInput, newInput)); | 1224 assert(newInput != null && !identical(oldInput, newInput)); |
1223 for (int i = 0; i < inputs.length; i++) { | 1225 for (int i = 0; i < inputs.length; i++) { |
1224 if (identical(inputs[i], oldInput)) { | 1226 if (identical(inputs[i], oldInput)) { |
1225 inputs[i] = newInput; | 1227 inputs[i] = newInput; |
1226 newInput.usedBy.add(this); | 1228 newInput.usedBy.add(this); |
1227 } | 1229 } |
1228 } | 1230 } |
1229 removeFromList(oldInput.usedBy, this); | 1231 removeFromList(oldInput.usedBy, this); |
1230 } | 1232 } |
1231 | 1233 |
1232 // Compute the set of users of this instruction that is dominated by | |
1233 // [other]. If [other] is a user of [this], it is included in the | |
1234 // returned set. | |
1235 Setlet<HInstruction> dominatedUsers(HInstruction other) { | |
1236 // Keep track of all instructions that we have to deal with later | |
1237 // and count the number of them that are in the current block. | |
1238 Setlet<HInstruction> users = new Setlet<HInstruction>(); | |
1239 int usersInCurrentBlock = 0; | |
1240 | |
1241 // Run through all the users and see if they are dominated or | |
1242 // potentially dominated by [other]. | |
1243 HBasicBlock otherBlock = other.block; | |
1244 for (int i = 0, length = usedBy.length; i < length; i++) { | |
1245 HInstruction current = usedBy[i]; | |
1246 HBasicBlock currentBlock = current.block; | |
1247 if (otherBlock.dominates(currentBlock)) { | |
1248 if (identical(currentBlock, otherBlock)) usersInCurrentBlock++; | |
1249 users.add(current); | |
1250 } | |
1251 } | |
1252 | |
1253 // Run through all the phis in the same block as [other] and remove them | |
1254 // from the users set. | |
1255 if (usersInCurrentBlock > 0) { | |
1256 for (HPhi phi = otherBlock.phis.first; phi != null; phi = phi.next) { | |
1257 if (users.contains(phi)) { | |
1258 users.remove(phi); | |
1259 if (--usersInCurrentBlock == 0) break; | |
1260 } | |
1261 } | |
1262 } | |
1263 | |
1264 // Run through all the instructions before [other] and remove them | |
1265 // from the users set. | |
1266 if (usersInCurrentBlock > 0) { | |
1267 HInstruction current = otherBlock.first; | |
1268 while (!identical(current, other)) { | |
1269 if (users.contains(current)) { | |
1270 users.remove(current); | |
1271 if (--usersInCurrentBlock == 0) break; | |
1272 } | |
1273 current = current.next; | |
1274 } | |
1275 } | |
1276 | |
1277 return users; | |
1278 } | |
1279 | |
1280 void replaceAllUsersDominatedBy( | 1234 void replaceAllUsersDominatedBy( |
1281 HInstruction cursor, HInstruction newInstruction) { | 1235 HInstruction cursor, HInstruction newInstruction) { |
1282 Setlet<HInstruction> users = dominatedUsers(cursor); | 1236 DominatedUses.of(this, cursor).replaceWith(newInstruction); |
1283 for (HInstruction user in users) { | |
1284 user.changeUse(this, newInstruction); | |
1285 } | |
1286 } | 1237 } |
1287 | 1238 |
1288 void moveBefore(HInstruction other) { | 1239 void moveBefore(HInstruction other) { |
1289 assert(this is! HControlFlow); | 1240 assert(this is! HControlFlow); |
1290 assert(this is! HPhi); | 1241 assert(this is! HPhi); |
1291 assert(other is! HPhi); | 1242 assert(other is! HPhi); |
1292 block.detach(this); | 1243 block.detach(this); |
1293 other.block.internalAddBefore(other, this); | 1244 other.block.internalAddBefore(other, this); |
1294 block = other.block; | 1245 block = other.block; |
1295 } | 1246 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1362 | 1313 |
1363 /** | 1314 /** |
1364 * Return whether the instructions do not belong to a loop or | 1315 * Return whether the instructions do not belong to a loop or |
1365 * belong to the same loop. | 1316 * belong to the same loop. |
1366 */ | 1317 */ |
1367 bool hasSameLoopHeaderAs(HInstruction other) { | 1318 bool hasSameLoopHeaderAs(HInstruction other) { |
1368 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; | 1319 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; |
1369 } | 1320 } |
1370 } | 1321 } |
1371 | 1322 |
1323 /// The set of uses of [source] that are dominated by [dominator]. | |
1324 class DominatedUses { | |
1325 final HInstruction _source; | |
1326 final HInstruction _dominator; | |
1327 | |
1328 // Two list of matching length holding (instruction, input-index) pairs for | |
1329 // the dominated uses. | |
1330 final List<HInstruction> _instructions = <HInstruction>[]; | |
1331 final List<int> _indexes = <int>[]; | |
1332 | |
1333 DominatedUses._(this._source, this._dominator); | |
1334 | |
1335 /// The uses of [source] that are dominated by [dominator]. | |
1336 /// | |
1337 /// The uses by [dominator] are included in the result, unless | |
1338 /// [excludeDominator] is `true`, so `true` selects uses following | |
1339 /// [dominator]. | |
1340 /// | |
1341 /// The uses include the in-edges of a HPhi node that corresponds to a | |
1342 /// dominated block. (There can be many such edges on a single phi at the exit | |
1343 /// of a loop with many break statements). If [excludePhiOutEdges] is `true` | |
1344 /// then these edge uses are not included. | |
1345 static of(HInstruction source, HInstruction dominator, | |
1346 {bool excludeDominator: false, bool excludePhiOutEdges: false}) { | |
1347 return new DominatedUses._(source, dominator) | |
1348 .._compute(source, dominator, excludeDominator, excludePhiOutEdges); | |
1349 } | |
1350 | |
1351 bool get isEmpty => _instructions.isEmpty; | |
1352 bool get isNotEmpty => !isEmpty; | |
1353 | |
1354 /// Changes all the uses in the set to [newInstruction]. | |
1355 void replaceWith(HInstruction newInstruction) { | |
1356 assert(!identical(newInstruction, _source)); | |
1357 if (isEmpty) return; | |
1358 for (int i = 0; i < _instructions.length; i++) { | |
1359 HInstruction user = _instructions[i]; | |
1360 int index = _indexes[i]; | |
1361 HInstruction oldInstruction = user.inputs[index]; | |
1362 assert( | |
1363 identical(oldInstruction, _source), | |
1364 'Input ${index} of ${user} changed.' | |
1365 '\n Found: ${oldInstruction}\n Expected: ${_source}'); | |
1366 user.inputs[index] = newInstruction; | |
1367 oldInstruction.usedBy.remove(user); | |
1368 newInstruction.usedBy.add(user); | |
1369 } | |
1370 } | |
1371 | |
1372 void _addUse(HInstruction user, int inputIndex) { | |
1373 _instructions.add(user); | |
1374 _indexes.add(inputIndex); | |
1375 } | |
1376 | |
1377 void _compute(HInstruction source, HInstruction dominator, | |
1378 bool excludeDominator, bool excludePhiOutEdges) { | |
1379 // Keep track of all instructions that we have to deal with later and count | |
1380 // the number of them that are in the current block. | |
1381 Set<HInstruction> users = new Setlet<HInstruction>(); | |
1382 Set<HInstruction> seen = new Setlet<HInstruction>(); | |
1383 int usersInCurrentBlock = 0; | |
1384 | |
1385 HBasicBlock dominatorBlock = dominator.block; | |
1386 | |
1387 // Run through all the users and see if they are dominated, or potentially | |
1388 // dominated, or partially dominated by [dominator]. It is easier to | |
1389 // de-duplicate [usedBy] and process all inputs of an instruction than to | |
1390 // track the repeated elements of usedBy and match them up by index. | |
1391 for (HInstruction current in source.usedBy) { | |
1392 if (!seen.add(current)) continue; | |
1393 HBasicBlock currentBlock = current.block; | |
1394 if (dominatorBlock.dominates(currentBlock)) { | |
1395 users.add(current); | |
1396 if (identical(currentBlock, dominatorBlock)) usersInCurrentBlock++; | |
1397 } else if (!excludePhiOutEdges && current is HPhi) { | |
1398 // A non-dominated HPhi. | |
1399 // See if there a dominated edge into the phi. The input must be | |
1400 // [source] and the position must correspond to a dominated block. | |
1401 List<HBasicBlock> predecessors = currentBlock.predecessors; | |
1402 for (int i = 0; i < predecessors.length; i++) { | |
1403 if (current.inputs[i] != source) continue; | |
1404 HBasicBlock predecessor = predecessors[i]; | |
1405 if (dominatorBlock.dominates(predecessor)) { | |
1406 _addUse(current, i); | |
1407 } | |
1408 } | |
1409 } | |
1410 } | |
1411 | |
1412 // Run through all the phis in the same block as [dominator] and remove them | |
1413 // from the users set. These come before [dominator]. | |
1414 // TODO(sra): Could we simply not add them in the first place? | |
1415 if (usersInCurrentBlock > 0) { | |
1416 for (HPhi phi = dominatorBlock.phis.first; phi != null; phi = phi.next) { | |
1417 if (users.remove(phi)) { | |
1418 if (--usersInCurrentBlock == 0) break; | |
Emily Fortuna
2017/04/03 20:48:46
small preference for doing the decrement in a sepa
| |
1419 } | |
1420 } | |
1421 } | |
1422 | |
1423 // Run through all the instructions before [dominator] and remove them from | |
1424 // the users set. | |
1425 if (usersInCurrentBlock > 0) { | |
1426 HInstruction current = dominatorBlock.first; | |
1427 while (!identical(current, dominator)) { | |
1428 if (users.remove(current)) { | |
1429 if (--usersInCurrentBlock == 0) break; | |
1430 } | |
1431 current = current.next; | |
1432 } | |
1433 if (excludeDominator) { | |
1434 users.remove(dominator); | |
1435 } | |
1436 } | |
1437 | |
1438 // Convert users into a list of (user, input-index) uses. | |
1439 for (HInstruction user in users) { | |
1440 var inputs = user.inputs; | |
1441 for (int i = 0; i < inputs.length; i++) { | |
1442 if (inputs[i] == source) { | |
1443 _addUse(user, i); | |
1444 } | |
1445 } | |
1446 } | |
1447 } | |
1448 } | |
1449 | |
1372 /// A reference to a [HInstruction] that can hold its own source information. | 1450 /// A reference to a [HInstruction] that can hold its own source information. |
1373 /// | 1451 /// |
1374 /// This used for attaching source information to reads of locals. | 1452 /// This used for attaching source information to reads of locals. |
1375 class HRef extends HInstruction { | 1453 class HRef extends HInstruction { |
1376 HRef(HInstruction value, SourceInformation sourceInformation) | 1454 HRef(HInstruction value, SourceInformation sourceInformation) |
1377 : super([value], value.instructionType) { | 1455 : super([value], value.instructionType) { |
1378 this.sourceInformation = sourceInformation; | 1456 this.sourceInformation = sourceInformation; |
1379 } | 1457 } |
1380 | 1458 |
1381 HInstruction get value => inputs[0]; | 1459 HInstruction get value => inputs[0]; |
(...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3393 | 3471 |
3394 String get kindAsString { | 3472 String get kindAsString { |
3395 switch (kind) { | 3473 switch (kind) { |
3396 case TypeInfoExpressionKind.COMPLETE: | 3474 case TypeInfoExpressionKind.COMPLETE: |
3397 return 'COMPLETE'; | 3475 return 'COMPLETE'; |
3398 case TypeInfoExpressionKind.INSTANCE: | 3476 case TypeInfoExpressionKind.INSTANCE: |
3399 return 'INSTANCE'; | 3477 return 'INSTANCE'; |
3400 } | 3478 } |
3401 } | 3479 } |
3402 } | 3480 } |
OLD | NEW |