mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 13:28:03 +00:00
Add a whitelist for functions that we always want to inline.
R=johnniwinther@google.com Review URL: https://codereview.chromium.org//543583002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@39869 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
06ca446607
commit
f4a8837f2d
|
@ -56,6 +56,8 @@ class JavaScriptBackend extends Backend {
|
|||
static final Uri DART_JS_HELPER = new Uri(scheme: 'dart', path: '_js_helper');
|
||||
static final Uri DART_INTERCEPTORS =
|
||||
new Uri(scheme: 'dart', path: '_interceptors');
|
||||
static final Uri DART_INTERNAL =
|
||||
new Uri(scheme: 'dart', path: '_internal');
|
||||
static final Uri DART_FOREIGN_HELPER =
|
||||
new Uri(scheme: 'dart', path: '_foreign_helper');
|
||||
static final Uri DART_JS_MIRRORS =
|
||||
|
@ -70,6 +72,24 @@ class JavaScriptBackend extends Backend {
|
|||
static const String INVOKE_ON = '_getCachedInvocation';
|
||||
static const String START_ROOT_ISOLATE = 'startRootIsolate';
|
||||
|
||||
|
||||
/// The list of functions for classes in the [internalLibrary] that we want
|
||||
/// to inline always. Any function in this list must be inlinable with
|
||||
/// respect to the conditions used in [InlineWeeder.canInline], except for
|
||||
/// size/complexity heuristics.
|
||||
static const Map<String, List<String>> ALWAYS_INLINE =
|
||||
const <String, List<String>> {
|
||||
'IterableMixinWorkaround': const <String>['forEach'],
|
||||
};
|
||||
|
||||
/// List of [FunctionElement]s that we want to inline always. This list is
|
||||
/// filled when resolution is complete by looking up in [internalLibrary].
|
||||
List<FunctionElement> functionsToAlwaysInline;
|
||||
|
||||
/// Reference to the internal library to lookup functions to always inline.
|
||||
LibraryElement internalLibrary;
|
||||
|
||||
|
||||
/// Set of classes that need to be considered for reflection although not
|
||||
/// otherwise visible during resolution.
|
||||
Iterable<ClassElement> get classesRequiredForReflection {
|
||||
|
@ -886,6 +906,26 @@ class JavaScriptBackend extends Backend {
|
|||
super.onResolutionComplete();
|
||||
computeMembersNeededForReflection();
|
||||
rti.computeClassesNeedingRti();
|
||||
computeFunctionsToAlwaysInline();
|
||||
}
|
||||
|
||||
void computeFunctionsToAlwaysInline() {
|
||||
functionsToAlwaysInline = <FunctionElement>[];
|
||||
if (internalLibrary == null) return;
|
||||
|
||||
// Try to find all functions intended to always inline. If their enclosing
|
||||
// class is not resolved we skip the methods, but it is an error to mention
|
||||
// a function or class that cannot be found.
|
||||
for (String className in ALWAYS_INLINE.keys) {
|
||||
ClassElement cls = find(internalLibrary, className);
|
||||
if (cls.resolutionState != STATE_DONE) continue;
|
||||
for (String functionName in ALWAYS_INLINE[className]) {
|
||||
Element function = cls.lookupMember(functionName);
|
||||
assert(invariant(cls, function is FunctionElement,
|
||||
message: 'unable to find function $functionName in $className'));
|
||||
functionsToAlwaysInline.add(function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void registerGetRuntimeTypeArgument(Registry registry) {
|
||||
|
@ -1584,6 +1624,8 @@ class JavaScriptBackend extends Backend {
|
|||
Uri uri = library.canonicalUri;
|
||||
if (uri == DART_JS_HELPER) {
|
||||
jsHelperLibrary = library;
|
||||
} else if (uri == DART_INTERNAL) {
|
||||
internalLibrary = library;
|
||||
} else if (uri == DART_INTERCEPTORS) {
|
||||
interceptorsLibrary = library;
|
||||
} else if (uri == DART_FOREIGN_HELPER) {
|
||||
|
|
|
@ -1256,6 +1256,13 @@ class SsaBuilder extends ResolvedVisitor {
|
|||
|
||||
if (cachedCanBeInlined == true) return cachedCanBeInlined;
|
||||
|
||||
if (backend.functionsToAlwaysInline.contains(function)) {
|
||||
// Inline this function regardless of it's size.
|
||||
assert(InlineWeeder.canBeInlined(function.node, -1, false,
|
||||
allowLoops: true));
|
||||
return true;
|
||||
}
|
||||
|
||||
int numParameters = function.functionSignature.parameterCount;
|
||||
int maxInliningNodes;
|
||||
bool useMaxInliningNodes = true;
|
||||
|
@ -6000,6 +6007,9 @@ class StringBuilderVisitor extends ast.Visitor {
|
|||
* This class visits the method that is a candidate for inlining and
|
||||
* finds whether it is too difficult to inline.
|
||||
*/
|
||||
// TODO(karlklose): refactor to make it possible to distinguish between
|
||||
// implementation restrictions (for example, we *can't* inline multiple returns)
|
||||
// and heuristics (we *shouldn't* inline large functions).
|
||||
class InlineWeeder extends ast.Visitor {
|
||||
// Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
|
||||
static const INLINING_NODES_OUTSIDE_LOOP = 18;
|
||||
|
@ -6012,14 +6022,18 @@ class InlineWeeder extends ast.Visitor {
|
|||
int nodeCount = 0;
|
||||
final int maxInliningNodes;
|
||||
final bool useMaxInliningNodes;
|
||||
final bool allowLoops;
|
||||
|
||||
InlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes);
|
||||
InlineWeeder(this.maxInliningNodes,
|
||||
this.useMaxInliningNodes,
|
||||
this.allowLoops);
|
||||
|
||||
static bool canBeInlined(ast.FunctionExpression functionExpression,
|
||||
int maxInliningNodes,
|
||||
bool useMaxInliningNodes) {
|
||||
bool useMaxInliningNodes,
|
||||
{bool allowLoops: false}) {
|
||||
InlineWeeder weeder =
|
||||
new InlineWeeder(maxInliningNodes, useMaxInliningNodes);
|
||||
new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops);
|
||||
weeder.visit(functionExpression.initializers);
|
||||
weeder.visit(functionExpression.body);
|
||||
return !weeder.tooDifficult;
|
||||
|
@ -6067,7 +6081,7 @@ class InlineWeeder extends ast.Visitor {
|
|||
// It's actually not difficult to inline a method with a loop, but
|
||||
// our measurements show that it's currently better to not inline a
|
||||
// method that contains a loop.
|
||||
tooDifficult = true;
|
||||
if (!allowLoops) tooDifficult = true;
|
||||
}
|
||||
|
||||
void visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
|
||||
|
|
Loading…
Reference in a new issue