| 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 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'; |
| 11 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 11 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 12 import '../common/names.dart' show Identifiers, Selectors; | 12 import '../common/names.dart' show Identifiers, Selectors; |
| 13 import '../common/tasks.dart' show CompilerTask; | 13 import '../common/tasks.dart' show CompilerTask; |
| 14 import '../compiler.dart' show Compiler; | 14 import '../compiler.dart' show Compiler; |
| 15 import '../constants/constant_system.dart'; | 15 import '../constants/constant_system.dart'; |
| 16 import '../constants/expressions.dart'; | 16 import '../constants/expressions.dart'; |
| 17 import '../constants/values.dart'; | 17 import '../constants/values.dart'; |
| 18 import '../common_elements.dart' show CommonElements; | |
| 19 import '../elements/resolution_types.dart'; | 18 import '../elements/resolution_types.dart'; |
| 20 import '../diagnostics/messages.dart' show Message, MessageTemplate; | 19 import '../diagnostics/messages.dart' show Message, MessageTemplate; |
| 21 import '../dump_info.dart' show InfoReporter; | 20 import '../dump_info.dart' show InfoReporter; |
| 22 import '../elements/elements.dart'; | 21 import '../elements/elements.dart'; |
| 23 import '../elements/entities.dart'; | 22 import '../elements/entities.dart'; |
| 24 import '../elements/modelx.dart' show ConstructorBodyElementX; | 23 import '../elements/modelx.dart' show ConstructorBodyElementX; |
| 25 import '../io/source_information.dart'; | 24 import '../io/source_information.dart'; |
| 26 import '../js/js.dart' as js; | 25 import '../js/js.dart' as js; |
| 27 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 26 import '../js_backend/backend_helpers.dart' show BackendHelpers; |
| 28 import '../js_backend/js_backend.dart'; | 27 import '../js_backend/js_backend.dart'; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 sourceInformationBuilder.buildVariableDeclaration(); | 219 sourceInformationBuilder.buildVariableDeclaration(); |
| 221 localsHandler = new LocalsHandler(this, target, null, compiler); | 220 localsHandler = new LocalsHandler(this, target, null, compiler); |
| 222 loopHandler = new SsaLoopHandler(this); | 221 loopHandler = new SsaLoopHandler(this); |
| 223 typeBuilder = new TypeBuilder(this); | 222 typeBuilder = new TypeBuilder(this); |
| 224 } | 223 } |
| 225 | 224 |
| 226 BackendHelpers get helpers => backend.helpers; | 225 BackendHelpers get helpers => backend.helpers; |
| 227 | 226 |
| 228 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; | 227 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; |
| 229 | 228 |
| 230 DiagnosticReporter get reporter => compiler.reporter; | |
| 231 | |
| 232 CommonElements get commonElements => closedWorld.commonElements; | |
| 233 | |
| 234 Element get targetElement => target; | 229 Element get targetElement => target; |
| 235 | 230 |
| 236 /// Reference to resolved elements in [target]'s AST. | 231 /// Reference to resolved elements in [target]'s AST. |
| 237 TreeElements get elements => resolvedAst.elements; | 232 TreeElements get elements => resolvedAst.elements; |
| 238 | 233 |
| 239 @override | 234 @override |
| 240 SemanticSendVisitor get sendVisitor => this; | 235 SemanticSendVisitor get sendVisitor => this; |
| 241 | 236 |
| 242 @override | 237 @override |
| 243 void visitNode(ast.Node node) { | 238 void visitNode(ast.Node node) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 if (target.isGenerativeConstructor) { | 273 if (target.isGenerativeConstructor) { |
| 279 result = buildFactory(resolvedAst); | 274 result = buildFactory(resolvedAst); |
| 280 } else if (target.isGenerativeConstructorBody || | 275 } else if (target.isGenerativeConstructorBody || |
| 281 target.isFactoryConstructor || | 276 target.isFactoryConstructor || |
| 282 target.isFunction || | 277 target.isFunction || |
| 283 target.isGetter || | 278 target.isGetter || |
| 284 target.isSetter) { | 279 target.isSetter) { |
| 285 result = buildMethod(target); | 280 result = buildMethod(target); |
| 286 } else if (target.isField) { | 281 } else if (target.isField) { |
| 287 if (target.isInstanceMember) { | 282 if (target.isInstanceMember) { |
| 288 assert(compiler.options.enableTypeAssertions); | 283 assert(options.enableTypeAssertions); |
| 289 result = buildCheckedSetter(target); | 284 result = buildCheckedSetter(target); |
| 290 } else { | 285 } else { |
| 291 result = buildLazyInitializer(target); | 286 result = buildLazyInitializer(target); |
| 292 } | 287 } |
| 293 } else { | 288 } else { |
| 294 reporter.internalError(target, 'Unexpected element kind $target.'); | 289 reporter.internalError(target, 'Unexpected element kind $target.'); |
| 295 } | 290 } |
| 296 assert(result.isValid()); | 291 assert(result.isValid()); |
| 297 return result; | 292 return result; |
| 298 } | 293 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 ResolvedAst functionResolvedAst = function.resolvedAst; | 415 ResolvedAst functionResolvedAst = function.resolvedAst; |
| 421 bool insideLoop = loopDepth > 0 || graph.calledInLoop; | 416 bool insideLoop = loopDepth > 0 || graph.calledInLoop; |
| 422 | 417 |
| 423 // Bail out early if the inlining decision is in the cache and we can't | 418 // Bail out early if the inlining decision is in the cache and we can't |
| 424 // inline (no need to check the hard constraints). | 419 // inline (no need to check the hard constraints). |
| 425 bool cachedCanBeInlined = | 420 bool cachedCanBeInlined = |
| 426 backend.inlineCache.canInline(function, insideLoop: insideLoop); | 421 backend.inlineCache.canInline(function, insideLoop: insideLoop); |
| 427 if (cachedCanBeInlined == false) return false; | 422 if (cachedCanBeInlined == false) return false; |
| 428 | 423 |
| 429 bool meetsHardConstraints() { | 424 bool meetsHardConstraints() { |
| 430 if (compiler.options.disableInlining) return false; | 425 if (options.disableInlining) return false; |
| 431 | 426 |
| 432 assert(invariant( | 427 assert(invariant( |
| 433 currentNode != null ? currentNode : function, | 428 currentNode != null ? currentNode : function, |
| 434 selector != null || | 429 selector != null || |
| 435 Elements.isStaticOrTopLevel(function) || | 430 Elements.isStaticOrTopLevel(function) || |
| 436 function.isGenerativeConstructorBody, | 431 function.isGenerativeConstructorBody, |
| 437 message: "Missing selector for inlining of $function.")); | 432 message: "Missing selector for inlining of $function.")); |
| 438 if (selector != null) { | 433 if (selector != null) { |
| 439 if (!selector.applies(function)) return false; | 434 if (!selector.applies(function)) return false; |
| 440 if (mask != null && !mask.canHit(function, selector, closedWorld)) { | 435 if (mask != null && !mask.canHit(function, selector, closedWorld)) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 467 return false; | 462 return false; |
| 468 } | 463 } |
| 469 } | 464 } |
| 470 | 465 |
| 471 return true; | 466 return true; |
| 472 } | 467 } |
| 473 | 468 |
| 474 bool doesNotContainCode() { | 469 bool doesNotContainCode() { |
| 475 // A function with size 1 does not contain any code. | 470 // A function with size 1 does not contain any code. |
| 476 return InlineWeeder.canBeInlined(functionResolvedAst, 1, | 471 return InlineWeeder.canBeInlined(functionResolvedAst, 1, |
| 477 enableUserAssertions: compiler.options.enableUserAssertions); | 472 enableUserAssertions: options.enableUserAssertions); |
| 478 } | 473 } |
| 479 | 474 |
| 480 bool reductiveHeuristic() { | 475 bool reductiveHeuristic() { |
| 481 // The call is on a path which is executed rarely, so inline only if it | 476 // The call is on a path which is executed rarely, so inline only if it |
| 482 // does not make the program larger. | 477 // does not make the program larger. |
| 483 if (isCalledOnce(function)) { | 478 if (isCalledOnce(function)) { |
| 484 return InlineWeeder.canBeInlined(functionResolvedAst, null, | 479 return InlineWeeder.canBeInlined(functionResolvedAst, null, |
| 485 enableUserAssertions: compiler.options.enableUserAssertions); | 480 enableUserAssertions: options.enableUserAssertions); |
| 486 } | 481 } |
| 487 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable | 482 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable |
| 488 // case we miss by doing nothing is inlining very simple constructors | 483 // case we miss by doing nothing is inlining very simple constructors |
| 489 // where all fields are initialized with values from the arguments at this | 484 // where all fields are initialized with values from the arguments at this |
| 490 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but | 485 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but |
| 491 // that usually means the factory constructor is left unused and not | 486 // that usually means the factory constructor is left unused and not |
| 492 // emitted. | 487 // emitted. |
| 493 // We at least inline bodies that are empty (and thus have a size of 1). | 488 // We at least inline bodies that are empty (and thus have a size of 1). |
| 494 return doesNotContainCode(); | 489 return doesNotContainCode(); |
| 495 } | 490 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 514 // Do not inline code that is rarely executed unless it reduces size. | 509 // Do not inline code that is rarely executed unless it reduces size. |
| 515 if (inExpressionOfThrow || inLazyInitializerExpression) { | 510 if (inExpressionOfThrow || inLazyInitializerExpression) { |
| 516 return reductiveHeuristic(); | 511 return reductiveHeuristic(); |
| 517 } | 512 } |
| 518 | 513 |
| 519 if (cachedCanBeInlined == true) { | 514 if (cachedCanBeInlined == true) { |
| 520 // We may have forced the inlining of some methods. Therefore check | 515 // We may have forced the inlining of some methods. Therefore check |
| 521 // if we can inline this method regardless of size. | 516 // if we can inline this method regardless of size. |
| 522 assert(InlineWeeder.canBeInlined(functionResolvedAst, null, | 517 assert(InlineWeeder.canBeInlined(functionResolvedAst, null, |
| 523 allowLoops: true, | 518 allowLoops: true, |
| 524 enableUserAssertions: compiler.options.enableUserAssertions)); | 519 enableUserAssertions: options.enableUserAssertions)); |
| 525 return true; | 520 return true; |
| 526 } | 521 } |
| 527 | 522 |
| 528 int numParameters = function.functionSignature.parameterCount; | 523 int numParameters = function.functionSignature.parameterCount; |
| 529 int maxInliningNodes; | 524 int maxInliningNodes; |
| 530 if (insideLoop) { | 525 if (insideLoop) { |
| 531 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + | 526 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + |
| 532 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; | 527 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; |
| 533 } else { | 528 } else { |
| 534 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + | 529 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
| 535 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; | 530 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
| 536 } | 531 } |
| 537 | 532 |
| 538 // If a method is called only once, and all the methods in the | 533 // If a method is called only once, and all the methods in the |
| 539 // inlining stack are called only once as well, we know we will | 534 // inlining stack are called only once as well, we know we will |
| 540 // save on output size by inlining this method. | 535 // save on output size by inlining this method. |
| 541 if (isCalledOnce(function)) { | 536 if (isCalledOnce(function)) { |
| 542 maxInliningNodes = null; | 537 maxInliningNodes = null; |
| 543 } | 538 } |
| 544 bool canInline = InlineWeeder.canBeInlined( | 539 bool canInline = InlineWeeder.canBeInlined( |
| 545 functionResolvedAst, maxInliningNodes, | 540 functionResolvedAst, maxInliningNodes, |
| 546 enableUserAssertions: compiler.options.enableUserAssertions); | 541 enableUserAssertions: options.enableUserAssertions); |
| 547 if (canInline) { | 542 if (canInline) { |
| 548 backend.inlineCache.markAsInlinable(function, insideLoop: insideLoop); | 543 backend.inlineCache.markAsInlinable(function, insideLoop: insideLoop); |
| 549 } else { | 544 } else { |
| 550 backend.inlineCache | 545 backend.inlineCache |
| 551 .markAsNonInlinable(function, insideLoop: insideLoop); | 546 .markAsNonInlinable(function, insideLoop: insideLoop); |
| 552 } | 547 } |
| 553 return canInline; | 548 return canInline; |
| 554 } | 549 } |
| 555 | 550 |
| 556 void doInlining() { | 551 void doInlining() { |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 push(attachPosition(instruction, node)); | 1496 push(attachPosition(instruction, node)); |
| 1502 } | 1497 } |
| 1503 | 1498 |
| 1504 /// Pops the most recent instruction from the stack and 'boolifies' it. | 1499 /// Pops the most recent instruction from the stack and 'boolifies' it. |
| 1505 /// | 1500 /// |
| 1506 /// Boolification is checking if the value is '=== true'. | 1501 /// Boolification is checking if the value is '=== true'. |
| 1507 @override | 1502 @override |
| 1508 HInstruction popBoolified() { | 1503 HInstruction popBoolified() { |
| 1509 HInstruction value = pop(); | 1504 HInstruction value = pop(); |
| 1510 if (typeBuilder.checkOrTrustTypes) { | 1505 if (typeBuilder.checkOrTrustTypes) { |
| 1511 ResolutionInterfaceType boolType = compiler.commonElements.boolType; | 1506 ResolutionInterfaceType boolType = commonElements.boolType; |
| 1512 return typeBuilder.potentiallyCheckOrTrustType(value, boolType, | 1507 return typeBuilder.potentiallyCheckOrTrustType(value, boolType, |
| 1513 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 1508 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
| 1514 } | 1509 } |
| 1515 HInstruction result = new HBoolify(value, commonMasks.boolType); | 1510 HInstruction result = new HBoolify(value, commonMasks.boolType); |
| 1516 add(result); | 1511 add(result); |
| 1517 return result; | 1512 return result; |
| 1518 } | 1513 } |
| 1519 | 1514 |
| 1520 HInstruction attachPosition(HInstruction target, ast.Node node) { | 1515 HInstruction attachPosition(HInstruction target, ast.Node node) { |
| 1521 if (node != null) { | 1516 if (node != null) { |
| 1522 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); | 1517 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); |
| 1523 } | 1518 } |
| 1524 return target; | 1519 return target; |
| 1525 } | 1520 } |
| 1526 | 1521 |
| 1527 void visit(ast.Node node) { | 1522 void visit(ast.Node node) { |
| 1528 if (node != null) node.accept(this); | 1523 if (node != null) node.accept(this); |
| 1529 } | 1524 } |
| 1530 | 1525 |
| 1531 /// Visit [node] and pop the resulting [HInstruction]. | 1526 /// Visit [node] and pop the resulting [HInstruction]. |
| 1532 HInstruction visitAndPop(ast.Node node) { | 1527 HInstruction visitAndPop(ast.Node node) { |
| 1533 node.accept(this); | 1528 node.accept(this); |
| 1534 return pop(); | 1529 return pop(); |
| 1535 } | 1530 } |
| 1536 | 1531 |
| 1537 visitAssert(ast.Assert node) { | 1532 visitAssert(ast.Assert node) { |
| 1538 if (!compiler.options.enableUserAssertions) return; | 1533 if (!options.enableUserAssertions) return; |
| 1539 | 1534 |
| 1540 if (!node.hasMessage) { | 1535 if (!node.hasMessage) { |
| 1541 // Generate: | 1536 // Generate: |
| 1542 // | 1537 // |
| 1543 // assertHelper(condition); | 1538 // assertHelper(condition); |
| 1544 // | 1539 // |
| 1545 visit(node.condition); | 1540 visit(node.condition); |
| 1546 pushInvokeStatic(node, helpers.assertHelper, [pop()]); | 1541 pushInvokeStatic(node, helpers.assertHelper, [pop()]); |
| 1547 pop(); | 1542 pop(); |
| 1548 return; | 1543 return; |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1848 node, "SsaFromAstMixin.visitIdentifier on non-this."); | 1843 node, "SsaFromAstMixin.visitIdentifier on non-this."); |
| 1849 } | 1844 } |
| 1850 } | 1845 } |
| 1851 | 1846 |
| 1852 void handleIf( | 1847 void handleIf( |
| 1853 {ast.Node node, | 1848 {ast.Node node, |
| 1854 void visitCondition(), | 1849 void visitCondition(), |
| 1855 void visitThen(), | 1850 void visitThen(), |
| 1856 void visitElse(), | 1851 void visitElse(), |
| 1857 SourceInformation sourceInformation}) { | 1852 SourceInformation sourceInformation}) { |
| 1858 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node); | 1853 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 1859 branchBuilder.handleIf(visitCondition, visitThen, visitElse, | 1854 branchBuilder.handleIf(visitCondition, visitThen, visitElse, |
| 1860 sourceInformation: sourceInformation); | 1855 sourceInformation: sourceInformation); |
| 1861 } | 1856 } |
| 1862 | 1857 |
| 1863 visitIf(ast.If node) { | 1858 visitIf(ast.If node) { |
| 1864 assert(isReachable); | 1859 assert(isReachable); |
| 1865 handleIf( | 1860 handleIf( |
| 1866 node: node, | 1861 node: node, |
| 1867 visitCondition: () => visit(node.condition), | 1862 visitCondition: () => visit(node.condition), |
| 1868 visitThen: () => visit(node.thenPart), | 1863 visitThen: () => visit(node.thenPart), |
| 1869 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, | 1864 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, |
| 1870 sourceInformation: sourceInformationBuilder.buildIf(node)); | 1865 sourceInformation: sourceInformationBuilder.buildIf(node)); |
| 1871 } | 1866 } |
| 1872 | 1867 |
| 1873 @override | 1868 @override |
| 1874 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { | 1869 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { |
| 1875 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 1870 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 1876 brancher.handleIfNull(() => visit(left), () => visit(right)); | 1871 brancher.handleIfNull(() => visit(left), () => visit(right)); |
| 1877 } | 1872 } |
| 1878 | 1873 |
| 1879 /// Optimizes logical binary where the left is also a logical binary. | 1874 /// Optimizes logical binary where the left is also a logical binary. |
| 1880 /// | 1875 /// |
| 1881 /// This method transforms the operator by optimizing the case where [left] is | 1876 /// This method transforms the operator by optimizing the case where [left] is |
| 1882 /// a logical "and" or logical "or". Then it uses [branchBuilder] to build the | 1877 /// a logical "and" or logical "or". Then it uses [branchBuilder] to build the |
| 1883 /// graph for the optimized expression. | 1878 /// graph for the optimized expression. |
| 1884 /// | 1879 /// |
| 1885 /// For example, `(x && y) && z` is transformed into `x && (y && z)`: | 1880 /// For example, `(x && y) && z` is transformed into `x && (y && z)`: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1910 branchBuilder, | 1905 branchBuilder, |
| 1911 isAnd: isAnd); | 1906 isAnd: isAnd); |
| 1912 } else { | 1907 } else { |
| 1913 branchBuilder.handleLogicalBinary(() => visit(left), visitRight, | 1908 branchBuilder.handleLogicalBinary(() => visit(left), visitRight, |
| 1914 isAnd: isAnd); | 1909 isAnd: isAnd); |
| 1915 } | 1910 } |
| 1916 } | 1911 } |
| 1917 | 1912 |
| 1918 @override | 1913 @override |
| 1919 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { | 1914 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { |
| 1920 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node); | 1915 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 1921 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder, | 1916 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder, |
| 1922 isAnd: true); | 1917 isAnd: true); |
| 1923 } | 1918 } |
| 1924 | 1919 |
| 1925 @override | 1920 @override |
| 1926 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { | 1921 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { |
| 1927 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node); | 1922 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 1928 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder, | 1923 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder, |
| 1929 isAnd: false); | 1924 isAnd: false); |
| 1930 } | 1925 } |
| 1931 | 1926 |
| 1932 @override | 1927 @override |
| 1933 void visitNot(ast.Send node, ast.Node expression, _) { | 1928 void visitNot(ast.Send node, ast.Node expression, _) { |
| 1934 assert(node.argumentsNode is ast.Prefix); | 1929 assert(node.argumentsNode is ast.Prefix); |
| 1935 visit(expression); | 1930 visit(expression); |
| 1936 SourceInformation sourceInformation = | 1931 SourceInformation sourceInformation = |
| 1937 sourceInformationBuilder.buildGeneric(node); | 1932 sourceInformationBuilder.buildGeneric(node); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 @override | 2181 @override |
| 2187 void visitIfNotNullDynamicPropertyGet( | 2182 void visitIfNotNullDynamicPropertyGet( |
| 2188 ast.Send node, ast.Node receiver, Name name, _) { | 2183 ast.Send node, ast.Node receiver, Name name, _) { |
| 2189 // exp?.x compiled as: | 2184 // exp?.x compiled as: |
| 2190 // t1 = exp; | 2185 // t1 = exp; |
| 2191 // result = t1 == null ? t1 : t1.x; | 2186 // result = t1 == null ? t1 : t1.x; |
| 2192 // This is equivalent to t1 == null ? null : t1.x, but in the current form | 2187 // This is equivalent to t1 == null ? null : t1.x, but in the current form |
| 2193 // we will be able to later compress it as: | 2188 // we will be able to later compress it as: |
| 2194 // t1 || t1.x | 2189 // t1 || t1.x |
| 2195 HInstruction expression; | 2190 HInstruction expression; |
| 2196 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 2191 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 2197 brancher.handleConditional( | 2192 brancher.handleConditional( |
| 2198 () { | 2193 () { |
| 2199 expression = visitAndPop(receiver); | 2194 expression = visitAndPop(receiver); |
| 2200 pushCheckNull(expression); | 2195 pushCheckNull(expression); |
| 2201 }, | 2196 }, |
| 2202 () => stack.add(expression), | 2197 () => stack.add(expression), |
| 2203 () { | 2198 () { |
| 2204 generateInstanceGetterWithCompiledReceiver( | 2199 generateInstanceGetterWithCompiledReceiver( |
| 2205 node, | 2200 node, |
| 2206 elements.getSelector(node), | 2201 elements.getSelector(node), |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2545 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver, | 2540 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver, |
| 2546 ast.NodeList arguments, Selector selector, _) { | 2541 ast.NodeList arguments, Selector selector, _) { |
| 2547 generateDynamicSend(node); | 2542 generateDynamicSend(node); |
| 2548 } | 2543 } |
| 2549 | 2544 |
| 2550 @override | 2545 @override |
| 2551 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver, | 2546 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver, |
| 2552 ast.NodeList arguments, Selector selector, _) { | 2547 ast.NodeList arguments, Selector selector, _) { |
| 2553 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()` | 2548 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()` |
| 2554 HInstruction receiver; | 2549 HInstruction receiver; |
| 2555 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 2550 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 2556 brancher.handleConditional(() { | 2551 brancher.handleConditional(() { |
| 2557 receiver = generateInstanceSendReceiver(node); | 2552 receiver = generateInstanceSendReceiver(node); |
| 2558 pushCheckNull(receiver); | 2553 pushCheckNull(receiver); |
| 2559 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver)); | 2554 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver)); |
| 2560 } | 2555 } |
| 2561 | 2556 |
| 2562 @override | 2557 @override |
| 2563 visitThisPropertyInvoke( | 2558 visitThisPropertyInvoke( |
| 2564 ast.Send node, ast.NodeList arguments, Selector selector, _) { | 2559 ast.Send node, ast.NodeList arguments, Selector selector, _) { |
| 2565 generateDynamicSend(node); | 2560 generateDynamicSend(node); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2716 reporter.reportErrorMessage(argument, MessageKind.GENERIC, | 2711 reporter.reportErrorMessage(argument, MessageKind.GENERIC, |
| 2717 {'text': 'Error: Expected a literal string.'}); | 2712 {'text': 'Error: Expected a literal string.'}); |
| 2718 } | 2713 } |
| 2719 String name = string.dartString.slowToString(); | 2714 String name = string.dartString.slowToString(); |
| 2720 bool value = false; | 2715 bool value = false; |
| 2721 switch (name) { | 2716 switch (name) { |
| 2722 case 'MUST_RETAIN_METADATA': | 2717 case 'MUST_RETAIN_METADATA': |
| 2723 value = backend.mirrorsData.mustRetainMetadata; | 2718 value = backend.mirrorsData.mustRetainMetadata; |
| 2724 break; | 2719 break; |
| 2725 case 'USE_CONTENT_SECURITY_POLICY': | 2720 case 'USE_CONTENT_SECURITY_POLICY': |
| 2726 value = compiler.options.useContentSecurityPolicy; | 2721 value = options.useContentSecurityPolicy; |
| 2727 break; | 2722 break; |
| 2728 default: | 2723 default: |
| 2729 reporter.reportErrorMessage(node, MessageKind.GENERIC, | 2724 reporter.reportErrorMessage(node, MessageKind.GENERIC, |
| 2730 {'text': 'Error: Unknown internal flag "$name".'}); | 2725 {'text': 'Error: Unknown internal flag "$name".'}); |
| 2731 } | 2726 } |
| 2732 stack.add(graph.addConstantBool(value, closedWorld)); | 2727 stack.add(graph.addConstantBool(value, closedWorld)); |
| 2733 } | 2728 } |
| 2734 | 2729 |
| 2735 void handleForeignJsGetName(ast.Send node) { | 2730 void handleForeignJsGetName(ast.Send node) { |
| 2736 List<ast.Node> arguments = node.arguments.toList(); | 2731 List<ast.Node> arguments = node.arguments.toList(); |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3496 expectedType.typeArguments.forEach((ResolutionDartType argument) { | 3491 expectedType.typeArguments.forEach((ResolutionDartType argument) { |
| 3497 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement, | 3492 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement, |
| 3498 sourceInformation: sourceInformation)); | 3493 sourceInformation: sourceInformation)); |
| 3499 }); | 3494 }); |
| 3500 } | 3495 } |
| 3501 | 3496 |
| 3502 /// In checked mode checks the [type] of [node] to be well-bounded. The method | 3497 /// In checked mode checks the [type] of [node] to be well-bounded. The method |
| 3503 /// returns [:true:] if an error can be statically determined. | 3498 /// returns [:true:] if an error can be statically determined. |
| 3504 bool checkTypeVariableBounds( | 3499 bool checkTypeVariableBounds( |
| 3505 ast.NewExpression node, ResolutionInterfaceType type) { | 3500 ast.NewExpression node, ResolutionInterfaceType type) { |
| 3506 if (!compiler.options.enableTypeAssertions) return false; | 3501 if (!options.enableTypeAssertions) return false; |
| 3507 | 3502 |
| 3508 Map<ResolutionDartType, Set<ResolutionDartType>> seenChecksMap = | 3503 Map<ResolutionDartType, Set<ResolutionDartType>> seenChecksMap = |
| 3509 new Map<ResolutionDartType, Set<ResolutionDartType>>(); | 3504 new Map<ResolutionDartType, Set<ResolutionDartType>>(); |
| 3510 bool definitelyFails = false; | 3505 bool definitelyFails = false; |
| 3511 | 3506 |
| 3512 void addTypeVariableBoundCheck( | 3507 void addTypeVariableBoundCheck( |
| 3513 GenericType instance, | 3508 GenericType instance, |
| 3514 ResolutionDartType typeArgument, | 3509 ResolutionDartType typeArgument, |
| 3515 ResolutionTypeVariableType typeVariable, | 3510 ResolutionTypeVariableType typeVariable, |
| 3516 ResolutionDartType bound) { | 3511 ResolutionDartType bound) { |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3882 | 3877 |
| 3883 @override | 3878 @override |
| 3884 void bulkHandleNode(ast.Node node, String message, _) { | 3879 void bulkHandleNode(ast.Node node, String message, _) { |
| 3885 internalError(node, "Unexpected bulk handled node: $node"); | 3880 internalError(node, "Unexpected bulk handled node: $node"); |
| 3886 } | 3881 } |
| 3887 | 3882 |
| 3888 @override | 3883 @override |
| 3889 void bulkHandleNew(ast.NewExpression node, [_]) { | 3884 void bulkHandleNew(ast.NewExpression node, [_]) { |
| 3890 Element element = elements[node.send]; | 3885 Element element = elements[node.send]; |
| 3891 final bool isSymbolConstructor = | 3886 final bool isSymbolConstructor = |
| 3892 element == compiler.commonElements.symbolConstructor; | 3887 element == commonElements.symbolConstructor; |
| 3893 if (!Elements.isMalformed(element)) { | 3888 if (!Elements.isMalformed(element)) { |
| 3894 ConstructorElement function = element; | 3889 ConstructorElement function = element; |
| 3895 element = function.effectiveTarget; | 3890 element = function.effectiveTarget; |
| 3896 } | 3891 } |
| 3897 if (Elements.isError(element)) { | 3892 if (Elements.isError(element)) { |
| 3898 ErroneousElement error = element; | 3893 ErroneousElement error = element; |
| 3899 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR || | 3894 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR || |
| 3900 error.messageKind == MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR) { | 3895 error.messageKind == MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR) { |
| 3901 generateThrowNoSuchMethod( | 3896 generateThrowNoSuchMethod( |
| 3902 node.send, noSuchMethodTargetSymbolString(error, 'constructor'), | 3897 node.send, noSuchMethodTargetSymbolString(error, 'constructor'), |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4030 backend.nativeData.computeUnescapedJSInteropName(parameter.name); | 4025 backend.nativeData.computeUnescapedJSInteropName(parameter.name); |
| 4031 parameterNameMap[jsName] = new js.InterpolatedExpression(positions++); | 4026 parameterNameMap[jsName] = new js.InterpolatedExpression(positions++); |
| 4032 } | 4027 } |
| 4033 i++; | 4028 i++; |
| 4034 }); | 4029 }); |
| 4035 var codeTemplate = | 4030 var codeTemplate = |
| 4036 new js.Template(null, js.objectLiteral(parameterNameMap)); | 4031 new js.Template(null, js.objectLiteral(parameterNameMap)); |
| 4037 | 4032 |
| 4038 var nativeBehavior = new native.NativeBehavior() | 4033 var nativeBehavior = new native.NativeBehavior() |
| 4039 ..codeTemplate = codeTemplate; | 4034 ..codeTemplate = codeTemplate; |
| 4040 if (compiler.options.trustJSInteropTypeAnnotations) { | 4035 if (options.trustJSInteropTypeAnnotations) { |
| 4041 nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType); | 4036 nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType); |
| 4042 } | 4037 } |
| 4043 return new HForeignCode( | 4038 return new HForeignCode( |
| 4044 codeTemplate, commonMasks.dynamicType, filteredArguments, | 4039 codeTemplate, commonMasks.dynamicType, filteredArguments, |
| 4045 nativeBehavior: nativeBehavior) | 4040 nativeBehavior: nativeBehavior) |
| 4046 ..sourceInformation = sourceInformation; | 4041 ..sourceInformation = sourceInformation; |
| 4047 } | 4042 } |
| 4048 var target = new HForeignCode( | 4043 var target = new HForeignCode( |
| 4049 js.js.parseForeignJS( | 4044 js.js.parseForeignJS( |
| 4050 "${backend.nativeData.getFixedBackendMethodPath(element)}." | 4045 "${backend.nativeData.getFixedBackendMethodPath(element)}." |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4061 | 4056 |
| 4062 var nativeBehavior = new native.NativeBehavior() | 4057 var nativeBehavior = new native.NativeBehavior() |
| 4063 ..sideEffects.setAllSideEffects(); | 4058 ..sideEffects.setAllSideEffects(); |
| 4064 | 4059 |
| 4065 ResolutionDartType type = element.isConstructor | 4060 ResolutionDartType type = element.isConstructor |
| 4066 ? element.enclosingClass.thisType | 4061 ? element.enclosingClass.thisType |
| 4067 : element.type.returnType; | 4062 : element.type.returnType; |
| 4068 // Native behavior effects here are similar to native/behavior.dart. | 4063 // Native behavior effects here are similar to native/behavior.dart. |
| 4069 // The return type is dynamic if we don't trust js-interop type | 4064 // The return type is dynamic if we don't trust js-interop type |
| 4070 // declarations. | 4065 // declarations. |
| 4071 nativeBehavior.typesReturned.add( | 4066 nativeBehavior.typesReturned.add(options.trustJSInteropTypeAnnotations |
| 4072 compiler.options.trustJSInteropTypeAnnotations | 4067 ? type |
| 4073 ? type | 4068 : const ResolutionDynamicType()); |
| 4074 : const ResolutionDynamicType()); | |
| 4075 | 4069 |
| 4076 // The allocation effects include the declared type if it is native (which | 4070 // The allocation effects include the declared type if it is native (which |
| 4077 // includes js interop types). | 4071 // includes js interop types). |
| 4078 if (type is ResolutionInterfaceType && | 4072 if (type is ResolutionInterfaceType && |
| 4079 backend.nativeData.isNativeClass(type.element)) { | 4073 backend.nativeData.isNativeClass(type.element)) { |
| 4080 nativeBehavior.typesInstantiated.add(type); | 4074 nativeBehavior.typesInstantiated.add(type); |
| 4081 } | 4075 } |
| 4082 | 4076 |
| 4083 // It also includes any other JS interop type if we don't trust the | 4077 // It also includes any other JS interop type if we don't trust the |
| 4084 // annotation or if is declared too broad. | 4078 // annotation or if is declared too broad. |
| 4085 if (!compiler.options.trustJSInteropTypeAnnotations || | 4079 if (!options.trustJSInteropTypeAnnotations || |
| 4086 type.isObject || | 4080 type.isObject || |
| 4087 type.isDynamic) { | 4081 type.isDynamic) { |
| 4088 ClassElement cls = backend.helpers.jsJavaScriptObjectClass; | 4082 ClassElement cls = backend.helpers.jsJavaScriptObjectClass; |
| 4089 nativeBehavior.typesInstantiated.add(cls.thisType); | 4083 nativeBehavior.typesInstantiated.add(cls.thisType); |
| 4090 } | 4084 } |
| 4091 | 4085 |
| 4092 String code; | 4086 String code; |
| 4093 if (element.isGetter) { | 4087 if (element.isGetter) { |
| 4094 code = "#"; | 4088 code = "#"; |
| 4095 } else if (element.isSetter) { | 4089 } else if (element.isSetter) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4236 if (Elements.isUnresolved(getter)) { | 4230 if (Elements.isUnresolved(getter)) { |
| 4237 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs); | 4231 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs); |
| 4238 getterInstruction = pop(); | 4232 getterInstruction = pop(); |
| 4239 } else { | 4233 } else { |
| 4240 getterInstruction = | 4234 getterInstruction = |
| 4241 buildInvokeSuper(getterSelector, getter, getterInputs); | 4235 buildInvokeSuper(getterSelector, getter, getterInputs); |
| 4242 add(getterInstruction); | 4236 add(getterInstruction); |
| 4243 } | 4237 } |
| 4244 | 4238 |
| 4245 if (node.isIfNullAssignment) { | 4239 if (node.isIfNullAssignment) { |
| 4246 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 4240 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 4247 brancher.handleIfNull(() => stack.add(getterInstruction), () { | 4241 brancher.handleIfNull(() => stack.add(getterInstruction), () { |
| 4248 addDynamicSendArgumentsToList(node, setterInputs); | 4242 addDynamicSendArgumentsToList(node, setterInputs); |
| 4249 generateSuperSendSet(); | 4243 generateSuperSendSet(); |
| 4250 stack.add(setterInputs.last); | 4244 stack.add(setterInputs.last); |
| 4251 }); | 4245 }); |
| 4252 } else { | 4246 } else { |
| 4253 handleComplexOperatorSend(node, getterInstruction, arguments); | 4247 handleComplexOperatorSend(node, getterInstruction, arguments); |
| 4254 setterInputs.add(pop()); | 4248 setterInputs.add(pop()); |
| 4255 generateSuperSendSet(); | 4249 generateSuperSendSet(); |
| 4256 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); | 4250 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4556 | 4550 |
| 4557 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node), | 4551 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node), |
| 4558 elementInferenceResults.typeOfGetter(node), [receiver, index]); | 4552 elementInferenceResults.typeOfGetter(node), [receiver, index]); |
| 4559 HInstruction getterInstruction = pop(); | 4553 HInstruction getterInstruction = pop(); |
| 4560 if (node.isIfNullAssignment) { | 4554 if (node.isIfNullAssignment) { |
| 4561 // Compile x[i] ??= e as: | 4555 // Compile x[i] ??= e as: |
| 4562 // t1 = x[i] | 4556 // t1 = x[i] |
| 4563 // if (t1 == null) | 4557 // if (t1 == null) |
| 4564 // t1 = x[i] = e; | 4558 // t1 = x[i] = e; |
| 4565 // result = t1 | 4559 // result = t1 |
| 4566 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 4560 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 4567 brancher.handleIfNull(() => stack.add(getterInstruction), () { | 4561 brancher.handleIfNull(() => stack.add(getterInstruction), () { |
| 4568 visit(arguments.head); | 4562 visit(arguments.head); |
| 4569 HInstruction value = pop(); | 4563 HInstruction value = pop(); |
| 4570 pushInvokeDynamic( | 4564 pushInvokeDynamic( |
| 4571 node, | 4565 node, |
| 4572 elements.getSelector(node), | 4566 elements.getSelector(node), |
| 4573 elementInferenceResults.typeOfSend(node), | 4567 elementInferenceResults.typeOfSend(node), |
| 4574 [receiver, index, value]); | 4568 [receiver, index, value]); |
| 4575 pop(); | 4569 pop(); |
| 4576 stack.add(value); | 4570 stack.add(value); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4607 void visitIfNotNullDynamicPropertySet( | 4601 void visitIfNotNullDynamicPropertySet( |
| 4608 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) { | 4602 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) { |
| 4609 // compile e?.x = e2 to: | 4603 // compile e?.x = e2 to: |
| 4610 // | 4604 // |
| 4611 // t1 = e | 4605 // t1 = e |
| 4612 // if (t1 == null) | 4606 // if (t1 == null) |
| 4613 // result = t1 // same as result = null | 4607 // result = t1 // same as result = null |
| 4614 // else | 4608 // else |
| 4615 // result = e.x = e2 | 4609 // result = e.x = e2 |
| 4616 HInstruction receiverInstruction; | 4610 HInstruction receiverInstruction; |
| 4617 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 4611 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 4618 brancher.handleConditional( | 4612 brancher.handleConditional( |
| 4619 () { | 4613 () { |
| 4620 receiverInstruction = generateInstanceSendReceiver(node); | 4614 receiverInstruction = generateInstanceSendReceiver(node); |
| 4621 pushCheckNull(receiverInstruction); | 4615 pushCheckNull(receiverInstruction); |
| 4622 }, | 4616 }, |
| 4623 () => stack.add(receiverInstruction), | 4617 () => stack.add(receiverInstruction), |
| 4624 () { | 4618 () { |
| 4625 generateInstanceSetterWithCompiledReceiver( | 4619 generateInstanceSetterWithCompiledReceiver( |
| 4626 node, receiverInstruction, visitAndPop(rhs)); | 4620 node, receiverInstruction, visitAndPop(rhs)); |
| 4627 }); | 4621 }); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4780 if (Elements.isInstanceSend(node, elements)) { | 4774 if (Elements.isInstanceSend(node, elements)) { |
| 4781 void generateAssignment(HInstruction receiver) { | 4775 void generateAssignment(HInstruction receiver) { |
| 4782 // desugars `e.x op= e2` to `e.x = e.x op e2` | 4776 // desugars `e.x op= e2` to `e.x = e.x op e2` |
| 4783 generateInstanceGetterWithCompiledReceiver( | 4777 generateInstanceGetterWithCompiledReceiver( |
| 4784 node, | 4778 node, |
| 4785 elements.getGetterSelectorInComplexSendSet(node), | 4779 elements.getGetterSelectorInComplexSendSet(node), |
| 4786 elementInferenceResults.typeOfGetter(node), | 4780 elementInferenceResults.typeOfGetter(node), |
| 4787 receiver); | 4781 receiver); |
| 4788 HInstruction getterInstruction = pop(); | 4782 HInstruction getterInstruction = pop(); |
| 4789 if (node.isIfNullAssignment) { | 4783 if (node.isIfNullAssignment) { |
| 4790 SsaBranchBuilder brancher = | 4784 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 4791 new SsaBranchBuilder(this, compiler, node); | |
| 4792 brancher.handleIfNull(() => stack.add(getterInstruction), () { | 4785 brancher.handleIfNull(() => stack.add(getterInstruction), () { |
| 4793 visit(node.arguments.head); | 4786 visit(node.arguments.head); |
| 4794 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); | 4787 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); |
| 4795 }); | 4788 }); |
| 4796 } else { | 4789 } else { |
| 4797 handleComplexOperatorSend(node, getterInstruction, node.arguments); | 4790 handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| 4798 HInstruction value = pop(); | 4791 HInstruction value = pop(); |
| 4799 generateInstanceSetterWithCompiledReceiver(node, receiver, value); | 4792 generateInstanceSetterWithCompiledReceiver(node, receiver, value); |
| 4800 } | 4793 } |
| 4801 if (node.isPostfix) { | 4794 if (node.isPostfix) { |
| 4802 pop(); | 4795 pop(); |
| 4803 stack.add(getterInstruction); | 4796 stack.add(getterInstruction); |
| 4804 } | 4797 } |
| 4805 } | 4798 } |
| 4806 | 4799 |
| 4807 if (node.isConditional) { | 4800 if (node.isConditional) { |
| 4808 // generate `e?.x op= e2` as: | 4801 // generate `e?.x op= e2` as: |
| 4809 // t1 = e | 4802 // t1 = e |
| 4810 // t1 == null ? t1 : (t1.x = t1.x op e2); | 4803 // t1 == null ? t1 : (t1.x = t1.x op e2); |
| 4811 HInstruction receiver; | 4804 HInstruction receiver; |
| 4812 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 4805 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 4813 brancher.handleConditional(() { | 4806 brancher.handleConditional(() { |
| 4814 receiver = generateInstanceSendReceiver(node); | 4807 receiver = generateInstanceSendReceiver(node); |
| 4815 pushCheckNull(receiver); | 4808 pushCheckNull(receiver); |
| 4816 }, () => stack.add(receiver), () => generateAssignment(receiver)); | 4809 }, () => stack.add(receiver), () => generateAssignment(receiver)); |
| 4817 } else { | 4810 } else { |
| 4818 generateAssignment(generateInstanceSendReceiver(node)); | 4811 generateAssignment(generateInstanceSendReceiver(node)); |
| 4819 } | 4812 } |
| 4820 return; | 4813 return; |
| 4821 } | 4814 } |
| 4822 | 4815 |
| 4823 if (getter.isMalformed) { | 4816 if (getter.isMalformed) { |
| 4824 generateStaticUnresolvedGet(node, getter); | 4817 generateStaticUnresolvedGet(node, getter); |
| 4825 } else if (getter.isField) { | 4818 } else if (getter.isField) { |
| 4826 generateStaticFieldGet(node, getter); | 4819 generateStaticFieldGet(node, getter); |
| 4827 } else if (getter.isGetter) { | 4820 } else if (getter.isGetter) { |
| 4828 generateStaticGetterGet(node, getter); | 4821 generateStaticGetterGet(node, getter); |
| 4829 } else if (getter.isFunction) { | 4822 } else if (getter.isFunction) { |
| 4830 generateStaticFunctionGet(node, getter); | 4823 generateStaticFunctionGet(node, getter); |
| 4831 } else if (getter.isLocal) { | 4824 } else if (getter.isLocal) { |
| 4832 handleLocalGet(node, getter); | 4825 handleLocalGet(node, getter); |
| 4833 } else { | 4826 } else { |
| 4834 internalError(node, "Unexpected getter: $getter"); | 4827 internalError(node, "Unexpected getter: $getter"); |
| 4835 } | 4828 } |
| 4836 HInstruction getterInstruction = pop(); | 4829 HInstruction getterInstruction = pop(); |
| 4837 if (node.isIfNullAssignment) { | 4830 if (node.isIfNullAssignment) { |
| 4838 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 4831 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 4839 brancher.handleIfNull(() => stack.add(getterInstruction), () { | 4832 brancher.handleIfNull(() => stack.add(getterInstruction), () { |
| 4840 visit(node.arguments.head); | 4833 visit(node.arguments.head); |
| 4841 generateNonInstanceSetter(node, element, pop()); | 4834 generateNonInstanceSetter(node, element, pop()); |
| 4842 }); | 4835 }); |
| 4843 } else { | 4836 } else { |
| 4844 handleComplexOperatorSend(node, getterInstruction, node.arguments); | 4837 handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| 4845 HInstruction value = pop(); | 4838 HInstruction value = pop(); |
| 4846 generateNonInstanceSetter(node, element, value); | 4839 generateNonInstanceSetter(node, element, value); |
| 4847 } | 4840 } |
| 4848 if (node.isPostfix) { | 4841 if (node.isPostfix) { |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5127 native.handleSsaNative(this, node.expression); | 5120 native.handleSsaNative(this, node.expression); |
| 5128 return; | 5121 return; |
| 5129 } | 5122 } |
| 5130 HInstruction value; | 5123 HInstruction value; |
| 5131 if (node.expression == null) { | 5124 if (node.expression == null) { |
| 5132 value = graph.addConstantNull(closedWorld); | 5125 value = graph.addConstantNull(closedWorld); |
| 5133 } else { | 5126 } else { |
| 5134 visit(node.expression); | 5127 visit(node.expression); |
| 5135 value = pop(); | 5128 value = pop(); |
| 5136 if (isBuildingAsyncFunction) { | 5129 if (isBuildingAsyncFunction) { |
| 5137 if (compiler.options.enableTypeAssertions && | 5130 if (options.enableTypeAssertions && |
| 5138 !isValidAsyncReturnType(returnType)) { | 5131 !isValidAsyncReturnType(returnType)) { |
| 5139 String message = "Async function returned a Future, " | 5132 String message = "Async function returned a Future, " |
| 5140 "was declared to return a $returnType."; | 5133 "was declared to return a $returnType."; |
| 5141 generateTypeError(node, message); | 5134 generateTypeError(node, message); |
| 5142 pop(); | 5135 pop(); |
| 5143 return; | 5136 return; |
| 5144 } | 5137 } |
| 5145 } else { | 5138 } else { |
| 5146 value = typeBuilder.potentiallyCheckOrTrustType(value, returnType); | 5139 value = typeBuilder.potentiallyCheckOrTrustType(value, returnType); |
| 5147 } | 5140 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5239 } | 5232 } |
| 5240 | 5233 |
| 5241 _inferredTypeOfNewList(ast.Send node) => | 5234 _inferredTypeOfNewList(ast.Send node) => |
| 5242 _resultOf(sourceElement).typeOfNewList(node) ?? commonMasks.dynamicType; | 5235 _resultOf(sourceElement).typeOfNewList(node) ?? commonMasks.dynamicType; |
| 5243 | 5236 |
| 5244 _inferredTypeOfListLiteral(ast.LiteralList node) => | 5237 _inferredTypeOfListLiteral(ast.LiteralList node) => |
| 5245 _resultOf(sourceElement).typeOfListLiteral(node) ?? | 5238 _resultOf(sourceElement).typeOfListLiteral(node) ?? |
| 5246 commonMasks.dynamicType; | 5239 commonMasks.dynamicType; |
| 5247 | 5240 |
| 5248 visitConditional(ast.Conditional node) { | 5241 visitConditional(ast.Conditional node) { |
| 5249 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 5242 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 5250 brancher.handleConditional(() => visit(node.condition), | 5243 brancher.handleConditional(() => visit(node.condition), |
| 5251 () => visit(node.thenExpression), () => visit(node.elseExpression)); | 5244 () => visit(node.thenExpression), () => visit(node.elseExpression)); |
| 5252 } | 5245 } |
| 5253 | 5246 |
| 5254 visitStringInterpolation(ast.StringInterpolation node) { | 5247 visitStringInterpolation(ast.StringInterpolation node) { |
| 5255 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 5248 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
| 5256 stringBuilder.visit(node); | 5249 stringBuilder.visit(node); |
| 5257 stack.add(stringBuilder.result); | 5250 stack.add(stringBuilder.result); |
| 5258 } | 5251 } |
| 5259 | 5252 |
| 5260 visitStringInterpolationPart(ast.StringInterpolationPart node) { | 5253 visitStringInterpolationPart(ast.StringInterpolationPart node) { |
| 5261 // The parts are iterated in visitStringInterpolation. | 5254 // The parts are iterated in visitStringInterpolation. |
| 5262 reporter.internalError( | 5255 reporter.internalError( |
| 5263 node, 'SsaBuilder.visitStringInterpolation should not be called.'); | 5256 node, 'SsaBuilder.visitStringInterpolation should not be called.'); |
| 5264 } | 5257 } |
| 5265 | 5258 |
| 5266 visitEmptyStatement(ast.EmptyStatement node) { | 5259 visitEmptyStatement(ast.EmptyStatement node) { |
| 5267 // Do nothing, empty statement. | 5260 // Do nothing, empty statement. |
| 5268 } | 5261 } |
| 5269 | 5262 |
| 5270 visitModifiers(ast.Modifiers node) { | 5263 visitModifiers(ast.Modifiers node) { |
| 5271 compiler.unimplemented(node, 'SsaFromAstMixin.visitModifiers.'); | 5264 throw new SpannableAssertionFailure( |
| 5265 node, 'SsaFromAstMixin.visitModifiers not implemented.'); |
| 5272 } | 5266 } |
| 5273 | 5267 |
| 5274 visitBreakStatement(ast.BreakStatement node) { | 5268 visitBreakStatement(ast.BreakStatement node) { |
| 5275 assert(!isAborted()); | 5269 assert(!isAborted()); |
| 5276 handleInTryStatement(); | 5270 handleInTryStatement(); |
| 5277 JumpTarget target = elements.getTargetOf(node); | 5271 JumpTarget target = elements.getTargetOf(node); |
| 5278 assert(target != null); | 5272 assert(target != null); |
| 5279 JumpHandler handler = jumpTargets[target]; | 5273 JumpHandler handler = jumpTargets[target]; |
| 5280 assert(handler != null); | 5274 assert(handler != null); |
| 5281 if (node.target == null) { | 5275 if (node.target == null) { |
| (...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6363 wrapStatementGraph(catchGraph), wrapStatementGraph(finallyGraph)), | 6357 wrapStatementGraph(catchGraph), wrapStatementGraph(finallyGraph)), |
| 6364 exitBlock); | 6358 exitBlock); |
| 6365 inTryStatement = oldInTryStatement; | 6359 inTryStatement = oldInTryStatement; |
| 6366 } | 6360 } |
| 6367 | 6361 |
| 6368 visitCatchBlock(ast.CatchBlock node) { | 6362 visitCatchBlock(ast.CatchBlock node) { |
| 6369 visit(node.block); | 6363 visit(node.block); |
| 6370 } | 6364 } |
| 6371 | 6365 |
| 6372 visitTypedef(ast.Typedef node) { | 6366 visitTypedef(ast.Typedef node) { |
| 6373 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); | 6367 throw new SpannableAssertionFailure( |
| 6368 node, 'SsaFromAstMixin.visitTypedef not implemented.'); |
| 6374 } | 6369 } |
| 6375 | 6370 |
| 6376 visitTypeVariable(ast.TypeVariable node) { | 6371 visitTypeVariable(ast.TypeVariable node) { |
| 6377 reporter.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); | 6372 throw new SpannableAssertionFailure( |
| 6373 node, 'SsaFromAstMixin.visitTypeVariable not implemented.'); |
| 6378 } | 6374 } |
| 6379 | 6375 |
| 6380 /** | 6376 /** |
| 6381 * This method is invoked before inlining the body of [function] into this | 6377 * This method is invoked before inlining the body of [function] into this |
| 6382 * [SsaBuilder]. | 6378 * [SsaBuilder]. |
| 6383 */ | 6379 */ |
| 6384 void enterInlinedMethod(MethodElement function, | 6380 void enterInlinedMethod(MethodElement function, |
| 6385 ResolvedAst functionResolvedAst, List<HInstruction> compiledArguments, | 6381 ResolvedAst functionResolvedAst, List<HInstruction> compiledArguments, |
| 6386 {ResolutionInterfaceType instanceType}) { | 6382 {ResolutionInterfaceType instanceType}) { |
| 6387 AstInliningState state = new AstInliningState( | 6383 AstInliningState state = new AstInliningState( |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6483 final SsaBuilder builder; | 6479 final SsaBuilder builder; |
| 6484 final ast.Node diagnosticNode; | 6480 final ast.Node diagnosticNode; |
| 6485 | 6481 |
| 6486 /** | 6482 /** |
| 6487 * The string value generated so far. | 6483 * The string value generated so far. |
| 6488 */ | 6484 */ |
| 6489 HInstruction result = null; | 6485 HInstruction result = null; |
| 6490 | 6486 |
| 6491 StringBuilderVisitor(this.builder, this.diagnosticNode); | 6487 StringBuilderVisitor(this.builder, this.diagnosticNode); |
| 6492 | 6488 |
| 6493 Compiler get compiler => builder.compiler; | |
| 6494 | |
| 6495 void visit(ast.Node node) { | 6489 void visit(ast.Node node) { |
| 6496 node.accept(this); | 6490 node.accept(this); |
| 6497 } | 6491 } |
| 6498 | 6492 |
| 6499 visitNode(ast.Node node) { | 6493 visitNode(ast.Node node) { |
| 6500 builder.reporter.internalError(node, 'Unexpected node.'); | 6494 builder.reporter.internalError(node, 'Unexpected node.'); |
| 6501 } | 6495 } |
| 6502 | 6496 |
| 6503 void visitExpression(ast.Node node) { | 6497 void visitExpression(ast.Node node) { |
| 6504 node.accept(builder); | 6498 node.accept(builder); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6760 this.oldReturnLocal, | 6754 this.oldReturnLocal, |
| 6761 this.oldReturnType, | 6755 this.oldReturnType, |
| 6762 this.oldResolvedAst, | 6756 this.oldResolvedAst, |
| 6763 this.oldStack, | 6757 this.oldStack, |
| 6764 this.oldLocalsHandler, | 6758 this.oldLocalsHandler, |
| 6765 this.inTryStatement, | 6759 this.inTryStatement, |
| 6766 this.allFunctionsCalledOnce, | 6760 this.allFunctionsCalledOnce, |
| 6767 this.oldElementInferenceResults) | 6761 this.oldElementInferenceResults) |
| 6768 : super(function); | 6762 : super(function); |
| 6769 } | 6763 } |
| OLD | NEW |