Skip to content

Commit 7a12e81

Browse files
committed
Simplify InvokeStyle
1 parent 096bc3b commit 7a12e81

File tree

2 files changed

+34
-71
lines changed

2 files changed

+34
-71
lines changed

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

Lines changed: 17 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import scala.tools.asm
1717
import GenBCode._
1818
import BackendReporting._
1919
import scala.tools.asm.tree.MethodInsnNode
20-
import scala.tools.nsc.backend.jvm.BCodeHelpers.TestOp
20+
import scala.tools.nsc.backend.jvm.BCodeHelpers.{InvokeStyle, TestOp}
2121

2222
/*
2323
*
@@ -35,8 +35,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
3535
* Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions.
3636
*/
3737
abstract class PlainBodyBuilder(cunit: CompilationUnit) extends PlainSkelBuilder(cunit) {
38-
import invokeStyles._
39-
4038
/* If the selector type has a member with the right name,
4139
* it is the host class; otherwise the symbol's owner.
4240
*/
@@ -581,8 +579,8 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
581579
// to call super constructors explicitly and/or use their 'returned' value.
582580
// therefore, we can ignore this fact, and generate code that leaves nothing
583581
// on the stack (contrary to what the type in the AST says).
584-
case Apply(fun @ Select(Super(_, mix), _), args) =>
585-
val invokeStyle = SuperCall(mix)
582+
case Apply(fun @ Select(Super(_, _), _), args) =>
583+
val invokeStyle = InvokeStyle.Super
586584
// if (fun.symbol.isConstructor) Static(true) else SuperCall(mix);
587585
mnode.visitVarInsn(asm.Opcodes.ALOAD, 0)
588586
genLoadArguments(args, paramTKs(app))
@@ -628,7 +626,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
628626
mnode.visitTypeInsn(asm.Opcodes.NEW, rt.internalName)
629627
bc dup generatedType
630628
genLoadArguments(args, paramTKs(app))
631-
genCallMethod(ctor, Static(onInstance = true), app.pos)
629+
genCallMethod(ctor, InvokeStyle.Special, app.pos)
632630

633631
case _ =>
634632
abort(s"Cannot instantiate $tpt of kind: $generatedType")
@@ -666,9 +664,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
666664
def genNormalMethodCall() {
667665

668666
val invokeStyle =
669-
if (sym.isStaticMember) Static(onInstance = false)
670-
else if (sym.isPrivate || sym.isClassConstructor) Static(onInstance = true)
671-
else Dynamic
667+
if (sym.isStaticMember) InvokeStyle.Static
668+
else if (sym.isPrivate || sym.isClassConstructor) InvokeStyle.Special
669+
else InvokeStyle.Virtual
672670

673671
if (invokeStyle.hasInstance) {
674672
genLoadQualifier(fun)
@@ -695,7 +693,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
695693

696694
case _ =>
697695
}
698-
if ((targetTypeKind != null) && (sym == definitions.Array_clone) && invokeStyle.isDynamic) {
696+
if ((targetTypeKind != null) && (sym == definitions.Array_clone) && invokeStyle.isVirtual) {
699697
// An invokevirtual points to a CONSTANT_Methodref_info which in turn points to a
700698
// CONSTANT_Class_info of the receiver type.
701699
// The JVMS is not explicit about this, but that receiver type may be an array type
@@ -997,7 +995,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
997995
// Optimization for expressions of the form "" + x. We can avoid the StringBuilder.
998996
case List(Literal(Constant("")), arg) =>
999997
genLoad(arg, ObjectRef)
1000-
genCallMethod(String_valueOf, Static(onInstance = false), arg.pos)
998+
genCallMethod(String_valueOf, InvokeStyle.Static, arg.pos)
1001999
case concatenations =>
10021000
bc.genStartConcat(tree.pos)
10031001
for (elem <- concatenations) {
@@ -1028,7 +1026,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
10281026
// whether to reference the type of the receiver or
10291027
// the type of the method owner
10301028
val useMethodOwner = (
1031-
style != Dynamic
1029+
!style.isVirtual
10321030
|| hostSymbol.isBottomClass
10331031
|| methodOwner == definitions.ObjectClass
10341032
)
@@ -1055,11 +1053,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
10551053
}
10561054
}
10571055

1058-
if (style.isStatic) {
1059-
if (style.hasInstance) { bc.invokespecial (jowner, jname, mdescr, pos) }
1060-
else { bc.invokestatic (jowner, jname, mdescr, pos) }
1061-
}
1062-
else if (style.isDynamic) {
1056+
if (style.isStatic) { bc.invokestatic (jowner, jname, mdescr, pos) }
1057+
else if (style.isSpecial) { bc.invokespecial (jowner, jname, mdescr, pos) }
1058+
else if (style.isVirtual) {
10631059
if (needsInterfaceCall(receiver)) { bc.invokeinterface(jowner, jname, mdescr, pos) }
10641060
else { bc.invokevirtual (jowner, jname, mdescr, pos) }
10651061
}
@@ -1075,7 +1071,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
10751071
def genScalaHash(tree: Tree, applyPos: Position): BType = {
10761072
genLoadModule(ScalaRunTimeModule) // TODO why load ScalaRunTimeModule if ## has InvokeStyle of Static(false) ?
10771073
genLoad(tree, ObjectRef)
1078-
genCallMethod(hashMethodSym, Static(onInstance = false), applyPos)
1074+
genCallMethod(hashMethodSym, InvokeStyle.Static, applyPos)
10791075
INT
10801076
}
10811077

@@ -1265,7 +1261,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
12651261
}
12661262
genLoad(l, ObjectRef)
12671263
genLoad(r, ObjectRef)
1268-
genCallMethod(equalsMethod, Static(onInstance = false), pos)
1264+
genCallMethod(equalsMethod, InvokeStyle.Static, pos)
12691265
genCZJUMP(success, failure, TestOp.NE, BOOL)
12701266
}
12711267
else {
@@ -1281,7 +1277,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
12811277
// SI-7852 Avoid null check if L is statically non-null.
12821278
genLoad(l, ObjectRef)
12831279
genLoad(r, ObjectRef)
1284-
genCallMethod(Object_equals, Dynamic, pos)
1280+
genCallMethod(Object_equals, InvokeStyle.Virtual, pos)
12851281
genCZJUMP(success, failure, TestOp.NE, BOOL)
12861282
} else {
12871283
// l == r -> if (l eq null) r eq null else l.equals(r)
@@ -1302,7 +1298,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
13021298

13031299
markProgramPoint(lNonNull)
13041300
locals.load(eqEqTempLocal)
1305-
genCallMethod(Object_equals, Dynamic, pos)
1301+
genCallMethod(Object_equals, InvokeStyle.Virtual, pos)
13061302
genCZJUMP(success, failure, TestOp.NE, BOOL)
13071303
}
13081304
}
@@ -1351,54 +1347,4 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
13511347
new asm.Handle(asm.Opcodes.H_INVOKESTATIC,
13521348
definitions.LambdaMetaFactory.fullName('/'), sn.AltMetafactory.toString,
13531349
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;")
1354-
1355-
object invokeStyles {
1356-
1357-
/** This class represents a method invocation style. */
1358-
sealed abstract class InvokeStyle {
1359-
/** Is this a dynamic method call? */
1360-
def isDynamic: Boolean = false
1361-
1362-
/** Is this a static method call? */
1363-
def isStatic: Boolean = false
1364-
1365-
def isSuper: Boolean = false
1366-
1367-
/** Is this an instance method call? */
1368-
def hasInstance: Boolean = true
1369-
1370-
/** Returns a string representation of this style. */
1371-
override def toString(): String
1372-
}
1373-
1374-
/** Virtual calls.
1375-
* On JVM, translated to either `invokeinterface` or `invokevirtual`.
1376-
*/
1377-
case object Dynamic extends InvokeStyle {
1378-
override def isDynamic = true
1379-
override def toString(): String = "dynamic"
1380-
}
1381-
1382-
/**
1383-
* Special invoke:
1384-
* Static(true) is used for calls to private members, ie `invokespecial` on JVM.
1385-
* Static(false) is used for calls to class-level instance-less static methods, ie `invokestatic` on JVM.
1386-
*/
1387-
case class Static(onInstance: Boolean) extends InvokeStyle {
1388-
override def isStatic = true
1389-
override def hasInstance = onInstance
1390-
override def toString(): String = {
1391-
if(onInstance) "static-instance"
1392-
else "static-class"
1393-
}
1394-
}
1395-
1396-
/** Call through super[mix].
1397-
* On JVM, translated to `invokespecial`.
1398-
*/
1399-
case class SuperCall(mix: Name) extends InvokeStyle {
1400-
override def isSuper = true
1401-
override def toString(): String = { "super(" + mix + ")" }
1402-
}
1403-
}
14041350
}

src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,4 +1366,21 @@ object BCodeHelpers {
13661366
val GT = new TestOp(4)
13671367
val LE = new TestOp(5)
13681368
}
1369+
1370+
class InvokeStyle(val style: Int) extends AnyVal {
1371+
import InvokeStyle._
1372+
def isVirtual: Boolean = this == Virtual
1373+
def isStatic : Boolean = this == Static
1374+
def isSpecial: Boolean = this == Special
1375+
def isSuper : Boolean = this == Super
1376+
1377+
def hasInstance = this != Static
1378+
}
1379+
1380+
object InvokeStyle {
1381+
val Virtual = new InvokeStyle(0) // InvokeVirtual or InvokeInterface
1382+
val Static = new InvokeStyle(1) // InvokeStatic
1383+
val Special = new InvokeStyle(2) // InvokeSpecial (private methods, constructors)
1384+
val Super = new InvokeStyle(3) // InvokeSpecial (super calls)
1385+
}
13691386
}

0 commit comments

Comments
 (0)