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
SI-6611 Tighten up an unsafe array optimization #1568
Conversation
The net was cast too wide and was unsafely optimizing away array copies.
Started jenkins job pr-scala-testsuite-linux-opt at https://scala-webapps.epfl.ch/jenkins/job/pr-scala-testsuite-linux-opt/1544/ |
jenkins job pr-scala-testsuite-linux-opt: Success - https://scala-webapps.epfl.ch/jenkins/job/pr-scala-testsuite-linux-opt/1544/ |
Started jenkins job pr-rangepos at https://scala-webapps.epfl.ch/jenkins/job/pr-rangepos/836/ |
jenkins job pr-rangepos: Success - https://scala-webapps.epfl.ch/jenkins/job/pr-rangepos/836/ |
object StripCast { | ||
def unapply(tree: Tree): Some[Tree] = Some(stripCast(tree)) | ||
} | ||
|
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.
I don't like this style of extractor; I think it should return Some(tree) when it's a different tree, and None otherwise. Otherwise you learn nothing from the fact that it matched. I have a work in progress with a bunch of extractors along these lines: https://github.com/paulp/scala/blob/value-class-extractors/src/compiler/scala/tools/nsc/Global.scala#L1118
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.
Here are some less value-class-specific ones: https://github.com/paulp/scala/blob/value-class-extractors/src/reflect/scala/reflect/internal/Definitions.scala#L1122
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.
I find that Some
returning extractors are useful additions to a pattern vocabulary. Particularly handy is: object && { def unapply[T](t) = Some((t, t)) }
.
In this case I'm relying on it matching in both of the trees:
// Array(null: Object)
scala.Array.apply(scala.this.Predef.wrapRefArray(Array[java.lang.Object]{(null: java.lang.Object)}), reflect.this.Manifest.Object());
// Array(null: String)
scala.Array.apply(scala.this.Predef.wrapRefArray(Array[java.lang.String]{(null: java.lang.String)}.$asInstanceOf[Array[java.lang.Object]]()), reflect.this.ClassManifest.classType(classOf[java.lang.String]));
The different approaches would result in these patterns:
Apply(appMeth, List(Apply(wrapRefArrayMeth, List(arg @ StripCast(ArrayValue(_, _)))), _))
Apply(appMeth, List(Apply(wrapRefArrayMeth, List(arg @ (AsInstanceOf(ArrayValue(_, _), _) | ArrayValue(_, _))), _))
Both extractors are situationally useful; even though AsInstanceOf
is more fundamental.
I see your point, though still unexcited about it. I think ideally the core logic of any extractor which involves a runtime check should have a "None" and "Some" components. Behavior like you want here I would wish to put in an "extractor combinator" (which I'm not at all sure is workable) which takes an unapply(x: T):Option[T] and transforms it into (x: T):Some[T] by tacking on "orElse Some(x)". Anyway, I was just throwing it out there, I have complete faith in the legitimacy of your reasons for doing things. |
BTW, ".tpe.resultType.dealias.typeSymbol" is redundant, .typeSymbol dealiases. |
So in summary, LGTM. |
Started jenkins job pr-rangepos at https://scala-webapps.epfl.ch/jenkins/job/pr-rangepos/836/ |
Started jenkins job pr-scala-testsuite-linux-opt at https://scala-webapps.epfl.ch/jenkins/job/pr-scala-testsuite-linux-opt/1544/ |
jenkins job pr-rangepos: Success - https://scala-webapps.epfl.ch/jenkins/job/pr-rangepos/836/ |
jenkins job pr-scala-testsuite-linux-opt: Success - https://scala-webapps.epfl.ch/jenkins/job/pr-scala-testsuite-linux-opt/1544/ |
I cleaned this up a little ways and extended this optimization for primitive arrays. Encore review, please, by @paulp. |
I'm just a simple country hacker, but LGTM. |
SI-6611 Tighten up an unsafe array optimization
The net was cast too wide and was unsafely optimizing away array
copies.
review by @paulp
I'd like to move the following to
Definitions
, but I'm not what I can use in there to pick a particular overload when arity isn't enough.One idea I had was to annotate such methods:
It would simplify the compiler logic and make it more self evident in the source that this method is treated specially by the compiler. But maybe they should just be macros, which would be even more revealing.
Relates to SI-6247, in that it shows where one overload of
Array.apply
is already optimized, and where the corresponding primitive optimizations could go (again, unless macros are preferred.)