Chromium Code Reviews| 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 |