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 /// Note that [TypeTest] always returns `false` if [value] is `null`. | |
367 /// Therefore, [type] should not be [Object], `dynamic`, or [Null], since `null` | |
karlklose
2015/06/08 09:46:53
'should' -> 'can't'?
asgerf
2015/06/08 10:46:16
Hmm.. the comment is actually outdated and wrong.
| |
368 /// is an instance of these types. | |
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) {} | |
1178 } | 1239 } |
1240 | |
1241 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | |
1242 class RemovalVisitor extends RecursiveVisitor { | |
1243 const RemovalVisitor(); | |
1244 | |
1245 processReference(Reference reference) { | |
1246 reference.unlink(); | |
1247 } | |
1248 | |
1249 static void remove(Node node) { | |
1250 (const RemovalVisitor()).visit(node); | |
1251 } | |
1252 } | |
OLD | NEW |