| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
| 9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
| 10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 }); | 329 }); |
| 330 reporter.log('Added $addedInGraph elements in inferencing graph.'); | 330 reporter.log('Added $addedInGraph elements in inferencing graph.'); |
| 331 | 331 |
| 332 TypeGraphDump dump = debug.PRINT_GRAPH ? new TypeGraphDump(this) : null; | 332 TypeGraphDump dump = debug.PRINT_GRAPH ? new TypeGraphDump(this) : null; |
| 333 | 333 |
| 334 dump?.beforeAnalysis(); | 334 dump?.beforeAnalysis(); |
| 335 buildWorkQueue(); | 335 buildWorkQueue(); |
| 336 refine(); | 336 refine(); |
| 337 | 337 |
| 338 // Try to infer element types of lists and compute their escape information. | 338 // Try to infer element types of lists and compute their escape information. |
| 339 types.allocatedLists.values.forEach((ListTypeInformation info) { | 339 types.allocatedLists.values.forEach((TypeInformation info) { |
| 340 analyzeListAndEnqueue(info); | 340 analyzeListAndEnqueue(info); |
| 341 }); | 341 }); |
| 342 | 342 |
| 343 // Try to infer the key and value types for maps and compute the values' | 343 // Try to infer the key and value types for maps and compute the values' |
| 344 // escape information. | 344 // escape information. |
| 345 types.allocatedMaps.values.forEach((MapTypeInformation info) { | 345 types.allocatedMaps.values.forEach((TypeInformation info) { |
| 346 analyzeMapAndEnqueue(info); | 346 analyzeMapAndEnqueue(info); |
| 347 }); | 347 }); |
| 348 | 348 |
| 349 Set<FunctionElement> bailedOutOn = new Set<FunctionElement>(); | 349 Set<FunctionElement> bailedOutOn = new Set<FunctionElement>(); |
| 350 | 350 |
| 351 // Trace closures to potentially infer argument types. | 351 // Trace closures to potentially infer argument types. |
| 352 types.allocatedClosures.forEach((info) { | 352 types.allocatedClosures.forEach((dynamic info) { |
| 353 void trace( | 353 void trace( |
| 354 Iterable<FunctionElement> elements, ClosureTracerVisitor tracer) { | 354 Iterable<FunctionElement> elements, ClosureTracerVisitor tracer) { |
| 355 tracer.run(); | 355 tracer.run(); |
| 356 if (!tracer.continueAnalyzing) { | 356 if (!tracer.continueAnalyzing) { |
| 357 elements.forEach((FunctionElement e) { | 357 elements.forEach((FunctionElement e) { |
| 358 closedWorldRefiner.registerMightBePassedToApply(e); | 358 closedWorldRefiner.registerMightBePassedToApply(e); |
| 359 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)"); | 359 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)"); |
| 360 e.functionSignature.forEachParameter((parameter) { | 360 e.functionSignature.forEachParameter((parameter) { |
| 361 types | 361 types |
| 362 .getInferredTypeOf(parameter) | 362 .getInferredTypeOf(parameter) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 // If the node cannot be reset, we do not need to update its users either. | 427 // If the node cannot be reset, we do not need to update its users either. |
| 428 if (!info.reset(this)) continue; | 428 if (!info.reset(this)) continue; |
| 429 seenTypes.add(info); | 429 seenTypes.add(info); |
| 430 workQueue.addAll(info.users); | 430 workQueue.addAll(info.users); |
| 431 } | 431 } |
| 432 | 432 |
| 433 workQueue.addAll(seenTypes); | 433 workQueue.addAll(seenTypes); |
| 434 refine(); | 434 refine(); |
| 435 | 435 |
| 436 if (debug.PRINT_SUMMARY) { | 436 if (debug.PRINT_SUMMARY) { |
| 437 types.allocatedLists.values.forEach((ListTypeInformation info) { | 437 types.allocatedLists.values.forEach((_info) { |
| 438 ListTypeInformation info = _info; |
| 438 print('${info.type} ' | 439 print('${info.type} ' |
| 439 'for ${info.originalType.allocationNode} ' | 440 'for ${info.originalType.allocationNode} ' |
| 440 'at ${info.originalType.allocationElement} ' | 441 'at ${info.originalType.allocationElement} ' |
| 441 'after ${info.refineCount}'); | 442 'after ${info.refineCount}'); |
| 442 }); | 443 }); |
| 443 types.allocatedMaps.values.forEach((MapTypeInformation info) { | 444 types.allocatedMaps.values.forEach((_info) { |
| 445 MapTypeInformation info = _info; |
| 444 print('${info.type} ' | 446 print('${info.type} ' |
| 445 'for ${info.originalType.allocationNode} ' | 447 'for ${info.originalType.allocationNode} ' |
| 446 'at ${info.originalType.allocationElement} ' | 448 'at ${info.originalType.allocationElement} ' |
| 447 'after ${info.refineCount}'); | 449 'after ${info.refineCount}'); |
| 448 }); | 450 }); |
| 449 types.allocatedClosures.forEach((TypeInformation info) { | 451 types.allocatedClosures.forEach((TypeInformation info) { |
| 450 if (info is ElementTypeInformation) { | 452 if (info is ElementTypeInformation) { |
| 451 print('${types.getInferredSignatureOf(info.element)} for ' | 453 print('${types.getInferredSignatureOf(info.element)} for ' |
| 452 '${info.element}'); | 454 '${info.element}'); |
| 453 } else if (info is ClosureTypeInformation) { | 455 } else if (info is ClosureTypeInformation) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 // assignment. Instance fields are dealt with in the constructor. | 548 // assignment. Instance fields are dealt with in the constructor. |
| 547 if (Elements.isStaticOrTopLevelField(element)) { | 549 if (Elements.isStaticOrTopLevelField(element)) { |
| 548 recordTypeOfNonFinalField(node, element, type); | 550 recordTypeOfNonFinalField(node, element, type); |
| 549 } | 551 } |
| 550 } else { | 552 } else { |
| 551 recordTypeOfNonFinalField(node, element, type); | 553 recordTypeOfNonFinalField(node, element, type); |
| 552 } | 554 } |
| 553 if (Elements.isStaticOrTopLevelField(element) && | 555 if (Elements.isStaticOrTopLevelField(element) && |
| 554 resolvedAst.body != null && | 556 resolvedAst.body != null && |
| 555 !element.isConst) { | 557 !element.isConst) { |
| 556 var argument = resolvedAst.body; | 558 dynamic argument = resolvedAst.body; |
| 557 // TODO(13429): We could do better here by using the | 559 // TODO(13429): We could do better here by using the |
| 558 // constant handler to figure out if it's a lazy field or not. | 560 // constant handler to figure out if it's a lazy field or not. |
| 559 if (argument.asSend() != null || | 561 if (argument.asSend() != null || |
| 560 (argument.asNewExpression() != null && !argument.isConst)) { | 562 (argument.asNewExpression() != null && !argument.isConst)) { |
| 561 recordType(element, types.nullType); | 563 recordType(element, types.nullType); |
| 562 } | 564 } |
| 563 } | 565 } |
| 564 } else { | 566 } else { |
| 565 recordReturnType(element, type); | 567 recordReturnType(element, type); |
| 566 } | 568 } |
| 567 } | 569 } |
| 568 | 570 |
| 569 void processLoopInformation() { | 571 void processLoopInformation() { |
| 570 types.allocatedCalls.forEach((info) { | 572 types.allocatedCalls.forEach((dynamic info) { |
| 571 if (!info.inLoop) return; | 573 if (!info.inLoop) return; |
| 572 if (info is StaticCallSiteTypeInformation) { | 574 if (info is StaticCallSiteTypeInformation) { |
| 573 closedWorldRefiner | 575 closedWorldRefiner |
| 574 .addFunctionCalledInLoop(info.calledElement.declaration); | 576 .addFunctionCalledInLoop(info.calledElement.declaration); |
| 575 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { | 577 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { |
| 576 // For instance methods, we only register a selector called in a | 578 // For instance methods, we only register a selector called in a |
| 577 // loop if it is a typed selector, to avoid marking too many | 579 // loop if it is a typed selector, to avoid marking too many |
| 578 // methods as being called from within a loop. This cuts down | 580 // methods as being called from within a loop. This cuts down |
| 579 // on the code bloat. | 581 // on the code bloat. |
| 580 info.targets.forEach((MemberElement element) { | 582 info.targets.forEach((MemberElement element) { |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 TypeInformation receiverType, | 894 TypeInformation receiverType, |
| 893 Element caller, | 895 Element caller, |
| 894 ArgumentsTypes arguments, | 896 ArgumentsTypes arguments, |
| 895 SideEffects sideEffects, | 897 SideEffects sideEffects, |
| 896 bool inLoop) { | 898 bool inLoop) { |
| 897 if (selector.isClosureCall) { | 899 if (selector.isClosureCall) { |
| 898 return registerCalledClosure(node, selector, mask, receiverType, caller, | 900 return registerCalledClosure(node, selector, mask, receiverType, caller, |
| 899 arguments, sideEffects, inLoop); | 901 arguments, sideEffects, inLoop); |
| 900 } | 902 } |
| 901 | 903 |
| 902 closedWorld.locateMembers(selector, mask).forEach((MemberElement callee) { | 904 closedWorld.locateMembers(selector, mask).forEach((_callee) { |
| 905 MemberElement callee = _callee; |
| 903 updateSideEffects(sideEffects, selector, callee); | 906 updateSideEffects(sideEffects, selector, callee); |
| 904 }); | 907 }); |
| 905 | 908 |
| 906 CallSiteTypeInformation info = new DynamicCallSiteTypeInformation( | 909 CallSiteTypeInformation info = new DynamicCallSiteTypeInformation( |
| 907 types.currentMember, | 910 types.currentMember, |
| 908 node, | 911 node, |
| 909 caller, | 912 caller, |
| 910 selector, | 913 selector, |
| 911 mask, | 914 mask, |
| 912 receiverType, | 915 receiverType, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 types.allocatedCalls.add(info); | 977 types.allocatedCalls.add(info); |
| 975 return info; | 978 return info; |
| 976 } | 979 } |
| 977 | 980 |
| 978 // Sorts the resolved elements by size. We do this for this inferrer | 981 // Sorts the resolved elements by size. We do this for this inferrer |
| 979 // to get the same results for [ListTracer] compared to the | 982 // to get the same results for [ListTracer] compared to the |
| 980 // [SimpleTypesInferrer]. | 983 // [SimpleTypesInferrer]. |
| 981 Iterable<ResolvedAst> sortResolvedAsts() { | 984 Iterable<ResolvedAst> sortResolvedAsts() { |
| 982 int max = 0; | 985 int max = 0; |
| 983 Map<int, Setlet<ResolvedAst>> methodSizes = <int, Setlet<ResolvedAst>>{}; | 986 Map<int, Setlet<ResolvedAst>> methodSizes = <int, Setlet<ResolvedAst>>{}; |
| 984 compiler.enqueuer.resolution.processedEntities | 987 compiler.enqueuer.resolution.processedEntities.forEach((_element) { |
| 985 .forEach((MemberElement element) { | 988 MemberElement element = _element; |
| 986 ResolvedAst resolvedAst = element.resolvedAst; | 989 ResolvedAst resolvedAst = element.resolvedAst; |
| 987 element = element.implementation; | 990 element = element.implementation; |
| 988 if (element.impliesType) return; | 991 if (element.impliesType) return; |
| 989 assert( | 992 assert( |
| 990 element.isField || | 993 element.isField || |
| 991 element.isFunction || | 994 element.isFunction || |
| 992 element.isConstructor || | 995 element.isConstructor || |
| 993 element.isGetter || | 996 element.isGetter || |
| 994 element.isSetter, | 997 element.isSetter, |
| 995 failedAt(element, 'Unexpected element kind: ${element.kind}')); | 998 failedAt(element, 'Unexpected element kind: ${element.kind}')); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 /** | 1087 /** |
| 1085 * Records that the captured variable [local] is read. | 1088 * Records that the captured variable [local] is read. |
| 1086 */ | 1089 */ |
| 1087 void recordCapturedLocalRead(Local local) {} | 1090 void recordCapturedLocalRead(Local local) {} |
| 1088 | 1091 |
| 1089 /** | 1092 /** |
| 1090 * Records that the variable [local] is being updated. | 1093 * Records that the variable [local] is being updated. |
| 1091 */ | 1094 */ |
| 1092 void recordLocalUpdate(Local local, TypeInformation type) {} | 1095 void recordLocalUpdate(Local local, TypeInformation type) {} |
| 1093 } | 1096 } |
| OLD | NEW |