OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 part of native; | 5 part of native; |
6 | 6 |
7 /// This class is a temporary work-around until we get a more powerful DartType. | 7 /// This class is a temporary work-around until we get a more powerful DartType. |
8 class SpecialType { | 8 class SpecialType { |
9 final String name; | 9 final String name; |
10 const SpecialType._(this.name); | 10 const SpecialType._(this.name); |
(...skipping 11 matching lines...) Expand all Loading... |
22 class NativeThrowBehavior { | 22 class NativeThrowBehavior { |
23 static const NativeThrowBehavior NEVER = const NativeThrowBehavior._(0); | 23 static const NativeThrowBehavior NEVER = const NativeThrowBehavior._(0); |
24 static const NativeThrowBehavior MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS = | 24 static const NativeThrowBehavior MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS = |
25 const NativeThrowBehavior._(1); | 25 const NativeThrowBehavior._(1); |
26 static const NativeThrowBehavior MAY = const NativeThrowBehavior._(2); | 26 static const NativeThrowBehavior MAY = const NativeThrowBehavior._(2); |
27 static const NativeThrowBehavior MUST = const NativeThrowBehavior._(3); | 27 static const NativeThrowBehavior MUST = const NativeThrowBehavior._(3); |
28 | 28 |
29 final int _bits; | 29 final int _bits; |
30 const NativeThrowBehavior._(this._bits); | 30 const NativeThrowBehavior._(this._bits); |
31 | 31 |
| 32 bool get canThrow => this != NEVER; |
| 33 |
32 String toString() { | 34 String toString() { |
33 if (this == NEVER) return 'never'; | 35 if (this == NEVER) return 'never'; |
34 if (this == MAY) return 'may'; | 36 if (this == MAY) return 'may'; |
35 if (this == MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS) return 'null(1)'; | 37 if (this == MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS) return 'null(1)'; |
36 if (this == MUST) return 'must'; | 38 if (this == MUST) return 'must'; |
37 return 'NativeThrowBehavior($_bits)'; | 39 return 'NativeThrowBehavior($_bits)'; |
38 } | 40 } |
39 } | 41 } |
40 | 42 |
41 /** | 43 /** |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 // parsed tree. | 82 // parsed tree. |
81 js.Template codeTemplate; | 83 js.Template codeTemplate; |
82 | 84 |
83 final SideEffects sideEffects = new SideEffects.empty(); | 85 final SideEffects sideEffects = new SideEffects.empty(); |
84 | 86 |
85 NativeThrowBehavior throwBehavior = NativeThrowBehavior.MAY; | 87 NativeThrowBehavior throwBehavior = NativeThrowBehavior.MAY; |
86 | 88 |
87 bool isAllocation = false; | 89 bool isAllocation = false; |
88 bool useGvn = false; | 90 bool useGvn = false; |
89 | 91 |
| 92 // TODO(sra): Make NativeBehavior immutable so PURE and PURE_ALLOCATION can be |
| 93 // final constant-like objects. |
| 94 static NativeBehavior get PURE => NativeBehavior._makePure(); |
| 95 static NativeBehavior get PURE_ALLOCATION => |
| 96 NativeBehavior._makePure(isAllocation: true); |
| 97 |
90 String toString() { | 98 String toString() { |
91 return 'NativeBehavior(' | 99 return 'NativeBehavior(' |
92 'returns: ${typesReturned}, ' | 100 'returns: ${typesReturned}' |
93 'creates: ${typesInstantiated}, ' | 101 ', creates: ${typesInstantiated}' |
94 'sideEffects: ${sideEffects}, ' | 102 ', sideEffects: ${sideEffects}' |
95 'throws: ${throwBehavior}' | 103 ', throws: ${throwBehavior}' |
96 '${isAllocation ? ", isAllocation" : ""}' | 104 '${isAllocation ? ", isAllocation" : ""}' |
97 '${useGvn ? ", useGvn" : ""}' | 105 '${useGvn ? ", useGvn" : ""}' |
98 ')'; | 106 ')'; |
99 } | 107 } |
100 | 108 |
| 109 static NativeBehavior _makePure({bool isAllocation: false}) { |
| 110 NativeBehavior behavior = new NativeBehavior(); |
| 111 behavior.sideEffects.clearAllDependencies(); |
| 112 behavior.sideEffects.clearAllSideEffects(); |
| 113 behavior.throwBehavior = NativeThrowBehavior.NEVER; |
| 114 behavior.isAllocation = isAllocation; |
| 115 return behavior; |
| 116 } |
101 | 117 |
102 /// Processes the type specification string of a call to JS and stores the | 118 /// Processes the type specification string of a call to JS and stores the |
103 /// result in the [typesReturned] and [typesInstantiated]. It furthermore | 119 /// result in the [typesReturned] and [typesInstantiated]. It furthermore |
104 /// computes the side effects, and, if given, invokes [setSideEffects] with | 120 /// computes the side effects, and, if given, invokes [setSideEffects] with |
105 /// the computed effects. If no side effects are encoded in the [specString] | 121 /// the computed effects. If no side effects are encoded in the [specString] |
106 /// the [setSideEffects] method is not invoked. | 122 /// the [setSideEffects] method is not invoked. |
107 /// | 123 /// |
108 /// Two forms of the string is supported: | 124 /// Two forms of the string is supported: |
109 /// | 125 /// |
110 /// 1) A single type string of the form 'void', '', 'var' or 'T1|...|Tn' | 126 /// 1) A single type string of the form 'void', '', 'var' or 'T1|...|Tn' |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 resolveType: resolveType, | 479 resolveType: resolveType, |
464 typesReturned: behavior.typesReturned, | 480 typesReturned: behavior.typesReturned, |
465 typesInstantiated: behavior.typesInstantiated, | 481 typesInstantiated: behavior.typesInstantiated, |
466 objectType: compiler.objectClass.computeType(compiler), | 482 objectType: compiler.objectClass.computeType(compiler), |
467 nullType: compiler.nullClass.computeType(compiler)); | 483 nullType: compiler.nullClass.computeType(compiler)); |
468 | 484 |
469 if (!sideEffectsAreEncodedInSpecString) { | 485 if (!sideEffectsAreEncodedInSpecString) { |
470 new SideEffectsVisitor(behavior.sideEffects) | 486 new SideEffectsVisitor(behavior.sideEffects) |
471 .visit(behavior.codeTemplate.ast); | 487 .visit(behavior.codeTemplate.ast); |
472 } | 488 } |
| 489 if (!throwBehaviorFromSpecString) { |
| 490 behavior.throwBehavior = |
| 491 new ThrowBehaviorVisitor().analyze(behavior.codeTemplate.ast); |
| 492 } |
473 | 493 |
474 return behavior; | 494 return behavior; |
475 } | 495 } |
476 | 496 |
477 static NativeBehavior ofJsEmbeddedGlobalCall(Send jsGlobalCall, | 497 static NativeBehavior ofJsEmbeddedGlobalCall(Send jsGlobalCall, |
478 Compiler compiler, | 498 Compiler compiler, |
479 resolver) { | 499 resolver) { |
480 // The first argument of a JS-embedded global call is a string encoding | 500 // The first argument of a JS-embedded global call is a string encoding |
481 // the type of the code. | 501 // the type of the code. |
482 // | 502 // |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 | 541 |
522 processSpecString(compiler, jsGlobalCall, | 542 processSpecString(compiler, jsGlobalCall, |
523 specString, | 543 specString, |
524 validTags: const ['returns', 'creates'], | 544 validTags: const ['returns', 'creates'], |
525 resolveType: resolveType, | 545 resolveType: resolveType, |
526 typesReturned: behavior.typesReturned, | 546 typesReturned: behavior.typesReturned, |
527 typesInstantiated: behavior.typesInstantiated, | 547 typesInstantiated: behavior.typesInstantiated, |
528 objectType: compiler.objectClass.computeType(compiler), | 548 objectType: compiler.objectClass.computeType(compiler), |
529 nullType: compiler.nullClass.computeType(compiler)); | 549 nullType: compiler.nullClass.computeType(compiler)); |
530 | 550 |
| 551 // Embedded globals are usually pre-computed data structures or JavaScript |
| 552 // functions that never change. |
| 553 // TODO(sra): Allow the use site to override these defaults. |
| 554 behavior.sideEffects.clearAllDependencies(); |
| 555 behavior.sideEffects.clearAllSideEffects(); |
| 556 behavior.throwBehavior = NativeThrowBehavior.NEVER; |
| 557 |
531 return behavior; | 558 return behavior; |
532 } | 559 } |
533 | 560 |
534 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { | 561 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { |
535 FunctionType type = method.computeType(compiler); | 562 FunctionType type = method.computeType(compiler); |
536 var behavior = new NativeBehavior(); | 563 var behavior = new NativeBehavior(); |
537 behavior.typesReturned.add(type.returnType); | 564 behavior.typesReturned.add(type.returnType); |
538 if (!type.returnType.isVoid) { | 565 if (!type.returnType.isVoid) { |
539 // Declared types are nullable. | 566 // Declared types are nullable. |
540 behavior.typesReturned.add(compiler.nullClass.computeType(compiler)); | 567 behavior.typesReturned.add(compiler.nullClass.computeType(compiler)); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 MessageKind.GENERIC, | 719 MessageKind.GENERIC, |
693 {'text': "Type '$typeString' not found."}); | 720 {'text': "Type '$typeString' not found."}); |
694 return const DynamicType(); | 721 return const DynamicType(); |
695 } | 722 } |
696 | 723 |
697 static _errorNode(locationNodeOrElement, compiler) { | 724 static _errorNode(locationNodeOrElement, compiler) { |
698 if (locationNodeOrElement is Node) return locationNodeOrElement; | 725 if (locationNodeOrElement is Node) return locationNodeOrElement; |
699 return locationNodeOrElement.parseNode(compiler); | 726 return locationNodeOrElement.parseNode(compiler); |
700 } | 727 } |
701 } | 728 } |
OLD | NEW |