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

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

Issue 1182053010: Revert "Split TypedSelector into Selector and TypeMask." (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/nodes.dart ('k') | pkg/compiler/lib/src/ssa/ssa_tracer.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) 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 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 : foldBinary(operation, node.inputs[1], node.inputs[2]); 294 : foldBinary(operation, node.inputs[1], node.inputs[2]);
295 if (instruction != null) return instruction; 295 if (instruction != null) return instruction;
296 } 296 }
297 297
298 // Try converting the instruction to a builtin instruction. 298 // Try converting the instruction to a builtin instruction.
299 HInstruction instruction = 299 HInstruction instruction =
300 node.specializer.tryConvertToBuiltin(node, compiler); 300 node.specializer.tryConvertToBuiltin(node, compiler);
301 if (instruction != null) return instruction; 301 if (instruction != null) return instruction;
302 302
303 Selector selector = node.selector; 303 Selector selector = node.selector;
304 TypeMask mask = node.mask;
305 HInstruction input = node.inputs[1]; 304 HInstruction input = node.inputs[1];
306 305
307 World world = compiler.world; 306 World world = compiler.world;
308
309 bool applies(Element element) {
310 return selector.applies(element, world) &&
311 (mask == null || mask.canHit(element, selector, world));
312 }
313
314 if (selector.isCall || selector.isOperator) { 307 if (selector.isCall || selector.isOperator) {
315 Element target; 308 Element target;
316 if (input.isExtendableArray(compiler)) { 309 if (input.isExtendableArray(compiler)) {
317 if (applies(backend.jsArrayRemoveLast)) { 310 if (selector.applies(backend.jsArrayRemoveLast, world)) {
318 target = backend.jsArrayRemoveLast; 311 target = backend.jsArrayRemoveLast;
319 } else if (applies(backend.jsArrayAdd)) { 312 } else if (selector.applies(backend.jsArrayAdd, world)) {
320 // The codegen special cases array calls, but does not 313 // The codegen special cases array calls, but does not
321 // inline argument type checks. 314 // inline argument type checks.
322 if (!compiler.enableTypeAssertions) { 315 if (!compiler.enableTypeAssertions) {
323 target = backend.jsArrayAdd; 316 target = backend.jsArrayAdd;
324 } 317 }
325 } 318 }
326 } else if (input.isStringOrNull(compiler)) { 319 } else if (input.isStringOrNull(compiler)) {
327 if (applies(backend.jsStringSplit)) { 320 if (selector.applies(backend.jsStringSplit, world)) {
328 HInstruction argument = node.inputs[2]; 321 HInstruction argument = node.inputs[2];
329 if (argument.isString(compiler)) { 322 if (argument.isString(compiler)) {
330 target = backend.jsStringSplit; 323 target = backend.jsStringSplit;
331 } 324 }
332 } else if (applies(backend.jsStringOperatorAdd)) { 325 } else if (selector.applies(backend.jsStringOperatorAdd, world)) {
333 // `operator+` is turned into a JavaScript '+' so we need to 326 // `operator+` is turned into a JavaScript '+' so we need to
334 // make sure the receiver and the argument are not null. 327 // make sure the receiver and the argument are not null.
335 // TODO(sra): Do this via [node.specializer]. 328 // TODO(sra): Do this via [node.specializer].
336 HInstruction argument = node.inputs[2]; 329 HInstruction argument = node.inputs[2];
337 if (argument.isString(compiler) 330 if (argument.isString(compiler)
338 && !input.canBeNull()) { 331 && !input.canBeNull()) {
339 return new HStringConcat(input, argument, null, 332 return new HStringConcat(input, argument, null,
340 node.instructionType); 333 node.instructionType);
341 } 334 }
342 } else if (applies(backend.jsStringToString) 335 } else if (selector.applies(backend.jsStringToString, world)
343 && !input.canBeNull()) { 336 && !input.canBeNull()) {
344 return input; 337 return input;
345 } 338 }
346 } 339 }
347 if (target != null) { 340 if (target != null) {
348 // TODO(ngeoffray): There is a strong dependency between codegen 341 // TODO(ngeoffray): There is a strong dependency between codegen
349 // and this optimization that the dynamic invoke does not need an 342 // and this optimization that the dynamic invoke does not need an
350 // interceptor. We currently need to keep a 343 // interceptor. We currently need to keep a
351 // HInvokeDynamicMethod and not create a HForeign because 344 // HInvokeDynamicMethod and not create a HForeign because
352 // HForeign is too opaque for the SsaCheckInserter (that adds a 345 // HForeign is too opaque for the SsaCheckInserter (that adds a
353 // bounds check on removeLast). Once we start inlining, the 346 // bounds check on removeLast). Once we start inlining, the
354 // bounds check will become explicit, so we won't need this 347 // bounds check will become explicit, so we won't need this
355 // optimization. 348 // optimization.
356 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 349 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
357 node.selector, node.mask, 350 node.selector, node.inputs.sublist(1), node.instructionType);
358 node.inputs.sublist(1), node.instructionType);
359 result.element = target; 351 result.element = target;
360 return result; 352 return result;
361 } 353 }
362 } else if (selector.isGetter) { 354 } else if (selector.isGetter) {
363 if (selector.applies(backend.jsIndexableLength, world)) { 355 if (selector.asUntyped.applies(backend.jsIndexableLength, world)) {
364 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node); 356 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
365 if (optimized != null) return optimized; 357 if (optimized != null) return optimized;
366 } 358 }
367 } 359 }
368 360
369 return node; 361 return node;
370 } 362 }
371 363
372 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 364 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
373 if (node.isInterceptedCall) { 365 if (node.isInterceptedCall) {
374 HInstruction folded = handleInterceptedCall(node); 366 HInstruction folded = handleInterceptedCall(node);
375 if (folded != node) return folded; 367 if (folded != node) return folded;
376 } 368 }
377 369
378 TypeMask receiverType = node.getDartReceiver(compiler).instructionType; 370 TypeMask receiverType = node.getDartReceiver(compiler).instructionType;
379 Element element = 371 Selector selector =
380 compiler.world.locateSingleElement(node.selector, receiverType); 372 new TypedSelector(receiverType, node.selector, compiler.world);
373 Element element = compiler.world.locateSingleElement(selector);
381 // TODO(ngeoffray): Also fold if it's a getter or variable. 374 // TODO(ngeoffray): Also fold if it's a getter or variable.
382 if (element != null 375 if (element != null
383 && element.isFunction 376 && element.isFunction
384 // If we found out that the only target is a [:noSuchMethod:], 377 // If we found out that the only target is a [:noSuchMethod:],
385 // we just ignore it. 378 // we just ignore it.
386 && element.name == node.selector.name) { 379 && element.name == selector.name) {
387 FunctionElement method = element; 380 FunctionElement method = element;
388 381
389 if (method.isNative) { 382 if (method.isNative) {
390 HInstruction folded = tryInlineNativeMethod(node, method); 383 HInstruction folded = tryInlineNativeMethod(node, method);
391 if (folded != null) return folded; 384 if (folded != null) return folded;
392 } else { 385 } else {
393 // TODO(ngeoffray): If the method has optional parameters, 386 // TODO(ngeoffray): If the method has optional parameters,
394 // we should pass the default values. 387 // we should pass the default values.
395 FunctionSignature parameters = method.functionSignature; 388 FunctionSignature parameters = method.functionSignature;
396 if (parameters.optionalParameterCount == 0 || 389 if (parameters.optionalParameterCount == 0
397 parameters.parameterCount == 390 || parameters.parameterCount == node.selector.argumentCount) {
398 node.selector.argumentCount) {
399 node.element = element; 391 node.element = element;
400 } 392 }
401 } 393 }
402 } 394 }
403 return node; 395 return node;
404 } 396 }
405 397
406 HInstruction tryInlineNativeMethod(HInvokeDynamicMethod node, 398 HInstruction tryInlineNativeMethod(HInvokeDynamicMethod node,
407 FunctionElement method) { 399 FunctionElement method) {
408 // Enable direct calls to a native method only if we don't run in checked 400 // Enable direct calls to a native method only if we don't run in checked
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 443
452 if (!canInline) return null; 444 if (!canInline) return null;
453 445
454 // Strengthen instruction type from annotations to help optimize 446 // Strengthen instruction type from annotations to help optimize
455 // dependent instructions. 447 // dependent instructions.
456 native.NativeBehavior nativeBehavior = 448 native.NativeBehavior nativeBehavior =
457 native.NativeBehavior.ofMethod(method, compiler); 449 native.NativeBehavior.ofMethod(method, compiler);
458 TypeMask returnType = 450 TypeMask returnType =
459 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); 451 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
460 HInvokeDynamicMethod result = 452 HInvokeDynamicMethod result =
461 new HInvokeDynamicMethod(node.selector, node.mask, inputs, returnType); 453 new HInvokeDynamicMethod(node.selector, inputs, returnType);
462 result.element = method; 454 result.element = method;
463 return result; 455 return result;
464 } 456 }
465 457
466 HInstruction visitBoundsCheck(HBoundsCheck node) { 458 HInstruction visitBoundsCheck(HBoundsCheck node) {
467 HInstruction index = node.index; 459 HInstruction index = node.index;
468 if (index.isInteger(compiler)) return node; 460 if (index.isInteger(compiler)) return node;
469 if (index.isConstant()) { 461 if (index.isConstant()) {
470 HConstant constantInstruction = index; 462 HConstant constantInstruction = index;
471 assert(!constantInstruction.constant.isInt); 463 assert(!constantInstruction.constant.isInt);
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 ClassWorld classWorld = compiler.world; 722 ClassWorld classWorld = compiler.world;
731 if (checkedType.containsAll(classWorld)) return node; 723 if (checkedType.containsAll(classWorld)) return node;
732 HInstruction input = node.checkedInput; 724 HInstruction input = node.checkedInput;
733 TypeMask inputType = input.instructionType; 725 TypeMask inputType = input.instructionType;
734 return inputType.isInMask(checkedType, classWorld) ? input : node; 726 return inputType.isInMask(checkedType, classWorld) ? input : node;
735 } 727 }
736 728
737 VariableElement findConcreteFieldForDynamicAccess(HInstruction receiver, 729 VariableElement findConcreteFieldForDynamicAccess(HInstruction receiver,
738 Selector selector) { 730 Selector selector) {
739 TypeMask receiverType = receiver.instructionType; 731 TypeMask receiverType = receiver.instructionType;
740 return compiler.world.locateSingleField(selector, receiverType); 732 return compiler.world.locateSingleField(
733 new TypedSelector(receiverType, selector, compiler.world));
741 } 734 }
742 735
743 HInstruction visitFieldGet(HFieldGet node) { 736 HInstruction visitFieldGet(HFieldGet node) {
744 if (node.isNullCheck) return node; 737 if (node.isNullCheck) return node;
745 var receiver = node.receiver; 738 var receiver = node.receiver;
746 if (node.element == backend.jsIndexableLength) { 739 if (node.element == backend.jsIndexableLength) {
747 JavaScriptItemCompilationContext context = work.compilationContext; 740 JavaScriptItemCompilationContext context = work.compilationContext;
748 if (context.allocatedFixedLists.contains(receiver)) { 741 if (context.allocatedFixedLists.contains(receiver)) {
749 // TODO(ngeoffray): checking if the second input is an integer 742 // TODO(ngeoffray): checking if the second input is an integer
750 // should not be necessary but it currently makes it easier for 743 // should not be necessary but it currently makes it easier for
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } 795 }
803 return node; 796 return node;
804 } 797 }
805 798
806 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 799 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
807 if (node.isInterceptedCall) { 800 if (node.isInterceptedCall) {
808 HInstruction folded = handleInterceptedCall(node); 801 HInstruction folded = handleInterceptedCall(node);
809 if (folded != node) return folded; 802 if (folded != node) return folded;
810 } 803 }
811 HInstruction receiver = node.getDartReceiver(compiler); 804 HInstruction receiver = node.getDartReceiver(compiler);
812 Element field = findConcreteFieldForDynamicAccess( 805 Element field = findConcreteFieldForDynamicAccess(receiver, node.selector);
813 receiver, node.selector);
814 if (field == null) return node; 806 if (field == null) return node;
815 return directFieldGet(receiver, field); 807 return directFieldGet(receiver, field);
816 } 808 }
817 809
818 HInstruction directFieldGet(HInstruction receiver, Element field) { 810 HInstruction directFieldGet(HInstruction receiver, Element field) {
819 bool isAssignable = !compiler.world.fieldNeverChanges(field); 811 bool isAssignable = !compiler.world.fieldNeverChanges(field);
820 812
821 TypeMask type; 813 TypeMask type;
822 if (field.enclosingClass.isNative) { 814 if (field.enclosingClass.isNative) {
823 type = TypeMaskFactory.fromNativeBehavior( 815 type = TypeMaskFactory.fromNativeBehavior(
(...skipping 1481 matching lines...) Expand 10 before | Expand all | Expand 10 after
2305 2297
2306 keyedValues.forEach((receiver, values) { 2298 keyedValues.forEach((receiver, values) {
2307 result.keyedValues[receiver] = 2299 result.keyedValues[receiver] =
2308 new Map<HInstruction, HInstruction>.from(values); 2300 new Map<HInstruction, HInstruction>.from(values);
2309 }); 2301 });
2310 2302
2311 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2303 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2312 return result; 2304 return result;
2313 } 2305 }
2314 } 2306 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/nodes.dart ('k') | pkg/compiler/lib/src/ssa/ssa_tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698