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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/inline.dart

Issue 1568103003: Specializations of instance methods have non-null receiver. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library cps_ir.optimization.inline; 5 library cps_ir.optimization.inline;
6 6
7 import 'cps_fragment.dart'; 7 import 'cps_fragment.dart';
8 import 'cps_ir_builder.dart' show ThisParameterLocal; 8 import 'cps_ir_builder.dart' show ThisParameterLocal;
9 import 'cps_ir_nodes.dart'; 9 import 'cps_ir_nodes.dart';
10 import 'optimizers.dart'; 10 import 'optimizers.dart';
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 // V8 does not optimize functions containing a try statement. Inlining 364 // V8 does not optimize functions containing a try statement. Inlining
365 // code containing a try statement will make the optimizable calling code 365 // code containing a try statement will make the optimizable calling code
366 // become unoptimizable. 366 // become unoptimizable.
367 if (target.resolvedAst.elements.containsTryStatement) { 367 if (target.resolvedAst.elements.containsTryStatement) {
368 return null; 368 return null;
369 } 369 }
370 370
371 Reference<Primitive> dartReceiver = invoke.dartReceiverReference; 371 Reference<Primitive> dartReceiver = invoke.dartReceiverReference;
372 TypeMask abstractReceiver = 372 TypeMask abstractReceiver =
373 dartReceiver == null ? null : abstractType(dartReceiver); 373 dartReceiver == null ? null : abstractType(dartReceiver);
374 // The receiver is non-null in a method body, unless the receiver is known
375 // to be `null` (isEmpty covers `null` and unreachable).
376 TypeMask abstractReceiverInMethod = abstractReceiver == null
377 ? null
378 : abstractReceiver.isEmpty
379 ? abstractReceiver
380 : abstractReceiver.nonNullable();
374 List<TypeMask> abstractArguments = 381 List<TypeMask> abstractArguments =
375 invoke.arguments.map(abstractType).toList(); 382 invoke.arguments.map(abstractType).toList();
376 var cachedResult = _inliner.cache.get(target, callStructure, 383 var cachedResult = _inliner.cache.get(target, callStructure,
377 abstractReceiver, 384 abstractReceiverInMethod,
378 abstractArguments); 385 abstractArguments);
379 386
380 // Negative inlining result in the cache. 387 // Negative inlining result in the cache.
381 if (cachedResult == InliningCache.NO_INLINE) return null; 388 if (cachedResult == InliningCache.NO_INLINE) return null;
382 389
383 Primitive finish(FunctionDefinition function) { 390 Primitive finish(FunctionDefinition function) {
384 _fragment = new CpsFragment(invoke.sourceInformation); 391 _fragment = new CpsFragment(invoke.sourceInformation);
385 Primitive receiver = invoke.receiver?.definition; 392 Primitive receiver = invoke.receiver?.definition;
386 List<Primitive> arguments = 393 List<Primitive> arguments =
387 invoke.arguments.map((Reference ref) => ref.definition).toList(); 394 invoke.arguments.map((Reference ref) => ref.definition).toList();
(...skipping 14 matching lines...) Expand all
402 409
403 // Positive inlining result in the cache. 410 // Positive inlining result in the cache.
404 if (cachedResult is FunctionDefinition) { 411 if (cachedResult is FunctionDefinition) {
405 return finish(cachedResult); 412 return finish(cachedResult);
406 } 413 }
407 414
408 // We have not seen this combination of target and abstract arguments 415 // We have not seen this combination of target and abstract arguments
409 // before. Make an inlining decision. 416 // before. Make an inlining decision.
410 assert(cachedResult == InliningCache.ABSENT); 417 assert(cachedResult == InliningCache.ABSENT);
411 Primitive doNotInline() { 418 Primitive doNotInline() {
412 _inliner.cache.putNegative(target, callStructure, abstractReceiver, 419 _inliner.cache.putNegative(
413 abstractArguments); 420 target, callStructure, abstractReceiverInMethod, abstractArguments);
414 return null; 421 return null;
415 } 422 }
416 if (backend.annotations.noInline(target)) return doNotInline(); 423 if (backend.annotations.noInline(target)) return doNotInline();
417 if (isRecursive(target, callStructure)) return doNotInline(); 424 if (isRecursive(target, callStructure)) return doNotInline();
418 425
419 FunctionDefinition function; 426 FunctionDefinition function;
420 if (callStructure != null && 427 if (callStructure != null &&
421 target.functionSignature.parameterCount != 428 target.functionSignature.parameterCount !=
422 callStructure.argumentCount) { 429 callStructure.argumentCount) {
423 // The argument count at the call site does not match the target's 430 // The argument count at the call site does not match the target's
424 // formal parameter count. Build the IR term for an adapter function 431 // formal parameter count. Build the IR term for an adapter function
425 // body. 432 // body.
426 function = buildAdapter(invoke, target); 433 function = buildAdapter(invoke, target);
427 } else { 434 } else {
428 function = _inliner.functionCompiler.compileToCpsIr(target); 435 function = _inliner.functionCompiler.compileToCpsIr(target);
429 void setValue(Variable variable, Reference<Primitive> value) { 436 void setValue(Variable variable, Reference<Primitive> value) {
430 variable.type = value.definition.type; 437 variable.type = value.definition.type;
431 } 438 }
432 if (invoke.receiver != null) { 439 if (invoke.callingConvention == CallingConvention.Intercepted) {
433 setValue(function.thisParameter, invoke.receiver); 440 setValue(function.thisParameter, invoke.receiver);
434 } 441 function.parameters[0].type = abstractReceiverInMethod;
435 for (int i = 0; i < invoke.arguments.length; ++i) { 442 for (int i = 1; i < invoke.arguments.length; ++i) {
436 setValue(function.parameters[i], invoke.arguments[i]); 443 setValue(function.parameters[i], invoke.arguments[i]);
444 }
445 } else {
446 if (invoke.receiver != null) {
447 function.thisParameter.type = abstractReceiverInMethod;
448 }
449 for (int i = 0; i < invoke.arguments.length; ++i) {
450 setValue(function.parameters[i], invoke.arguments[i]);
451 }
437 } 452 }
438 optimizeBeforeInlining(function); 453 optimizeBeforeInlining(function);
439 } 454 }
440 455
441 // Inline calls in the body. 456 // Inline calls in the body.
442 _inliner.rewrite(function, callStructure); 457 _inliner.rewrite(function, callStructure);
443 458
444 // Compute the size. 459 // Compute the size.
445 // TODO(kmillikin): Tune the size bound. 460 // TODO(kmillikin): Tune the size bound.
446 int size = SizeVisitor.sizeOf(invoke, function); 461 int size = SizeVisitor.sizeOf(invoke, function);
447 if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline(); 462 if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline();
448 463
449 _inliner.cache.putPositive(target, callStructure, abstractReceiver, 464 _inliner.cache.putPositive(target, callStructure, abstractReceiverInMethod,
450 abstractArguments, function); 465 abstractArguments, function);
451 return finish(function); 466 return finish(function);
452 } 467 }
453 468
454 Primitive nullReceiverGuard(InvocationPrimitive invoke, 469 Primitive nullReceiverGuard(InvocationPrimitive invoke,
455 CpsFragment fragment, 470 CpsFragment fragment,
456 Primitive dartReceiver, 471 Primitive dartReceiver,
457 TypeMask abstractReceiver) { 472 TypeMask abstractReceiver) {
458 Selector selector = invoke is InvokeMethod ? invoke.selector : null; 473 Selector selector = invoke is InvokeMethod ? invoke.selector : null;
459 if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) { 474 if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 // We cannot inline a constructor invocation containing type arguments 522 // We cannot inline a constructor invocation containing type arguments
508 // because CreateInstance in the body does not know the type arguments. 523 // because CreateInstance in the body does not know the type arguments.
509 // We would incorrectly instantiate a class like A instead of A<B>. 524 // We would incorrectly instantiate a class like A instead of A<B>.
510 // TODO(kmillikin): try to fix this. 525 // TODO(kmillikin): try to fix this.
511 GenericType generic = node.dartType; 526 GenericType generic = node.dartType;
512 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null; 527 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null;
513 } 528 }
514 return tryInlining(node, node.target, null); 529 return tryInlining(node, node.target, null);
515 } 530 }
516 } 531 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698