OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.ir_builder_task; | 5 library dart2js.ir_builder_task; |
6 | 6 |
7 import '../closure.dart' as closurelib; | 7 import '../closure.dart' as closurelib; |
8 import '../closure.dart' hide ClosureScope; | 8 import '../closure.dart' hide ClosureScope; |
9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
(...skipping 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2490 | 2490 |
2491 JsIrBuilder getBuilderFor(Element element) { | 2491 JsIrBuilder getBuilderFor(Element element) { |
2492 return new JsIrBuilder( | 2492 return new JsIrBuilder( |
2493 new GlobalProgramInformation(compiler), | 2493 new GlobalProgramInformation(compiler), |
2494 compiler.backend.constantSystem, | 2494 compiler.backend.constantSystem, |
2495 element); | 2495 element); |
2496 } | 2496 } |
2497 | 2497 |
2498 /// Builds the IR for a given constructor. | 2498 /// Builds the IR for a given constructor. |
2499 /// | 2499 /// |
2500 /// 1. Evaluates all own or inherited field initializers. | 2500 /// 1. Builds all types held in own or "inherited" type variables. |
karlklose
2015/05/28 08:12:19
Not sure what 'builds' means here. Further down we
asgerf
2015/05/28 09:34:21
I've tried to clarify a bit.
| |
2501 /// 2. Creates the object and assigns its fields. | 2501 /// 2. Evaluates all own or inherited field initializers. |
2502 /// 3. Calls constructor body and super constructor bodies. | 2502 /// 3. Creates the object and assigns its fields. |
2503 /// 4. Returns the created object. | 2503 /// 4. Calls constructor body and super constructor bodies. |
2504 /// 5. Returns the created object. | |
2504 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { | 2505 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { |
2505 // TODO(asgerf): Optimization: If constructor is redirecting, then just | 2506 // TODO(asgerf): Optimization: If constructor is redirecting, then just |
2506 // evaluate arguments and call the target constructor. | 2507 // evaluate arguments and call the target constructor. |
2507 constructor = constructor.implementation; | 2508 constructor = constructor.implementation; |
2508 ClassElement classElement = constructor.enclosingClass.implementation; | 2509 ClassElement classElement = constructor.enclosingClass.implementation; |
2509 | 2510 |
2510 JsIrBuilder builder = getBuilderFor(constructor); | 2511 JsIrBuilder builder = getBuilderFor(constructor); |
2511 | 2512 |
2512 final bool requiresTypeInformation = | 2513 final bool requiresTypeInformation = |
2513 builder.program.requiresRuntimeTypesFor(classElement); | 2514 builder.program.requiresRuntimeTypesFor(classElement); |
2514 | 2515 |
2515 return withBuilder(builder, () { | 2516 return withBuilder(builder, () { |
2516 // Setup parameters and create a box if anything is captured. | 2517 // Setup parameters and create a box if anything is captured. |
2517 List<Local> parameters = <Local>[]; | 2518 List<Local> parameters = <Local>[]; |
2518 constructor.functionSignature.orderedForEachParameter( | 2519 constructor.functionSignature.orderedForEachParameter( |
2519 (ParameterElement p) => parameters.add(p)); | 2520 (ParameterElement p) => parameters.add(p)); |
2520 | 2521 |
2521 int firstTypeArgumentParameterIndex; | 2522 int firstTypeArgumentParameterIndex; |
2522 | 2523 |
2523 // If instances of the class may need runtime type information, we add a | 2524 // If instances of the class may need runtime type information, we add a |
2524 // synthetic parameter for each type parameter. | 2525 // synthetic parameter for each type parameter. |
2525 if (requiresTypeInformation) { | 2526 if (requiresTypeInformation) { |
2526 firstTypeArgumentParameterIndex = parameters.length; | 2527 firstTypeArgumentParameterIndex = parameters.length; |
2527 classElement.typeVariables.forEach((TypeVariableType variable) { | 2528 classElement.typeVariables.forEach((TypeVariableType variable) { |
2528 parameters.add( | 2529 parameters.add(new TypeVariableLocal(variable, constructor)); |
2529 new TypeInformationParameter(variable.element, constructor)); | 2530 }); |
2531 } else { | |
2532 classElement.typeVariables.forEach((TypeVariableType variable) { | |
2533 irBuilder.declareTypeVariable(variable, const DynamicType()); | |
2530 }); | 2534 }); |
2531 } | 2535 } |
2532 | 2536 |
2533 // Create IR parameters and setup the environment. | 2537 // Create IR parameters and setup the environment. |
2534 List<ir.Parameter> irParameters = builder.buildFunctionHeader(parameters, | 2538 List<ir.Parameter> irParameters = builder.buildFunctionHeader(parameters, |
2535 closureScope: getClosureScopeForFunction(constructor)); | 2539 closureScope: getClosureScopeForFunction(constructor)); |
2536 | 2540 |
2537 // Create a list of the values of all type argument parameters, if any. | 2541 // Create a list of the values of all type argument parameters, if any. |
2538 List<ir.Primitive> typeInformation; | 2542 List<ir.Primitive> typeInformation; |
2539 if (requiresTypeInformation) { | 2543 if (requiresTypeInformation) { |
2540 typeInformation = irParameters.sublist(firstTypeArgumentParameterIndex); | 2544 typeInformation = irParameters.sublist(firstTypeArgumentParameterIndex); |
2541 } else { | 2545 } else { |
2542 typeInformation = const <ir.Primitive>[]; | 2546 typeInformation = const <ir.Primitive>[]; |
2543 } | 2547 } |
2544 | 2548 |
2545 // -- Step 1: evaluate field initializers --- | 2549 // -- Load values for type variables declared on super classes -- |
2550 // Field initializers for super classes can reference these, so they | |
2551 // must be available before evaluating field initializers. | |
2552 // This could be interleaved with field initialization, but we choose do | |
2553 // get it out of the way here to avoid complications with mixins. | |
2554 loadTypeVariablesForSuperClasses(classElement); | |
2555 | |
2556 // -- Evaluate field initializers --- | |
2546 // Evaluate field initializers in constructor and super constructors. | 2557 // Evaluate field initializers in constructor and super constructors. |
2547 irBuilder.enterInitializers(); | 2558 irBuilder.enterInitializers(); |
2548 List<ConstructorElement> constructorList = <ConstructorElement>[]; | 2559 List<ConstructorElement> constructorList = <ConstructorElement>[]; |
2549 evaluateConstructorFieldInitializers(constructor, constructorList); | 2560 evaluateConstructorFieldInitializers(constructor, constructorList); |
2550 irBuilder.leaveInitializers(); | 2561 irBuilder.leaveInitializers(); |
2551 | 2562 |
2552 // All parameters in all constructors are now bound in the environment. | 2563 // All parameters in all constructors are now bound in the environment. |
2553 // BoxLocals for captured parameters are also in the environment. | 2564 // BoxLocals for captured parameters are also in the environment. |
2554 // The initial value of all fields are now bound in [fieldValues]. | 2565 // The initial value of all fields are now bound in [fieldValues]. |
2555 | 2566 |
2556 // --- Step 2: create the object --- | 2567 // --- Create the object --- |
2557 // Get the initial field values in the canonical order. | 2568 // Get the initial field values in the canonical order. |
2558 List<ir.Primitive> instanceArguments = <ir.Primitive>[]; | 2569 List<ir.Primitive> instanceArguments = <ir.Primitive>[]; |
2559 classElement.forEachInstanceField((ClassElement c, FieldElement field) { | 2570 classElement.forEachInstanceField((ClassElement c, FieldElement field) { |
2560 ir.Primitive value = fieldValues[field]; | 2571 ir.Primitive value = fieldValues[field]; |
2561 if (value != null) { | 2572 if (value != null) { |
2562 instanceArguments.add(value); | 2573 instanceArguments.add(value); |
2563 } else { | 2574 } else { |
2564 assert(Elements.isNativeOrExtendsNative(c)); | 2575 assert(Elements.isNativeOrExtendsNative(c)); |
2565 // Native fields are initialized elsewhere. | 2576 // Native fields are initialized elsewhere. |
2566 } | 2577 } |
2567 }, includeSuperAndInjectedMembers: true); | 2578 }, includeSuperAndInjectedMembers: true); |
2568 ir.Primitive instance = new ir.CreateInstance( | 2579 ir.Primitive instance = new ir.CreateInstance( |
2569 classElement, | 2580 classElement, |
2570 instanceArguments, | 2581 instanceArguments, |
2571 typeInformation); | 2582 typeInformation); |
2572 irBuilder.add(new ir.LetPrim(instance)); | 2583 irBuilder.add(new ir.LetPrim(instance)); |
2573 | 2584 |
2574 // --- Step 3: call constructor bodies --- | 2585 // --- Call constructor bodies --- |
2575 for (ConstructorElement target in constructorList) { | 2586 for (ConstructorElement target in constructorList) { |
2576 ConstructorBodyElement bodyElement = getConstructorBody(target); | 2587 ConstructorBodyElement bodyElement = getConstructorBody(target); |
2577 if (bodyElement == null) continue; // Skip if constructor has no body. | 2588 if (bodyElement == null) continue; // Skip if constructor has no body. |
2578 List<ir.Primitive> bodyArguments = <ir.Primitive>[]; | 2589 List<ir.Primitive> bodyArguments = <ir.Primitive>[]; |
2579 for (Local param in getConstructorBodyParameters(bodyElement)) { | 2590 for (Local param in getConstructorBodyParameters(bodyElement)) { |
2580 bodyArguments.add(irBuilder.environment.lookup(param)); | 2591 bodyArguments.add(irBuilder.environment.lookup(param)); |
2581 } | 2592 } |
2582 irBuilder.buildInvokeDirectly(bodyElement, instance, bodyArguments); | 2593 irBuilder.buildInvokeDirectly(bodyElement, instance, bodyArguments); |
2583 } | 2594 } |
2584 | 2595 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2666 FunctionElement target = superClass.lookupDefaultConstructor(); | 2677 FunctionElement target = superClass.lookupDefaultConstructor(); |
2667 if (target == null) { | 2678 if (target == null) { |
2668 compiler.internalError(superClass, "No default constructor available."); | 2679 compiler.internalError(superClass, "No default constructor available."); |
2669 } | 2680 } |
2670 evaluateConstructorFieldInitializers(target, supers); | 2681 evaluateConstructorFieldInitializers(target, supers); |
2671 } | 2682 } |
2672 // Add this constructor after the superconstructors. | 2683 // Add this constructor after the superconstructors. |
2673 supers.add(constructor); | 2684 supers.add(constructor); |
2674 } | 2685 } |
2675 | 2686 |
2687 /// Loads the type variables for all super classes of [superClass] into the | |
2688 /// IR builder's environment with their corresponding values. | |
2689 /// | |
2690 /// The type variables for [currentClass] must already be in the IR builder's | |
2691 /// environment. | |
2692 /// | |
2693 /// Type variables are stored as [TypeVariableLocal] in the environment. | |
2694 /// | |
2695 /// This ensures that access to type variables mentioned inside the | |
2696 /// constructors and initializers will happen through the local environment | |
2697 /// instead of using 'this'. | |
2698 void loadTypeVariablesForSuperClasses(ClassElement currentClass) { | |
2699 if (currentClass.isObject) return; | |
2700 loadTypeVariablesForType(currentClass.supertype); | |
2701 if (currentClass is MixinApplicationElement) { | |
2702 loadTypeVariablesForType(currentClass.mixinType); | |
2703 } | |
2704 } | |
2705 | |
2706 /// Loads all type variables for [superType] and all of its super classes into | |
2707 /// the environment. All type variables mentioned in [superType] must already | |
2708 /// be in the environment. | |
2709 void loadTypeVariablesForType(InterfaceType type) { | |
2710 ClassElement clazz = type.element; | |
2711 assert(clazz.typeVariables.length == type.typeArguments.length); | |
2712 for (int i = 0; i < clazz.typeVariables.length; ++i) { | |
2713 TypeVariableType typeParameter = clazz.typeVariables[i]; | |
karlklose
2015/05/28 08:12:19
Maybe inline typeParameter and typeArgument.
asgerf
2015/05/28 09:34:21
Done.
| |
2714 DartType typeArgument = type.typeArguments[i]; | |
2715 irBuilder.declareTypeVariable(typeParameter, typeArgument); | |
2716 } | |
2717 loadTypeVariablesForSuperClasses(clazz); | |
2718 } | |
2719 | |
2676 /// In preparation of inlining (part of) [target], the [arguments] are moved | 2720 /// In preparation of inlining (part of) [target], the [arguments] are moved |
2677 /// into the environment bindings for the corresponding parameters. | 2721 /// into the environment bindings for the corresponding parameters. |
2678 /// | 2722 /// |
2679 /// Defaults for optional arguments are evaluated in order to ensure | 2723 /// Defaults for optional arguments are evaluated in order to ensure |
2680 /// all parameters are available in the environment. | 2724 /// all parameters are available in the environment. |
2681 void loadArguments(FunctionElement target, | 2725 void loadArguments(ConstructorElement target, |
2682 Selector selector, | 2726 Selector selector, |
2683 List<ir.Primitive> arguments) { | 2727 List<ir.Primitive> arguments) { |
2684 target = target.implementation; | 2728 target = target.implementation; |
2685 FunctionSignature signature = target.functionSignature; | 2729 FunctionSignature signature = target.functionSignature; |
2686 | 2730 |
2687 // Establish a scope in case parameters are captured. | 2731 // Establish a scope in case parameters are captured. |
2688 ClosureScope scope = getClosureScopeForFunction(target); | 2732 ClosureScope scope = getClosureScopeForFunction(target); |
2689 irBuilder.enterScope(scope); | 2733 irBuilder.enterScope(scope); |
2690 | 2734 |
2691 // Load required parameters | 2735 // Load required parameters |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3075 node.body = replacementFor(node.body); | 3119 node.body = replacementFor(node.body); |
3076 } | 3120 } |
3077 } | 3121 } |
3078 | 3122 |
3079 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 3123 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
3080 class RemovalVisitor extends ir.RecursiveVisitor { | 3124 class RemovalVisitor extends ir.RecursiveVisitor { |
3081 processReference(ir.Reference reference) { | 3125 processReference(ir.Reference reference) { |
3082 reference.unlink(); | 3126 reference.unlink(); |
3083 } | 3127 } |
3084 } | 3128 } |
OLD | NEW |