OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
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.md file. | |
4 | |
5 library fletchc.function_codegen; | |
6 | |
7 import 'package:compiler/src/resolution/tree_elements.dart' show | |
8 TreeElements; | |
9 | |
10 import 'package:compiler/src/elements/elements.dart'; | |
11 import 'package:compiler/src/tree/tree.dart'; | |
12 | |
13 import 'fletch_context.dart'; | |
14 | |
15 import 'fletch_function_builder.dart' show | |
16 FletchFunctionBuilder; | |
17 | |
18 import 'fletch_registry.dart' show | |
19 FletchRegistry; | |
20 | |
21 import 'closure_environment.dart'; | |
22 | |
23 import 'codegen_visitor.dart'; | |
24 | |
25 class FunctionCodegen extends CodegenVisitor with FletchRegistryMixin { | |
26 final FletchRegistry registry; | |
27 int setterResultSlot; | |
28 | |
29 FunctionCodegen(FletchFunctionBuilder functionBuilder, | |
30 FletchContext context, | |
31 TreeElements elements, | |
32 this.registry, | |
33 ClosureEnvironment closureEnvironment, | |
34 FunctionElement function) | |
35 : super(functionBuilder, context, elements, | |
36 closureEnvironment, function); | |
37 | |
38 FunctionElement get function => element; | |
39 | |
40 // If the function is a setter, push the argument to later be returned. | |
41 // TODO(ajohnsen): If the argument is semantically final, we don't have to | |
42 // do this. | |
43 bool get hasAssignmentSemantics => | |
44 function.isSetter || function.name == '[]='; | |
45 | |
46 void compile() { | |
47 if (checkCompileError(function)) { | |
48 assembler.methodEnd(); | |
49 return; | |
50 } | |
51 | |
52 ClassElement enclosing = function.enclosingClass; | |
53 // Generate implicit 'null' check for '==' functions. | |
54 if (enclosing != null && function.name == '==') { | |
55 BytecodeLabel notNull = new BytecodeLabel(); | |
56 assembler.loadParameter(1); | |
57 assembler.loadLiteralNull(); | |
58 assembler.identicalNonNumeric(); | |
59 assembler.branchIfFalse(notNull); | |
60 // TODO(ajohnsen): Consider creating an injected operator== into 'null', | |
61 // to avoid this extra check. | |
62 assembler.loadParameter(0); | |
63 assembler.loadLiteralNull(); | |
64 assembler.identicalNonNumeric(); | |
65 assembler.ret(); | |
66 assembler.bind(notNull); | |
67 } | |
68 | |
69 FunctionSignature functionSignature = function.functionSignature; | |
70 int parameterCount = functionSignature.parameterCount; | |
71 | |
72 if (hasAssignmentSemantics) { | |
73 setterResultSlot = assembler.stackSize; | |
74 // The result is always the last argument. | |
75 assembler.loadParameter(functionBuilder.arity - 1); | |
76 } | |
77 | |
78 // Skip 'this' if present. | |
79 int parameterIndex = functionBuilder.arity - parameterCount; | |
80 | |
81 functionSignature.orderedForEachParameter((ParameterElement parameter) { | |
82 // For constructors, the argument is passed as boxed (from the initializer | |
83 // inlining). | |
84 LocalValue value = createLocalValueForParameter( | |
85 parameter, | |
86 parameterIndex, | |
87 isCapturedValueBoxed: element.isGenerativeConstructor); | |
88 pushVariableDeclaration(value); | |
89 parameterIndex++; | |
90 }); | |
91 | |
92 ClosureInfo info = closureEnvironment.closures[function]; | |
93 if (info != null) { | |
94 int index = 0; | |
95 if (info.isThisFree) { | |
96 thisValue = new UnboxedLocalValue(assembler.stackSize, null); | |
97 assembler.loadParameter(0); | |
98 assembler.loadField(index++); | |
99 } | |
100 for (LocalElement local in info.free) { | |
101 pushVariableDeclaration(createLocalValueFor(local)); | |
102 // TODO(ajohnsen): Use a specialized helper for loading the closure. | |
103 assembler.loadParameter(0); | |
104 assembler.loadField(index++); | |
105 } | |
106 } | |
107 | |
108 FunctionExpression node = function.node; | |
109 if (node != null) { | |
110 node.body.accept(this); | |
111 } | |
112 | |
113 // Emit implicit 'return null' if no terminator is present. | |
114 if (!assembler.endsWithTerminator) generateImplicitReturn(node); | |
115 | |
116 assembler.methodEnd(); | |
117 } | |
118 | |
119 void generateImplicitReturn(FunctionExpression node) { | |
120 if (hasAssignmentSemantics) { | |
121 assembler.loadSlot(setterResultSlot); | |
122 assembler.ret(); | |
123 } else { | |
124 assembler.returnNull(); | |
125 } | |
126 } | |
127 | |
128 void optionalReplaceResultValue() { | |
129 if (hasAssignmentSemantics) { | |
130 assembler.pop(); | |
131 assembler.loadSlot(setterResultSlot); | |
132 } | |
133 } | |
134 } | |
OLD | NEW |