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

Side by Side Diff: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart

Issue 1050343002: Revert "Avoid getInterceptor calls in cases were the interceptor would be constant if it were not `… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * This phase simplifies interceptors in multiple ways: 8 * This phase simplifies interceptors in multiple ways:
9 * 9 *
10 * 1) If the interceptor is for an object whose type is known, it 10 * 1) If the interceptor is for an object whose type is known, it
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 HInstruction tryComputeConstantInterceptor( 103 HInstruction tryComputeConstantInterceptor(
104 HInstruction input, 104 HInstruction input,
105 Set<ClassElement> interceptedClasses) { 105 Set<ClassElement> interceptedClasses) {
106 if (input == graph.explicitReceiverParameter) { 106 if (input == graph.explicitReceiverParameter) {
107 // If `explicitReceiverParameter` is set it means the current method is an 107 // If `explicitReceiverParameter` is set it means the current method is an
108 // interceptor method, and `this` is the interceptor. The caller just did 108 // interceptor method, and `this` is the interceptor. The caller just did
109 // `getInterceptor(foo).currentMethod(foo)` to enter the current method. 109 // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
110 return graph.thisInstruction; 110 return graph.thisInstruction;
111 } 111 }
112 112
113 ClassElement constantInterceptor = tryComputeConstantInterceptorFromType( 113 ClassElement constantInterceptor;
114 input.instructionType, interceptedClasses);
115
116 if (constantInterceptor == null) return null;
117
118 // If we just happen to be in an instance method of the constant
119 // interceptor, `this` is a shorter alias.
120 if (constantInterceptor == work.element.enclosingClass &&
121 graph.thisInstruction != null) {
122 return graph.thisInstruction;
123 }
124
125 ConstantValue constant =
126 new InterceptorConstantValue(constantInterceptor.thisType);
127 return graph.addConstant(constant, compiler);
128 }
129
130 ClassElement tryComputeConstantInterceptorFromType(
131 TypeMask type,
132 Set<ClassElement> interceptedClasses) {
133
134 ClassWorld classWorld = compiler.world; 114 ClassWorld classWorld = compiler.world;
135 JavaScriptBackend backend = compiler.backend; 115 JavaScriptBackend backend = compiler.backend;
136 if (type.isNullable) { 116 if (input.canBeNull()) {
137 if (type.isEmpty) { 117 if (input.isNull()) {
138 return backend.jsNullClass; 118 constantInterceptor = backend.jsNullClass;
139 } 119 }
140 } else if (type.containsOnlyInt(classWorld)) { 120 } else if (input.isInteger(compiler)) {
141 return backend.jsIntClass; 121 constantInterceptor = backend.jsIntClass;
142 } else if (type.containsOnlyDouble(classWorld)) { 122 } else if (input.isDouble(compiler)) {
143 return backend.jsDoubleClass; 123 constantInterceptor = backend.jsDoubleClass;
144 } else if (type.containsOnlyBool(classWorld)) { 124 } else if (input.isBoolean(compiler)) {
145 return backend.jsBoolClass; 125 constantInterceptor = backend.jsBoolClass;
146 } else if (type.containsOnlyString(classWorld)) { 126 } else if (input.isString(compiler)) {
147 return backend.jsStringClass; 127 constantInterceptor = backend.jsStringClass;
148 } else if (type.satisfies(backend.jsArrayClass, classWorld)) { 128 } else if (input.isArray(compiler)) {
149 return backend.jsArrayClass; 129 constantInterceptor = backend.jsArrayClass;
150 } else if (type.containsOnlyNum(classWorld) && 130 } else if (input.isNumber(compiler) &&
151 !interceptedClasses.contains(backend.jsIntClass) && 131 !interceptedClasses.contains(backend.jsIntClass) &&
152 !interceptedClasses.contains(backend.jsDoubleClass)) { 132 !interceptedClasses.contains(backend.jsDoubleClass)) {
153 // If the method being intercepted is not defined in [int] or [double] we 133 // If the method being intercepted is not defined in [int] or [double] we
154 // can safely use the number interceptor. This is because none of the 134 // can safely use the number interceptor. This is because none of the
155 // [int] or [double] methods are called from a method defined on [num]. 135 // [int] or [double] methods are called from a method defined on [num].
156 return backend.jsNumberClass; 136 constantInterceptor = backend.jsNumberClass;
157 } else { 137 } else {
158 // Try to find constant interceptor for a native class. If the receiver 138 // Try to find constant interceptor for a native class. If the receiver
159 // is constrained to a leaf native class, we can use the class's 139 // is constrained to a leaf native class, we can use the class's
160 // interceptor directly. 140 // interceptor directly.
161 141
162 // TODO(sra): Key DOM classes like Node, Element and Event are not leaf 142 // TODO(sra): Key DOM classes like Node, Element and Event are not leaf
163 // classes. When the receiver type is not a leaf class, we might still be 143 // classes. When the receiver type is not a leaf class, we might still be
164 // able to use the receiver class as a constant interceptor. It is 144 // able to use the receiver class as a constant interceptor. It is
165 // usually the case that methods defined on a non-leaf class don't test 145 // usually the case that methods defined on a non-leaf class don't test
166 // for a subclass or call methods defined on a subclass. Provided the 146 // for a subclass or call methods defined on a subclass. Provided the
167 // code is completely insensitive to the specific instance subclasses, we 147 // code is completely insensitive to the specific instance subclasses, we
168 // can use the non-leaf class directly. 148 // can use the non-leaf class directly.
169 ClassElement element = type.singleClass(classWorld); 149 ClassElement element = input.instructionType.singleClass(classWorld);
170 if (element != null && element.isNative) { 150 if (element != null && element.isNative) {
171 return element; 151 constantInterceptor = element;
172 } 152 }
173 } 153 }
174 154
175 return null; 155 if (constantInterceptor == null) return null;
156
157 // If we just happen to be in an instance method of the constant
158 // interceptor, `this` is a shorter alias.
159 if (constantInterceptor == work.element.enclosingClass &&
160 graph.thisInstruction != null) {
161 return graph.thisInstruction;
162 }
163
164 ConstantValue constant =
165 new InterceptorConstantValue(constantInterceptor.thisType);
166 return graph.addConstant(constant, compiler);
176 } 167 }
177 168
178 HInstruction findDominator(Iterable<HInstruction> instructions) { 169 HInstruction findDominator(Iterable<HInstruction> instructions) {
179 HInstruction result; 170 HInstruction result;
180 L1: for (HInstruction candidate in instructions) { 171 L1: for (HInstruction candidate in instructions) {
181 for (HInstruction current in instructions) { 172 for (HInstruction current in instructions) {
182 if (current != candidate && !candidate.dominates(current)) continue L1; 173 if (current != candidate && !candidate.dominates(current)) continue L1;
183 } 174 }
184 result = candidate; 175 result = candidate;
185 break; 176 break;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 } 269 }
279 270
280 // Try computing a constant interceptor. 271 // Try computing a constant interceptor.
281 HInstruction constantInterceptor = 272 HInstruction constantInterceptor =
282 tryComputeConstantInterceptor(receiver, interceptedClasses); 273 tryComputeConstantInterceptor(receiver, interceptedClasses);
283 if (constantInterceptor != null) { 274 if (constantInterceptor != null) {
284 node.block.rewrite(node, constantInterceptor); 275 node.block.rewrite(node, constantInterceptor);
285 return false; 276 return false;
286 } 277 }
287 278
288 // Do we have an 'almost constant' interceptor? The receiver could be
289 // `null` but not any other JavaScript falsy value, `null` values cause
290 // `NoSuchMethodError`s, and if the receiver was not null we would have a
291 // constant interceptor `C`. Then we can use `(receiver && C)` for the
292 // interceptor.
293 if (receiver.canBeNull() && !node.isConditionalConstantInterceptor) {
294 if (!interceptedClasses.contains(backend.jsNullClass)) {
295 // Can use `(receiver && C)` only if receiver is either null or truthy.
296 if (!(receiver.canBePrimitiveNumber(compiler) ||
297 receiver.canBePrimitiveBoolean(compiler) ||
298 receiver.canBePrimitiveString(compiler))) {
299 ClassElement interceptorClass = tryComputeConstantInterceptorFromType(
300 receiver.instructionType.nonNullable(), interceptedClasses);
301 if (interceptorClass != null) {
302 HInstruction constantInstruction =
303 graph.addConstant(
304 new InterceptorConstantValue(interceptorClass.thisType),
305 compiler);
306 node.conditionalConstantInterceptor = constantInstruction;
307 constantInstruction.usedBy.add(node);
308 return false;
309 }
310 }
311 }
312 }
313
314 // Try creating a one-shot interceptor or optimized is-check 279 // Try creating a one-shot interceptor or optimized is-check
315 if (compiler.hasIncrementalSupport) return false; 280 if (compiler.hasIncrementalSupport) return false;
316 if (node.usedBy.length != 1) return false; 281 if (node.usedBy.length != 1) return false;
317 HInstruction user = node.usedBy.single; 282 HInstruction user = node.usedBy.single;
318 283
319 // If the interceptor [node] was loop hoisted, we keep the interceptor. 284 // If the interceptor [node] was loop hoisted, we keep the interceptor.
320 if (!user.hasSameLoopHeaderAs(node)) return false; 285 if (!user.hasSameLoopHeaderAs(node)) return false;
321 286
322 bool replaceUserWith(HInstruction replacement) { 287 bool replaceUserWith(HInstruction replacement) {
323 HBasicBlock block = user.block; 288 HBasicBlock block = user.block;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 instruction = new HInvokeDynamicMethod( 364 instruction = new HInvokeDynamicMethod(
400 selector, inputs, node.instructionType, true); 365 selector, inputs, node.instructionType, true);
401 } 366 }
402 367
403 HBasicBlock block = node.block; 368 HBasicBlock block = node.block;
404 block.addAfter(node, instruction); 369 block.addAfter(node, instruction);
405 block.rewrite(node, instruction); 370 block.rewrite(node, instruction);
406 return true; 371 return true;
407 } 372 }
408 } 373 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698