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

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: 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 5279a74f499e883357e4a5e10c5440dcc8a2d304..46ea69240f2a0a5f2c21c0a18ebc214cd28e8b9e 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -24,41 +24,68 @@ abstract class FunctionCompiler {
* Invariants:
* canInline(function) implies canInline(function, insideLoop:true)
* !canInline(function, insideLoop: true) implies !canInline(function)
+ * mustInline(function) implies canInline.
*/
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;
+ // May-inline in loop means that we don't know yet.
+ static const int _mayInlineInLoop = 1;
+ static const int _canInlineInLoop = 2;
+ static const int _canInline = 3;
+ static const int _mustInline = 4;
+
+ 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);
+ }
+ return decision >= _canInline;
+ }
+
+ bool mustInline(FunctionElement element) {
+ return _cachedDecisions[element] == _mustInline;
}
void markAsInlinable(FunctionElement element, {bool insideLoop}) {
- if (insideLoop) {
- canBeInlinedInsideLoop[element] = true;
- } 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;
+ int oldDecision = _cachedDecisions[element];
+ assert(oldDecision != 0);
+ if (oldDecision == null) oldDecision = _mustNotInline;
+
+ int newDecision = insideLoop ? _canInlineInLoop : _canInline;
+
+ if (newDecision > oldDecision) {
+ _cachedDecisions[element] = newDecision;
}
}
void markAsNonInlinable(FunctionElement element, {bool insideLoop}) {
+ assert(_cachedDecisions[element] != _mustInline);
+
if (insideLoop == null || insideLoop) {
Johnni Winther 2015/03/02 10:02:28 Why allow [insideLoop] to be null. Shouldn't the d
floitsch 2015/03/02 15:18:29 Done.
- // 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;
+ _cachedDecisions[element] = _mustNotInline;
} else {
- canBeInlined[element] = false;
+ // We can't inline outside a loop, but we might still be allowed to do it
+ // outside.
+ // If the cached decision already has a value we must not change it.
+ // Otherwise mark this function as potentially inlinable inside a loop.
+ int oldDecision = _cachedDecisions[element];
+ if (oldDecision == null) {
+ _cachedDecisions[element] = _mayInlineInLoop;
+ }
}
}
+
+ void markAsMustInline(FunctionElement element) {
+ _cachedDecisions[element] = _mustInline;
+ }
}
class JavaScriptBackend extends Backend {
@@ -84,22 +111,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 +189,7 @@ class JavaScriptBackend extends Backend {
ClassElement noSideEffectsClass;
ClassElement noThrowsClass;
ClassElement noInlineClass;
+ ClassElement forceInlineClass;
ClassElement irRepresentationClass;
Element getInterceptorMethod;
@@ -960,26 +976,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) {
@@ -1868,6 +1864,7 @@ class JavaScriptBackend extends Backend {
noSideEffectsClass = findClass('NoSideEffects');
noThrowsClass = findClass('NoThrows');
noInlineClass = findClass('NoInline');
+ forceInlineClass = findClass('ForceInline');
irRepresentationClass = findClass('IrRepresentation');
getIsolateAffinityTagMarker = findMethod('getIsolateAffinityTag');
@@ -2324,6 +2321,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) {
@@ -2331,7 +2329,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,
@@ -2362,6 +2368,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