| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library dart2js.cps_ir.eagerly_load_statics; |
| |
| import 'cps_ir_nodes.dart'; |
| import 'optimizers.dart' show Pass; |
| import '../elements/elements.dart'; |
| |
| /// Replaces [GetLazyStatic] with [GetStatic] when the static field is known |
| /// to have been initialized. |
| /// |
| /// Apart from [GetStatic] generating better code, this improves the side-effect |
| /// analysis in the [GVN] pass, since [GetStatic] has no effects. |
| class EagerlyLoadStatics extends TrampolineRecursiveVisitor implements Pass { |
| String get passName => 'Eagerly load statics'; |
| |
| Map<FieldElement, Primitive> initializerFor = <FieldElement, Primitive>{}; |
| |
| final Map<Continuation, Map<FieldElement, Primitive>> initializersAt = |
| <Continuation, Map<FieldElement, Primitive>>{}; |
| |
| static Map<FieldElement, Primitive> cloneFieldMap( |
| Map<FieldElement, Primitive> map) { |
| return new Map<FieldElement, Primitive>.from(map); |
| } |
| |
| void rewrite(FunctionDefinition node) { |
| visit(node.body); |
| } |
| |
| Expression traverseLetCont(LetCont node) { |
| for (Continuation cont in node.continuations) { |
| initializersAt[cont] = cloneFieldMap(initializerFor); |
| push(cont); |
| } |
| return node.body; |
| } |
| |
| Expression traverseLetHandler(LetHandler node) { |
| initializersAt[node.handler] = cloneFieldMap(initializerFor); |
| push(node.handler); |
| return node.body; |
| } |
| |
| Expression traverseContinuation(Continuation cont) { |
| initializerFor = initializersAt[cont]; |
| return cont.body; |
| } |
| |
| void visitGetLazyStatic(GetLazyStatic node) { |
| Primitive initializer = initializerFor[node.element]; |
| if (initializer != null) { |
| GetStatic newNode = new GetStatic.witnessed(node.element, initializer, |
| node.sourceInformation); |
| newNode.type = node.type; |
| node.replaceWith(newNode); |
| } else { |
| initializerFor[node.element] = node; |
| } |
| } |
| |
| void visitSetStatic(SetStatic node) { |
| initializerFor.putIfAbsent(node.element, () => node); |
| } |
| } |