| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_nodes; | 4 library dart2js.ir_nodes; |
| 5 | 5 |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'cps_fragment.dart' show CpsFragment; | 7 import 'cps_fragment.dart' show CpsFragment; |
| 8 import 'cps_ir_nodes_sexpr.dart'; | 8 import 'cps_ir_nodes_sexpr.dart'; |
| 9 import '../constants/values.dart' as values; | 9 import '../constants/values.dart' as values; |
| 10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
| 11 import '../elements/elements.dart'; | 11 import '../elements/elements.dart'; |
| 12 import '../io/source_information.dart' show SourceInformation; | 12 import '../io/source_information.dart' show SourceInformation; |
| 13 import '../types/types.dart' show TypeMask; | 13 import '../types/types.dart' show TypeMask; |
| 14 import '../universe/selector.dart' show Selector; | 14 import '../universe/selector.dart' show Selector; |
| 15 import '../universe/side_effects.dart'; | |
| 16 | 15 |
| 17 import 'builtin_operator.dart'; | 16 import 'builtin_operator.dart'; |
| 18 export 'builtin_operator.dart'; | 17 export 'builtin_operator.dart'; |
| 19 | 18 |
| 20 import 'effects.dart'; | |
| 21 | |
| 22 // These imports are only used for the JavaScript specific nodes. If we want to | 19 // These imports are only used for the JavaScript specific nodes. If we want to |
| 23 // support more than one native backend, we should probably create better | 20 // support more than one native backend, we should probably create better |
| 24 // abstractions for native code and its type and effect system. | 21 // abstractions for native code and its type and effect system. |
| 25 import '../js/js.dart' as js show Template, isNullGuardOnFirstArgument; | 22 import '../js/js.dart' as js show Template, isNullGuardOnFirstArgument; |
| 26 import '../native/native.dart' as native show NativeBehavior; | 23 import '../native/native.dart' as native show NativeBehavior; |
| 27 | 24 |
| 28 abstract class Node { | 25 abstract class Node { |
| 29 /// A pointer to the parent node. Is null until set by optimization passes. | 26 /// A pointer to the parent node. Is null until set by optimization passes. |
| 30 Node parent; | 27 Node parent; |
| 31 | 28 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 235 |
| 239 /// A named value. | 236 /// A named value. |
| 240 /// | 237 /// |
| 241 /// The identity of the [Primitive] object is the name of the value. | 238 /// The identity of the [Primitive] object is the name of the value. |
| 242 /// The subclass describes how to compute the value. | 239 /// The subclass describes how to compute the value. |
| 243 /// | 240 /// |
| 244 /// All primitives except [Parameter] must be bound by a [LetPrim]. | 241 /// All primitives except [Parameter] must be bound by a [LetPrim]. |
| 245 abstract class Primitive extends Variable<Primitive> { | 242 abstract class Primitive extends Variable<Primitive> { |
| 246 Primitive() : super(null); | 243 Primitive() : super(null); |
| 247 | 244 |
| 248 /// Returns a bitmask with the non-local side effects and dependencies of | |
| 249 /// this primitive, as defined by [Effects]. | |
| 250 int get effects => Effects.none; | |
| 251 | |
| 252 /// True if this primitive has a value that can be used by other expressions. | 245 /// True if this primitive has a value that can be used by other expressions. |
| 253 bool get hasValue; | 246 bool get hasValue; |
| 254 | 247 |
| 255 /// True if the primitive can be removed, assuming it has no uses | 248 /// True if the primitive can be removed, assuming it has no uses |
| 256 /// (this getter does not check if there are any uses). | 249 /// (this getter does not check if there are any uses). |
| 257 /// | 250 /// |
| 258 /// False must be returned for primitives that may throw, diverge, or have | 251 /// False must be returned for primitives that may throw, diverge, or have |
| 259 /// observable side-effects. | 252 /// observable side-effects. |
| 260 bool get isSafeForElimination; | 253 bool get isSafeForElimination; |
| 261 | 254 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 replaceUsesWith(newPrimitive); | 338 replaceUsesWith(newPrimitive); |
| 346 destroy(); | 339 destroy(); |
| 347 LetPrim let = parent; | 340 LetPrim let = parent; |
| 348 fragment.insertBelow(let); | 341 fragment.insertBelow(let); |
| 349 let.remove(); | 342 let.remove(); |
| 350 } | 343 } |
| 351 } | 344 } |
| 352 | 345 |
| 353 /// A primitive that is generally not safe for elimination, but may be marked | 346 /// A primitive that is generally not safe for elimination, but may be marked |
| 354 /// as safe by type propagation | 347 /// as safe by type propagation |
| 348 // |
| 349 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this |
| 350 // class. |
| 355 abstract class UnsafePrimitive extends Primitive { | 351 abstract class UnsafePrimitive extends Primitive { |
| 356 int effects = Effects.all; | |
| 357 bool isSafeForElimination = false; | 352 bool isSafeForElimination = false; |
| 358 bool isSafeForReordering = false; | 353 bool isSafeForReordering = false; |
| 359 } | 354 } |
| 360 | 355 |
| 361 /// Operands to invocations and primitives are always variables. They point to | 356 /// Operands to invocations and primitives are always variables. They point to |
| 362 /// their definition and are doubly-linked into a list of occurrences. | 357 /// their definition and are doubly-linked into a list of occurrences. |
| 363 class Reference<T extends Definition<T>> { | 358 class Reference<T extends Definition<T>> { |
| 364 T definition; | 359 T definition; |
| 365 Reference<T> previous; | 360 Reference<T> previous; |
| 366 Reference<T> next; | 361 Reference<T> next; |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); | 1136 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); |
| 1142 | 1137 |
| 1143 bool get hasValue => true; | 1138 bool get hasValue => true; |
| 1144 bool get isSafeForElimination => false; | 1139 bool get isSafeForElimination => false; |
| 1145 bool get isSafeForReordering => false; | 1140 bool get isSafeForReordering => false; |
| 1146 | 1141 |
| 1147 void setParentPointers() { | 1142 void setParentPointers() { |
| 1148 receiver.parent = this; | 1143 receiver.parent = this; |
| 1149 _setParentsOnList(arguments, this); | 1144 _setParentsOnList(arguments, this); |
| 1150 } | 1145 } |
| 1151 | |
| 1152 int get effects => getEffectsOfBuiltinMethod(method); | |
| 1153 } | 1146 } |
| 1154 | 1147 |
| 1155 /// Throw a value. | 1148 /// Throw a value. |
| 1156 /// | 1149 /// |
| 1157 /// Throw is an expression, i.e., it always occurs in tail position with | 1150 /// Throw is an expression, i.e., it always occurs in tail position with |
| 1158 /// respect to a body or expression. | 1151 /// respect to a body or expression. |
| 1159 class Throw extends TailExpression { | 1152 class Throw extends TailExpression { |
| 1160 Reference<Primitive> value; | 1153 Reference<Primitive> value; |
| 1161 | 1154 |
| 1162 Throw(Primitive value) : value = new Reference<Primitive>(value); | 1155 Throw(Primitive value) : value = new Reference<Primitive>(value); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 accept(Visitor visitor) => visitor.visitSetField(this); | 1331 accept(Visitor visitor) => visitor.visitSetField(this); |
| 1339 | 1332 |
| 1340 bool get hasValue => false; | 1333 bool get hasValue => false; |
| 1341 bool get isSafeForElimination => false; | 1334 bool get isSafeForElimination => false; |
| 1342 bool get isSafeForReordering => false; | 1335 bool get isSafeForReordering => false; |
| 1343 | 1336 |
| 1344 void setParentPointers() { | 1337 void setParentPointers() { |
| 1345 object.parent = this; | 1338 object.parent = this; |
| 1346 value.parent = this; | 1339 value.parent = this; |
| 1347 } | 1340 } |
| 1348 | |
| 1349 int get effects => Effects.changesInstanceField; | |
| 1350 } | 1341 } |
| 1351 | 1342 |
| 1352 /// Directly reads from a field on a given object. | 1343 /// Directly reads from a field on a given object. |
| 1353 /// | 1344 /// |
| 1354 /// The [object] must either be `null` or an object that has [field]. | 1345 /// The [object] must either be `null` or an object that has [field]. |
| 1355 class GetField extends Primitive { | 1346 class GetField extends Primitive { |
| 1356 final Reference<Primitive> object; | 1347 final Reference<Primitive> object; |
| 1357 FieldElement field; | 1348 FieldElement field; |
| 1358 | 1349 |
| 1359 /// True if the field never changes value. | |
| 1360 final bool isFinal; | |
| 1361 | |
| 1362 /// True if the object is known not to be null. | 1350 /// True if the object is known not to be null. |
| 1363 // TODO(asgerf): This is a placeholder until we agree on how to track | 1351 // TODO(asgerf): This is a placeholder until we agree on how to track |
| 1364 // side effects. | 1352 // side effects. |
| 1365 bool objectIsNotNull = false; | 1353 bool objectIsNotNull = false; |
| 1366 | 1354 |
| 1367 GetField(Primitive object, this.field, {this.isFinal}) | 1355 GetField(Primitive object, this.field) |
| 1368 : this.object = new Reference<Primitive>(object) { | 1356 : this.object = new Reference<Primitive>(object); |
| 1369 assert(isFinal != null); | |
| 1370 } | |
| 1371 | 1357 |
| 1372 accept(Visitor visitor) => visitor.visitGetField(this); | 1358 accept(Visitor visitor) => visitor.visitGetField(this); |
| 1373 | 1359 |
| 1374 bool get hasValue => true; | 1360 bool get hasValue => true; |
| 1375 bool get isSafeForElimination => objectIsNotNull; | 1361 bool get isSafeForElimination => objectIsNotNull; |
| 1376 bool get isSafeForReordering => false; | 1362 bool get isSafeForReordering => false; |
| 1377 | 1363 |
| 1378 toString() => 'GetField($field)'; | 1364 toString() => 'GetField($field)'; |
| 1379 | 1365 |
| 1380 void setParentPointers() { | 1366 void setParentPointers() { |
| 1381 object.parent = this; | 1367 object.parent = this; |
| 1382 } | 1368 } |
| 1383 | |
| 1384 int get effects => isFinal ? 0 : Effects.dependsOnInstanceField; | |
| 1385 } | 1369 } |
| 1386 | 1370 |
| 1387 /// Get the length of a string or native list. | 1371 /// Get the length of a string or native list. |
| 1388 class GetLength extends Primitive { | 1372 class GetLength extends Primitive { |
| 1389 final Reference<Primitive> object; | 1373 final Reference<Primitive> object; |
| 1390 | 1374 |
| 1391 /// True if the length of the given object can never change. | |
| 1392 bool isFinal; | |
| 1393 | |
| 1394 /// True if the object is known not to be null. | 1375 /// True if the object is known not to be null. |
| 1395 bool objectIsNotNull = false; | 1376 bool objectIsNotNull = false; |
| 1396 | 1377 |
| 1397 GetLength(Primitive object, {this.isFinal: false}) | 1378 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); |
| 1398 : this.object = new Reference<Primitive>(object); | |
| 1399 | 1379 |
| 1400 bool get hasValue => true; | 1380 bool get hasValue => true; |
| 1401 bool get isSafeForElimination => objectIsNotNull; | 1381 bool get isSafeForElimination => objectIsNotNull; |
| 1402 bool get isSafeForReordering => false; | 1382 bool get isSafeForReordering => false; |
| 1403 | 1383 |
| 1404 accept(Visitor v) => v.visitGetLength(this); | 1384 accept(Visitor v) => v.visitGetLength(this); |
| 1405 | 1385 |
| 1406 void setParentPointers() { | 1386 void setParentPointers() { |
| 1407 object.parent = this; | 1387 object.parent = this; |
| 1408 } | 1388 } |
| 1409 | |
| 1410 int get effects => isFinal ? 0 : Effects.dependsOnIndexableLength; | |
| 1411 } | 1389 } |
| 1412 | 1390 |
| 1413 /// Read an entry from an indexable object. | 1391 /// Read an entry from an indexable object. |
| 1414 /// | 1392 /// |
| 1415 /// [object] must be null or an indexable object, and [index] must be | 1393 /// [object] must be null or an indexable object, and [index] must be |
| 1416 /// an integer where `0 <= index < object.length`. | 1394 /// an integer where `0 <= index < object.length`. |
| 1417 class GetIndex extends Primitive { | 1395 class GetIndex extends Primitive { |
| 1418 final Reference<Primitive> object; | 1396 final Reference<Primitive> object; |
| 1419 final Reference<Primitive> index; | 1397 final Reference<Primitive> index; |
| 1420 | 1398 |
| 1421 /// True if the object is known not to be null. | 1399 /// True if the object is known not to be null. |
| 1422 bool objectIsNotNull = false; | 1400 bool objectIsNotNull = false; |
| 1423 | 1401 |
| 1424 GetIndex(Primitive object, Primitive index) | 1402 GetIndex(Primitive object, Primitive index) |
| 1425 : this.object = new Reference<Primitive>(object), | 1403 : this.object = new Reference<Primitive>(object), |
| 1426 this.index = new Reference<Primitive>(index); | 1404 this.index = new Reference<Primitive>(index); |
| 1427 | 1405 |
| 1428 bool get hasValue => true; | 1406 bool get hasValue => true; |
| 1429 bool get isSafeForElimination => objectIsNotNull; | 1407 bool get isSafeForElimination => objectIsNotNull; |
| 1430 bool get isSafeForReordering => false; | 1408 bool get isSafeForReordering => false; |
| 1431 | 1409 |
| 1432 accept(Visitor v) => v.visitGetIndex(this); | 1410 accept(Visitor v) => v.visitGetIndex(this); |
| 1433 | 1411 |
| 1434 void setParentPointers() { | 1412 void setParentPointers() { |
| 1435 object.parent = this; | 1413 object.parent = this; |
| 1436 index.parent = this; | 1414 index.parent = this; |
| 1437 } | 1415 } |
| 1438 | |
| 1439 int get effects => Effects.dependsOnIndexableContent; | |
| 1440 } | 1416 } |
| 1441 | 1417 |
| 1442 /// Set an entry on a native list. | 1418 /// Set an entry on a native list. |
| 1443 /// | 1419 /// |
| 1444 /// [object] must be null or a native list, and [index] must be an integer | 1420 /// [object] must be null or a native list, and [index] must be an integer. |
| 1445 /// within the bounds of the indexable object. | |
| 1446 /// | |
| 1447 /// [SetIndex] may not be used to alter the length of a JS array. | |
| 1448 /// | 1421 /// |
| 1449 /// The primitive itself has no value and may not be referenced. | 1422 /// The primitive itself has no value and may not be referenced. |
| 1450 class SetIndex extends Primitive { | 1423 class SetIndex extends Primitive { |
| 1451 final Reference<Primitive> object; | 1424 final Reference<Primitive> object; |
| 1452 final Reference<Primitive> index; | 1425 final Reference<Primitive> index; |
| 1453 final Reference<Primitive> value; | 1426 final Reference<Primitive> value; |
| 1454 | 1427 |
| 1455 SetIndex(Primitive object, Primitive index, Primitive value) | 1428 SetIndex(Primitive object, Primitive index, Primitive value) |
| 1456 : this.object = new Reference<Primitive>(object), | 1429 : this.object = new Reference<Primitive>(object), |
| 1457 this.index = new Reference<Primitive>(index), | 1430 this.index = new Reference<Primitive>(index), |
| 1458 this.value = new Reference<Primitive>(value); | 1431 this.value = new Reference<Primitive>(value); |
| 1459 | 1432 |
| 1460 bool get hasValue => false; | 1433 bool get hasValue => false; |
| 1461 bool get isSafeForElimination => false; | 1434 bool get isSafeForElimination => false; |
| 1462 bool get isSafeForReordering => false; | 1435 bool get isSafeForReordering => false; |
| 1463 | 1436 |
| 1464 accept(Visitor v) => v.visitSetIndex(this); | 1437 accept(Visitor v) => v.visitSetIndex(this); |
| 1465 | 1438 |
| 1466 void setParentPointers() { | 1439 void setParentPointers() { |
| 1467 object.parent = this; | 1440 object.parent = this; |
| 1468 index.parent = this; | 1441 index.parent = this; |
| 1469 value.parent = this; | 1442 value.parent = this; |
| 1470 } | 1443 } |
| 1471 | |
| 1472 int get effects => Effects.changesIndexableContent; | |
| 1473 } | 1444 } |
| 1474 | 1445 |
| 1475 /// Reads the value of a static field or tears off a static method. | 1446 /// Reads the value of a static field or tears off a static method. |
| 1476 /// | 1447 /// |
| 1477 /// If [GetStatic] is used to load a lazily initialized static field, it must | 1448 /// If [GetStatic] is used to load a lazily initialized static field, it must |
| 1478 /// have been initialized beforehand, and a [witness] must be set to restrict | 1449 /// have been initialized beforehand, and a [witness] must be set to restrict |
| 1479 /// code motion. | 1450 /// code motion. |
| 1480 class GetStatic extends Primitive { | 1451 class GetStatic extends Primitive { |
| 1481 /// Can be [FieldElement] or [FunctionElement]. | 1452 /// Can be [FieldElement] or [FunctionElement]. |
| 1482 final Element element; | 1453 final Element element; |
| 1483 final SourceInformation sourceInformation; | 1454 final SourceInformation sourceInformation; |
| 1484 | 1455 |
| 1485 /// True if the field never changes value. | |
| 1486 final bool isFinal; | |
| 1487 | |
| 1488 /// If reading a lazily initialized field, [witness] must refer to a node | 1456 /// If reading a lazily initialized field, [witness] must refer to a node |
| 1489 /// that initializes the field or always occurs after the field initializer. | 1457 /// that initializes the field or always occurs after the field initializer. |
| 1490 /// | 1458 /// |
| 1491 /// The value of the witness is not used. | 1459 /// The value of the witness is not used. |
| 1492 Reference<Primitive> witness; | 1460 Reference<Primitive> witness; |
| 1493 | 1461 |
| 1494 GetStatic(this.element, {this.isFinal: false, this.sourceInformation}); | 1462 GetStatic(this.element, [this.sourceInformation]); |
| 1495 | 1463 |
| 1496 /// Read a lazily initialized static field that is known to have been | 1464 /// Read a lazily initialized static field that is known to have been |
| 1497 /// initialized by [witness] or earlier. | 1465 /// initialized by [witness] or earlier. |
| 1498 GetStatic.witnessed(this.element, Primitive witness, {this.sourceInformation}) | 1466 GetStatic.witnessed(this.element, Primitive witness, [this.sourceInformation]) |
| 1499 : witness = witness == null ? null : new Reference<Primitive>(witness), | 1467 : witness = witness == null ? null : new Reference<Primitive>(witness); |
| 1500 isFinal = false; | |
| 1501 | 1468 |
| 1502 accept(Visitor visitor) => visitor.visitGetStatic(this); | 1469 accept(Visitor visitor) => visitor.visitGetStatic(this); |
| 1503 | 1470 |
| 1504 bool get hasValue => true; | 1471 bool get hasValue => true; |
| 1505 bool get isSafeForElimination => true; | 1472 bool get isSafeForElimination => true; |
| 1506 bool get isSafeForReordering => isFinal; | 1473 bool get isSafeForReordering { |
| 1474 return element is FunctionElement || element.isFinal; |
| 1475 } |
| 1507 | 1476 |
| 1508 void setParentPointers() { | 1477 void setParentPointers() { |
| 1509 if (witness != null) { | 1478 if (witness != null) { |
| 1510 witness.parent = this; | 1479 witness.parent = this; |
| 1511 } | 1480 } |
| 1512 } | 1481 } |
| 1513 | |
| 1514 int get effects => isFinal ? 0 : Effects.dependsOnStaticField; | |
| 1515 } | 1482 } |
| 1516 | 1483 |
| 1517 /// Sets the value of a static field. | 1484 /// Sets the value of a static field. |
| 1518 class SetStatic extends Primitive { | 1485 class SetStatic extends Primitive { |
| 1519 final FieldElement element; | 1486 final FieldElement element; |
| 1520 final Reference<Primitive> value; | 1487 final Reference<Primitive> value; |
| 1521 final SourceInformation sourceInformation; | 1488 final SourceInformation sourceInformation; |
| 1522 | 1489 |
| 1523 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 1490 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
| 1524 : this.value = new Reference<Primitive>(value); | 1491 : this.value = new Reference<Primitive>(value); |
| 1525 | 1492 |
| 1526 accept(Visitor visitor) => visitor.visitSetStatic(this); | 1493 accept(Visitor visitor) => visitor.visitSetStatic(this); |
| 1527 | 1494 |
| 1528 bool get hasValue => false; | 1495 bool get hasValue => false; |
| 1529 bool get isSafeForElimination => false; | 1496 bool get isSafeForElimination => false; |
| 1530 bool get isSafeForReordering => false; | 1497 bool get isSafeForReordering => false; |
| 1531 | 1498 |
| 1532 void setParentPointers() { | 1499 void setParentPointers() { |
| 1533 value.parent = this; | 1500 value.parent = this; |
| 1534 } | 1501 } |
| 1535 | |
| 1536 int get effects => Effects.changesStaticField; | |
| 1537 } | 1502 } |
| 1538 | 1503 |
| 1539 /// Reads the value of a lazily initialized static field. | 1504 /// Reads the value of a lazily initialized static field. |
| 1540 /// | 1505 /// |
| 1541 /// If the field has not yet been initialized, its initializer is evaluated | 1506 /// If the field has not yet been initialized, its initializer is evaluated |
| 1542 /// and assigned to the field. | 1507 /// and assigned to the field. |
| 1543 class GetLazyStatic extends UnsafePrimitive { | 1508 class GetLazyStatic extends UnsafePrimitive { |
| 1544 final FieldElement element; | 1509 final FieldElement element; |
| 1545 final SourceInformation sourceInformation; | 1510 final SourceInformation sourceInformation; |
| 1546 | 1511 |
| 1547 /// True if the field never changes value. | 1512 GetLazyStatic(this.element, [this.sourceInformation]); |
| 1548 final bool isFinal; | |
| 1549 | |
| 1550 GetLazyStatic(this.element, {this.isFinal: false, this.sourceInformation}); | |
| 1551 | 1513 |
| 1552 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); | 1514 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
| 1553 | 1515 |
| 1554 bool get hasValue => true; | 1516 bool get hasValue => true; |
| 1555 | 1517 |
| 1556 void setParentPointers() {} | 1518 void setParentPointers() {} |
| 1557 | |
| 1558 // TODO(asgerf): Track side effects of lazy field initializers. | |
| 1559 int get effects => Effects.all; | |
| 1560 } | 1519 } |
| 1561 | 1520 |
| 1562 /// Creates an object for holding boxed variables captured by a closure. | 1521 /// Creates an object for holding boxed variables captured by a closure. |
| 1563 class CreateBox extends Primitive { | 1522 class CreateBox extends Primitive { |
| 1564 accept(Visitor visitor) => visitor.visitCreateBox(this); | 1523 accept(Visitor visitor) => visitor.visitCreateBox(this); |
| 1565 | 1524 |
| 1566 bool get hasValue => true; | 1525 bool get hasValue => true; |
| 1567 bool get isSafeForElimination => true; | 1526 bool get isSafeForElimination => true; |
| 1568 bool get isSafeForReordering => true; | 1527 bool get isSafeForReordering => true; |
| 1569 | 1528 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1669 | 1628 |
| 1670 class ForeignCode extends UnsafePrimitive { | 1629 class ForeignCode extends UnsafePrimitive { |
| 1671 final js.Template codeTemplate; | 1630 final js.Template codeTemplate; |
| 1672 final TypeMask storedType; | 1631 final TypeMask storedType; |
| 1673 final List<Reference<Primitive>> arguments; | 1632 final List<Reference<Primitive>> arguments; |
| 1674 final native.NativeBehavior nativeBehavior; | 1633 final native.NativeBehavior nativeBehavior; |
| 1675 final FunctionElement dependency; | 1634 final FunctionElement dependency; |
| 1676 | 1635 |
| 1677 ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments, | 1636 ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments, |
| 1678 this.nativeBehavior, {this.dependency}) | 1637 this.nativeBehavior, {this.dependency}) |
| 1679 : this.arguments = _referenceList(arguments) { | 1638 : this.arguments = _referenceList(arguments); |
| 1680 effects = Effects.from(nativeBehavior.sideEffects); | |
| 1681 } | |
| 1682 | 1639 |
| 1683 accept(Visitor visitor) => visitor.visitForeignCode(this); | 1640 accept(Visitor visitor) => visitor.visitForeignCode(this); |
| 1684 | 1641 |
| 1685 bool get hasValue => true; | 1642 bool get hasValue => true; |
| 1686 | 1643 |
| 1687 void setParentPointers() { | 1644 void setParentPointers() { |
| 1688 _setParentsOnList(arguments, this); | 1645 _setParentsOnList(arguments, this); |
| 1689 } | 1646 } |
| 1690 | 1647 |
| 1691 bool isNullGuardOnNullFirstArgument() { | 1648 bool isNullGuardOnNullFirstArgument() { |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2672 Variable originalVariable = original; | 2629 Variable originalVariable = original; |
| 2673 copy.type = originalVariable.type; | 2630 copy.type = originalVariable.type; |
| 2674 copy.hint = originalVariable.hint; | 2631 copy.hint = originalVariable.hint; |
| 2675 } | 2632 } |
| 2676 return _copies[original] = copy; | 2633 return _copies[original] = copy; |
| 2677 } | 2634 } |
| 2678 | 2635 |
| 2679 /// Get the copy of a [Reference]'s definition from the map. | 2636 /// Get the copy of a [Reference]'s definition from the map. |
| 2680 Definition getCopy(Reference reference) => _copies[reference.definition]; | 2637 Definition getCopy(Reference reference) => _copies[reference.definition]; |
| 2681 | 2638 |
| 2682 /// Get the copy of a [Reference]'s definition from the map. | |
| 2683 Definition getCopyOrNull(Reference reference) => reference == null | |
| 2684 ? null | |
| 2685 : getCopy(reference); | |
| 2686 | |
| 2687 /// Map a list of [Reference]s to the list of their definition's copies. | 2639 /// Map a list of [Reference]s to the list of their definition's copies. |
| 2688 List<Definition> getList(List<Reference> list) => list.map(getCopy).toList(); | 2640 List<Definition> getList(List<Reference> list) => list.map(getCopy).toList(); |
| 2689 | 2641 |
| 2690 /// Copy a non-[Continuation] [Definition]. | 2642 /// Copy a non-[Continuation] [Definition]. |
| 2691 Definition copy(Definition node) { | 2643 Definition copy(Definition node) { |
| 2692 assert (node is! Continuation); | 2644 assert (node is! Continuation); |
| 2693 return putCopy(node, visit(node)); | 2645 return putCopy(node, visit(node)); |
| 2694 } | 2646 } |
| 2695 | 2647 |
| 2696 Definition visit(Node node) => node.accept(this); | 2648 Definition visit(Node node) => node.accept(this); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 Definition visitSetStatic(SetStatic node) { | 2698 Definition visitSetStatic(SetStatic node) { |
| 2747 return new SetStatic(node.element, getCopy(node.value), | 2699 return new SetStatic(node.element, getCopy(node.value), |
| 2748 node.sourceInformation); | 2700 node.sourceInformation); |
| 2749 } | 2701 } |
| 2750 | 2702 |
| 2751 Definition visitSetField(SetField node) { | 2703 Definition visitSetField(SetField node) { |
| 2752 return new SetField(getCopy(node.object), node.field, getCopy(node.value)); | 2704 return new SetField(getCopy(node.object), node.field, getCopy(node.value)); |
| 2753 } | 2705 } |
| 2754 | 2706 |
| 2755 Definition visitGetLazyStatic(GetLazyStatic node) { | 2707 Definition visitGetLazyStatic(GetLazyStatic node) { |
| 2756 return new GetLazyStatic(node.element, | 2708 return new GetLazyStatic(node.element, node.sourceInformation); |
| 2757 isFinal: node.isFinal, | |
| 2758 sourceInformation: node.sourceInformation); | |
| 2759 } | 2709 } |
| 2760 | 2710 |
| 2761 Definition visitAwait(Await node) { | 2711 Definition visitAwait(Await node) { |
| 2762 return new Await(getCopy(node.input)); | 2712 return new Await(getCopy(node.input)); |
| 2763 } | 2713 } |
| 2764 | 2714 |
| 2765 Definition visitYield(Yield node) { | 2715 Definition visitYield(Yield node) { |
| 2766 return new Yield(getCopy(node.input), node.hasStar); | 2716 return new Yield(getCopy(node.input), node.hasStar); |
| 2767 } | 2717 } |
| 2768 | 2718 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2781 | 2731 |
| 2782 Definition visitParameter(Parameter node) { | 2732 Definition visitParameter(Parameter node) { |
| 2783 return new Parameter(node.hint); | 2733 return new Parameter(node.hint); |
| 2784 } | 2734 } |
| 2785 | 2735 |
| 2786 Definition visitMutableVariable(MutableVariable node) { | 2736 Definition visitMutableVariable(MutableVariable node) { |
| 2787 return new MutableVariable(node.hint); | 2737 return new MutableVariable(node.hint); |
| 2788 } | 2738 } |
| 2789 | 2739 |
| 2790 Definition visitGetStatic(GetStatic node) { | 2740 Definition visitGetStatic(GetStatic node) { |
| 2791 if (node.witness != null) { | 2741 return new GetStatic(node.element, node.sourceInformation); |
| 2792 return new GetStatic.witnessed(node.element, | |
| 2793 getCopy(node.witness), | |
| 2794 sourceInformation: node.sourceInformation); | |
| 2795 } else { | |
| 2796 return new GetStatic(node.element, | |
| 2797 isFinal: node.isFinal, | |
| 2798 sourceInformation: node.sourceInformation); | |
| 2799 } | |
| 2800 } | 2742 } |
| 2801 | 2743 |
| 2802 Definition visitInterceptor(Interceptor node) { | 2744 Definition visitInterceptor(Interceptor node) { |
| 2803 return new Interceptor(getCopy(node.input), node.sourceInformation) | 2745 return new Interceptor(getCopy(node.input), node.sourceInformation) |
| 2804 ..interceptedClasses.addAll(node.interceptedClasses); | 2746 ..interceptedClasses.addAll(node.interceptedClasses); |
| 2805 } | 2747 } |
| 2806 | 2748 |
| 2807 Definition visitCreateInstance(CreateInstance node) { | 2749 Definition visitCreateInstance(CreateInstance node) { |
| 2808 return new CreateInstance( | 2750 return new CreateInstance( |
| 2809 node.classElement, | 2751 node.classElement, |
| 2810 getList(node.arguments), | 2752 getList(node.arguments), |
| 2811 node.typeInformation == null ? null : getCopy(node.typeInformation), | 2753 node.typeInformation == null ? null : getCopy(node.typeInformation), |
| 2812 node.sourceInformation); | 2754 node.sourceInformation); |
| 2813 } | 2755 } |
| 2814 | 2756 |
| 2815 Definition visitGetField(GetField node) { | 2757 Definition visitGetField(GetField node) { |
| 2816 return new GetField(getCopy(node.object), node.field, | 2758 return new GetField(getCopy(node.object), node.field); |
| 2817 isFinal: node.isFinal); | |
| 2818 } | 2759 } |
| 2819 | 2760 |
| 2820 Definition visitCreateBox(CreateBox node) { | 2761 Definition visitCreateBox(CreateBox node) { |
| 2821 return new CreateBox(); | 2762 return new CreateBox(); |
| 2822 } | 2763 } |
| 2823 | 2764 |
| 2824 Definition visitReifyRuntimeType(ReifyRuntimeType node) { | 2765 Definition visitReifyRuntimeType(ReifyRuntimeType node) { |
| 2825 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation); | 2766 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation); |
| 2826 } | 2767 } |
| 2827 | 2768 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2854 } | 2795 } |
| 2855 | 2796 |
| 2856 Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) { | 2797 Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) { |
| 2857 return new ApplyBuiltinMethod(node.method, getCopy(node.receiver), | 2798 return new ApplyBuiltinMethod(node.method, getCopy(node.receiver), |
| 2858 getList(node.arguments), | 2799 getList(node.arguments), |
| 2859 node.sourceInformation, | 2800 node.sourceInformation, |
| 2860 receiverIsNotNull: node.receiverIsNotNull); | 2801 receiverIsNotNull: node.receiverIsNotNull); |
| 2861 } | 2802 } |
| 2862 | 2803 |
| 2863 Definition visitGetLength(GetLength node) { | 2804 Definition visitGetLength(GetLength node) { |
| 2864 return new GetLength(getCopy(node.object), isFinal: node.isFinal); | 2805 return new GetLength(getCopy(node.object)); |
| 2865 } | 2806 } |
| 2866 | 2807 |
| 2867 Definition visitGetIndex(GetIndex node) { | 2808 Definition visitGetIndex(GetIndex node) { |
| 2868 return new GetIndex(getCopy(node.object), getCopy(node.index)); | 2809 return new GetIndex(getCopy(node.object), getCopy(node.index)); |
| 2869 } | 2810 } |
| 2870 | 2811 |
| 2871 Definition visitSetIndex(SetIndex node) { | 2812 Definition visitSetIndex(SetIndex node) { |
| 2872 return new SetIndex(getCopy(node.object), getCopy(node.index), | 2813 return new SetIndex(getCopy(node.object), getCopy(node.index), |
| 2873 getCopy(node.value)); | 2814 getCopy(node.value)); |
| 2874 } | 2815 } |
| 2875 | 2816 |
| 2876 Definition visitRefinement(Refinement node) { | 2817 Definition visitRefinement(Refinement node) { |
| 2877 return new Refinement(getCopy(node.value), node.refineType); | 2818 return new Refinement(getCopy(node.value), node.refineType); |
| 2878 } | 2819 } |
| 2879 | 2820 |
| 2880 Definition visitBoundsCheck(BoundsCheck node) { | 2821 Definition visitBoundsCheck(BoundsCheck node) { |
| 2881 if (node.hasNoChecks) { | 2822 if (node.hasNoChecks) { |
| 2882 return new BoundsCheck.noCheck(getCopy(node.object), | 2823 return new BoundsCheck.noCheck(getCopy(node.object), |
| 2883 node.sourceInformation); | 2824 node.sourceInformation); |
| 2884 } else { | 2825 } else { |
| 2885 return new BoundsCheck(getCopy(node.object), getCopy(node.index), | 2826 return new BoundsCheck(getCopy(node.object), getCopy(node.index), |
| 2886 getCopyOrNull(node.length), | 2827 node.length == null ? null : getCopy(node.length), |
| 2887 node.checks, | 2828 node.checks, |
| 2888 node.sourceInformation); | 2829 node.sourceInformation); |
| 2889 } | 2830 } |
| 2890 } | 2831 } |
| 2891 | 2832 |
| 2892 Definition visitReceiverCheck(ReceiverCheck node) { | 2833 Definition visitReceiverCheck(ReceiverCheck node) { |
| 2893 return new ReceiverCheck(getCopy(node.value), | 2834 return new ReceiverCheck(getCopy(node.value), |
| 2894 node.selector, | 2835 node.selector, |
| 2895 node.sourceInformation, | 2836 node.sourceInformation, |
| 2896 condition: getCopyOrNull(node.condition), | 2837 condition: node.condition == null ? null : getCopy(node.condition), |
| 2897 useSelector: node.useSelector, | 2838 useSelector: node.useSelector, |
| 2898 isNullCheck: node.isNullCheck); | 2839 isNullCheck: node.isNullCheck); |
| 2899 } | 2840 } |
| 2900 | 2841 |
| 2901 Definition visitForeignCode(ForeignCode node) { | 2842 Definition visitForeignCode(ForeignCode node) { |
| 2902 return new ForeignCode(node.codeTemplate, node.storedType, | 2843 return new ForeignCode(node.codeTemplate, node.storedType, |
| 2903 getList(node.arguments), | 2844 getList(node.arguments), |
| 2904 node.nativeBehavior, | 2845 node.nativeBehavior, |
| 2905 dependency: node.dependency); | 2846 dependency: node.dependency); |
| 2906 } | 2847 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3039 plug(new Branch.loose(_definitions.getCopy(node.condition), | 2980 plug(new Branch.loose(_definitions.getCopy(node.condition), |
| 3040 _copies[node.trueContinuation.definition], | 2981 _copies[node.trueContinuation.definition], |
| 3041 _copies[node.falseContinuation.definition]) | 2982 _copies[node.falseContinuation.definition]) |
| 3042 ..isStrictCheck = node.isStrictCheck); | 2983 ..isStrictCheck = node.isStrictCheck); |
| 3043 } | 2984 } |
| 3044 | 2985 |
| 3045 visitUnreachable(Unreachable node) { | 2986 visitUnreachable(Unreachable node) { |
| 3046 plug(new Unreachable()); | 2987 plug(new Unreachable()); |
| 3047 } | 2988 } |
| 3048 } | 2989 } |
| OLD | NEW |