summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala75
1 files changed, 45 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala
index e7dd5abc57..7bc4ea2392 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala
@@ -27,7 +27,7 @@ import scala.tools.nsc.backend.jvm.BackendReporting.UnknownScalaInlineInfoVersio
* In principle we could encode the InlineInfo into a Java annotation (instead of a classfile attribute).
* However, an attribute allows us to save many bits. In particular, note that the strings in an
* InlineInfo are serialized as references to constants in the constant pool, and those strings
- * (traitImplClassSelfType, method names, method signatures) would exist in there anyway. So the
+ * (method names, method signatures) would exist in there anyway. So the
* ScalaInlineAttribute remains relatively compact.
*/
case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineInfoAttribute.attributeName) {
@@ -47,13 +47,16 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI
result.putByte(InlineInfoAttribute.VERSION)
- var hasSelfIsFinal = 0
- if (inlineInfo.isEffectivelyFinal) hasSelfIsFinal |= 1
- if (inlineInfo.traitImplClassSelfType.isDefined) hasSelfIsFinal |= 2
- result.putByte(hasSelfIsFinal)
+ var flags = 0
+ if (inlineInfo.isEffectivelyFinal) flags |= 1
+ // flags |= 2 // no longer written
+ if (inlineInfo.sam.isDefined) flags |= 4
+ result.putByte(flags)
- for (selfInternalName <- inlineInfo.traitImplClassSelfType) {
- result.putShort(cw.newUTF8(selfInternalName))
+ for (samNameDesc <- inlineInfo.sam) {
+ val (name, desc) = samNameDesc.span(_ != '(')
+ result.putShort(cw.newUTF8(name))
+ result.putShort(cw.newUTF8(desc))
}
// The method count fits in a short (the methods_count in a classfile is also a short)
@@ -68,10 +71,10 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI
result.putShort(cw.newUTF8(desc))
var inlineInfo = 0
- if (info.effectivelyFinal) inlineInfo |= 1
- if (info.traitMethodWithStaticImplementation) inlineInfo |= 2
- if (info.annotatedInline) inlineInfo |= 4
- if (info.annotatedNoInline) inlineInfo |= 8
+ if (info.effectivelyFinal) inlineInfo |= 1
+ // inlineInfo |= 2 // no longer written
+ if (info.annotatedInline) inlineInfo |= 4
+ if (info.annotatedNoInline) inlineInfo |= 8
result.putByte(inlineInfo)
}
@@ -79,7 +82,7 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI
}
/**
- * De-serialize the attribute into an InlineInfo. The attribute starts at cr.b(off), but we don't
+ * Deserialize the attribute into an InlineInfo. The attribute starts at cr.b(off), but we don't
* need to access that array directly, we can use the `read` methods provided by the ClassReader.
*
* `buf` is a pre-allocated character array that is guaranteed to be long enough to hold any
@@ -94,15 +97,17 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI
val version = nextByte()
if (version == 1) {
- val hasSelfIsFinal = nextByte()
- val isFinal = (hasSelfIsFinal & 1) != 0
- val hasSelf = (hasSelfIsFinal & 2) != 0
-
- val self = if (hasSelf) {
- val selfName = nextUTF8()
- Some(selfName)
- } else {
- None
+ val flags = nextByte()
+ val isFinal = (flags & 1) != 0
+ val hasSelf = (flags & 2) != 0
+ val hasSam = (flags & 4) != 0
+
+ if (hasSelf) nextUTF8() // no longer used
+
+ val sam = if (!hasSam) None else {
+ val name = nextUTF8()
+ val desc = nextUTF8()
+ Some(name + desc)
}
val numEntries = nextShort()
@@ -111,14 +116,15 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI
val desc = nextUTF8()
val inlineInfo = nextByte()
- val isFinal = (inlineInfo & 1) != 0
- val traitMethodWithStaticImplementation = (inlineInfo & 2) != 0
- val isInline = (inlineInfo & 4) != 0
- val isNoInline = (inlineInfo & 8) != 0
- (name + desc, MethodInlineInfo(isFinal, traitMethodWithStaticImplementation, isInline, isNoInline))
+ val isFinal = (inlineInfo & 1) != 0
+ // = (inlineInfo & 2) != 0 // no longer used
+ val isInline = (inlineInfo & 4) != 0
+ val isNoInline = (inlineInfo & 8) != 0
+ (name + desc, MethodInlineInfo(isFinal, isInline, isNoInline))
}).toMap
- InlineInfoAttribute(InlineInfo(self, isFinal, infos, None))
+ val info = InlineInfo(isFinal, sam, infos, None)
+ InlineInfoAttribute(info)
} else {
val msg = UnknownScalaInlineInfoVersion(cr.getClassName, version)
InlineInfoAttribute(BTypes.EmptyInlineInfo.copy(warning = Some(msg)))
@@ -128,9 +134,18 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI
object InlineInfoAttribute {
/**
+ * Notes:
+ * - `traitImplClassSelfType` is no longer emitted, `hasTraitImplClassSelfType` is always emitted
+ * as 0. Similarly, `traitMethodWithStaticImplementation` is always emitted 0.
+ * - When reading an existing attribute where `hasTraitImplClassSelfType` is 1, the
+ * `traitImplClassSelfType` is ignored. Also the value of `traitMethodWithStaticImplementation`
+ * is ignored.
+ *
* [u1] version
- * [u1] isEffectivelyFinal (<< 0), hasTraitImplClassSelfType (<< 1)
+ * [u1] isEffectivelyFinal (<< 0), hasTraitImplClassSelfType (<< 1), hasSam (<< 2), hasLateInterfaces (<< 3)
* [u2]? traitImplClassSelfType (reference)
+ * [u2]? samName (reference)
+ * [u2]? samDescriptor (reference)
* [u2] numMethodEntries
* [u2] name (reference)
* [u2] descriptor (reference)
@@ -142,7 +157,7 @@ object InlineInfoAttribute {
}
/**
- * In order to instruct the ASM framework to de-serialize the ScalaInlineInfo attribute, we need
+ * In order to instruct the ASM framework to deserialize the ScalaInlineInfo attribute, we need
* to pass a prototype instance when running the class reader.
*/
-object InlineInfoAttributePrototype extends InlineInfoAttribute(InlineInfo(null, false, null, null))
+object InlineInfoAttributePrototype extends InlineInfoAttribute(InlineInfo(false, null, null, null))