Skip to content

Commit 3d66b0d

Browse files
committed
Factoring out methods used in backend. No direct usages of global anymore.
1 parent 0e8c6da commit 3d66b0d

21 files changed

+1991
-1206
lines changed

src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala

Lines changed: 243 additions & 235 deletions
Large diffs are not rendered by default.

src/compiler/scala/tools/nsc/backend/icode/ICodes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ abstract class ICodes extends AnyRef
2323
with TypeStacks
2424
with TypeKinds
2525
with ExceptionHandlers
26-
with Primitives
2726
with Linearizers
2827
with Printers
2928
with Repository
3029
{
3130
val global: Global
3231
import global.{ log, definitions, settings, perRunCaches, devWarning }
32+
import Primitives._
3333

3434
/** The ICode representation of classes */
3535
val classes = perRunCaches.newMap[global.Symbol, IClass]()

src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package backend
99
package icode
1010

1111
import scala.reflect.internal.util.{Position,NoPosition}
12-
12+
import Primitives._
1313
/*
1414
A pattern match
1515
@@ -66,6 +66,7 @@ import scala.reflect.internal.util.{Position,NoPosition}
6666
*/
6767
trait Opcodes { self: ICodes =>
6868
import global.{Symbol, NoSymbol, Name, Constant}
69+
import Opcodes._
6970

7071
// categories of ICode instructions
7172
final val localsCat = 1
@@ -307,30 +308,30 @@ trait Opcodes { self: ICodes =>
307308
override def produced = 1
308309

309310
override def consumedTypes = primitive match {
310-
case Negation(kind) => kind :: Nil
311-
case Test(_, kind, true) => kind :: Nil
312-
case Test(_, kind, false) => kind :: kind :: Nil
313-
case Comparison(_, kind) => kind :: kind :: Nil
314-
case Arithmetic(NOT, kind) => kind :: Nil
315-
case Arithmetic(_, kind) => kind :: kind :: Nil
316-
case Logical(_, kind) => kind :: kind :: Nil
317-
case Shift(_, kind) => kind :: INT :: Nil
318-
case Conversion(from, _) => from :: Nil
319-
case ArrayLength(kind) => ARRAY(kind) :: Nil
320-
case StringConcat(kind) => ConcatClass :: kind :: Nil
311+
case Negation(kind: Opcodes.this.TypeKind) => kind :: Nil
312+
case Test(_, kind: Opcodes.this.TypeKind, true) => kind :: Nil
313+
case Test(_, kind: Opcodes.this.TypeKind, false) => kind :: kind :: Nil
314+
case Comparison(_, kind: Opcodes.this.TypeKind) => kind :: kind :: Nil
315+
case Arithmetic(NOT, kind: Opcodes.this.TypeKind) => kind :: Nil
316+
case Arithmetic(_, kind: Opcodes.this.TypeKind) => kind :: kind :: Nil
317+
case Logical(_, kind: Opcodes.this.TypeKind) => kind :: kind :: Nil
318+
case Shift(_, kind: Opcodes.this.TypeKind) => kind :: INT :: Nil
319+
case Conversion(from: Opcodes.this.TypeKind, _) => from :: Nil
320+
case ArrayLength(kind: Opcodes.this.TypeKind) => ARRAY(kind) :: Nil
321+
case StringConcat(kind: Opcodes.this.TypeKind) => ConcatClass :: kind :: Nil
321322
case StartConcat => Nil
322323
case EndConcat => ConcatClass :: Nil
323324
}
324325

325326
override def producedTypes = primitive match {
326-
case Negation(kind) => kind :: Nil
327+
case Negation(kind: Opcodes.this.TypeKind) => kind :: Nil
327328
case Test(_, _, true) => BOOL :: Nil
328329
case Test(_, _, false) => BOOL :: Nil
329330
case Comparison(_, _) => INT :: Nil
330-
case Arithmetic(_, kind) => kind :: Nil
331-
case Logical(_, kind) => kind :: Nil
332-
case Shift(_, kind) => kind :: Nil
333-
case Conversion(_, to) => to :: Nil
331+
case Arithmetic(_, kind: Opcodes.this.TypeKind) => kind :: Nil
332+
case Logical(_, kind: Opcodes.this.TypeKind) => kind :: Nil
333+
case Shift(_, kind: Opcodes.this.TypeKind) => kind :: Nil
334+
case Conversion(_, to: Opcodes.this.TypeKind) => to :: Nil
334335
case ArrayLength(_) => INT :: Nil
335336
case StringConcat(_) => ConcatClass :: Nil
336337
case StartConcat => ConcatClass :: Nil
@@ -716,52 +717,56 @@ trait Opcodes { self: ICodes =>
716717
override def producedTypes = REFERENCE(clasz) :: Nil
717718
override def category = stackCat
718719
}
720+
}
721+
}
719722

720-
/** This class represents a method invocation style. */
721-
sealed abstract class InvokeStyle {
722-
/** Is this a dynamic method call? */
723-
def isDynamic: Boolean = false
723+
object Opcodes{
724724

725-
/** Is this a static method call? */
726-
def isStatic: Boolean = false
725+
/** This class represents a method invocation style. */
726+
sealed abstract class InvokeStyle {
727+
/** Is this a dynamic method call? */
728+
def isDynamic: Boolean = false
727729

728-
def isSuper: Boolean = false
730+
/** Is this a static method call? */
731+
def isStatic: Boolean = false
729732

730-
/** Is this an instance method call? */
731-
def hasInstance: Boolean = true
733+
def isSuper: Boolean = false
732734

733-
/** Returns a string representation of this style. */
734-
override def toString(): String
735-
}
735+
/** Is this an instance method call? */
736+
def hasInstance: Boolean = true
736737

737-
/** Virtual calls.
738-
* On JVM, translated to either `invokeinterface` or `invokevirtual`.
739-
*/
740-
case object Dynamic extends InvokeStyle {
741-
override def isDynamic = true
742-
override def toString(): String = "dynamic"
743-
}
738+
/** Returns a string representation of this style. */
739+
override def toString(): String
740+
}
744741

745-
/**
746-
* Special invoke:
747-
* Static(true) is used for calls to private members, ie `invokespecial` on JVM.
748-
* Static(false) is used for calls to class-level instance-less static methods, ie `invokestatic` on JVM.
749-
*/
750-
case class Static(onInstance: Boolean) extends InvokeStyle {
751-
override def isStatic = true
752-
override def hasInstance = onInstance
753-
override def toString(): String = {
754-
if(onInstance) "static-instance"
755-
else "static-class"
756-
}
757-
}
742+
/** Virtual calls.
743+
* On JVM, translated to either `invokeinterface` or `invokevirtual`.
744+
*/
745+
case object Dynamic extends InvokeStyle {
746+
override def isDynamic = true
747+
override def toString(): String = "dynamic"
748+
}
758749

759-
/** Call through super[mix].
760-
* On JVM, translated to `invokespecial`.
761-
*/
762-
case class SuperCall(mix: Name) extends InvokeStyle {
763-
override def isSuper = true
764-
override def toString(): String = { "super(" + mix + ")" }
750+
/**
751+
* Special invoke:
752+
* Static(true) is used for calls to private members, ie `invokespecial` on JVM.
753+
* Static(false) is used for calls to class-level instance-less static methods, ie `invokestatic` on JVM.
754+
*/
755+
case class Static(onInstance: Boolean) extends InvokeStyle {
756+
override def isStatic = true
757+
override def hasInstance = onInstance
758+
override def toString(): String = {
759+
if(onInstance) "static-instance"
760+
else "static-class"
765761
}
766762
}
763+
764+
/** Call through super[mix].
765+
* On JVM, translated to `invokespecial`.
766+
*/
767+
case class SuperCall(mix: String) extends InvokeStyle {
768+
override def isSuper = true
769+
override def toString(): String = { "super(" + mix + ")" }
770+
}
771+
767772
}

src/compiler/scala/tools/nsc/backend/icode/Primitives.scala

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ package icode
1010

1111
import java.io.PrintWriter
1212

13-
trait Primitives { self: ICodes =>
14-
13+
object Primitives {
1514
/** This class represents a primitive operation. */
1615
class Primitive {
1716
}
@@ -20,48 +19,48 @@ trait Primitives { self: ICodes =>
2019
// type : (type) => type
2120
// range: type <- { BOOL, Ix, Ux, Rx }
2221
// jvm : {i, l, f, d}neg
23-
case class Negation(kind: TypeKind) extends Primitive
22+
case class Negation(kind: TypeKinds#TypeKind) extends Primitive
2423

2524
// type : zero ? (type) => BOOL : (type,type) => BOOL
2625
// range: type <- { BOOL, Ix, Ux, Rx, REF }
2726
// jvm : if{eq, ne, lt, ge, le, gt}, if{null, nonnull}
2827
// if_icmp{eq, ne, lt, ge, le, gt}, if_acmp{eq,ne}
29-
case class Test(op: TestOp, kind: TypeKind, zero: Boolean) extends Primitive
28+
case class Test(op: TestOp, kind: TypeKinds#TypeKind, zero: Boolean) extends Primitive
3029

3130
// type : (type,type) => I4
3231
// range: type <- { Ix, Ux, Rx }
3332
// jvm : lcmp, {f, d}cmp{l, g}
34-
case class Comparison(op: ComparisonOp, kind: TypeKind) extends Primitive
33+
case class Comparison(op: ComparisonOp, kind: TypeKinds#TypeKind) extends Primitive
3534

3635
// type : (type,type) => type
3736
// range: type <- { Ix, Ux, Rx }
3837
// jvm : {i, l, f, d}{add, sub, mul, div, rem}
39-
case class Arithmetic(op: ArithmeticOp, kind: TypeKind) extends Primitive
38+
case class Arithmetic(op: ArithmeticOp, kind: TypeKinds#TypeKind) extends Primitive
4039

4140
// type : (type,type) => type
4241
// range: type <- { BOOL, Ix, Ux }
4342
// jvm : {i, l}{and, or, xor}
44-
case class Logical(op: LogicalOp, kind: TypeKind) extends Primitive
43+
case class Logical(op: LogicalOp, kind: TypeKinds#TypeKind) extends Primitive
4544

4645
// type : (type,I4) => type
4746
// range: type <- { Ix, Ux }
4847
// jvm : {i, l}{shl, ushl, shr}
49-
case class Shift(op: ShiftOp, kind: TypeKind) extends Primitive
48+
case class Shift(op: ShiftOp, kind: TypeKinds#TypeKind) extends Primitive
5049

5150
// type : (src) => dst
5251
// range: src,dst <- { Ix, Ux, Rx }
5352
// jvm : i2{l, f, d}, l2{i, f, d}, f2{i, l, d}, d2{i, l, f}, i2{b, c, s}
54-
case class Conversion(src: TypeKind, dst: TypeKind) extends Primitive
53+
case class Conversion(src: TypeKinds#TypeKind, dst: TypeKinds#TypeKind) extends Primitive
5554

5655
// type : (Array[REF]) => I4
5756
// range: type <- { BOOL, Ix, Ux, Rx, REF }
5857
// jvm : arraylength
59-
case class ArrayLength(kind: TypeKind) extends Primitive
58+
case class ArrayLength(kind: TypeKinds#TypeKind) extends Primitive
6059

6160
// type : (buf,el) => buf
6261
// range: lf,rg <- { BOOL, Ix, Ux, Rx, REF, STR }
6362
// jvm : It should call the appropiate 'append' method on StringBuffer
64-
case class StringConcat(el: TypeKind) extends Primitive
63+
case class StringConcat(el: TypeKinds#TypeKind) extends Primitive
6564

6665
/** Signals the beginning of a series of concatenations.
6766
* On the JVM platform, it should create a new StringBuffer

src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package scala.tools.nsc
77
package backend
88
package icode
99

10+
import scala.tools.nsc.backend.jvm.BackendInterface
11+
1012
/* A type case
1113
1214
case UNIT =>

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

Lines changed: 51 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,15 @@
55

66
package scala.tools.nsc.backend.jvm
77

8+
import scala.reflect.internal.AnnotationInfos
89
import scala.tools.nsc.Global
910

1011
/**
1112
* This trait contains code shared between GenBCode and GenASM that depends on types defined in
1213
* the compiler cake (Global).
1314
*/
14-
final class BCodeAsmCommon[G <: Global](val global: G) {
15-
import global._
16-
import definitions._
17-
18-
val ExcludedForwarderFlags = {
19-
import scala.tools.nsc.symtab.Flags._
20-
// Should include DEFERRED but this breaks findMember.
21-
SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO
22-
}
15+
final class BCodeAsmCommon[I <: BackendInterface](interface: I) {
16+
import interface._
2317

2418
/**
2519
* True if `classSym` is an anonymous class or a local class. I.e., false if `classSym` is a
@@ -103,63 +97,58 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
10397
None
10498
}
10599
}
100+
}
106101

107-
/**
108-
* This is basically a re-implementation of sym.isStaticOwner, but using the originalOwner chain.
109-
*
110-
* The problem is that we are interested in a source-level property. Various phases changed the
111-
* symbol's properties in the meantime, mostly lambdalift modified (destructively) the owner.
112-
* Therefore, `sym.isStatic` is not what we want. For example, in
113-
* object T { def f { object U } }
114-
* the owner of U is T, so UModuleClass.isStatic is true. Phase travel does not help here.
115-
*/
116-
def isOriginallyStaticOwner(sym: Symbol): Boolean = {
117-
sym.isPackageClass || sym.isModuleClass && isOriginallyStaticOwner(sym.originalOwner)
118-
}
119-
120-
/**
121-
* The member classes of a class symbol. Note that the result of this method depends on the
122-
* current phase, for example, after lambdalift, all local classes become member of the enclosing
123-
* class.
124-
*/
125-
def memberClassesOf(classSymbol: Symbol): List[Symbol] = classSymbol.info.decls.collect({
126-
case sym if sym.isClass =>
127-
sym
128-
case sym if sym.isModule =>
129-
val r = exitingPickler(sym.moduleClass)
130-
assert(r != NoSymbol, sym.fullLocationString)
131-
r
132-
})(collection.breakOut)
133-
134-
lazy val AnnotationRetentionPolicyModule = AnnotationRetentionPolicyAttr.companionModule
135-
lazy val AnnotationRetentionPolicySourceValue = AnnotationRetentionPolicyModule.tpe.member(TermName("SOURCE"))
136-
lazy val AnnotationRetentionPolicyClassValue = AnnotationRetentionPolicyModule.tpe.member(TermName("CLASS"))
137-
lazy val AnnotationRetentionPolicyRuntimeValue = AnnotationRetentionPolicyModule.tpe.member(TermName("RUNTIME"))
102+
object BCodeAsmCommon{
103+
def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
104+
val ca = new Array[Char](bytes.length)
105+
var idx = 0
106+
while(idx < bytes.length) {
107+
val b: Byte = bytes(idx)
108+
assert((b & ~0x7f) == 0)
109+
ca(idx) = b.asInstanceOf[Char]
110+
idx += 1
111+
}
138112

139-
/** Whether an annotation should be emitted as a Java annotation
140-
* .initialize: if 'annot' is read from pickle, atp might be un-initialized
141-
*/
142-
def shouldEmitAnnotation(annot: AnnotationInfo) = {
143-
annot.symbol.initialize.isJavaDefined &&
144-
annot.matches(ClassfileAnnotationClass) &&
145-
retentionPolicyOf(annot) != AnnotationRetentionPolicySourceValue &&
146-
annot.args.isEmpty
113+
ca
147114
}
148115

149-
def isRuntimeVisible(annot: AnnotationInfo): Boolean = {
150-
annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr) match {
151-
case Some(retentionAnnot) =>
152-
retentionAnnot.assocs.contains(nme.value -> LiteralAnnotArg(Constant(AnnotationRetentionPolicyRuntimeValue)))
153-
case _ =>
154-
// SI-8926: if the annotation class symbol doesn't have a @RetentionPolicy annotation, the
155-
// annotation is emitted with visibility `RUNTIME`
156-
true
116+
final def arrEncode(sb: AnnotationInfos#ScalaSigBytes): Array[String] = {
117+
var strs: List[String] = Nil
118+
val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
119+
// chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
120+
var prevOffset = 0
121+
var offset = 0
122+
var encLength = 0
123+
while(offset < bSeven.length) {
124+
val deltaEncLength = (if(bSeven(offset) == 0) 2 else 1)
125+
val newEncLength = encLength.toLong + deltaEncLength
126+
if(newEncLength >= 65535) {
127+
val ba = bSeven.slice(prevOffset, offset)
128+
strs ::= new java.lang.String(ubytesToCharArray(ba))
129+
encLength = 0
130+
prevOffset = offset
131+
} else {
132+
encLength += deltaEncLength
133+
offset += 1
134+
}
157135
}
136+
if(prevOffset < offset) {
137+
assert(offset == bSeven.length)
138+
val ba = bSeven.slice(prevOffset, offset)
139+
strs ::= new java.lang.String(ubytesToCharArray(ba))
140+
}
141+
assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
142+
strs.reverse.toArray
158143
}
159144

160-
private def retentionPolicyOf(annot: AnnotationInfo): Symbol =
161-
annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr).map(_.assocs).map(assoc =>
162-
assoc.collectFirst {
163-
case (`nme`.value, LiteralAnnotArg(Constant(value: Symbol))) => value
164-
}).flatten.getOrElse(AnnotationRetentionPolicyClassValue)
165-
}
145+
146+
def strEncode(sb: AnnotationInfos#ScalaSigBytes): String = {
147+
val ca = ubytesToCharArray(sb.sevenBitsMayBeZero)
148+
new java.lang.String(ca)
149+
// debug val bvA = new asm.ByteVector; bvA.putUTF8(s)
150+
// debug val enc: Array[Byte] = scala.reflect.internal.pickling.ByteCodecs.encode(bytes)
151+
// debug assert(enc(idx) == bvA.getByte(idx + 2))
152+
// debug assert(bvA.getLength == enc.size + 2)
153+
}
154+
}

0 commit comments

Comments
 (0)