More JVM backend cleanup#25747
Conversation
51479f4 to
9c5119c
Compare
| import java.util.ConcurrentModificationException | ||
|
|
||
| object FileWriters { | ||
| type InternalName = String |
There was a problem hiding this comment.
The existence of BTypes.InternalName is already questionable, having a dupe here is really weird IMHO
(This file already does its own stuff too much, like a unique "ReadOnlyContext" abstraction...)
|
|
||
| object FileWriters { | ||
| type InternalName = String | ||
| type NullableFile = AbstractFile | Null |
There was a problem hiding this comment.
The backend needs to always get a file back, and only the JAR writer didn't do that here, so I copied the code from the backend version, and thus we no longer have nullable files
| type InternalName = String | ||
| type NullableFile = AbstractFile | Null | ||
| private def classRelativePath(className: String, suffix: String): String = | ||
| className.replace('.', '/') + suffix |
There was a problem hiding this comment.
Moved up because it's used by both the tasty and classfile writers
| } | ||
|
|
||
| } | ||
| /** |
There was a problem hiding this comment.
Review with "ignore whitespace" on
bd6071a to
e29a481
Compare
| import dotty.tools.dotc.core.StdNames.nme | ||
|
|
||
| final class BoxUnbox(backendUtils: BackendUtils, callGraph: CallGraph, ts: CoreBTypes) { | ||
| final class BoxUnbox(backendUtils: BackendUtils, callGraph: CallGraph, ts: WellKnownBTypes) { |
There was a problem hiding this comment.
This is a large commit but it's just renaming and moving stuff. Anything loading is in the loader, any known types are in WellKnownBTypes, though the loader also has Object + Null + Nothing well-known types since it needs them as part of loading (and WellKnownBTypes just forwards)
| Some(classNode, moduleNode) | ||
| } catch { | ||
| case ex: Exception => | ||
| frontendAccess.optimizerWarning(em"Error while reading InlineInfoAttribute: ${ex.getMessage}", fullName, NoSourcePosition) |
There was a problem hiding this comment.
I don't think this is a useful "warning". It's a try/catch around the entire classloading for a hypothetical problem reading one small part of it. If this loading fails we should fail, imho.
There was a problem hiding this comment.
I think the idea is that we didn't want to fail the compiler just because something could not be inlined / optimized. Maybe the warning text ("while reading InlineInfoAttribute") is just misleading?
There was a problem hiding this comment.
Fair, let's reuse the existing "class not found" return value infrastructure then
b5f6a77 to
91daf55
Compare
|
Rebased over the latest changes in main (mostly the unsafeNulls removal outside of the backend, and the entry point collection removal) Now the only non-backend file referencing the JVM backend is |
lrytz
left a comment
There was a problem hiding this comment.
Looks good, a lot of nice cleanups!
| Some(classNode, moduleNode) | ||
| } catch { | ||
| case ex: Exception => | ||
| frontendAccess.optimizerWarning(em"Error while reading InlineInfoAttribute: ${ex.getMessage}", fullName, NoSourcePosition) |
There was a problem hiding this comment.
I think the idea is that we didn't want to fail the compiler just because something could not be inlined / optimized. Maybe the warning text ("while reading InlineInfoAttribute") is just misleading?
| } | ||
| // Don't try to build a BType for `VarHandle`, it doesn't exist on JDK 8 | ||
| if (owner.name == ts.jliMethodHandleRef.internalName || owner.name == "java/lang/invoke/VarHandle") | ||
| if (owner.name == "java/lang/invoke/MethodHandle" || owner.name == "java/lang/invoke/VarHandle") |
There was a problem hiding this comment.
In general we should try to always use a BType instance. The reason is the getCommonSuperClass method, which is invoked by ASM during bytecode writing for computing stack map frames.
The comment in getCommonSuperClass mentions "see [[cachedClassBType]]", which was renamed in one of the refactorings in scala3, it's "classBTypeFromInternalName" now, but I think the principle is the same. BType lookup at this stage will only succeed if the BType was previously constructed while running the backend / optimizer.
If it can't be done here, I would at least add a code comment about it.
There was a problem hiding this comment.
So the idea is that if owner.name == ts.jliMethodHandleRef.internalName here, we want to make sure we have ts.jliMethodHandleRef in the "already loaded" classes later?
Do we save a significant amount of effort doing this compared to, e.g., listing these descriptors as vals somewhere and always loading the corresponding BTypes if the optimizer is on, without having to thread a "well-known BTypes" object throughout?
There was a problem hiding this comment.
It probably doesn't matter here, but I tried to stick to the principle across the backend of not using strings for static internal names.
The background is: if a reference type p/C appears in generated code, ASM might invoke getCommonSuperClass for that type. At this point we need to be able to get to the corresponding ClassBType.
There was a problem hiding this comment.
in this case I believe it's fine because if we get here the owner will have been loaded as a BType already. Added a comment.
|
|
||
| def srNothingRef(using Context): ClassBType = | ||
| if srNothingRefLazy eq null then | ||
| srNothingRefLazy = classBTypeFromSymbol(requiredClass("scala.runtime.Nothing$")) |
There was a problem hiding this comment.
There's no more lock on initializing srNothingRef and the other types here, is that fine? I think we should not have concurrent operations on the symbol table.
There was a problem hiding this comment.
It might be theoretically possible for this not to be initialized before getting into the optimizer indeed...
The reason these three are not eagerly initialized, even though they'll basically always be needed, is that we have a test with just class java and that causes -Ycheck:all to fail if we load java.lang.Object because there are two things named java. I'll see if I can fix -Ycheck instead.
There was a problem hiding this comment.
ok, loading the BTypes themselves isn't feasible because the class needs those fields as part of BType loading, but fetching the symbols from the symbol table at construction time is easy, so let's do that. it also avoids the problem from my previous comment.
… OptimizerSettings
…thus thread safe val
…r does not capture a Context
91daf55 to
258e041
Compare
Part of #25218
Review commit by commit, each of them individually passes tests (I think, I did some light rebasing).
Contextin methods, do not capture it inside classesCoreBTypesintoBTypeLoaderandWellKnownBTypes; the latter is whatCoreBTypesFromSymbolsused to be, minus loading stuff that went into the former. Only the latter captures a Context (and it's the only remaining class to do so).ContextinGenBCodegenClassDef(it isn't supposed to be multi-threaded anyway, but right now on main if you remove the lock all hell breaks loose)We can't quite remove
frontendLock/ PPFA yet, as this happens if we do:How much have you relied on LLM-based tools in this contribution?
not
How was the solution tested?
existing tests, this is a pure refactoring