Skip to content

Commit 713ac6e

Browse files
authored
Merge pull request #8499 from dotty-staging/backend-call-receiver
backend: Emit calls using the correct receiver
2 parents fb2c650 + 4fa3eb2 commit 713ac6e

18 files changed

+467
-187
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 152 additions & 156 deletions
Large diffs are not rendered by default.

compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import scala.tools.asm
66
import scala.annotation.switch
77
import scala.collection.mutable
88
import Primitives.{NE, EQ, TestOp, ArithmeticOp}
9+
import scala.tools.asm.tree.MethodInsnNode
910

1011
/*
1112
* A high-level facade to the ASM API for bytecode generation.
@@ -104,7 +105,7 @@ trait BCodeIdiomatic {
104105
*/
105106
abstract class JCodeMethodN {
106107

107-
def jmethod: asm.MethodVisitor
108+
def jmethod: asm.tree.MethodNode
108109

109110
import asm.Opcodes;
110111

@@ -394,21 +395,27 @@ trait BCodeIdiomatic {
394395

395396
// can-multi-thread
396397
final def invokespecial(owner: String, name: String, desc: String, itf: Boolean): Unit = {
397-
jmethod.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf)
398+
emitInvoke(Opcodes.INVOKESPECIAL, owner, name, desc, itf)
398399
}
399400
// can-multi-thread
400401
final def invokestatic(owner: String, name: String, desc: String, itf: Boolean): Unit = {
401-
jmethod.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf)
402+
emitInvoke(Opcodes.INVOKESTATIC, owner, name, desc, itf)
402403
}
403404
// can-multi-thread
404405
final def invokeinterface(owner: String, name: String, desc: String): Unit = {
405-
jmethod.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true)
406+
emitInvoke(Opcodes.INVOKEINTERFACE, owner, name, desc, itf = true)
406407
}
407408
// can-multi-thread
408409
final def invokevirtual(owner: String, name: String, desc: String): Unit = {
409-
jmethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false)
410+
emitInvoke(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf = false)
410411
}
411412

413+
def emitInvoke(opcode: Int, owner: String, name: String, desc: String, itf: Boolean): Unit = {
414+
val node = new MethodInsnNode(opcode, owner, name, desc, itf)
415+
jmethod.instructions.add(node)
416+
}
417+
418+
412419
// can-multi-thread
413420
final def goTo(label: asm.Label): Unit = { jmethod.visitJumpInsn(Opcodes.GOTO, label) }
414421
// can-multi-thread

compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class BTypesFromSymbols[I <: BackendInterface](val int: I) extends BTypes {
4949
assert(
5050
(!primitiveTypeMap.contains(classSym) || isCompilingPrimitive) &&
5151
(classSym != NothingClass && classSym != NullClass),
52-
s"Cannot create ClassBType for special class symbol ${classSym.fullName}")
52+
s"Cannot create ClassBType for special class symbol ${classSym.showFullName}")
5353

