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.constructor_codegen; | 5 library fletchc.constructor_codegen; |
6 | 6 |
7 import 'package:compiler/src/constants/expressions.dart' show | 7 import 'package:compiler/src/constants/expressions.dart' show |
8 ConstantExpression; | 8 ConstantExpression; |
9 | 9 |
10 import 'package:compiler/src/dart2jslib.dart' show | 10 import 'package:compiler/src/dart2jslib.dart' show |
11 MessageKind, | 11 MessageKind, |
12 Registry; | 12 Registry; |
13 | 13 |
14 import 'package:compiler/src/elements/elements.dart'; | 14 import 'package:compiler/src/elements/elements.dart'; |
15 import 'package:compiler/src/resolution/resolution.dart'; | 15 import 'package:compiler/src/resolution/resolution.dart'; |
16 import 'package:compiler/src/tree/tree.dart'; | 16 import 'package:compiler/src/tree/tree.dart'; |
17 import 'package:compiler/src/universe/universe.dart'; | 17 import 'package:compiler/src/universe/universe.dart'; |
18 import 'package:compiler/src/util/util.dart' show Spannable; | 18 import 'package:compiler/src/util/util.dart' show Spannable; |
19 import 'package:compiler/src/dart_types.dart'; | 19 import 'package:compiler/src/dart_types.dart'; |
20 | 20 |
21 import 'fletch_context.dart'; | 21 import 'fletch_context.dart'; |
22 | 22 |
23 import 'fletch_backend.dart'; | 23 import 'fletch_backend.dart'; |
24 | 24 |
25 import 'fletch_constants.dart' show | 25 import 'fletch_constants.dart' show |
26 CompiledFunctionConstant, | 26 FletchFunctionBuilderConstant, |
27 FletchClassConstant; | 27 FletchClassConstant; |
28 | 28 |
29 import '../bytecodes.dart' show | 29 import '../bytecodes.dart' show |
30 Bytecode; | 30 Bytecode; |
31 | 31 |
32 import 'compiled_function.dart' show | 32 import 'fletch_function_builder.dart' show |
33 CompiledFunction; | 33 FletchFunctionBuilder; |
34 | 34 |
35 import 'compiled_class.dart' show | 35 import 'fletch_class_builder.dart' show |
36 CompiledClass; | 36 FletchClassBuilder; |
37 | 37 |
38 import 'closure_environment.dart'; | 38 import 'closure_environment.dart'; |
39 | 39 |
40 import 'lazy_field_initializer_codegen.dart'; | 40 import 'lazy_field_initializer_codegen.dart'; |
41 | 41 |
42 import 'codegen_visitor.dart'; | 42 import 'codegen_visitor.dart'; |
43 | 43 |
44 class ConstructorCodegen extends CodegenVisitor { | 44 class ConstructorCodegen extends CodegenVisitor { |
45 final CompiledClass compiledClass; | 45 final FletchClassBuilder classBuilder; |
46 | 46 |
47 final Map<FieldElement, LocalValue> fieldScope = <FieldElement, LocalValue>{}; | 47 final Map<FieldElement, LocalValue> fieldScope = <FieldElement, LocalValue>{}; |
48 | 48 |
49 final List<ConstructorElement> constructors = <ConstructorElement>[]; | 49 final List<ConstructorElement> constructors = <ConstructorElement>[]; |
50 | 50 |
51 TreeElements initializerElements; | 51 TreeElements initializerElements; |
52 | 52 |
53 ConstructorCodegen(CompiledFunction compiledFunction, | 53 ConstructorCodegen(FletchFunctionBuilder functionBuilder, |
54 FletchContext context, | 54 FletchContext context, |
55 TreeElements elements, | 55 TreeElements elements, |
56 Registry registry, | 56 Registry registry, |
57 ClosureEnvironment closureEnvironment, | 57 ClosureEnvironment closureEnvironment, |
58 ConstructorElement constructor, | 58 ConstructorElement constructor, |
59 this.compiledClass) | 59 this.classBuilder) |
60 : super(compiledFunction, context, elements, registry, | 60 : super(functionBuilder, context, elements, registry, |
61 closureEnvironment, constructor); | 61 closureEnvironment, constructor); |
62 | 62 |
63 ConstructorElement get constructor => element; | 63 ConstructorElement get constructor => element; |
64 | 64 |
65 BytecodeBuilder get builder => compiledFunction.builder; | 65 BytecodeBuilder get builder => functionBuilder.builder; |
66 | 66 |
67 TreeElements get elements { | 67 TreeElements get elements { |
68 if (initializerElements != null) return initializerElements; | 68 if (initializerElements != null) return initializerElements; |
69 return super.elements; | 69 return super.elements; |
70 } | 70 } |
71 | 71 |
72 void compile() { | 72 void compile() { |
73 // Push all initial field values (including super-classes). | 73 // Push all initial field values (including super-classes). |
74 pushInitialFieldValues(compiledClass); | 74 pushInitialFieldValues(classBuilder); |
75 // The stack is now: | 75 // The stack is now: |
76 // Value for field-0 | 76 // Value for field-0 |
77 // ... | 77 // ... |
78 // Value for field-n | 78 // Value for field-n |
79 // | 79 // |
80 FunctionSignature signature = constructor.functionSignature; | 80 FunctionSignature signature = constructor.functionSignature; |
81 int parameterCount = signature.parameterCount; | 81 int parameterCount = signature.parameterCount; |
82 | 82 |
83 // Visit constructor and evaluate initializers and super calls. The | 83 // Visit constructor and evaluate initializers and super calls. The |
84 // arguments to the constructor are located before the return address. | 84 // arguments to the constructor are located before the return address. |
85 inlineInitializers(constructor, -parameterCount - 1); | 85 inlineInitializers(constructor, -parameterCount - 1); |
86 | 86 |
87 handleAllocationAndBodyCall(); | 87 handleAllocationAndBodyCall(); |
88 } | 88 } |
89 | 89 |
90 LazyFieldInitializerCodegen lazyFieldInitializerCodegenFor( | 90 LazyFieldInitializerCodegen lazyFieldInitializerCodegenFor( |
91 CompiledFunction function, | 91 FletchFunctionBuilder function, |
92 FieldElement field) { | 92 FieldElement field) { |
93 TreeElements elements = field.resolvedAst.elements; | 93 TreeElements elements = field.resolvedAst.elements; |
94 return new LazyFieldInitializerCodegen( | 94 return new LazyFieldInitializerCodegen( |
95 function, | 95 function, |
96 context, | 96 context, |
97 elements, | 97 elements, |
98 registry, | 98 registry, |
99 context.backend.createClosureEnvironment(field, elements), | 99 context.backend.createClosureEnvironment(field, elements), |
100 field); | 100 field); |
101 } | 101 } |
102 | 102 |
103 void handleAllocationAndBodyCall() { | 103 void handleAllocationAndBodyCall() { |
104 // TODO(ajohnsen): Let allocate take an offset to the field stack, so we | 104 // TODO(ajohnsen): Let allocate take an offset to the field stack, so we |
105 // don't have to copy all the fields? | 105 // don't have to copy all the fields? |
106 // Copy all the fields to the end of the stack. | 106 // Copy all the fields to the end of the stack. |
107 int fields = compiledClass.fields; | 107 int fields = classBuilder.fields; |
108 for (int i = 0; i < fields; i++) { | 108 for (int i = 0; i < fields; i++) { |
109 builder.loadSlot(i); | 109 builder.loadSlot(i); |
110 } | 110 } |
111 | 111 |
112 // The stack is now: | 112 // The stack is now: |
113 // Value for field-0 | 113 // Value for field-0 |
114 // ... | 114 // ... |
115 // Value for field-n | 115 // Value for field-n |
116 // [super arguments] | 116 // [super arguments] |
117 // Value for field-0 | 117 // Value for field-0 |
118 // ... | 118 // ... |
119 // Value for field-n | 119 // Value for field-n |
120 | 120 |
121 // Create the actual instance. | 121 // Create the actual instance. |
122 int classConstant = compiledFunction.allocateConstantFromClass( | 122 int classConstant = functionBuilder.allocateConstantFromClass( |
123 compiledClass.id); | 123 classBuilder.id); |
124 // TODO(ajohnsen): Set immutable for all-final classes. | 124 // TODO(ajohnsen): Set immutable for all-final classes. |
125 builder.allocate(classConstant, fields, immutable: element.isConst); | 125 builder.allocate(classConstant, fields, immutable: element.isConst); |
126 | 126 |
127 // The stack is now: | 127 // The stack is now: |
128 // Value for field-0 | 128 // Value for field-0 |
129 // ... | 129 // ... |
130 // Value for field-n | 130 // Value for field-n |
131 // [super arguments] | 131 // [super arguments] |
132 // instance | 132 // instance |
133 | 133 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 return argumentCount + signature.parameterCount; | 324 return argumentCount + signature.parameterCount; |
325 } | 325 } |
326 | 326 |
327 void callConstructorBody(ConstructorElement constructor) { | 327 void callConstructorBody(ConstructorElement constructor) { |
328 FunctionExpression node = constructor.node; | 328 FunctionExpression node = constructor.node; |
329 if (node == null || node.body.asEmptyStatement() != null) return; | 329 if (node == null || node.body.asEmptyStatement() != null) return; |
330 | 330 |
331 registerStaticInvocation(constructor.declaration); | 331 registerStaticInvocation(constructor.declaration); |
332 | 332 |
333 int methodId = context.backend.functionMethodId(constructor); | 333 int methodId = context.backend.functionMethodId(constructor); |
334 int constructorId = compiledFunction.allocateConstantFromFunction(methodId); | 334 int constructorId = functionBuilder.allocateConstantFromFunction(methodId); |
335 | 335 |
336 FunctionSignature signature = constructor.functionSignature; | 336 FunctionSignature signature = constructor.functionSignature; |
337 | 337 |
338 // Prepare for constructor body invoke. | 338 // Prepare for constructor body invoke. |
339 builder.dup(); | 339 builder.dup(); |
340 signature.orderedForEachParameter((FormalElement parameter) { | 340 signature.orderedForEachParameter((FormalElement parameter) { |
341 scope[parameter].load(builder); | 341 scope[parameter].load(builder); |
342 }); | 342 }); |
343 | 343 |
344 builder | 344 builder |
345 ..invokeStatic(constructorId, 1 + signature.parameterCount) | 345 ..invokeStatic(constructorId, 1 + signature.parameterCount) |
346 ..pop(); | 346 ..pop(); |
347 } | 347 } |
348 | 348 |
349 void pushInitialFieldValues(CompiledClass compiledClass) { | 349 void pushInitialFieldValues(FletchClassBuilder classBuilder) { |
350 if (compiledClass.hasSuperClass) { | 350 if (classBuilder.hasSuperClass) { |
351 pushInitialFieldValues(compiledClass.superclass); | 351 pushInitialFieldValues(classBuilder.superclass); |
352 } | 352 } |
353 int fieldIndex = compiledClass.superclassFields; | 353 int fieldIndex = classBuilder.superclassFields; |
354 ClassElement classElement = compiledClass.element.implementation; | 354 ClassElement classElement = classBuilder.element.implementation; |
355 classElement.forEachInstanceField((_, FieldElement field) { | 355 classElement.forEachInstanceField((_, FieldElement field) { |
356 fieldScope[field] = new UnboxedLocalValue(fieldIndex++, field); | 356 fieldScope[field] = new UnboxedLocalValue(fieldIndex++, field); |
357 Expression initializer = field.initializer; | 357 Expression initializer = field.initializer; |
358 if (initializer == null) { | 358 if (initializer == null) { |
359 builder.loadLiteralNull(); | 359 builder.loadLiteralNull(); |
360 } else { | 360 } else { |
361 // Create a LazyFieldInitializerCodegen for compiling the initializer. | 361 // Create a LazyFieldInitializerCodegen for compiling the initializer. |
362 // Note that we reuse the compiledFunction, to inline it into the | 362 // Note that we reuse the functionBuilder, to inline it into the |
363 // constructor. | 363 // constructor. |
364 LazyFieldInitializerCodegen codegen = | 364 LazyFieldInitializerCodegen codegen = |
365 lazyFieldInitializerCodegenFor(compiledFunction, field); | 365 lazyFieldInitializerCodegenFor(functionBuilder, field); |
366 | 366 |
367 // We only want the value of the actual initializer, not the usual | 367 // We only want the value of the actual initializer, not the usual |
368 // 'body'. | 368 // 'body'. |
369 codegen.visitForValue(initializer); | 369 codegen.visitForValue(initializer); |
370 } | 370 } |
371 }); | 371 }); |
372 } | 372 } |
373 } | 373 } |
OLD | NEW |