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 SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
8 | 8 |
9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
10 | 10 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
45 return node.withPosition(sourcePosition, endSourcePosition); | 45 return node.withPosition(sourcePosition, endSourcePosition); |
46 } | 46 } |
47 | 47 |
48 SourceFile sourceFileOfElement(Element element) { | 48 SourceFile sourceFileOfElement(Element element) { |
49 return element.implementation.compilationUnit.script.file; | 49 return element.implementation.compilationUnit.script.file; |
50 } | 50 } |
51 | 51 |
52 js.Fun buildJavaScriptFunction(FunctionElement element, | 52 js.Fun buildJavaScriptFunction(FunctionElement element, |
53 List<js.Parameter> parameters, | 53 List<js.Parameter> parameters, |
54 js.Block body) { | 54 js.Block body) { |
55 return attachPosition(new js.Fun(parameters, body), element); | 55 js.AsyncModifier asyncModifier = element.asyncMarker.isAsync |
56 ? (element.asyncMarker.isYielding | |
57 ? const js.AsyncModifier.asyncStar() | |
58 : const js.AsyncModifier.async()) | |
59 : (element.asyncMarker.isYielding | |
60 ? const js.AsyncModifier.syncStar() | |
61 : const js.AsyncModifier.sync()); | |
62 | |
63 return attachPosition( | |
64 new js.Fun(parameters, body, asyncModifier: asyncModifier), element); | |
56 } | 65 } |
57 | 66 |
58 js.Expression generateCode(CodegenWorkItem work, HGraph graph) { | 67 js.Expression generateCode(CodegenWorkItem work, HGraph graph) { |
59 if (work.element.isField) { | 68 if (work.element.isField) { |
60 return generateLazyInitializer(work, graph); | 69 return generateLazyInitializer(work, graph); |
61 } else { | 70 } else { |
62 return generateMethod(work, graph); | 71 return generateMethod(work, graph); |
63 } | 72 } |
64 } | 73 } |
65 | 74 |
66 js.Expression generateLazyInitializer(work, graph) { | 75 js.Expression generateLazyInitializer(work, graph) { |
67 return measure(() { | 76 return measure(() { |
68 compiler.tracer.traceGraph("codegen", graph); | 77 compiler.tracer.traceGraph("codegen", graph); |
69 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); | 78 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); |
70 codegen.visitGraph(graph); | 79 codegen.visitGraph(graph); |
71 return new js.Fun(codegen.parameters, | 80 return new js.Fun(codegen.parameters, |
72 attachPosition(codegen.body, work.element)); | 81 attachPosition(codegen.body, work.element)); |
73 }); | 82 }); |
74 } | 83 } |
75 | 84 |
76 js.Expression generateMethod(CodegenWorkItem work, HGraph graph) { | 85 js.Expression generateMethod(CodegenWorkItem work, HGraph graph) { |
77 return measure(() { | 86 return measure(() { |
87 Element element = work.element; | |
88 if (element is FunctionElement && | |
89 element.asyncMarker != AsyncMarker.SYNC) { | |
90 work.registry.registerAsyncMarker(element); | |
91 } | |
78 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); | 92 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); |
79 codegen.visitGraph(graph); | 93 codegen.visitGraph(graph); |
80 compiler.tracer.traceGraph("codegen", graph); | 94 compiler.tracer.traceGraph("codegen", graph); |
81 FunctionElement element = work.element; | |
82 return buildJavaScriptFunction(element, codegen.parameters, codegen.body); | 95 return buildJavaScriptFunction(element, codegen.parameters, codegen.body); |
83 }); | 96 }); |
84 } | 97 } |
85 } | 98 } |
86 | 99 |
87 typedef void EntityAction(Entity element); | 100 typedef void EntityAction(Entity element); |
88 | 101 |
89 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { | 102 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
90 /** | 103 /** |
91 * Returned by [expressionType] to tell how code can be generated for | 104 * Returned by [expressionType] to tell how code can be generated for |
(...skipping 1870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1962 | 1975 |
1963 visitThrow(HThrow node) { | 1976 visitThrow(HThrow node) { |
1964 if (node.isRethrow) { | 1977 if (node.isRethrow) { |
1965 use(node.inputs[0]); | 1978 use(node.inputs[0]); |
1966 pushStatement(new js.Throw(pop()), node); | 1979 pushStatement(new js.Throw(pop()), node); |
1967 } else { | 1980 } else { |
1968 generateThrowWithHelper('wrapException', node.inputs[0]); | 1981 generateThrowWithHelper('wrapException', node.inputs[0]); |
1969 } | 1982 } |
1970 } | 1983 } |
1971 | 1984 |
1985 visitAwait(HAwait node) { | |
1986 use(node.inputs[0]); | |
1987 push(new js.Await(pop()), node); | |
1988 } | |
1989 | |
1990 visitYield(HYield node) { | |
1991 use(node.inputs[0]); | |
1992 pushStatement(new js.DartYield(pop(), node.hasStar), node); | |
1993 } | |
1994 | |
1972 visitRangeConversion(HRangeConversion node) { | 1995 visitRangeConversion(HRangeConversion node) { |
1973 // Range conversion instructions are removed by the value range | 1996 // Range conversion instructions are removed by the value range |
1974 // analyzer. | 1997 // analyzer. |
1975 assert(false); | 1998 assert(false); |
1976 } | 1999 } |
1977 | 2000 |
1978 visitBoundsCheck(HBoundsCheck node) { | 2001 visitBoundsCheck(HBoundsCheck node) { |
1979 // TODO(ngeoffray): Separate the two checks of the bounds check, so, | 2002 // TODO(ngeoffray): Separate the two checks of the bounds check, so, |
1980 // e.g., the zero checks can be shared if possible. | 2003 // e.g., the zero checks can be shared if possible. |
1981 | 2004 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2040 arguments.add(pop()); | 2063 arguments.add(pop()); |
2041 } | 2064 } |
2042 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false)); | 2065 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false)); |
2043 value = attachLocation(value, location); | 2066 value = attachLocation(value, location); |
2044 // BUG(4906): Using throw/return here adds to the size of the generated code | 2067 // BUG(4906): Using throw/return here adds to the size of the generated code |
2045 // but it has the advantage of explicitly telling the JS engine that | 2068 // but it has the advantage of explicitly telling the JS engine that |
2046 // this code path will terminate abruptly. Needs more work. | 2069 // this code path will terminate abruptly. Needs more work. |
2047 if (helperName == 'wrapException') { | 2070 if (helperName == 'wrapException') { |
2048 pushStatement(new js.Throw(value)); | 2071 pushStatement(new js.Throw(value)); |
2049 } else { | 2072 } else { |
2050 pushStatement(new js.Return(value)); | 2073 Element element = work.element; |
2074 if (element is FunctionElement && element.asyncMarker.isYielding) { | |
2075 // `return <expr>;` is illegal in a sync* or async* function. | |
floitsch
2015/02/04 12:31:28
That's not true.
It's legal, but you cannot "abuse
sigurdm
2015/02/05 14:06:04
I think it is true. (spec p. 109 reads: It is a co
| |
2076 pushStatement(new js.ExpressionStatement(value)); | |
2077 } else { | |
2078 pushStatement(new js.Return(value)); | |
2079 } | |
2051 } | 2080 } |
2052 } | 2081 } |
2053 | 2082 |
2054 visitThrowExpression(HThrowExpression node) { | 2083 visitThrowExpression(HThrowExpression node) { |
2055 HInstruction argument = node.inputs[0]; | 2084 HInstruction argument = node.inputs[0]; |
2056 use(argument); | 2085 use(argument); |
2057 | 2086 |
2058 Element helper = backend.findHelper("throwExpression"); | 2087 Element helper = backend.findHelper("throwExpression"); |
2059 registry.registerStaticUse(helper); | 2088 registry.registerStaticUse(helper); |
2060 | 2089 |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2669 js.PropertyAccess accessHelper(String name) { | 2698 js.PropertyAccess accessHelper(String name) { |
2670 Element helper = backend.findHelper(name); | 2699 Element helper = backend.findHelper(name); |
2671 if (helper == null) { | 2700 if (helper == null) { |
2672 // For mocked-up tests. | 2701 // For mocked-up tests. |
2673 return js.js('(void 0).$name'); | 2702 return js.js('(void 0).$name'); |
2674 } | 2703 } |
2675 registry.registerStaticUse(helper); | 2704 registry.registerStaticUse(helper); |
2676 return backend.emitter.staticFunctionAccess(helper); | 2705 return backend.emitter.staticFunctionAccess(helper); |
2677 } | 2706 } |
2678 } | 2707 } |
OLD | NEW |