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 | 4 |
| 5 // IrNodes are kept in a separate library to have precise control over their | 5 // IrNodes are kept in a separate library to have precise control over their |
| 6 // dependencies on other parts of the system. | 6 // dependencies on other parts of the system. |
| 7 library dart2js.ir_nodes; | 7 library dart2js.ir_nodes; |
| 8 | 8 |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart' as values show ConstantValue; | 10 import '../constants/values.dart' as values show ConstantValue; |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 bool get isFactory => target.isFactoryConstructor; | 375 bool get isFactory => target.isFactoryConstructor; |
| 376 | 376 |
| 377 InvokeConstructor(this.type, | 377 InvokeConstructor(this.type, |
| 378 this.target, | 378 this.target, |
| 379 this.selector, | 379 this.selector, |
| 380 Continuation cont, | 380 Continuation cont, |
| 381 List<Primitive> args) | 381 List<Primitive> args) |
| 382 : continuation = new Reference<Continuation>(cont), | 382 : continuation = new Reference<Continuation>(cont), |
| 383 arguments = _referenceList(args) { | 383 arguments = _referenceList(args) { |
| 384 assert(dart2js.invariant(target, | 384 assert(dart2js.invariant(target, |
| 385 target.isErroneous || target.isConstructor, | |
| 386 message: "Constructor invocation target is not a constructor: " | |
| 387 "$target.")); | |
| 388 assert(dart2js.invariant(target, | |
| 389 target.isErroneous || | 385 target.isErroneous || |
| 390 type.isDynamic || | 386 type.isDynamic || |
| 391 type.element == target.enclosingClass.declaration, | 387 type.element == target.enclosingClass.declaration, |
| 392 message: "Constructor invocation type ${type} does not match enclosing " | 388 message: "Constructor invocation target is not a constructor: " |
| 393 "class of target ${target}.")); | 389 "$target.")); |
| 394 } | 390 } |
| 395 | 391 |
| 396 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 392 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
| 397 } | 393 } |
| 398 | 394 |
| 399 /// "as" casts and "is" checks. | 395 /// "as" casts and "is" checks. |
| 400 // We might want to turn "is"-checks into a [Primitive] as it can never diverge. | 396 // We might want to turn "is"-checks into a [Primitive] as it can never diverge. |
| 401 // But then we need to special-case for is-checks with an erroneous .type as | 397 // But then we need to special-case for is-checks with an erroneous .type as |
| 402 // these will throw. | 398 // these will throw. |
| 403 class TypeOperator extends Expression { | 399 class TypeOperator extends Expression { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 : this.object = new Reference<Primitive>(object); | 586 : this.object = new Reference<Primitive>(object); |
| 591 | 587 |
| 592 accept(Visitor visitor) => visitor.visitGetField(this); | 588 accept(Visitor visitor) => visitor.visitGetField(this); |
| 593 } | 589 } |
| 594 | 590 |
| 595 /// Creates an object for holding boxed variables captured by a closure. | 591 /// Creates an object for holding boxed variables captured by a closure. |
| 596 class CreateBox extends Primitive implements JsSpecificNode { | 592 class CreateBox extends Primitive implements JsSpecificNode { |
| 597 accept(Visitor visitor) => visitor.visitCreateBox(this); | 593 accept(Visitor visitor) => visitor.visitCreateBox(this); |
| 598 } | 594 } |
| 599 | 595 |
| 600 /// Creates an instance of a class and initializes its fields. | 596 /// Creates an instance of a class and initializes its fields and runtime type |
| 597 /// information. | |
| 601 class CreateInstance extends Primitive implements JsSpecificNode { | 598 class CreateInstance extends Primitive implements JsSpecificNode { |
| 602 final ClassElement classElement; | 599 final ClassElement classElement; |
| 603 | 600 |
| 604 /// Initial values for the fields on the class. | 601 /// Initial values for the fields on the class. |
| 605 /// The order corresponds to the order of fields on the class. | 602 /// The order corresponds to the order of fields on the class. |
| 606 final List<Reference<Primitive>> arguments; | 603 final List<Reference<Primitive>> arguments; |
| 607 | 604 |
| 608 CreateInstance(this.classElement, List<Primitive> arguments) | 605 /// The runtime type information structure which contains the type arguments. |
| 609 : this.arguments = _referenceList(arguments); | 606 /// |
| 607 /// May be `null` to indicate that no type information is needed because the | |
| 608 /// compiler determined that the type information for instances of this class | |
| 609 /// is not needed at runtime. | |
| 610 final List<Reference<Primitive>> typeInformation; | |
|
asgerf
2015/03/24 12:37:22
Is there ever a need to distinguish the empty list
karlklose
2015/03/26 09:50:07
Currently not. Changed.
| |
| 611 | |
| 612 CreateInstance(this.classElement, List<Primitive> arguments, | |
| 613 [List<Primitive> typeInformation]) | |
| 614 : this.arguments = _referenceList(arguments), | |
| 615 this.typeInformation = | |
| 616 typeInformation == null ? null : _referenceList(typeInformation); | |
| 617 | |
| 618 bool get hasTypeInformation => typeInformation != null; | |
| 610 | 619 |
| 611 accept(Visitor visitor) => visitor.visitCreateInstance(this); | 620 accept(Visitor visitor) => visitor.visitCreateInstance(this); |
| 612 } | 621 } |
| 613 | 622 |
| 614 class Identical extends Primitive implements JsSpecificNode { | 623 class Identical extends Primitive implements JsSpecificNode { |
| 615 final Reference<Primitive> left; | 624 final Reference<Primitive> left; |
| 616 final Reference<Primitive> right; | 625 final Reference<Primitive> right; |
| 617 Identical(Primitive left, Primitive right) | 626 Identical(Primitive left, Primitive right) |
| 618 : left = new Reference<Primitive>(left), | 627 : left = new Reference<Primitive>(left), |
| 619 right = new Reference<Primitive>(right); | 628 right = new Reference<Primitive>(right); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 final TypeVariableType variable; | 900 final TypeVariableType variable; |
| 892 final Reference<Primitive> target; | 901 final Reference<Primitive> target; |
| 893 | 902 |
| 894 ReadTypeVariable(this.variable, Primitive target) | 903 ReadTypeVariable(this.variable, Primitive target) |
| 895 : this.target = new Reference<Primitive>(target); | 904 : this.target = new Reference<Primitive>(target); |
| 896 | 905 |
| 897 @override | 906 @override |
| 898 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); | 907 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
| 899 } | 908 } |
| 900 | 909 |
| 910 /// Representation of a closed type (that is, a type without type variables). | |
| 911 /// | |
| 912 /// The resulting value is constructed from [dartType] by replacing the type | |
| 913 /// variables with consecutive values from [arguments], in the order generated | |
| 914 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are | |
| 915 /// treated as 'holes' in the term, which means that it must be ensured at | |
| 916 /// construction, that duplicate occurences of a type variable in [dartType] | |
| 917 /// are assigned the same value. | |
| 918 class TypeExpression extends Primitive implements JsSpecificNode { | |
| 919 final DartType dartType; | |
| 920 final List<Reference<Primitive>> arguments; | |
| 921 | |
| 922 TypeExpression(this.dartType, | |
| 923 [List<Primitive> arguments = const <Primitive>[]]) | |
| 924 : this.arguments = _referenceList(arguments); | |
| 925 | |
| 926 @override | |
| 927 accept(Visitor visitor) { | |
| 928 return visitor.visitTypeExpression(this); | |
| 929 } | |
| 930 } | |
| 931 | |
| 901 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 932 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
| 902 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 933 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
| 903 } | 934 } |
| 904 | 935 |
| 905 abstract class Visitor<T> { | 936 abstract class Visitor<T> { |
| 906 const Visitor(); | 937 const Visitor(); |
| 907 | 938 |
| 908 T visit(Node node); | 939 T visit(Node node); |
| 909 | 940 |
| 910 // Concrete classes. | 941 // Concrete classes. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 953 T visitSetField(SetField node); | 984 T visitSetField(SetField node); |
| 954 | 985 |
| 955 // Definitions. | 986 // Definitions. |
| 956 T visitIdentical(Identical node); | 987 T visitIdentical(Identical node); |
| 957 T visitInterceptor(Interceptor node); | 988 T visitInterceptor(Interceptor node); |
| 958 T visitCreateInstance(CreateInstance node); | 989 T visitCreateInstance(CreateInstance node); |
| 959 T visitGetField(GetField node); | 990 T visitGetField(GetField node); |
| 960 T visitCreateBox(CreateBox node); | 991 T visitCreateBox(CreateBox node); |
| 961 T visitReifyRuntimeType(ReifyRuntimeType node); | 992 T visitReifyRuntimeType(ReifyRuntimeType node); |
| 962 T visitReadTypeVariable(ReadTypeVariable node); | 993 T visitReadTypeVariable(ReadTypeVariable node); |
| 994 T visitTypeExpression(TypeExpression node); | |
| 963 } | 995 } |
| 964 | 996 |
| 965 /// Recursively visits the entire CPS term, and calls abstract `process*` | 997 /// Recursively visits the entire CPS term, and calls abstract `process*` |
| 966 /// (i.e. `processLetPrim`) functions in pre-order. | 998 /// (i.e. `processLetPrim`) functions in pre-order. |
| 967 class RecursiveVisitor implements Visitor { | 999 class RecursiveVisitor implements Visitor { |
| 968 const RecursiveVisitor(); | 1000 const RecursiveVisitor(); |
| 969 | 1001 |
| 970 visit(Node node) => node.accept(this); | 1002 visit(Node node) => node.accept(this); |
| 971 | 1003 |
| 972 processReference(Reference ref) {} | 1004 processReference(Reference ref) {} |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1192 processInterceptor(Interceptor node) {} | 1224 processInterceptor(Interceptor node) {} |
| 1193 visitInterceptor(Interceptor node) { | 1225 visitInterceptor(Interceptor node) { |
| 1194 processInterceptor(node); | 1226 processInterceptor(node); |
| 1195 processReference(node.input); | 1227 processReference(node.input); |
| 1196 } | 1228 } |
| 1197 | 1229 |
| 1198 processCreateInstance(CreateInstance node) {} | 1230 processCreateInstance(CreateInstance node) {} |
| 1199 visitCreateInstance(CreateInstance node) { | 1231 visitCreateInstance(CreateInstance node) { |
| 1200 processCreateInstance(node); | 1232 processCreateInstance(node); |
| 1201 node.arguments.forEach(processReference); | 1233 node.arguments.forEach(processReference); |
| 1234 if (node.hasTypeInformation) { | |
| 1235 node.typeInformation.forEach(processReference); | |
| 1236 } | |
| 1202 } | 1237 } |
| 1203 | 1238 |
| 1204 processSetField(SetField node) {} | 1239 processSetField(SetField node) {} |
| 1205 visitSetField(SetField node) { | 1240 visitSetField(SetField node) { |
| 1206 processSetField(node); | 1241 processSetField(node); |
| 1207 processReference(node.object); | 1242 processReference(node.object); |
| 1208 processReference(node.value); | 1243 processReference(node.value); |
| 1209 visit(node.body); | 1244 visit(node.body); |
| 1210 } | 1245 } |
| 1211 | 1246 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1224 visitReifyRuntimeType(ReifyRuntimeType node) { | 1259 visitReifyRuntimeType(ReifyRuntimeType node) { |
| 1225 processReifyRuntimeType(node); | 1260 processReifyRuntimeType(node); |
| 1226 processReference(node.value); | 1261 processReference(node.value); |
| 1227 } | 1262 } |
| 1228 | 1263 |
| 1229 processReadTypeVariable(ReadTypeVariable node) {} | 1264 processReadTypeVariable(ReadTypeVariable node) {} |
| 1230 visitReadTypeVariable(ReadTypeVariable node) { | 1265 visitReadTypeVariable(ReadTypeVariable node) { |
| 1231 processReadTypeVariable(node); | 1266 processReadTypeVariable(node); |
| 1232 processReference(node.target); | 1267 processReference(node.target); |
| 1233 } | 1268 } |
| 1269 | |
| 1270 processTypeExpression(TypeExpression node) {} | |
| 1271 @override | |
| 1272 visitTypeExpression(TypeExpression node) { | |
| 1273 processTypeExpression(node); | |
| 1274 node.arguments.forEach(processReference); | |
| 1275 } | |
| 1234 } | 1276 } |
| 1235 | 1277 |
| 1236 /// Keeps track of currently unused register indices. | 1278 /// Keeps track of currently unused register indices. |
| 1237 class RegisterArray { | 1279 class RegisterArray { |
| 1238 int nextIndex = 0; | 1280 int nextIndex = 0; |
| 1239 final List<int> freeStack = <int>[]; | 1281 final List<int> freeStack = <int>[]; |
| 1240 | 1282 |
| 1241 /// Returns an index that is currently unused. | 1283 /// Returns an index that is currently unused. |
| 1242 int makeIndex() { | 1284 int makeIndex() { |
| 1243 if (freeStack.isEmpty) { | 1285 if (freeStack.isEmpty) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1475 | 1517 |
| 1476 void visitGetField(GetField node) { | 1518 void visitGetField(GetField node) { |
| 1477 visitReference(node.object); | 1519 visitReference(node.object); |
| 1478 } | 1520 } |
| 1479 | 1521 |
| 1480 void visitCreateBox(CreateBox node) { | 1522 void visitCreateBox(CreateBox node) { |
| 1481 } | 1523 } |
| 1482 | 1524 |
| 1483 void visitCreateInstance(CreateInstance node) { | 1525 void visitCreateInstance(CreateInstance node) { |
| 1484 node.arguments.forEach(visitReference); | 1526 node.arguments.forEach(visitReference); |
| 1527 if (node.hasTypeInformation) { | |
| 1528 node.typeInformation.forEach(visitReference); | |
| 1529 } | |
| 1485 } | 1530 } |
| 1486 | 1531 |
| 1487 void visitIdentical(Identical node) { | 1532 void visitIdentical(Identical node) { |
| 1488 visitReference(node.left); | 1533 visitReference(node.left); |
| 1489 visitReference(node.right); | 1534 visitReference(node.right); |
| 1490 } | 1535 } |
| 1491 | 1536 |
| 1492 void visitInterceptor(Interceptor node) { | 1537 void visitInterceptor(Interceptor node) { |
| 1493 visitReference(node.input); | 1538 visitReference(node.input); |
| 1494 } | 1539 } |
| 1495 | 1540 |
| 1496 void visitReifyRuntimeType(ReifyRuntimeType node) { | 1541 void visitReifyRuntimeType(ReifyRuntimeType node) { |
| 1497 visitReference(node.value); | 1542 visitReference(node.value); |
| 1498 } | 1543 } |
| 1499 | 1544 |
| 1500 void visitReadTypeVariable(ReadTypeVariable node) { | 1545 void visitReadTypeVariable(ReadTypeVariable node) { |
| 1501 visitReference(node.target); | 1546 visitReference(node.target); |
| 1502 } | 1547 } |
| 1548 | |
| 1549 @override | |
| 1550 visitTypeExpression(TypeExpression node) { | |
| 1551 node.arguments.forEach(visitReference); | |
| 1552 } | |
| 1503 } | 1553 } |
| OLD | NEW |