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 FunctionElement element = work.element; |
| 88 if (element.asyncMarker != AsyncMarker.SYNC) { |
| 89 work.registry.registerAsyncMarker(element); |
| 90 } |
78 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); | 91 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); |
79 codegen.visitGraph(graph); | 92 codegen.visitGraph(graph); |
80 compiler.tracer.traceGraph("codegen", graph); | 93 compiler.tracer.traceGraph("codegen", graph); |
81 FunctionElement element = work.element; | |
82 return buildJavaScriptFunction(element, codegen.parameters, codegen.body); | 94 return buildJavaScriptFunction(element, codegen.parameters, codegen.body); |
83 }); | 95 }); |
84 } | 96 } |
85 } | 97 } |
86 | 98 |
87 typedef void EntityAction(Entity element); | 99 typedef void EntityAction(Entity element); |
88 | 100 |
89 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { | 101 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
90 /** | 102 /** |
91 * Returned by [expressionType] to tell how code can be generated for | 103 * 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 | 1974 |
1963 visitThrow(HThrow node) { | 1975 visitThrow(HThrow node) { |
1964 if (node.isRethrow) { | 1976 if (node.isRethrow) { |
1965 use(node.inputs[0]); | 1977 use(node.inputs[0]); |
1966 pushStatement(new js.Throw(pop()), node); | 1978 pushStatement(new js.Throw(pop()), node); |
1967 } else { | 1979 } else { |
1968 generateThrowWithHelper('wrapException', node.inputs[0]); | 1980 generateThrowWithHelper('wrapException', node.inputs[0]); |
1969 } | 1981 } |
1970 } | 1982 } |
1971 | 1983 |
| 1984 visitAwait(HAwait node) { |
| 1985 use(node.inputs[0]); |
| 1986 push(new js.Await(pop()), node); |
| 1987 } |
| 1988 |
| 1989 visitYield(HYield node) { |
| 1990 use(node.inputs[0]); |
| 1991 pushStatement(new js.DartYield(pop(), node.hasStar), node); |
| 1992 } |
| 1993 |
1972 visitRangeConversion(HRangeConversion node) { | 1994 visitRangeConversion(HRangeConversion node) { |
1973 // Range conversion instructions are removed by the value range | 1995 // Range conversion instructions are removed by the value range |
1974 // analyzer. | 1996 // analyzer. |
1975 assert(false); | 1997 assert(false); |
1976 } | 1998 } |
1977 | 1999 |
1978 visitBoundsCheck(HBoundsCheck node) { | 2000 visitBoundsCheck(HBoundsCheck node) { |
1979 // TODO(ngeoffray): Separate the two checks of the bounds check, so, | 2001 // TODO(ngeoffray): Separate the two checks of the bounds check, so, |
1980 // e.g., the zero checks can be shared if possible. | 2002 // e.g., the zero checks can be shared if possible. |
1981 | 2003 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2040 arguments.add(pop()); | 2062 arguments.add(pop()); |
2041 } | 2063 } |
2042 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false)); | 2064 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false)); |
2043 value = attachLocation(value, location); | 2065 value = attachLocation(value, location); |
2044 // BUG(4906): Using throw/return here adds to the size of the generated code | 2066 // 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 | 2067 // but it has the advantage of explicitly telling the JS engine that |
2046 // this code path will terminate abruptly. Needs more work. | 2068 // this code path will terminate abruptly. Needs more work. |
2047 if (helperName == 'wrapException') { | 2069 if (helperName == 'wrapException') { |
2048 pushStatement(new js.Throw(value)); | 2070 pushStatement(new js.Throw(value)); |
2049 } else { | 2071 } else { |
2050 pushStatement(new js.Return(value)); | 2072 Element element = work.element; |
| 2073 if (element is FunctionElement && element.asyncMarker.isYielding) { |
| 2074 // `return <expr>;` is illegal in a sync* or async* function. |
| 2075 // To have the the async-translator working, we avoid introducing |
| 2076 // `return` nodes. |
| 2077 pushStatement(new js.ExpressionStatement(value)); |
| 2078 } else { |
| 2079 pushStatement(new js.Return(value)); |
| 2080 } |
2051 } | 2081 } |
2052 } | 2082 } |
2053 | 2083 |
2054 visitThrowExpression(HThrowExpression node) { | 2084 visitThrowExpression(HThrowExpression node) { |
2055 HInstruction argument = node.inputs[0]; | 2085 HInstruction argument = node.inputs[0]; |
2056 use(argument); | 2086 use(argument); |
2057 | 2087 |
2058 Element helper = backend.findHelper("throwExpression"); | 2088 Element helper = backend.findHelper("throwExpression"); |
2059 registry.registerStaticUse(helper); | 2089 registry.registerStaticUse(helper); |
2060 | 2090 |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2669 js.PropertyAccess accessHelper(String name) { | 2699 js.PropertyAccess accessHelper(String name) { |
2670 Element helper = backend.findHelper(name); | 2700 Element helper = backend.findHelper(name); |
2671 if (helper == null) { | 2701 if (helper == null) { |
2672 // For mocked-up tests. | 2702 // For mocked-up tests. |
2673 return js.js('(void 0).$name'); | 2703 return js.js('(void 0).$name'); |
2674 } | 2704 } |
2675 registry.registerStaticUse(helper); | 2705 registry.registerStaticUse(helper); |
2676 return backend.emitter.staticFunctionAccess(helper); | 2706 return backend.emitter.staticFunctionAccess(helper); |
2677 } | 2707 } |
2678 } | 2708 } |
OLD | NEW |