Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import dotty.tools.dotc.util.SrcPos
* @version 1.0
*
*/
trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder {
trait BCodeBodyBuilder(val primitives: ScalaPrimitives, val bTypes: KnownBTypes) extends BCodeSkelBuilder {
/*
* Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions.
*/
Expand Down Expand Up @@ -155,7 +155,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
// binary operation
case rarg :: Nil =>
val isShift = isShiftOp(code)
resKind = tpeTK(larg).maxType(if (isShift) INT else tpeTK(rarg), bTypes)
resKind = tpeTK(larg).maxType(if (isShift) INT else tpeTK(rarg), bTypes.ObjectRef)

if (isShift || isBitwiseOp(code)) {
assert(resKind.isIntegralType || (resKind == BOOL),
Expand Down Expand Up @@ -522,7 +522,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
val thrownType = expectedType
// `throw null` is valid although scala.Null (as defined in src/library-aux) isn't a subtype of Throwable.
// Similarly for scala.Nothing (again, as defined in src/library-aux).
assert(thrownType == bTypes.srNullRef || thrownType == bTypes.srNothingRef || thrownType.asClassBType.isSubtypeOf(bTypes.jlThrowableRef))
assert(thrownType.isNull || thrownType.isNothing || thrownType.asClassBType.isSubtypeOf(bTypes.jlThrowableRef))
emit(asm.Opcodes.ATHROW)
end genAdaptAndSendToDest

Expand Down Expand Up @@ -1160,7 +1160,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
* `varsInScope`, ending at the current program point.
*/
def emitLocalVarScopes(): Unit =
if (BackendUtils.emitVars) {
if (emitVars) {
val end = currProgramPoint()
for ((sym, start) <- varsInScope.nn.reverse) {
emitLocalVarScope(sym, start, end)
Expand All @@ -1169,7 +1169,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
end emitLocalVarScopes

def adapt(from: BType, to: BType)(using Context): Unit = {
if (from == bTypes.srNothingRef) {
if (from.isNothing) {
/* There are two possibilities for from being Nothing: emitting a "throw e" expressions and
* loading a (phantom) value of type Nothing.
*
Expand Down Expand Up @@ -1216,7 +1216,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
*/
if (lastInsn.getOpcode != asm.Opcodes.ATHROW)
emit(asm.Opcodes.ATHROW)
} else if (from == bTypes.srNullRef) {
} else if (from.isNull) {
/* After loading an expression of type `scala.runtime.Null$`, introduce POP; ACONST_NULL.
* This is required to pass the verifier: in Scala's type system, Null conforms to any
* reference type. In bytecode, the type Null is represented by scala.runtime.Null$, which
Expand Down Expand Up @@ -1483,7 +1483,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
val ownerBType = bTypeLoader.bTypeFromType(method.owner.info)
if (isInterface && !method.is(JavaDefined)) {
val staticDesc = MethodBType(ownerBType :: bmType.argumentTypes, bmType.returnType).descriptor
val staticName = BackendUtils.traitSuperAccessorName(method)
val staticName = SymbolUtils.traitSuperAccessorName(method)
bc.invokestatic(receiverName, staticName, staticDesc, isInterface, pos)
} else {
if (isInterface) {
Expand Down Expand Up @@ -1607,7 +1607,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder
genLoad(nonNullSide, bTypes.ObjectRef)
genCZJUMP(success, failure, op, bTypes.ObjectRef, targetIfNoJump)
} else {
val tk = tpeTK(l).maxType(tpeTK(r), bTypes)
val tk = tpeTK(l).maxType(tpeTK(r), bTypes.ObjectRef)
genLoad(l, tk)
stack.push(tk)
genLoad(r, tk)
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import dotty.tools.dotc.config.ScalaSettingsProperties
* @version 1.0
*
*/
trait BCodeHelpers(val bTypeLoader: BTypeLoader, val bTypes: WellKnownBTypes) extends BCodeIdiomatic {
trait BCodeHelpers(val bTypeLoader: BTypeLoader) extends BCodeIdiomatic {

// OK to cache because it won't change across Contexts
private var cachedClassfileVersion: Int | Null = null
Expand Down Expand Up @@ -570,11 +570,11 @@ trait BCodeHelpers(val bTypeLoader: BTypeLoader, val bTypes: WellKnownBTypes) ex
bType.info.flags,
mirrorName,
null /* no java-generic-signature */,
bTypes.ObjectRef.internalName,
ClassBType.javaLangObjectInternalName,
EMPTY_STRING_ARRAY
)

if (BackendUtils.emitSource) {
if (emitSource) {
mirrorClass.visitSource("" + ctx.compilationUnit.source.file.name, null /* SourceDebugExtension */)
}

Expand Down
22 changes: 16 additions & 6 deletions compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package dotty.tools
package backend
package jvm

import dotty.tools.backend.jvm.opt.CallGraph
import scala.tools.asm
import scala.annotation.switch
import scala.tools.asm.tree.MethodInsnNode
import dotty.tools.dotc.ast.Positioned
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.util.NoSourcePosition

/*
* A high-level facade to the ASM API for bytecode generation.
Expand All @@ -15,9 +17,17 @@ import dotty.tools.dotc.core.Contexts.Context
* @version 1.0
*
*/
trait BCodeIdiomatic {

def recordCallsitePosition(m: MethodInsnNode, pos: Positioned | Null)(using Context): Unit
trait BCodeIdiomatic(callGraph: Option[CallGraph]) {
private val debugLevel = 3 // 0 -> no debug info; 1-> filename; 2-> lines; 3-> varnames
final val emitSource = debugLevel >= 1
final val emitLines = debugLevel >= 2
final val emitVars = debugLevel >= 3

private def recordCallsitePosition(m: MethodInsnNode, pos: Positioned | Null)(using Context): Unit =
callGraph.foreach(_.recordCallsitePosition(m, pos match {
case p: Positioned => p.sourcePos
case null => NoSourcePosition
}))

val CLASS_CONSTRUCTOR_NAME = "<clinit>"
val INSTANCE_CONSTRUCTOR_NAME = "<init>"
Expand Down Expand Up @@ -172,12 +182,12 @@ trait BCodeIdiomatic {
recipe: String,
argTypes: Seq[asm.Type],
constants: Seq[String],
ts: WellKnownBTypes
bTypes: KnownBTypes
): Unit = {
jmethod.visitInvokeDynamicInsn(
"makeConcatWithConstants",
asm.Type.getMethodDescriptor(ts.StringRef.toASMType, argTypes*),
ts.jliStringConcatFactoryMakeConcatWithConstantsHandle,
asm.Type.getMethodDescriptor(bTypes.StringRef.toASMType, argTypes*),
bTypes.jliStringConcatFactoryMakeConcatWithConstantsHandle,
(recipe +: constants)*
)
}
Expand Down
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
private def initJClass(jclass: asm.ClassVisitor)(using Context): Unit = {

val ps = claszSymbol.info.parents
val superClass: String = if ps.isEmpty then bTypes.ObjectRef.internalName
val superClass: String = if ps.isEmpty then ClassBType.javaLangObjectInternalName
else bTypeLoader.classBTypeFromSymbol(ps.head.typeSymbol).internalName

// We need to emit not only directly implemented interfaces, but also any indirectly implemented ones that are the target of super calls.
Expand Down Expand Up @@ -343,7 +343,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
thisName, thisSignature,
superClass, interfaceNames.toArray)

if (BackendUtils.emitSource) {
if (emitSource) {
cnode.visitSource(ctx.compilationUnit.source.file.name, null /* SourceDebugExtension */)
}

Expand Down Expand Up @@ -619,7 +619,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
case _ => a
}

if (BackendUtils.emitLines && tree.span.exists && !tree.hasAttachment(SyntheticUnit)) {
if (emitLines && tree.span.exists && !tree.hasAttachment(SyntheticUnit)) {
val nr =
val sourcePos = tree.sourcePos
(
Expand Down Expand Up @@ -759,7 +759,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
*/
private def makeStatifiedDefDef(dd: DefDef)(using Context): DefDef =
val origSym = dd.symbol.asTerm
val newSym = BackendUtils.makeStatifiedDefSymbol(origSym, origSym.name)
val newSym = SymbolUtils.makeStatifiedDefSymbol(origSym, origSym.name)
tpd.DefDef(newSym, { paramRefss =>
val selfParamRef :: regularParamRefs = paramRefss.head: @unchecked
val enclosingClass = origSym.owner.asClass
Expand Down Expand Up @@ -799,8 +799,8 @@ trait BCodeSkelBuilder extends BCodeHelpers {
// but remember to change it there if you make changes here
// !!!
val origSym = dd.symbol.asTerm
val name = BackendUtils.traitSuperAccessorName(origSym).toTermName
val sym = BackendUtils.makeStatifiedDefSymbol(origSym, name)
val name = SymbolUtils.traitSuperAccessorName(origSym).toTermName
val sym = SymbolUtils.makeStatifiedDefSymbol(origSym, name)
tpd.DefDef(sym, { paramss =>
val params = paramss.head
tpd.Apply(params.head.select(origSym), params.tail)
Expand Down Expand Up @@ -898,7 +898,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
else
genLoadTo(trimmedRhs, returnType, LoadDestination.Return)

if (BackendUtils.emitVars) {
if (emitVars) {
// add entries to LocalVariableTable JVM attribute
val onePastLastProgramPoint = currProgramPoint()
val hasStaticBitSet = ((flags & asm.Opcodes.ACC_STATIC) != 0)
Expand Down
23 changes: 20 additions & 3 deletions compiler/src/dotty/tools/backend/jvm/BTypeLoader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ final class BTypeLoader(primitives: ScalaPrimitives, inlineInfoLoader: () => Opt
assert(
classSym != defn.NothingClass && classSym != defn.NullClass,
s"Cannot create ClassBType for special class symbol ${classSym.showFullName}")
assert(classSym != defn.ArrayClass || BackendUtils.compilingArray, classSym)
assert(!classSym.isPrimitiveValueClass || BackendUtils.compilingPrimitive, s"Found $classSym while compiling ${ctx.compilationUnit.source.file.name}")
assert(classSym != defn.ArrayClass || compilingArray, classSym)
assert(!classSym.isPrimitiveValueClass || compilingPrimitive, s"Found $classSym while compiling ${ctx.compilationUnit.source.file.name}")

classBType(classSym.javaBinaryName)(ct => createClassInfo(ct, classSym.asClass))
}
Expand Down Expand Up @@ -354,7 +354,7 @@ final class BTypeLoader(primitives: ScalaPrimitives, inlineInfoLoader: () => Opt
val staticForwarders = if classSym.is(Trait) then
// !!! This logic duplicates PlainSkelBuilder::makeStaticForwarder, copy changes there !!!
classSym.info.decls.filter(s => s.isTerm && !s.isPrivate && !s.isStaticMember && s.name != nme.TRAIT_CONSTRUCTOR).map(s => {
BackendUtils.makeStatifiedDefSymbol(s.asTerm, BackendUtils.traitSuperAccessorName(s).toTermName)
SymbolUtils.makeStatifiedDefSymbol(s.asTerm, SymbolUtils.traitSuperAccessorName(s).toTermName)
})
else Nil
classMethods ++ staticForwarders
Expand Down Expand Up @@ -395,4 +395,21 @@ final class BTypeLoader(primitives: ScalaPrimitives, inlineInfoLoader: () => Opt
@tailrec
private def isOriginallyStaticOwner(sym: Symbol)(using Context): Boolean =
sym.is(PackageClass) || sym.is(ModuleClass) && isOriginallyStaticOwner(sym.originalOwner.originalLexicallyEnclosingClass)

private def compilingArray(using Context) =
ctx.compilationUnit.source.file.name == "Array.scala"

private val primitiveCompilationUnits = Set(
"Unit.scala",
"Boolean.scala",
"Char.scala",
"Byte.scala",
"Short.scala",
"Int.scala",
"Float.scala",
"Long.scala",
"Double.scala"
)
private def compilingPrimitive(using Context) =
primitiveCompilationUnits(ctx.compilationUnit.source.file.name)
}
Loading
Loading