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/values.dart' as values show ConstantValue; | 6 import '../constants/values.dart' as values show ConstantValue; |
7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
9 import '../io/source_information.dart' show SourceInformation; | 9 import '../io/source_information.dart' show SourceInformation; |
10 import '../types/types.dart' show TypeMask; | 10 import '../types/types.dart' show TypeMask; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 this.hint = hint; | 89 this.hint = hint; |
90 } | 90 } |
91 } | 91 } |
92 | 92 |
93 /// True if the primitive can be removed, assuming it has no uses | 93 /// True if the primitive can be removed, assuming it has no uses |
94 /// (this getter does not check if there are any uses). | 94 /// (this getter does not check if there are any uses). |
95 /// | 95 /// |
96 /// False must be returned for primitives that may throw, diverge, or have | 96 /// False must be returned for primitives that may throw, diverge, or have |
97 /// observable side-effects. | 97 /// observable side-effects. |
98 bool get isSafeForElimination => true; | 98 bool get isSafeForElimination => true; |
99 | |
100 /// True if time-of-evaluation is irrelevant for the given primitive, | |
101 /// assuming its inputs are the same values. | |
102 bool get isSafeForReordering => true; | |
floitsch
2015/07/03 11:56:58
I would rather have the default be the safe "false
asgerf
2015/07/03 12:27:52
I agree, although I changed it to be abstract (no
| |
99 } | 103 } |
100 | 104 |
101 /// Operands to invocations and primitives are always variables. They point to | 105 /// Operands to invocations and primitives are always variables. They point to |
102 /// their definition and are doubly-linked into a list of occurrences. | 106 /// their definition and are doubly-linked into a list of occurrences. |
103 class Reference<T extends Definition<T>> { | 107 class Reference<T extends Definition<T>> { |
104 T definition; | 108 T definition; |
105 Reference<T> previous; | 109 Reference<T> previous; |
106 Reference<T> next; | 110 Reference<T> next; |
107 | 111 |
108 /// A pointer to the parent node. Is null until set by optimization passes. | 112 /// A pointer to the parent node. Is null until set by optimization passes. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 final SourceInformation sourceInformation; | 263 final SourceInformation sourceInformation; |
260 | 264 |
261 InvokeStatic(this.target, | 265 InvokeStatic(this.target, |
262 this.selector, | 266 this.selector, |
263 List<Primitive> args, | 267 List<Primitive> args, |
264 Continuation cont, | 268 Continuation cont, |
265 [this.sourceInformation]) | 269 [this.sourceInformation]) |
266 : arguments = _referenceList(args), | 270 : arguments = _referenceList(args), |
267 continuation = new Reference<Continuation>(cont); | 271 continuation = new Reference<Continuation>(cont); |
268 | 272 |
273 InvokeStatic.byReference(this.target, | |
274 this.selector, | |
275 this.arguments, | |
276 this.continuation, | |
277 [this.sourceInformation]); | |
278 | |
269 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 279 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
270 } | 280 } |
271 | 281 |
272 /// Invoke a method on an object. | 282 /// Invoke a method on an object. |
273 /// | 283 /// |
274 /// This includes getters, setters, operators, and index getter/setters. | 284 /// This includes getters, setters, operators, and index getter/setters. |
275 /// | 285 /// |
276 /// Tearing off a method is treated like a getter invocation (getters and | 286 /// Tearing off a method is treated like a getter invocation (getters and |
277 /// tear-offs cannot be distinguished at compile-time). | 287 /// tear-offs cannot be distinguished at compile-time). |
278 /// | 288 /// |
(...skipping 13 matching lines...) Expand all Loading... | |
292 InvokeMethod(Primitive receiver, | 302 InvokeMethod(Primitive receiver, |
293 this.selector, | 303 this.selector, |
294 this.mask, | 304 this.mask, |
295 List<Primitive> arguments, | 305 List<Primitive> arguments, |
296 Continuation continuation, | 306 Continuation continuation, |
297 [this.sourceInformation]) | 307 [this.sourceInformation]) |
298 : this.receiver = new Reference<Primitive>(receiver), | 308 : this.receiver = new Reference<Primitive>(receiver), |
299 this.arguments = _referenceList(arguments), | 309 this.arguments = _referenceList(arguments), |
300 this.continuation = new Reference<Continuation>(continuation); | 310 this.continuation = new Reference<Continuation>(continuation); |
301 | 311 |
312 InvokeMethod.byReference(this.receiver, | |
313 this.selector, | |
314 this.mask, | |
315 this.arguments, | |
316 this.continuation, | |
317 [this.sourceInformation]); | |
318 | |
302 accept(Visitor visitor) => visitor.visitInvokeMethod(this); | 319 accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
303 } | 320 } |
304 | 321 |
305 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. | 322 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
306 /// | 323 /// |
307 /// That is, if [receiver] is an instance of a class that overrides [target] | 324 /// That is, if [receiver] is an instance of a class that overrides [target] |
308 /// with a different implementation, the overriding implementation is bypassed | 325 /// with a different implementation, the overriding implementation is bypassed |
309 /// and [target]'s implementation is invoked. | 326 /// and [target]'s implementation is invoked. |
310 /// | 327 /// |
311 /// As with [InvokeMethod], this can be used to invoke a method, operator, | 328 /// As with [InvokeMethod], this can be used to invoke a method, operator, |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 /// | 515 /// |
499 /// let prim p = ![variable] in [body] | 516 /// let prim p = ![variable] in [body] |
500 /// | 517 /// |
501 class GetMutableVariable extends Primitive { | 518 class GetMutableVariable extends Primitive { |
502 final Reference<MutableVariable> variable; | 519 final Reference<MutableVariable> variable; |
503 | 520 |
504 GetMutableVariable(MutableVariable variable) | 521 GetMutableVariable(MutableVariable variable) |
505 : this.variable = new Reference<MutableVariable>(variable); | 522 : this.variable = new Reference<MutableVariable>(variable); |
506 | 523 |
507 accept(Visitor visitor) => visitor.visitGetMutableVariable(this); | 524 accept(Visitor visitor) => visitor.visitGetMutableVariable(this); |
525 | |
526 @override | |
527 bool get isSafeForReordering => false; | |
508 } | 528 } |
509 | 529 |
510 /// Assign a [MutableVariable]. | 530 /// Assign a [MutableVariable]. |
511 /// | 531 /// |
512 /// [MutableVariable]s can be seen as ref cells that are not first-class | 532 /// [MutableVariable]s can be seen as ref cells that are not first-class |
513 /// values. This can be seen as a dereferencing assignment: | 533 /// values. This can be seen as a dereferencing assignment: |
514 /// | 534 /// |
515 /// { [variable] := [value]; [body] } | 535 /// { [variable] := [value]; [body] } |
516 class SetMutableVariable extends Expression implements InteriorNode { | 536 class SetMutableVariable extends Expression implements InteriorNode { |
517 final Reference<MutableVariable> variable; | 537 final Reference<MutableVariable> variable; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 // side effects. | 637 // side effects. |
618 bool objectIsNotNull = false; | 638 bool objectIsNotNull = false; |
619 | 639 |
620 GetField(Primitive object, this.field) | 640 GetField(Primitive object, this.field) |
621 : this.object = new Reference<Primitive>(object); | 641 : this.object = new Reference<Primitive>(object); |
622 | 642 |
623 accept(Visitor visitor) => visitor.visitGetField(this); | 643 accept(Visitor visitor) => visitor.visitGetField(this); |
624 | 644 |
625 @override | 645 @override |
626 bool get isSafeForElimination => objectIsNotNull; | 646 bool get isSafeForElimination => objectIsNotNull; |
647 | |
648 @override | |
649 bool get isSafeForReordering => objectIsNotNull && field.isFinal; | |
627 } | 650 } |
628 | 651 |
629 /// Reads the value of a static field or tears off a static method. | 652 /// Reads the value of a static field or tears off a static method. |
653 /// | |
654 /// Note that lazily initialized fields should be read using GetLazyStatic. | |
630 class GetStatic extends Primitive { | 655 class GetStatic extends Primitive { |
631 /// Can be [FieldElement] or [FunctionElement]. | 656 /// Can be [FieldElement] or [FunctionElement]. |
632 final Element element; | 657 final Element element; |
633 final SourceInformation sourceInformation; | 658 final SourceInformation sourceInformation; |
634 | 659 |
635 GetStatic(this.element, [this.sourceInformation]); | 660 GetStatic(this.element, [this.sourceInformation]); |
636 | 661 |
637 accept(Visitor visitor) => visitor.visitGetStatic(this); | 662 accept(Visitor visitor) => visitor.visitGetStatic(this); |
663 | |
664 @override | |
665 bool get isSafeForReordering { | |
666 return element is FunctionElement || element.isFinal; | |
667 } | |
638 } | 668 } |
639 | 669 |
640 /// Sets the value of a static field. | 670 /// Sets the value of a static field. |
641 class SetStatic extends Expression implements InteriorNode { | 671 class SetStatic extends Expression implements InteriorNode { |
642 final FieldElement element; | 672 final FieldElement element; |
643 final Reference<Primitive> value; | 673 final Reference<Primitive> value; |
644 Expression body; | 674 Expression body; |
645 final SourceInformation sourceInformation; | 675 final SourceInformation sourceInformation; |
646 | 676 |
647 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 677 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1267 const RemovalVisitor(); | 1297 const RemovalVisitor(); |
1268 | 1298 |
1269 processReference(Reference reference) { | 1299 processReference(Reference reference) { |
1270 reference.unlink(); | 1300 reference.unlink(); |
1271 } | 1301 } |
1272 | 1302 |
1273 static void remove(Node node) { | 1303 static void remove(Node node) { |
1274 (const RemovalVisitor()).visit(node); | 1304 (const RemovalVisitor()).visit(node); |
1275 } | 1305 } |
1276 } | 1306 } |
OLD | NEW |