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

Unified Diff: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart

Issue 829913006: Optimize is-check to instanceof when it eliminates an interceptor (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 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 | « pkg/compiler/lib/src/ssa/codegen_helpers.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 79a527cf92b5680af27fcdbb3175887c7be97769..3a0f46787611b4ba445ddf7d5a93aea16d08c351 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -10,15 +10,18 @@ part of ssa;
* 1) If the interceptor is for an object whose type is known, it
* tries to use a constant interceptor instead.
*
- * 2) It specializes interceptors based on the selectors it is being
- * called with.
+ * 2) Interceptors are specialized based on the selector it is used with.
*
- * 3) If we know the object is not intercepted, we just use it
+ * 3) If we know the object is not intercepted, we just use the object
* instead.
*
- * 4) It replaces all interceptors that are used only once with
- * one-shot interceptors. It saves code size and makes the receiver of
- * an intercepted call a candidate for being generated at use site.
+ * 4) Single use interceptors at dynamic invoke sites are replaced with 'one
+ * shot interceptors' which are synthesized static helper functions that fetch
+ * the interceptor and then call the method. This saves code size and makes the
+ * receiver of an intercepted call a candidate for being generated at use site.
+ *
+ * 5) Some HIs operations on an interceptor are replaced with a HIs version that
+ * uses 'instanceof' rather than testing a type flag.
*
*/
class SsaSimplifyInterceptors extends HBaseVisitor
@@ -56,6 +59,17 @@ class SsaSimplifyInterceptors extends HBaseVisitor
if (!invoke.isInterceptedCall) return false;
var interceptor = invoke.inputs[0];
if (interceptor is! HInterceptor) return false;
+
+ // TODO(sra): Move this per-call code to visitInterceptor.
+ //
+ // The interceptor is visited first, so we get here only when the
+ // interceptor was not rewritten to a single shared replacement. I'm not
+ // sure we should substitute a constant interceptor on a per-call basis if
+ // the interceptor is already available in a local variable, but it is
+ // possible that all uses can be rewritten to use different constants.
+
+ // TODO(sra): Also do self-interceptor rewrites on a per-use basis.
+
HInstruction constant = tryComputeConstantInterceptor(
invoke.inputs[1], interceptor.interceptedClasses);
if (constant != null) {
@@ -238,8 +252,18 @@ class SsaSimplifyInterceptors extends HBaseVisitor
}
}
+ node.interceptedClasses = interceptedClasses;
+
HInstruction receiver = node.receiver;
+ // TODO(sra): We should consider each use individually and then all uses
+ // together. Each use might permit a different rewrite due to a refined
+ // receiver type. Self-interceptor rewrites are always beneficial since the
+ // receiver is live at a invocation. Constant-interceptor rewrites are only
+ // guaranteed to be beneficial if they can eliminate the need for the
+ // interceptor or reduce the uses to one that can be simplified with a
+ // one-shot interceptor or optimized is-check.
+
if (canUseSelfForInterceptor(receiver, interceptedClasses)) {
return rewriteToUseSelfAsInterceptor(node, receiver);
}
@@ -252,32 +276,50 @@ class SsaSimplifyInterceptors extends HBaseVisitor
return false;
}
- node.interceptedClasses = interceptedClasses;
-
- // Try creating a one-shot interceptor.
+ // Try creating a one-shot interceptor or optimized is-check
if (compiler.hasIncrementalSupport) return false;
if (node.usedBy.length != 1) return false;
- if (node.usedBy[0] is !HInvokeDynamic) return false;
-
- HInvokeDynamic user = node.usedBy[0];
+ HInstruction user = node.usedBy.single;
- // If [node] was loop hoisted, we keep the interceptor.
+ // If the interceptor [node] was loop hoisted, we keep the interceptor.
if (!user.hasSameLoopHeaderAs(node)) return false;
- // Replace the user with a [HOneShotInterceptor].
- HConstant nullConstant = graph.addConstantNull(compiler);
- List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
- inputs[0] = nullConstant;
- HOneShotInterceptor interceptor = new HOneShotInterceptor(
- user.selector, inputs, user.instructionType, node.interceptedClasses);
- interceptor.sourcePosition = user.sourcePosition;
- interceptor.sourceElement = user.sourceElement;
-
- HBasicBlock block = user.block;
- block.addAfter(user, interceptor);
- block.rewrite(user, interceptor);
- block.remove(user);
- return true;
+ bool replaceUserWith(HInstruction replacement) {
+ HBasicBlock block = user.block;
+ block.addAfter(user, replacement);
+ block.rewrite(user, replacement);
+ block.remove(user);
+ return false;
+ }
+
+ if (user is HIs) {
+ // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite
+ // "getInterceptor(x).$isT" to "x instanceof T".
+ if (node == user.interceptor) {
+ JavaScriptBackend backend = compiler.backend;
+ if (backend.mayGenerateInstanceofCheck(user.typeExpression)) {
+ HInstruction instanceofCheck = new HIs.instanceOf(
+ user.typeExpression, user.expression, user.instructionType);
+ instanceofCheck.sourcePosition = user.sourcePosition;
+ instanceofCheck.sourceElement = user.sourceElement;
+ return replaceUserWith(instanceofCheck);
+ }
+ }
+ } else if (user is HInvokeDynamic) {
+ if (node == user.inputs[0]) {
+ // Replace the user with a [HOneShotInterceptor].
+ HConstant nullConstant = graph.addConstantNull(compiler);
+ List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
+ inputs[0] = nullConstant;
+ HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor(
+ user.selector, inputs, user.instructionType, interceptedClasses);
+ oneShotInterceptor.sourcePosition = user.sourcePosition;
+ oneShotInterceptor.sourceElement = user.sourceElement;
+ return replaceUserWith(oneShotInterceptor);
+ }
+ }
+
+ return false;
}
bool rewriteToUseSelfAsInterceptor(HInterceptor node, HInstruction receiver) {
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen_helpers.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698