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 int get effectFlags => Effects.none; | |
|
Siggi Cherem (dart-lang)
2016/02/17 20:53:23
+ dartdoc
Also, low-priority but, what do you thi
asgerf
2016/02/29 12:48:17
Done.
| |
| 249 | |
| 245 /// True if this primitive has a value that can be used by other expressions. | 250 /// True if this primitive has a value that can be used by other expressions. |
| 246 bool get hasValue; | 251 bool get hasValue; |
| 247 | 252 |
| 248 /// True if the primitive can be removed, assuming it has no uses | 253 /// True if the primitive can be removed, assuming it has no uses |
| 249 /// (this getter does not check if there are any uses). | 254 /// (this getter does not check if there are any uses). |
| 250 /// | 255 /// |
| 251 /// False must be returned for primitives that may throw, diverge, or have | 256 /// False must be returned for primitives that may throw, diverge, or have |
| 252 /// observable side-effects. | 257 /// observable side-effects. |
| 253 bool get isSafeForElimination; | 258 bool get isSafeForElimination; |
| 254 | 259 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 replaceUsesWith(newPrimitive); | 343 replaceUsesWith(newPrimitive); |
| 339 destroy(); | 344 destroy(); |
| 340 LetPrim let = parent; | 345 LetPrim let = parent; |
| 341 fragment.insertBelow(let); | 346 fragment.insertBelow(let); |
| 342 let.remove(); | 347 let.remove(); |
| 343 } | 348 } |
| 344 } | 349 } |
| 345 | 350 |
| 346 /// A primitive that is generally not safe for elimination, but may be marked | 351 /// A primitive that is generally not safe for elimination, but may be marked |
| 347 /// as safe by type propagation | 352 /// 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 { | 353 abstract class UnsafePrimitive extends Primitive { |
| 354 int effectFlags = Effects.all; | |
| 352 bool isSafeForElimination = false; | 355 bool isSafeForElimination = false; |
| 353 bool isSafeForReordering = false; | 356 bool isSafeForReordering = false; |
| 354 } | 357 } |
| 355 | 358 |
| 356 /// Operands to invocations and primitives are always variables. They point to | 359 /// Operands to invocations and primitives are always variables. They point to |
| 357 /// their definition and are doubly-linked into a list of occurrences. | 360 /// their definition and are doubly-linked into a list of occurrences. |
| 358 class Reference<T extends Definition<T>> { | 361 class Reference<T extends Definition<T>> { |
| 359 T definition; | 362 T definition; |
| 360 Reference<T> previous; | 363 Reference<T> previous; |
| 361 Reference<T> next; | 364 Reference<T> next; |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1076 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); | 1079 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); |
| 1077 | 1080 |
| 1078 bool get hasValue => true; | 1081 bool get hasValue => true; |
| 1079 bool get isSafeForElimination => false; | 1082 bool get isSafeForElimination => false; |
| 1080 bool get isSafeForReordering => false; | 1083 bool get isSafeForReordering => false; |
| 1081 | 1084 |
| 1082 void setParentPointers() { | 1085 void setParentPointers() { |
| 1083 receiver.parent = this; | 1086 receiver.parent = this; |
| 1084 _setParentsOnList(arguments, this); | 1087 _setParentsOnList(arguments, this); |
| 1085 } | 1088 } |
| 1089 | |
| 1090 int get effectFlags => getEffectsOfBuiltinMethod(method); | |
| 1086 } | 1091 } |
| 1087 | 1092 |
| 1088 /// Throw a value. | 1093 /// Throw a value. |
| 1089 /// | 1094 /// |
| 1090 /// Throw is an expression, i.e., it always occurs in tail position with | 1095 /// Throw is an expression, i.e., it always occurs in tail position with |
| 1091 /// respect to a body or expression. | 1096 /// respect to a body or expression. |
| 1092 class Throw extends TailExpression { | 1097 class Throw extends TailExpression { |
| 1093 Reference<Primitive> value; | 1098 Reference<Primitive> value; |
| 1094 | 1099 |
| 1095 Throw(Primitive value) : value = new Reference<Primitive>(value); | 1100 Throw(Primitive value) : value = new Reference<Primitive>(value); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1271 accept(Visitor visitor) => visitor.visitSetField(this); | 1276 accept(Visitor visitor) => visitor.visitSetField(this); |
| 1272 | 1277 |
| 1273 bool get hasValue => false; | 1278 bool get hasValue => false; |
| 1274 bool get isSafeForElimination => false; | 1279 bool get isSafeForElimination => false; |
| 1275 bool get isSafeForReordering => false; | 1280 bool get isSafeForReordering => false; |
| 1276 | 1281 |
| 1277 void setParentPointers() { | 1282 void setParentPointers() { |
| 1278 object.parent = this; | 1283 object.parent = this; |
| 1279 value.parent = this; | 1284 value.parent = this; |
| 1280 } | 1285 } |
| 1286 | |
| 1287 int get effectFlags => Effects.changesInstanceField; | |
| 1281 } | 1288 } |
| 1282 | 1289 |
| 1283 /// Directly reads from a field on a given object. | 1290 /// Directly reads from a field on a given object. |
| 1284 /// | 1291 /// |
| 1285 /// The [object] must either be `null` or an object that has [field]. | 1292 /// The [object] must either be `null` or an object that has [field]. |
| 1286 class GetField extends Primitive { | 1293 class GetField extends Primitive { |
| 1287 final Reference<Primitive> object; | 1294 final Reference<Primitive> object; |
| 1288 FieldElement field; | 1295 FieldElement field; |
| 1296 bool isFinal = false; | |
|
Siggi Cherem (dart-lang)
2016/02/17 20:53:23
+dartdoc
asgerf
2016/02/29 12:48:17
Done.
| |
| 1289 | 1297 |
| 1290 /// True if the object is known not to be null. | 1298 /// True if the object is known not to be null. |
| 1291 // TODO(asgerf): This is a placeholder until we agree on how to track | 1299 // TODO(asgerf): This is a placeholder until we agree on how to track |
| 1292 // side effects. | 1300 // side effects. |
| 1293 bool objectIsNotNull = false; | 1301 bool objectIsNotNull = false; |
| 1294 | 1302 |
| 1295 GetField(Primitive object, this.field) | 1303 GetField(Primitive object, this.field) |
| 1296 : this.object = new Reference<Primitive>(object); | 1304 : this.object = new Reference<Primitive>(object); |
| 1297 | 1305 |
| 1298 accept(Visitor visitor) => visitor.visitGetField(this); | 1306 accept(Visitor visitor) => visitor.visitGetField(this); |
| 1299 | 1307 |
| 1300 bool get hasValue => true; | 1308 bool get hasValue => true; |
| 1301 bool get isSafeForElimination => objectIsNotNull; | 1309 bool get isSafeForElimination => objectIsNotNull; |
| 1302 bool get isSafeForReordering => false; | 1310 bool get isSafeForReordering => false; |
| 1303 | 1311 |
| 1304 toString() => 'GetField($field)'; | 1312 toString() => 'GetField($field)'; |
| 1305 | 1313 |
| 1306 void setParentPointers() { | 1314 void setParentPointers() { |
| 1307 object.parent = this; | 1315 object.parent = this; |
| 1308 } | 1316 } |
| 1317 | |
| 1318 int get effectFlags => isFinal ? 0 : Effects.dependsOnInstanceField; | |
| 1309 } | 1319 } |
| 1310 | 1320 |
| 1311 /// Get the length of a string or native list. | 1321 /// Get the length of a string or native list. |
| 1312 class GetLength extends Primitive { | 1322 class GetLength extends Primitive { |
| 1313 final Reference<Primitive> object; | 1323 final Reference<Primitive> object; |
| 1324 bool isFinal = false; | |
| 1314 | 1325 |
| 1315 /// True if the object is known not to be null. | 1326 /// True if the object is known not to be null. |
| 1316 bool objectIsNotNull = false; | 1327 bool objectIsNotNull = false; |
| 1317 | 1328 |
| 1318 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); | 1329 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); |
| 1319 | 1330 |
| 1320 bool get hasValue => true; | 1331 bool get hasValue => true; |
| 1321 bool get isSafeForElimination => objectIsNotNull; | 1332 bool get isSafeForElimination => objectIsNotNull; |
| 1322 bool get isSafeForReordering => false; | 1333 bool get isSafeForReordering => false; |
| 1323 | 1334 |
| 1324 accept(Visitor v) => v.visitGetLength(this); | 1335 accept(Visitor v) => v.visitGetLength(this); |
| 1325 | 1336 |
| 1326 void setParentPointers() { | 1337 void setParentPointers() { |
| 1327 object.parent = this; | 1338 object.parent = this; |
| 1328 } | 1339 } |
| 1340 | |
| 1341 int get effectFlags => isFinal ? 0 : Effects.dependsOnIndexableLength; | |
| 1329 } | 1342 } |
| 1330 | 1343 |
| 1331 /// Read an entry from an indexable object. | 1344 /// Read an entry from an indexable object. |
| 1332 /// | 1345 /// |
| 1333 /// [object] must be null or an indexable object, and [index] must be | 1346 /// [object] must be null or an indexable object, and [index] must be |
| 1334 /// an integer where `0 <= index < object.length`. | 1347 /// an integer where `0 <= index < object.length`. |
| 1335 class GetIndex extends Primitive { | 1348 class GetIndex extends Primitive { |
| 1336 final Reference<Primitive> object; | 1349 final Reference<Primitive> object; |
| 1337 final Reference<Primitive> index; | 1350 final Reference<Primitive> index; |
| 1338 | 1351 |
| 1339 /// True if the object is known not to be null. | 1352 /// True if the object is known not to be null. |
| 1340 bool objectIsNotNull = false; | 1353 bool objectIsNotNull = false; |
| 1341 | 1354 |
| 1342 GetIndex(Primitive object, Primitive index) | 1355 GetIndex(Primitive object, Primitive index) |
| 1343 : this.object = new Reference<Primitive>(object), | 1356 : this.object = new Reference<Primitive>(object), |
| 1344 this.index = new Reference<Primitive>(index); | 1357 this.index = new Reference<Primitive>(index); |
| 1345 | 1358 |
| 1346 bool get hasValue => true; | 1359 bool get hasValue => true; |
| 1347 bool get isSafeForElimination => objectIsNotNull; | 1360 bool get isSafeForElimination => objectIsNotNull; |
| 1348 bool get isSafeForReordering => false; | 1361 bool get isSafeForReordering => false; |
| 1349 | 1362 |
| 1350 accept(Visitor v) => v.visitGetIndex(this); | 1363 accept(Visitor v) => v.visitGetIndex(this); |
| 1351 | 1364 |
| 1352 void setParentPointers() { | 1365 void setParentPointers() { |
| 1353 object.parent = this; | 1366 object.parent = this; |
| 1354 index.parent = this; | 1367 index.parent = this; |
| 1355 } | 1368 } |
| 1369 | |
| 1370 int get effectFlags => Effects.dependsOnIndexableContent; | |
| 1356 } | 1371 } |
| 1357 | 1372 |
| 1358 /// Set an entry on a native list. | 1373 /// Set an entry on a native list. |
| 1359 /// | 1374 /// |
| 1360 /// [object] must be null or a native list, and [index] must be an integer. | 1375 /// [object] must be null or a native list, and [index] must be an integer |
| 1376 /// within the bounds of the indexable object. | |
| 1377 /// | |
| 1378 /// [SetIndex] may not be used to alter the length of a JS array. | |
| 1361 /// | 1379 /// |
| 1362 /// The primitive itself has no value and may not be referenced. | 1380 /// The primitive itself has no value and may not be referenced. |
| 1363 class SetIndex extends Primitive { | 1381 class SetIndex extends Primitive { |
| 1364 final Reference<Primitive> object; | 1382 final Reference<Primitive> object; |
| 1365 final Reference<Primitive> index; | 1383 final Reference<Primitive> index; |
| 1366 final Reference<Primitive> value; | 1384 final Reference<Primitive> value; |
| 1367 | 1385 |
| 1368 SetIndex(Primitive object, Primitive index, Primitive value) | 1386 SetIndex(Primitive object, Primitive index, Primitive value) |
| 1369 : this.object = new Reference<Primitive>(object), | 1387 : this.object = new Reference<Primitive>(object), |
| 1370 this.index = new Reference<Primitive>(index), | 1388 this.index = new Reference<Primitive>(index), |
| 1371 this.value = new Reference<Primitive>(value); | 1389 this.value = new Reference<Primitive>(value); |
| 1372 | 1390 |
| 1373 bool get hasValue => false; | 1391 bool get hasValue => false; |
| 1374 bool get isSafeForElimination => false; | 1392 bool get isSafeForElimination => false; |
| 1375 bool get isSafeForReordering => false; | 1393 bool get isSafeForReordering => false; |
| 1376 | 1394 |
| 1377 accept(Visitor v) => v.visitSetIndex(this); | 1395 accept(Visitor v) => v.visitSetIndex(this); |
| 1378 | 1396 |
| 1379 void setParentPointers() { | 1397 void setParentPointers() { |
| 1380 object.parent = this; | 1398 object.parent = this; |
| 1381 index.parent = this; | 1399 index.parent = this; |
| 1382 value.parent = this; | 1400 value.parent = this; |
| 1383 } | 1401 } |
| 1402 | |
| 1403 int get effectFlags => Effects.changesIndexableContent; | |
| 1384 } | 1404 } |
| 1385 | 1405 |
| 1386 /// Reads the value of a static field or tears off a static method. | 1406 /// Reads the value of a static field or tears off a static method. |
| 1387 /// | 1407 /// |
| 1388 /// If [GetStatic] is used to load a lazily initialized static field, it must | 1408 /// If [GetStatic] is used to load a lazily initialized static field, it must |
| 1389 /// have been initialized beforehand, and a [witness] must be set to restrict | 1409 /// have been initialized beforehand, and a [witness] must be set to restrict |
| 1390 /// code motion. | 1410 /// code motion. |
| 1391 class GetStatic extends Primitive { | 1411 class GetStatic extends Primitive { |
| 1392 /// Can be [FieldElement] or [FunctionElement]. | 1412 /// Can be [FieldElement] or [FunctionElement]. |
| 1393 final Element element; | 1413 final Element element; |
| 1394 final SourceInformation sourceInformation; | 1414 final SourceInformation sourceInformation; |
| 1415 bool isFinal = false; | |
| 1395 | 1416 |
| 1396 /// If reading a lazily initialized field, [witness] must refer to a node | 1417 /// If reading a lazily initialized field, [witness] must refer to a node |
| 1397 /// that initializes the field or always occurs after the field initializer. | 1418 /// that initializes the field or always occurs after the field initializer. |
| 1398 /// | 1419 /// |
| 1399 /// The value of the witness is not used. | 1420 /// The value of the witness is not used. |
| 1400 Reference<Primitive> witness; | 1421 Reference<Primitive> witness; |
| 1401 | 1422 |
| 1402 GetStatic(this.element, [this.sourceInformation]); | 1423 GetStatic(this.element, [this.sourceInformation]); |
| 1403 | 1424 |
| 1404 /// Read a lazily initialized static field that is known to have been | 1425 /// Read a lazily initialized static field that is known to have been |
| 1405 /// initialized by [witness] or earlier. | 1426 /// initialized by [witness] or earlier. |
| 1406 GetStatic.witnessed(this.element, Primitive witness, [this.sourceInformation]) | 1427 GetStatic.witnessed(this.element, Primitive witness, [this.sourceInformation]) |
| 1407 : witness = witness == null ? null : new Reference<Primitive>(witness); | 1428 : witness = witness == null ? null : new Reference<Primitive>(witness); |
| 1408 | 1429 |
| 1409 accept(Visitor visitor) => visitor.visitGetStatic(this); | 1430 accept(Visitor visitor) => visitor.visitGetStatic(this); |
| 1410 | 1431 |
| 1411 bool get hasValue => true; | 1432 bool get hasValue => true; |
| 1412 bool get isSafeForElimination => true; | 1433 bool get isSafeForElimination => true; |
| 1413 bool get isSafeForReordering { | 1434 bool get isSafeForReordering => isFinal; |
| 1414 return element is FunctionElement || element.isFinal; | |
| 1415 } | |
| 1416 | 1435 |
| 1417 void setParentPointers() { | 1436 void setParentPointers() { |
| 1418 if (witness != null) { | 1437 if (witness != null) { |
| 1419 witness.parent = this; | 1438 witness.parent = this; |
| 1420 } | 1439 } |
| 1421 } | 1440 } |
| 1441 | |
| 1442 int get effectFlags => isFinal ? 0 : Effects.dependsOnStaticField; | |
| 1422 } | 1443 } |
| 1423 | 1444 |
| 1424 /// Sets the value of a static field. | 1445 /// Sets the value of a static field. |
| 1425 class SetStatic extends Primitive { | 1446 class SetStatic extends Primitive { |
| 1426 final FieldElement element; | 1447 final FieldElement element; |
| 1427 final Reference<Primitive> value; | 1448 final Reference<Primitive> value; |
| 1428 final SourceInformation sourceInformation; | 1449 final SourceInformation sourceInformation; |
| 1429 | 1450 |
| 1430 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 1451 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
| 1431 : this.value = new Reference<Primitive>(value); | 1452 : this.value = new Reference<Primitive>(value); |
| 1432 | 1453 |
| 1433 accept(Visitor visitor) => visitor.visitSetStatic(this); | 1454 accept(Visitor visitor) => visitor.visitSetStatic(this); |
| 1434 | 1455 |
| 1435 bool get hasValue => false; | 1456 bool get hasValue => false; |
| 1436 bool get isSafeForElimination => false; | 1457 bool get isSafeForElimination => false; |
| 1437 bool get isSafeForReordering => false; | 1458 bool get isSafeForReordering => false; |
| 1438 | 1459 |
| 1439 void setParentPointers() { | 1460 void setParentPointers() { |
| 1440 value.parent = this; | 1461 value.parent = this; |
| 1441 } | 1462 } |
| 1463 | |
| 1464 int get effectFlags => Effects.changesStaticField; | |
| 1442 } | 1465 } |
| 1443 | 1466 |
| 1444 /// Reads the value of a lazily initialized static field. | 1467 /// Reads the value of a lazily initialized static field. |
| 1445 /// | 1468 /// |
| 1446 /// If the field has not yet been initialized, its initializer is evaluated | 1469 /// If the field has not yet been initialized, its initializer is evaluated |
| 1447 /// and assigned to the field. | 1470 /// and assigned to the field. |
| 1448 class GetLazyStatic extends UnsafePrimitive { | 1471 class GetLazyStatic extends UnsafePrimitive { |
| 1449 final FieldElement element; | 1472 final FieldElement element; |
| 1450 final SourceInformation sourceInformation; | 1473 final SourceInformation sourceInformation; |
| 1474 bool isFinal = false; | |
| 1451 | 1475 |
| 1452 GetLazyStatic(this.element, [this.sourceInformation]); | 1476 GetLazyStatic(this.element, [this.sourceInformation]); |
| 1453 | 1477 |
| 1454 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); | 1478 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
| 1455 | 1479 |
| 1456 bool get hasValue => true; | 1480 bool get hasValue => true; |
| 1457 | 1481 |
| 1458 void setParentPointers() {} | 1482 void setParentPointers() {} |
| 1483 | |
| 1484 // TODO(asgerf): Track side effects of lazy field initializers. | |
| 1485 int get effectFlags => Effects.all; | |
| 1459 } | 1486 } |
| 1460 | 1487 |
| 1461 /// Creates an object for holding boxed variables captured by a closure. | 1488 /// Creates an object for holding boxed variables captured by a closure. |
| 1462 class CreateBox extends Primitive { | 1489 class CreateBox extends Primitive { |
| 1463 accept(Visitor visitor) => visitor.visitCreateBox(this); | 1490 accept(Visitor visitor) => visitor.visitCreateBox(this); |
| 1464 | 1491 |
| 1465 bool get hasValue => true; | 1492 bool get hasValue => true; |
| 1466 bool get isSafeForElimination => true; | 1493 bool get isSafeForElimination => true; |
| 1467 bool get isSafeForReordering => true; | 1494 bool get isSafeForReordering => true; |
| 1468 | 1495 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1568 | 1595 |
| 1569 class ForeignCode extends UnsafePrimitive { | 1596 class ForeignCode extends UnsafePrimitive { |
| 1570 final js.Template codeTemplate; | 1597 final js.Template codeTemplate; |
| 1571 final TypeMask storedType; | 1598 final TypeMask storedType; |
| 1572 final List<Reference<Primitive>> arguments; | 1599 final List<Reference<Primitive>> arguments; |
| 1573 final native.NativeBehavior nativeBehavior; | 1600 final native.NativeBehavior nativeBehavior; |
| 1574 final FunctionElement dependency; | 1601 final FunctionElement dependency; |
| 1575 | 1602 |
| 1576 ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments, | 1603 ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments, |
| 1577 this.nativeBehavior, {this.dependency}) | 1604 this.nativeBehavior, {this.dependency}) |
| 1578 : this.arguments = _referenceList(arguments); | 1605 : this.arguments = _referenceList(arguments) { |
| 1606 effectFlags = Effects.from(nativeBehavior.sideEffects); | |
| 1607 } | |
| 1579 | 1608 |
| 1580 accept(Visitor visitor) => visitor.visitForeignCode(this); | 1609 accept(Visitor visitor) => visitor.visitForeignCode(this); |
| 1581 | 1610 |
| 1582 bool get hasValue => true; | 1611 bool get hasValue => true; |
| 1583 | 1612 |
| 1584 void setParentPointers() { | 1613 void setParentPointers() { |
| 1585 _setParentsOnList(arguments, this); | 1614 _setParentsOnList(arguments, this); |
| 1586 } | 1615 } |
| 1587 | 1616 |
| 1588 bool isNullGuardOnNullFirstArgument() { | 1617 bool isNullGuardOnNullFirstArgument() { |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2557 Variable originalVariable = original; | 2586 Variable originalVariable = original; |
| 2558 copy.type = originalVariable.type; | 2587 copy.type = originalVariable.type; |
| 2559 copy.hint = originalVariable.hint; | 2588 copy.hint = originalVariable.hint; |
| 2560 } | 2589 } |
| 2561 return _copies[original] = copy; | 2590 return _copies[original] = copy; |
| 2562 } | 2591 } |
| 2563 | 2592 |
| 2564 /// Get the copy of a [Reference]'s definition from the map. | 2593 /// Get the copy of a [Reference]'s definition from the map. |
| 2565 Definition getCopy(Reference reference) => _copies[reference.definition]; | 2594 Definition getCopy(Reference reference) => _copies[reference.definition]; |
| 2566 | 2595 |
| 2596 /// Get the copy of a [Reference]'s definition from the map. | |
| 2597 Definition getCopyOrNull(Reference reference) => reference == null | |
| 2598 ? null | |
| 2599 : getCopy(reference); | |
| 2600 | |
| 2567 /// Map a list of [Reference]s to the list of their definition's copies. | 2601 /// Map a list of [Reference]s to the list of their definition's copies. |
| 2568 List<Definition> getList(List<Reference> list) => list.map(getCopy).toList(); | 2602 List<Definition> getList(List<Reference> list) => list.map(getCopy).toList(); |
| 2569 | 2603 |
| 2570 /// Copy a non-[Continuation] [Definition]. | 2604 /// Copy a non-[Continuation] [Definition]. |
| 2571 Definition copy(Definition node) { | 2605 Definition copy(Definition node) { |
| 2572 assert (node is! Continuation); | 2606 assert (node is! Continuation); |
| 2573 return putCopy(node, visit(node)); | 2607 return putCopy(node, visit(node)); |
| 2574 } | 2608 } |
| 2575 | 2609 |
| 2576 Definition visit(Node node) => node.accept(this); | 2610 Definition visit(Node node) => node.accept(this); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2626 Definition visitSetStatic(SetStatic node) { | 2660 Definition visitSetStatic(SetStatic node) { |
| 2627 return new SetStatic(node.element, getCopy(node.value), | 2661 return new SetStatic(node.element, getCopy(node.value), |
| 2628 node.sourceInformation); | 2662 node.sourceInformation); |
| 2629 } | 2663 } |
| 2630 | 2664 |
| 2631 Definition visitSetField(SetField node) { | 2665 Definition visitSetField(SetField node) { |
| 2632 return new SetField(getCopy(node.object), node.field, getCopy(node.value)); | 2666 return new SetField(getCopy(node.object), node.field, getCopy(node.value)); |
| 2633 } | 2667 } |
| 2634 | 2668 |
| 2635 Definition visitGetLazyStatic(GetLazyStatic node) { | 2669 Definition visitGetLazyStatic(GetLazyStatic node) { |
| 2636 return new GetLazyStatic(node.element, node.sourceInformation); | 2670 return new GetLazyStatic(node.element, node.sourceInformation) |
| 2671 ..isFinal = node.isFinal; | |
| 2637 } | 2672 } |
| 2638 | 2673 |
| 2639 Definition visitAwait(Await node) { | 2674 Definition visitAwait(Await node) { |
| 2640 return new Await(getCopy(node.input)); | 2675 return new Await(getCopy(node.input)); |
| 2641 } | 2676 } |
| 2642 | 2677 |
| 2643 Definition visitYield(Yield node) { | 2678 Definition visitYield(Yield node) { |
| 2644 return new Yield(getCopy(node.input), node.hasStar); | 2679 return new Yield(getCopy(node.input), node.hasStar); |
| 2645 } | 2680 } |
| 2646 | 2681 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2659 | 2694 |
| 2660 Definition visitParameter(Parameter node) { | 2695 Definition visitParameter(Parameter node) { |
| 2661 return new Parameter(node.hint); | 2696 return new Parameter(node.hint); |
| 2662 } | 2697 } |
| 2663 | 2698 |
| 2664 Definition visitMutableVariable(MutableVariable node) { | 2699 Definition visitMutableVariable(MutableVariable node) { |
| 2665 return new MutableVariable(node.hint); | 2700 return new MutableVariable(node.hint); |
| 2666 } | 2701 } |
| 2667 | 2702 |
| 2668 Definition visitGetStatic(GetStatic node) { | 2703 Definition visitGetStatic(GetStatic node) { |
| 2669 return new GetStatic(node.element, node.sourceInformation); | 2704 if (node.witness != null) { |
| 2705 return new GetStatic.witnessed(node.element, | |
| 2706 getCopy(node.witness), | |
| 2707 node.sourceInformation); | |
| 2708 } else { | |
| 2709 return new GetStatic(node.element, node.sourceInformation); | |
| 2710 } | |
| 2670 } | 2711 } |
| 2671 | 2712 |
| 2672 Definition visitInterceptor(Interceptor node) { | 2713 Definition visitInterceptor(Interceptor node) { |
| 2673 return new Interceptor(getCopy(node.input), node.sourceInformation) | 2714 return new Interceptor(getCopy(node.input), node.sourceInformation) |
| 2674 ..interceptedClasses.addAll(node.interceptedClasses); | 2715 ..interceptedClasses.addAll(node.interceptedClasses); |
| 2675 } | 2716 } |
| 2676 | 2717 |
| 2677 Definition visitCreateInstance(CreateInstance node) { | 2718 Definition visitCreateInstance(CreateInstance node) { |
| 2678 return new CreateInstance( | 2719 return new CreateInstance( |
| 2679 node.classElement, | 2720 node.classElement, |
| 2680 getList(node.arguments), | 2721 getList(node.arguments), |
| 2681 node.typeInformation == null ? null : getCopy(node.typeInformation), | 2722 node.typeInformation == null ? null : getCopy(node.typeInformation), |
| 2682 node.sourceInformation); | 2723 node.sourceInformation); |
| 2683 } | 2724 } |
| 2684 | 2725 |
| 2685 Definition visitGetField(GetField node) { | 2726 Definition visitGetField(GetField node) { |
| 2686 return new GetField(getCopy(node.object), node.field); | 2727 return new GetField(getCopy(node.object), node.field) |
| 2728 ..isFinal = node.isFinal; | |
| 2687 } | 2729 } |
| 2688 | 2730 |
| 2689 Definition visitCreateBox(CreateBox node) { | 2731 Definition visitCreateBox(CreateBox node) { |
| 2690 return new CreateBox(); | 2732 return new CreateBox(); |
| 2691 } | 2733 } |
| 2692 | 2734 |
| 2693 Definition visitReifyRuntimeType(ReifyRuntimeType node) { | 2735 Definition visitReifyRuntimeType(ReifyRuntimeType node) { |
| 2694 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation); | 2736 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation); |
| 2695 } | 2737 } |
| 2696 | 2738 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2745 Definition visitRefinement(Refinement node) { | 2787 Definition visitRefinement(Refinement node) { |
| 2746 return new Refinement(getCopy(node.value), node.refineType); | 2788 return new Refinement(getCopy(node.value), node.refineType); |
| 2747 } | 2789 } |
| 2748 | 2790 |
| 2749 Definition visitBoundsCheck(BoundsCheck node) { | 2791 Definition visitBoundsCheck(BoundsCheck node) { |
| 2750 if (node.hasNoChecks) { | 2792 if (node.hasNoChecks) { |
| 2751 return new BoundsCheck.noCheck(getCopy(node.object), | 2793 return new BoundsCheck.noCheck(getCopy(node.object), |
| 2752 node.sourceInformation); | 2794 node.sourceInformation); |
| 2753 } else { | 2795 } else { |
| 2754 return new BoundsCheck(getCopy(node.object), getCopy(node.index), | 2796 return new BoundsCheck(getCopy(node.object), getCopy(node.index), |
| 2755 node.length == null ? null : getCopy(node.length), | 2797 getCopyOrNull(node.length), |
| 2756 node.checks, | 2798 node.checks, |
| 2757 node.sourceInformation); | 2799 node.sourceInformation); |
| 2758 } | 2800 } |
| 2759 } | 2801 } |
| 2760 | 2802 |
| 2761 Definition visitNullCheck(NullCheck node) { | 2803 Definition visitNullCheck(NullCheck node) { |
| 2762 return new NullCheck(getCopy(node.value), node.sourceInformation, | 2804 return new NullCheck(getCopy(node.value), node.sourceInformation, |
| 2763 condition: node.condition == null ? null : getCopy(node.condition), | 2805 condition: getCopyOrNull(node.condition), |
| 2764 selector: node.selector, | 2806 selector: node.selector, |
| 2765 useSelector: node.useSelector); | 2807 useSelector: node.useSelector); |
| 2766 } | 2808 } |
| 2767 | 2809 |
| 2768 Definition visitForeignCode(ForeignCode node) { | 2810 Definition visitForeignCode(ForeignCode node) { |
| 2769 return new ForeignCode(node.codeTemplate, node.storedType, | 2811 return new ForeignCode(node.codeTemplate, node.storedType, |
| 2770 getList(node.arguments), | 2812 getList(node.arguments), |
| 2771 node.nativeBehavior, | 2813 node.nativeBehavior, |
| 2772 dependency: node.dependency); | 2814 dependency: node.dependency); |
| 2773 } | 2815 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2906 plug(new Branch.loose(_definitions.getCopy(node.condition), | 2948 plug(new Branch.loose(_definitions.getCopy(node.condition), |
| 2907 _copies[node.trueContinuation.definition], | 2949 _copies[node.trueContinuation.definition], |
| 2908 _copies[node.falseContinuation.definition]) | 2950 _copies[node.falseContinuation.definition]) |
| 2909 ..isStrictCheck = node.isStrictCheck); | 2951 ..isStrictCheck = node.isStrictCheck); |
| 2910 } | 2952 } |
| 2911 | 2953 |
| 2912 visitUnreachable(Unreachable node) { | 2954 visitUnreachable(Unreachable node) { |
| 2913 plug(new Unreachable()); | 2955 plug(new Unreachable()); |
| 2914 } | 2956 } |
| 2915 } | 2957 } |
| OLD | NEW |