blob: e03f9cad33bc96a02b3daaa241c94945cdb25fd9 [file] [log] [blame]
// 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';
import 'cps_fragment.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 traverseLetPrim(LetPrim node) {
Expression next = node.body;
visit(node.primitive);
return next;
}
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 is GetLazyStatic && initializer.isFinal) {
// No reason to create a GetStatic when the field is final.
node.replaceWithFragment(new CpsFragment(), initializer);
} else if (initializer != null) {
GetStatic newNode = new GetStatic.witnessed(node.element,
initializer, sourceInformation: node.sourceInformation)
..type = node.type;
node.replaceWith(newNode);
} else {
initializerFor[node.element] = node;
}
}
void visitSetStatic(SetStatic node) {
initializerFor.putIfAbsent(node.element, () => node);
}
}