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

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

Issue 11348316: 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 }
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 HInstruction operand = node.operand; 199 HInstruction operand = node.operand;
200 if (operand is HConstant) { 200 if (operand is HConstant) {
201 UnaryOperation operation = node.operation(constantSystem); 201 UnaryOperation operation = node.operation(constantSystem);
202 HConstant receiver = operand; 202 HConstant receiver = operand;
203 Constant folded = operation.fold(receiver.constant); 203 Constant folded = operation.fold(receiver.constant);
204 if (folded != null) return graph.addConstant(folded); 204 if (folded != null) return graph.addConstant(folded);
205 } 205 }
206 return node; 206 return node;
207 } 207 }
208 208
209 HInstruction handleInterceptorCall(HInvokeDynamic node) { 209 HInstruction handleInterceptorCall(HInvokeDynamicMethod node) {
210 if (node is !HInvokeDynamicMethod) return null;
211 HInstruction input = node.inputs[1]; 210 HInstruction input = node.inputs[1];
212 if (input.isString(types) 211 if (input.isString(types)
213 && node.selector.name == const SourceString('toString')) { 212 && node.selector.name == const SourceString('toString')) {
214 return node.inputs[1]; 213 return node.inputs[1];
215 } 214 }
216 // Check if this call does not need to be intercepted. 215 // Check if this call does not need to be intercepted.
217 HType type = types[input]; 216 HType type = types[input];
218 var interceptor = node.inputs[0]; 217 var interceptor = node.inputs[0];
219 if (interceptor is !HThis && !type.canBePrimitive()) { 218 if (interceptor is !HThis && !type.canBePrimitive()) {
220 // If the type can be null, and the intercepted method can be in 219 // If the type can be null, and the intercepted method can be in
221 // the object class, keep the interceptor. 220 // the object class, keep the interceptor.
222 if (type.canBeNull() 221 if (type.canBeNull()
223 && interceptor.interceptedClasses.contains(compiler.objectClass)) { 222 && interceptor.interceptedClasses.contains(compiler.objectClass)) {
224 return node; 223 return node;
225 } 224 }
226 // Change the call to a regular invoke dynamic call. 225 // Change the call to a regular invoke dynamic call.
227 return new HInvokeDynamicMethod( 226 return new HInvokeDynamicMethod(
228 node.selector, node.inputs.getRange(1, node.inputs.length - 1)); 227 node.selector, node.inputs.getRange(1, node.inputs.length - 1));
229 } 228 }
230 229
231 Selector selector = node.selector; 230 Selector selector = node.selector;
231
232 if (node.isIndexOperatorOnIndexablePrimitive(types)) {
233 return new HIndex(node.inputs[1], node.inputs[2]);
234 }
235
232 SourceString selectorName = selector.name; 236 SourceString selectorName = selector.name;
233 Element target; 237 Element target;
234 if (input.isExtendableArray(types)) { 238 if (input.isExtendableArray(types)) {
235 if (selectorName == backend.jsArrayRemoveLast.name 239 if (selectorName == backend.jsArrayRemoveLast.name
236 && selector.argumentCount == 0) { 240 && selector.argumentCount == 0) {
237 target = backend.jsArrayRemoveLast; 241 target = backend.jsArrayRemoveLast;
238 } else if (selectorName == backend.jsArrayAdd.name 242 } else if (selectorName == backend.jsArrayAdd.name
239 && selector.argumentCount == 1 243 && selector.argumentCount == 1
240 && selector.namedArgumentCount == 0 244 && selector.namedArgumentCount == 0
241 && !compiler.enableTypeAssertions) { 245 && !compiler.enableTypeAssertions) {
(...skipping 28 matching lines...) Expand all
270 && node.inputs[1].isInteger(types); 274 && node.inputs[1].isInteger(types);
271 } 275 }
272 276
273 HInstruction visitInvokeStatic(HInvokeStatic node) { 277 HInstruction visitInvokeStatic(HInvokeStatic node) {
274 if (isFixedSizeListConstructor(node)) { 278 if (isFixedSizeListConstructor(node)) {
275 node.guaranteedType = HType.FIXED_ARRAY; 279 node.guaranteedType = HType.FIXED_ARRAY;
276 } 280 }
277 return node; 281 return node;
278 } 282 }
279 283
280 HInstruction visitInvokeDynamic(HInvokeDynamic node) { 284 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
281 if (node.isInterceptorCall) return handleInterceptorCall(node); 285 if (node.isInterceptorCall) return handleInterceptorCall(node);
282 HType receiverType = types[node.receiver]; 286 HType receiverType = types[node.receiver];
283 if (receiverType.isExact()) { 287 if (receiverType.isExact()) {
284 HBoundedType type = receiverType; 288 HBoundedType type = receiverType;
285 Element element = type.lookupMember(node.selector.name); 289 Element element = type.lookupMember(node.selector.name);
286 // TODO(ngeoffray): Also fold if it's a getter or variable. 290 // TODO(ngeoffray): Also fold if it's a getter or variable.
287 if (element != null && element.isFunction()) { 291 if (element != null && element.isFunction()) {
288 if (node.selector.applies(element, compiler)) { 292 if (node.selector.applies(element, compiler)) {
289 FunctionElement method = element; 293 FunctionElement method = element;
290 FunctionSignature parameters = method.computeSignature(compiler); 294 FunctionSignature parameters = method.computeSignature(compiler);
291 if (parameters.optionalParameterCount == 0) { 295 if (parameters.optionalParameterCount == 0) {
292 node.element = element; 296 node.element = element;
293 } 297 }
294 // TODO(ngeoffray): If the method has optional parameters, 298 // TODO(ngeoffray): If the method has optional parameters,
295 // we should pass the default values here. 299 // we should pass the default values here.
296 } 300 }
297 } 301 }
298 } 302 }
299 return node; 303 return node;
300 } 304 }
301 305
302 /** 306 /**
303 * Turns a primitive instruction (e.g. [HIndex], [HAdd], ...) into a 307 * Turns a primitive instruction (e.g. [HIndex], [HAdd], ...) into a
304 * [HInvokeDynamic] because we know the receiver is not a JS 308 * [HInvokeDynamic] because we know the receiver is not a JS
305 * primitive object. 309 * primitive object.
306 */ 310 */
307 HInstruction fromPrimitiveInstructionToDynamicInvocation(HInvokeStatic node, 311 HInstruction fromPrimitiveInstructionToDynamicInvocation(HInstruction node,
308 Selector selector) { 312 Selector selector) {
309 HBoundedType type = types[node.inputs[1]]; 313 HBoundedType type = types[node.inputs[1]];
310 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 314 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
311 selector, 315 selector,
312 node.inputs.getRange(1, node.inputs.length - 1)); 316 node.inputs.getRange(1, node.inputs.length - 1));
313 if (type.isExact()) { 317 if (type.isExact()) {
314 HBoundedType concrete = type; 318 HBoundedType concrete = type;
315 result.element = concrete.lookupMember(selector.name); 319 result.element = concrete.lookupMember(selector.name);
316 } 320 }
317 return result; 321 return result;
318 } 322 }
319 323
320 HInstruction visitIntegerCheck(HIntegerCheck node) { 324 HInstruction visitIntegerCheck(HIntegerCheck node) {
321 HInstruction value = node.value; 325 HInstruction value = node.value;
322 if (value.isInteger(types)) return value; 326 if (value.isInteger(types)) return value;
323 if (value.isConstant()) { 327 if (value.isConstant()) {
324 HConstant constantInstruction = value; 328 HConstant constantInstruction = value;
325 assert(!constantInstruction.constant.isInt()); 329 assert(!constantInstruction.constant.isInt());
326 if (!constantSystem.isInt(constantInstruction.constant)) { 330 if (!constantSystem.isInt(constantInstruction.constant)) {
327 // -0.0 is a double but will pass the runtime integer check. 331 // -0.0 is a double but will pass the runtime integer check.
328 node.alwaysFalse = true; 332 node.alwaysFalse = true;
329 } 333 }
330 } 334 }
331 return node; 335 return node;
332 } 336 }
333 337
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) { 338 HInstruction visitIndexAssign(HIndexAssign node) {
344 if (!node.receiver.canBePrimitive(types)) { 339 if (!node.receiver.canBePrimitive(types)) {
345 Selector selector = new Selector.indexSet(); 340 Selector selector = new Selector.indexSet();
346 return fromPrimitiveInstructionToDynamicInvocation(node, selector); 341 return fromPrimitiveInstructionToDynamicInvocation(node, selector);
347 } 342 }
348 return node; 343 return node;
349 } 344 }
350 345
351 HInstruction visitInvokeBinary(HInvokeBinary node) { 346 HInstruction visitInvokeBinary(HInvokeBinary node) {
352 HInstruction left = node.left; 347 HInstruction left = node.left;
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 HIntegerCheck check = new HIntegerCheck(value); 791 HIntegerCheck check = new HIntegerCheck(value);
797 node.block.addBefore(node, check); 792 node.block.addBefore(node, check);
798 Set<HInstruction> dominatedUsers = value.dominatedUsers(node); 793 Set<HInstruction> dominatedUsers = value.dominatedUsers(node);
799 for (HInstruction user in dominatedUsers) { 794 for (HInstruction user in dominatedUsers) {
800 user.changeUse(value, check); 795 user.changeUse(value, check);
801 } 796 }
802 return check; 797 return check;
803 } 798 }
804 799
805 void visitIndex(HIndex node) { 800 void visitIndex(HIndex node) {
806 if (!node.receiver.isIndexablePrimitive(types)) return;
807 if (boundsChecked.contains(node)) return; 801 if (boundsChecked.contains(node)) return;
808 HInstruction index = node.index; 802 HInstruction index = node.index;
809 if (!node.index.isInteger(types)) { 803 if (!node.index.isInteger(types)) {
810 index = insertIntegerCheck(node, index); 804 index = insertIntegerCheck(node, index);
811 } 805 }
812 index = insertBoundsCheck(node, node.receiver, index); 806 index = insertBoundsCheck(node, node.receiver, index);
813 node.changeUse(node.index, index); 807 node.changeUse(node.index, index);
814 assert(node.isBuiltin(types));
815 } 808 }
816 809
817 void visitIndexAssign(HIndexAssign node) { 810 void visitIndexAssign(HIndexAssign node) {
818 if (!node.receiver.isMutableArray(types)) return; 811 if (!node.receiver.isMutableArray(types)) return;
819 if (boundsChecked.contains(node)) return; 812 if (boundsChecked.contains(node)) return;
820 HInstruction index = node.index; 813 HInstruction index = node.index;
821 if (!node.index.isInteger(types)) { 814 if (!node.index.isInteger(types)) {
822 index = insertIntegerCheck(node, index); 815 index = insertIntegerCheck(node, index);
823 } 816 }
824 index = insertBoundsCheck(node, node.receiver, index); 817 index = insertBoundsCheck(node, node.receiver, index);
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 HInstruction receiver = interceptor.receiver; 1470 HInstruction receiver = interceptor.receiver;
1478 for (var user in receiver.usedBy) { 1471 for (var user in receiver.usedBy) {
1479 if (user is HInterceptor && interceptor.dominates(user)) { 1472 if (user is HInterceptor && interceptor.dominates(user)) {
1480 user.interceptedClasses = interceptor.interceptedClasses; 1473 user.interceptedClasses = interceptor.interceptedClasses;
1481 } 1474 }
1482 } 1475 }
1483 } 1476 }
1484 1477
1485 // TODO(ngeoffray): Also implement it for non-intercepted calls. 1478 // TODO(ngeoffray): Also implement it for non-intercepted calls.
1486 } 1479 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/nodes.dart ('k') | sdk/lib/_internal/compiler/implementation/ssa/tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698