Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1128)

Unified Diff: pkg/compiler/lib/src/js_backend/backend.dart

Issue 962703004: Add "force inline" to internal annotations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove mustInline. It's not used. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_backend/backend.dart
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 0723cd1beec8f57bc926737cfc713882f56527ef..3d9ffc42e197dd3fec21d356e855fd9eadd9fa01 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -26,39 +26,77 @@ abstract class FunctionCompiler {
* !canInline(function, insideLoop: true) implies !canInline(function)
*/
class FunctionInlineCache {
- final Map<FunctionElement, bool> canBeInlined =
- new Map<FunctionElement, bool>();
-
- final Map<FunctionElement, bool> canBeInlinedInsideLoop =
- new Map<FunctionElement, bool>();
-
- // Returns [:true:]/[:false:] if we have a cached decision.
- // Returns [:null:] otherwise.
+ static const int _mustNotInline = 0;
Johnni Winther 2015/03/03 08:57:47 The logic for these tags is both complex and scatt
floitsch 2015/03/03 18:54:13 Made the logic much more explicit (and verbose).
+ // May-inline-in-loop means that the function may not be inlined outside loops
+ // but may be inlined in a loop.
+ static const int _mayInlineInLoop = 1;
+ // The function can be inlined in a loop, but not outside.
+ static const int _canInlineInLoop = 2;
+ // May-inline means that we know that it can be inlined inside a loop, but
+ // don't know about the general case yet.
+ static const int _mayInline = 3;
+ static const int _canInline = 4;
+ static const int _mustInline = 5;
+
+ final Map<FunctionElement, int> _cachedDecisions =
+ new Map<FunctionElement, int>();
+
+ // Returns `true`/`false` if we have a cached decision.
+ // Returns `null` otherwise.
bool canInline(FunctionElement element, {bool insideLoop}) {
- return insideLoop ? canBeInlinedInsideLoop[element] : canBeInlined[element];
+ int decision = _cachedDecisions[element];
+ if (decision == null) return null;
+ if (insideLoop) {
+ // We might be able to inline inside a loop, but don't know it yet.
+ if (decision == _mayInlineInLoop) return null;
+ return (decision >= _canInlineInLoop);
+ }
+ if (decision == _mayInline) return null;
+ return decision >= _canInline;
}
void markAsInlinable(FunctionElement element, {bool insideLoop}) {
+ int oldDecision = _cachedDecisions[element];
+ assert(oldDecision != _mustNotInline);
+
if (insideLoop) {
- canBeInlinedInsideLoop[element] = true;
+ if (oldDecision == null) {
+ // We know that it can be inlined in a loop, but don't know about the
+ // non-loop case yet.
+ _cachedDecisions[element] = _mayInline;
+ } else if (oldDecision == _mayInlineInLoop) {
+ _cachedDecisions[element] = _canInlineInLoop;
+ }
} else {
- // If we can inline a function outside a loop then we should do it inside
- // a loop as well.
- canBeInlined[element] = true;
- canBeInlinedInsideLoop[element] = true;
+ if (oldDecision == null || oldDecision <= _mayInline) {
+ _cachedDecisions[element] = _canInline;
+ }
}
}
- void markAsNonInlinable(FunctionElement element, {bool insideLoop}) {
- if (insideLoop == null || insideLoop) {
- // If we can't inline a function inside a loop, then we should not inline
- // it outside a loop either.
- canBeInlined[element] = false;
- canBeInlinedInsideLoop[element] = false;
+ void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) {
+ assert(_cachedDecisions[element] != _mustInline);
+
+ if (insideLoop) {
+ _cachedDecisions[element] = _mustNotInline;
} else {
- canBeInlined[element] = false;
+ // We can't inline outside a loop, but we might still be allowed to do it
+ // outside.
+ int oldDecision = _cachedDecisions[element];
+ if (oldDecision == null) {
+ _cachedDecisions[element] = _mayInlineInLoop;
+ } else if (oldDecision == _mayInline) {
+ // We already knew that the function could be inlined inside a loop, but
+ // didn't have information about the non-loop case. Now we know that it
+ // can't be inlined outside a loop.
+ _cachedDecisions[element] = _canInlineInLoop;
+ }
}
}
+
+ void markAsMustInline(FunctionElement element) {
+ _cachedDecisions[element] = _mustInline;
+ }
}
class JavaScriptBackend extends Backend {
@@ -84,22 +122,10 @@ class JavaScriptBackend extends Backend {
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>> {
- };
-
String get patchVersion => USE_NEW_EMITTER ? 'new' : 'old';
final Annotations annotations = new Annotations();
- /// 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;
@@ -174,6 +200,7 @@ class JavaScriptBackend extends Backend {
ClassElement noSideEffectsClass;
ClassElement noThrowsClass;
ClassElement noInlineClass;
+ ClassElement forceInlineClass;
ClassElement irRepresentationClass;
Element getInterceptorMethod;
@@ -961,26 +988,6 @@ 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) {
@@ -1869,6 +1876,7 @@ class JavaScriptBackend extends Backend {
noSideEffectsClass = findClass('NoSideEffects');
noThrowsClass = findClass('NoThrows');
noInlineClass = findClass('NoInline');
+ forceInlineClass = findClass('ForceInline');
irRepresentationClass = findClass('IrRepresentation');
getIsolateAffinityTagMarker = findMethod('getIsolateAffinityTag');
@@ -2325,6 +2333,7 @@ class JavaScriptBackend extends Backend {
LibraryElement library = element.library;
if (!library.isPlatformLibrary && !library.canUseNative) return;
bool hasNoInline = false;
+ bool hasForceInline = false;
bool hasNoThrows = false;
bool hasNoSideEffects = false;
for (MetadataAnnotation metadata in element.metadata) {
@@ -2332,7 +2341,15 @@ class JavaScriptBackend extends Backend {
if (!metadata.constant.value.isConstructedObject) continue;
ObjectConstantValue value = metadata.constant.value;
ClassElement cls = value.type.element;
- if (cls == noInlineClass) {
+ if (cls == forceInlineClass) {
+ hasForceInline = true;
+ if (VERBOSE_OPTIMIZER_HINTS) {
+ compiler.reportHint(element,
+ MessageKind.GENERIC,
+ {'text': "Must inline"});
+ }
+ inlineCache.markAsMustInline(element);
+ } else if (cls == noInlineClass) {
hasNoInline = true;
if (VERBOSE_OPTIMIZER_HINTS) {
compiler.reportHint(element,
@@ -2363,6 +2380,10 @@ class JavaScriptBackend extends Backend {
compiler.world.registerSideEffectsFree(element);
}
}
+ if (hasForceInline && hasNoInline) {
+ compiler.internalError(element,
+ "@ForceInline() must not be used with @NoInline.");
+ }
if (hasNoThrows && !hasNoInline) {
compiler.internalError(element,
"@NoThrows() should always be combined with @NoInline.");
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698