| 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 |