5454
convertedClasses.getOrElse(classSym, {
5555
val internalName = classSym.javaBinaryName

compiler/src/dotty/tools/backend/jvm/BackendInterface.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,10 +442,10 @@ abstract class BackendInterface extends BackendInterfaceDefinitions {
442442
}
443443

444444
abstract class SymbolHelper {
445+
def exists: Boolean
446+
445447
// names
446-
def fullName(sep: Char): String
447-
def fullName: String
448-
def simpleName: Name
448+
def showFullName: String
449449
def javaSimpleName: String
450450
def javaBinaryName: String
451451
def javaClassName: String
@@ -460,10 +460,11 @@ abstract class BackendInterface extends BackendInterfaceDefinitions {
460460
/** Does this symbol actually correspond to an interface that will be emitted?
461461
* In the backend, this should be preferred over `isInterface` because it
462462
* also returns true for the symbols of the fake companion objects we
463-
* create for Java-defined classes.
463+
* create for Java-defined classes as well as for Java annotations
464+
* which we represent as classes.
464465
*/
465466
final def isEmittedInterface: Boolean = isInterface ||
466-
isJavaDefined && isModuleClass && companionClass.isInterface
467+
isJavaDefined && (isAnnotation || isModuleClass && companionClass.isInterface)
467468

468469
// tests
469470
def isClass: Boolean
@@ -491,6 +492,7 @@ abstract class BackendInterface extends BackendInterfaceDefinitions {
491492
def getsJavaPrivateFlag: Boolean
492493
def isFinal: Boolean
493494
def getsJavaFinalFlag: Boolean
495+
def isScalaStatic: Boolean
494496
def isStaticMember: Boolean
495497
def isBottomClass: Boolean
496498
def isBridge: Boolean
@@ -508,6 +510,7 @@ abstract class BackendInterface extends BackendInterfaceDefinitions {
508510
def shouldEmitForwarders: Boolean
509511
def isJavaDefaultMethod: Boolean
510512
def isClassConstructor: Boolean
513+
def isAnnotation: Boolean
511514
def isSerializable: Boolean
512515
def isEnum: Boolean
513516

@@ -536,6 +539,7 @@ abstract class BackendInterface extends BackendInterfaceDefinitions {
536539
def enclosingClassSym: Symbol
537540
def originalLexicallyEnclosingClass: Symbol
538541
def nextOverriddenSymbol: Symbol
542+
def allOverriddenSymbols: List[Symbol]
539543

540544

541545
// members
@@ -605,6 +609,7 @@ abstract class BackendInterface extends BackendInterfaceDefinitions {
605609
*/
606610
def sortedMembersBasedOnFlags(required: Flags, excluded: Flags): List[Symbol]
607611
def members: List[Symbol]
612+
def decl(name: Name): Symbol
608613
def decls: List[Symbol]
609614
def underlying: Type
610615
def parents: List[Type]

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -627,10 +627,10 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
627627
}
628628

629629
implicit def symHelper(sym: Symbol): SymbolHelper = new SymbolHelper {
630+
def exists: Boolean = sym.exists
631+
630632
// names
631-
def fullName(sep: Char): String = sym.showFullName
632-
def fullName: String = sym.showFullName
633-
def simpleName: Name = sym.name
633+
def showFullName: String = sym.showFullName
634634
def javaSimpleName: String = toDenot(sym).name.mangledString // addModuleSuffix(simpleName.dropLocal)
635635
def javaBinaryName: String = javaClassName.replace('.', '/') // TODO: can we make this a string? addModuleSuffix(fullNameInternal('/'))
636636
def javaClassName: String = toDenot(sym).fullName.mangledString // addModuleSuffix(fullNameInternal('.')).toString
@@ -678,11 +678,13 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
678678
isPrivate || (sym.isPrimaryConstructor && sym.owner.isTopLevelModuleClass)
679679

680680
def isFinal: Boolean = sym.is(Flags.Final)
681+
def isScalaStatic: Boolean =
682+
toDenot(sym).hasAnnotation(ctx.definitions.ScalaStaticAnnot)
681683
def isStaticMember: Boolean = (sym ne NoSymbol) &&
682-
(sym.is(Flags.JavaStatic) || toDenot(sym).hasAnnotation(ctx.definitions.ScalaStaticAnnot))
684+
(sym.is(Flags.JavaStatic) || isScalaStatic)
683685
// guard against no sumbol cause this code is executed to select which call type(static\dynamic) to use to call array.clone
684686

685-
def isBottomClass: Boolean = (sym ne defn.NullClass) && (sym ne defn.NothingClass)
687+
def isBottomClass: Boolean = (sym eq defn.NullClass) || (sym eq defn.NothingClass)
686688
def isBridge: Boolean = sym.is(Flags.Bridge)
687689
def isArtifact: Boolean = sym.is(Flags.Artifact)
688690
def hasEnumFlag: Boolean = sym.isAllOf(Flags.JavaEnumTrait)
@@ -700,6 +702,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
700702
def isEnum = sym.is(Flags.Enum)
701703

702704
def isClassConstructor: Boolean = toDenot(sym).isClassConstructor
705+
def isAnnotation: Boolean = toDenot(sym).isAnnotation
703706
def isSerializable: Boolean = toDenot(sym).isSerializable
704707

705708
/**
@@ -761,12 +764,14 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
761764
toDenot(sym)(shiftedContext).lexicallyEnclosingClass(shiftedContext)
762765
} else NoSymbol
763766
def nextOverriddenSymbol: Symbol = toDenot(sym).nextOverriddenSymbol
767+
def allOverriddenSymbols: List[Symbol] = toDenot(sym).allOverriddenSymbols.toList
764768

765769
// members
766770
def primaryConstructor: Symbol = toDenot(sym).primaryConstructor
767771

768772
/** For currently compiled classes: All locally defined classes including local classes.
769773
* The empty list for classes that are not currently compiled.
774+
770775
*/
771776
def nestedClasses: List[Symbol] = definedClasses(ctx.flattenPhase)
772777

@@ -878,6 +883,8 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
878883

879884
def memberInfo(s: Symbol): Type = tp.memberInfo(s)
880885

886+
def decl(name: Name): Symbol = tp.decl(name).symbol
887+
881888
def decls: List[Symbol] = tp.decls.toList
882889

883890
def members: List[Symbol] = tp.allMembers.map(_.symbol).toList

compiler/src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class GenBCodePipeline(val int: DottyBackendInterface)(implicit val ctx: Context
207207
if (claszSymbol.companionClass == NoSymbol) {
208208
mirrorCodeGen.genMirrorClass(claszSymbol, cunit)
209209
} else {
210-
ctx.log(s"No mirror class for module with linked class: ${claszSymbol.fullName}")
210+
ctx.log(s"No mirror class for module with linked class: ${claszSymbol.showFullName}")
211211
null
212212
}
213213
} else null

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,15 +246,21 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
246246
}
247247
}
248248

249-
def compileFromStrings(sourceCodes: String*): Unit = {
250-
val sourceFiles = sourceCodes.map {sourceCode =>
251-
val virtualFile = new VirtualFile(s"compileFromString-${java.util.UUID.randomUUID().toString}")
249+
def compileFromStrings(scalaSources: List[String], javaSources: List[String] = Nil): Unit = {
250+
def sourceFile(source: String, isJava: Boolean): SourceFile = {
251+
val uuid = java.util.UUID.randomUUID().toString
252+
val ext = if (isJava) ".java" else ".scala"
253+
val virtualFile = new VirtualFile(s"compileFromString-$uuid.$ext")
252254
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8")) // buffering is still advised by javadoc
253-
writer.write(sourceCode)
255+
writer.write(source)
254256
writer.close()
255257
new SourceFile(virtualFile, Codec.UTF8)
256258
}
257-
compileSources(sourceFiles.toList)
259+
val sources =
260+
scalaSources.map(sourceFile(_, isJava = false)) ++
261+
javaSources.map(sourceFile(_, isJava = true))
262+
263+
compileSources(sources)
258264
}
259265

260266
/** Print summary; return # of errors encountered */

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,10 @@ object SymDenotations {
787787
*/
788788
def derivesFrom(base: Symbol)(implicit ctx: Context): Boolean = false
789789

790+
/** Is this a Scala or Java annotation ? */
791+
def isAnnotation(implicit ctx: Context): Boolean =
792+
isClass && derivesFrom(defn.AnnotationClass)
793+
790794
/** Is this symbol a class that extends `java.io.Serializable` ? */
791795
def isSerializable(implicit ctx: Context): Boolean =
792796
isClass && derivesFrom(defn.JavaSerializableClass)

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ object Types {
421421
case tp: ClassInfo => tp.cls
422422
case tp: SingletonType => NoSymbol
423423
case tp: TypeProxy => tp.underlying.typeSymbol
424+
case _: JavaArrayType => defn.ArrayClass
424425
case _ => NoSymbol
425426
}
426427

@@ -448,6 +449,8 @@ object Types {
448449
else NoSymbol
449450
case tp: OrType =>
450451
tp.join.classSymbol
452+
case _: JavaArrayType =>
453+
defn.ArrayClass
451454
case _ =>
452455
NoSymbol
453456
}

compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ object Scala3:
123123
def isSyntheticWithIdent(using Context): Boolean =
124124
sym.is(Synthetic) && !sym.isAnonymous && !sym.name.isEmptyNumbered
125125

126-
def isAnnotation(using Context): Boolean =
127-
sym.derivesFrom(defn.AnnotationClass)
128-
129126
// end SymbolOps
130127

131128
object LocalSymbol:

0 commit comments

Comments
 (0)