| 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 |