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
Optimize away ClassTags and ArrayBuilders #1669
Optimize away ClassTags and ArrayBuilders #1669
Conversation
|
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1698/ |
Test FAILed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1699/ |
c41293a
to
1c99868
Compare
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1702/ |
1c99868
to
d229654
Compare
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1703/ |
9c5926a
to
0969fe2
Compare
OK, I'm done with this one. |
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1705/ |
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1704/ |
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1706/ |
What is |
isSubclass(lhsBase, rhsBase) | ||
/* All things must be considered subclasses of Object for this | ||
* purpose, even raw JS types and interfaces that do not have | ||
* Object in their ancestors, strictly speaking. |
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.
What do you mean by "strictly speaking"?
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.
Hum, nothing, really. I guess when I wrote that I was still surprised myself to rediscover that interfaces did not have Object
in their ancestors.
Also, why is not every class type subtype of |
Why not generalize |
@@ -0,0 +1,72 @@ | |||
/* __ *\ | |||
** ________ ___ / / ___ __ ____ Scala.js Test Suite ** |
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 file should be ReflectArrayTest.scala
.
Short for |
Hahahaha, I have no idea. But I though its something like |
For raw JS types, because they're not. They're subtypes of For interfaces, well, it might be an accident of history, because interfaces in .class files do not list Object as their superclass. So sjsir files do not either. But I guess we could instead decide that |
"intf java": 89k |
Because the qualifier could be |
Seems like we need a semantic flag :) |
Hmmm... nevertheless you can call all methods of |
I think we should do that. Doesn't this also apply in other (non-array) cases? We know that any non raw interface is a subtype of |
Even without optimizer, we never truly respect
Checking things accurately would be so awful, from both a performance perspective than a maintenance of JSDesaguring perspective, that this will never happen. |
Oh. OK for NPEs. If they are officially undefined behavior, we can do whatever we want :) So let's elide |
genericArrayBuilderResult( | ||
if (classOf[Unit] == elementClass) classOf[BoxedUnit] | ||
else if (classOf[Null] == elementClass || classOf[Nothing] == elementClass) classOf[Object] | ||
else elementClass, |
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.
Consider making a tmp var with this (except if it hinders inlining). It is hard to read.
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.
It does not do harm to inlining, no. It just produces a bit more JS code in the case where the runtimeClass is not known statically.
(edit: so I'll change it)
OK. I'll continue this later. The Array inlining tests were too much :) |
By the way, I think this PR is a good candidate for running a partest on it. |
Already did locally (that's how I found out that |
} | ||
cont(PreTransTree(CallHelper("makeNativeArrayWrapper", | ||
CallHelper("arrayDataOf", | ||
CallHelper("classDataOf", runtimeClass)(AnyType))(AnyType), |
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 since it exposes the existence of class data to the optimizer. Could we make a single dummy that takes a j.l.Class
and a js.Array
and produces the wrapped array?
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.
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.
Well yes... but the bracket part of it... Let's leave it. Probably not doable differently.
That's all. |
The side effects of `qualifier` are kept, obviously. We can do this because NPE is undefined behavior.
LoadModule, NewArray, ArrayValue, GetClass and ClassOf always return non-nullable values of an exact type. This can help some other optimizations, the most obvious being optimizing away a test LoadModule(_) === Null().
8c738ff
to
a85b6e4
Compare
Updated. |
* GetClass(expr) when expr has an exact type * clazz.getComponentType() * j.l.reflect.Array.newInstance(clazz, length) * Inline ScalaRunTime.{arrayClass,arrayElementClass}
This allows inlining of `Array.tabulate(x, y)`, for example, which is implemented as def tabulate[T: ClassTag](n1: Int, n2: Int)( f: (Int, Int) => T): Array[Array[T]] = tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) in which the tabulate_1 method is called with a lambda that itself calls tabulate_1.
Test PASSed. https://scala-webapps.epfl.ch/jenkins/job/scalajs-pr/1709/ |
Nightly passed on a85b6e4 |
LGTM |
…builders Optimize away ClassTags and ArrayBuilders
No description provided.