| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 final SsaCodeGeneratorTask generator; | 8 final SsaCodeGeneratorTask generator; |
| 9 final SsaBuilderTask builder; | 9 final SsaBuilderTask builder; |
| 10 final SsaOptimizerTask optimizer; | 10 final SsaOptimizerTask optimizer; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 final JavaScriptBackend backend; | 53 final JavaScriptBackend backend; |
| 54 final SourceInformationStrategy sourceInformationFactory; | 54 final SourceInformationStrategy sourceInformationFactory; |
| 55 | 55 |
| 56 String get name => 'SSA builder'; | 56 String get name => 'SSA builder'; |
| 57 | 57 |
| 58 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) | 58 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) |
| 59 : emitter = backend.emitter, | 59 : emitter = backend.emitter, |
| 60 backend = backend, | 60 backend = backend, |
| 61 super(backend.compiler); | 61 super(backend.compiler); |
| 62 | 62 |
| 63 DiagnosticReporter get reporter => compiler.reporter; |
| 64 |
| 63 HGraph build(CodegenWorkItem work) { | 65 HGraph build(CodegenWorkItem work) { |
| 64 return measure(() { | 66 return measure(() { |
| 65 Element element = work.element.implementation; | 67 Element element = work.element.implementation; |
| 66 return compiler.withCurrentElement(element, () { | 68 return reporter.withCurrentElement(element, () { |
| 67 HInstruction.idCounter = 0; | 69 HInstruction.idCounter = 0; |
| 68 SsaBuilder builder = | 70 SsaBuilder builder = |
| 69 new SsaBuilder( | 71 new SsaBuilder( |
| 70 backend, work, emitter.nativeEmitter, | 72 backend, work, emitter.nativeEmitter, |
| 71 sourceInformationFactory); | 73 sourceInformationFactory); |
| 72 HGraph graph; | 74 HGraph graph; |
| 73 ElementKind kind = element.kind; | 75 ElementKind kind = element.kind; |
| 74 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 76 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 75 graph = compileConstructor(builder, work); | 77 graph = compileConstructor(builder, work); |
| 76 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 78 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 77 kind == ElementKind.FUNCTION || | 79 kind == ElementKind.FUNCTION || |
| 78 kind == ElementKind.GETTER || | 80 kind == ElementKind.GETTER || |
| 79 kind == ElementKind.SETTER) { | 81 kind == ElementKind.SETTER) { |
| 80 graph = builder.buildMethod(element); | 82 graph = builder.buildMethod(element); |
| 81 } else if (kind == ElementKind.FIELD) { | 83 } else if (kind == ElementKind.FIELD) { |
| 82 if (element.isInstanceMember) { | 84 if (element.isInstanceMember) { |
| 83 assert(compiler.enableTypeAssertions); | 85 assert(compiler.enableTypeAssertions); |
| 84 graph = builder.buildCheckedSetter(element); | 86 graph = builder.buildCheckedSetter(element); |
| 85 } else { | 87 } else { |
| 86 graph = builder.buildLazyInitializer(element); | 88 graph = builder.buildLazyInitializer(element); |
| 87 } | 89 } |
| 88 } else { | 90 } else { |
| 89 compiler.internalError(element, 'Unexpected element kind $kind.'); | 91 reporter.internalError(element, 'Unexpected element kind $kind.'); |
| 90 } | 92 } |
| 91 assert(graph.isValid()); | 93 assert(graph.isValid()); |
| 92 if (!identical(kind, ElementKind.FIELD)) { | 94 if (!identical(kind, ElementKind.FIELD)) { |
| 93 FunctionElement function = element; | 95 FunctionElement function = element; |
| 94 FunctionSignature signature = function.functionSignature; | 96 FunctionSignature signature = function.functionSignature; |
| 95 signature.forEachOptionalParameter((ParameterElement parameter) { | 97 signature.forEachOptionalParameter((ParameterElement parameter) { |
| 96 // This ensures the default value will be computed. | 98 // This ensures the default value will be computed. |
| 97 ConstantValue constant = | 99 ConstantValue constant = |
| 98 backend.constants.getConstantValueForVariable(parameter); | 100 backend.constants.getConstantValueForVariable(parameter); |
| 99 CodegenRegistry registry = work.registry; | 101 CodegenRegistry registry = work.registry; |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 /** | 434 /** |
| 433 * Returns an [HInstruction] for the given element. If the element is | 435 * Returns an [HInstruction] for the given element. If the element is |
| 434 * boxed or stored in a closure then the method generates code to retrieve | 436 * boxed or stored in a closure then the method generates code to retrieve |
| 435 * the value. | 437 * the value. |
| 436 */ | 438 */ |
| 437 HInstruction readLocal(Local local, | 439 HInstruction readLocal(Local local, |
| 438 {SourceInformation sourceInformation}) { | 440 {SourceInformation sourceInformation}) { |
| 439 if (isAccessedDirectly(local)) { | 441 if (isAccessedDirectly(local)) { |
| 440 if (directLocals[local] == null) { | 442 if (directLocals[local] == null) { |
| 441 if (local is TypeVariableElement) { | 443 if (local is TypeVariableElement) { |
| 442 builder.compiler.internalError(builder.compiler.currentElement, | 444 builder.reporter.internalError(builder.compiler.currentElement, |
| 443 "Runtime type information not available for $local."); | 445 "Runtime type information not available for $local."); |
| 444 } else { | 446 } else { |
| 445 builder.compiler.internalError(local, | 447 builder.reporter.internalError(local, |
| 446 "Cannot find value $local."); | 448 "Cannot find value $local."); |
| 447 } | 449 } |
| 448 } | 450 } |
| 449 HInstruction value = directLocals[local]; | 451 HInstruction value = directLocals[local]; |
| 450 if (sourceInformation != null) { | 452 if (sourceInformation != null) { |
| 451 value = new HRef(value, sourceInformation); | 453 value = new HRef(value, sourceInformation); |
| 452 builder.add(value); | 454 builder.add(value); |
| 453 } | 455 } |
| 454 return value; | 456 return value; |
| 455 } else if (isStoredInClosureField(local)) { | 457 } else if (isStoredInClosureField(local)) { |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 bool hasAnyBreak(); | 787 bool hasAnyBreak(); |
| 786 void close(); | 788 void close(); |
| 787 final JumpTarget target; | 789 final JumpTarget target; |
| 788 List<LabelDefinition> labels(); | 790 List<LabelDefinition> labels(); |
| 789 } | 791 } |
| 790 | 792 |
| 791 // Insert break handler used to avoid null checks when a target isn't | 793 // Insert break handler used to avoid null checks when a target isn't |
| 792 // used as the target of a break, and therefore doesn't need a break | 794 // used as the target of a break, and therefore doesn't need a break |
| 793 // handler associated with it. | 795 // handler associated with it. |
| 794 class NullJumpHandler implements JumpHandler { | 796 class NullJumpHandler implements JumpHandler { |
| 795 final Compiler compiler; | 797 final DiagnosticReporter reporter; |
| 796 | 798 |
| 797 NullJumpHandler(this.compiler); | 799 NullJumpHandler(this.reporter); |
| 798 | 800 |
| 799 void generateBreak([LabelDefinition label]) { | 801 void generateBreak([LabelDefinition label]) { |
| 800 compiler.internalError(CURRENT_ELEMENT_SPANNABLE, | 802 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
| 801 'NullJumpHandler.generateBreak should not be called.'); | 803 'NullJumpHandler.generateBreak should not be called.'); |
| 802 } | 804 } |
| 803 | 805 |
| 804 void generateContinue([LabelDefinition label]) { | 806 void generateContinue([LabelDefinition label]) { |
| 805 compiler.internalError(CURRENT_ELEMENT_SPANNABLE, | 807 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
| 806 'NullJumpHandler.generateContinue should not be called.'); | 808 'NullJumpHandler.generateContinue should not be called.'); |
| 807 } | 809 } |
| 808 | 810 |
| 809 void forEachBreak(Function ignored) { } | 811 void forEachBreak(Function ignored) { } |
| 810 void forEachContinue(Function ignored) { } | 812 void forEachContinue(Function ignored) { } |
| 811 void close() { } | 813 void close() { } |
| 812 bool hasAnyContinue() => false; | 814 bool hasAnyContinue() => false; |
| 813 bool hasAnyBreak() => false; | 815 bool hasAnyBreak() => false; |
| 814 | 816 |
| 815 List<LabelDefinition> labels() => const <LabelDefinition>[]; | 817 List<LabelDefinition> labels() => const <LabelDefinition>[]; |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1098 this.rti = backend.rti, | 1100 this.rti = backend.rti, |
| 1099 this.elements = work.resolutionTree { | 1101 this.elements = work.resolutionTree { |
| 1100 graph.element = work.element; | 1102 graph.element = work.element; |
| 1101 localsHandler = new LocalsHandler(this, work.element, null); | 1103 localsHandler = new LocalsHandler(this, work.element, null); |
| 1102 sourceElementStack.add(work.element); | 1104 sourceElementStack.add(work.element); |
| 1103 sourceInformationBuilder = | 1105 sourceInformationBuilder = |
| 1104 sourceInformationFactory.createBuilderForContext( | 1106 sourceInformationFactory.createBuilderForContext( |
| 1105 work.element.implementation); | 1107 work.element.implementation); |
| 1106 } | 1108 } |
| 1107 | 1109 |
| 1110 |
| 1111 DiagnosticReporter get reporter => compiler.reporter; |
| 1112 |
| 1108 // TODO(johnniwinther): Avoid the need for this. | 1113 // TODO(johnniwinther): Avoid the need for this. |
| 1109 Resolution get resolution => compiler.resolution; | 1114 Resolution get resolution => compiler.resolution; |
| 1110 | 1115 |
| 1111 @override | 1116 @override |
| 1112 SemanticSendVisitor get sendVisitor => this; | 1117 SemanticSendVisitor get sendVisitor => this; |
| 1113 | 1118 |
| 1114 @override | 1119 @override |
| 1115 void visitNode(ast.Node node) { | 1120 void visitNode(ast.Node node) { |
| 1116 internalError(node, "Unhandled node: $node"); | 1121 internalError(node, "Unhandled node: $node"); |
| 1117 } | 1122 } |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 } | 1494 } |
| 1490 | 1495 |
| 1491 bool isCalledOnce(Element element) { | 1496 bool isCalledOnce(Element element) { |
| 1492 if (!allInlinedFunctionsCalledOnce) return false; | 1497 if (!allInlinedFunctionsCalledOnce) return false; |
| 1493 TypesInferrer inferrer = compiler.typesTask.typesInferrer; | 1498 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
| 1494 return inferrer.isCalledOnce(element); | 1499 return inferrer.isCalledOnce(element); |
| 1495 } | 1500 } |
| 1496 | 1501 |
| 1497 inlinedFrom(Element element, f()) { | 1502 inlinedFrom(Element element, f()) { |
| 1498 assert(element is FunctionElement || element is VariableElement); | 1503 assert(element is FunctionElement || element is VariableElement); |
| 1499 return compiler.withCurrentElement(element, () { | 1504 return reporter.withCurrentElement(element, () { |
| 1500 // The [sourceElementStack] contains declaration elements. | 1505 // The [sourceElementStack] contains declaration elements. |
| 1501 SourceInformationBuilder oldSourceInformationBuilder = | 1506 SourceInformationBuilder oldSourceInformationBuilder = |
| 1502 sourceInformationBuilder; | 1507 sourceInformationBuilder; |
| 1503 sourceInformationBuilder = | 1508 sourceInformationBuilder = |
| 1504 sourceInformationBuilder.forContext(element.implementation); | 1509 sourceInformationBuilder.forContext(element.implementation); |
| 1505 sourceElementStack.add(element.declaration); | 1510 sourceElementStack.add(element.declaration); |
| 1506 var result = f(); | 1511 var result = f(); |
| 1507 sourceInformationBuilder = oldSourceInformationBuilder; | 1512 sourceInformationBuilder = oldSourceInformationBuilder; |
| 1508 sourceElementStack.removeLast(); | 1513 sourceElementStack.removeLast(); |
| 1509 return result; | 1514 return result; |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1861 * Documentation wanted -- johnniwinther | 1866 * Documentation wanted -- johnniwinther |
| 1862 * | 1867 * |
| 1863 * Invariant: [constructors] must contain only implementation elements. | 1868 * Invariant: [constructors] must contain only implementation elements. |
| 1864 */ | 1869 */ |
| 1865 void inlineSuperOrRedirect(ConstructorElement callee, | 1870 void inlineSuperOrRedirect(ConstructorElement callee, |
| 1866 List<HInstruction> compiledArguments, | 1871 List<HInstruction> compiledArguments, |
| 1867 List<FunctionElement> constructors, | 1872 List<FunctionElement> constructors, |
| 1868 Map<Element, HInstruction> fieldValues, | 1873 Map<Element, HInstruction> fieldValues, |
| 1869 FunctionElement caller) { | 1874 FunctionElement caller) { |
| 1870 callee = callee.implementation; | 1875 callee = callee.implementation; |
| 1871 compiler.withCurrentElement(callee, () { | 1876 reporter.withCurrentElement(callee, () { |
| 1872 constructors.add(callee); | 1877 constructors.add(callee); |
| 1873 ClassElement enclosingClass = callee.enclosingClass; | 1878 ClassElement enclosingClass = callee.enclosingClass; |
| 1874 if (backend.classNeedsRti(enclosingClass)) { | 1879 if (backend.classNeedsRti(enclosingClass)) { |
| 1875 // If [enclosingClass] needs RTI, we have to give a value to its | 1880 // If [enclosingClass] needs RTI, we have to give a value to its |
| 1876 // type parameters. | 1881 // type parameters. |
| 1877 ClassElement currentClass = caller.enclosingClass; | 1882 ClassElement currentClass = caller.enclosingClass; |
| 1878 // For a super constructor call, the type is the supertype of | 1883 // For a super constructor call, the type is the supertype of |
| 1879 // [currentClass]. For a redirecting constructor, the type is | 1884 // [currentClass]. For a redirecting constructor, the type is |
| 1880 // the current type. [InterfaceType.asInstanceOf] takes care | 1885 // the current type. [InterfaceType.asInstanceOf] takes care |
| 1881 // of both. | 1886 // of both. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1976 compileArgument, | 1981 compileArgument, |
| 1977 handleConstantForOptionalParameter); | 1982 handleConstantForOptionalParameter); |
| 1978 if (!match) { | 1983 if (!match) { |
| 1979 if (compiler.elementHasCompileTimeError(constructor)) { | 1984 if (compiler.elementHasCompileTimeError(constructor)) { |
| 1980 return; | 1985 return; |
| 1981 } | 1986 } |
| 1982 // If this fails, the selector we constructed for the call to a | 1987 // If this fails, the selector we constructed for the call to a |
| 1983 // forwarding constructor in a mixin application did not match the | 1988 // forwarding constructor in a mixin application did not match the |
| 1984 // constructor (which, for example, may happen when the libraries are | 1989 // constructor (which, for example, may happen when the libraries are |
| 1985 // not compatible for private names, see issue 20394). | 1990 // not compatible for private names, see issue 20394). |
| 1986 compiler.internalError(constructor, | 1991 reporter.internalError(constructor, |
| 1987 'forwarding constructor call does not match'); | 1992 'forwarding constructor call does not match'); |
| 1988 } | 1993 } |
| 1989 inlineSuperOrRedirect( | 1994 inlineSuperOrRedirect( |
| 1990 target, | 1995 target, |
| 1991 arguments, | 1996 arguments, |
| 1992 constructors, | 1997 constructors, |
| 1993 fieldValues, | 1998 fieldValues, |
| 1994 constructor); | 1999 constructor); |
| 1995 return; | 2000 return; |
| 1996 } | 2001 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2038 // No super initializer found. Try to find the default constructor if | 2043 // No super initializer found. Try to find the default constructor if |
| 2039 // the class is not Object. | 2044 // the class is not Object. |
| 2040 ClassElement enclosingClass = constructor.enclosingClass; | 2045 ClassElement enclosingClass = constructor.enclosingClass; |
| 2041 ClassElement superClass = enclosingClass.superclass; | 2046 ClassElement superClass = enclosingClass.superclass; |
| 2042 if (!enclosingClass.isObject) { | 2047 if (!enclosingClass.isObject) { |
| 2043 assert(superClass != null); | 2048 assert(superClass != null); |
| 2044 assert(superClass.isResolved); | 2049 assert(superClass.isResolved); |
| 2045 // TODO(johnniwinther): Should we find injected constructors as well? | 2050 // TODO(johnniwinther): Should we find injected constructors as well? |
| 2046 FunctionElement target = superClass.lookupDefaultConstructor(); | 2051 FunctionElement target = superClass.lookupDefaultConstructor(); |
| 2047 if (target == null) { | 2052 if (target == null) { |
| 2048 compiler.internalError(superClass, | 2053 reporter.internalError(superClass, |
| 2049 "No default constructor available."); | 2054 "No default constructor available."); |
| 2050 } | 2055 } |
| 2051 List<HInstruction> arguments = | 2056 List<HInstruction> arguments = |
| 2052 CallStructure.NO_ARGS.makeArgumentsList( | 2057 CallStructure.NO_ARGS.makeArgumentsList( |
| 2053 const Link<ast.Node>(), | 2058 const Link<ast.Node>(), |
| 2054 target.implementation, | 2059 target.implementation, |
| 2055 null, | 2060 null, |
| 2056 handleConstantForOptionalParameter); | 2061 handleConstantForOptionalParameter); |
| 2057 inlineSuperOrRedirect(target, | 2062 inlineSuperOrRedirect(target, |
| 2058 arguments, | 2063 arguments, |
| 2059 constructors, | 2064 constructors, |
| 2060 fieldValues, | 2065 fieldValues, |
| 2061 constructor); | 2066 constructor); |
| 2062 } | 2067 } |
| 2063 } | 2068 } |
| 2064 } | 2069 } |
| 2065 | 2070 |
| 2066 /** | 2071 /** |
| 2067 * Run through the fields of [cls] and add their potential | 2072 * Run through the fields of [cls] and add their potential |
| 2068 * initializers. | 2073 * initializers. |
| 2069 * | 2074 * |
| 2070 * Invariant: [classElement] must be an implementation element. | 2075 * Invariant: [classElement] must be an implementation element. |
| 2071 */ | 2076 */ |
| 2072 void buildFieldInitializers(ClassElement classElement, | 2077 void buildFieldInitializers(ClassElement classElement, |
| 2073 Map<Element, HInstruction> fieldValues) { | 2078 Map<Element, HInstruction> fieldValues) { |
| 2074 assert(invariant(classElement, classElement.isImplementation)); | 2079 assert(invariant(classElement, classElement.isImplementation)); |
| 2075 classElement.forEachInstanceField( | 2080 classElement.forEachInstanceField( |
| 2076 (ClassElement enclosingClass, VariableElement member) { | 2081 (ClassElement enclosingClass, VariableElement member) { |
| 2077 if (compiler.elementHasCompileTimeError(member)) return; | 2082 if (compiler.elementHasCompileTimeError(member)) return; |
| 2078 compiler.withCurrentElement(member, () { | 2083 reporter.withCurrentElement(member, () { |
| 2079 TreeElements definitions = member.treeElements; | 2084 TreeElements definitions = member.treeElements; |
| 2080 ast.Node node = member.node; | 2085 ast.Node node = member.node; |
| 2081 ast.Expression initializer = member.initializer; | 2086 ast.Expression initializer = member.initializer; |
| 2082 if (initializer == null) { | 2087 if (initializer == null) { |
| 2083 // Unassigned fields of native classes are not initialized to | 2088 // Unassigned fields of native classes are not initialized to |
| 2084 // prevent overwriting pre-initialized native properties. | 2089 // prevent overwriting pre-initialized native properties. |
| 2085 if (!Elements.isNativeOrExtendsNative(classElement)) { | 2090 if (!Elements.isNativeOrExtendsNative(classElement)) { |
| 2086 fieldValues[member] = graph.addConstantNull(compiler); | 2091 fieldValues[member] = graph.addConstantNull(compiler); |
| 2087 } | 2092 } |
| 2088 } else { | 2093 } else { |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2656 visitBlock(ast.Block node) { | 2661 visitBlock(ast.Block node) { |
| 2657 assert(!isAborted()); | 2662 assert(!isAborted()); |
| 2658 if (!isReachable) return; // This can only happen when inlining. | 2663 if (!isReachable) return; // This can only happen when inlining. |
| 2659 for (Link<ast.Node> link = node.statements.nodes; | 2664 for (Link<ast.Node> link = node.statements.nodes; |
| 2660 !link.isEmpty; | 2665 !link.isEmpty; |
| 2661 link = link.tail) { | 2666 link = link.tail) { |
| 2662 visit(link.head); | 2667 visit(link.head); |
| 2663 if (!isReachable) { | 2668 if (!isReachable) { |
| 2664 // The block has been aborted by a return or a throw. | 2669 // The block has been aborted by a return or a throw. |
| 2665 if (!stack.isEmpty) { | 2670 if (!stack.isEmpty) { |
| 2666 compiler.internalError(node, 'Non-empty instruction stack.'); | 2671 reporter.internalError(node, 'Non-empty instruction stack.'); |
| 2667 } | 2672 } |
| 2668 return; | 2673 return; |
| 2669 } | 2674 } |
| 2670 } | 2675 } |
| 2671 assert(!current.isClosed()); | 2676 assert(!current.isClosed()); |
| 2672 if (!stack.isEmpty) { | 2677 if (!stack.isEmpty) { |
| 2673 compiler.internalError(node, 'Non-empty instruction stack.'); | 2678 reporter.internalError(node, 'Non-empty instruction stack.'); |
| 2674 } | 2679 } |
| 2675 } | 2680 } |
| 2676 | 2681 |
| 2677 visitClassNode(ast.ClassNode node) { | 2682 visitClassNode(ast.ClassNode node) { |
| 2678 compiler.internalError(node, | 2683 reporter.internalError(node, |
| 2679 'SsaBuilder.visitClassNode should not be called.'); | 2684 'SsaBuilder.visitClassNode should not be called.'); |
| 2680 } | 2685 } |
| 2681 | 2686 |
| 2682 visitThrowExpression(ast.Expression expression) { | 2687 visitThrowExpression(ast.Expression expression) { |
| 2683 bool old = inExpressionOfThrow; | 2688 bool old = inExpressionOfThrow; |
| 2684 try { | 2689 try { |
| 2685 inExpressionOfThrow = true; | 2690 inExpressionOfThrow = true; |
| 2686 visit(expression); | 2691 visit(expression); |
| 2687 } finally { | 2692 } finally { |
| 2688 inExpressionOfThrow = old; | 2693 inExpressionOfThrow = old; |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3208 | 3213 |
| 3209 @override | 3214 @override |
| 3210 void visitThisGet(ast.Identifier node, [_]) { | 3215 void visitThisGet(ast.Identifier node, [_]) { |
| 3211 stack.add(localsHandler.readThis()); | 3216 stack.add(localsHandler.readThis()); |
| 3212 } | 3217 } |
| 3213 | 3218 |
| 3214 visitIdentifier(ast.Identifier node) { | 3219 visitIdentifier(ast.Identifier node) { |
| 3215 if (node.isThis()) { | 3220 if (node.isThis()) { |
| 3216 visitThisGet(node); | 3221 visitThisGet(node); |
| 3217 } else { | 3222 } else { |
| 3218 compiler.internalError(node, | 3223 reporter.internalError(node, |
| 3219 "SsaFromAstMixin.visitIdentifier on non-this."); | 3224 "SsaFromAstMixin.visitIdentifier on non-this."); |
| 3220 } | 3225 } |
| 3221 } | 3226 } |
| 3222 | 3227 |
| 3223 visitIf(ast.If node) { | 3228 visitIf(ast.If node) { |
| 3224 assert(isReachable); | 3229 assert(isReachable); |
| 3225 handleIf( | 3230 handleIf( |
| 3226 node, | 3231 node, |
| 3227 visitCondition: () => visit(node.condition), | 3232 visitCondition: () => visit(node.condition), |
| 3228 visitThen: () => visit(node.thenPart), | 3233 visitThen: () => visit(node.thenPart), |
| (...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4071 generateCallInvoke(node, localsHandler.readLocal(function), | 4076 generateCallInvoke(node, localsHandler.readLocal(function), |
| 4072 sourceInformationBuilder.buildCall(node, node.argumentsNode)); | 4077 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 4073 } | 4078 } |
| 4074 | 4079 |
| 4075 void handleForeignJs(ast.Send node) { | 4080 void handleForeignJs(ast.Send node) { |
| 4076 Link<ast.Node> link = node.arguments; | 4081 Link<ast.Node> link = node.arguments; |
| 4077 // Don't visit the first argument, which is the type, and the second | 4082 // Don't visit the first argument, which is the type, and the second |
| 4078 // argument, which is the foreign code. | 4083 // argument, which is the foreign code. |
| 4079 if (link.isEmpty || link.tail.isEmpty) { | 4084 if (link.isEmpty || link.tail.isEmpty) { |
| 4080 // We should not get here because the call should be compiled to NSM. | 4085 // We should not get here because the call should be compiled to NSM. |
| 4081 compiler.internalError(node.argumentsNode, | 4086 reporter.internalError(node.argumentsNode, |
| 4082 'At least two arguments expected.'); | 4087 'At least two arguments expected.'); |
| 4083 } | 4088 } |
| 4084 native.NativeBehavior nativeBehavior = | 4089 native.NativeBehavior nativeBehavior = |
| 4085 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 4090 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 4086 | 4091 |
| 4087 List<HInstruction> inputs = <HInstruction>[]; | 4092 List<HInstruction> inputs = <HInstruction>[]; |
| 4088 addGenericSendArgumentsToList(link.tail.tail, inputs); | 4093 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 4089 | 4094 |
| 4090 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { | 4095 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
| 4091 compiler.reportErrorMessage( | 4096 reporter.reportErrorMessage( |
| 4092 node, MessageKind.GENERIC, | 4097 node, MessageKind.GENERIC, |
| 4093 {'text': | 4098 {'text': |
| 4094 'Mismatch between number of placeholders' | 4099 'Mismatch between number of placeholders' |
| 4095 ' and number of arguments.'}); | 4100 ' and number of arguments.'}); |
| 4096 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. | 4101 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 4097 return; | 4102 return; |
| 4098 } | 4103 } |
| 4099 | 4104 |
| 4100 TypeMask ssaType = | 4105 TypeMask ssaType = |
| 4101 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 4106 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4115 effects: nativeBehavior.sideEffects, | 4120 effects: nativeBehavior.sideEffects, |
| 4116 nativeBehavior: nativeBehavior) | 4121 nativeBehavior: nativeBehavior) |
| 4117 ..sourceInformation = sourceInformation); | 4122 ..sourceInformation = sourceInformation); |
| 4118 } | 4123 } |
| 4119 } | 4124 } |
| 4120 | 4125 |
| 4121 void handleJsStringConcat(ast.Send node) { | 4126 void handleJsStringConcat(ast.Send node) { |
| 4122 List<HInstruction> inputs = <HInstruction>[]; | 4127 List<HInstruction> inputs = <HInstruction>[]; |
| 4123 addGenericSendArgumentsToList(node.arguments, inputs); | 4128 addGenericSendArgumentsToList(node.arguments, inputs); |
| 4124 if (inputs.length != 2) { | 4129 if (inputs.length != 2) { |
| 4125 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); | 4130 reporter.internalError(node.argumentsNode, 'Two arguments expected.'); |
| 4126 } | 4131 } |
| 4127 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); | 4132 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); |
| 4128 } | 4133 } |
| 4129 | 4134 |
| 4130 void handleForeignJsCurrentIsolateContext(ast.Send node) { | 4135 void handleForeignJsCurrentIsolateContext(ast.Send node) { |
| 4131 if (!node.arguments.isEmpty) { | 4136 if (!node.arguments.isEmpty) { |
| 4132 compiler.internalError(node, | 4137 reporter.internalError(node, |
| 4133 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); | 4138 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); |
| 4134 } | 4139 } |
| 4135 | 4140 |
| 4136 if (!compiler.hasIsolateSupport) { | 4141 if (!compiler.hasIsolateSupport) { |
| 4137 // If the isolate library is not used, we just generate code | 4142 // If the isolate library is not used, we just generate code |
| 4138 // to fetch the static state. | 4143 // to fetch the static state. |
| 4139 String name = backend.namer.staticStateHolder; | 4144 String name = backend.namer.staticStateHolder; |
| 4140 push(new HForeignCode(js.js.parseForeignJS(name), | 4145 push(new HForeignCode(js.js.parseForeignJS(name), |
| 4141 backend.dynamicType, | 4146 backend.dynamicType, |
| 4142 <HInstruction>[])); | 4147 <HInstruction>[])); |
| 4143 } else { | 4148 } else { |
| 4144 // Call a helper method from the isolate library. The isolate | 4149 // Call a helper method from the isolate library. The isolate |
| 4145 // library uses its own isolate structure, that encapsulates | 4150 // library uses its own isolate structure, that encapsulates |
| 4146 // Leg's isolate. | 4151 // Leg's isolate. |
| 4147 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); | 4152 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); |
| 4148 if (element == null) { | 4153 if (element == null) { |
| 4149 compiler.internalError(node, | 4154 reporter.internalError(node, |
| 4150 'Isolate library and compiler mismatch.'); | 4155 'Isolate library and compiler mismatch.'); |
| 4151 } | 4156 } |
| 4152 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); | 4157 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 4153 } | 4158 } |
| 4154 } | 4159 } |
| 4155 | 4160 |
| 4156 void handleForeignJsGetFlag(ast.Send node) { | 4161 void handleForeignJsGetFlag(ast.Send node) { |
| 4157 List<ast.Node> arguments = node.arguments.toList(); | 4162 List<ast.Node> arguments = node.arguments.toList(); |
| 4158 ast.Node argument; | 4163 ast.Node argument; |
| 4159 switch (arguments.length) { | 4164 switch (arguments.length) { |
| 4160 case 0: | 4165 case 0: |
| 4161 compiler.reportErrorMessage( | 4166 reporter.reportErrorMessage( |
| 4162 node, MessageKind.GENERIC, | 4167 node, MessageKind.GENERIC, |
| 4163 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); | 4168 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); |
| 4164 return; | 4169 return; |
| 4165 case 1: | 4170 case 1: |
| 4166 argument = arguments[0]; | 4171 argument = arguments[0]; |
| 4167 break; | 4172 break; |
| 4168 default: | 4173 default: |
| 4169 for (int i = 1; i < arguments.length; i++) { | 4174 for (int i = 1; i < arguments.length; i++) { |
| 4170 compiler.reportErrorMessage( | 4175 reporter.reportErrorMessage( |
| 4171 arguments[i], MessageKind.GENERIC, | 4176 arguments[i], MessageKind.GENERIC, |
| 4172 {'text': 'Error: Extra argument to JS_GET_FLAG.'}); | 4177 {'text': 'Error: Extra argument to JS_GET_FLAG.'}); |
| 4173 } | 4178 } |
| 4174 return; | 4179 return; |
| 4175 } | 4180 } |
| 4176 ast.LiteralString string = argument.asLiteralString(); | 4181 ast.LiteralString string = argument.asLiteralString(); |
| 4177 if (string == null) { | 4182 if (string == null) { |
| 4178 compiler.reportErrorMessage( | 4183 reporter.reportErrorMessage( |
| 4179 argument, MessageKind.GENERIC, | 4184 argument, MessageKind.GENERIC, |
| 4180 {'text': 'Error: Expected a literal string.'}); | 4185 {'text': 'Error: Expected a literal string.'}); |
| 4181 } | 4186 } |
| 4182 String name = string.dartString.slowToString(); | 4187 String name = string.dartString.slowToString(); |
| 4183 bool value = false; | 4188 bool value = false; |
| 4184 switch (name) { | 4189 switch (name) { |
| 4185 case 'MUST_RETAIN_METADATA': | 4190 case 'MUST_RETAIN_METADATA': |
| 4186 value = backend.mustRetainMetadata; | 4191 value = backend.mustRetainMetadata; |
| 4187 break; | 4192 break; |
| 4188 case 'USE_CONTENT_SECURITY_POLICY': | 4193 case 'USE_CONTENT_SECURITY_POLICY': |
| 4189 value = compiler.useContentSecurityPolicy; | 4194 value = compiler.useContentSecurityPolicy; |
| 4190 break; | 4195 break; |
| 4191 default: | 4196 default: |
| 4192 compiler.reportErrorMessage( | 4197 reporter.reportErrorMessage( |
| 4193 node, MessageKind.GENERIC, | 4198 node, MessageKind.GENERIC, |
| 4194 {'text': 'Error: Unknown internal flag "$name".'}); | 4199 {'text': 'Error: Unknown internal flag "$name".'}); |
| 4195 } | 4200 } |
| 4196 stack.add(graph.addConstantBool(value, compiler)); | 4201 stack.add(graph.addConstantBool(value, compiler)); |
| 4197 } | 4202 } |
| 4198 | 4203 |
| 4199 void handleForeignJsGetName(ast.Send node) { | 4204 void handleForeignJsGetName(ast.Send node) { |
| 4200 List<ast.Node> arguments = node.arguments.toList(); | 4205 List<ast.Node> arguments = node.arguments.toList(); |
| 4201 ast.Node argument; | 4206 ast.Node argument; |
| 4202 switch (arguments.length) { | 4207 switch (arguments.length) { |
| 4203 case 0: | 4208 case 0: |
| 4204 compiler.reportErrorMessage( | 4209 reporter.reportErrorMessage( |
| 4205 node, MessageKind.GENERIC, | 4210 node, MessageKind.GENERIC, |
| 4206 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); | 4211 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); |
| 4207 return; | 4212 return; |
| 4208 case 1: | 4213 case 1: |
| 4209 argument = arguments[0]; | 4214 argument = arguments[0]; |
| 4210 break; | 4215 break; |
| 4211 default: | 4216 default: |
| 4212 for (int i = 1; i < arguments.length; i++) { | 4217 for (int i = 1; i < arguments.length; i++) { |
| 4213 compiler.reportErrorMessage( | 4218 reporter.reportErrorMessage( |
| 4214 arguments[i], MessageKind.GENERIC, | 4219 arguments[i], MessageKind.GENERIC, |
| 4215 {'text': 'Error: Extra argument to JS_GET_NAME.'}); | 4220 {'text': 'Error: Extra argument to JS_GET_NAME.'}); |
| 4216 } | 4221 } |
| 4217 return; | 4222 return; |
| 4218 } | 4223 } |
| 4219 Element element = elements[argument]; | 4224 Element element = elements[argument]; |
| 4220 if (element == null || | 4225 if (element == null || |
| 4221 element is! FieldElement || | 4226 element is! FieldElement || |
| 4222 element.enclosingClass != backend.jsGetNameEnum) { | 4227 element.enclosingClass != backend.jsGetNameEnum) { |
| 4223 compiler.reportErrorMessage( | 4228 reporter.reportErrorMessage( |
| 4224 argument, MessageKind.GENERIC, | 4229 argument, MessageKind.GENERIC, |
| 4225 {'text': 'Error: Expected a JsGetName enum value.'}); | 4230 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 4226 } | 4231 } |
| 4227 EnumClassElement enumClass = element.enclosingClass; | 4232 EnumClassElement enumClass = element.enclosingClass; |
| 4228 int index = enumClass.enumValues.indexOf(element); | 4233 int index = enumClass.enumValues.indexOf(element); |
| 4229 stack.add( | 4234 stack.add( |
| 4230 addConstantStringFromName( | 4235 addConstantStringFromName( |
| 4231 backend.namer.getNameForJsGetName( | 4236 backend.namer.getNameForJsGetName( |
| 4232 argument, JsGetName.values[index]))); | 4237 argument, JsGetName.values[index]))); |
| 4233 } | 4238 } |
| 4234 | 4239 |
| 4235 void handleForeignJsBuiltin(ast.Send node) { | 4240 void handleForeignJsBuiltin(ast.Send node) { |
| 4236 List<ast.Node> arguments = node.arguments.toList(); | 4241 List<ast.Node> arguments = node.arguments.toList(); |
| 4237 ast.Node argument; | 4242 ast.Node argument; |
| 4238 if (arguments.length < 2) { | 4243 if (arguments.length < 2) { |
| 4239 compiler.reportErrorMessage( | 4244 reporter.reportErrorMessage( |
| 4240 node, MessageKind.GENERIC, | 4245 node, MessageKind.GENERIC, |
| 4241 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); | 4246 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); |
| 4242 } | 4247 } |
| 4243 | 4248 |
| 4244 Element builtinElement = elements[arguments[1]]; | 4249 Element builtinElement = elements[arguments[1]]; |
| 4245 if (builtinElement == null || | 4250 if (builtinElement == null || |
| 4246 (builtinElement is! FieldElement) || | 4251 (builtinElement is! FieldElement) || |
| 4247 builtinElement.enclosingClass != backend.jsBuiltinEnum) { | 4252 builtinElement.enclosingClass != backend.jsBuiltinEnum) { |
| 4248 compiler.reportErrorMessage( | 4253 reporter.reportErrorMessage( |
| 4249 argument, MessageKind.GENERIC, | 4254 argument, MessageKind.GENERIC, |
| 4250 {'text': 'Error: Expected a JsBuiltin enum value.'}); | 4255 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 4251 } | 4256 } |
| 4252 EnumClassElement enumClass = builtinElement.enclosingClass; | 4257 EnumClassElement enumClass = builtinElement.enclosingClass; |
| 4253 int index = enumClass.enumValues.indexOf(builtinElement); | 4258 int index = enumClass.enumValues.indexOf(builtinElement); |
| 4254 | 4259 |
| 4255 js.Template template = | 4260 js.Template template = |
| 4256 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); | 4261 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); |
| 4257 | 4262 |
| 4258 List<HInstruction> compiledArguments = <HInstruction>[]; | 4263 List<HInstruction> compiledArguments = <HInstruction>[]; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4272 compiledArguments, | 4277 compiledArguments, |
| 4273 nativeBehavior: nativeBehavior)); | 4278 nativeBehavior: nativeBehavior)); |
| 4274 } | 4279 } |
| 4275 | 4280 |
| 4276 void handleForeignJsEmbeddedGlobal(ast.Send node) { | 4281 void handleForeignJsEmbeddedGlobal(ast.Send node) { |
| 4277 List<ast.Node> arguments = node.arguments.toList(); | 4282 List<ast.Node> arguments = node.arguments.toList(); |
| 4278 ast.Node globalNameNode; | 4283 ast.Node globalNameNode; |
| 4279 switch (arguments.length) { | 4284 switch (arguments.length) { |
| 4280 case 0: | 4285 case 0: |
| 4281 case 1: | 4286 case 1: |
| 4282 compiler.reportErrorMessage( | 4287 reporter.reportErrorMessage( |
| 4283 node, MessageKind.GENERIC, | 4288 node, MessageKind.GENERIC, |
| 4284 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); | 4289 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); |
| 4285 return; | 4290 return; |
| 4286 case 2: | 4291 case 2: |
| 4287 // The type has been extracted earlier. We are only interested in the | 4292 // The type has been extracted earlier. We are only interested in the |
| 4288 // name in this function. | 4293 // name in this function. |
| 4289 globalNameNode = arguments[1]; | 4294 globalNameNode = arguments[1]; |
| 4290 break; | 4295 break; |
| 4291 default: | 4296 default: |
| 4292 for (int i = 2; i < arguments.length; i++) { | 4297 for (int i = 2; i < arguments.length; i++) { |
| 4293 compiler.reportErrorMessage( | 4298 reporter.reportErrorMessage( |
| 4294 arguments[i], MessageKind.GENERIC, | 4299 arguments[i], MessageKind.GENERIC, |
| 4295 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); | 4300 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); |
| 4296 } | 4301 } |
| 4297 return; | 4302 return; |
| 4298 } | 4303 } |
| 4299 visit(globalNameNode); | 4304 visit(globalNameNode); |
| 4300 HInstruction globalNameHNode = pop(); | 4305 HInstruction globalNameHNode = pop(); |
| 4301 if (!globalNameHNode.isConstantString()) { | 4306 if (!globalNameHNode.isConstantString()) { |
| 4302 compiler.reportErrorMessage( | 4307 reporter.reportErrorMessage( |
| 4303 arguments[1], MessageKind.GENERIC, | 4308 arguments[1], MessageKind.GENERIC, |
| 4304 {'text': 'Error: Expected String as second argument ' | 4309 {'text': 'Error: Expected String as second argument ' |
| 4305 'to JS_EMBEDDED_GLOBAL.'}); | 4310 'to JS_EMBEDDED_GLOBAL.'}); |
| 4306 return; | 4311 return; |
| 4307 } | 4312 } |
| 4308 HConstant hConstant = globalNameHNode; | 4313 HConstant hConstant = globalNameHNode; |
| 4309 StringConstantValue constant = hConstant.constant; | 4314 StringConstantValue constant = hConstant.constant; |
| 4310 String globalName = constant.primitiveValue.slowToString(); | 4315 String globalName = constant.primitiveValue.slowToString(); |
| 4311 js.Template expr = js.js.expressionTemplateYielding( | 4316 js.Template expr = js.js.expressionTemplateYielding( |
| 4312 backend.emitter.generateEmbeddedGlobalAccess(globalName)); | 4317 backend.emitter.generateEmbeddedGlobalAccess(globalName)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4329 ConstantValue argumentConstant = argumentInstruction.constant; | 4334 ConstantValue argumentConstant = argumentInstruction.constant; |
| 4330 if (argumentConstant is TypeConstantValue) { | 4335 if (argumentConstant is TypeConstantValue) { |
| 4331 ConstantValue constant = | 4336 ConstantValue constant = |
| 4332 new InterceptorConstantValue(argumentConstant.representedType); | 4337 new InterceptorConstantValue(argumentConstant.representedType); |
| 4333 HInstruction instruction = graph.addConstant(constant, compiler); | 4338 HInstruction instruction = graph.addConstant(constant, compiler); |
| 4334 stack.add(instruction); | 4339 stack.add(instruction); |
| 4335 return; | 4340 return; |
| 4336 } | 4341 } |
| 4337 } | 4342 } |
| 4338 } | 4343 } |
| 4339 compiler.reportErrorMessage( | 4344 reporter.reportErrorMessage( |
| 4340 node, | 4345 node, |
| 4341 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 4346 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
| 4342 stack.add(graph.addConstantNull(compiler)); | 4347 stack.add(graph.addConstantNull(compiler)); |
| 4343 } | 4348 } |
| 4344 | 4349 |
| 4345 void handleForeignJsCallInIsolate(ast.Send node) { | 4350 void handleForeignJsCallInIsolate(ast.Send node) { |
| 4346 Link<ast.Node> link = node.arguments; | 4351 Link<ast.Node> link = node.arguments; |
| 4347 if (!compiler.hasIsolateSupport) { | 4352 if (!compiler.hasIsolateSupport) { |
| 4348 // If the isolate library is not used, we just invoke the | 4353 // If the isolate library is not used, we just invoke the |
| 4349 // closure. | 4354 // closure. |
| 4350 visit(link.tail.head); | 4355 visit(link.tail.head); |
| 4351 push(new HInvokeClosure(new Selector.callClosure(0), | 4356 push(new HInvokeClosure(new Selector.callClosure(0), |
| 4352 <HInstruction>[pop()], | 4357 <HInstruction>[pop()], |
| 4353 backend.dynamicType)); | 4358 backend.dynamicType)); |
| 4354 } else { | 4359 } else { |
| 4355 // Call a helper method from the isolate library. | 4360 // Call a helper method from the isolate library. |
| 4356 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); | 4361 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); |
| 4357 if (element == null) { | 4362 if (element == null) { |
| 4358 compiler.internalError(node, | 4363 reporter.internalError(node, |
| 4359 'Isolate library and compiler mismatch.'); | 4364 'Isolate library and compiler mismatch.'); |
| 4360 } | 4365 } |
| 4361 List<HInstruction> inputs = <HInstruction>[]; | 4366 List<HInstruction> inputs = <HInstruction>[]; |
| 4362 addGenericSendArgumentsToList(link, inputs); | 4367 addGenericSendArgumentsToList(link, inputs); |
| 4363 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); | 4368 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); |
| 4364 } | 4369 } |
| 4365 } | 4370 } |
| 4366 | 4371 |
| 4367 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { | 4372 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { |
| 4368 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 4373 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 4369 compiler.internalError(node.argumentsNode, | 4374 reporter.internalError(node.argumentsNode, |
| 4370 '"$name" requires exactly one argument.'); | 4375 '"$name" requires exactly one argument.'); |
| 4371 } | 4376 } |
| 4372 ast.Node closure = node.arguments.head; | 4377 ast.Node closure = node.arguments.head; |
| 4373 Element element = elements[closure]; | 4378 Element element = elements[closure]; |
| 4374 if (!Elements.isStaticOrTopLevelFunction(element)) { | 4379 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 4375 compiler.internalError(closure, | 4380 reporter.internalError(closure, |
| 4376 '"$name" requires a static or top-level method.'); | 4381 '"$name" requires a static or top-level method.'); |
| 4377 } | 4382 } |
| 4378 FunctionElement function = element; | 4383 FunctionElement function = element; |
| 4379 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration | 4384 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration |
| 4380 // and implementation signatures. Currently it is need because the | 4385 // and implementation signatures. Currently it is need because the |
| 4381 // signatures have different elements for parameters. | 4386 // signatures have different elements for parameters. |
| 4382 FunctionElement implementation = function.implementation; | 4387 FunctionElement implementation = function.implementation; |
| 4383 FunctionSignature params = implementation.functionSignature; | 4388 FunctionSignature params = implementation.functionSignature; |
| 4384 if (params.optionalParameterCount != 0) { | 4389 if (params.optionalParameterCount != 0) { |
| 4385 compiler.internalError(closure, | 4390 reporter.internalError(closure, |
| 4386 '"$name" does not handle closure with optional parameters.'); | 4391 '"$name" does not handle closure with optional parameters.'); |
| 4387 } | 4392 } |
| 4388 | 4393 |
| 4389 registry.registerStaticUse(element); | 4394 registry.registerStaticUse(element); |
| 4390 push(new HForeignCode( | 4395 push(new HForeignCode( |
| 4391 js.js.expressionTemplateYielding( | 4396 js.js.expressionTemplateYielding( |
| 4392 backend.emitter.staticFunctionAccess(element)), | 4397 backend.emitter.staticFunctionAccess(element)), |
| 4393 backend.dynamicType, | 4398 backend.dynamicType, |
| 4394 <HInstruction>[], | 4399 <HInstruction>[], |
| 4395 nativeBehavior: native.NativeBehavior.PURE)); | 4400 nativeBehavior: native.NativeBehavior.PURE)); |
| 4396 return params; | 4401 return params; |
| 4397 } | 4402 } |
| 4398 | 4403 |
| 4399 void handleForeignDartClosureToJs(ast.Send node, String name) { | 4404 void handleForeignDartClosureToJs(ast.Send node, String name) { |
| 4400 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take | 4405 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take |
| 4401 // care to wrap the closure in another closure that saves the current | 4406 // care to wrap the closure in another closure that saves the current |
| 4402 // isolate. | 4407 // isolate. |
| 4403 handleForeignRawFunctionRef(node, name); | 4408 handleForeignRawFunctionRef(node, name); |
| 4404 } | 4409 } |
| 4405 | 4410 |
| 4406 void handleForeignJsSetStaticState(ast.Send node) { | 4411 void handleForeignJsSetStaticState(ast.Send node) { |
| 4407 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 4412 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 4408 compiler.internalError(node.argumentsNode, | 4413 reporter.internalError(node.argumentsNode, |
| 4409 'Exactly one argument required.'); | 4414 'Exactly one argument required.'); |
| 4410 } | 4415 } |
| 4411 visit(node.arguments.head); | 4416 visit(node.arguments.head); |
| 4412 String isolateName = backend.namer.staticStateHolder; | 4417 String isolateName = backend.namer.staticStateHolder; |
| 4413 SideEffects sideEffects = new SideEffects.empty(); | 4418 SideEffects sideEffects = new SideEffects.empty(); |
| 4414 sideEffects.setAllSideEffects(); | 4419 sideEffects.setAllSideEffects(); |
| 4415 push(new HForeignCode( | 4420 push(new HForeignCode( |
| 4416 js.js.parseForeignJS("$isolateName = #"), | 4421 js.js.parseForeignJS("$isolateName = #"), |
| 4417 backend.dynamicType, | 4422 backend.dynamicType, |
| 4418 <HInstruction>[pop()], | 4423 <HInstruction>[pop()], |
| 4419 nativeBehavior: native.NativeBehavior.PURE, | 4424 nativeBehavior: native.NativeBehavior.PURE, |
| 4420 effects: sideEffects)); | 4425 effects: sideEffects)); |
| 4421 } | 4426 } |
| 4422 | 4427 |
| 4423 void handleForeignJsGetStaticState(ast.Send node) { | 4428 void handleForeignJsGetStaticState(ast.Send node) { |
| 4424 if (!node.arguments.isEmpty) { | 4429 if (!node.arguments.isEmpty) { |
| 4425 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 4430 reporter.internalError(node.argumentsNode, 'Too many arguments.'); |
| 4426 } | 4431 } |
| 4427 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), | 4432 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), |
| 4428 backend.dynamicType, | 4433 backend.dynamicType, |
| 4429 <HInstruction>[])); | 4434 <HInstruction>[])); |
| 4430 } | 4435 } |
| 4431 | 4436 |
| 4432 void handleForeignSend(ast.Send node, FunctionElement element) { | 4437 void handleForeignSend(ast.Send node, FunctionElement element) { |
| 4433 String name = element.name; | 4438 String name = element.name; |
| 4434 if (name == 'JS') { | 4439 if (name == 'JS') { |
| 4435 handleForeignJs(node); | 4440 handleForeignJs(node); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4453 handleForeignJsBuiltin(node); | 4458 handleForeignJsBuiltin(node); |
| 4454 } else if (name == 'JS_GET_FLAG') { | 4459 } else if (name == 'JS_GET_FLAG') { |
| 4455 handleForeignJsGetFlag(node); | 4460 handleForeignJsGetFlag(node); |
| 4456 } else if (name == 'JS_EFFECT') { | 4461 } else if (name == 'JS_EFFECT') { |
| 4457 stack.add(graph.addConstantNull(compiler)); | 4462 stack.add(graph.addConstantNull(compiler)); |
| 4458 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4463 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 4459 handleJsInterceptorConstant(node); | 4464 handleJsInterceptorConstant(node); |
| 4460 } else if (name == 'JS_STRING_CONCAT') { | 4465 } else if (name == 'JS_STRING_CONCAT') { |
| 4461 handleJsStringConcat(node); | 4466 handleJsStringConcat(node); |
| 4462 } else { | 4467 } else { |
| 4463 compiler.internalError(node, "Unknown foreign: ${element}"); | 4468 reporter.internalError(node, "Unknown foreign: ${element}"); |
| 4464 } | 4469 } |
| 4465 } | 4470 } |
| 4466 | 4471 |
| 4467 generateDeferredLoaderGet(ast.Send node, | 4472 generateDeferredLoaderGet(ast.Send node, |
| 4468 FunctionElement deferredLoader, | 4473 FunctionElement deferredLoader, |
| 4469 SourceInformation sourceInformation) { | 4474 SourceInformation sourceInformation) { |
| 4470 // Until now we only handle these as getters. | 4475 // Until now we only handle these as getters. |
| 4471 invariant(node, deferredLoader.isDeferredLoaderGetter); | 4476 invariant(node, deferredLoader.isDeferredLoaderGetter); |
| 4472 Element loadFunction = compiler.loadLibraryFunction; | 4477 Element loadFunction = compiler.loadLibraryFunction; |
| 4473 PrefixElement prefixElement = deferredLoader.enclosingElement; | 4478 PrefixElement prefixElement = deferredLoader.enclosingElement; |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4880 // The type variable is stored in a parameter of the method. | 4885 // The type variable is stored in a parameter of the method. |
| 4881 return localsHandler.readLocal( | 4886 return localsHandler.readLocal( |
| 4882 typeVariableLocal, sourceInformation: sourceInformation); | 4887 typeVariableLocal, sourceInformation: sourceInformation); |
| 4883 } else if (member.isInstanceMember) { | 4888 } else if (member.isInstanceMember) { |
| 4884 // The type variable is stored on the object. | 4889 // The type variable is stored on the object. |
| 4885 return readTypeVariable( | 4890 return readTypeVariable( |
| 4886 member.enclosingClass, | 4891 member.enclosingClass, |
| 4887 type.element, | 4892 type.element, |
| 4888 sourceInformation: sourceInformation); | 4893 sourceInformation: sourceInformation); |
| 4889 } else { | 4894 } else { |
| 4890 compiler.internalError(type.element, | 4895 reporter.internalError(type.element, |
| 4891 'Unexpected type variable in static context.'); | 4896 'Unexpected type variable in static context.'); |
| 4892 return null; | 4897 return null; |
| 4893 } | 4898 } |
| 4894 } | 4899 } |
| 4895 | 4900 |
| 4896 HInstruction analyzeTypeArgument( | 4901 HInstruction analyzeTypeArgument( |
| 4897 DartType argument, | 4902 DartType argument, |
| 4898 {SourceInformation sourceInformation}) { | 4903 {SourceInformation sourceInformation}) { |
| 4899 | 4904 |
| 4900 assert(assertTypeInContext(argument)); | 4905 assert(assertTypeInContext(argument)); |
| (...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5567 inputs, backend.dynamicType) | 5572 inputs, backend.dynamicType) |
| 5568 ..sourceInformation = sourceInformation); | 5573 ..sourceInformation = sourceInformation); |
| 5569 } | 5574 } |
| 5570 | 5575 |
| 5571 visitGetterSend(ast.Send node) { | 5576 visitGetterSend(ast.Send node) { |
| 5572 internalError(node, "Unexpected visitGetterSend"); | 5577 internalError(node, "Unexpected visitGetterSend"); |
| 5573 } | 5578 } |
| 5574 | 5579 |
| 5575 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 5580 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
| 5576 internalError(Spannable node, String reason) { | 5581 internalError(Spannable node, String reason) { |
| 5577 compiler.internalError(node, reason); | 5582 reporter.internalError(node, reason); |
| 5578 } | 5583 } |
| 5579 | 5584 |
| 5580 void generateError(ast.Node node, String message, Element helper) { | 5585 void generateError(ast.Node node, String message, Element helper) { |
| 5581 HInstruction errorMessage = addConstantString(message); | 5586 HInstruction errorMessage = addConstantString(message); |
| 5582 pushInvokeStatic(node, helper, [errorMessage]); | 5587 pushInvokeStatic(node, helper, [errorMessage]); |
| 5583 } | 5588 } |
| 5584 | 5589 |
| 5585 void generateRuntimeError(ast.Node node, String message) { | 5590 void generateRuntimeError(ast.Node node, String message) { |
| 5586 generateError(node, message, backend.getThrowRuntimeError()); | 5591 generateError(node, message, backend.getThrowRuntimeError()); |
| 5587 } | 5592 } |
| (...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6887 stack.add(stringBuilder.result); | 6892 stack.add(stringBuilder.result); |
| 6888 } | 6893 } |
| 6889 | 6894 |
| 6890 void visitLiteralNull(ast.LiteralNull node) { | 6895 void visitLiteralNull(ast.LiteralNull node) { |
| 6891 stack.add(graph.addConstantNull(compiler)); | 6896 stack.add(graph.addConstantNull(compiler)); |
| 6892 } | 6897 } |
| 6893 | 6898 |
| 6894 visitNodeList(ast.NodeList node) { | 6899 visitNodeList(ast.NodeList node) { |
| 6895 for (Link<ast.Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 6900 for (Link<ast.Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 6896 if (isAborted()) { | 6901 if (isAborted()) { |
| 6897 compiler.reportHintMessage( | 6902 reporter.reportHintMessage( |
| 6898 link.head, | 6903 link.head, |
| 6899 MessageKind.GENERIC, | 6904 MessageKind.GENERIC, |
| 6900 {'text': 'dead code'}); | 6905 {'text': 'dead code'}); |
| 6901 } else { | 6906 } else { |
| 6902 visit(link.head); | 6907 visit(link.head); |
| 6903 } | 6908 } |
| 6904 } | 6909 } |
| 6905 } | 6910 } |
| 6906 | 6911 |
| 6907 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { | 6912 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { |
| 6908 visit(node.expression); | 6913 visit(node.expression); |
| 6909 } | 6914 } |
| 6910 | 6915 |
| 6911 visitOperator(ast.Operator node) { | 6916 visitOperator(ast.Operator node) { |
| 6912 // Operators are intercepted in their surrounding Send nodes. | 6917 // Operators are intercepted in their surrounding Send nodes. |
| 6913 compiler.internalError(node, | 6918 reporter.internalError(node, |
| 6914 'SsaBuilder.visitOperator should not be called.'); | 6919 'SsaBuilder.visitOperator should not be called.'); |
| 6915 } | 6920 } |
| 6916 | 6921 |
| 6917 visitCascade(ast.Cascade node) { | 6922 visitCascade(ast.Cascade node) { |
| 6918 visit(node.expression); | 6923 visit(node.expression); |
| 6919 // Remove the result and reveal the duplicated receiver on the stack. | 6924 // Remove the result and reveal the duplicated receiver on the stack. |
| 6920 pop(); | 6925 pop(); |
| 6921 } | 6926 } |
| 6922 | 6927 |
| 6923 visitCascadeReceiver(ast.CascadeReceiver node) { | 6928 visitCascadeReceiver(ast.CascadeReceiver node) { |
| 6924 visit(node.expression); | 6929 visit(node.expression); |
| 6925 dup(); | 6930 dup(); |
| 6926 } | 6931 } |
| 6927 | 6932 |
| 6928 void handleInTryStatement() { | 6933 void handleInTryStatement() { |
| 6929 if (!inTryStatement) return; | 6934 if (!inTryStatement) return; |
| 6930 HBasicBlock block = close(new HExitTry()); | 6935 HBasicBlock block = close(new HExitTry()); |
| 6931 HBasicBlock newBlock = graph.addNewBlock(); | 6936 HBasicBlock newBlock = graph.addNewBlock(); |
| 6932 block.addSuccessor(newBlock); | 6937 block.addSuccessor(newBlock); |
| 6933 open(newBlock); | 6938 open(newBlock); |
| 6934 } | 6939 } |
| 6935 | 6940 |
| 6936 visitRethrow(ast.Rethrow node) { | 6941 visitRethrow(ast.Rethrow node) { |
| 6937 HInstruction exception = rethrowableException; | 6942 HInstruction exception = rethrowableException; |
| 6938 if (exception == null) { | 6943 if (exception == null) { |
| 6939 exception = graph.addConstantNull(compiler); | 6944 exception = graph.addConstantNull(compiler); |
| 6940 compiler.internalError(node, | 6945 reporter.internalError(node, |
| 6941 'rethrowableException should not be null.'); | 6946 'rethrowableException should not be null.'); |
| 6942 } | 6947 } |
| 6943 handleInTryStatement(); | 6948 handleInTryStatement(); |
| 6944 closeAndGotoExit( | 6949 closeAndGotoExit( |
| 6945 new HThrow(exception, | 6950 new HThrow(exception, |
| 6946 sourceInformationBuilder.buildThrow(node), | 6951 sourceInformationBuilder.buildThrow(node), |
| 6947 isRethrow: true)); | 6952 isRethrow: true)); |
| 6948 } | 6953 } |
| 6949 | 6954 |
| 6950 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { | 6955 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7055 | 7060 |
| 7056 visitAwait(ast.Await node) { | 7061 visitAwait(ast.Await node) { |
| 7057 visit(node.expression); | 7062 visit(node.expression); |
| 7058 HInstruction awaited = pop(); | 7063 HInstruction awaited = pop(); |
| 7059 // TODO(herhut): Improve this type. | 7064 // TODO(herhut): Improve this type. |
| 7060 push(new HAwait(awaited, new TypeMask.subclass(compiler.objectClass, | 7065 push(new HAwait(awaited, new TypeMask.subclass(compiler.objectClass, |
| 7061 compiler.world))); | 7066 compiler.world))); |
| 7062 } | 7067 } |
| 7063 | 7068 |
| 7064 visitTypeAnnotation(ast.TypeAnnotation node) { | 7069 visitTypeAnnotation(ast.TypeAnnotation node) { |
| 7065 compiler.internalError(node, | 7070 reporter.internalError(node, |
| 7066 'Visiting type annotation in SSA builder.'); | 7071 'Visiting type annotation in SSA builder.'); |
| 7067 } | 7072 } |
| 7068 | 7073 |
| 7069 visitVariableDefinitions(ast.VariableDefinitions node) { | 7074 visitVariableDefinitions(ast.VariableDefinitions node) { |
| 7070 assert(isReachable); | 7075 assert(isReachable); |
| 7071 for (Link<ast.Node> link = node.definitions.nodes; | 7076 for (Link<ast.Node> link = node.definitions.nodes; |
| 7072 !link.isEmpty; | 7077 !link.isEmpty; |
| 7073 link = link.tail) { | 7078 link = link.tail) { |
| 7074 ast.Node definition = link.head; | 7079 ast.Node definition = link.head; |
| 7075 LocalElement local = elements[definition]; | 7080 LocalElement local = elements[definition]; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7131 } | 7136 } |
| 7132 | 7137 |
| 7133 visitStringInterpolation(ast.StringInterpolation node) { | 7138 visitStringInterpolation(ast.StringInterpolation node) { |
| 7134 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 7139 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
| 7135 stringBuilder.visit(node); | 7140 stringBuilder.visit(node); |
| 7136 stack.add(stringBuilder.result); | 7141 stack.add(stringBuilder.result); |
| 7137 } | 7142 } |
| 7138 | 7143 |
| 7139 visitStringInterpolationPart(ast.StringInterpolationPart node) { | 7144 visitStringInterpolationPart(ast.StringInterpolationPart node) { |
| 7140 // The parts are iterated in visitStringInterpolation. | 7145 // The parts are iterated in visitStringInterpolation. |
| 7141 compiler.internalError(node, | 7146 reporter.internalError(node, |
| 7142 'SsaBuilder.visitStringInterpolation should not be called.'); | 7147 'SsaBuilder.visitStringInterpolation should not be called.'); |
| 7143 } | 7148 } |
| 7144 | 7149 |
| 7145 visitEmptyStatement(ast.EmptyStatement node) { | 7150 visitEmptyStatement(ast.EmptyStatement node) { |
| 7146 // Do nothing, empty statement. | 7151 // Do nothing, empty statement. |
| 7147 } | 7152 } |
| 7148 | 7153 |
| 7149 visitModifiers(ast.Modifiers node) { | 7154 visitModifiers(ast.Modifiers node) { |
| 7150 compiler.unimplemented(node, 'SsaFromAstMixin.visitModifiers.'); | 7155 compiler.unimplemented(node, 'SsaFromAstMixin.visitModifiers.'); |
| 7151 } | 7156 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7186 * a special "null handler" is returned. | 7191 * a special "null handler" is returned. |
| 7187 * | 7192 * |
| 7188 * [isLoopJump] is [:true:] when the jump handler is for a loop. This is used | 7193 * [isLoopJump] is [:true:] when the jump handler is for a loop. This is used |
| 7189 * to distinguish the synthetized loop created for a switch statement with | 7194 * to distinguish the synthetized loop created for a switch statement with |
| 7190 * continue statements from simple switch statements. | 7195 * continue statements from simple switch statements. |
| 7191 */ | 7196 */ |
| 7192 JumpHandler createJumpHandler(ast.Statement node, {bool isLoopJump}) { | 7197 JumpHandler createJumpHandler(ast.Statement node, {bool isLoopJump}) { |
| 7193 JumpTarget element = elements.getTargetDefinition(node); | 7198 JumpTarget element = elements.getTargetDefinition(node); |
| 7194 if (element == null || !identical(element.statement, node)) { | 7199 if (element == null || !identical(element.statement, node)) { |
| 7195 // No breaks or continues to this node. | 7200 // No breaks or continues to this node. |
| 7196 return new NullJumpHandler(compiler); | 7201 return new NullJumpHandler(reporter); |
| 7197 } | 7202 } |
| 7198 if (isLoopJump && node is ast.SwitchStatement) { | 7203 if (isLoopJump && node is ast.SwitchStatement) { |
| 7199 // Create a special jump handler for loops created for switch statements | 7204 // Create a special jump handler for loops created for switch statements |
| 7200 // with continue statements. | 7205 // with continue statements. |
| 7201 return new SwitchCaseJumpHandler(this, element, node); | 7206 return new SwitchCaseJumpHandler(this, element, node); |
| 7202 } | 7207 } |
| 7203 return new JumpHandler(this, element); | 7208 return new JumpHandler(this, element); |
| 7204 } | 7209 } |
| 7205 | 7210 |
| 7206 visitAsyncForIn(ast.AsyncForIn node) { | 7211 visitAsyncForIn(ast.AsyncForIn node) { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7453 HInstruction addInstruction = | 7458 HInstruction addInstruction = |
| 7454 new HAdd(index, one, null, backend.positiveIntType); | 7459 new HAdd(index, one, null, backend.positiveIntType); |
| 7455 add(addInstruction); | 7460 add(addInstruction); |
| 7456 localsHandler.updateLocal(indexVariable, addInstruction); | 7461 localsHandler.updateLocal(indexVariable, addInstruction); |
| 7457 } | 7462 } |
| 7458 | 7463 |
| 7459 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); | 7464 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); |
| 7460 } | 7465 } |
| 7461 | 7466 |
| 7462 visitLabel(ast.Label node) { | 7467 visitLabel(ast.Label node) { |
| 7463 compiler.internalError(node, 'SsaFromAstMixin.visitLabel.'); | 7468 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.'); |
| 7464 } | 7469 } |
| 7465 | 7470 |
| 7466 visitLabeledStatement(ast.LabeledStatement node) { | 7471 visitLabeledStatement(ast.LabeledStatement node) { |
| 7467 ast.Statement body = node.statement; | 7472 ast.Statement body = node.statement; |
| 7468 if (body is ast.Loop | 7473 if (body is ast.Loop |
| 7469 || body is ast.SwitchStatement | 7474 || body is ast.SwitchStatement |
| 7470 || Elements.isUnusedLabel(node, elements)) { | 7475 || Elements.isUnusedLabel(node, elements)) { |
| 7471 // Loops and switches handle their own labels. | 7476 // Loops and switches handle their own labels. |
| 7472 visit(body); | 7477 visit(body); |
| 7473 return; | 7478 return; |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7783 if (!isAborted()) { | 7788 if (!isAborted()) { |
| 7784 // Ensure that we break the loop if the case falls through. (This | 7789 // Ensure that we break the loop if the case falls through. (This |
| 7785 // is only possible for the last case.) | 7790 // is only possible for the last case.) |
| 7786 jumpTargets[switchTarget].generateBreak(); | 7791 jumpTargets[switchTarget].generateBreak(); |
| 7787 } | 7792 } |
| 7788 } | 7793 } |
| 7789 // Pass a [NullJumpHandler] because the target for the contained break | 7794 // Pass a [NullJumpHandler] because the target for the contained break |
| 7790 // is not the generated switch statement but instead the loop generated | 7795 // is not the generated switch statement but instead the loop generated |
| 7791 // in the call to [handleLoop] below. | 7796 // in the call to [handleLoop] below. |
| 7792 handleSwitch(node, | 7797 handleSwitch(node, |
| 7793 new NullJumpHandler(compiler), | 7798 new NullJumpHandler(reporter), |
| 7794 buildExpression, node.cases, getConstants, | 7799 buildExpression, node.cases, getConstants, |
| 7795 (_) => false, // No case is default. | 7800 (_) => false, // No case is default. |
| 7796 buildSwitchCase); | 7801 buildSwitchCase); |
| 7797 } | 7802 } |
| 7798 | 7803 |
| 7799 void buildLoop() { | 7804 void buildLoop() { |
| 7800 handleLoop(node, | 7805 handleLoop(node, |
| 7801 () {}, | 7806 () {}, |
| 7802 buildCondition, | 7807 buildCondition, |
| 7803 () {}, | 7808 () {}, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7950 new HSwitchBlockInformation(expressionInfo, | 7955 new HSwitchBlockInformation(expressionInfo, |
| 7951 statements, | 7956 statements, |
| 7952 jumpHandler.target, | 7957 jumpHandler.target, |
| 7953 jumpHandler.labels()), | 7958 jumpHandler.labels()), |
| 7954 joinBlock); | 7959 joinBlock); |
| 7955 | 7960 |
| 7956 jumpHandler.close(); | 7961 jumpHandler.close(); |
| 7957 } | 7962 } |
| 7958 | 7963 |
| 7959 visitSwitchCase(ast.SwitchCase node) { | 7964 visitSwitchCase(ast.SwitchCase node) { |
| 7960 compiler.internalError(node, 'SsaFromAstMixin.visitSwitchCase.'); | 7965 reporter.internalError(node, 'SsaFromAstMixin.visitSwitchCase.'); |
| 7961 } | 7966 } |
| 7962 | 7967 |
| 7963 visitCaseMatch(ast.CaseMatch node) { | 7968 visitCaseMatch(ast.CaseMatch node) { |
| 7964 compiler.internalError(node, 'SsaFromAstMixin.visitCaseMatch.'); | 7969 reporter.internalError(node, 'SsaFromAstMixin.visitCaseMatch.'); |
| 7965 } | 7970 } |
| 7966 | 7971 |
| 7967 /// Calls [buildTry] inside a synthetic try block with [buildFinally] in the | 7972 /// Calls [buildTry] inside a synthetic try block with [buildFinally] in the |
| 7968 /// finally block. | 7973 /// finally block. |
| 7969 /// | 7974 /// |
| 7970 /// Note that to get the right locals behavior, the code visited by [buildTry] | 7975 /// Note that to get the right locals behavior, the code visited by [buildTry] |
| 7971 /// and [buildFinally] must have been analyzed as if inside a try-statement by | 7976 /// and [buildFinally] must have been analyzed as if inside a try-statement by |
| 7972 /// [ClosureTranslator]. | 7977 /// [ClosureTranslator]. |
| 7973 void buildProtectedByFinally(void buildTry(), void buildFinally()) { | 7978 void buildProtectedByFinally(void buildTry(), void buildFinally()) { |
| 7974 // Save the current locals. The finally block must not reuse the existing | 7979 // Save the current locals. The finally block must not reuse the existing |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8105 | 8110 |
| 8106 pushInvokeStatic(node, backend.getExceptionUnwrapper(), [exception]); | 8111 pushInvokeStatic(node, backend.getExceptionUnwrapper(), [exception]); |
| 8107 HInvokeStatic unwrappedException = pop(); | 8112 HInvokeStatic unwrappedException = pop(); |
| 8108 tryInstruction.exception = exception; | 8113 tryInstruction.exception = exception; |
| 8109 Link<ast.Node> link = node.catchBlocks.nodes; | 8114 Link<ast.Node> link = node.catchBlocks.nodes; |
| 8110 | 8115 |
| 8111 void pushCondition(ast.CatchBlock catchBlock) { | 8116 void pushCondition(ast.CatchBlock catchBlock) { |
| 8112 if (catchBlock.onKeyword != null) { | 8117 if (catchBlock.onKeyword != null) { |
| 8113 DartType type = elements.getType(catchBlock.type); | 8118 DartType type = elements.getType(catchBlock.type); |
| 8114 if (type == null) { | 8119 if (type == null) { |
| 8115 compiler.internalError(catchBlock.type, 'On with no type.'); | 8120 reporter.internalError(catchBlock.type, 'On with no type.'); |
| 8116 } | 8121 } |
| 8117 HInstruction condition = | 8122 HInstruction condition = |
| 8118 buildIsNode(catchBlock.type, type, unwrappedException); | 8123 buildIsNode(catchBlock.type, type, unwrappedException); |
| 8119 push(condition); | 8124 push(condition); |
| 8120 } else { | 8125 } else { |
| 8121 ast.VariableDefinitions declaration = catchBlock.formals.nodes.head; | 8126 ast.VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 8122 HInstruction condition = null; | 8127 HInstruction condition = null; |
| 8123 if (declaration.type == null) { | 8128 if (declaration.type == null) { |
| 8124 condition = graph.addConstantBool(true, compiler); | 8129 condition = graph.addConstantBool(true, compiler); |
| 8125 stack.add(condition); | 8130 stack.add(condition); |
| 8126 } else { | 8131 } else { |
| 8127 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 8132 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 8128 // "if" condition above and this "else" branch should be deleted as | 8133 // "if" condition above and this "else" branch should be deleted as |
| 8129 // type of declared variable won't matter for the catch | 8134 // type of declared variable won't matter for the catch |
| 8130 // condition. | 8135 // condition. |
| 8131 DartType type = elements.getType(declaration.type); | 8136 DartType type = elements.getType(declaration.type); |
| 8132 if (type == null) { | 8137 if (type == null) { |
| 8133 compiler.internalError(catchBlock, 'Catch with unresolved type.'); | 8138 reporter.internalError(catchBlock, 'Catch with unresolved type.'); |
| 8134 } | 8139 } |
| 8135 condition = buildIsNode(declaration.type, type, unwrappedException); | 8140 condition = buildIsNode(declaration.type, type, unwrappedException); |
| 8136 push(condition); | 8141 push(condition); |
| 8137 } | 8142 } |
| 8138 } | 8143 } |
| 8139 } | 8144 } |
| 8140 | 8145 |
| 8141 void visitThen() { | 8146 void visitThen() { |
| 8142 ast.CatchBlock catchBlock = link.head; | 8147 ast.CatchBlock catchBlock = link.head; |
| 8143 link = link.tail; | 8148 link = link.tail; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8262 | 8267 |
| 8263 visitCatchBlock(ast.CatchBlock node) { | 8268 visitCatchBlock(ast.CatchBlock node) { |
| 8264 visit(node.block); | 8269 visit(node.block); |
| 8265 } | 8270 } |
| 8266 | 8271 |
| 8267 visitTypedef(ast.Typedef node) { | 8272 visitTypedef(ast.Typedef node) { |
| 8268 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); | 8273 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); |
| 8269 } | 8274 } |
| 8270 | 8275 |
| 8271 visitTypeVariable(ast.TypeVariable node) { | 8276 visitTypeVariable(ast.TypeVariable node) { |
| 8272 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); | 8277 reporter.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); |
| 8273 } | 8278 } |
| 8274 | 8279 |
| 8275 /** | 8280 /** |
| 8276 * This method is invoked before inlining the body of [function] into this | 8281 * This method is invoked before inlining the body of [function] into this |
| 8277 * [SsaBuilder]. | 8282 * [SsaBuilder]. |
| 8278 */ | 8283 */ |
| 8279 void enterInlinedMethod(FunctionElement function, | 8284 void enterInlinedMethod(FunctionElement function, |
| 8280 ast.Node _, | 8285 ast.Node _, |
| 8281 List<HInstruction> compiledArguments, | 8286 List<HInstruction> compiledArguments, |
| 8282 {InterfaceType instanceType}) { | 8287 {InterfaceType instanceType}) { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8399 | 8404 |
| 8400 StringBuilderVisitor(this.builder, this.diagnosticNode); | 8405 StringBuilderVisitor(this.builder, this.diagnosticNode); |
| 8401 | 8406 |
| 8402 Compiler get compiler => builder.compiler; | 8407 Compiler get compiler => builder.compiler; |
| 8403 | 8408 |
| 8404 void visit(ast.Node node) { | 8409 void visit(ast.Node node) { |
| 8405 node.accept(this); | 8410 node.accept(this); |
| 8406 } | 8411 } |
| 8407 | 8412 |
| 8408 visitNode(ast.Node node) { | 8413 visitNode(ast.Node node) { |
| 8409 builder.compiler.internalError(node, 'Unexpected node.'); | 8414 builder.reporter.internalError(node, 'Unexpected node.'); |
| 8410 } | 8415 } |
| 8411 | 8416 |
| 8412 void visitExpression(ast.Node node) { | 8417 void visitExpression(ast.Node node) { |
| 8413 node.accept(builder); | 8418 node.accept(builder); |
| 8414 HInstruction expression = builder.pop(); | 8419 HInstruction expression = builder.pop(); |
| 8415 | 8420 |
| 8416 // We want to use HStringify when: | 8421 // We want to use HStringify when: |
| 8417 // 1. The value is known to be a primitive type, because it might get | 8422 // 1. The value is known to be a primitive type, because it might get |
| 8418 // constant-folded and codegen has some tricks with JavaScript | 8423 // constant-folded and codegen has some tricks with JavaScript |
| 8419 // conversions. | 8424 // conversions. |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8991 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8996 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 8992 unaliased.accept(this, builder); | 8997 unaliased.accept(this, builder); |
| 8993 } | 8998 } |
| 8994 | 8999 |
| 8995 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 9000 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 8996 JavaScriptBackend backend = builder.compiler.backend; | 9001 JavaScriptBackend backend = builder.compiler.backend; |
| 8997 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 9002 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 8998 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 9003 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 8999 } | 9004 } |
| 9000 } | 9005 } |
| OLD | NEW |