| 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 '../common.dart'; | 10 import '../common.dart'; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 | 72 |
| 73 void tryScalarReplacement(Primitive allocation) { | 73 void tryScalarReplacement(Primitive allocation) { |
| 74 | 74 |
| 75 // We can do scalar replacement of an aggregate if all uses of an allocation | 75 // We can do scalar replacement of an aggregate if all uses of an allocation |
| 76 // are reads or writes. | 76 // are reads or writes. |
| 77 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { | 77 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { |
| 78 Node use = ref.parent; | 78 Node use = ref.parent; |
| 79 if (use is GetField) continue; | 79 if (use is GetField) continue; |
| 80 if (use is SetField && use.object == ref) continue; | 80 if (use is SetField && use.objectRef == ref) continue; |
| 81 return; | 81 return; |
| 82 } | 82 } |
| 83 | 83 |
| 84 Set<FieldElement> reads = new Set<FieldElement>(); | 84 Set<FieldElement> reads = new Set<FieldElement>(); |
| 85 Set<FieldElement> writes = new Set<FieldElement>(); | 85 Set<FieldElement> writes = new Set<FieldElement>(); |
| 86 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { | 86 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { |
| 87 Node use = ref.parent; | 87 Node use = ref.parent; |
| 88 if (use is GetField) { | 88 if (use is GetField) { |
| 89 reads.add(use.field); | 89 reads.add(use.field); |
| 90 } else if (use is SetField) { | 90 } else if (use is SetField) { |
| 91 writes.add(use.field); | 91 writes.add(use.field); |
| 92 } else { | 92 } else { |
| 93 assert(false); | 93 assert(false); |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 // Find the initial values of the fields. A CreateBox has no initial | 97 // Find the initial values of the fields. A CreateBox has no initial |
| 98 // values. CreateInstance has initial values in the order of the fields. | 98 // values. CreateInstance has initial values in the order of the fields. |
| 99 Map<FieldElement, Primitive> fieldInitialValues = | 99 Map<FieldElement, Primitive> fieldInitialValues = |
| 100 <FieldElement, Primitive>{}; | 100 <FieldElement, Primitive>{}; |
| 101 if (allocation is CreateInstance) { | 101 if (allocation is CreateInstance) { |
| 102 int i = 0; | 102 int i = 0; |
| 103 allocation.classElement.forEachInstanceField( | 103 allocation.classElement.forEachInstanceField( |
| 104 (ClassElement enclosingClass, FieldElement field) { | 104 (ClassElement enclosingClass, FieldElement field) { |
| 105 Primitive argument = allocation.arguments[i++].definition; | 105 Primitive argument = allocation.argument(i++); |
| 106 fieldInitialValues[field] = argument; | 106 fieldInitialValues[field] = argument; |
| 107 }, | 107 }, |
| 108 includeSuperAndInjectedMembers: true); | 108 includeSuperAndInjectedMembers: true); |
| 109 } | 109 } |
| 110 | 110 |
| 111 // Create [MutableVariable]s for each written field. Initialize the | 111 // Create [MutableVariable]s for each written field. Initialize the |
| 112 // MutableVariable with the value from the allocator, or initialize with a | 112 // MutableVariable with the value from the allocator, or initialize with a |
| 113 // `null` constant if there is not initial value. | 113 // `null` constant if there is not initial value. |
| 114 Map<FieldElement, MutableVariable> cells = | 114 Map<FieldElement, MutableVariable> cells = |
| 115 <FieldElement, MutableVariable>{}; | 115 <FieldElement, MutableVariable>{}; |
| 116 InteriorNode insertionPoint = allocation.parent; // LetPrim | 116 InteriorNode insertionPoint = allocation.parent; // LetPrim |
| 117 for (FieldElement field in writes) { | 117 for (FieldElement field in writes) { |
| 118 MutableVariable variable = new MutableVariable(field); | 118 MutableVariable variable = new MutableVariable(field); |
| 119 variable.type = new TypeMask.nonNullEmpty(); | 119 variable.type = new TypeMask.nonNullEmpty(); |
| 120 cells[field] = variable; | 120 cells[field] = variable; |
| 121 Primitive initialValue = fieldInitialValues[field]; | 121 Primitive initialValue = fieldInitialValues[field]; |
| 122 if (initialValue == null) { | 122 if (initialValue == null) { |
| 123 assert(allocation is CreateBox); | 123 assert(allocation is CreateBox); |
| 124 initialValue = new Constant(new NullConstantValue()); | 124 initialValue = new Constant(new NullConstantValue()); |
| 125 LetPrim let = new LetPrim(initialValue); | 125 LetPrim let = new LetPrim(initialValue); |
| 126 let.primitive.parent = let; | 126 let.primitive.parent = let; |
| 127 insertionPoint = let..insertBelow(insertionPoint); | 127 insertionPoint = let..insertBelow(insertionPoint); |
| 128 } | 128 } |
| 129 LetMutable let = new LetMutable(variable, initialValue); | 129 LetMutable let = new LetMutable(variable, initialValue); |
| 130 let.value.parent = let; | 130 let.valueRef.parent = let; |
| 131 insertionPoint = let..insertBelow(insertionPoint); | 131 insertionPoint = let..insertBelow(insertionPoint); |
| 132 } | 132 } |
| 133 | 133 |
| 134 // Replace references with MutableVariable operations or references to the | 134 // Replace references with MutableVariable operations or references to the |
| 135 // field's value. | 135 // field's value. |
| 136 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { | 136 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) { |
| 137 Node use = ref.parent; | 137 Node use = ref.parent; |
| 138 if (use is GetField) { | 138 if (use is GetField) { |
| 139 GetField getField = use; | 139 GetField getField = use; |
| 140 MutableVariable variable = cells[getField.field]; | 140 MutableVariable variable = cells[getField.field]; |
| 141 if (variable != null) { | 141 if (variable != null) { |
| 142 GetMutable getter = new GetMutable(variable); | 142 GetMutable getter = new GetMutable(variable); |
| 143 getter.type = getField.type; | 143 getter.type = getField.type; |
| 144 getter.variable.parent = getter; | 144 getter.variableRef.parent = getter; |
| 145 getField.replaceUsesWith(getter); | 145 getField.replaceUsesWith(getter); |
| 146 replacePrimitive(getField, getter); | 146 replacePrimitive(getField, getter); |
| 147 deletePrimitive(getField); | 147 deletePrimitive(getField); |
| 148 } else { | 148 } else { |
| 149 Primitive value = fieldInitialValues[getField.field]; | 149 Primitive value = fieldInitialValues[getField.field]; |
| 150 getField.replaceUsesWith(value); | 150 getField.replaceUsesWith(value); |
| 151 deleteLetPrimOf(getField); | 151 deleteLetPrimOf(getField); |
| 152 } | 152 } |
| 153 } else if (use is SetField && use.object == ref) { | 153 } else if (use is SetField && use.objectRef == ref) { |
| 154 SetField setField = use; | 154 SetField setField = use; |
| 155 MutableVariable variable = cells[setField.field]; | 155 MutableVariable variable = cells[setField.field]; |
| 156 Primitive value = setField.value.definition; | 156 Primitive value = setField.value; |
| 157 variable.type = variable.type.union(value.type, classWorld); | 157 variable.type = variable.type.union(value.type, classWorld); |
| 158 SetMutable setter = new SetMutable(variable, value); | 158 SetMutable setter = new SetMutable(variable, value); |
| 159 setter.variable.parent = setter; | 159 setter.variableRef.parent = setter; |
| 160 setter.value.parent = setter; | 160 setter.valueRef.parent = setter; |
| 161 setField.replaceUsesWith(setter); | 161 setField.replaceUsesWith(setter); |
| 162 replacePrimitive(setField, setter); | 162 replacePrimitive(setField, setter); |
| 163 deletePrimitive(setField); | 163 deletePrimitive(setField); |
| 164 } else { | 164 } else { |
| 165 assert(false); | 165 assert(false); |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 | 168 |
| 169 // Delete [allocation] since that might 'free' another scalar replacement | 169 // Delete [allocation] since that might 'free' another scalar replacement |
| 170 // candidate by deleting the last non-field-access. | 170 // candidate by deleting the last non-field-access. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 class ScalarReplacementRemovalVisitor extends TrampolineRecursiveVisitor { | 220 class ScalarReplacementRemovalVisitor extends TrampolineRecursiveVisitor { |
| 221 ScalarReplacementVisitor process; | 221 ScalarReplacementVisitor process; |
| 222 | 222 |
| 223 ScalarReplacementRemovalVisitor(this.process); | 223 ScalarReplacementRemovalVisitor(this.process); |
| 224 | 224 |
| 225 processReference(Reference reference) { | 225 processReference(Reference reference) { |
| 226 process.reconsider(reference.definition); | 226 process.reconsider(reference.definition); |
| 227 reference.unlink(); | 227 reference.unlink(); |
| 228 } | 228 } |
| 229 } | 229 } |
| OLD | NEW |