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 '../constants/expressions.dart'; | 6 import '../constants/expressions.dart'; |
7 import '../constants/values.dart' as values show ConstantValue; | 7 import '../constants/values.dart' as values show ConstantValue; |
8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
10 import '../io/source_information.dart' show SourceInformation; | 10 import '../io/source_information.dart' show SourceInformation; |
(...skipping 10 matching lines...) Expand all Loading... |
21 /// side-effects. | 21 /// side-effects. |
22 /// | 22 /// |
23 /// Evaluation continues by stepping into a sub-expression, invoking a | 23 /// Evaluation continues by stepping into a sub-expression, invoking a |
24 /// continuation, or throwing an exception. | 24 /// continuation, or throwing an exception. |
25 /// | 25 /// |
26 /// Expressions do not a return value. Expressions that produce values should | 26 /// Expressions do not a return value. Expressions that produce values should |
27 /// invoke a [Continuation] with the result as argument. Alternatively, values | 27 /// invoke a [Continuation] with the result as argument. Alternatively, values |
28 /// that can be obtained without side-effects, divergence, or throwing | 28 /// that can be obtained without side-effects, divergence, or throwing |
29 /// exceptions can be built using a [LetPrim]. | 29 /// exceptions can be built using a [LetPrim]. |
30 abstract class Expression extends Node { | 30 abstract class Expression extends Node { |
| 31 InteriorNode get parent; // Only InteriorNodes may contain expressions. |
| 32 |
31 Expression plug(Expression expr) => throw 'impossible'; | 33 Expression plug(Expression expr) => throw 'impossible'; |
32 } | 34 } |
33 | 35 |
34 /// The base class of things that variables can refer to: primitives, | 36 /// The base class of things that variables can refer to: primitives, |
35 /// continuations, function and continuation parameters, etc. | 37 /// continuations, function and continuation parameters, etc. |
36 abstract class Definition<T extends Definition<T>> extends Node { | 38 abstract class Definition<T extends Definition<T>> extends Node { |
37 // The head of a linked-list of occurrences, in no particular order. | 39 // The head of a linked-list of occurrences, in no particular order. |
38 Reference<T> firstRef; | 40 Reference<T> firstRef; |
39 | 41 |
40 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null; | 42 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null; |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 this.target, | 352 this.target, |
351 this.selector, | 353 this.selector, |
352 List<Primitive> args, | 354 List<Primitive> args, |
353 Continuation cont) | 355 Continuation cont) |
354 : arguments = _referenceList(args), | 356 : arguments = _referenceList(args), |
355 continuation = new Reference<Continuation>(cont); | 357 continuation = new Reference<Continuation>(cont); |
356 | 358 |
357 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 359 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
358 } | 360 } |
359 | 361 |
360 // TODO(asgerf): Make a Primitive for "is" and an Expression for "as". | 362 /// An "is" type test. |
361 | 363 /// |
362 /// An "as" cast or an "is" check. | 364 /// Returns `true` if [value] not `null` and is an instance of [type]. |
363 class TypeOperator extends Expression { | 365 /// |
| 366 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might |
| 367 /// be a type variable containing one of these types). This design is chosen |
| 368 /// to simplify code generation for type tests. |
| 369 class TypeTest extends Primitive { |
364 Reference<Primitive> value; | 370 Reference<Primitive> value; |
365 final DartType type; | 371 final DartType type; |
366 | 372 |
| 373 /// If [type] is an [InterfaceType], this holds the internal representation of |
| 374 /// the type arguments to [type]. Since these may reference type variables |
| 375 /// from the enclosing class, they are not constant. |
| 376 /// |
| 377 /// If [type] is a [TypeVariableType], this is a singleton list with |
| 378 /// the internal representation of the type held in that type variable. |
| 379 /// |
| 380 /// Otherwise the list is empty. |
| 381 final List<Reference<Primitive>> typeArguments; |
| 382 |
| 383 TypeTest(Primitive value, |
| 384 this.type, |
| 385 List<Primitive> typeArguments) |
| 386 : this.value = new Reference<Primitive>(value), |
| 387 this.typeArguments = _referenceList(typeArguments); |
| 388 |
| 389 accept(Visitor visitor) => visitor.visitTypeTest(this); |
| 390 } |
| 391 |
| 392 /// An "as" type cast. |
| 393 /// |
| 394 /// If [value] is `null` or is an instance of [type], [continuation] is invoked |
| 395 /// with [value] as argument. Otherwise, a [CastError] is thrown. |
| 396 /// |
| 397 /// Discussion: |
| 398 /// The parameter to [continuation] is redundant since it will always equal |
| 399 /// [value], which is typically in scope in the continuation. However, it might |
| 400 /// simplify type propagation, since a better type can be computed for the |
| 401 /// continuation parameter without needing flow-sensitive analysis. |
| 402 class TypeCast extends Expression { |
| 403 Reference<Primitive> value; |
| 404 final DartType type; |
| 405 |
367 /// If [type] is an [InterfaceType], this holds the internal representation of | 406 /// If [type] is an [InterfaceType], this holds the internal representation of |
368 /// the type arguments to [type]. Since these may reference type variables | 407 /// the type arguments to [type]. Since these may reference type variables |
369 /// from the enclosing class, they are not constant. | 408 /// from the enclosing class, they are not constant. |
370 /// | 409 /// |
371 /// If [type] is a [TypeVariableType], this is a singleton list with | 410 /// If [type] is a [TypeVariableType], this is a singleton list with |
372 /// the internal representation of the type held in that type variable. | 411 /// the internal representation of the type held in that type variable. |
373 /// | 412 /// |
374 /// Otherwise the list is empty. | 413 /// Otherwise the list is empty. |
375 final List<Reference<Primitive>> typeArguments; | 414 final List<Reference<Primitive>> typeArguments; |
376 final Reference<Continuation> continuation; | 415 final Reference<Continuation> continuation; |
377 final bool isTypeTest; | |
378 | 416 |
379 TypeOperator(Primitive value, | 417 TypeCast(Primitive value, |
380 this.type, | 418 this.type, |
381 List<Primitive> typeArguments, | 419 List<Primitive> typeArguments, |
382 Continuation cont, | 420 Continuation cont) |
383 {bool this.isTypeTest}) | |
384 : this.value = new Reference<Primitive>(value), | 421 : this.value = new Reference<Primitive>(value), |
385 this.typeArguments = _referenceList(typeArguments), | 422 this.typeArguments = _referenceList(typeArguments), |
386 this.continuation = new Reference<Continuation>(cont) { | 423 this.continuation = new Reference<Continuation>(cont); |
387 assert(isTypeTest != null); | |
388 } | |
389 | 424 |
390 bool get isTypeCast => !isTypeTest; | 425 accept(Visitor visitor) => visitor.visitTypeCast(this); |
391 | |
392 accept(Visitor visitor) => visitor.visitTypeOperator(this); | |
393 } | 426 } |
394 | 427 |
395 /// Invoke [toString] on each argument and concatenate the results. | 428 /// Invoke [toString] on each argument and concatenate the results. |
396 class ConcatenateStrings extends Expression { | 429 class ConcatenateStrings extends Expression { |
397 final List<Reference<Primitive>> arguments; | 430 final List<Reference<Primitive>> arguments; |
398 final Reference<Continuation> continuation; | 431 final Reference<Continuation> continuation; |
399 | 432 |
400 ConcatenateStrings(List<Primitive> args, Continuation cont) | 433 ConcatenateStrings(List<Primitive> args, Continuation cont) |
401 : arguments = _referenceList(args), | 434 : arguments = _referenceList(args), |
402 continuation = new Reference<Continuation>(cont); | 435 continuation = new Reference<Continuation>(cont); |
(...skipping 29 matching lines...) Expand all Loading... |
432 /// translation, a [NonTailThrow] is used as that value. A cleanup pass | 465 /// translation, a [NonTailThrow] is used as that value. A cleanup pass |
433 /// removes these and replaces them with [Throw] expressions. | 466 /// removes these and replaces them with [Throw] expressions. |
434 class NonTailThrow extends Primitive { | 467 class NonTailThrow extends Primitive { |
435 final Reference<Primitive> value; | 468 final Reference<Primitive> value; |
436 | 469 |
437 NonTailThrow(Primitive value) : value = new Reference<Primitive>(value); | 470 NonTailThrow(Primitive value) : value = new Reference<Primitive>(value); |
438 | 471 |
439 accept(Visitor visitor) => visitor.visitNonTailThrow(this); | 472 accept(Visitor visitor) => visitor.visitNonTailThrow(this); |
440 } | 473 } |
441 | 474 |
| 475 /// An expression that is known to be unreachable. |
| 476 /// |
| 477 /// This can be placed as the body of a call continuation, when the caller is |
| 478 /// known never to invoke it, e.g. because the calling expression always throws. |
| 479 class Unreachable extends Expression { |
| 480 accept(Visitor visitor) => visitor.visitUnreachable(this); |
| 481 } |
| 482 |
442 /// Gets the value from a [MutableVariable]. | 483 /// Gets the value from a [MutableVariable]. |
443 /// | 484 /// |
444 /// [MutableVariable]s can be seen as ref cells that are not first-class | 485 /// [MutableVariable]s can be seen as ref cells that are not first-class |
445 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: | 486 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: |
446 /// | 487 /// |
447 /// let prim p = ![variable] in [body] | 488 /// let prim p = ![variable] in [body] |
448 /// | 489 /// |
449 class GetMutableVariable extends Primitive { | 490 class GetMutableVariable extends Primitive { |
450 final Reference<MutableVariable> variable; | 491 final Reference<MutableVariable> variable; |
451 | 492 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 bool isRecursive; | 529 bool isRecursive; |
489 | 530 |
490 InvokeContinuation(Continuation cont, List<Primitive> args, | 531 InvokeContinuation(Continuation cont, List<Primitive> args, |
491 {this.isRecursive: false}) | 532 {this.isRecursive: false}) |
492 : continuation = new Reference<Continuation>(cont), | 533 : continuation = new Reference<Continuation>(cont), |
493 arguments = _referenceList(args) { | 534 arguments = _referenceList(args) { |
494 assert(cont.parameters == null || cont.parameters.length == args.length); | 535 assert(cont.parameters == null || cont.parameters.length == args.length); |
495 if (isRecursive) cont.isRecursive = true; | 536 if (isRecursive) cont.isRecursive = true; |
496 } | 537 } |
497 | 538 |
| 539 /// Build a one-argument InvokeContinuation using existing reference objects. |
| 540 /// |
| 541 /// This is useful for converting call continuations to local continuations. |
| 542 InvokeContinuation.fromCall(this.continuation, |
| 543 Reference<Primitive> argument) |
| 544 : arguments = <Reference<Primitive>>[argument], |
| 545 isRecursive = false; |
| 546 |
498 /// A continuation invocation whose target and arguments will be filled | 547 /// A continuation invocation whose target and arguments will be filled |
499 /// in later. | 548 /// in later. |
500 /// | 549 /// |
501 /// Used as a placeholder for a jump whose target is not yet created | 550 /// Used as a placeholder for a jump whose target is not yet created |
502 /// (e.g., in the translation of break and continue). | 551 /// (e.g., in the translation of break and continue). |
503 InvokeContinuation.uninitialized({this.isRecursive: false}) | 552 InvokeContinuation.uninitialized({this.isRecursive: false}) |
504 : continuation = null, | 553 : continuation = null, |
505 arguments = null; | 554 arguments = null; |
506 | 555 |
507 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); | 556 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 T visitLetMutable(LetMutable node); | 917 T visitLetMutable(LetMutable node); |
869 T visitInvokeContinuation(InvokeContinuation node); | 918 T visitInvokeContinuation(InvokeContinuation node); |
870 T visitInvokeStatic(InvokeStatic node); | 919 T visitInvokeStatic(InvokeStatic node); |
871 T visitInvokeMethod(InvokeMethod node); | 920 T visitInvokeMethod(InvokeMethod node); |
872 T visitInvokeMethodDirectly(InvokeMethodDirectly node); | 921 T visitInvokeMethodDirectly(InvokeMethodDirectly node); |
873 T visitInvokeConstructor(InvokeConstructor node); | 922 T visitInvokeConstructor(InvokeConstructor node); |
874 T visitConcatenateStrings(ConcatenateStrings node); | 923 T visitConcatenateStrings(ConcatenateStrings node); |
875 T visitThrow(Throw node); | 924 T visitThrow(Throw node); |
876 T visitRethrow(Rethrow node); | 925 T visitRethrow(Rethrow node); |
877 T visitBranch(Branch node); | 926 T visitBranch(Branch node); |
878 T visitTypeOperator(TypeOperator node); | 927 T visitTypeCast(TypeCast node); |
879 T visitSetMutableVariable(SetMutableVariable node); | 928 T visitSetMutableVariable(SetMutableVariable node); |
880 T visitSetStatic(SetStatic node); | 929 T visitSetStatic(SetStatic node); |
881 T visitGetLazyStatic(GetLazyStatic node); | 930 T visitGetLazyStatic(GetLazyStatic node); |
882 T visitSetField(SetField node); | 931 T visitSetField(SetField node); |
| 932 T visitUnreachable(Unreachable node); |
883 | 933 |
884 // Definitions. | 934 // Definitions. |
885 T visitLiteralList(LiteralList node); | 935 T visitLiteralList(LiteralList node); |
886 T visitLiteralMap(LiteralMap node); | 936 T visitLiteralMap(LiteralMap node); |
887 T visitConstant(Constant node); | 937 T visitConstant(Constant node); |
888 T visitCreateFunction(CreateFunction node); | 938 T visitCreateFunction(CreateFunction node); |
889 T visitGetMutableVariable(GetMutableVariable node); | 939 T visitGetMutableVariable(GetMutableVariable node); |
890 T visitParameter(Parameter node); | 940 T visitParameter(Parameter node); |
891 T visitContinuation(Continuation node); | 941 T visitContinuation(Continuation node); |
892 T visitMutableVariable(MutableVariable node); | 942 T visitMutableVariable(MutableVariable node); |
893 T visitNonTailThrow(NonTailThrow node); | 943 T visitNonTailThrow(NonTailThrow node); |
894 T visitGetStatic(GetStatic node); | 944 T visitGetStatic(GetStatic node); |
895 T visitIdentical(Identical node); | 945 T visitIdentical(Identical node); |
896 T visitInterceptor(Interceptor node); | 946 T visitInterceptor(Interceptor node); |
897 T visitCreateInstance(CreateInstance node); | 947 T visitCreateInstance(CreateInstance node); |
898 T visitGetField(GetField node); | 948 T visitGetField(GetField node); |
899 T visitCreateBox(CreateBox node); | 949 T visitCreateBox(CreateBox node); |
900 T visitReifyRuntimeType(ReifyRuntimeType node); | 950 T visitReifyRuntimeType(ReifyRuntimeType node); |
901 T visitReadTypeVariable(ReadTypeVariable node); | 951 T visitReadTypeVariable(ReadTypeVariable node); |
902 T visitTypeExpression(TypeExpression node); | 952 T visitTypeExpression(TypeExpression node); |
903 T visitCreateInvocationMirror(CreateInvocationMirror node); | 953 T visitCreateInvocationMirror(CreateInvocationMirror node); |
| 954 T visitTypeTest(TypeTest node); |
904 | 955 |
905 // Conditions. | 956 // Conditions. |
906 T visitIsTrue(IsTrue node); | 957 T visitIsTrue(IsTrue node); |
907 } | 958 } |
908 | 959 |
909 /// Recursively visits the entire CPS term, and calls abstract `process*` | 960 /// Recursively visits the entire CPS term, and calls abstract `process*` |
910 /// (i.e. `processLetPrim`) functions in pre-order. | 961 /// (i.e. `processLetPrim`) functions in pre-order. |
911 class RecursiveVisitor implements Visitor { | 962 class RecursiveVisitor implements Visitor { |
912 const RecursiveVisitor(); | 963 const RecursiveVisitor(); |
913 | 964 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 } | 1062 } |
1012 | 1063 |
1013 processBranch(Branch node) {} | 1064 processBranch(Branch node) {} |
1014 visitBranch(Branch node) { | 1065 visitBranch(Branch node) { |
1015 processBranch(node); | 1066 processBranch(node); |
1016 processReference(node.trueContinuation); | 1067 processReference(node.trueContinuation); |
1017 processReference(node.falseContinuation); | 1068 processReference(node.falseContinuation); |
1018 visit(node.condition); | 1069 visit(node.condition); |
1019 } | 1070 } |
1020 | 1071 |
1021 processTypeOperator(TypeOperator node) {} | 1072 processTypeCast(TypeCast node) {} |
1022 visitTypeOperator(TypeOperator node) { | 1073 visitTypeCast(TypeCast node) { |
1023 processTypeOperator(node); | 1074 processTypeCast(node); |
1024 processReference(node.continuation); | 1075 processReference(node.continuation); |
1025 processReference(node.value); | 1076 processReference(node.value); |
1026 node.typeArguments.forEach(processReference); | 1077 node.typeArguments.forEach(processReference); |
1027 } | 1078 } |
1028 | 1079 |
| 1080 processTypeTest(TypeTest node) {} |
| 1081 visitTypeTest(TypeTest node) { |
| 1082 processTypeTest(node); |
| 1083 processReference(node.value); |
| 1084 node.typeArguments.forEach(processReference); |
| 1085 } |
| 1086 |
1029 processSetMutableVariable(SetMutableVariable node) {} | 1087 processSetMutableVariable(SetMutableVariable node) {} |
1030 visitSetMutableVariable(SetMutableVariable node) { | 1088 visitSetMutableVariable(SetMutableVariable node) { |
1031 processSetMutableVariable(node); | 1089 processSetMutableVariable(node); |
1032 processReference(node.variable); | 1090 processReference(node.variable); |
1033 processReference(node.value); | 1091 processReference(node.value); |
1034 visit(node.body); | 1092 visit(node.body); |
1035 } | 1093 } |
1036 | 1094 |
1037 processGetLazyStatic(GetLazyStatic node) {} | 1095 processGetLazyStatic(GetLazyStatic node) {} |
1038 visitGetLazyStatic(GetLazyStatic node) { | 1096 visitGetLazyStatic(GetLazyStatic node) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 visitNonTailThrow(NonTailThrow node) { | 1226 visitNonTailThrow(NonTailThrow node) { |
1169 processNonTailThrow(node); | 1227 processNonTailThrow(node); |
1170 processReference(node.value); | 1228 processReference(node.value); |
1171 } | 1229 } |
1172 | 1230 |
1173 processCreateInvocationMirror(CreateInvocationMirror node) {} | 1231 processCreateInvocationMirror(CreateInvocationMirror node) {} |
1174 visitCreateInvocationMirror(CreateInvocationMirror node) { | 1232 visitCreateInvocationMirror(CreateInvocationMirror node) { |
1175 processCreateInvocationMirror(node); | 1233 processCreateInvocationMirror(node); |
1176 node.arguments.forEach(processReference); | 1234 node.arguments.forEach(processReference); |
1177 } | 1235 } |
| 1236 |
| 1237 processUnreachable(Unreachable node) {} |
| 1238 visitUnreachable(Unreachable node) { |
| 1239 processUnreachable(node); |
| 1240 } |
1178 } | 1241 } |
| 1242 |
| 1243 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 1244 class RemovalVisitor extends RecursiveVisitor { |
| 1245 const RemovalVisitor(); |
| 1246 |
| 1247 processReference(Reference reference) { |
| 1248 reference.unlink(); |
| 1249 } |
| 1250 |
| 1251 static void remove(Node node) { |
| 1252 (const RemovalVisitor()).visit(node); |
| 1253 } |
| 1254 } |
OLD | NEW |