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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart

Issue 11316354: Re-apply "Move the handling of operator[] into the new interceptors." (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 abstract class OptimizationPhase { 7 abstract class OptimizationPhase {
8 String get name; 8 String get name;
9 void visitGraph(HGraph graph); 9 void visitGraph(HGraph graph);
10 } 10 }
11 11
12 class SsaOptimizerTask extends CompilerTask { 12 class SsaOptimizerTask extends CompilerTask {
13 final JavaScriptBackend backend; 13 final JavaScriptBackend backend;
14 SsaOptimizerTask(JavaScriptBackend backend) 14 SsaOptimizerTask(JavaScriptBackend backend)
15 : this.backend = backend, 15 : this.backend = backend,
16 super(backend.compiler); 16 super(backend.compiler);
17 String get name => 'SSA optimizer'; 17 String get name => 'SSA optimizer';
18 Compiler get compiler => backend.compiler; 18 Compiler get compiler => backend.compiler;
19 19
20 void runPhases(HGraph graph, List<OptimizationPhase> phases) { 20 void runPhases(HGraph graph, List<OptimizationPhase> phases) {
21 for (OptimizationPhase phase in phases) { 21 for (OptimizationPhase phase in phases) {
22 runPhase(graph, phase); 22 runPhase(graph, phase);
23 } 23 }
24 } 24 }
25 25
26 void runPhase(HGraph graph, OptimizationPhase phase) { 26 void runPhase(HGraph graph, OptimizationPhase phase) {
27 phase.visitGraph(graph); 27 phase.visitGraph(graph);
28 compiler.tracer.traceGraph(phase.name, graph); 28 compiler.tracer.traceGraph(phase.name, graph);
29 assert(graph.isValid());
29 } 30 }
30 31
31 void optimize(WorkItem work, HGraph graph, bool speculative) { 32 void optimize(WorkItem work, HGraph graph, bool speculative) {
32 ConstantSystem constantSystem = compiler.backend.constantSystem; 33 ConstantSystem constantSystem = compiler.backend.constantSystem;
33 JavaScriptItemCompilationContext context = work.compilationContext; 34 JavaScriptItemCompilationContext context = work.compilationContext;
34 HTypeMap types = context.types; 35 HTypeMap types = context.types;
35 measure(() { 36 measure(() {
36 List<OptimizationPhase> phases = <OptimizationPhase>[ 37 List<OptimizationPhase> phases = <OptimizationPhase>[
37 // Run trivial constant folding first to optimize 38 // Run trivial constant folding first to optimize
38 // some patterns useful for type conversion. 39 // some patterns useful for type conversion.
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 HInstruction operand = node.operand; 200 HInstruction operand = node.operand;
200 if (operand is HConstant) { 201 if (operand is HConstant) {
201 UnaryOperation operation = node.operation(constantSystem); 202 UnaryOperation operation = node.operation(constantSystem);
202 HConstant receiver = operand; 203 HConstant receiver = operand;
203 Constant folded = operation.fold(receiver.constant); 204 Constant folded = operation.fold(receiver.constant);
204 if (folded != null) return graph.addConstant(folded); 205 if (folded != null) return graph.addConstant(folded);
205 } 206 }
206 return node; 207 return node;
207 } 208 }
208 209
209 HInstruction handleInterceptorCall(HInvokeDynamic node) { 210 HInstruction handleInterceptorCall(HInvokeDynamicMethod node) {
210 if (node is !HInvokeDynamicMethod) return null;
211 HInstruction input = node.inputs[1]; 211 HInstruction input = node.inputs[1];
212 if (input.isString(types) 212 if (input.isString(types)
213 && node.selector.name == const SourceString('toString')) { 213 && node.selector.name == const SourceString('toString')) {
214 return node.inputs[1]; 214 return node.inputs[1];
215 } 215 }
216 // Check if this call does not need to be intercepted. 216 // Check if this call does not need to be intercepted.
217 HType type = types[input]; 217 HType type = types[input];
218 var interceptor = node.inputs[0]; 218 var interceptor = node.inputs[0];
219 if (interceptor is !HThis && !type.canBePrimitive()) { 219 if (interceptor is !HThis && !type.canBePrimitive()) {
220 // If the type can be null, and the intercepted method can be in 220 // If the type can be null, and the intercepted method can be in
221 // the object class, keep the interceptor. 221 // the object class, keep the interceptor.
222 if (type.canBeNull() 222 if (type.canBeNull()
223 && interceptor.interceptedClasses.contains(compiler.objectClass)) { 223 && interceptor.interceptedClasses.contains(compiler.objectClass)) {
224 return node; 224 return node;
225 } 225 }
226 // Change the call to a regular invoke dynamic call. 226 // Change the call to a regular invoke dynamic call.
227 return new HInvokeDynamicMethod( 227 return new HInvokeDynamicMethod(
228 node.selector, node.inputs.getRange(1, node.inputs.length - 1)); 228 node.selector, node.inputs.getRange(1, node.inputs.length - 1));
229 } 229 }
230 230
231 Selector selector = node.selector; 231 Selector selector = node.selector;
232
233 if (node.isIndexOperatorOnIndexablePrimitive(types)) {
234 return new HIndex(node.inputs[1], node.inputs[2]);
235 }
236
232 SourceString selectorName = selector.name; 237 SourceString selectorName = selector.name;
233 Element target; 238 Element target;
234 if (input.isExtendableArray(types)) { 239 if (input.isExtendableArray(types)) {
235 if (selectorName == backend.jsArrayRemoveLast.name 240 if (selectorName == backend.jsArrayRemoveLast.name
236 && selector.argumentCount == 0) { 241 && selector.argumentCount == 0) {
237 target = backend.jsArrayRemoveLast; 242 target = backend.jsArrayRemoveLast;
238 } else if (selectorName == backend.jsArrayAdd.name 243 } else if (selectorName == backend.jsArrayAdd.name
239 && selector.argumentCount == 1 244 && selector.argumentCount == 1
240 && selector.namedArgumentCount == 0 245 && selector.namedArgumentCount == 0
241 && !compiler.enableTypeAssertions) { 246 && !compiler.enableTypeAssertions) {
(...skipping 28 matching lines...) Expand all
270 && node.inputs[1].isInteger(types); 275 && node.inputs[1].isInteger(types);
271 } 276 }
272 277
273 HInstruction visitInvokeStatic(HInvokeStatic node) { 278 HInstruction visitInvokeStatic(HInvokeStatic node) {
274 if (isFixedSizeListConstructor(node)) { 279 if (isFixedSizeListConstructor(node)) {
275 node.guaranteedType = HType.FIXED_ARRAY; 280 node.guaranteedType = HType.FIXED_ARRAY;
276 } 281 }
277 return node; 282 return node;
278 } 283 }
279 284
280 HInstruction visitInvokeDynamic(HInvokeDynamic node) { 285 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
281 if (node.isInterceptorCall) return handleInterceptorCall(node); 286 if (node.isInterceptorCall) return handleInterceptorCall(node);
282 HType receiverType = types[node.receiver]; 287 HType receiverType = types[node.receiver];
283 if (receiverType.isExact()) { 288 if (receiverType.isExact()) {
284 HBoundedType type = receiverType; 289 HBoundedType type = receiverType;
285 Element element = type.lookupMember(node.selector.name); 290 Element element = type.lookupMember(node.selector.name);
286 // TODO(ngeoffray): Also fold if it's a getter or variable. 291 // TODO(ngeoffray): Also fold if it's a getter or variable.
287 if (element != null && element.isFunction()) { 292 if (element != null && element.isFunction()) {
288 if (node.selector.applies(element, compiler)) { 293 if (node.selector.applies(element, compiler)) {
289 FunctionElement method = element; 294 FunctionElement method = element;
290 FunctionSignature parameters = method.computeSignature(compiler); 295 FunctionSignature parameters = method.computeSignature(compiler);
291 if (parameters.optionalParameterCount == 0) { 296 if (parameters.optionalParameterCount == 0) {
292 node.element = element; 297 node.element = element;
293 } 298 }
294 // TODO(ngeoffray): If the method has optional parameters, 299 // TODO(ngeoffray): If the method has optional parameters,
295 // we should pass the default values here. 300 // we should pass the default values here.
296 } 301 }
297 } 302 }
298 } 303 }
299 return node; 304 return node;
300 } 305 }
301 306
302 /** 307 /**
303 * Turns a primitive instruction (e.g. [HIndex], [HAdd], ...) into a 308 * Turns a primitive instruction (e.g. [HIndex], [HAdd], ...) into a
304 * [HInvokeDynamic] because we know the receiver is not a JS 309 * [HInvokeDynamic] because we know the receiver is not a JS
305 * primitive object. 310 * primitive object.
306 */ 311 */
307 HInstruction fromPrimitiveInstructionToDynamicInvocation(HInvokeStatic node, 312 HInstruction fromPrimitiveInstructionToDynamicInvocation(HInstruction node,
308 Selector selector) { 313 Selector selector) {
309 HBoundedType type = types[node.inputs[1]]; 314 HBoundedType type = types[node.inputs[1]];
310 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 315 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
311 selector, 316 selector,
312 node.inputs.getRange(1, node.inputs.length - 1)); 317 node.inputs.getRange(1, node.inputs.length - 1));
313 if (type.isExact()) { 318 if (type.isExact()) {
314 HBoundedType concrete = type; 319 HBoundedType concrete = type;
315 result.element = concrete.lookupMember(selector.name); 320 result.element = concrete.lookupMember(selector.name);
316 } 321 }
317 return result; 322 return result;
318 } 323 }
319 324
320 HInstruction visitIntegerCheck(HIntegerCheck node) { 325 HInstruction visitIntegerCheck(HIntegerCheck node) {
321 HInstruction value = node.value; 326 HInstruction value = node.value;
322 if (value.isInteger(types)) return value; 327 if (value.isInteger(types)) return value;
323 if (value.isConstant()) { 328 if (value.isConstant()) {
324 HConstant constantInstruction = value; 329 HConstant constantInstruction = value;
325 assert(!constantInstruction.constant.isInt()); 330 assert(!constantInstruction.constant.isInt());
326 if (!constantSystem.isInt(constantInstruction.constant)) { 331 if (!constantSystem.isInt(constantInstruction.constant)) {
327 // -0.0 is a double but will pass the runtime integer check. 332 // -0.0 is a double but will pass the runtime integer check.
328 node.alwaysFalse = true; 333 node.alwaysFalse = true;
329 } 334 }
330 } 335 }
331 return node; 336 return node;
332 } 337 }
333 338
334
335 HInstruction visitIndex(HIndex node) {
336 if (!node.receiver.canBePrimitive(types)) {
337 Selector selector = new Selector.index();
338 return fromPrimitiveInstructionToDynamicInvocation(node, selector);
339 }
340 return node;
341 }
342
343 HInstruction visitIndexAssign(HIndexAssign node) { 339 HInstruction visitIndexAssign(HIndexAssign node) {
344 if (!node.receiver.canBePrimitive(types)) { 340 if (!node.receiver.canBePrimitive(types)) {
345 Selector selector = new Selector.indexSet(); 341 Selector selector = new Selector.indexSet();
346 return fromPrimitiveInstructionToDynamicInvocation(node, selector); 342 return fromPrimitiveInstructionToDynamicInvocation(node, selector);
347 } 343 }
348 return node; 344 return node;
349 } 345 }
350 346
351 HInstruction visitInvokeBinary(HInvokeBinary node) { 347 HInstruction visitInvokeBinary(HInvokeBinary node) {
352 HInstruction left = node.left; 348 HInstruction left = node.left;
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 HIntegerCheck check = new HIntegerCheck(value); 792 HIntegerCheck check = new HIntegerCheck(value);
797 node.block.addBefore(node, check); 793 node.block.addBefore(node, check);
798 Set<HInstruction> dominatedUsers = value.dominatedUsers(node); 794 Set<HInstruction> dominatedUsers = value.dominatedUsers(node);
799 for (HInstruction user in dominatedUsers) { 795 for (HInstruction user in dominatedUsers) {
800 user.changeUse(value, check); 796 user.changeUse(value, check);
801 } 797 }
802 return check; 798 return check;
803 } 799 }
804 800
805 void visitIndex(HIndex node) { 801 void visitIndex(HIndex node) {
806 if (!node.receiver.isIndexablePrimitive(types)) return;
807 if (boundsChecked.contains(node)) return; 802 if (boundsChecked.contains(node)) return;
808 HInstruction index = node.index; 803 HInstruction index = node.index;
809 if (!node.index.isInteger(types)) { 804 if (!node.index.isInteger(types)) {
810 index = insertIntegerCheck(node, index); 805 index = insertIntegerCheck(node, index);
811 } 806 }
812 index = insertBoundsCheck(node, node.receiver, index); 807 index = insertBoundsCheck(node, node.receiver, index);
813 node.changeUse(node.index, index); 808 node.changeUse(node.index, index);
814 assert(node.isBuiltin(types));
815 } 809 }
816 810
817 void visitIndexAssign(HIndexAssign node) { 811 void visitIndexAssign(HIndexAssign node) {
818 if (!node.receiver.isMutableArray(types)) return; 812 if (!node.receiver.isMutableArray(types)) return;
819 if (boundsChecked.contains(node)) return; 813 if (boundsChecked.contains(node)) return;
820 HInstruction index = node.index; 814 HInstruction index = node.index;
821 if (!node.index.isInteger(types)) { 815 if (!node.index.isInteger(types)) {
822 index = insertIntegerCheck(node, index); 816 index = insertIntegerCheck(node, index);
823 } 817 }
824 index = insertBoundsCheck(node, node.receiver, index); 818 index = insertBoundsCheck(node, node.receiver, index);
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 HInstruction receiver = interceptor.receiver; 1471 HInstruction receiver = interceptor.receiver;
1478 for (var user in receiver.usedBy) { 1472 for (var user in receiver.usedBy) {
1479 if (user is HInterceptor && interceptor.dominates(user)) { 1473 if (user is HInterceptor && interceptor.dominates(user)) {
1480 user.interceptedClasses = interceptor.interceptedClasses; 1474 user.interceptedClasses = interceptor.interceptedClasses;
1481 } 1475 }
1482 } 1476 }
1483 } 1477 }
1484 1478
1485 // TODO(ngeoffray): Also implement it for non-intercepted calls. 1479 // TODO(ngeoffray): Also implement it for non-intercepted calls.
1486 } 1480 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698