OLD | NEW |
1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 library fletchc.compiled_function; | 5 library fletchc.compiled_function; |
6 | 6 |
7 import 'package:compiler/src/constants/values.dart' show | 7 import 'package:compiler/src/constants/values.dart' show |
8 ConstantValue; | 8 ConstantValue; |
9 | 9 |
10 import 'package:compiler/src/constants/expressions.dart' show | 10 import 'package:compiler/src/constants/expressions.dart' show |
11 ConstantExpression; | 11 ConstantExpression; |
12 | 12 |
13 import 'package:compiler/src/tree/tree.dart' show | 13 import 'package:compiler/src/tree/tree.dart' show |
14 Expression; | 14 Expression; |
15 | 15 |
16 import 'package:compiler/src/elements/elements.dart'; | 16 import 'package:compiler/src/elements/elements.dart'; |
17 | 17 |
18 import 'fletch_constants.dart' show | 18 import 'fletch_constants.dart' show |
19 FletchFunctionConstant, | 19 FletchFunctionConstant, |
20 FletchClassConstant; | 20 FletchClassConstant; |
21 | 21 |
22 import 'package:compiler/src/universe/universe.dart' | 22 import 'package:compiler/src/universe/universe.dart' |
23 show Selector; | 23 show Selector; |
24 | 24 |
25 import '../bytecodes.dart' show | 25 import '../bytecodes.dart' show |
26 Bytecode; | 26 Bytecode; |
27 | 27 |
28 import 'compiled_class.dart' show | 28 import 'fletch_class_builder.dart' show |
29 CompiledClass; | 29 FletchClassBuilder; |
30 | 30 |
31 import 'fletch_context.dart'; | 31 import 'fletch_context.dart'; |
32 import 'bytecode_builder.dart'; | 32 import 'bytecode_builder.dart'; |
33 import 'debug_info.dart'; | 33 import 'debug_info.dart'; |
34 | 34 |
35 enum CompiledFunctionKind { | 35 enum FletchFunctionBuilderKind { |
36 NORMAL, | 36 NORMAL, |
37 LAZY_FIELD_INITIALIZER, | 37 LAZY_FIELD_INITIALIZER, |
38 INITIALIZER_LIST, | 38 INITIALIZER_LIST, |
39 PARAMETER_STUB, | 39 PARAMETER_STUB, |
40 ACCESSOR | 40 ACCESSOR |
41 } | 41 } |
42 | 42 |
43 class CompiledFunction { | 43 class FletchFunctionBuilder { |
44 final BytecodeBuilder builder; | 44 final BytecodeBuilder builder; |
45 final int methodId; | 45 final int methodId; |
46 | 46 |
47 /** | 47 /** |
48 * The signature of the CompiledFunction. | 48 * The signature of the FletchFunctionBuilder. |
49 * | 49 * |
50 * Som compiled functions does not have a signature (for example, generated | 50 * Som compiled functions does not have a signature (for example, generated |
51 * accessors). | 51 * accessors). |
52 */ | 52 */ |
53 final FunctionSignature signature; | 53 final FunctionSignature signature; |
54 | 54 |
55 /** | 55 /** |
56 * If the functions is an instance member, [memberOf] is set to the compiled | 56 * If the functions is an instance member, [memberOf] is set to the compiled |
57 * class. | 57 * class. |
58 * | 58 * |
59 * If [memberOf] is set, the compiled function takes an 'this' argument in | 59 * If [memberOf] is set, the compiled function takes an 'this' argument in |
60 * addition to that of [signature]. | 60 * addition to that of [signature]. |
61 */ | 61 */ |
62 final CompiledClass memberOf; | 62 final FletchClassBuilder memberOf; |
63 final String name; | 63 final String name; |
64 final Element element; | 64 final Element element; |
65 final Map<ConstantValue, int> constants = <ConstantValue, int>{}; | 65 final Map<ConstantValue, int> constants = <ConstantValue, int>{}; |
66 final Map<int, ConstantValue> functionConstantValues = <int, ConstantValue>{}; | 66 final Map<int, ConstantValue> functionConstantValues = <int, ConstantValue>{}; |
67 final Map<int, ConstantValue> classConstantValues = <int, ConstantValue>{}; | 67 final Map<int, ConstantValue> classConstantValues = <int, ConstantValue>{}; |
68 final Map<Selector, CompiledFunction> parameterMappings = | 68 final Map<Selector, FletchFunctionBuilder> parameterMappings = |
69 <Selector, CompiledFunction>{}; | 69 <Selector, FletchFunctionBuilder>{}; |
70 final int arity; | 70 final int arity; |
71 final CompiledFunctionKind kind; | 71 final FletchFunctionBuilderKind kind; |
72 | 72 |
73 DebugInfo debugInfo; | 73 DebugInfo debugInfo; |
74 | 74 |
75 CompiledFunction(this.methodId, | 75 FletchFunctionBuilder(this.methodId, |
76 this.name, | 76 this.name, |
77 this.element, | 77 this.element, |
78 FunctionSignature signature, | 78 FunctionSignature signature, |
79 CompiledClass memberOf, | 79 FletchClassBuilder memberOf, |
80 {this.kind: CompiledFunctionKind.NORMAL}) | 80 {this.kind: FletchFunctionBuilderKind.NORMAL}) |
81 : this.signature = signature, | 81 : this.signature = signature, |
82 this.memberOf = memberOf, | 82 this.memberOf = memberOf, |
83 arity = signature.parameterCount + (memberOf != null ? 1 : 0), | 83 arity = signature.parameterCount + (memberOf != null ? 1 : 0), |
84 builder = new BytecodeBuilder( | 84 builder = new BytecodeBuilder( |
85 signature.parameterCount + (memberOf != null ? 1 : 0)); | 85 signature.parameterCount + (memberOf != null ? 1 : 0)); |
86 | 86 |
87 CompiledFunction.normal(this.methodId, int argumentCount) | 87 FletchFunctionBuilder.normal(this.methodId, int argumentCount) |
88 : arity = argumentCount, | 88 : arity = argumentCount, |
89 builder = new BytecodeBuilder(argumentCount), | 89 builder = new BytecodeBuilder(argumentCount), |
90 kind = CompiledFunctionKind.NORMAL; | 90 kind = FletchFunctionBuilderKind.NORMAL; |
91 | 91 |
92 CompiledFunction.lazyInit(this.methodId, | 92 FletchFunctionBuilder.lazyInit(this.methodId, |
93 this.name, | 93 this.name, |
94 this.element, | 94 this.element, |
95 int argumentCount) | 95 int argumentCount) |
96 : arity = argumentCount, | 96 : arity = argumentCount, |
97 builder = new BytecodeBuilder(argumentCount), | 97 builder = new BytecodeBuilder(argumentCount), |
98 kind = CompiledFunctionKind.LAZY_FIELD_INITIALIZER; | 98 kind = FletchFunctionBuilderKind.LAZY_FIELD_INITIALIZER; |
99 | 99 |
100 CompiledFunction.parameterStub(this.methodId, int argumentCount) | 100 FletchFunctionBuilder.parameterStub(this.methodId, int argumentCount) |
101 : arity = argumentCount, | 101 : arity = argumentCount, |
102 builder = new BytecodeBuilder(argumentCount), | 102 builder = new BytecodeBuilder(argumentCount), |
103 kind = CompiledFunctionKind.PARAMETER_STUB; | 103 kind = FletchFunctionBuilderKind.PARAMETER_STUB; |
104 | 104 |
105 CompiledFunction.accessor(this.methodId, bool setter) | 105 FletchFunctionBuilder.accessor(this.methodId, bool setter) |
106 : arity = setter ? 2 : 1, | 106 : arity = setter ? 2 : 1, |
107 builder = new BytecodeBuilder(setter ? 2 : 1), | 107 builder = new BytecodeBuilder(setter ? 2 : 1), |
108 kind = CompiledFunctionKind.ACCESSOR; | 108 kind = FletchFunctionBuilderKind.ACCESSOR; |
109 | 109 |
110 void reuse() { | 110 void reuse() { |
111 builder.reuse(); | 111 builder.reuse(); |
112 constants.clear(); | 112 constants.clear(); |
113 functionConstantValues.clear(); | 113 functionConstantValues.clear(); |
114 classConstantValues.clear(); | 114 classConstantValues.clear(); |
115 } | 115 } |
116 | 116 |
117 bool get hasThisArgument => memberOf != null; | 117 bool get hasThisArgument => memberOf != null; |
118 | 118 |
119 bool get isLazyFieldInitializer { | 119 bool get isLazyFieldInitializer { |
120 return kind == CompiledFunctionKind.LAZY_FIELD_INITIALIZER; | 120 return kind == FletchFunctionBuilderKind.LAZY_FIELD_INITIALIZER; |
121 } | 121 } |
122 | 122 |
123 bool get isInitializerList { | 123 bool get isInitializerList { |
124 return kind == CompiledFunctionKind.INITIALIZER_LIST; | 124 return kind == FletchFunctionBuilderKind.INITIALIZER_LIST; |
125 } | 125 } |
126 | 126 |
127 bool get isAccessor { | 127 bool get isAccessor { |
128 return kind == CompiledFunctionKind.ACCESSOR; | 128 return kind == FletchFunctionBuilderKind.ACCESSOR; |
129 } | 129 } |
130 | 130 |
131 bool get isParameterStub { | 131 bool get isParameterStub { |
132 return kind == CompiledFunctionKind.PARAMETER_STUB; | 132 return kind == FletchFunctionBuilderKind.PARAMETER_STUB; |
133 } | 133 } |
134 | 134 |
135 bool get isConstructor => element != null && element.isConstructor; | 135 bool get isConstructor => element != null && element.isConstructor; |
136 | 136 |
137 int allocateConstant(ConstantValue constant) { | 137 int allocateConstant(ConstantValue constant) { |
138 if (constant == null) throw "bad constant"; | 138 if (constant == null) throw "bad constant"; |
139 return constants.putIfAbsent(constant, () => constants.length); | 139 return constants.putIfAbsent(constant, () => constants.length); |
140 } | 140 } |
141 | 141 |
142 int allocateConstantFromFunction(int methodId) { | 142 int allocateConstantFromFunction(int methodId) { |
143 FletchFunctionConstant constant = | 143 FletchFunctionConstant constant = |
144 functionConstantValues.putIfAbsent( | 144 functionConstantValues.putIfAbsent( |
145 methodId, () => new FletchFunctionConstant(methodId)); | 145 methodId, () => new FletchFunctionConstant(methodId)); |
146 return allocateConstant(constant); | 146 return allocateConstant(constant); |
147 } | 147 } |
148 | 148 |
149 int allocateConstantFromClass(int classId) { | 149 int allocateConstantFromClass(int classId) { |
150 FletchClassConstant constant = | 150 FletchClassConstant constant = |
151 classConstantValues.putIfAbsent( | 151 classConstantValues.putIfAbsent( |
152 classId, () => new FletchClassConstant(classId)); | 152 classId, () => new FletchClassConstant(classId)); |
153 return allocateConstant(constant); | 153 return allocateConstant(constant); |
154 } | 154 } |
155 | 155 |
156 // TODO(ajohnsen): Remove this function when usage is avoided in | 156 // TODO(ajohnsen): Remove this function when usage is avoided in |
157 // FletchBackend. | 157 // FletchBackend. |
158 void copyFrom(CompiledFunction function) { | 158 void copyFrom(FletchFunctionBuilder function) { |
159 builder.bytecodes.addAll(function.builder.bytecodes); | 159 builder.bytecodes.addAll(function.builder.bytecodes); |
160 builder.catchRanges.addAll(function.builder.catchRanges); | 160 builder.catchRanges.addAll(function.builder.catchRanges); |
161 constants.addAll(function.constants); | 161 constants.addAll(function.constants); |
162 functionConstantValues.addAll(function.functionConstantValues); | 162 functionConstantValues.addAll(function.functionConstantValues); |
163 classConstantValues.addAll(function.classConstantValues); | 163 classConstantValues.addAll(function.classConstantValues); |
164 } | 164 } |
165 | 165 |
166 bool matchesSelector(Selector selector) { | 166 bool matchesSelector(Selector selector) { |
167 if (!canBeCalledAs(selector)) return false; | 167 if (!canBeCalledAs(selector)) return false; |
168 if (selector.namedArguments.length != signature.optionalParameterCount) { | 168 if (selector.namedArguments.length != signature.optionalParameterCount) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 if (!nameSet.contains(name)) return false; | 206 if (!nameSet.contains(name)) return false; |
207 // TODO(5213): By removing from the set we are checking | 207 // TODO(5213): By removing from the set we are checking |
208 // that we are not passing the name twice. We should have this | 208 // that we are not passing the name twice. We should have this |
209 // check in the resolver also. | 209 // check in the resolver also. |
210 nameSet.remove(name); | 210 nameSet.remove(name); |
211 } | 211 } |
212 return true; | 212 return true; |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 CompiledFunction createParameterMappingFor( | 216 FletchFunctionBuilder createParameterMappingFor( |
217 Selector selector, | 217 Selector selector, |
218 FletchContext context) { | 218 FletchContext context) { |
219 return parameterMappings.putIfAbsent(selector, () { | 219 return parameterMappings.putIfAbsent(selector, () { |
220 assert(canBeCalledAs(selector)); | 220 assert(canBeCalledAs(selector)); |
221 int arity = selector.argumentCount; | 221 int arity = selector.argumentCount; |
222 if (hasThisArgument) arity++; | 222 if (hasThisArgument) arity++; |
223 | 223 |
224 CompiledFunction compiledFunction = new CompiledFunction.parameterStub( | 224 FletchFunctionBuilder functionBuilder = |
225 context.backend.functions.length, | 225 new FletchFunctionBuilder.parameterStub( |
226 arity); | 226 context.backend.functions.length, |
227 context.backend.functions.add(compiledFunction); | 227 arity); |
| 228 context.backend.functions.add(functionBuilder); |
228 | 229 |
229 BytecodeBuilder builder = compiledFunction.builder; | 230 BytecodeBuilder builder = functionBuilder.builder; |
230 | 231 |
231 void loadInitializerOrNull(ParameterElement parameter) { | 232 void loadInitializerOrNull(ParameterElement parameter) { |
232 Expression initializer = parameter.initializer; | 233 Expression initializer = parameter.initializer; |
233 if (initializer != null) { | 234 if (initializer != null) { |
234 ConstantExpression expression = context.compileConstant( | 235 ConstantExpression expression = context.compileConstant( |
235 initializer, | 236 initializer, |
236 parameter.memberContext.resolvedAst.elements, | 237 parameter.memberContext.resolvedAst.elements, |
237 isConst: true); | 238 isConst: true); |
238 int constId = compiledFunction.allocateConstant( | 239 int constId = functionBuilder.allocateConstant( |
239 context.getConstantValue(expression)); | 240 context.getConstantValue(expression)); |
240 builder.loadConst(constId); | 241 builder.loadConst(constId); |
241 } else { | 242 } else { |
242 builder.loadLiteralNull(); | 243 builder.loadLiteralNull(); |
243 } | 244 } |
244 } | 245 } |
245 | 246 |
246 // Load this. | 247 // Load this. |
247 if (hasThisArgument) builder.loadParameter(0); | 248 if (hasThisArgument) builder.loadParameter(0); |
248 | 249 |
(...skipping 17 matching lines...) Expand all Loading... |
266 loadInitializerOrNull(parameter); | 267 loadInitializerOrNull(parameter); |
267 } | 268 } |
268 } | 269 } |
269 index++; | 270 index++; |
270 }); | 271 }); |
271 | 272 |
272 // TODO(ajohnsen): We have to be extra careful when overriding a | 273 // TODO(ajohnsen): We have to be extra careful when overriding a |
273 // method that takes optional arguments. We really should | 274 // method that takes optional arguments. We really should |
274 // enumerate all the stubs in the superclasses and make sure | 275 // enumerate all the stubs in the superclasses and make sure |
275 // they're overridden. | 276 // they're overridden. |
276 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 277 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
277 builder | 278 builder |
278 ..invokeStatic(constId, index) | 279 ..invokeStatic(constId, index) |
279 ..ret() | 280 ..ret() |
280 ..methodEnd(); | 281 ..methodEnd(); |
281 | 282 |
282 if (memberOf != null) { | 283 if (memberOf != null) { |
283 int fletchSelector = context.toFletchSelector(selector); | 284 int fletchSelector = context.toFletchSelector(selector); |
284 memberOf.addToMethodTable(fletchSelector, compiledFunction); | 285 memberOf.addToMethodTable(fletchSelector, functionBuilder); |
285 } | 286 } |
286 | 287 |
287 return compiledFunction; | 288 return functionBuilder; |
288 }); | 289 }); |
289 } | 290 } |
290 | 291 |
291 String verboseToString() { | 292 String verboseToString() { |
292 StringBuffer sb = new StringBuffer(); | 293 StringBuffer sb = new StringBuffer(); |
293 | 294 |
294 sb.writeln("Method $methodId, Arity=${builder.functionArity}"); | 295 sb.writeln("Method $methodId, Arity=${builder.functionArity}"); |
295 sb.writeln("Constants:"); | 296 sb.writeln("Constants:"); |
296 constants.forEach((constant, int index) { | 297 constants.forEach((constant, int index) { |
297 if (constant is ConstantValue) { | 298 if (constant is ConstantValue) { |
298 constant = constant.toStructuredString(); | 299 constant = constant.toStructuredString(); |
299 } | 300 } |
300 sb.writeln(" #$index: $constant"); | 301 sb.writeln(" #$index: $constant"); |
301 }); | 302 }); |
302 | 303 |
303 sb.writeln("Bytecodes:"); | 304 sb.writeln("Bytecodes:"); |
304 int offset = 0; | 305 int offset = 0; |
305 for (Bytecode bytecode in builder.bytecodes) { | 306 for (Bytecode bytecode in builder.bytecodes) { |
306 sb.writeln(" $offset: $bytecode"); | 307 sb.writeln(" $offset: $bytecode"); |
307 offset += bytecode.size; | 308 offset += bytecode.size; |
308 } | 309 } |
309 | 310 |
310 return '$sb'; | 311 return '$sb'; |
311 } | 312 } |
312 } | 313 } |
OLD | NEW |