OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 import '../common/codegen.dart' show CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenWorkItem; |
6 import '../common/tasks.dart' show CompilerTask; | 6 import '../common/tasks.dart' show CompilerTask; |
7 import '../compiler.dart' show Compiler; | 7 import '../compiler.dart' show Compiler; |
8 import '../constants/constant_system.dart'; | 8 import '../constants/constant_system.dart'; |
9 import '../constants/values.dart'; | 9 import '../constants/values.dart'; |
10 import '../core_types.dart' show CoreClasses; | 10 import '../core_types.dart' show CoreClasses; |
(...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 return node; | 1158 return node; |
1159 } | 1159 } |
1160 | 1160 |
1161 // Look for an allocation with type information and re-write type variable | 1161 // Look for an allocation with type information and re-write type variable |
1162 // as a function of the type parameters of the allocation. This effectively | 1162 // as a function of the type parameters of the allocation. This effectively |
1163 // store-forwards a type variable read through an allocation. | 1163 // store-forwards a type variable read through an allocation. |
1164 | 1164 |
1165 // Match: | 1165 // Match: |
1166 // | 1166 // |
1167 // setRuntimeTypeInfo( | 1167 // setRuntimeTypeInfo( |
1168 // HForeignNew(ClassElement), | 1168 // HCreate(ClassElement), |
1169 // HTypeInfoExpression(t_0, t_1, t_2, ...)); | 1169 // HTypeInfoExpression(t_0, t_1, t_2, ...)); |
1170 // | 1170 // |
1171 // The `t_i` are the values of the type parameters of ClassElement. | 1171 // The `t_i` are the values of the type parameters of ClassElement. |
1172 if (object is HInvokeStatic) { | 1172 if (object is HInvokeStatic) { |
1173 if (object.element == helpers.setRuntimeTypeInfo) { | 1173 if (object.element == helpers.setRuntimeTypeInfo) { |
1174 HInstruction allocation = object.inputs[0]; | 1174 HInstruction allocation = object.inputs[0]; |
1175 if (allocation is HForeignNew) { | 1175 if (allocation is HCreate) { |
1176 HInstruction typeInfo = object.inputs[1]; | 1176 HInstruction typeInfo = object.inputs[1]; |
1177 if (typeInfo is HTypeInfoExpression) { | 1177 if (typeInfo is HTypeInfoExpression) { |
1178 return finishSubstituted( | 1178 return finishSubstituted( |
1179 allocation.element, (int index) => typeInfo.inputs[index]); | 1179 allocation.element, (int index) => typeInfo.inputs[index]); |
1180 } | 1180 } |
1181 } | 1181 } |
1182 return node; | 1182 return node; |
1183 } | 1183 } |
1184 // TODO(sra): Factory constructors pass type arguments after the value | 1184 // TODO(sra): Factory constructors pass type arguments after the value |
1185 // arguments. The [select] argument indexes into these type arguments. | 1185 // arguments. The [select] argument indexes into these type arguments. |
1186 } | 1186 } |
1187 | 1187 |
1188 // Non-generic type (which extends or mixes in a generic type, for example | 1188 // Non-generic type (which extends or mixes in a generic type, for example |
1189 // CodeUnits extends UnmodifiableListBase<int>). | 1189 // CodeUnits extends UnmodifiableListBase<int>). |
1190 // Also used for raw-type when the type parameters are elided. | 1190 // Also used for raw-type when the type parameters are elided. |
1191 if (object is HForeignNew) { | 1191 if (object is HCreate) { |
1192 return finishSubstituted( | 1192 return finishSubstituted( |
1193 object.element, | 1193 object.element, |
1194 // If there are type arguments, all type arguments are 'dynamic'. | 1194 // If there are type arguments, all type arguments are 'dynamic'. |
1195 (int i) => graph.addConstantNull(compiler)); | 1195 (int i) => graph.addConstantNull(compiler)); |
1196 } | 1196 } |
1197 | 1197 |
1198 return node; | 1198 return node; |
1199 } | 1199 } |
1200 } | 1200 } |
1201 | 1201 |
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 memorySet.registerFieldValue(element, receiver, instruction); | 2191 memorySet.registerFieldValue(element, receiver, instruction); |
2192 } | 2192 } |
2193 } | 2193 } |
2194 | 2194 |
2195 void visitFieldSet(HFieldSet instruction) { | 2195 void visitFieldSet(HFieldSet instruction) { |
2196 HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck(); | 2196 HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck(); |
2197 memorySet.registerFieldValueUpdate( | 2197 memorySet.registerFieldValueUpdate( |
2198 instruction.element, receiver, instruction.inputs.last); | 2198 instruction.element, receiver, instruction.inputs.last); |
2199 } | 2199 } |
2200 | 2200 |
2201 void visitForeignNew(HForeignNew instruction) { | 2201 void visitCreate(HCreate instruction) { |
2202 memorySet.registerAllocation(instruction); | 2202 memorySet.registerAllocation(instruction); |
2203 if (shouldTrackInitialValues(instruction)) { | 2203 if (shouldTrackInitialValues(instruction)) { |
2204 int argumentIndex = 0; | 2204 int argumentIndex = 0; |
2205 instruction.element.forEachInstanceField((_, Element member) { | 2205 instruction.element.forEachInstanceField((_, Element member) { |
2206 if (compiler.elementHasCompileTimeError(member)) return; | 2206 if (compiler.elementHasCompileTimeError(member)) return; |
2207 memorySet.registerFieldValue( | 2207 memorySet.registerFieldValue( |
2208 member, instruction, instruction.inputs[argumentIndex++]); | 2208 member, instruction, instruction.inputs[argumentIndex++]); |
2209 }, includeSuperAndInjectedMembers: true); | 2209 }, includeSuperAndInjectedMembers: true); |
2210 } | 2210 } |
2211 // In case this instruction has as input non-escaping objects, we | 2211 // In case this instruction has as input non-escaping objects, we |
2212 // need to mark these objects as escaping. | 2212 // need to mark these objects as escaping. |
2213 memorySet.killAffectedBy(instruction); | 2213 memorySet.killAffectedBy(instruction); |
2214 } | 2214 } |
2215 | 2215 |
2216 bool shouldTrackInitialValues(HForeignNew instruction) { | 2216 bool shouldTrackInitialValues(HCreate instruction) { |
2217 // Don't track initial field values of an allocation that are | 2217 // Don't track initial field values of an allocation that are |
2218 // unprofitable. We search the chain of single uses in allocations for a | 2218 // unprofitable. We search the chain of single uses in allocations for a |
2219 // limited depth. | 2219 // limited depth. |
2220 | 2220 |
2221 const MAX_HEAP_DEPTH = 5; | 2221 const MAX_HEAP_DEPTH = 5; |
2222 | 2222 |
2223 bool interestingUse(HInstruction instruction, int heapDepth) { | 2223 bool interestingUse(HInstruction instruction, int heapDepth) { |
2224 // Heuristic: if the allocation is too deep in heap it is unlikely we will | 2224 // Heuristic: if the allocation is too deep in heap it is unlikely we will |
2225 // recover a field by load-elimination. | 2225 // recover a field by load-elimination. |
2226 // TODO(sra): We can measure this depth by looking at load chains. | 2226 // TODO(sra): We can measure this depth by looking at load chains. |
2227 if (heapDepth == MAX_HEAP_DEPTH) return false; | 2227 if (heapDepth == MAX_HEAP_DEPTH) return false; |
2228 // There are multiple uses so do the full store analysis. | 2228 // There are multiple uses so do the full store analysis. |
2229 if (instruction.usedBy.length != 1) return true; | 2229 if (instruction.usedBy.length != 1) return true; |
2230 HInstruction use = instruction.usedBy.single; | 2230 HInstruction use = instruction.usedBy.single; |
2231 // When the only use is an allocation, the allocation becomes the only | 2231 // When the only use is an allocation, the allocation becomes the only |
2232 // heap alias for the current instruction. | 2232 // heap alias for the current instruction. |
2233 if (use is HForeignNew) return interestingUse(use, heapDepth + 1); | 2233 if (use is HCreate) return interestingUse(use, heapDepth + 1); |
2234 if (use is HLiteralList) return interestingUse(use, heapDepth + 1); | 2234 if (use is HLiteralList) return interestingUse(use, heapDepth + 1); |
2235 if (use is HInvokeStatic) { | 2235 if (use is HInvokeStatic) { |
2236 // Assume the argument escapes. All we do with our initial allocation is | 2236 // Assume the argument escapes. All we do with our initial allocation is |
2237 // have it escape or store it into an object that escapes. | 2237 // have it escape or store it into an object that escapes. |
2238 return false; | 2238 return false; |
2239 // TODO(sra): Handle more functions. `setRuntimeTypeInfo` does not | 2239 // TODO(sra): Handle more functions. `setRuntimeTypeInfo` does not |
2240 // actually kill it's input, but we don't make use of that elsewhere so | 2240 // actually kill it's input, but we don't make use of that elsewhere so |
2241 // there is not point in checking here. | 2241 // there is not point in checking here. |
2242 } | 2242 } |
2243 if (use is HPhi) { | 2243 if (use is HPhi) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2351 if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true; | 2351 if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true; |
2352 return !first.instructionType | 2352 return !first.instructionType |
2353 .isDisjoint(second.instructionType, compiler.world); | 2353 .isDisjoint(second.instructionType, compiler.world); |
2354 } | 2354 } |
2355 | 2355 |
2356 bool isFinal(Element element) { | 2356 bool isFinal(Element element) { |
2357 return compiler.world.fieldNeverChanges(element); | 2357 return compiler.world.fieldNeverChanges(element); |
2358 } | 2358 } |
2359 | 2359 |
2360 bool isConcrete(HInstruction instruction) { | 2360 bool isConcrete(HInstruction instruction) { |
2361 return instruction is HForeignNew || | 2361 return instruction is HCreate || |
2362 instruction is HConstant || | 2362 instruction is HConstant || |
2363 instruction is HLiteralList; | 2363 instruction is HLiteralList; |
2364 } | 2364 } |
2365 | 2365 |
2366 bool couldBeTypedArray(HInstruction receiver) { | 2366 bool couldBeTypedArray(HInstruction receiver) { |
2367 JavaScriptBackend backend = compiler.backend; | 2367 JavaScriptBackend backend = compiler.backend; |
2368 return backend.couldBeTypedArray(receiver.instructionType); | 2368 return backend.couldBeTypedArray(receiver.instructionType); |
2369 } | 2369 } |
2370 | 2370 |
2371 /** | 2371 /** |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2588 | 2588 |
2589 keyedValues.forEach((receiver, values) { | 2589 keyedValues.forEach((receiver, values) { |
2590 result.keyedValues[receiver] = | 2590 result.keyedValues[receiver] = |
2591 new Map<HInstruction, HInstruction>.from(values); | 2591 new Map<HInstruction, HInstruction>.from(values); |
2592 }); | 2592 }); |
2593 | 2593 |
2594 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2594 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
2595 return result; | 2595 return result; |
2596 } | 2596 } |
2597 } | 2597 } |
OLD | NEW |