Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: lib/compiler/implementation/js_backend/backend.dart

Issue 11341041: Fix for dartbug.com/6036: the intersection of two different types is not always conflicting. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/bailout.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 part of js_backend; 5 part of js_backend;
6 6
7 typedef void Recompile(Element element); 7 typedef void Recompile(Element element);
8 8
9 class ReturnInfo { 9 class ReturnInfo {
10 HType returnType; 10 HType returnType;
11 List<Element> compiledFunctions; 11 List<Element> compiledFunctions;
12 12
13 ReturnInfo(HType this.returnType) 13 ReturnInfo(HType this.returnType)
14 : compiledFunctions = new List<Element>(); 14 : compiledFunctions = new List<Element>();
15 15
16 ReturnInfo.unknownType() 16 ReturnInfo.unknownType()
17 : this.returnType = null, 17 : this.returnType = null,
18 compiledFunctions = new List<Element>(); 18 compiledFunctions = new List<Element>();
19 19
20 void update(HType type, Recompile recompile) { 20 void update(HType type, Recompile recompile, Compiler compiler) {
21 HType newType = returnType != null ? returnType.union(type) : type; 21 HType newType =
22 returnType != null ? returnType.union(type, compiler) : type;
22 if (newType != returnType) { 23 if (newType != returnType) {
23 if (returnType == null && identical(newType, HType.UNKNOWN)) { 24 if (returnType == null && identical(newType, HType.UNKNOWN)) {
24 // If the first actual piece of information is not providing any type 25 // If the first actual piece of information is not providing any type
25 // information there is no need to recompile callers. 26 // information there is no need to recompile callers.
26 compiledFunctions.clear(); 27 compiledFunctions.clear();
27 } 28 }
28 returnType = newType; 29 returnType = newType;
29 if (recompile != null) { 30 if (recompile != null) {
30 compiledFunctions.forEach(recompile); 31 compiledFunctions.forEach(recompile);
31 } 32 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 return result; 114 return result;
114 } 115 }
115 116
116 static const HTypeList ALL_UNKNOWN = const HTypeList.withAllUnknown(); 117 static const HTypeList ALL_UNKNOWN = const HTypeList.withAllUnknown();
117 118
118 bool get allUnknown => types == null; 119 bool get allUnknown => types == null;
119 bool get hasNamedArguments => namedArguments != null; 120 bool get hasNamedArguments => namedArguments != null;
120 int get length => types.length; 121 int get length => types.length;
121 HType operator[](int index) => types[index]; 122 HType operator[](int index) => types[index];
122 123
123 HTypeList union(HTypeList other) { 124 HTypeList union(HTypeList other, Compiler compiler) {
124 if (allUnknown) return this; 125 if (allUnknown) return this;
125 if (other.allUnknown) return other; 126 if (other.allUnknown) return other;
126 if (length != other.length) return HTypeList.ALL_UNKNOWN; 127 if (length != other.length) return HTypeList.ALL_UNKNOWN;
127 bool onlyUnknown = true; 128 bool onlyUnknown = true;
128 HTypeList result = this; 129 HTypeList result = this;
129 for (int i = 0; i < length; i++) { 130 for (int i = 0; i < length; i++) {
130 HType newType = this[i].union(other[i]); 131 HType newType = this[i].union(other[i], compiler);
131 if (result == this && newType != this[i]) { 132 if (result == this && newType != this[i]) {
132 // Create a new argument types object with the matching types copied. 133 // Create a new argument types object with the matching types copied.
133 result = new HTypeList(length); 134 result = new HTypeList(length);
134 result.types.setRange(0, i, this.types); 135 result.types.setRange(0, i, this.types);
135 } 136 }
136 if (result != this) { 137 if (result != this) {
137 result.types[i] = newType; 138 result.types[i] = newType;
138 } 139 }
139 if (result[i] != HType.UNKNOWN) onlyUnknown = false; 140 if (result[i] != HType.UNKNOWN) onlyUnknown = false;
140 } 141 }
141 return onlyUnknown ? HTypeList.ALL_UNKNOWN : result; 142 return onlyUnknown ? HTypeList.ALL_UNKNOWN : result;
142 } 143 }
143 144
144 /** 145 /**
145 * Create the union of this [HTypeList] object with the types used by 146 * Create the union of this [HTypeList] object with the types used by
146 * the [node]. If the union results in exactly the same types the receiver 147 * the [node]. If the union results in exactly the same types the receiver
147 * is returned. Otherwise a different [HTypeList] object is returned 148 * is returned. Otherwise a different [HTypeList] object is returned
148 * with the type union information. 149 * with the type union information.
149 */ 150 */
150 HTypeList unionWithInvoke(HInvoke node, HTypeMap types) { 151 HTypeList unionWithInvoke(HInvoke node, HTypeMap types, Compiler compiler) {
151 // Union an all unknown list with something stays all unknown. 152 // Union an all unknown list with something stays all unknown.
152 if (allUnknown) return this; 153 if (allUnknown) return this;
153 154
154 bool allUnknown = true; 155 bool allUnknown = true;
155 if (length != node.inputs.length - 1) { 156 if (length != node.inputs.length - 1) {
156 return HTypeList.ALL_UNKNOWN; 157 return HTypeList.ALL_UNKNOWN;
157 } 158 }
158 159
159 bool onlyUnknown = true; 160 bool onlyUnknown = true;
160 HTypeList result = this; 161 HTypeList result = this;
161 for (int i = 0; i < length; i++) { 162 for (int i = 0; i < length; i++) {
162 HType newType = this[i].union(types[node.inputs[i + 1]]); 163 HType newType = this[i].union(types[node.inputs[i + 1]], compiler);
163 if (result == this && newType != this[i]) { 164 if (result == this && newType != this[i]) {
164 // Create a new argument types object with the matching types copied. 165 // Create a new argument types object with the matching types copied.
165 result = new HTypeList(length); 166 result = new HTypeList(length);
166 result.types.setRange(0, i, this.types); 167 result.types.setRange(0, i, this.types);
167 } 168 }
168 if (result != this) { 169 if (result != this) {
169 result.types[i] = newType; 170 result.types[i] = newType;
170 } 171 }
171 if (result[i] != HType.UNKNOWN) onlyUnknown = false; 172 if (result[i] != HType.UNKNOWN) onlyUnknown = false;
172 } 173 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 void registerFieldType(Map<Element, HType> typeMap, 301 void registerFieldType(Map<Element, HType> typeMap,
301 Element field, 302 Element field,
302 HType type) { 303 HType type) {
303 assert(field.isField()); 304 assert(field.isField());
304 HType before = optimisticFieldType(field); 305 HType before = optimisticFieldType(field);
305 306
306 HType oldType = typeMap[field]; 307 HType oldType = typeMap[field];
307 HType newType; 308 HType newType;
308 309
309 if (oldType != null) { 310 if (oldType != null) {
310 newType = oldType.union(type); 311 newType = oldType.union(type, compiler);
311 } else { 312 } else {
312 newType = type; 313 newType = type;
313 } 314 }
314 typeMap[field] = newType; 315 typeMap[field] = newType;
315 if (oldType != newType) { 316 if (oldType != newType) {
316 scheduleRecompilation(field); 317 scheduleRecompilation(field);
317 } 318 }
318 } 319 }
319 320
320 void registerConstructor(Element element) { 321 void registerConstructor(Element element) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 if (initializerType == null && constructorType == null) { 397 if (initializerType == null && constructorType == null) {
397 // If there are no constructor type information return UNKNOWN. This 398 // If there are no constructor type information return UNKNOWN. This
398 // ensures that the function will be recompiled if useful constructor 399 // ensures that the function will be recompiled if useful constructor
399 // type information becomes available. 400 // type information becomes available.
400 return HType.UNKNOWN; 401 return HType.UNKNOWN;
401 } 402 }
402 // A type set through the constructor overrides the type from the 403 // A type set through the constructor overrides the type from the
403 // initializer list. 404 // initializer list.
404 HType result = constructorType != null ? constructorType : initializerType; 405 HType result = constructorType != null ? constructorType : initializerType;
405 HType type = fieldTypeMap[field]; 406 HType type = fieldTypeMap[field];
406 if (type != null) result = result.union(type); 407 if (type != null) result = result.union(type, compiler);
407 return result; 408 return result;
408 } 409 }
409 410
410 void registerOptimizedFunction(FunctionElement element, 411 void registerOptimizedFunction(FunctionElement element,
411 Element field, 412 Element field,
412 HType type) { 413 HType type) {
413 assert(field.isField()); 414 assert(field.isField());
414 if (Elements.isStaticOrTopLevel(element)) { 415 if (Elements.isStaticOrTopLevel(element)) {
415 optimizedStaticFunctions.putIfAbsent( 416 optimizedStaticFunctions.putIfAbsent(
416 field, () => new Set<Element>()); 417 field, () => new Set<Element>());
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 Compiler get compiler => backend.compiler; 474 Compiler get compiler => backend.compiler;
474 475
475 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { 476 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) {
476 Element element = node.element; 477 Element element = node.element;
477 assert(invariant(node, element.isDeclaration)); 478 assert(invariant(node, element.isDeclaration));
478 HTypeList oldTypes = staticTypeMap[element]; 479 HTypeList oldTypes = staticTypeMap[element];
479 if (oldTypes == null) { 480 if (oldTypes == null) {
480 staticTypeMap[element] = new HTypeList.fromStaticInvocation(node, types); 481 staticTypeMap[element] = new HTypeList.fromStaticInvocation(node, types);
481 } else { 482 } else {
482 if (oldTypes.allUnknown) return; 483 if (oldTypes.allUnknown) return;
483 HTypeList newTypes = oldTypes.unionWithInvoke(node, types); 484 HTypeList newTypes =
485 oldTypes.unionWithInvoke(node, types, backend.compiler);
484 if (identical(newTypes, oldTypes)) return; 486 if (identical(newTypes, oldTypes)) return;
485 staticTypeMap[element] = newTypes; 487 staticTypeMap[element] = newTypes;
486 if (optimizedStaticFunctions.contains(element)) { 488 if (optimizedStaticFunctions.contains(element)) {
487 backend.scheduleForRecompilation(element); 489 backend.scheduleForRecompilation(element);
488 } 490 }
489 } 491 }
490 } 492 }
491 493
492 void registerNonCallStaticUse(HStatic node) { 494 void registerNonCallStaticUse(HStatic node) {
493 // When a static is used for anything else than a call target we cannot 495 // When a static is used for anything else than a call target we cannot
(...skipping 21 matching lines...) Expand all
515 resolverWorld.hasInvokedGetter(element, compiler))) { 517 resolverWorld.hasInvokedGetter(element, compiler))) {
516 return; 518 return;
517 } 519 }
518 520
519 HTypeList providedTypes = 521 HTypeList providedTypes =
520 new HTypeList.fromDynamicInvocation(node, selector, types); 522 new HTypeList.fromDynamicInvocation(node, selector, types);
521 if (!selectorTypeMap.containsKey(selector)) { 523 if (!selectorTypeMap.containsKey(selector)) {
522 selectorTypeMap[selector] = providedTypes; 524 selectorTypeMap[selector] = providedTypes;
523 } else { 525 } else {
524 HTypeList oldTypes = selectorTypeMap[selector]; 526 HTypeList oldTypes = selectorTypeMap[selector];
525 HTypeList newTypes = oldTypes.unionWithInvoke(node, types); 527 HTypeList newTypes =
528 oldTypes.unionWithInvoke(node, types, backend.compiler);
526 if (identical(newTypes, oldTypes)) return; 529 if (identical(newTypes, oldTypes)) return;
527 selectorTypeMap[selector] = newTypes; 530 selectorTypeMap[selector] = newTypes;
528 } 531 }
529 532
530 // If we're not compiling, we don't have to do anything. 533 // If we're not compiling, we don't have to do anything.
531 if (compiler.phase != Compiler.PHASE_COMPILING) return; 534 if (compiler.phase != Compiler.PHASE_COMPILING) return;
532 535
533 // Run through all optimized functions and figure out if they need 536 // Run through all optimized functions and figure out if they need
534 // to be recompiled because of this new invocation. 537 // to be recompiled because of this new invocation.
535 optimizedFunctions.filterBySelector(selector).forEach((Element element) { 538 optimizedFunctions.filterBySelector(selector).forEach((Element element) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 HTypeList found = null; 585 HTypeList found = null;
583 selectorTypeMap.visitMatching(element, 586 selectorTypeMap.visitMatching(element,
584 (Selector selector, HTypeList types) { 587 (Selector selector, HTypeList types) {
585 if (selector.argumentCount != signature.parameterCount || 588 if (selector.argumentCount != signature.parameterCount ||
586 selector.namedArgumentCount > 0) { 589 selector.namedArgumentCount > 0) {
587 types = types.unionWithOptionalParameters(selector, 590 types = types.unionWithOptionalParameters(selector,
588 signature, 591 signature,
589 defaultValueTypes); 592 defaultValueTypes);
590 } 593 }
591 assert(types.allUnknown || types.length == signature.parameterCount); 594 assert(types.allUnknown || types.length == signature.parameterCount);
592 found = (found == null) ? types : found.union(types); 595 found = (found == null) ? types : found.union(types, compiler);
593 return !found.allUnknown; 596 return !found.allUnknown;
594 }); 597 });
595 return found != null ? found : HTypeList.ALL_UNKNOWN; 598 return found != null ? found : HTypeList.ALL_UNKNOWN;
596 } 599 }
597 600
598 void registerOptimizedFunction(Element element, 601 void registerOptimizedFunction(Element element,
599 HTypeList parameterTypes, 602 HTypeList parameterTypes,
600 OptionalParameterTypes defaultValueTypes) { 603 OptionalParameterTypes defaultValueTypes) {
601 if (Elements.isStaticOrTopLevelFunction(element)) { 604 if (Elements.isStaticOrTopLevelFunction(element)) {
602 if (parameterTypes.allUnknown) { 605 if (parameterTypes.allUnknown) {
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 837
835 /** 838 /**
836 * Documentation wanted -- johnniwinther 839 * Documentation wanted -- johnniwinther
837 * 840 *
838 * Invariant: [element] must be a declaration element. 841 * Invariant: [element] must be a declaration element.
839 */ 842 */
840 void registerReturnType(FunctionElement element, HType returnType) { 843 void registerReturnType(FunctionElement element, HType returnType) {
841 assert(invariant(element, element.isDeclaration)); 844 assert(invariant(element, element.isDeclaration));
842 ReturnInfo info = returnInfo[element]; 845 ReturnInfo info = returnInfo[element];
843 if (info != null) { 846 if (info != null) {
844 info.update(returnType, scheduleForRecompilation); 847 info.update(returnType, scheduleForRecompilation, compiler);
845 } else { 848 } else {
846 returnInfo[element] = new ReturnInfo(returnType); 849 returnInfo[element] = new ReturnInfo(returnType);
847 } 850 }
848 } 851 }
849 852
850 /** 853 /**
851 * Retrieve the return type of the function [callee]. The type is optimistic 854 * Retrieve the return type of the function [callee]. The type is optimistic
852 * in the sense that is is based on the compilation of [callee]. If [callee] 855 * in the sense that is is based on the compilation of [callee]. If [callee]
853 * is recompiled the return type might change to someting broader. For that 856 * is recompiled the return type might change to someting broader. For that
854 * reason [caller] is registered for recompilation if this happens. If the 857 * reason [caller] is registered for recompilation if this happens. If the
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 print("Inferred return types:"); 950 print("Inferred return types:");
948 print("----------------------"); 951 print("----------------------");
949 dumpReturnTypes(); 952 dumpReturnTypes();
950 print(""); 953 print("");
951 print("Inferred field types:"); 954 print("Inferred field types:");
952 print("------------------------"); 955 print("------------------------");
953 fieldTypes.dump(); 956 fieldTypes.dump();
954 print(""); 957 print("");
955 } 958 }
956 } 959 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/bailout.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698