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.fletch_backend; | 5 library fletchc.fletch_backend; |
6 | 6 |
7 import 'dart:async' show | 7 import 'dart:async' show |
8 Future; | 8 Future; |
9 | 9 |
10 import 'package:compiler/src/dart2jslib.dart' show | 10 import 'package:compiler/src/dart2jslib.dart' show |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 TreeElements; | 81 TreeElements; |
82 | 82 |
83 import 'package:compiler/src/library_loader.dart' show | 83 import 'package:compiler/src/library_loader.dart' show |
84 LibraryLoader; | 84 LibraryLoader; |
85 | 85 |
86 import 'fletch_constants.dart' show | 86 import 'fletch_constants.dart' show |
87 FletchClassConstant, | 87 FletchClassConstant, |
88 FletchFunctionConstant, | 88 FletchFunctionConstant, |
89 FletchClassInstanceConstant; | 89 FletchClassInstanceConstant; |
90 | 90 |
91 import 'compiled_function.dart' show | 91 import 'fletch_function_builder.dart' show |
92 CompiledFunctionKind, | 92 FletchFunctionBuilderKind, |
93 CompiledFunction, | 93 FletchFunctionBuilder, |
94 DebugInfo; | 94 DebugInfo; |
95 | 95 |
96 import 'compiled_class.dart' show | 96 import 'fletch_class_builder.dart' show |
97 CompiledClass; | 97 FletchClassBuilder; |
98 | 98 |
99 import 'codegen_visitor.dart'; | 99 import 'codegen_visitor.dart'; |
100 import 'debug_info.dart'; | 100 import 'debug_info.dart'; |
101 import 'debug_info_constructor_codegen.dart'; | 101 import 'debug_info_constructor_codegen.dart'; |
102 import 'debug_info_function_codegen.dart'; | 102 import 'debug_info_function_codegen.dart'; |
103 import 'debug_info_lazy_field_initializer_codegen.dart'; | 103 import 'debug_info_lazy_field_initializer_codegen.dart'; |
104 import 'fletch_context.dart'; | 104 import 'fletch_context.dart'; |
105 import 'fletch_selector.dart'; | 105 import 'fletch_selector.dart'; |
106 import 'function_codegen.dart'; | 106 import 'function_codegen.dart'; |
107 import 'lazy_field_initializer_codegen.dart'; | 107 import 'lazy_field_initializer_codegen.dart'; |
108 import 'constructor_codegen.dart'; | 108 import 'constructor_codegen.dart'; |
109 import 'closure_environment.dart'; | 109 import 'closure_environment.dart'; |
110 import '../bytecodes.dart'; | 110 import '../bytecodes.dart'; |
111 import '../commands.dart'; | 111 import '../commands.dart'; |
112 | 112 |
113 class FletchBackend extends Backend { | 113 class FletchBackend extends Backend { |
114 static const String growableListName = '_GrowableList'; | 114 static const String growableListName = '_GrowableList'; |
115 static const String constantListName = '_ConstantList'; | 115 static const String constantListName = '_ConstantList'; |
116 static const String constantMapName = '_ConstantMap'; | 116 static const String constantMapName = '_ConstantMap'; |
117 static const String linkedHashMapName = '_CompactLinkedHashMap'; | 117 static const String linkedHashMapName = '_CompactLinkedHashMap'; |
118 static const String noSuchMethodName = '_noSuchMethod'; | 118 static const String noSuchMethodName = '_noSuchMethod'; |
119 static const String noSuchMethodTrampolineName = '_noSuchMethodTrampoline'; | 119 static const String noSuchMethodTrampolineName = '_noSuchMethodTrampoline'; |
120 | 120 |
121 final FletchContext context; | 121 final FletchContext context; |
122 | 122 |
123 final DartConstantTask constantCompilerTask; | 123 final DartConstantTask constantCompilerTask; |
124 | 124 |
125 final Map<FunctionElement, CompiledFunction> compiledFunctions = | 125 final Map<FunctionElement, FletchFunctionBuilder> functionBuilders = |
126 <FunctionElement, CompiledFunction>{}; | 126 <FunctionElement, FletchFunctionBuilder>{}; |
127 | 127 |
128 final Map<ConstructorElement, CompiledFunction> constructors = | 128 final Map<ConstructorElement, FletchFunctionBuilder> constructors = |
129 <ConstructorElement, CompiledFunction>{}; | 129 <ConstructorElement, FletchFunctionBuilder>{}; |
130 | 130 |
131 final List<CompiledFunction> functions = <CompiledFunction>[]; | 131 final List<FletchFunctionBuilder> functions = <FletchFunctionBuilder>[]; |
132 | 132 |
133 final Set<FunctionElement> externals = new Set<FunctionElement>(); | 133 final Set<FunctionElement> externals = new Set<FunctionElement>(); |
134 | 134 |
135 final Map<ClassElement, CompiledClass> compiledClasses = | 135 final Map<ClassElement, FletchClassBuilder> classBuilders = |
136 <ClassElement, CompiledClass>{}; | 136 <ClassElement, FletchClassBuilder>{}; |
137 final Map<ClassElement, Set<ClassElement>> directSubclasses = | 137 final Map<ClassElement, Set<ClassElement>> directSubclasses = |
138 <ClassElement, Set<ClassElement>>{}; | 138 <ClassElement, Set<ClassElement>>{}; |
139 | 139 |
140 final List<CompiledClass> classes = <CompiledClass>[]; | 140 final List<FletchClassBuilder> classes = <FletchClassBuilder>[]; |
141 | 141 |
142 final Set<ClassElement> builtinClasses = new Set<ClassElement>(); | 142 final Set<ClassElement> builtinClasses = new Set<ClassElement>(); |
143 | 143 |
144 final Map<MemberElement, ClosureEnvironment> closureEnvironments = | 144 final Map<MemberElement, ClosureEnvironment> closureEnvironments = |
145 <MemberElement, ClosureEnvironment>{}; | 145 <MemberElement, ClosureEnvironment>{}; |
146 | 146 |
147 final Map<FunctionElement, CompiledClass> closureClasses = | 147 final Map<FunctionElement, FletchClassBuilder> closureClasses = |
148 <FunctionElement, CompiledClass>{}; | 148 <FunctionElement, FletchClassBuilder>{}; |
149 | 149 |
150 final Map<FieldElement, CompiledFunction> lazyFieldInitializers = | 150 final Map<FieldElement, FletchFunctionBuilder> lazyFieldInitializers = |
151 <FieldElement, CompiledFunction>{}; | 151 <FieldElement, FletchFunctionBuilder>{}; |
152 | 152 |
153 final Map<CompiledFunction, CompiledClass> tearoffClasses = | 153 final Map<FletchFunctionBuilder, FletchClassBuilder> tearoffClasses = |
154 <CompiledFunction, CompiledClass>{}; | 154 <FletchFunctionBuilder, FletchClassBuilder>{}; |
155 | 155 |
156 final Map<int, int> getters = <int, int>{}; | 156 final Map<int, int> getters = <int, int>{}; |
157 final Map<int, int> setters = <int, int>{}; | 157 final Map<int, int> setters = <int, int>{}; |
158 | 158 |
159 Map<CompiledClass, CompiledFunction> tearoffFunctions; | 159 Map<FletchClassBuilder, FletchFunctionBuilder> tearoffFunctions; |
160 | 160 |
161 List<Command> commands; | 161 List<Command> commands; |
162 | 162 |
163 LibraryElement fletchSystemLibrary; | 163 LibraryElement fletchSystemLibrary; |
164 LibraryElement fletchFFILibrary; | 164 LibraryElement fletchFFILibrary; |
165 LibraryElement fletchIOSystemLibrary; | 165 LibraryElement fletchIOSystemLibrary; |
166 LibraryElement collectionLibrary; | 166 LibraryElement collectionLibrary; |
167 LibraryElement mathLibrary; | 167 LibraryElement mathLibrary; |
168 | 168 |
169 FunctionElement fletchSystemEntry; | 169 FunctionElement fletchSystemEntry; |
170 | 170 |
171 FunctionElement fletchExternalInvokeMain; | 171 FunctionElement fletchExternalInvokeMain; |
172 | 172 |
173 FunctionElement fletchExternalYield; | 173 FunctionElement fletchExternalYield; |
174 | 174 |
175 FunctionElement fletchExternalNativeError; | 175 FunctionElement fletchExternalNativeError; |
176 | 176 |
177 FunctionElement fletchExternalCoroutineChange; | 177 FunctionElement fletchExternalCoroutineChange; |
178 | 178 |
179 FunctionElement fletchUnresolved; | 179 FunctionElement fletchUnresolved; |
180 FunctionElement fletchCompileError; | 180 FunctionElement fletchCompileError; |
181 | 181 |
182 CompiledClass compiledObjectClass; | 182 FletchClassBuilder compiledObjectClass; |
183 | 183 |
184 ClassElement stringClass; | 184 ClassElement stringClass; |
185 ClassElement smiClass; | 185 ClassElement smiClass; |
186 ClassElement mintClass; | 186 ClassElement mintClass; |
187 ClassElement growableListClass; | 187 ClassElement growableListClass; |
188 ClassElement linkedHashMapClass; | 188 ClassElement linkedHashMapClass; |
189 ClassElement coroutineClass; | 189 ClassElement coroutineClass; |
190 | 190 |
191 final Set<FunctionElement> alwaysEnqueue = new Set<FunctionElement>(); | 191 final Set<FunctionElement> alwaysEnqueue = new Set<FunctionElement>(); |
192 | 192 |
193 FletchBackend(FletchCompiler compiler) | 193 FletchBackend(FletchCompiler compiler) |
194 : this.context = compiler.context, | 194 : this.context = compiler.context, |
195 this.constantCompilerTask = new DartConstantTask(compiler), | 195 this.constantCompilerTask = new DartConstantTask(compiler), |
196 super(compiler) { | 196 super(compiler) { |
197 context.resolutionCallbacks = new FletchResolutionCallbacks(context); | 197 context.resolutionCallbacks = new FletchResolutionCallbacks(context); |
198 } | 198 } |
199 | 199 |
200 CompiledClass registerClassElement(ClassElement element) { | 200 FletchClassBuilder registerClassElement(ClassElement element) { |
201 if (element == null) return null; | 201 if (element == null) return null; |
202 assert(element.isDeclaration); | 202 assert(element.isDeclaration); |
203 return compiledClasses.putIfAbsent(element, () { | 203 return classBuilders.putIfAbsent(element, () { |
204 directSubclasses[element] = new Set<ClassElement>(); | 204 directSubclasses[element] = new Set<ClassElement>(); |
205 CompiledClass superclass = registerClassElement(element.superclass); | 205 FletchClassBuilder superclass = registerClassElement(element.superclass); |
206 if (superclass != null) { | 206 if (superclass != null) { |
207 Set<ClassElement> subclasses = directSubclasses[element.superclass]; | 207 Set<ClassElement> subclasses = directSubclasses[element.superclass]; |
208 subclasses.add(element); | 208 subclasses.add(element); |
209 } | 209 } |
210 int id = classes.length; | 210 int id = classes.length; |
211 CompiledClass compiledClass = new CompiledClass(id, element, superclass); | 211 FletchClassBuilder classBuilder = new FletchClassBuilder( |
| 212 id, element, superclass); |
212 if (element.lookupLocalMember(Compiler.CALL_OPERATOR_NAME) != null) { | 213 if (element.lookupLocalMember(Compiler.CALL_OPERATOR_NAME) != null) { |
213 compiledClass.createIsFunctionEntry(this); | 214 classBuilder.createIsFunctionEntry(this); |
214 } | 215 } |
215 classes.add(compiledClass); | 216 classes.add(classBuilder); |
216 return compiledClass; | 217 return classBuilder; |
217 }); | 218 }); |
218 } | 219 } |
219 | 220 |
220 CompiledClass createCallableStubClass(int fields, CompiledClass superclass) { | 221 FletchClassBuilder createCallableStubClass( |
| 222 int fields, FletchClassBuilder superclass) { |
221 int id = classes.length; | 223 int id = classes.length; |
222 CompiledClass compiledClass = new CompiledClass( | 224 FletchClassBuilder classBuilder = new FletchClassBuilder( |
223 id, null, superclass, extraFields: fields); | 225 id, null, superclass, extraFields: fields); |
224 classes.add(compiledClass); | 226 classes.add(classBuilder); |
225 compiledClass.createIsFunctionEntry(this); | 227 classBuilder.createIsFunctionEntry(this); |
226 return compiledClass; | 228 return classBuilder; |
227 } | 229 } |
228 | 230 |
229 FletchResolutionCallbacks get resolutionCallbacks { | 231 FletchResolutionCallbacks get resolutionCallbacks { |
230 return context.resolutionCallbacks; | 232 return context.resolutionCallbacks; |
231 } | 233 } |
232 | 234 |
233 List<CompilerTask> get tasks => <CompilerTask>[]; | 235 List<CompilerTask> get tasks => <CompilerTask>[]; |
234 | 236 |
235 ConstantSystem get constantSystem { | 237 ConstantSystem get constantSystem { |
236 return constantCompilerTask.constantCompiler.constantSystem; | 238 return constantCompilerTask.constantCompiler.constantSystem; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 } | 276 } |
275 fletchExternalInvokeMain = findExternal('invokeMain'); | 277 fletchExternalInvokeMain = findExternal('invokeMain'); |
276 fletchExternalYield = findExternal('yield'); | 278 fletchExternalYield = findExternal('yield'); |
277 fletchExternalCoroutineChange = findExternal('coroutineChange'); | 279 fletchExternalCoroutineChange = findExternal('coroutineChange'); |
278 fletchExternalNativeError = findExternal('nativeError'); | 280 fletchExternalNativeError = findExternal('nativeError'); |
279 fletchUnresolved = findExternal('unresolved'); | 281 fletchUnresolved = findExternal('unresolved'); |
280 world.registerStaticUse(fletchUnresolved); | 282 world.registerStaticUse(fletchUnresolved); |
281 fletchCompileError = findExternal('compileError'); | 283 fletchCompileError = findExternal('compileError'); |
282 world.registerStaticUse(fletchCompileError); | 284 world.registerStaticUse(fletchCompileError); |
283 | 285 |
284 CompiledClass loadClass(String name, LibraryElement library) { | 286 FletchClassBuilder loadClass(String name, LibraryElement library) { |
285 var classImpl = library.findLocal(name); | 287 var classImpl = library.findLocal(name); |
286 if (classImpl == null) classImpl = library.implementation.find(name); | 288 if (classImpl == null) classImpl = library.implementation.find(name); |
287 if (classImpl == null) { | 289 if (classImpl == null) { |
288 compiler.internalError(library, "Internal class '$name' not found."); | 290 compiler.internalError(library, "Internal class '$name' not found."); |
289 return null; | 291 return null; |
290 } | 292 } |
291 // TODO(ahe): Register in ResolutionCallbacks. The 3 lines below should | 293 // TODO(ahe): Register in ResolutionCallbacks. The 3 lines below should |
292 // not happen at this point in time. | 294 // not happen at this point in time. |
293 classImpl.ensureResolved(compiler); | 295 classImpl.ensureResolved(compiler); |
294 CompiledClass compiledClass = registerClassElement(classImpl); | 296 FletchClassBuilder classBuilder = registerClassElement(classImpl); |
295 world.registerInstantiatedType(classImpl.rawType, registry); | 297 world.registerInstantiatedType(classImpl.rawType, registry); |
296 // TODO(ahe): This is a hack to let both the world and the codegen know | 298 // TODO(ahe): This is a hack to let both the world and the codegen know |
297 // about the instantiated type. | 299 // about the instantiated type. |
298 registry.registerInstantiatedType(classImpl.rawType); | 300 registry.registerInstantiatedType(classImpl.rawType); |
299 return compiledClass; | 301 return classBuilder; |
300 } | 302 } |
301 | 303 |
302 CompiledClass loadBuiltinClass(String name, LibraryElement library) { | 304 FletchClassBuilder loadBuiltinClass(String name, LibraryElement library) { |
303 CompiledClass compiledClass = loadClass(name, library); | 305 FletchClassBuilder classBuilder = loadClass(name, library); |
304 builtinClasses.add(compiledClass.element); | 306 builtinClasses.add(classBuilder.element); |
305 return compiledClass; | 307 return classBuilder; |
306 } | 308 } |
307 | 309 |
308 compiledObjectClass = loadBuiltinClass("Object", compiler.coreLibrary); | 310 compiledObjectClass = loadBuiltinClass("Object", compiler.coreLibrary); |
309 smiClass = loadBuiltinClass("_Smi", compiler.coreLibrary).element; | 311 smiClass = loadBuiltinClass("_Smi", compiler.coreLibrary).element; |
310 mintClass = loadBuiltinClass("_Mint", compiler.coreLibrary).element; | 312 mintClass = loadBuiltinClass("_Mint", compiler.coreLibrary).element; |
311 stringClass = loadBuiltinClass("_StringImpl", compiler.coreLibrary).element; | 313 stringClass = loadBuiltinClass("_StringImpl", compiler.coreLibrary).element; |
312 // TODO(ahe): Register _ConstantList through ResolutionCallbacks. | 314 // TODO(ahe): Register _ConstantList through ResolutionCallbacks. |
313 loadBuiltinClass(constantListName, fletchSystemLibrary); | 315 loadBuiltinClass(constantListName, fletchSystemLibrary); |
314 loadBuiltinClass(constantMapName, fletchSystemLibrary); | 316 loadBuiltinClass(constantMapName, fletchSystemLibrary); |
315 loadBuiltinClass("_DoubleImpl", compiler.coreLibrary); | 317 loadBuiltinClass("_DoubleImpl", compiler.coreLibrary); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 /// The patch parser (pkg/compiler/lib/src/patch_parser.dart). The patch | 366 /// The patch parser (pkg/compiler/lib/src/patch_parser.dart). The patch |
365 /// parser looks for an annotation on the form "@patch", where "patch" is | 367 /// parser looks for an annotation on the form "@patch", where "patch" is |
366 /// compile-time constant instance of [patchAnnotationClass]. | 368 /// compile-time constant instance of [patchAnnotationClass]. |
367 ClassElement get patchAnnotationClass { | 369 ClassElement get patchAnnotationClass { |
368 // TODO(ahe): Introduce a proper constant class to identify constants. For | 370 // TODO(ahe): Introduce a proper constant class to identify constants. For |
369 // now, we simply put "const patch = "patch";" in the beginning of patch | 371 // now, we simply put "const patch = "patch";" in the beginning of patch |
370 // files. | 372 // files. |
371 return super.stringImplementation; | 373 return super.stringImplementation; |
372 } | 374 } |
373 | 375 |
374 CompiledClass createClosureClass( | 376 FletchClassBuilder createClosureClass( |
375 FunctionElement closure, | 377 FunctionElement closure, |
376 ClosureEnvironment closureEnvironment) { | 378 ClosureEnvironment closureEnvironment) { |
377 return closureClasses.putIfAbsent(closure, () { | 379 return closureClasses.putIfAbsent(closure, () { |
378 ClosureInfo info = closureEnvironment.closures[closure]; | 380 ClosureInfo info = closureEnvironment.closures[closure]; |
379 int fields = info.free.length; | 381 int fields = info.free.length; |
380 if (info.isThisFree) fields++; | 382 if (info.isThisFree) fields++; |
381 return createCallableStubClass(fields, compiledObjectClass); | 383 return createCallableStubClass(fields, compiledObjectClass); |
382 }); | 384 }); |
383 } | 385 } |
384 | 386 |
385 /** | 387 /** |
386 * Create a tearoff class for function [function]. | 388 * Create a tearoff class for function [function]. |
387 * | 389 * |
388 * The class will have one method named 'call', accepting the same arguments | 390 * The class will have one method named 'call', accepting the same arguments |
389 * as [function]. The method will load the arguments received and statically | 391 * as [function]. The method will load the arguments received and statically |
390 * call [function] (essential a tail-call). | 392 * call [function] (essential a tail-call). |
391 * | 393 * |
392 * If [function] is an instance member, the class will have one field, the | 394 * If [function] is an instance member, the class will have one field, the |
393 * instance. | 395 * instance. |
394 */ | 396 */ |
395 CompiledClass createTearoffClass(CompiledFunction function) { | 397 FletchClassBuilder createTearoffClass(FletchFunctionBuilder function) { |
396 return tearoffClasses.putIfAbsent(function, () { | 398 return tearoffClasses.putIfAbsent(function, () { |
397 FunctionSignature signature = function.signature; | 399 FunctionSignature signature = function.signature; |
398 bool hasThis = function.hasThisArgument; | 400 bool hasThis = function.hasThisArgument; |
399 CompiledClass compiledClass = createCallableStubClass( | 401 FletchClassBuilder classBuilder = createCallableStubClass( |
400 hasThis ? 1 : 0, | 402 hasThis ? 1 : 0, |
401 compiledObjectClass); | 403 compiledObjectClass); |
402 CompiledFunction compiledFunction = new CompiledFunction( | 404 FletchFunctionBuilder functionBuilder = new FletchFunctionBuilder( |
403 functions.length, | 405 functions.length, |
404 'call', | 406 'call', |
405 null, | 407 null, |
406 signature, | 408 signature, |
407 compiledClass); | 409 classBuilder); |
408 functions.add(compiledFunction); | 410 functions.add(functionBuilder); |
409 | 411 |
410 BytecodeBuilder builder = compiledFunction.builder; | 412 BytecodeBuilder builder = functionBuilder.builder; |
411 int argumentCount = signature.parameterCount; | 413 int argumentCount = signature.parameterCount; |
412 if (hasThis) { | 414 if (hasThis) { |
413 argumentCount++; | 415 argumentCount++; |
414 // If the tearoff has a 'this' value, load it. It's the only field | 416 // If the tearoff has a 'this' value, load it. It's the only field |
415 // in the tearoff class. | 417 // in the tearoff class. |
416 builder | 418 builder |
417 ..loadParameter(0) | 419 ..loadParameter(0) |
418 ..loadField(0); | 420 ..loadField(0); |
419 } | 421 } |
420 for (int i = 0; i < signature.parameterCount; i++) { | 422 for (int i = 0; i < signature.parameterCount; i++) { |
421 // The closure-class is at parameter index 0, so argument i is at | 423 // The closure-class is at parameter index 0, so argument i is at |
422 // i + 1. | 424 // i + 1. |
423 builder.loadParameter(i + 1); | 425 builder.loadParameter(i + 1); |
424 } | 426 } |
425 int constId = compiledFunction.allocateConstantFromFunction( | 427 int constId = functionBuilder.allocateConstantFromFunction( |
426 function.methodId); | 428 function.methodId); |
427 // TODO(ajohnsen): Create a tail-call bytecode, so we don't have to | 429 // TODO(ajohnsen): Create a tail-call bytecode, so we don't have to |
428 // load all the arguments. | 430 // load all the arguments. |
429 builder | 431 builder |
430 ..invokeStatic(constId, argumentCount) | 432 ..invokeStatic(constId, argumentCount) |
431 ..ret() | 433 ..ret() |
432 ..methodEnd(); | 434 ..methodEnd(); |
433 | 435 |
434 String symbol = context.getCallSymbol(signature); | 436 String symbol = context.getCallSymbol(signature); |
435 int id = context.getSymbolId(symbol); | 437 int id = context.getSymbolId(symbol); |
436 int fletchSelector = FletchSelector.encodeMethod( | 438 int fletchSelector = FletchSelector.encodeMethod( |
437 id, | 439 id, |
438 signature.parameterCount); | 440 signature.parameterCount); |
439 compiledClass.addToMethodTable(fletchSelector, compiledFunction); | 441 classBuilder.addToMethodTable(fletchSelector, functionBuilder); |
440 | 442 |
441 if (hasThis && function.memberOf.element != null) { | 443 if (hasThis && function.memberOf.element != null) { |
442 // Create == function that tests for equality. | 444 // Create == function that tests for equality. |
443 int isSelector = context.toFletchTearoffIsSelector( | 445 int isSelector = context.toFletchTearoffIsSelector( |
444 function.name, | 446 function.name, |
445 function.memberOf.element); | 447 function.memberOf.element); |
446 compiledClass.addIsSelector(isSelector); | 448 classBuilder.addIsSelector(isSelector); |
447 | 449 |
448 CompiledFunction equal = new CompiledFunction.normal( | 450 FletchFunctionBuilder equal = new FletchFunctionBuilder.normal( |
449 functions.length, | 451 functions.length, |
450 2); | 452 2); |
451 functions.add(equal); | 453 functions.add(equal); |
452 | 454 |
453 BytecodeLabel isFalse = new BytecodeLabel(); | 455 BytecodeLabel isFalse = new BytecodeLabel(); |
454 equal.builder | 456 equal.builder |
455 // First test for class. This ensures it's the exact function that | 457 // First test for class. This ensures it's the exact function that |
456 // we expect. | 458 // we expect. |
457 ..loadParameter(1) | 459 ..loadParameter(1) |
458 ..invokeTest(isSelector, 0) | 460 ..invokeTest(isSelector, 0) |
459 ..branchIfFalse(isFalse) | 461 ..branchIfFalse(isFalse) |
460 // Then test that the receiver is identical. | 462 // Then test that the receiver is identical. |
461 ..loadParameter(0) | 463 ..loadParameter(0) |
462 ..loadField(0) | 464 ..loadField(0) |
463 ..loadParameter(1) | 465 ..loadParameter(1) |
464 ..loadField(0) | 466 ..loadField(0) |
465 ..identicalNonNumeric() | 467 ..identicalNonNumeric() |
466 ..branchIfFalse(isFalse) | 468 ..branchIfFalse(isFalse) |
467 ..loadLiteralTrue() | 469 ..loadLiteralTrue() |
468 ..ret() | 470 ..ret() |
469 ..bind(isFalse) | 471 ..bind(isFalse) |
470 ..loadLiteralFalse() | 472 ..loadLiteralFalse() |
471 ..ret() | 473 ..ret() |
472 ..methodEnd(); | 474 ..methodEnd(); |
473 | 475 |
474 int id = context.getSymbolId("=="); | 476 int id = context.getSymbolId("=="); |
475 int equalsSelector = FletchSelector.encodeMethod(id, 1); | 477 int equalsSelector = FletchSelector.encodeMethod(id, 1); |
476 compiledClass.addToMethodTable(equalsSelector, equal); | 478 classBuilder.addToMethodTable(equalsSelector, equal); |
477 | 479 |
478 // Create hashCode getter. We simply xor the object hashCode and the | 480 // Create hashCode getter. We simply xor the object hashCode and the |
479 // method id of the tearoff'ed function. | 481 // method id of the tearoff'ed function. |
480 CompiledFunction hashCode = new CompiledFunction.accessor( | 482 FletchFunctionBuilder hashCode = new FletchFunctionBuilder.accessor( |
481 functions.length, | 483 functions.length, |
482 false); | 484 false); |
483 functions.add(hashCode); | 485 functions.add(hashCode); |
484 | 486 |
485 int hashCodeSelector = FletchSelector.encodeGetter( | 487 int hashCodeSelector = FletchSelector.encodeGetter( |
486 context.getSymbolId("hashCode")); | 488 context.getSymbolId("hashCode")); |
487 int xorSelector = FletchSelector.encodeMethod( | 489 int xorSelector = FletchSelector.encodeMethod( |
488 context.getSymbolId("^"), 1); | 490 context.getSymbolId("^"), 1); |
489 hashCode.builder | 491 hashCode.builder |
490 ..loadParameter(0) | 492 ..loadParameter(0) |
491 ..loadField(0) | 493 ..loadField(0) |
492 ..invokeMethod(hashCodeSelector, 0) | 494 ..invokeMethod(hashCodeSelector, 0) |
493 ..loadLiteral(function.methodId) | 495 ..loadLiteral(function.methodId) |
494 ..invokeMethod(xorSelector, 1) | 496 ..invokeMethod(xorSelector, 1) |
495 ..ret() | 497 ..ret() |
496 ..methodEnd(); | 498 ..methodEnd(); |
497 | 499 |
498 compiledClass.addToMethodTable(hashCodeSelector, hashCode); | 500 classBuilder.addToMethodTable(hashCodeSelector, hashCode); |
499 } | 501 } |
500 return compiledClass; | 502 return classBuilder; |
501 }); | 503 }); |
502 } | 504 } |
503 | 505 |
504 CompiledFunction createCompiledFunction(FunctionElement function) { | 506 FletchFunctionBuilder createFletchFunctionBuilder(FunctionElement function) { |
505 assert(function.memberContext == function); | 507 assert(function.memberContext == function); |
506 | 508 |
507 CompiledClass holderClass; | 509 FletchClassBuilder holderClass; |
508 if (function.isInstanceMember || function.isGenerativeConstructor) { | 510 if (function.isInstanceMember || function.isGenerativeConstructor) { |
509 ClassElement enclosingClass = function.enclosingClass.declaration; | 511 ClassElement enclosingClass = function.enclosingClass.declaration; |
510 holderClass = registerClassElement(enclosingClass); | 512 holderClass = registerClassElement(enclosingClass); |
511 } | 513 } |
512 return internalCreateCompiledFunction( | 514 return internalCreateFletchFunctionBuilder( |
513 function, | 515 function, |
514 function.name, | 516 function.name, |
515 holderClass); | 517 holderClass); |
516 } | 518 } |
517 | 519 |
518 CompiledFunction internalCreateCompiledFunction( | 520 FletchFunctionBuilder internalCreateFletchFunctionBuilder( |
519 FunctionElement function, | 521 FunctionElement function, |
520 String name, | 522 String name, |
521 CompiledClass holderClass) { | 523 FletchClassBuilder holderClass) { |
522 return compiledFunctions.putIfAbsent(function.declaration, () { | 524 return functionBuilders.putIfAbsent(function.declaration, () { |
523 FunctionTypedElement implementation = function.implementation; | 525 FunctionTypedElement implementation = function.implementation; |
524 CompiledFunction compiledFunction = new CompiledFunction( | 526 FletchFunctionBuilder functionBuilder = new FletchFunctionBuilder( |
525 functions.length, | 527 functions.length, |
526 name, | 528 name, |
527 function, | 529 function, |
528 // Parameter initializers are expressed in the potential | 530 // Parameter initializers are expressed in the potential |
529 // implementation. | 531 // implementation. |
530 implementation.functionSignature, | 532 implementation.functionSignature, |
531 holderClass, | 533 holderClass, |
532 kind: function.isAccessor | 534 kind: function.isAccessor |
533 ? CompiledFunctionKind.ACCESSOR | 535 ? FletchFunctionBuilderKind.ACCESSOR |
534 : CompiledFunctionKind.NORMAL); | 536 : FletchFunctionBuilderKind.NORMAL); |
535 functions.add(compiledFunction); | 537 functions.add(functionBuilder); |
536 return compiledFunction; | 538 return functionBuilder; |
537 }); | 539 }); |
538 } | 540 } |
539 | 541 |
540 int functionMethodId(FunctionElement function) { | 542 int functionMethodId(FunctionElement function) { |
541 return createCompiledFunction(function).methodId; | 543 return createFletchFunctionBuilder(function).methodId; |
542 } | 544 } |
543 | 545 |
544 CompiledFunction compiledFunctionFromTearoffClass(CompiledClass klass) { | 546 FletchFunctionBuilder functionBuilderFromTearoffClass( |
| 547 FletchClassBuilder klass) { |
545 if (tearoffFunctions == null) { | 548 if (tearoffFunctions == null) { |
546 tearoffFunctions = <CompiledClass, CompiledFunction>{}; | 549 tearoffFunctions = <FletchClassBuilder, FletchFunctionBuilder>{}; |
547 tearoffClasses.forEach((k, v) => tearoffFunctions[v] = k); | 550 tearoffClasses.forEach((k, v) => tearoffFunctions[v] = k); |
548 } | 551 } |
549 return tearoffFunctions[klass]; | 552 return tearoffFunctions[klass]; |
550 } | 553 } |
551 | 554 |
552 void ensureDebugInfo(CompiledFunction function) { | 555 void ensureDebugInfo(FletchFunctionBuilder function) { |
553 if (function.debugInfo != null) return; | 556 if (function.debugInfo != null) return; |
554 function.debugInfo = new DebugInfo(function); | 557 function.debugInfo = new DebugInfo(function); |
555 AstElement element = function.element; | 558 AstElement element = function.element; |
556 if (element == null) return; | 559 if (element == null) return; |
557 List<Bytecode> expectedBytecodes = function.builder.bytecodes; | 560 List<Bytecode> expectedBytecodes = function.builder.bytecodes; |
558 element = element.implementation; | 561 element = element.implementation; |
559 TreeElements elements = element.resolvedAst.elements; | 562 TreeElements elements = element.resolvedAst.elements; |
560 ClosureEnvironment closureEnvironment = createClosureEnvironment( | 563 ClosureEnvironment closureEnvironment = createClosureEnvironment( |
561 element, | 564 element, |
562 elements); | 565 elements); |
563 CodegenVisitor codegen; | 566 CodegenVisitor codegen; |
564 if (function.isLazyFieldInitializer) { | 567 if (function.isLazyFieldInitializer) { |
565 codegen = new DebugInfoLazyFieldInitializerCodegen( | 568 codegen = new DebugInfoLazyFieldInitializerCodegen( |
566 function, | 569 function, |
567 context, | 570 context, |
568 elements, | 571 elements, |
569 null, | 572 null, |
570 closureEnvironment, | 573 closureEnvironment, |
571 element, | 574 element, |
572 compiler); | 575 compiler); |
573 } else if (function.isInitializerList) { | 576 } else if (function.isInitializerList) { |
574 ClassElement enclosingClass = element.enclosingClass; | 577 ClassElement enclosingClass = element.enclosingClass; |
575 CompiledClass compiledClass = compiledClasses[enclosingClass]; | 578 FletchClassBuilder classBuilder = classBuilders[enclosingClass]; |
576 codegen = new DebugInfoConstructorCodegen( | 579 codegen = new DebugInfoConstructorCodegen( |
577 function, | 580 function, |
578 context, | 581 context, |
579 elements, | 582 elements, |
580 null, | 583 null, |
581 closureEnvironment, | 584 closureEnvironment, |
582 element, | 585 element, |
583 compiledClass, | 586 classBuilder, |
584 compiler); | 587 compiler); |
585 } else { | 588 } else { |
586 codegen = new DebugInfoFunctionCodegen( | 589 codegen = new DebugInfoFunctionCodegen( |
587 function, | 590 function, |
588 context, | 591 context, |
589 elements, | 592 elements, |
590 null, | 593 null, |
591 closureEnvironment, | 594 closureEnvironment, |
592 element, | 595 element, |
593 compiler); | 596 compiler); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 void codegenFunction( | 639 void codegenFunction( |
637 FunctionElement function, | 640 FunctionElement function, |
638 TreeElements elements, | 641 TreeElements elements, |
639 Registry registry) { | 642 Registry registry) { |
640 registry.registerStaticInvocation(fletchSystemEntry); | 643 registry.registerStaticInvocation(fletchSystemEntry); |
641 | 644 |
642 ClosureEnvironment closureEnvironment = createClosureEnvironment( | 645 ClosureEnvironment closureEnvironment = createClosureEnvironment( |
643 function, | 646 function, |
644 elements); | 647 elements); |
645 | 648 |
646 CompiledFunction compiledFunction; | 649 FletchFunctionBuilder functionBuilder; |
647 | 650 |
648 if (function.memberContext != function) { | 651 if (function.memberContext != function) { |
649 compiledFunction = internalCreateCompiledFunction( | 652 functionBuilder = internalCreateFletchFunctionBuilder( |
650 function, | 653 function, |
651 Compiler.CALL_OPERATOR_NAME, | 654 Compiler.CALL_OPERATOR_NAME, |
652 createClosureClass(function, closureEnvironment)); | 655 createClosureClass(function, closureEnvironment)); |
653 } else { | 656 } else { |
654 compiledFunction = createCompiledFunction(function); | 657 functionBuilder = createFletchFunctionBuilder(function); |
655 } | 658 } |
656 | 659 |
657 FunctionCodegen codegen = new FunctionCodegen( | 660 FunctionCodegen codegen = new FunctionCodegen( |
658 compiledFunction, | 661 functionBuilder, |
659 context, | 662 context, |
660 elements, | 663 elements, |
661 registry, | 664 registry, |
662 closureEnvironment, | 665 closureEnvironment, |
663 function); | 666 function); |
664 | 667 |
665 if (isNative(function)) { | 668 if (isNative(function)) { |
666 codegenNativeFunction(function, codegen); | 669 codegenNativeFunction(function, codegen); |
667 } else if (isExternal(function)) { | 670 } else if (isExternal(function)) { |
668 codegenExternalFunction(function, codegen); | 671 codegenExternalFunction(function, codegen); |
669 } else { | 672 } else { |
670 codegen.compile(); | 673 codegen.compile(); |
671 } | 674 } |
672 | 675 |
673 // TODO(ahe): Don't do this. | 676 // TODO(ahe): Don't do this. |
674 compiler.enqueuer.codegen.generatedCode[function.declaration] = null; | 677 compiler.enqueuer.codegen.generatedCode[function.declaration] = null; |
675 | 678 |
676 if (compiledFunction.memberOf != null && | 679 if (functionBuilder.memberOf != null && |
677 !function.isGenerativeConstructor) { | 680 !function.isGenerativeConstructor) { |
678 // Inject the function into the method table of the 'holderClass' class. | 681 // Inject the function into the method table of the 'holderClass' class. |
679 // Note that while constructor bodies has a this argument, we don't inject | 682 // Note that while constructor bodies has a this argument, we don't inject |
680 // them into the method table. | 683 // them into the method table. |
681 String symbol = context.getSymbolForFunction( | 684 String symbol = context.getSymbolForFunction( |
682 compiledFunction.name, | 685 functionBuilder.name, |
683 function.functionSignature, | 686 function.functionSignature, |
684 function.library); | 687 function.library); |
685 int id = context.getSymbolId(symbol); | 688 int id = context.getSymbolId(symbol); |
686 int arity = function.functionSignature.parameterCount; | 689 int arity = function.functionSignature.parameterCount; |
687 SelectorKind kind = SelectorKind.Method; | 690 SelectorKind kind = SelectorKind.Method; |
688 if (function.isGetter) kind = SelectorKind.Getter; | 691 if (function.isGetter) kind = SelectorKind.Getter; |
689 if (function.isSetter) kind = SelectorKind.Setter; | 692 if (function.isSetter) kind = SelectorKind.Setter; |
690 int fletchSelector = FletchSelector.encode(id, kind, arity); | 693 int fletchSelector = FletchSelector.encode(id, kind, arity); |
691 int methodId = compiledFunction.methodId; | 694 int methodId = functionBuilder.methodId; |
692 compiledFunction.memberOf.addToMethodTable( | 695 functionBuilder.memberOf.addToMethodTable( |
693 fletchSelector, compiledFunction); | 696 fletchSelector, functionBuilder); |
694 // Inject method into all mixin usages. | 697 // Inject method into all mixin usages. |
695 Iterable<ClassElement> mixinUsage = | 698 Iterable<ClassElement> mixinUsage = |
696 compiler.world.mixinUsesOf(function.enclosingClass); | 699 compiler.world.mixinUsesOf(function.enclosingClass); |
697 for (ClassElement usage in mixinUsage) { | 700 for (ClassElement usage in mixinUsage) { |
698 // TODO(ajohnsen): Consider having multiple 'memberOf' in | 701 // TODO(ajohnsen): Consider having multiple 'memberOf' in |
699 // CompiledFunction, to avoid duplicates. | 702 // FletchFunctionBuilder, to avoid duplicates. |
700 // Create a copy with a unique 'memberOf', so we can detect missing | 703 // Create a copy with a unique 'memberOf', so we can detect missing |
701 // stubs for the mixin applications as well. | 704 // stubs for the mixin applications as well. |
702 CompiledClass compiledUsage = registerClassElement(usage); | 705 FletchClassBuilder compiledUsage = registerClassElement(usage); |
703 FunctionTypedElement implementation = function.implementation; | 706 FunctionTypedElement implementation = function.implementation; |
704 CompiledFunction copy = new CompiledFunction( | 707 FletchFunctionBuilder copy = new FletchFunctionBuilder( |
705 functions.length, | 708 functions.length, |
706 function.name, | 709 function.name, |
707 implementation, | 710 implementation, |
708 implementation.functionSignature, | 711 implementation.functionSignature, |
709 compiledUsage, | 712 compiledUsage, |
710 kind: function.isAccessor | 713 kind: function.isAccessor |
711 ? CompiledFunctionKind.ACCESSOR | 714 ? FletchFunctionBuilderKind.ACCESSOR |
712 : CompiledFunctionKind.NORMAL); | 715 : FletchFunctionBuilderKind.NORMAL); |
713 functions.add(copy); | 716 functions.add(copy); |
714 compiledUsage.addToMethodTable(fletchSelector, copy); | 717 compiledUsage.addToMethodTable(fletchSelector, copy); |
715 copy.copyFrom(compiledFunction); | 718 copy.copyFrom(functionBuilder); |
716 } | 719 } |
717 } | 720 } |
718 | 721 |
719 if (compiler.verbose) { | 722 if (compiler.verbose) { |
720 compiler.log(compiledFunction.verboseToString()); | 723 compiler.log(functionBuilder.verboseToString()); |
721 } | 724 } |
722 } | 725 } |
723 | 726 |
724 void codegenNativeFunction( | 727 void codegenNativeFunction( |
725 FunctionElement function, | 728 FunctionElement function, |
726 FunctionCodegen codegen) { | 729 FunctionCodegen codegen) { |
727 String name = '.${function.name}'; | 730 String name = '.${function.name}'; |
728 | 731 |
729 ClassElement enclosingClass = function.enclosingClass; | 732 ClassElement enclosingClass = function.enclosingClass; |
730 if (enclosingClass != null) name = '${enclosingClass.name}$name'; | 733 if (enclosingClass != null) name = '${enclosingClass.name}$name'; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 MemberElement member = element.memberContext; | 854 MemberElement member = element.memberContext; |
852 return closureEnvironments.putIfAbsent(member, () { | 855 return closureEnvironments.putIfAbsent(member, () { |
853 ClosureVisitor environment = new ClosureVisitor(member, elements); | 856 ClosureVisitor environment = new ClosureVisitor(member, elements); |
854 return environment.compute(); | 857 return environment.compute(); |
855 }); | 858 }); |
856 } | 859 } |
857 | 860 |
858 void createParameterMatchingStubs() { | 861 void createParameterMatchingStubs() { |
859 int length = functions.length; | 862 int length = functions.length; |
860 for (int i = 0; i < length; i++) { | 863 for (int i = 0; i < length; i++) { |
861 CompiledFunction function = functions[i]; | 864 FletchFunctionBuilder function = functions[i]; |
862 if (!function.hasThisArgument || function.isAccessor) continue; | 865 if (!function.hasThisArgument || function.isAccessor) continue; |
863 String name = function.name; | 866 String name = function.name; |
864 Set<Selector> usage = compiler.resolverWorld.invokedNames[name]; | 867 Set<Selector> usage = compiler.resolverWorld.invokedNames[name]; |
865 if (usage == null) continue; | 868 if (usage == null) continue; |
866 for (Selector use in usage) { | 869 for (Selector use in usage) { |
867 // TODO(ajohnsen): Somehow filter out private selectors of other | 870 // TODO(ajohnsen): Somehow filter out private selectors of other |
868 // libraries. | 871 // libraries. |
869 if (function.canBeCalledAs(use) && | 872 if (function.canBeCalledAs(use) && |
870 !function.matchesSelector(use)) { | 873 !function.matchesSelector(use)) { |
871 function.createParameterMappingFor(use, context); | 874 function.createParameterMappingFor(use, context); |
872 } | 875 } |
873 } | 876 } |
874 } | 877 } |
875 } | 878 } |
876 | 879 |
877 void createTearoffStubs() { | 880 void createTearoffStubs() { |
878 int length = functions.length; | 881 int length = functions.length; |
879 for (int i = 0; i < length; i++) { | 882 for (int i = 0; i < length; i++) { |
880 CompiledFunction function = functions[i]; | 883 FletchFunctionBuilder function = functions[i]; |
881 if (!function.hasThisArgument || function.isAccessor) continue; | 884 if (!function.hasThisArgument || function.isAccessor) continue; |
882 String name = function.name; | 885 String name = function.name; |
883 if (compiler.resolverWorld.invokedGetters.containsKey(name)) { | 886 if (compiler.resolverWorld.invokedGetters.containsKey(name)) { |
884 createTearoffGetterForFunction(function); | 887 createTearoffGetterForFunction(function); |
885 } | 888 } |
886 } | 889 } |
887 } | 890 } |
888 | 891 |
889 void createTearoffGetterForFunction(CompiledFunction function) { | 892 void createTearoffGetterForFunction(FletchFunctionBuilder function) { |
890 CompiledClass tearoffClass = createTearoffClass(function); | 893 FletchClassBuilder tearoffClass = createTearoffClass(function); |
891 CompiledFunction getter = new CompiledFunction.accessor( | 894 FletchFunctionBuilder getter = new FletchFunctionBuilder.accessor( |
892 functions.length, | 895 functions.length, |
893 false); | 896 false); |
894 functions.add(getter); | 897 functions.add(getter); |
895 int constId = getter.allocateConstantFromClass(tearoffClass.id); | 898 int constId = getter.allocateConstantFromClass(tearoffClass.id); |
896 getter.builder | 899 getter.builder |
897 ..loadParameter(0) | 900 ..loadParameter(0) |
898 ..allocate(constId, tearoffClass.fields) | 901 ..allocate(constId, tearoffClass.fields) |
899 ..ret() | 902 ..ret() |
900 ..methodEnd(); | 903 ..methodEnd(); |
901 // If the name is private, we need the library. | 904 // If the name is private, we need the library. |
902 // Invariant: We only generate public stubs, e.g. 'call'. | 905 // Invariant: We only generate public stubs, e.g. 'call'. |
903 LibraryElement library; | 906 LibraryElement library; |
904 if (function.memberOf.element != null) { | 907 if (function.memberOf.element != null) { |
905 library = function.memberOf.element.library; | 908 library = function.memberOf.element.library; |
906 } | 909 } |
907 int fletchSelector = context.toFletchSelector( | 910 int fletchSelector = context.toFletchSelector( |
908 new Selector.getter(function.name, library)); | 911 new Selector.getter(function.name, library)); |
909 function.memberOf.addToMethodTable(fletchSelector, getter); | 912 function.memberOf.addToMethodTable(fletchSelector, getter); |
910 } | 913 } |
911 | 914 |
912 int assembleProgram() { | 915 int assembleProgram() { |
913 createTearoffStubs(); | 916 createTearoffStubs(); |
914 createParameterMatchingStubs(); | 917 createParameterMatchingStubs(); |
915 | 918 |
916 for (CompiledClass compiledClass in classes) { | 919 for (FletchClassBuilder classBuilder in classes) { |
917 compiledClass.createIsEntries(this); | 920 classBuilder.createIsEntries(this); |
918 // TODO(ajohnsen): Currently, the CodegenRegistry does not enqueue fields. | 921 // TODO(ajohnsen): Currently, the CodegenRegistry does not enqueue fields. |
919 // This is a workaround, where we basically add getters for all fields. | 922 // This is a workaround, where we basically add getters for all fields. |
920 compiledClass.createImplicitAccessors(this); | 923 classBuilder.createImplicitAccessors(this); |
921 } | 924 } |
922 | 925 |
923 List<Command> commands = <Command>[ | 926 List<Command> commands = <Command>[ |
924 const NewMap(MapId.methods), | 927 const NewMap(MapId.methods), |
925 const NewMap(MapId.classes), | 928 const NewMap(MapId.classes), |
926 const NewMap(MapId.constants), | 929 const NewMap(MapId.constants), |
927 ]; | 930 ]; |
928 | 931 |
929 List<Function> deferredActions = <Function>[]; | 932 List<Function> deferredActions = <Function>[]; |
930 | 933 |
931 functions.forEach((f) => pushNewFunction(f, commands, deferredActions)); | 934 functions.forEach((f) => pushNewFunction(f, commands, deferredActions)); |
932 | 935 |
933 int changes = 0; | 936 int changes = 0; |
934 | 937 |
935 for (CompiledClass compiledClass in classes) { | 938 for (FletchClassBuilder classBuilder in classes) { |
936 ClassElement element = compiledClass.element; | 939 ClassElement element = classBuilder.element; |
937 if (builtinClasses.contains(element)) { | 940 if (builtinClasses.contains(element)) { |
938 int nameId = context.getSymbolId(element.name); | 941 int nameId = context.getSymbolId(element.name); |
939 commands.add(new PushBuiltinClass(nameId, compiledClass.fields)); | 942 commands.add(new PushBuiltinClass(nameId, classBuilder.fields)); |
940 } else { | 943 } else { |
941 commands.add(new PushNewClass(compiledClass.fields)); | 944 commands.add(new PushNewClass(classBuilder.fields)); |
942 } | 945 } |
943 | 946 |
944 commands.add(const Dup()); | 947 commands.add(const Dup()); |
945 commands.add(new PopToMap(MapId.classes, compiledClass.id)); | 948 commands.add(new PopToMap(MapId.classes, classBuilder.id)); |
946 | 949 |
947 Map<int, int> methodTable = compiledClass.computeMethodTable(this); | 950 Map<int, int> methodTable = classBuilder.computeMethodTable(this); |
948 methodTable.forEach((int selector, int methodId) { | 951 methodTable.forEach((int selector, int methodId) { |
949 commands.add(new PushNewInteger(selector)); | 952 commands.add(new PushNewInteger(selector)); |
950 commands.add(new PushFromMap(MapId.methods, methodId)); | 953 commands.add(new PushFromMap(MapId.methods, methodId)); |
951 }); | 954 }); |
952 commands.add(new ChangeMethodTable(methodTable.length)); | 955 commands.add(new ChangeMethodTable(methodTable.length)); |
953 | 956 |
954 changes++; | 957 changes++; |
955 } | 958 } |
956 | 959 |
957 context.forEachStatic((element, index) { | 960 context.forEachStatic((element, index) { |
958 CompiledFunction initializer = lazyFieldInitializers[element]; | 961 FletchFunctionBuilder initializer = lazyFieldInitializers[element]; |
959 if (initializer != null) { | 962 if (initializer != null) { |
960 commands.add(new PushFromMap(MapId.methods, initializer.methodId)); | 963 commands.add(new PushFromMap(MapId.methods, initializer.methodId)); |
961 commands.add(const PushNewInitializer()); | 964 commands.add(const PushNewInitializer()); |
962 } else { | 965 } else { |
963 commands.add(const PushNull()); | 966 commands.add(const PushNull()); |
964 } | 967 } |
965 }); | 968 }); |
966 commands.add(new ChangeStatics(context.staticIndices.length)); | 969 commands.add(new ChangeStatics(context.staticIndices.length)); |
967 changes++; | 970 changes++; |
968 | 971 |
(...skipping 23 matching lines...) Expand all Loading... |
992 ListConstantValue value = constant; | 995 ListConstantValue value = constant; |
993 addList(constant.entries); | 996 addList(constant.entries); |
994 } else if (constant.isMap) { | 997 } else if (constant.isMap) { |
995 MapConstantValue value = constant; | 998 MapConstantValue value = constant; |
996 addList(value.keys); | 999 addList(value.keys); |
997 addList(value.values); | 1000 addList(value.values); |
998 commands.add(new PushConstantMap(value.length * 2)); | 1001 commands.add(new PushConstantMap(value.length * 2)); |
999 } else if (constant.isConstructedObject) { | 1002 } else if (constant.isConstructedObject) { |
1000 ConstructedConstantValue value = constant; | 1003 ConstructedConstantValue value = constant; |
1001 ClassElement classElement = value.type.element; | 1004 ClassElement classElement = value.type.element; |
1002 CompiledClass compiledClass = compiledClasses[classElement]; | 1005 FletchClassBuilder classBuilder = classBuilders[classElement]; |
1003 for (ConstantValue field in value.fields.values) { | 1006 for (ConstantValue field in value.fields.values) { |
1004 int fieldId = context.compiledConstants[field]; | 1007 int fieldId = context.compiledConstants[field]; |
1005 commands.add(new PushFromMap(MapId.constants, fieldId)); | 1008 commands.add(new PushFromMap(MapId.constants, fieldId)); |
1006 } | 1009 } |
1007 commands | 1010 commands |
1008 ..add(new PushFromMap(MapId.classes, compiledClass.id)) | 1011 ..add(new PushFromMap(MapId.classes, classBuilder.id)) |
1009 ..add(const PushNewInstance()); | 1012 ..add(const PushNewInstance()); |
1010 } else if (constant is FletchClassInstanceConstant) { | 1013 } else if (constant is FletchClassInstanceConstant) { |
1011 commands | 1014 commands |
1012 ..add(new PushFromMap(MapId.classes, constant.classId)) | 1015 ..add(new PushFromMap(MapId.classes, constant.classId)) |
1013 ..add(const PushNewInstance()); | 1016 ..add(const PushNewInstance()); |
1014 } else { | 1017 } else { |
1015 throw "Unsupported constant: ${constant.toStructuredString()}"; | 1018 throw "Unsupported constant: ${constant.toStructuredString()}"; |
1016 } | 1019 } |
1017 commands.add(new PopToMap(MapId.constants, id)); | 1020 commands.add(new PopToMap(MapId.constants, id)); |
1018 }); | 1021 }); |
1019 | 1022 |
1020 for (CompiledClass compiledClass in classes) { | 1023 for (FletchClassBuilder classBuilder in classes) { |
1021 CompiledClass superclass = compiledClass.superclass; | 1024 FletchClassBuilder superclass = classBuilder.superclass; |
1022 if (superclass == null) continue; | 1025 if (superclass == null) continue; |
1023 commands.add(new PushFromMap(MapId.classes, compiledClass.id)); | 1026 commands.add(new PushFromMap(MapId.classes, classBuilder.id)); |
1024 commands.add(new PushFromMap(MapId.classes, superclass.id)); | 1027 commands.add(new PushFromMap(MapId.classes, superclass.id)); |
1025 commands.add(const ChangeSuperClass()); | 1028 commands.add(const ChangeSuperClass()); |
1026 changes++; | 1029 changes++; |
1027 } | 1030 } |
1028 | 1031 |
1029 for (Function action in deferredActions) { | 1032 for (Function action in deferredActions) { |
1030 action(); | 1033 action(); |
1031 changes++; | 1034 changes++; |
1032 } | 1035 } |
1033 | 1036 |
1034 commands.add(new CommitChanges(changes)); | 1037 commands.add(new CommitChanges(changes)); |
1035 | 1038 |
1036 commands.add(const PushNewInteger(0)); | 1039 commands.add(const PushNewInteger(0)); |
1037 | 1040 |
1038 commands.add(new PushFromMap( | 1041 commands.add(new PushFromMap( |
1039 MapId.methods, | 1042 MapId.methods, |
1040 compiledFunctions[fletchSystemEntry].methodId)); | 1043 functionBuilders[fletchSystemEntry].methodId)); |
1041 | 1044 |
1042 this.commands = commands; | 1045 this.commands = commands; |
1043 | 1046 |
1044 return 0; | 1047 return 0; |
1045 } | 1048 } |
1046 | 1049 |
1047 void pushNewFunction( | 1050 void pushNewFunction( |
1048 CompiledFunction compiledFunction, | 1051 FletchFunctionBuilder functionBuilder, |
1049 List<Command> commands, | 1052 List<Command> commands, |
1050 List<Function> deferredActions) { | 1053 List<Function> deferredActions) { |
1051 int arity = compiledFunction.builder.functionArity; | 1054 int arity = functionBuilder.builder.functionArity; |
1052 int constantCount = compiledFunction.constants.length; | 1055 int constantCount = functionBuilder.constants.length; |
1053 int methodId = compiledFunction.methodId; | 1056 int methodId = functionBuilder.methodId; |
1054 | 1057 |
1055 assert(functions[methodId] == compiledFunction); | 1058 assert(functions[methodId] == functionBuilder); |
1056 assert(compiledFunction.builder.bytecodes.isNotEmpty); | 1059 assert(functionBuilder.builder.bytecodes.isNotEmpty); |
1057 | 1060 |
1058 compiledFunction.constants.forEach((constant, int index) { | 1061 functionBuilder.constants.forEach((constant, int index) { |
1059 if (constant is ConstantValue) { | 1062 if (constant is ConstantValue) { |
1060 if (constant is FletchFunctionConstant) { | 1063 if (constant is FletchFunctionConstant) { |
1061 commands.add(const PushNull()); | 1064 commands.add(const PushNull()); |
1062 deferredActions.add(() { | 1065 deferredActions.add(() { |
1063 commands | 1066 commands |
1064 ..add(new PushFromMap(MapId.methods, methodId)) | 1067 ..add(new PushFromMap(MapId.methods, methodId)) |
1065 ..add(new PushFromMap(MapId.methods, constant.methodId)) | 1068 ..add(new PushFromMap(MapId.methods, constant.methodId)) |
1066 ..add(new ChangeMethodLiteral(index)); | 1069 ..add(new ChangeMethodLiteral(index)); |
1067 }); | 1070 }); |
1068 } else if (constant is FletchClassConstant) { | 1071 } else if (constant is FletchClassConstant) { |
(...skipping 19 matching lines...) Expand all Loading... |
1088 } | 1091 } |
1089 } else { | 1092 } else { |
1090 throw "Unsupported constant: ${constant.runtimeType}"; | 1093 throw "Unsupported constant: ${constant.runtimeType}"; |
1091 } | 1094 } |
1092 }); | 1095 }); |
1093 | 1096 |
1094 commands.add( | 1097 commands.add( |
1095 new PushNewFunction( | 1098 new PushNewFunction( |
1096 arity, | 1099 arity, |
1097 constantCount, | 1100 constantCount, |
1098 compiledFunction.builder.bytecodes, | 1101 functionBuilder.builder.bytecodes, |
1099 compiledFunction.builder.catchRanges)); | 1102 functionBuilder.builder.catchRanges)); |
1100 | 1103 |
1101 commands.add(new PopToMap(MapId.methods, methodId)); | 1104 commands.add(new PopToMap(MapId.methods, methodId)); |
1102 } | 1105 } |
1103 | 1106 |
1104 bool registerDeferredLoading(Spannable node, Registry registry) { | 1107 bool registerDeferredLoading(Spannable node, Registry registry) { |
1105 compiler.reportWarning( | 1108 compiler.reportWarning( |
1106 node, | 1109 node, |
1107 MessageKind.GENERIC, | 1110 MessageKind.GENERIC, |
1108 {'text': "Deferred loading is not supported."}); | 1111 {'text': "Deferred loading is not supported."}); |
1109 return false; | 1112 return false; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 return element; | 1185 return element; |
1183 } | 1186 } |
1184 | 1187 |
1185 int compileLazyFieldInitializer(FieldElement field, Registry registry) { | 1188 int compileLazyFieldInitializer(FieldElement field, Registry registry) { |
1186 int index = context.getStaticFieldIndex(field, null); | 1189 int index = context.getStaticFieldIndex(field, null); |
1187 | 1190 |
1188 if (field.initializer == null) return index; | 1191 if (field.initializer == null) return index; |
1189 | 1192 |
1190 if (lazyFieldInitializers.containsKey(field)) return index; | 1193 if (lazyFieldInitializers.containsKey(field)) return index; |
1191 | 1194 |
1192 CompiledFunction compiledFunction = new CompiledFunction.lazyInit( | 1195 FletchFunctionBuilder functionBuilder = new FletchFunctionBuilder.lazyInit( |
1193 functions.length, | 1196 functions.length, |
1194 "${field.name} lazy initializer", | 1197 "${field.name} lazy initializer", |
1195 field, | 1198 field, |
1196 0); | 1199 0); |
1197 functions.add(compiledFunction); | 1200 functions.add(functionBuilder); |
1198 lazyFieldInitializers[field] = compiledFunction; | 1201 lazyFieldInitializers[field] = functionBuilder; |
1199 | 1202 |
1200 TreeElements elements = field.resolvedAst.elements; | 1203 TreeElements elements = field.resolvedAst.elements; |
1201 | 1204 |
1202 ClosureEnvironment closureEnvironment = createClosureEnvironment( | 1205 ClosureEnvironment closureEnvironment = createClosureEnvironment( |
1203 field, | 1206 field, |
1204 elements); | 1207 elements); |
1205 | 1208 |
1206 LazyFieldInitializerCodegen codegen = new LazyFieldInitializerCodegen( | 1209 LazyFieldInitializerCodegen codegen = new LazyFieldInitializerCodegen( |
1207 compiledFunction, | 1210 functionBuilder, |
1208 context, | 1211 context, |
1209 elements, | 1212 elements, |
1210 registry, | 1213 registry, |
1211 closureEnvironment, | 1214 closureEnvironment, |
1212 field); | 1215 field); |
1213 | 1216 |
1214 codegen.compile(); | 1217 codegen.compile(); |
1215 | 1218 |
1216 return index; | 1219 return index; |
1217 } | 1220 } |
1218 | 1221 |
1219 CompiledFunction compileConstructor(ConstructorElement constructor, | 1222 FletchFunctionBuilder compileConstructor(ConstructorElement constructor, |
1220 Registry registry) { | 1223 Registry registry) { |
1221 assert(constructor.isDeclaration); | 1224 assert(constructor.isDeclaration); |
1222 CompiledFunction compiledFunction = constructors[constructor]; | 1225 FletchFunctionBuilder functionBuilder = constructors[constructor]; |
1223 if (compiledFunction != null) return compiledFunction; | 1226 if (functionBuilder != null) return functionBuilder; |
1224 | 1227 |
1225 ClassElement classElement = constructor.enclosingClass; | 1228 ClassElement classElement = constructor.enclosingClass; |
1226 CompiledClass compiledClass = registerClassElement(classElement); | 1229 FletchClassBuilder classBuilder = registerClassElement(classElement); |
1227 | 1230 |
1228 ConstructorElement implementation = constructor.implementation; | 1231 ConstructorElement implementation = constructor.implementation; |
1229 | 1232 |
1230 if (compiler.verbose) { | 1233 if (compiler.verbose) { |
1231 // TODO(johnniwinther): Use reportVerboseInfo once added. | 1234 // TODO(johnniwinther): Use reportVerboseInfo once added. |
1232 compiler.reportHint( | 1235 compiler.reportHint( |
1233 constructor, | 1236 constructor, |
1234 MessageKind.GENERIC, | 1237 MessageKind.GENERIC, |
1235 {'text': 'Compiling constructor ${implementation.name}'}); | 1238 {'text': 'Compiling constructor ${implementation.name}'}); |
1236 } | 1239 } |
1237 | 1240 |
1238 TreeElements elements = implementation.resolvedAst.elements; | 1241 TreeElements elements = implementation.resolvedAst.elements; |
1239 | 1242 |
1240 ClosureEnvironment closureEnvironment = createClosureEnvironment( | 1243 ClosureEnvironment closureEnvironment = createClosureEnvironment( |
1241 implementation, | 1244 implementation, |
1242 elements); | 1245 elements); |
1243 | 1246 |
1244 compiledFunction = new CompiledFunction( | 1247 functionBuilder = new FletchFunctionBuilder( |
1245 functions.length, | 1248 functions.length, |
1246 implementation.name, | 1249 implementation.name, |
1247 implementation, | 1250 implementation, |
1248 implementation.functionSignature, | 1251 implementation.functionSignature, |
1249 null, | 1252 null, |
1250 kind: CompiledFunctionKind.INITIALIZER_LIST); | 1253 kind: FletchFunctionBuilderKind.INITIALIZER_LIST); |
1251 functions.add(compiledFunction); | 1254 functions.add(functionBuilder); |
1252 constructors[constructor] = compiledFunction; | 1255 constructors[constructor] = functionBuilder; |
1253 | 1256 |
1254 ConstructorCodegen codegen = new ConstructorCodegen( | 1257 ConstructorCodegen codegen = new ConstructorCodegen( |
1255 compiledFunction, | 1258 functionBuilder, |
1256 context, | 1259 context, |
1257 elements, | 1260 elements, |
1258 registry, | 1261 registry, |
1259 closureEnvironment, | 1262 closureEnvironment, |
1260 implementation, | 1263 implementation, |
1261 compiledClass); | 1264 classBuilder); |
1262 | 1265 |
1263 codegen.compile(); | 1266 codegen.compile(); |
1264 | 1267 |
1265 if (compiler.verbose) { | 1268 if (compiler.verbose) { |
1266 compiler.log(compiledFunction.verboseToString()); | 1269 compiler.log(functionBuilder.verboseToString()); |
1267 } | 1270 } |
1268 | 1271 |
1269 return compiledFunction; | 1272 return functionBuilder; |
1270 } | 1273 } |
1271 | 1274 |
1272 /** | 1275 /** |
1273 * Generate a getter for field [fieldIndex]. | 1276 * Generate a getter for field [fieldIndex]. |
1274 */ | 1277 */ |
1275 int makeGetter(int fieldIndex) { | 1278 int makeGetter(int fieldIndex) { |
1276 return getters.putIfAbsent(fieldIndex, () { | 1279 return getters.putIfAbsent(fieldIndex, () { |
1277 CompiledFunction stub = new CompiledFunction.accessor( | 1280 FletchFunctionBuilder stub = new FletchFunctionBuilder.accessor( |
1278 functions.length, | 1281 functions.length, |
1279 false); | 1282 false); |
1280 functions.add(stub); | 1283 functions.add(stub); |
1281 stub.builder | 1284 stub.builder |
1282 ..loadParameter(0) | 1285 ..loadParameter(0) |
1283 ..loadField(fieldIndex) | 1286 ..loadField(fieldIndex) |
1284 ..ret() | 1287 ..ret() |
1285 ..methodEnd(); | 1288 ..methodEnd(); |
1286 return stub.methodId; | 1289 return stub.methodId; |
1287 }); | 1290 }); |
1288 } | 1291 } |
1289 | 1292 |
1290 /** | 1293 /** |
1291 * Generate a setter for field [fieldIndex]. | 1294 * Generate a setter for field [fieldIndex]. |
1292 */ | 1295 */ |
1293 int makeSetter(int fieldIndex) { | 1296 int makeSetter(int fieldIndex) { |
1294 return setters.putIfAbsent(fieldIndex, () { | 1297 return setters.putIfAbsent(fieldIndex, () { |
1295 CompiledFunction stub = new CompiledFunction.accessor( | 1298 FletchFunctionBuilder stub = new FletchFunctionBuilder.accessor( |
1296 functions.length, | 1299 functions.length, |
1297 true); | 1300 true); |
1298 functions.add(stub); | 1301 functions.add(stub); |
1299 stub.builder | 1302 stub.builder |
1300 ..loadParameter(0) | 1303 ..loadParameter(0) |
1301 ..loadParameter(1) | 1304 ..loadParameter(1) |
1302 ..storeField(fieldIndex) | 1305 ..storeField(fieldIndex) |
1303 // Top is at this point the rhs argument, thus the return value. | 1306 // Top is at this point the rhs argument, thus the return value. |
1304 ..ret() | 1307 ..ret() |
1305 ..methodEnd(); | 1308 ..methodEnd(); |
1306 return stub.methodId; | 1309 return stub.methodId; |
1307 }); | 1310 }); |
1308 } | 1311 } |
1309 | 1312 |
1310 void generateUnimplementedError( | 1313 void generateUnimplementedError( |
1311 Spannable spannable, | 1314 Spannable spannable, |
1312 String reason, | 1315 String reason, |
1313 CompiledFunction function) { | 1316 FletchFunctionBuilder function) { |
1314 compiler.reportError( | 1317 compiler.reportError( |
1315 spannable, MessageKind.GENERIC, {'text': reason}); | 1318 spannable, MessageKind.GENERIC, {'text': reason}); |
1316 var constString = constantSystem.createString( | 1319 var constString = constantSystem.createString( |
1317 new DartString.literal(reason)); | 1320 new DartString.literal(reason)); |
1318 context.markConstantUsed(constString); | 1321 context.markConstantUsed(constString); |
1319 function | 1322 function |
1320 ..builder.loadConst(function.allocateConstant(constString)) | 1323 ..builder.loadConst(function.allocateConstant(constString)) |
1321 ..builder.emitThrow(); | 1324 ..builder.emitThrow(); |
1322 } | 1325 } |
1323 | 1326 |
1324 void forgetElement(Element element) { | 1327 void forgetElement(Element element) { |
1325 CompiledFunction compiledFunction = compiledFunctions[element]; | 1328 FletchFunctionBuilder functionBuilder = functionBuilders[element]; |
1326 if (compiledFunction == null) return; | 1329 if (functionBuilder == null) return; |
1327 compiledFunction.reuse(); | 1330 functionBuilder.reuse(); |
1328 } | 1331 } |
1329 } | 1332 } |
OLD | NEW |