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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 2965223002: Change inference element invariants (Closed)
Patch Set: Updated cf. comments 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
« no previous file with comments | « pkg/compiler/lib/src/inferrer/type_system.dart ('k') | no next file » | 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 import 'dart:collection'; 5 import 'dart:collection';
6 6
7 import 'package:js_runtime/shared/embedded_names.dart'; 7 import 'package:js_runtime/shared/embedded_names.dart';
8 8
9 import '../closure.dart'; 9 import '../closure.dart';
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 this.registry, 232 this.registry,
233 JavaScriptBackend backend, 233 JavaScriptBackend backend,
234 this.closedWorld, 234 this.closedWorld,
235 this.nativeEmitter, 235 this.nativeEmitter,
236 SourceInformationStrategy sourceInformationFactory) 236 SourceInformationStrategy sourceInformationFactory)
237 : this.infoReporter = backend.compiler.dumpInfoTask, 237 : this.infoReporter = backend.compiler.dumpInfoTask,
238 this.backend = backend, 238 this.backend = backend,
239 this.constantSystem = backend.constantSystem, 239 this.constantSystem = backend.constantSystem,
240 this.rtiSubstitutions = backend.rtiSubstitutions { 240 this.rtiSubstitutions = backend.rtiSubstitutions {
241 assert(target.isImplementation); 241 assert(target.isImplementation);
242 elementInferenceResults = _resultOf(target); 242 elementInferenceResults = _resultOf(target.declaration);
243 assert(elementInferenceResults != null); 243 assert(elementInferenceResults != null);
244 graph.element = target; 244 graph.element = target;
245 sourceElementStack.add(target); 245 sourceElementStack.add(target.declaration);
246 sourceInformationBuilder = 246 sourceInformationBuilder =
247 sourceInformationFactory.createBuilderForContext(target); 247 sourceInformationFactory.createBuilderForContext(target);
248 graph.sourceInformation = 248 graph.sourceInformation =
249 sourceInformationBuilder.buildVariableDeclaration(); 249 sourceInformationBuilder.buildVariableDeclaration();
250 localsHandler = new LocalsHandler( 250 localsHandler = new LocalsHandler(
251 this, 251 this,
252 target, 252 target,
253 target.memberContext, 253 target.memberContext,
254 target.contextClass, 254 target.contextClass,
255 null, 255 null,
(...skipping 29 matching lines...) Expand all
285 @override 285 @override
286 MemberElement get sourceElement => sourceElementStack.last; 286 MemberElement get sourceElement => sourceElementStack.last;
287 287
288 /// Helper to retrieve global inference results for [element] with special 288 /// Helper to retrieve global inference results for [element] with special
289 /// care for `ConstructorBodyElement`s which don't exist at the time the 289 /// care for `ConstructorBodyElement`s which don't exist at the time the
290 /// global analysis run. 290 /// global analysis run.
291 /// 291 ///
292 /// Note: this helper is used selectively. When we know that we are in a 292 /// Note: this helper is used selectively. When we know that we are in a
293 /// context were we don't expect to see a constructor body element, we 293 /// context were we don't expect to see a constructor body element, we
294 /// directly fetch the data from the global inference results. 294 /// directly fetch the data from the global inference results.
295 GlobalTypeInferenceElementResult _resultOf(MemberElement element) => 295 GlobalTypeInferenceElementResult _resultOf(MemberElement element) {
296 globalInferenceResults.resultOfMember( 296 assert(element.isDeclaration);
297 element is ConstructorBodyElementX ? element.constructor : element); 297 return globalInferenceResults.resultOfMember(
298 element is ConstructorBodyElementX ? element.constructor : element);
299 }
298 300
299 /// Build the graph for [target]. 301 /// Build the graph for [target].
300 HGraph build() { 302 HGraph build() {
301 assert(target.isImplementation, failedAt(target)); 303 assert(target.isImplementation, failedAt(target));
302 HInstruction.idCounter = 0; 304 HInstruction.idCounter = 0;
303 // TODO(sigmund): remove `result` and return graph directly, need to ensure 305 // TODO(sigmund): remove `result` and return graph directly, need to ensure
304 // that it can never be null (see result in buildFactory for instance). 306 // that it can never be null (see result in buildFactory for instance).
305 var result; 307 var result;
306 if (target.isGenerativeConstructor) { 308 if (target.isGenerativeConstructor) {
307 result = buildFactory(resolvedAst); 309 result = buildFactory(resolvedAst);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 // Generative constructors of native classes should not be called directly 484 // Generative constructors of native classes should not be called directly
483 // and have an extra argument that causes problems with inlining. 485 // and have an extra argument that causes problems with inlining.
484 if (function.isGenerativeConstructor && 486 if (function.isGenerativeConstructor &&
485 nativeData.isNativeOrExtendsNative(function.enclosingClass)) { 487 nativeData.isNativeOrExtendsNative(function.enclosingClass)) {
486 return false; 488 return false;
487 } 489 }
488 490
489 // A generative constructor body is not seen by global analysis, 491 // A generative constructor body is not seen by global analysis,
490 // so we should not query for its type. 492 // so we should not query for its type.
491 if (!function.isGenerativeConstructorBody) { 493 if (!function.isGenerativeConstructorBody) {
492 if (globalInferenceResults.resultOfMember(function).throwsAlways) { 494 if (globalInferenceResults.resultOfMember(declaration).throwsAlways) {
493 isReachable = false; 495 isReachable = false;
494 return false; 496 return false;
495 } 497 }
496 } 498 }
497 499
498 return true; 500 return true;
499 } 501 }
500 502
501 bool doesNotContainCode() { 503 bool doesNotContainCode() {
502 // A function with size 1 does not contain any code. 504 // A function with size 1 does not contain any code.
503 return InlineWeeder.canBeInlined(functionResolvedAst, 1, 505 return InlineWeeder.canBeInlined(functionResolvedAst, 1,
504 enableUserAssertions: options.enableUserAssertions); 506 enableUserAssertions: options.enableUserAssertions);
505 } 507 }
506 508
507 bool reductiveHeuristic() { 509 bool reductiveHeuristic() {
508 // The call is on a path which is executed rarely, so inline only if it 510 // The call is on a path which is executed rarely, so inline only if it
509 // does not make the program larger. 511 // does not make the program larger.
510 if (isCalledOnce(function)) { 512 if (isCalledOnce(declaration)) {
511 return InlineWeeder.canBeInlined(functionResolvedAst, null, 513 return InlineWeeder.canBeInlined(functionResolvedAst, null,
512 enableUserAssertions: options.enableUserAssertions); 514 enableUserAssertions: options.enableUserAssertions);
513 } 515 }
514 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable 516 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable
515 // case we miss by doing nothing is inlining very simple constructors 517 // case we miss by doing nothing is inlining very simple constructors
516 // where all fields are initialized with values from the arguments at this 518 // where all fields are initialized with values from the arguments at this
517 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but 519 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but
518 // that usually means the factory constructor is left unused and not 520 // that usually means the factory constructor is left unused and not
519 // emitted. 521 // emitted.
520 // We at least inline bodies that are empty (and thus have a size of 1). 522 // We at least inline bodies that are empty (and thus have a size of 1).
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + 560 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP +
559 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; 561 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters;
560 } else { 562 } else {
561 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + 563 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP +
562 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; 564 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters;
563 } 565 }
564 566
565 // If a method is called only once, and all the methods in the 567 // If a method is called only once, and all the methods in the
566 // inlining stack are called only once as well, we know we will 568 // inlining stack are called only once as well, we know we will
567 // save on output size by inlining this method. 569 // save on output size by inlining this method.
568 if (isCalledOnce(function)) { 570 if (isCalledOnce(declaration)) {
569 maxInliningNodes = null; 571 maxInliningNodes = null;
570 } 572 }
571 bool canInline = InlineWeeder.canBeInlined( 573 bool canInline = InlineWeeder.canBeInlined(
572 functionResolvedAst, maxInliningNodes, 574 functionResolvedAst, maxInliningNodes,
573 enableUserAssertions: options.enableUserAssertions); 575 enableUserAssertions: options.enableUserAssertions);
574 if (canInline) { 576 if (canInline) {
575 inlineCache.markAsInlinable(declaration, insideLoop: insideLoop); 577 inlineCache.markAsInlinable(declaration, insideLoop: insideLoop);
576 } else { 578 } else {
577 inlineCache.markAsNonInlinable(declaration, insideLoop: insideLoop); 579 inlineCache.markAsNonInlinable(declaration, insideLoop: insideLoop);
578 } 580 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce; 623 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce;
622 } 624 }
623 625
624 bool isFunctionCalledOnce(MethodElement element) { 626 bool isFunctionCalledOnce(MethodElement element) {
625 // ConstructorBodyElements are not in the type inference graph. 627 // ConstructorBodyElements are not in the type inference graph.
626 if (element is ConstructorBodyElement) return false; 628 if (element is ConstructorBodyElement) return false;
627 return globalInferenceResults.resultOfMember(element).isCalledOnce; 629 return globalInferenceResults.resultOfMember(element).isCalledOnce;
628 } 630 }
629 631
630 bool isCalledOnce(MethodElement element) { 632 bool isCalledOnce(MethodElement element) {
633 assert(element.isDeclaration);
631 return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element); 634 return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element);
632 } 635 }
633 636
634 inlinedFrom(ResolvedAst resolvedAst, f()) { 637 inlinedFrom(ResolvedAst resolvedAst, f()) {
635 MemberElement element = resolvedAst.element; 638 MemberElement element = resolvedAst.element;
636 assert(element is FunctionElement || element is VariableElement); 639 assert(element is FunctionElement || element is VariableElement);
637 return reporter.withCurrentElement(element.implementation, () { 640 return reporter.withCurrentElement(element.implementation, () {
638 // The [sourceElementStack] contains declaration elements. 641 // The [sourceElementStack] contains declaration elements.
639 SourceInformationBuilder oldSourceInformationBuilder = 642 SourceInformationBuilder oldSourceInformationBuilder =
640 sourceInformationBuilder; 643 sourceInformationBuilder;
641 sourceInformationBuilder = sourceInformationBuilder.forContext(element); 644 sourceInformationBuilder = sourceInformationBuilder.forContext(element);
642 sourceElementStack.add(element.declaration); 645 sourceElementStack.add(element);
643 var result = f(); 646 var result = f();
644 sourceInformationBuilder = oldSourceInformationBuilder; 647 sourceInformationBuilder = oldSourceInformationBuilder;
645 sourceElementStack.removeLast(); 648 sourceElementStack.removeLast();
646 return result; 649 return result;
647 }); 650 });
648 } 651 }
649 652
650 /** 653 /**
651 * Return null so it is simple to remove the optional parameters completely 654 * Return null so it is simple to remove the optional parameters completely
652 * from interop methods to match JavaScript semantics for omitted arguments. 655 * from interop methods to match JavaScript semantics for omitted arguments.
(...skipping 3023 matching lines...) Expand 10 before | Expand all | Expand 10 after
3676 void visitTopLevelFieldInvoke(ast.Send node, FieldElement field, 3679 void visitTopLevelFieldInvoke(ast.Send node, FieldElement field,
3677 ast.NodeList arguments, CallStructure callStructure, _) { 3680 ast.NodeList arguments, CallStructure callStructure, _) {
3678 generateStaticFieldGet(node, field); 3681 generateStaticFieldGet(node, field);
3679 generateCallInvoke(node, pop(), 3682 generateCallInvoke(node, pop(),
3680 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 3683 sourceInformationBuilder.buildCall(node, node.argumentsNode));
3681 } 3684 }
3682 3685
3683 @override 3686 @override
3684 void visitTopLevelFunctionInvoke(ast.Send node, MethodElement function, 3687 void visitTopLevelFunctionInvoke(ast.Send node, MethodElement function,
3685 ast.NodeList arguments, CallStructure callStructure, _) { 3688 ast.NodeList arguments, CallStructure callStructure, _) {
3686 if (backend.isForeign(closedWorld.commonElements, function)) { 3689 if (closedWorld.commonElements.isForeign(function)) {
3687 handleForeignSend(node, function); 3690 handleForeignSend(node, function);
3688 } else { 3691 } else {
3689 generateStaticFunctionInvoke(node, function, callStructure); 3692 generateStaticFunctionInvoke(node, function, callStructure);
3690 } 3693 }
3691 } 3694 }
3692 3695
3693 @override 3696 @override
3694 void visitTopLevelFunctionIncompatibleInvoke( 3697 void visitTopLevelFunctionIncompatibleInvoke(
3695 ast.Send node, 3698 ast.Send node,
3696 MethodElement function, 3699 MethodElement function,
(...skipping 2774 matching lines...) Expand 10 before | Expand all | Expand 10 after
6471 ResolvedAst functionResolvedAst, List<HInstruction> compiledArguments, 6474 ResolvedAst functionResolvedAst, List<HInstruction> compiledArguments,
6472 {ResolutionInterfaceType instanceType}) { 6475 {ResolutionInterfaceType instanceType}) {
6473 AstInliningState state = new AstInliningState( 6476 AstInliningState state = new AstInliningState(
6474 function, 6477 function,
6475 returnLocal, 6478 returnLocal,
6476 returnType, 6479 returnType,
6477 resolvedAst, 6480 resolvedAst,
6478 stack, 6481 stack,
6479 localsHandler, 6482 localsHandler,
6480 inTryStatement, 6483 inTryStatement,
6481 isCalledOnce(function), 6484 isCalledOnce(functionResolvedAst.element),
6482 elementInferenceResults); 6485 elementInferenceResults);
6483 resolvedAst = functionResolvedAst; 6486 resolvedAst = functionResolvedAst;
6484 elementInferenceResults = _resultOf(function); 6487 elementInferenceResults = _resultOf(functionResolvedAst.element);
6485 inliningStack.add(state); 6488 inliningStack.add(state);
6486 6489
6487 // Setting up the state of the (AST) builder is performed even when the 6490 // Setting up the state of the (AST) builder is performed even when the
6488 // inlined function is in IR, because the irInliner uses the [returnElement] 6491 // inlined function is in IR, because the irInliner uses the [returnElement]
6489 // of the AST builder. 6492 // of the AST builder.
6490 setupStateForInlining(function, compiledArguments, 6493 setupStateForInlining(function, compiledArguments,
6491 instanceType: instanceType); 6494 instanceType: instanceType);
6492 } 6495 }
6493 6496
6494 void leaveInlinedMethod() { 6497 void leaveInlinedMethod() {
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
6844 this.oldReturnLocal, 6847 this.oldReturnLocal,
6845 this.oldReturnType, 6848 this.oldReturnType,
6846 this.oldResolvedAst, 6849 this.oldResolvedAst,
6847 this.oldStack, 6850 this.oldStack,
6848 this.oldLocalsHandler, 6851 this.oldLocalsHandler,
6849 this.inTryStatement, 6852 this.inTryStatement,
6850 this.allFunctionsCalledOnce, 6853 this.allFunctionsCalledOnce,
6851 this.oldElementInferenceResults) 6854 this.oldElementInferenceResults)
6852 : super(function); 6855 : super(function);
6853 } 6856 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/inferrer/type_system.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698