Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 dartReceiver == null ? null : abstractType(dartReceiver); | 373 dartReceiver == null ? null : abstractType(dartReceiver); |
| 374 List<TypeMask> abstractArguments = | 374 List<TypeMask> abstractArguments = |
| 375 invoke.arguments.map(abstractType).toList(); | 375 invoke.arguments.map(abstractType).toList(); |
| 376 var cachedResult = _inliner.cache.get(target, callStructure, | 376 var cachedResult = _inliner.cache.get(target, callStructure, |
| 377 abstractReceiver, | 377 abstractReceiver, |
| 378 abstractArguments); | 378 abstractArguments); |
| 379 | 379 |
| 380 // Negative inlining result in the cache. | 380 // Negative inlining result in the cache. |
| 381 if (cachedResult == InliningCache.NO_INLINE) return null; | 381 if (cachedResult == InliningCache.NO_INLINE) return null; |
| 382 | 382 |
| 383 // Positive inlining result in the cache. | 383 Primitive finish(FunctionDefinition function) { |
| 384 if (cachedResult is FunctionDefinition) { | |
| 385 FunctionDefinition function = cachedResult; | |
| 386 _fragment = new CpsFragment(invoke.sourceInformation); | 384 _fragment = new CpsFragment(invoke.sourceInformation); |
| 387 Primitive receiver = invoke.receiver?.definition; | 385 Primitive receiver = invoke.receiver?.definition; |
| 386 Reference<Primitive> dartReceiver = invoke.dartReceiverReference; | |
|
Kevin Millikin (Google)
2016/01/07 18:15:08
This is already in scope, isn't it?
sra1
2016/01/07 18:23:14
Yes, thanks.
| |
| 388 List<Primitive> arguments = | 387 List<Primitive> arguments = |
| 389 invoke.arguments.map((Reference ref) => ref.definition).toList(); | 388 invoke.arguments.map((Reference ref) => ref.definition).toList(); |
| 390 // Add a null check to the inlined function body if necessary. The | 389 // Add a null check to the inlined function body if necessary. The |
| 391 // cached function body does not contain the null check. | 390 // cached function body does not contain the null check. |
| 392 if (dartReceiver != null && abstractReceiver.isNullable) { | 391 if (dartReceiver != null && abstractReceiver.isNullable) { |
| 393 Primitive check = nullReceiverGuard( | 392 Primitive check = nullReceiverGuard( |
| 394 invoke, _fragment, dartReceiver.definition, abstractReceiver); | 393 invoke, _fragment, dartReceiver.definition, abstractReceiver); |
| 395 if (invoke.callingConvention == CallingConvention.Intercepted) { | 394 if (invoke.callingConvention == CallingConvention.Intercepted) { |
| 396 arguments[0] = check; | 395 arguments[0] = check; |
| 397 } else { | 396 } else { |
| 398 receiver = check; | 397 receiver = check; |
| 399 } | 398 } |
| 400 } | 399 } |
| 401 return _fragment.inlineFunction(function, receiver, arguments, | 400 return _fragment.inlineFunction(function, receiver, arguments, |
| 402 hint: invoke.hint); | 401 hint: invoke.hint); |
| 403 } | 402 } |
| 404 | 403 |
| 404 // Positive inlining result in the cache. | |
| 405 if (cachedResult is FunctionDefinition) { | |
| 406 return finish(cachedResult); | |
| 407 } | |
| 408 | |
| 405 // We have not seen this combination of target and abstract arguments | 409 // We have not seen this combination of target and abstract arguments |
| 406 // before. Make an inlining decision. | 410 // before. Make an inlining decision. |
| 407 assert(cachedResult == InliningCache.ABSENT); | 411 assert(cachedResult == InliningCache.ABSENT); |
| 408 Primitive doNotInline() { | 412 Primitive doNotInline() { |
| 409 _inliner.cache.putNegative(target, callStructure, abstractReceiver, | 413 _inliner.cache.putNegative(target, callStructure, abstractReceiver, |
| 410 abstractArguments); | 414 abstractArguments); |
| 411 return null; | 415 return null; |
| 412 } | 416 } |
| 413 if (backend.annotations.noInline(target)) return doNotInline(); | 417 if (backend.annotations.noInline(target)) return doNotInline(); |
| 414 if (isRecursive(target, callStructure)) return doNotInline(); | 418 if (isRecursive(target, callStructure)) return doNotInline(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 438 // Inline calls in the body. | 442 // Inline calls in the body. |
| 439 _inliner.rewrite(function, callStructure); | 443 _inliner.rewrite(function, callStructure); |
| 440 | 444 |
| 441 // Compute the size. | 445 // Compute the size. |
| 442 // TODO(kmillikin): Tune the size bound. | 446 // TODO(kmillikin): Tune the size bound. |
| 443 int size = SizeVisitor.sizeOf(invoke, function); | 447 int size = SizeVisitor.sizeOf(invoke, function); |
| 444 if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline(); | 448 if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline(); |
| 445 | 449 |
| 446 _inliner.cache.putPositive(target, callStructure, abstractReceiver, | 450 _inliner.cache.putPositive(target, callStructure, abstractReceiver, |
| 447 abstractArguments, function); | 451 abstractArguments, function); |
| 448 _fragment = new CpsFragment(invoke.sourceInformation); | 452 return finish(function); |
| 449 Primitive receiver = invoke.receiver?.definition; | |
| 450 List<Primitive> arguments = | |
| 451 invoke.arguments.map((Reference ref) => ref.definition).toList(); | |
| 452 if (dartReceiver != null && abstractReceiver.isNullable) { | |
| 453 Primitive check = | |
| 454 _fragment.letPrim(new NullCheck(dartReceiver.definition, | |
| 455 invoke.sourceInformation)); | |
| 456 check.type = abstractReceiver.nonNullable(); | |
| 457 if (invoke.callingConvention == CallingConvention.Intercepted) { | |
| 458 arguments[0] = check; | |
| 459 } else { | |
| 460 receiver = check; | |
| 461 } | |
| 462 } | |
| 463 return _fragment.inlineFunction(function, receiver, arguments, | |
| 464 hint: invoke.hint); | |
| 465 } | 453 } |
| 466 | 454 |
| 467 Primitive nullReceiverGuard(InvocationPrimitive invoke, | 455 Primitive nullReceiverGuard(InvocationPrimitive invoke, |
| 468 CpsFragment fragment, | 456 CpsFragment fragment, |
| 469 Primitive dartReceiver, | 457 Primitive dartReceiver, |
| 470 TypeMask abstractReceiver) { | 458 TypeMask abstractReceiver) { |
| 471 Selector selector = invoke is InvokeMethod ? invoke.selector : null; | 459 Selector selector = invoke is InvokeMethod ? invoke.selector : null; |
| 472 if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) { | 460 if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) { |
| 473 Primitive condition = _fragment.letPrim( | 461 Primitive condition = _fragment.letPrim( |
| 474 new ApplyBuiltinOperator(BuiltinOperator.IsNotNumber, | 462 new ApplyBuiltinOperator(BuiltinOperator.IsNotNumber, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 // We cannot inline a constructor invocation containing type arguments | 508 // We cannot inline a constructor invocation containing type arguments |
| 521 // because CreateInstance in the body does not know the type arguments. | 509 // because CreateInstance in the body does not know the type arguments. |
| 522 // We would incorrectly instantiate a class like A instead of A<B>. | 510 // We would incorrectly instantiate a class like A instead of A<B>. |
| 523 // TODO(kmillikin): try to fix this. | 511 // TODO(kmillikin): try to fix this. |
| 524 GenericType generic = node.dartType; | 512 GenericType generic = node.dartType; |
| 525 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null; | 513 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null; |
| 526 } | 514 } |
| 527 return tryInlining(node, node.target, null); | 515 return tryInlining(node, node.target, null); |
| 528 } | 516 } |
| 529 } | 517 } |
| OLD | NEW |