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 |