-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Delay name mangling #2128
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
Delay name mangling #2128
Conversation
/** A term name that's derived from an `underlying` name and that | ||
* adds `info` to it. | ||
*/ | ||
class DerivedTermName(override val underlying: TermName, override val info: NameInfo) |
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.
Instead of having a NameInfo
object as parameter, what about a NameFlagSet
?
@@ -163,7 +163,7 @@ object Names { | |||
def info = NameInfo.TermName | |||
def underlying: TermName = unsupported("underlying") | |||
|
|||
private var derivedNames: AnyRef /* SimpleMap | j.u.HashMap */ = | |||
@sharable private var derivedNames: AnyRef /* SimpleMap | j.u.HashMap */ = |
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 is this safe? synchronized
is not used when modifying derivedNames
currently.
e295718
to
9981ae1
Compare
The build failures are due to ContextEscapeDetection not compiling. I see: /drone/src/github.com/lampepfl/dotty/compiler/test/dotty/tools/ContextEscapeDetection.java:23: cannot find symbol Locally |
06316e6
to
ae6bd27
Compare
Rebased to master |
The issue only happen with the bootstrapped tests, to run them you need to first publish the non-bootstrapped compiler: publishLocal Then run the tests in the dotty-compiler-bootstrapped/test The test failure is very reminiscent of a problem I fixed in the backend some times ago: lampepfl/scala#4 The problem was that the inner class table in the classfile had incorrect outer class names, and indeed if we do public static abstract #10= #7 of #9; //Context=class dotty/tools/dotc/core/Contexts$Context of class dotty/tools/dotc/core/Contexts$ Instead of (from the compiled-by-scalac public static abstract #25= #24 of #2; //Context=class dotty/tools/dotc/core/Contexts$Context of class dotty/tools/dotc/core/Contexts The crucial difference is the last thing in the line: def dropModule: Name = n.stripModuleClassSuffix If I print |
Ah, I see now, the full relevant code in the backend is: val outerName = innerClassSym.rawowner.javaBinaryName
// Java compatibility. See the big comment in BTypes that summarizes the InnerClass spec.
val outerNameModule = if (innerClassSym.rawowner.isTopLevelModuleClass) outerName.dropModule Where def javaBinaryName: Name = toDenot(sym).fullNameSeparated("/") And |
The current failures are due to: assert(isValidJVMName(sym.name), s"${sym.fullName} name is invalid on jvm") Because in some cases we get |
I have two features request to aid debugging, let me know what you think:
|
e52ad28
to
29b51e8
Compare
@@ -339,7 +339,12 @@ object Names { | |||
|
|||
def isSimple = false | |||
def asSimpleName = throw new UnsupportedOperationException(s"$debugString is not a simple name") | |||
def toSimpleName = termName(toString) | |||
|
|||
private var simpleName: SimpleTermName = null |
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 think you want private[this] var
here to avoid creating a setter
def name = myName | ||
|
||
/** Update the name; only called when unpickling top-level classes */ | ||
def name_=(n: Name) = myName = n |
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.
Should this setter be protected[dotc]
like def info_=
?
override def newScopeLikeThis() = new PackageScope | ||
} | ||
|
||
private[core] val currentDecls: MutableScope = new PackageScope() | ||
|
||
def isFlatName(name: SimpleTermName) = name.lastIndexOf('$', name.length - 2) >= 0 |
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.
Could you add a comment explaining the name.length - 2
here? Also why is this logic different from the one for the other overload for isFlatName
?
newScopeEntry(defn.newFunctionNTrait(name.asTypeName)) | ||
else if (isFlatName(mangled.toSimpleName) && enterFlatClasses.isDefined) { | ||
Stats.record("package scopes with flatnames entered") | ||
enterFlatClasses.get(ctx) |
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 not use ensureComplete
here?
94e70aa
to
c6b6b30
Compare
c6b6b30
to
96304b4
Compare
Rebased to master |
d14baae
to
5bada41
Compare
This commit is too big to leave in the queue. There's constant breakage wrt other commits. So I want to get this in by the end of today at the latest. |
77992c9
to
1058278
Compare
This PR LGTM, except that I don't see how |
The use of @sharable private val simpleNameKinds = new mutable.HashMap[Int, ClassifiedNameKind]
@sharable private val qualifiedNameKinds = new mutable.HashMap[Int, QualifiedNameKind]
@sharable private val uniqueNameKinds = new mutable.HashMap[String, UniqueNameKind] is also suspicious. Right now it should be fine since all the NameKinds are instantiated in |
21bc82f
to
628a967
Compare
Remove unused functionality
It fails without any test output in partest
Drop Seq implementation of name. This implementation was always problematic because it entailed potentially very costly conversions to toSimpleName. We now have better control over when we convert a name to a simple name.
toSimpleName is called a lot from the backend, so it makes sense to memoize it. It would be even better to communicate with the backend using strings, because then we would not have to enter all these simple names in the name table.
Classfile parsing is about JVM-level names, not Scala level ones. So it is more consistent to use mangled names throughout.
Simplifies the test that the class represented by a classfile is the class logically referenced by the file. The simplification is needed if we want to populate package scopes with unmangled classnames.
Once we start using unencoded operators internally, we will face the problem that one cannot decode realiably a class file filename. We therefore turn things around, keeping members of package scopes in mangled and encoded form. This is compensated by (1) mangling names for lookup of such members and (2) when unpickling from Scala 2 info or Tasty, comparing mangled names when matching a read class or module object against a root.
Mangled is like toSimpleName, except that it keeps the term/type distinction.
Prevviously they were actually unused.
and fix a bug in TreeUnpickler
Since we now have separate package-scopes, it's easier to have them take into account the special role played by the scala package. So we can drop the funky logic of `makeScalaSpecial`.
Names with internal $'s are entered in package scopes only if - we look for a name with internal $'s. - we want to know all the members of a package scope This optimization seems to be fairly effective. The typical range of package scopes that need $-names is between 0 and 20%. The optimization seems to improve execution time of all unit tests by about 3%. Also. drop the inheritance from Iterable to Scope. The reason is that we now need a context parameter for toList and other Iterable operations which makes them impossible to fit into the Iterable framework.
Running the test suite with the pickling printer on showed up two more problems which are fixed in this commit.
Used a hardcoded string before, which caused test failures.
I'll roll the private constructor changes into the next PR. |
This PR aims to delay name mangling until the point where we emit code. Before, names should be "semantic", i.e. the kind of a name is represented by its structure instead of its characters.