| 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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 if (argument != null && | 230 if (argument != null && |
| 231 argument.definition.hasExactlyOneUse && | 231 argument.definition.hasExactlyOneUse && |
| 232 parameter.hasNoUses) { | 232 parameter.hasNoUses) { |
| 233 --size; | 233 --size; |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 | 236 |
| 237 static int sizeOf(InvocationPrimitive invoke, FunctionDefinition function) { | 237 static int sizeOf(InvocationPrimitive invoke, FunctionDefinition function) { |
| 238 SizeVisitor visitor = new SizeVisitor(); | 238 SizeVisitor visitor = new SizeVisitor(); |
| 239 visitor.visit(function); | 239 visitor.visit(function); |
| 240 visitor.countArgument(invoke.receiver, function.thisParameter); | 240 visitor.countArgument(invoke.receiverRef, function.thisParameter); |
| 241 for (int i = 0; i < invoke.arguments.length; ++i) { | 241 for (int i = 0; i < invoke.argumentRefs.length; ++i) { |
| 242 visitor.countArgument(invoke.arguments[i], function.parameters[i]); | 242 visitor.countArgument(invoke.argumentRefs[i], function.parameters[i]); |
| 243 } | 243 } |
| 244 return visitor.size; | 244 return visitor.size; |
| 245 } | 245 } |
| 246 | 246 |
| 247 // Inlining a function incurs a cost equal to the number of primitives and | 247 // Inlining a function incurs a cost equal to the number of primitives and |
| 248 // non-jump tail expressions. | 248 // non-jump tail expressions. |
| 249 // TODO(kmillikin): Tune the size computation and size bound. | 249 // TODO(kmillikin): Tune the size computation and size bound. |
| 250 processLetPrim(LetPrim node) => ++size; | 250 processLetPrim(LetPrim node) => ++size; |
| 251 processLetMutable(LetMutable node) => ++size; | 251 processLetMutable(LetMutable node) => ++size; |
| 252 processBranch(Branch node) => ++size; | 252 processBranch(Branch node) => ++size; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 } | 329 } |
| 330 | 330 |
| 331 TypeMask abstractType(Reference<Primitive> ref) { | 331 TypeMask abstractType(Reference<Primitive> ref) { |
| 332 return ref.definition.type ?? typeSystem.dynamicType; | 332 return ref.definition.type ?? typeSystem.dynamicType; |
| 333 } | 333 } |
| 334 | 334 |
| 335 /// Build the IR term for the function that adapts a call site targeting a | 335 /// Build the IR term for the function that adapts a call site targeting a |
| 336 /// function that takes optional arguments not passed at the call site. | 336 /// function that takes optional arguments not passed at the call site. |
| 337 FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) { | 337 FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) { |
| 338 Parameter thisParameter = new Parameter(new ThisParameterLocal(target)) | 338 Parameter thisParameter = new Parameter(new ThisParameterLocal(target)) |
| 339 ..type = node.receiver.definition.type; | 339 ..type = node.receiver.type; |
| 340 List<Parameter> parameters = new List<Parameter>.generate( | 340 List<Parameter> parameters = new List<Parameter>.generate( |
| 341 node.arguments.length, | 341 node.argumentRefs.length, |
| 342 (int index) { | 342 (int index) { |
| 343 // TODO(kmillikin): Use a hint for the parameter names. | 343 // TODO(kmillikin): Use a hint for the parameter names. |
| 344 return new Parameter(null) | 344 return new Parameter(null) |
| 345 ..type = node.arguments[index].definition.type; | 345 ..type = node.argument(index).type; |
| 346 }); | 346 }); |
| 347 Continuation returnContinuation = new Continuation.retrn(); | 347 Continuation returnContinuation = new Continuation.retrn(); |
| 348 CpsFragment cps = new CpsFragment(); | 348 CpsFragment cps = new CpsFragment(); |
| 349 | 349 |
| 350 FunctionSignature signature = target.functionSignature; | 350 FunctionSignature signature = target.functionSignature; |
| 351 int requiredParameterCount = signature.requiredParameterCount; | 351 int requiredParameterCount = signature.requiredParameterCount; |
| 352 if (node.callingConvention == CallingConvention.Intercepted || | 352 if (node.callingConvention == CallingConvention.Intercepted || |
| 353 node.callingConvention == CallingConvention.DummyIntercepted) { | 353 node.callingConvention == CallingConvention.DummyIntercepted) { |
| 354 ++requiredParameterCount; | 354 ++requiredParameterCount; |
| 355 } | 355 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 } | 437 } |
| 438 | 438 |
| 439 if (isBlacklisted(target)) return null; | 439 if (isBlacklisted(target)) return null; |
| 440 | 440 |
| 441 if (invoke.callingConvention == CallingConvention.OneShotIntercepted) { | 441 if (invoke.callingConvention == CallingConvention.OneShotIntercepted) { |
| 442 // One-shot interceptor calls with a known target are only inserted on | 442 // One-shot interceptor calls with a known target are only inserted on |
| 443 // uncommon code paths, so they should not be inlined. | 443 // uncommon code paths, so they should not be inlined. |
| 444 return null; | 444 return null; |
| 445 } | 445 } |
| 446 | 446 |
| 447 Reference<Primitive> dartReceiver = invoke.dartReceiverReference; | 447 Reference<Primitive> dartReceiver = invoke.dartReceiverRef; |
| 448 TypeMask abstractReceiver = | 448 TypeMask abstractReceiver = |
| 449 dartReceiver == null ? null : abstractType(dartReceiver); | 449 dartReceiver == null ? null : abstractType(dartReceiver); |
| 450 // The receiver is non-null in a method body, unless the receiver is known | 450 // The receiver is non-null in a method body, unless the receiver is known |
| 451 // to be `null` (isEmpty covers `null` and unreachable). | 451 // to be `null` (isEmpty covers `null` and unreachable). |
| 452 TypeMask abstractReceiverInMethod = abstractReceiver == null | 452 TypeMask abstractReceiverInMethod = abstractReceiver == null |
| 453 ? null | 453 ? null |
| 454 : abstractReceiver.isEmpty | 454 : abstractReceiver.isEmpty |
| 455 ? abstractReceiver | 455 ? abstractReceiver |
| 456 : abstractReceiver.nonNullable(); | 456 : abstractReceiver.nonNullable(); |
| 457 List<TypeMask> abstractArguments = | 457 List<TypeMask> abstractArguments = |
| 458 invoke.arguments.map(abstractType).toList(); | 458 invoke.argumentRefs.map(abstractType).toList(); |
| 459 var cachedResult = _inliner.cache.get(target, callStructure, | 459 var cachedResult = _inliner.cache.get(target, callStructure, |
| 460 abstractReceiverInMethod, | 460 abstractReceiverInMethod, |
| 461 abstractArguments); | 461 abstractArguments); |
| 462 | 462 |
| 463 // Negative inlining result in the cache. | 463 // Negative inlining result in the cache. |
| 464 if (cachedResult == InliningCache.NO_INLINE) return null; | 464 if (cachedResult == InliningCache.NO_INLINE) return null; |
| 465 | 465 |
| 466 Primitive finish(FunctionDefinition function) { | 466 Primitive finish(FunctionDefinition function) { |
| 467 _fragment = new CpsFragment(invoke.sourceInformation); | 467 _fragment = new CpsFragment(invoke.sourceInformation); |
| 468 Primitive receiver = invoke.receiver?.definition; | 468 Primitive receiver = invoke.receiver; |
| 469 List<Primitive> arguments = | 469 List<Primitive> arguments = invoke.arguments.toList(); |
| 470 invoke.arguments.map((Reference ref) => ref.definition).toList(); | |
| 471 // Add a null check to the inlined function body if necessary. The | 470 // Add a null check to the inlined function body if necessary. The |
| 472 // cached function body does not contain the null check. | 471 // cached function body does not contain the null check. |
| 473 if (dartReceiver != null && abstractReceiver.isNullable) { | 472 if (dartReceiver != null && abstractReceiver.isNullable) { |
| 474 Primitive check = nullReceiverGuard( | 473 Primitive check = nullReceiverGuard( |
| 475 invoke, _fragment, dartReceiver.definition, abstractReceiver); | 474 invoke, _fragment, dartReceiver.definition, abstractReceiver); |
| 476 if (invoke.callingConvention == CallingConvention.Intercepted) { | 475 if (invoke.callingConvention == CallingConvention.Intercepted) { |
| 477 arguments[0] = check; | 476 arguments[0] = check; |
| 478 } else { | 477 } else { |
| 479 receiver = check; | 478 receiver = check; |
| 480 } | 479 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 511 return doNotInline(); | 510 return doNotInline(); |
| 512 } else { | 511 } else { |
| 513 function = buildAdapter(invoke, target); | 512 function = buildAdapter(invoke, target); |
| 514 } | 513 } |
| 515 } else { | 514 } else { |
| 516 function = compileToCpsIr(target); | 515 function = compileToCpsIr(target); |
| 517 void setValue(Variable variable, Reference<Primitive> value) { | 516 void setValue(Variable variable, Reference<Primitive> value) { |
| 518 variable.type = value.definition.type; | 517 variable.type = value.definition.type; |
| 519 } | 518 } |
| 520 if (invoke.callingConvention == CallingConvention.Intercepted) { | 519 if (invoke.callingConvention == CallingConvention.Intercepted) { |
| 521 setValue(function.thisParameter, invoke.receiver); | 520 setValue(function.thisParameter, invoke.receiverRef); |
| 522 function.parameters[0].type = abstractReceiverInMethod; | 521 function.parameters[0].type = abstractReceiverInMethod; |
| 523 for (int i = 1; i < invoke.arguments.length; ++i) { | 522 for (int i = 1; i < invoke.argumentRefs.length; ++i) { |
| 524 setValue(function.parameters[i], invoke.arguments[i]); | 523 setValue(function.parameters[i], invoke.argumentRefs[i]); |
| 525 } | 524 } |
| 526 } else { | 525 } else { |
| 527 if (invoke.receiver != null) { | 526 if (invoke.receiverRef != null) { |
| 528 function.thisParameter.type = abstractReceiverInMethod; | 527 function.thisParameter.type = abstractReceiverInMethod; |
| 529 } | 528 } |
| 530 for (int i = 0; i < invoke.arguments.length; ++i) { | 529 for (int i = 0; i < invoke.argumentRefs.length; ++i) { |
| 531 setValue(function.parameters[i], invoke.arguments[i]); | 530 setValue(function.parameters[i], invoke.argumentRefs[i]); |
| 532 } | 531 } |
| 533 } | 532 } |
| 534 optimizeBeforeInlining(function); | 533 optimizeBeforeInlining(function); |
| 535 } | 534 } |
| 536 | 535 |
| 537 // Inline calls in the body. | 536 // Inline calls in the body. |
| 538 _inliner.rewrite(function, callStructure); | 537 _inliner.rewrite(function, callStructure); |
| 539 | 538 |
| 540 // Compute the size. | 539 // Compute the size. |
| 541 // TODO(kmillikin): Tune the size bound. | 540 // TODO(kmillikin): Tune the size bound. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 (enclosingClass == backend.helpers.jsNumberClass || | 619 (enclosingClass == backend.helpers.jsNumberClass || |
| 621 enclosingClass == backend.helpers.jsDoubleClass || | 620 enclosingClass == backend.helpers.jsDoubleClass || |
| 622 enclosingClass == backend.helpers.jsIntClass)) { | 621 enclosingClass == backend.helpers.jsIntClass)) { |
| 623 // These should be handled by operator specialization. | 622 // These should be handled by operator specialization. |
| 624 return true; | 623 return true; |
| 625 } | 624 } |
| 626 if (target == backend.helpers.stringInterpolationHelper) return true; | 625 if (target == backend.helpers.stringInterpolationHelper) return true; |
| 627 return false; | 626 return false; |
| 628 } | 627 } |
| 629 } | 628 } |
| OLD | NEW |