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

Side by Side Diff: pkg/compiler/lib/src/inferrer/inferrer_engine.dart

Issue 2965223002: Change inference element invariants (Closed)
Patch Set: More entities Created 3 years, 5 months 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
OLDNEW
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 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 if (compiler.options.verbose) { 305 if (compiler.options.verbose) {
306 compiler.progress.reset(); 306 compiler.progress.reset();
307 } 307 }
308 sortResolvedAsts().forEach((ResolvedAst resolvedAst) { 308 sortResolvedAsts().forEach((ResolvedAst resolvedAst) {
309 if (compiler.shouldPrintProgress) { 309 if (compiler.shouldPrintProgress) {
310 reporter.log('Added $addedInGraph elements in inferencing graph.'); 310 reporter.log('Added $addedInGraph elements in inferencing graph.');
311 compiler.progress.reset(); 311 compiler.progress.reset();
312 } 312 }
313 // This also forces the creation of the [ElementTypeInformation] to ensure 313 // This also forces the creation of the [ElementTypeInformation] to ensure
314 // it is in the graph. 314 // it is in the graph.
315 types.withMember( 315 types.withMember(resolvedAst.element, () => analyze(resolvedAst, null));
316 resolvedAst.element.implementation, () => analyze(resolvedAst, null));
317 }); 316 });
318 reporter.log('Added $addedInGraph elements in inferencing graph.'); 317 reporter.log('Added $addedInGraph elements in inferencing graph.');
319 318
320 TypeGraphDump dump = debug.PRINT_GRAPH ? new TypeGraphDump(this) : null; 319 TypeGraphDump dump = debug.PRINT_GRAPH ? new TypeGraphDump(this) : null;
321 320
322 dump?.beforeAnalysis(); 321 dump?.beforeAnalysis();
323 buildWorkQueue(); 322 buildWorkQueue();
324 refine(); 323 refine();
325 324
326 // Try to infer element types of lists and compute their escape information. 325 // Try to infer element types of lists and compute their escape information.
327 types.allocatedLists.values.forEach((TypeInformation info) { 326 types.allocatedLists.values.forEach((TypeInformation info) {
328 analyzeListAndEnqueue(info); 327 analyzeListAndEnqueue(info);
329 }); 328 });
330 329
331 // Try to infer the key and value types for maps and compute the values' 330 // Try to infer the key and value types for maps and compute the values'
332 // escape information. 331 // escape information.
333 types.allocatedMaps.values.forEach((TypeInformation info) { 332 types.allocatedMaps.values.forEach((TypeInformation info) {
334 analyzeMapAndEnqueue(info); 333 analyzeMapAndEnqueue(info);
335 }); 334 });
336 335
337 Set<MethodElement> bailedOutOn = new Set<MethodElement>(); 336 Set<FunctionEntity> bailedOutOn = new Set<FunctionEntity>();
338 337
339 // Trace closures to potentially infer argument types. 338 // Trace closures to potentially infer argument types.
340 types.allocatedClosures.forEach((dynamic info) { 339 types.allocatedClosures.forEach((dynamic info) {
341 void trace( 340 void trace(
342 Iterable<MethodElement> elements, ClosureTracerVisitor tracer) { 341 Iterable<FunctionEntity> elements, ClosureTracerVisitor tracer) {
343 tracer.run(); 342 tracer.run();
344 if (!tracer.continueAnalyzing) { 343 if (!tracer.continueAnalyzing) {
345 elements.forEach((MethodElement e) { 344 elements.forEach((FunctionEntity _element) {
346 closedWorldRefiner.registerMightBePassedToApply(e); 345 MethodElement element = _element;
347 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)"); 346 MethodElement implementation = element.implementation;
348 e.functionSignature.forEachParameter((parameter) { 347 closedWorldRefiner.registerMightBePassedToApply(element);
348 if (debug.VERBOSE) {
349 print("traced closure $element as ${true} (bail)");
350 }
351 implementation.functionSignature.forEachParameter((parameter) {
349 types 352 types
350 .getInferredTypeOfParameter(parameter) 353 .getInferredTypeOfParameter(parameter)
351 .giveUp(this, clearAssignments: false); 354 .giveUp(this, clearAssignments: false);
352 }); 355 });
353 }); 356 });
354 bailedOutOn.addAll(elements); 357 bailedOutOn.addAll(elements);
355 return; 358 return;
356 } 359 }
357 elements 360 elements
358 .where((e) => !bailedOutOn.contains(e)) 361 .where((e) => !bailedOutOn.contains(e))
359 .forEach((MethodElement e) { 362 .forEach((FunctionEntity _element) {
360 e.functionSignature.forEachParameter((parameter) { 363 MethodElement element = _element;
364 MethodElement implementation = element.implementation;
365 implementation.functionSignature.forEachParameter((parameter) {
361 var info = types.getInferredTypeOfParameter(parameter); 366 var info = types.getInferredTypeOfParameter(parameter);
362 info.maybeResume(); 367 info.maybeResume();
363 workQueue.add(info); 368 workQueue.add(info);
364 }); 369 });
365 if (tracer.tracedType.mightBePassedToFunctionApply) { 370 if (tracer.tracedType.mightBePassedToFunctionApply) {
366 closedWorldRefiner.registerMightBePassedToApply(e); 371 closedWorldRefiner.registerMightBePassedToApply(element);
367 } 372 }
368 if (debug.VERBOSE) { 373 if (debug.VERBOSE) {
369 print("traced closure $e as " 374 print("traced closure $element as "
370 "${closedWorldRefiner 375 "${closedWorldRefiner
371 .getCurrentlyKnownMightBePassedToApply(e)}"); 376 .getCurrentlyKnownMightBePassedToApply(element)}");
372 } 377 }
373 }); 378 });
374 } 379 }
375 380
376 if (info is ClosureTypeInformation) { 381 if (info is ClosureTypeInformation) {
377 Iterable<MethodElement> elements = [info.closure]; 382 Iterable<MethodElement> elements = [info.closure];
378 trace(elements, new ClosureTracerVisitor(elements, info, this)); 383 trace(elements, new ClosureTracerVisitor(elements, info, this));
379 } else if (info is CallSiteTypeInformation) { 384 } else if (info is CallSiteTypeInformation) {
380 if (info is StaticCallSiteTypeInformation && 385 if (info is StaticCallSiteTypeInformation &&
381 info.selector != null && 386 info.selector != null &&
382 info.selector.isCall) { 387 info.selector.isCall) {
383 // This is a constructor call to a class with a call method. So we 388 // This is a constructor call to a class with a call method. So we
384 // need to trace the call method here. 389 // need to trace the call method here.
385 assert(info.calledElement.isGenerativeConstructor); 390 MethodElement calledElement = info.calledElement;
386 ClassElement cls = info.calledElement.enclosingClass; 391 assert(calledElement.isGenerativeConstructor);
392 ClassElement cls = calledElement.enclosingClass;
387 MethodElement callMethod = cls.lookupMember(Identifiers.call); 393 MethodElement callMethod = cls.lookupMember(Identifiers.call);
388 assert(callMethod != null, failedAt(cls)); 394 assert(callMethod != null, failedAt(cls));
389 Iterable<MethodElement> elements = [callMethod]; 395 Iterable<FunctionEntity> elements = [callMethod];
390 trace(elements, new ClosureTracerVisitor(elements, info, this)); 396 trace(elements, new ClosureTracerVisitor(elements, info, this));
391 } else { 397 } else {
392 // We only are interested in functions here, as other targets 398 // We only are interested in functions here, as other targets
393 // of this closure call are not a root to trace but an intermediate 399 // of this closure call are not a root to trace but an intermediate
394 // for some other function. 400 // for some other function.
395 Iterable<MethodElement> elements = new List<MethodElement>.from( 401 Iterable<FunctionEntity> elements = new List<FunctionEntity>.from(
396 info.callees.where((e) => e.isFunction)); 402 info.callees.where((e) => e.isFunction));
397 trace(elements, new ClosureTracerVisitor(elements, info, this)); 403 trace(elements, new ClosureTracerVisitor(elements, info, this));
398 } 404 }
399 } else if (info is MemberTypeInformation) { 405 } else if (info is MemberTypeInformation) {
400 trace([info.member], 406 trace(<FunctionEntity>[info.member],
401 new StaticTearOffClosureTracerVisitor(info.member, info, this)); 407 new StaticTearOffClosureTracerVisitor(info.member, info, this));
402 } else if (info is ParameterTypeInformation) { 408 } else if (info is ParameterTypeInformation) {
403 throw new SpannableAssertionFailure( 409 throw new SpannableAssertionFailure(
404 NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info'); 410 NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info');
405 } 411 }
406 }); 412 });
407 413
408 dump?.beforeTracing(); 414 dump?.beforeTracing();
409 415
410 // Reset all nodes that use lists/maps that have been inferred, as well 416 // Reset all nodes that use lists/maps that have been inferred, as well
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 }); 475 });
470 } 476 }
471 dump?.afterAnalysis(); 477 dump?.afterAnalysis();
472 478
473 reporter.log('Inferred $overallRefineCount types.'); 479 reporter.log('Inferred $overallRefineCount types.');
474 480
475 processLoopInformation(); 481 processLoopInformation();
476 } 482 }
477 483
478 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments) { 484 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments) {
479 MemberElement element = resolvedAst.element.implementation; 485 MemberElement element = resolvedAst.element;
480 if (analyzedElements.contains(element)) return; 486 if (analyzedElements.contains(element)) return;
481 analyzedElements.add(element); 487 analyzedElements.add(element);
482 488
483 dynamic visitor = compiler.options.kernelGlobalInference 489 dynamic visitor = compiler.options.kernelGlobalInference
484 ? new KernelTypeGraphBuilder(element, resolvedAst, compiler, this) 490 ? new KernelTypeGraphBuilder(element, resolvedAst, compiler, this)
485 : new ElementGraphBuilder(element, resolvedAst, compiler, this); 491 : new ElementGraphBuilder(element, resolvedAst, compiler, this);
486 TypeInformation type; 492 TypeInformation type;
487 reporter.withCurrentElement(element, () { 493 reporter.withCurrentElement(element, () {
488 // ignore: UNDEFINED_METHOD 494 // ignore: UNDEFINED_METHOD
489 type = visitor.run(); 495 type = visitor.run();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 } 563 }
558 } else { 564 } else {
559 recordReturnType(element, type); 565 recordReturnType(element, type);
560 } 566 }
561 } 567 }
562 568
563 void processLoopInformation() { 569 void processLoopInformation() {
564 types.allocatedCalls.forEach((dynamic info) { 570 types.allocatedCalls.forEach((dynamic info) {
565 if (!info.inLoop) return; 571 if (!info.inLoop) return;
566 if (info is StaticCallSiteTypeInformation) { 572 if (info is StaticCallSiteTypeInformation) {
567 MemberElement member = info.calledElement.declaration; 573 MemberEntity member = info.calledElement;
568 closedWorldRefiner.addFunctionCalledInLoop(member); 574 closedWorldRefiner.addFunctionCalledInLoop(member);
569 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { 575 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) {
570 // For instance methods, we only register a selector called in a 576 // For instance methods, we only register a selector called in a
571 // loop if it is a typed selector, to avoid marking too many 577 // loop if it is a typed selector, to avoid marking too many
572 // methods as being called from within a loop. This cuts down 578 // methods as being called from within a loop. This cuts down
573 // on the code bloat. 579 // on the code bloat.
574 info.targets.forEach((MemberElement element) { 580 info.targets.forEach((MemberElement element) {
575 closedWorldRefiner.addFunctionCalledInLoop(element); 581 closedWorldRefiner.addFunctionCalledInLoop(element);
576 }); 582 });
577 } 583 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 workQueue.addAll(types.allocatedTypes); 620 workQueue.addAll(types.allocatedTypes);
615 workQueue.addAll(types.allocatedClosures); 621 workQueue.addAll(types.allocatedClosures);
616 workQueue.addAll(types.allocatedCalls); 622 workQueue.addAll(types.allocatedCalls);
617 } 623 }
618 624
619 /** 625 /**
620 * Update the assignments to parameters in the graph. [remove] tells 626 * Update the assignments to parameters in the graph. [remove] tells
621 * wheter assignments must be added or removed. If [init] is false, 627 * wheter assignments must be added or removed. If [init] is false,
622 * parameters are added to the work queue. 628 * parameters are added to the work queue.
623 */ 629 */
624 void updateParameterAssignments(TypeInformation caller, Element callee, 630 void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
625 ArgumentsTypes arguments, Selector selector, TypeMask mask, 631 ArgumentsTypes arguments, Selector selector, TypeMask mask,
626 {bool remove, bool addToQueue: true}) { 632 {bool remove, bool addToQueue: true}) {
627 if (callee.name == Identifiers.noSuchMethod_) return; 633 if (callee.name == Identifiers.noSuchMethod_) return;
628 if (callee.isField) { 634 if (callee.isField) {
629 if (selector.isSetter) { 635 if (selector.isSetter) {
630 ElementTypeInformation info = types.getInferredTypeOfMember(callee); 636 ElementTypeInformation info = types.getInferredTypeOfMember(callee);
631 if (remove) { 637 if (remove) {
632 info.removeAssignment(arguments.positional[0]); 638 info.removeAssignment(arguments.positional[0]);
633 } else { 639 } else {
634 info.addAssignment(arguments.positional[0]); 640 info.addAssignment(arguments.positional[0]);
635 } 641 }
636 if (addToQueue) workQueue.add(info); 642 if (addToQueue) workQueue.add(info);
637 } 643 }
638 } else if (callee.isGetter) { 644 } else if (callee.isGetter) {
639 return; 645 return;
640 } else if (selector != null && selector.isGetter) { 646 } else if (selector != null && selector.isGetter) {
641 // We are tearing a function off and thus create a closure. 647 // We are tearing a function off and thus create a closure.
642 assert(callee.isFunction); 648 assert(callee.isFunction);
643 MemberTypeInformation info = types.getInferredTypeOfMember(callee); 649 MethodElement method = callee;
650 MemberTypeInformation info = types.getInferredTypeOfMember(method);
644 if (remove) { 651 if (remove) {
645 info.closurizedCount--; 652 info.closurizedCount--;
646 } else { 653 } else {
647 info.closurizedCount++; 654 info.closurizedCount++;
648 if (Elements.isStaticOrTopLevel(callee)) { 655 if (Elements.isStaticOrTopLevel(method)) {
649 types.allocatedClosures.add(info); 656 types.allocatedClosures.add(info);
650 } else { 657 } else {
651 // We add the call-site type information here so that we 658 // We add the call-site type information here so that we
652 // can benefit from further refinement of the selector. 659 // can benefit from further refinement of the selector.
653 types.allocatedClosures.add(caller); 660 types.allocatedClosures.add(caller);
654 } 661 }
655 FunctionElement function = callee.implementation; 662 FunctionElement function = method.implementation;
656 FunctionSignature signature = function.functionSignature; 663 FunctionSignature signature = function.functionSignature;
657 signature.forEachParameter((Element parameter) { 664 signature.forEachParameter((Element parameter) {
658 ParameterTypeInformation info = 665 ParameterTypeInformation info =
659 types.getInferredTypeOfParameter(parameter); 666 types.getInferredTypeOfParameter(parameter);
660 info.tagAsTearOffClosureParameter(this); 667 info.tagAsTearOffClosureParameter(this);
661 if (addToQueue) workQueue.add(info); 668 if (addToQueue) workQueue.add(info);
662 }); 669 });
663 } 670 }
664 } else { 671 } else {
665 FunctionElement function = callee.implementation; 672 MethodElement method = callee;
673 FunctionElement function = method.implementation;
666 FunctionSignature signature = function.functionSignature; 674 FunctionSignature signature = function.functionSignature;
667 int parameterIndex = 0; 675 int parameterIndex = 0;
668 bool visitingRequiredParameter = true; 676 bool visitingRequiredParameter = true;
669 signature.forEachParameter((Element parameter) { 677 signature.forEachParameter((Element parameter) {
670 if (signature.hasOptionalParameters && 678 if (signature.hasOptionalParameters &&
671 parameter == signature.optionalParameters.first) { 679 parameter == signature.optionalParameters.first) {
672 visitingRequiredParameter = false; 680 visitingRequiredParameter = false;
673 } 681 }
674 TypeInformation type = visitingRequiredParameter 682 TypeInformation type = visitingRequiredParameter
675 ? arguments.positional[parameterIndex] 683 ? arguments.positional[parameterIndex]
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 /** 1104 /**
1097 * Records that the captured variable [local] is read. 1105 * Records that the captured variable [local] is read.
1098 */ 1106 */
1099 void recordCapturedLocalRead(Local local) {} 1107 void recordCapturedLocalRead(Local local) {}
1100 1108
1101 /** 1109 /**
1102 * Records that the variable [local] is being updated. 1110 * Records that the variable [local] is being updated.
1103 */ 1111 */
1104 void recordLocalUpdate(Local local, TypeInformation type) {} 1112 void recordLocalUpdate(Local local, TypeInformation type) {}
1105 } 1113 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698