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 |