Chromium Code Reviews| 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 |