| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.cps_ir.scalar_replacement; | 4 library dart2js.cps_ir.scalar_replacement; |
| 5 | 5 |
| 6 import 'optimizers.dart'; | 6 import 'optimizers.dart'; |
| 7 | 7 |
| 8 import 'dart:collection' show Queue; | 8 import 'dart:collection' show Queue; |
| 9 | 9 |
| 10 import '../closure.dart' show | 10 import '../closure.dart' show |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 import 'cps_ir_nodes_sexpr.dart' show SExpressionStringifier; | 33 import 'cps_ir_nodes_sexpr.dart' show SExpressionStringifier; |
| 34 | 34 |
| 35 /** | 35 /** |
| 36 * Replaces aggregates with a set of local values. Performs inlining of | 36 * Replaces aggregates with a set of local values. Performs inlining of |
| 37 * single-use closures to generate more replacable aggregates. | 37 * single-use closures to generate more replacable aggregates. |
| 38 */ | 38 */ |
| 39 class ScalarReplacer extends Pass { | 39 class ScalarReplacer extends Pass { |
| 40 String get passName => 'Scalar replacement'; | 40 String get passName => 'Scalar replacement'; |
| 41 | 41 |
| 42 final dart2js.InternalErrorFunction _internalError; | 42 final dart2js.InternalErrorFunction _internalError; |
| 43 final World _classWorld; |
| 43 | 44 |
| 44 ScalarReplacer(dart2js.Compiler compiler) | 45 ScalarReplacer(dart2js.Compiler compiler) |
| 45 : _internalError = compiler.internalError; | 46 : _internalError = compiler.internalError, |
| 47 _classWorld = compiler.world; |
| 46 | 48 |
| 47 @override | 49 @override |
| 48 void rewrite(FunctionDefinition root) { | 50 void rewrite(FunctionDefinition root) { |
| 49 // Set all parent pointers. | 51 // Set all parent pointers. |
| 50 new ParentVisitor().visit(root); | 52 new ParentVisitor().visit(root); |
| 51 ScalarReplacementVisitor analyzer = | 53 ScalarReplacementVisitor analyzer = |
| 52 new ScalarReplacementVisitor(_internalError); | 54 new ScalarReplacementVisitor(_internalError, _classWorld); |
| 53 analyzer.analyze(root); | 55 analyzer.analyze(root); |
| 54 analyzer.process(); | 56 analyzer.process(); |
| 55 } | 57 } |
| 56 } | 58 } |
| 57 | 59 |
| 58 /** | 60 /** |
| 59 * Do scalar replacement of aggregates on instances. Since scalar replacement | 61 * Do scalar replacement of aggregates on instances. Since scalar replacement |
| 60 * can create new candidiates, iterate until all scalar replacements are done. | 62 * can create new candidiates, iterate until all scalar replacements are done. |
| 61 */ | 63 */ |
| 62 class ScalarReplacementVisitor extends RecursiveVisitor { | 64 class ScalarReplacementVisitor extends RecursiveVisitor { |
| 63 | 65 |
| 64 final dart2js.InternalErrorFunction internalError; | 66 final dart2js.InternalErrorFunction internalError; |
| 67 final World classWorld; |
| 65 ScalarReplacementRemovalVisitor removalVisitor; | 68 ScalarReplacementRemovalVisitor removalVisitor; |
| 66 | 69 |
| 67 Primitive _current = null; | 70 Primitive _current = null; |
| 68 Set<Primitive> _allocations = new Set<Primitive>(); | 71 Set<Primitive> _allocations = new Set<Primitive>(); |
| 69 Queue<Primitive> _queue = new Queue<Primitive>(); | 72 Queue<Primitive> _queue = new Queue<Primitive>(); |
| 70 | 73 |
| 71 ScalarReplacementVisitor(this.internalError) { | 74 ScalarReplacementVisitor(this.internalError, this.classWorld) { |
| 72 removalVisitor = new ScalarReplacementRemovalVisitor(this); | 75 removalVisitor = new ScalarReplacementRemovalVisitor(this); |
| 73 } | 76 } |
| 74 | 77 |
| 75 void analyze(FunctionDefinition root) { | 78 void analyze(FunctionDefinition root) { |
| 76 visit(root); | 79 visit(root); |
| 77 } | 80 } |
| 78 | 81 |
| 79 void process() { | 82 void process() { |
| 80 while (_queue.isNotEmpty) { | 83 while (_queue.isNotEmpty) { |
| 81 Primitive allocation = _queue.removeFirst(); | 84 Primitive allocation = _queue.removeFirst(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 } | 126 } |
| 124 | 127 |
| 125 // Create [MutableVariable]s for each written field. Initialize the | 128 // Create [MutableVariable]s for each written field. Initialize the |
| 126 // MutableVariable with the value from the allocator, or initialize with a | 129 // MutableVariable with the value from the allocator, or initialize with a |
| 127 // `null` constant if there is not initial value. | 130 // `null` constant if there is not initial value. |
| 128 Map<FieldElement, MutableVariable> cells = | 131 Map<FieldElement, MutableVariable> cells = |
| 129 <FieldElement, MutableVariable>{}; | 132 <FieldElement, MutableVariable>{}; |
| 130 InteriorNode insertionPoint = allocation.parent; // LetPrim | 133 InteriorNode insertionPoint = allocation.parent; // LetPrim |
| 131 for (FieldElement field in writes) { | 134 for (FieldElement field in writes) { |
| 132 MutableVariable variable = new MutableVariable(field); | 135 MutableVariable variable = new MutableVariable(field); |
| 136 variable.type = new TypeMask.nonNullEmpty(); |
| 133 cells[field] = variable; | 137 cells[field] = variable; |
| 134 Primitive initialValue = fieldInitialValues[field]; | 138 Primitive initialValue = fieldInitialValues[field]; |
| 135 if (initialValue == null) { | 139 if (initialValue == null) { |
| 136 assert(allocation is CreateBox); | 140 assert(allocation is CreateBox); |
| 137 initialValue = new Constant(new NullConstantValue()); | 141 initialValue = new Constant(new NullConstantValue()); |
| 138 LetPrim let = new LetPrim(initialValue); | 142 LetPrim let = new LetPrim(initialValue); |
| 139 let.primitive.parent = let; | 143 let.primitive.parent = let; |
| 140 insertionPoint = insertAtBody(insertionPoint, let); | 144 insertionPoint = insertAtBody(insertionPoint, let); |
| 141 } | 145 } |
| 142 LetMutable let = new LetMutable(variable, initialValue); | 146 LetMutable let = new LetMutable(variable, initialValue); |
| 143 let.value.parent = let; | 147 let.value.parent = let; |
| 144 insertionPoint = insertAtBody(insertionPoint, let); | 148 insertionPoint = insertAtBody(insertionPoint, let); |
| 145 } | 149 } |
| 146 | 150 |
| 147 // Replace references with MutableVariable operations or references to the | 151 // Replace references with MutableVariable operations or references to the |
| 148 // field's value. | 152 // field's value. |
| 149 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { | 153 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { |
| 150 Node use = ref.parent; | 154 Node use = ref.parent; |
| 151 if (use is GetField) { | 155 if (use is GetField) { |
| 152 GetField getField = use; | 156 GetField getField = use; |
| 153 MutableVariable variable = cells[getField.field]; | 157 MutableVariable variable = cells[getField.field]; |
| 154 if (variable != null) { | 158 if (variable != null) { |
| 155 GetMutable getter = new GetMutable(variable); | 159 GetMutable getter = new GetMutable(variable); |
| 160 getter.type = getField.type; |
| 156 getter.variable.parent = getter; | 161 getter.variable.parent = getter; |
| 157 getter.substituteFor(getField); | 162 getter.substituteFor(getField); |
| 158 replacePrimitive(getField, getter); | 163 replacePrimitive(getField, getter); |
| 159 deletePrimitive(getField); | 164 deletePrimitive(getField); |
| 160 } else { | 165 } else { |
| 161 Primitive value = fieldInitialValues[getField.field]; | 166 Primitive value = fieldInitialValues[getField.field]; |
| 162 value.substituteFor(getField); | 167 value.substituteFor(getField); |
| 163 deleteLetPrimOf(getField); | 168 deleteLetPrimOf(getField); |
| 164 } | 169 } |
| 165 } else if (use is SetField && use.object == ref) { | 170 } else if (use is SetField && use.object == ref) { |
| 166 SetField setField = use; | 171 SetField setField = use; |
| 167 MutableVariable variable = cells[setField.field]; | 172 MutableVariable variable = cells[setField.field]; |
| 168 Primitive value = setField.value.definition; | 173 Primitive value = setField.value.definition; |
| 174 variable.type = variable.type.union(value.type, classWorld); |
| 169 SetMutable setter = new SetMutable(variable, value); | 175 SetMutable setter = new SetMutable(variable, value); |
| 170 setter.variable.parent = setter; | 176 setter.variable.parent = setter; |
| 171 setter.value.parent = setter; | 177 setter.value.parent = setter; |
| 172 setter.substituteFor(setField); | 178 setter.substituteFor(setField); |
| 173 replacePrimitive(setField, setter); | 179 replacePrimitive(setField, setter); |
| 174 deletePrimitive(setField); | 180 deletePrimitive(setField); |
| 175 } else { | 181 } else { |
| 176 assert(false); | 182 assert(false); |
| 177 } | 183 } |
| 178 } | 184 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 class ScalarReplacementRemovalVisitor extends RecursiveVisitor { | 249 class ScalarReplacementRemovalVisitor extends RecursiveVisitor { |
| 244 ScalarReplacementVisitor process; | 250 ScalarReplacementVisitor process; |
| 245 | 251 |
| 246 ScalarReplacementRemovalVisitor(this.process); | 252 ScalarReplacementRemovalVisitor(this.process); |
| 247 | 253 |
| 248 processReference(Reference reference) { | 254 processReference(Reference reference) { |
| 249 process.reconsider(reference.definition); | 255 process.reconsider(reference.definition); |
| 250 reference.unlink(); | 256 reference.unlink(); |
| 251 } | 257 } |
| 252 } | 258 } |
| OLD | NEW |