-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implement method type specialisation #630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -0,0 +1,11 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be part of PR.
Alex, a lot of your commits do reformatting of already existing code for not good reason(I guess your IDE has different formatting options), could you please update your commits to not do this, as this affects git history. Also, you have committed files that are specific to your IDE(I guess that's Intellij) that shouldn't be part of PR. Neither should there be anything in out/ folder. |
5132ba1
to
7b75837
Compare
Junit failed in GenBCode, as output directory does not exist.. |
Great to see all the tests pass 👍 PS: this PR only contains method specialization, it does not handle classes or fields. |
sym.name != nme.isInstanceOf_ && | ||
!(sym is Flags.JavaDefined) && | ||
!sym.isConstructor && | ||
!sym.name.toString.contains("Function2") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
How did you guys fix the transitivity issue? |
As a last transformation step, in all places where expected type propagation starts, casts are introduced. This isn't a solution, this is a hacky-workaround. I do not see a good solution besides #592. |
@@ -326,6 +326,7 @@ class Definitions { | |||
lazy val TransientAnnot = ctx.requiredClass("scala.transient") | |||
lazy val NativeAnnot = ctx.requiredClass("scala.native") | |||
lazy val ScalaStrictFPAnnot = ctx.requiredClass("scala.annotation.strictfp") | |||
lazy val specializedAnnot = ctx.requiredClass("scala.specialized") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capital S
trait Spec {
def plus[@specialized T](a: T, b:T)(ev: Numeric[T]): T = plus(b, a)(ev)
} Generates specialized versions, but does not dispatch to them in recursive call. |
@DarkDimius @AlexSikia doesn't casting introduce boxes in the backend? |
@VladUreche the problems we've been seeing here mostly have to do with type arguments of enclosing scope, that are bounded by specialized types defined in inner scope. This happens infrequently in real code, and when it happens, it's mostly in higher kinded types, ie casts will be erased. Examples can be found here: https://github.com/AlexSikia/dotty/blob/add/Type-specialisation/tests/pos/specialization/this_specialization.scala But yes, it could potentially introduce boxing, and this could keep some calls not being dispatched to specialized versions. |
7aed2e7
to
ac75f1c
Compare
def generateSpecializedSymbols(instantiations: List[Type], names: List[String], poly: PolyType, decl: Symbol) | ||
(implicit ctx: Context): List[Symbol] = { | ||
val newSym = | ||
ctx.newSymbol(decl.owner, (decl.name + "$mc" + names.mkString + "$sp").toTermName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand the name mangling of specialization correctly, this should be (decl.name + "$m" + names.mkString + "c$sp")
.
m
means method and c
means class, for example if there's a specialized Int method in a specialized Int class, the signature will contain $mIcI$sp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good point; thanks for finding that.
needs to be rebased over current master. |
VCInline is split into two phases: - VCInlineMethods (before Erasure) replaces value class method calls by calls to extension methods - VCInlineEqAndField (after Erasure) handles == and the underlying field of a value class, as VCInline did before. This should not affect anything currently, but in the future we will have phases before Erasure that mangle names (like TypeSpecializer, see scala#630), being able to put these phases after VCInlineMethods means that VCInlineMethods does not need to know anything about how these phases mangle names, this reduces the coupling between phases. The trade-off is that VCInlineMethods needs to deal with type parameters whereas VCInline didn't.
VCInline is split into two phases: - VCInlineMethods (before Erasure) replaces value class method calls by calls to extension methods - VCInlineEqAndField (after Erasure) handles == and the underlying field of a value class, as VCInline did before. This should not affect anything currently, but in the future we will have phases before Erasure that mangle names (like TypeSpecializer, see scala#630), being able to put these phases after VCInlineMethods means that VCInlineMethods does not need to know anything about how these phases mangle names, this reduces the coupling between phases. The trade-off is that VCInlineMethods needs to deal with type parameters and multiple parameter lists whereas VCInline didn't.
VCInline is split into two phases: - VCInlineMethods (before Erasure) replaces value class method calls by calls to extension methods - VCInlineEqAndField (after Erasure) handles == and the underlying field of a value class, as VCInline did before. This should not affect anything currently, but in the future we will have phases before Erasure that mangle names (like TypeSpecializer, see scala#630), being able to put these phases after VCInlineMethods means that VCInlineMethods does not need to know anything about how these phases mangle names, this reduces the coupling between phases. The trade-off is that VCInlineMethods needs to deal with type parameters and multiple parameter lists whereas VCInline didn't.
VCInline is split into two phases: - VCInlineMethods (before Erasure) replaces value class method calls by calls to extension methods - VCInlineEqAndField (after Erasure) handles == and the underlying field of a value class, as VCInline did before. This should not affect anything currently, but in the future we will have phases before Erasure that mangle names (like TypeSpecializer, see scala#630), being able to put these phases after VCInlineMethods means that VCInlineMethods does not need to know anything about how these phases mangle names, this reduces the coupling between phases. The trade-off is that VCInlineMethods needs to deal with type parameters and multiple parameter lists whereas VCInline didn't.
@AlexSikia, This PR has been around for quite some time. Let's do a push and get this in? |
instead of `Name`s
Fixes dispatching of specialised methods to recursive calls. Also takes care of mutually recursive calls. Adds a few tests for recursive specialisation, and `@specialized` annotations with parameter `AnyRef` or `Specializable.specializable_group`
Detecting annotations on `Specializable` groups or `AnyRef` was flawed
Name mangling was incorrect previously. Now uses the `specializedFor` method in `NameOps`.
Conflicts: src/dotty/tools/dotc/core/NameOps.scala Conflicts: src/dotty/tools/dotc/core/NameOps.scala
`until` argument of `mergeArgs(...)` was passed the value of `argTypes.length` (only types which are used for instantiation) by `args(...)`, and therefore did not account for remaining generics.
Only type params directly preceded by an `@specialized` annotation will be specialised.
Changes type from `StringSetting` to `IntSetting`. Value x passed to the setting is the maximum number of parameters to specialize. Any method with type parameters will see the x first (or all if there are not enough) of them specialized. Conflicts: src/dotty/tools/dotc/config/ScalaSettings.scala
Makes for a more complete handling of different elements
Widening the type of the function is necessary before checking for parameterlessness of the methods.
154e6de
to
852ae7e
Compare
Refines names of variables and refactors small (outdated) parts of the code.
852ae7e
to
417fc96
Compare
Commit AlexSikia@07e9ae1 should be removed from this pull request, it's just an accidental revert of 10ea712 . |
Superseded by new work |
This implements method type specialization.
@DarkDimius Please review (and of course let me know if I should do anything differently with the pull request!)
Thanks