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