summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-08-12 16:12:15 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2014-08-19 17:50:02 +0200
commitf73f026bf250e6eb3c22c2b1975d4fdc2f23eab6 (patch)
treeb1d49a853c90740c6e4b15b0c8365c72b702970d /src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
parentbdc3ff97e7f869b393de7e4deb53535a93738ad1 (diff)
downloadscala-f73f026bf250e6eb3c22c2b1975d4fdc2f23eab6.tar.gz
scala-f73f026bf250e6eb3c22c2b1975d4fdc2f23eab6.tar.bz2
scala-f73f026bf250e6eb3c22c2b1975d4fdc2f23eab6.zip
Remove Tracked, add type information to ClassBType
Before this change, a ClassBType was just a name. The `exemplars` map stored a Tracked instance for every ClassBType. Tracked stored type information that is required later in the backend when things may run concurrently. In particular: superclass, interfaces, flags and information for emitting the InnerClass attribute. Now we put all the information stored in Tracked directly in the ClassBType. There is still one hash map: `classBTypeFromInternalNameMap` maps a JVM internal class name (e.g. "scala/Predef$") to the corresponding ClassBType. This map is used during bytecode generation, when the ASM framework computes stack map frames. In order to compute stack map frames, the ASM framework needs to be able to get the LUB of two types. The default implementation uses reflection to get type information, however that doesn't work in our case: the classes we compile are not on the classpath. So instead, the backend overwrites the method `getCommonSuperClass` of the ClassWriter. This method receives two class internal names and computes their LUB. This is done by looking up the ClassBTypes in the `classBTypeFromInternalNameMap` and invoking `jvmWiseLUB`. This commit was reviwed in https://github.com/scala/scala/pull/3855. It consists of all commits labelled [squash-after-review], squashed into one.
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala36
1 files changed, 18 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index 2d1030121e..542ff48c33 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -92,7 +92,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
val thrownKind = tpeTK(expr)
// `throw null` is valid although scala.Null (as defined in src/libray-aux) isn't a subtype of Throwable.
// Similarly for scala.Nothing (again, as defined in src/libray-aux).
- assert(thrownKind.isNullType || thrownKind.isNothingType || exemplars.get(thrownKind).isSubtypeOf(ThrowableReference))
+ assert(thrownKind.isNullType || thrownKind.isNothingType || thrownKind.asClassBType.isSubtypeOf(ThrowableReference))
genLoad(expr, thrownKind)
lineNumber(expr)
emit(asm.Opcodes.ATHROW) // ICode enters here into enterIgnoreMode, we'll rely instead on DCE at ClassNode level.
@@ -123,7 +123,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
// binary operation
case rarg :: Nil =>
- resKind = maxType(tpeTK(larg), tpeTK(rarg))
+ resKind = tpeTK(larg).maxType(tpeTK(rarg))
if (scalaPrimitives.isShiftOp(code) || scalaPrimitives.isBitwiseOp(code)) {
assert(resKind.isIntegralType || (resKind == BOOL),
s"$resKind incompatible with arithmetic modulo operation.")
@@ -321,7 +321,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
mnode.visitVarInsn(asm.Opcodes.ALOAD, 0)
generatedType =
if (tree.symbol == ArrayClass) ObjectReference
- else ClassBType(thisName) // inner class (if any) for claszSymbol already tracked.
+ else classBTypeFromSymbol(claszSymbol)
}
case Select(Ident(nme.EMPTY_PACKAGE_NAME), module) =>
@@ -459,9 +459,10 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
case ClazzTag =>
val toPush: BType = {
- val kind = toTypeKind(const.typeValue)
- if (kind.isPrimitive) classLiteral(kind)
- else kind
+ toTypeKind(const.typeValue) match {
+ case kind: PrimitiveBType => boxedClassOfPrimitive(kind)
+ case kind => kind
+ }
}
mnode.visitLdcInsn(toPush.toASMType)
@@ -558,7 +559,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
abort(s"Erasure should have added an unboxing operation to prevent this cast. Tree: $app")
}
else if (r.isPrimitive) {
- bc isInstance classLiteral(r)
+ bc isInstance boxedClassOfPrimitive(r.asPrimitiveBType)
}
else {
assert(r.isRef, r) // ensure that it's not a method
@@ -619,7 +620,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
}
case rt: ClassBType =>
- assert(exemplar(ctor.owner).c == rt, s"Symbol ${ctor.owner.fullName} is different from $rt")
+ assert(classBTypeFromSymbol(ctor.owner) == rt, s"Symbol ${ctor.owner.fullName} is different from $rt")
mnode.visitTypeInsn(asm.Opcodes.NEW, rt.internalName)
bc dup generatedType
genLoadArguments(args, paramTKs(app))
@@ -632,16 +633,16 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
case Apply(fun @ _, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) =>
val nativeKind = tpeTK(expr)
genLoad(expr, nativeKind)
- val MethodNameAndType(mname, mdesc) = asmBoxTo(nativeKind)
- bc.invokestatic(BoxesRunTime.internalName, mname, mdesc)
+ val MethodNameAndType(mname, methodType) = asmBoxTo(nativeKind)
+ bc.invokestatic(BoxesRunTime.internalName, mname, methodType.descriptor)
generatedType = boxResultType(fun.symbol) // was toTypeKind(fun.symbol.tpe.resultType)
case Apply(fun @ _, List(expr)) if currentRun.runDefinitions.isUnbox(fun.symbol) =>
genLoad(expr)
val boxType = unboxResultType(fun.symbol) // was toTypeKind(fun.symbol.owner.linkedClassOfClass.tpe)
generatedType = boxType
- val MethodNameAndType(mname, mdesc) = asmUnboxTo(boxType)
- bc.invokestatic(BoxesRunTime.internalName, mname, mdesc)
+ val MethodNameAndType(mname, methodType) = asmUnboxTo(boxType)
+ bc.invokestatic(BoxesRunTime.internalName, mname, methodType.descriptor)
case app @ Apply(fun, args) =>
val sym = fun.symbol
@@ -807,7 +808,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
}
def adapt(from: BType, to: BType) {
- if (!conforms(from, to)) {
+ if (!from.conformsTo(to)) {
to match {
case UNIT => bc drop from
case _ => bc.emitT2T(from, to)
@@ -948,7 +949,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
def genCallMethod(method: Symbol, style: InvokeStyle, hostClass0: Symbol = null, pos: Position = NoPosition) {
val siteSymbol = claszSymbol
- val hostSymbol = if (hostClass0 == null) method.owner else hostClass0;
+ val hostSymbol = if (hostClass0 == null) method.owner else hostClass0;
val methodOwner = method.owner
// info calls so that types are up to date; erasure may add lateINTERFACE to traits
hostSymbol.info ; methodOwner.info
@@ -966,8 +967,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
|| methodOwner == definitions.ObjectClass
)
val receiver = if (useMethodOwner) methodOwner else hostSymbol
- val bmOwner = asmClassType(receiver)
- val jowner = bmOwner.internalName
+ val jowner = internalName(receiver)
val jname = method.javaSimpleName.toString
val bmType = asmMethodType(method)
val mdescr = bmType.descriptor
@@ -1100,7 +1100,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
genCZJUMP(success, failure, op, ObjectReference)
}
else {
- val tk = maxType(tpeTK(l), tpeTK(r))
+ val tk = tpeTK(l).maxType(tpeTK(r))
genLoad(l, tk)
genLoad(r, tk)
genCJUMP(success, failure, op, tk)
@@ -1206,7 +1206,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
genCZJUMP(success, failure, icodes.NE, BOOL)
} else {
// l == r -> if (l eq null) r eq null else l.equals(r)
- val eqEqTempLocal = locals.makeLocal(AnyRefReference, nme.EQEQ_LOCAL_VAR.toString)
+ val eqEqTempLocal = locals.makeLocal(ObjectReference, nme.EQEQ_LOCAL_VAR.toString)
val lNull = new asm.Label
val lNonNull = new asm.Label