| 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 typedef void Recompile(Element element); | 5 typedef void Recompile(Element element); |
| 6 | 6 |
| 7 class ReturnInfo { | 7 class ReturnInfo { |
| 8 HType returnType; | 8 HType returnType; |
| 9 List<Element> compiledFunctions; | 9 List<Element> compiledFunctions; |
| 10 | 10 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 } | 57 } |
| 58 return result; | 58 return result; |
| 59 } | 59 } |
| 60 | 60 |
| 61 static const HTypeList ALL_UNKNOWN = const HTypeList.allUnknown(); | 61 static const HTypeList ALL_UNKNOWN = const HTypeList.allUnknown(); |
| 62 | 62 |
| 63 bool get allUnknown => types === null; | 63 bool get allUnknown => types === null; |
| 64 int get length => types.length; | 64 int get length => types.length; |
| 65 HType operator[](int index) => types[index]; | 65 HType operator[](int index) => types[index]; |
| 66 | 66 |
| 67 HTypeList union(HTypeList other) { |
| 68 if (allUnknown) return this; |
| 69 if (other.allUnknown) return other; |
| 70 if (length != other.length) return HTypeList.ALL_UNKNOWN; |
| 71 bool onlyUnknown = true; |
| 72 HTypeList result = this; |
| 73 for (int i = 0; i < length; i++) { |
| 74 HType newType = this[i].union(other[i]); |
| 75 if (result == this && newType != this[i]) { |
| 76 // Create a new argument types object with the matching types copied. |
| 77 result = new HTypeList(length); |
| 78 result.types.setRange(0, i, this.types); |
| 79 } |
| 80 if (result != this) { |
| 81 result.types[i] = newType; |
| 82 } |
| 83 if (result[i] != HType.UNKNOWN) onlyUnknown = false; |
| 84 } |
| 85 return onlyUnknown ? HTypeList.ALL_UNKNOWN : result; |
| 86 } |
| 87 |
| 67 /** | 88 /** |
| 68 * Create the union of this [HTypeList] object with the types used by | 89 * Create the union of this [HTypeList] object with the types used by |
| 69 * the [node]. If the union results in exactly the same types the receiver | 90 * the [node]. If the union results in exactly the same types the receiver |
| 70 * is returned. Otherwise a different [HTypeList] object is returned | 91 * is returned. Otherwise a different [HTypeList] object is returned |
| 71 * with the type union information. | 92 * with the type union information. |
| 72 */ | 93 */ |
| 73 HTypeList union(HInvoke node, HTypeMap types) { | 94 HTypeList unionWithInvoke(HInvoke node, HTypeMap types) { |
| 74 // Union an all unknown list with something stays all unknown. | 95 // Union an all unknown list with something stays all unknown. |
| 75 if (allUnknown) return this; | 96 if (allUnknown) return this; |
| 76 | 97 |
| 77 bool allUnknown = true; | 98 bool allUnknown = true; |
| 78 if (length != node.inputs.length - 1) { | 99 if (length != node.inputs.length - 1) { |
| 79 return HTypeList.ALL_UNKNOWN; | 100 return HTypeList.ALL_UNKNOWN; |
| 80 } | 101 } |
| 81 | 102 |
| 82 bool onlyUnknown = true; | 103 bool onlyUnknown = true; |
| 83 HTypeList result = this; | 104 HTypeList result = this; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 return new HTypeList.fromInvocation(node, types); | 145 return new HTypeList.fromInvocation(node, types); |
| 125 } | 146 } |
| 126 | 147 |
| 127 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { | 148 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { |
| 128 Element element = node.element; | 149 Element element = node.element; |
| 129 HTypeList oldTypes = staticTypeMap[element]; | 150 HTypeList oldTypes = staticTypeMap[element]; |
| 130 if (oldTypes == null) { | 151 if (oldTypes == null) { |
| 131 staticTypeMap[element] = computeProvidedTypes(node, types); | 152 staticTypeMap[element] = computeProvidedTypes(node, types); |
| 132 } else { | 153 } else { |
| 133 if (oldTypes.allUnknown) return; | 154 if (oldTypes.allUnknown) return; |
| 134 HTypeList newTypes = oldTypes.union(node, types); | 155 HTypeList newTypes = oldTypes.unionWithInvoke(node, types); |
| 135 if (newTypes === oldTypes) return; | 156 if (newTypes === oldTypes) return; |
| 136 staticTypeMap[element] = newTypes; | 157 staticTypeMap[element] = newTypes; |
| 137 if (optimizedStaticFunctions.contains(element)) { | 158 if (optimizedStaticFunctions.contains(element)) { |
| 138 backend.scheduleForRecompilation(element); | 159 backend.scheduleForRecompilation(element); |
| 139 } | 160 } |
| 140 } | 161 } |
| 141 } | 162 } |
| 142 | 163 |
| 143 void registerNonCallStaticUse(HStatic node) { | 164 void registerNonCallStaticUse(HStatic node) { |
| 144 // When a static is used for anything else than a call target we cannot | 165 // When a static is used for anything else than a call target we cannot |
| (...skipping 23 matching lines...) Expand all Loading... |
| 168 | 189 |
| 169 // TODO(kasperl): For now, we're only dealing with non-named arguments. | 190 // TODO(kasperl): For now, we're only dealing with non-named arguments. |
| 170 // We should generalize this. | 191 // We should generalize this. |
| 171 HTypeList providedTypes = selector.namedArguments.isEmpty() | 192 HTypeList providedTypes = selector.namedArguments.isEmpty() |
| 172 ? computeProvidedTypes(node, types) | 193 ? computeProvidedTypes(node, types) |
| 173 : HTypeList.ALL_UNKNOWN; | 194 : HTypeList.ALL_UNKNOWN; |
| 174 if (!selectorTypeMap.containsKey(selector)) { | 195 if (!selectorTypeMap.containsKey(selector)) { |
| 175 selectorTypeMap[selector] = providedTypes; | 196 selectorTypeMap[selector] = providedTypes; |
| 176 } else { | 197 } else { |
| 177 HTypeList oldTypes = selectorTypeMap[selector]; | 198 HTypeList oldTypes = selectorTypeMap[selector]; |
| 178 HTypeList newTypes = oldTypes.union(node, types); | 199 HTypeList newTypes = oldTypes.unionWithInvoke(node, types); |
| 179 if (newTypes === oldTypes) return; | 200 if (newTypes === oldTypes) return; |
| 180 selectorTypeMap[selector] = newTypes; | 201 selectorTypeMap[selector] = newTypes; |
| 181 } | 202 } |
| 182 | 203 |
| 183 // If we're not compiling, we don't have to do anything. | 204 // If we're not compiling, we don't have to do anything. |
| 184 if (compiler.phase != Compiler.PHASE_COMPILING) return; | 205 if (compiler.phase != Compiler.PHASE_COMPILING) return; |
| 185 | 206 |
| 186 // Run through all optimized functions and figure out if they need | 207 // Run through all optimized functions and figure out if they need |
| 187 // to be recompiled because of this new invocation. | 208 // to be recompiled because of this new invocation. |
| 188 optimizedFunctions.filterBySelector(selector).forEach((Element element) { | 209 optimizedFunctions.filterBySelector(selector).forEach((Element element) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 245 } |
| 225 } | 246 } |
| 226 | 247 |
| 227 // TODO(kasperl): What kind of non-members do we get here? | 248 // TODO(kasperl): What kind of non-members do we get here? |
| 228 if (!element.isMember()) return HTypeList.ALL_UNKNOWN; | 249 if (!element.isMember()) return HTypeList.ALL_UNKNOWN; |
| 229 | 250 |
| 230 FunctionSignature signature = element.computeSignature(compiler); | 251 FunctionSignature signature = element.computeSignature(compiler); |
| 231 HTypeList found = null; | 252 HTypeList found = null; |
| 232 selectorTypeMap.visitMatching(element, | 253 selectorTypeMap.visitMatching(element, |
| 233 (Selector selector, HTypeList types) { | 254 (Selector selector, HTypeList types) { |
| 234 if (selector.argumentCount != signature.parameterCount || | 255 if (selector.argumentCount != signature.parameterCount) { |
| 235 types === null) { | |
| 236 found = HTypeList.ALL_UNKNOWN; | 256 found = HTypeList.ALL_UNKNOWN; |
| 237 return false; | 257 return false; |
| 238 } else if (found === null) { | 258 } else if (found === null) { |
| 239 found = types; | 259 found = types; |
| 240 return true; | 260 return true; |
| 241 } else { | 261 } else { |
| 242 found = HTypeList.ALL_UNKNOWN; | 262 found = found.union(types); |
| 243 return false; | 263 return !found.allUnknown; |
| 244 } | 264 } |
| 245 }); | 265 }); |
| 246 return found !== null ? found : HTypeList.ALL_UNKNOWN; | 266 return found !== null ? found : HTypeList.ALL_UNKNOWN; |
| 247 } | 267 } |
| 248 | 268 |
| 249 void registerOptimization(Element element, HTypeList parameterTypes) { | 269 void registerOptimization(Element element, HTypeList parameterTypes) { |
| 250 if (Elements.isStaticOrTopLevelFunction(element)) { | 270 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 251 if (parameterTypes.allUnknown) { | 271 if (parameterTypes.allUnknown) { |
| 252 optimizedStaticFunctions.remove(element); | 272 optimizedStaticFunctions.remove(element); |
| 253 } else { | 273 } else { |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 HType optimisticReturnTypesWithRecompilationOnTypeChange( | 538 HType optimisticReturnTypesWithRecompilationOnTypeChange( |
| 519 FunctionElement caller, FunctionElement callee) { | 539 FunctionElement caller, FunctionElement callee) { |
| 520 returnInfo.putIfAbsent(callee, () => new ReturnInfo.unknownType()); | 540 returnInfo.putIfAbsent(callee, () => new ReturnInfo.unknownType()); |
| 521 ReturnInfo info = returnInfo[callee]; | 541 ReturnInfo info = returnInfo[callee]; |
| 522 if (info.returnType != HType.UNKNOWN && caller != null) { | 542 if (info.returnType != HType.UNKNOWN && caller != null) { |
| 523 info.addCompiledFunction(caller); | 543 info.addCompiledFunction(caller); |
| 524 } | 544 } |
| 525 return info.returnType; | 545 return info.returnType; |
| 526 } | 546 } |
| 527 } | 547 } |
| OLD | NEW |