Skip to content

Commit 906d022

Browse files
committed
Detach the constant pool from the full byte array of the class
This is in preparation for using lazy types for Java method types. Those lazy types need to capture the constant pool, so we don't want to retain the entire classfile contents.
1 parent 7b017f7 commit 906d022

File tree

2 files changed

+25
-19
lines changed

2 files changed

+25
-19
lines changed

src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package classfile
1111
import java.lang.Float.intBitsToFloat
1212
import java.lang.Double.longBitsToDouble
1313

14+
import scala.reflect.io.NoAbstractFile
1415
import scala.tools.nsc.io.AbstractFile
1516

1617
/**
@@ -19,11 +20,13 @@ import scala.tools.nsc.io.AbstractFile
1920
* @author Philippe Altherr
2021
* @version 1.0, 23/03/2004
2122
*/
22-
class AbstractFileReader(val file: AbstractFile) {
23-
24-
/** the buffer containing the file
25-
*/
26-
val buf: Array[Byte] = file.toByteArray
23+
class AbstractFileReader(val buf: Array[Byte], val file: AbstractFile) {
24+
def this(file: AbstractFile) {
25+
this(file.toByteArray, file)
26+
}
27+
def this(buf: Array[Byte]) {
28+
this(buf, NoAbstractFile)
29+
}
2730

2831
/** the current input pointer
2932
*/

src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import scala.collection.mutable.{ArrayBuffer, ListBuffer}
1616
import scala.annotation.switch
1717
import scala.reflect.internal.JavaAccFlags
1818
import scala.reflect.internal.pickling.{ByteCodecs, PickleBuffer}
19-
import scala.reflect.io.NoAbstractFile
19+
import scala.reflect.io.{NoAbstractFile, VirtualFile}
2020
import scala.reflect.internal.util.Collections._
2121
import scala.tools.nsc.util.ClassPath
2222
import scala.tools.nsc.io.AbstractFile
@@ -171,6 +171,8 @@ abstract class ClassfileParser {
171171
protected val values = new Array[AnyRef](len)
172172
protected val internalized = new Array[NameOrString](len)
173173

174+
private val initBp = in.bp
175+
174176
{ var i = 1
175177
while (i < starts.length) {
176178
starts(i) = in.bp
@@ -187,6 +189,7 @@ abstract class ClassfileParser {
187189
}
188190
}
189191
}
192+
private val in1: AbstractFileReader = new AbstractFileReader(java.util.Arrays.copyOfRange(in.buf, initBp, in.bp))
190193

191194
def recordAtIndex[T <: AnyRef](value: T, idx: Int): T = {
192195
values(idx) = value
@@ -195,12 +198,12 @@ abstract class ClassfileParser {
195198

196199
def firstExpecting(index: Int, expected: Int): Int = {
197200
val start = starts(index)
198-
val first = in.buf(start).toInt
201+
val first = in1.buf(start - initBp).toInt
199202
if (first == expected) start + 1
200203
else this errorBadTag start
201204
}
202205

203-
class NameOrString(val value: String) {
206+
class NameOrString(val value: String) { // TODO encode this as Name | String
204207
private var _name: Name = null
205208
def name: Name = {
206209
if (_name eq null) _name = TermName(value)
@@ -214,8 +217,8 @@ abstract class ClassfileParser {
214217
case name: NameOrString => name
215218
case _ =>
216219
val start = firstExpecting(index, CONSTANT_UTF8)
217-
val len = in.getChar(start).toInt
218-
recordAtIndex(new NameOrString(fromMUTF8(in.buf, start, len + 2)), index)
220+
val len = in1.getChar(start - initBp).toInt
221+
recordAtIndex(new NameOrString(fromMUTF8(in1.buf, start - initBp, len + 2)), index)
219222
}
220223
)
221224

@@ -251,7 +254,7 @@ abstract class ClassfileParser {
251254
*/
252255
def getClassName(index: Int): NameOrString = {
253256
val start = firstExpecting(index, CONSTANT_CLASS)
254-
getExternalName((in getChar start).toInt)
257+
getExternalName((in1.getChar(start - initBp)).toInt)
255258
}
256259

257260
/** Return a name and a type at the given index. If the type is a method
@@ -266,10 +269,10 @@ abstract class ClassfileParser {
266269
case p: ((Name @unchecked, Type @unchecked)) => p
267270
case _ =>
268271
val start = firstExpecting(index, CONSTANT_NAMEANDTYPE)
269-
val name = getName(in.getChar(start).toInt)
272+
val name = getName(in1.getChar(start - initBp).toInt)
270273
// create a dummy symbol for method types
271274
val dummy = ownerTpe.typeSymbol.newMethod(name.name.toTermName, ownerTpe.typeSymbol.pos)
272-
val tpe = getType(dummy, in.getChar(start + 2).toInt)
275+
val tpe = getType(dummy, in1.getChar(start + 2 - initBp).toInt)
273276
// fix the return type, which is blindly set to the class currently parsed
274277
val restpe = tpe match {
275278
case MethodType(formals, _) if name == nme.CONSTRUCTOR => MethodType(formals, ownerTpe)
@@ -303,12 +306,12 @@ abstract class ClassfileParser {
303306

304307
private def createConstant(index: Int): Constant = {
305308
val start = starts(index)
306-
Constant((in.buf(start).toInt: @switch) match {
307-
case CONSTANT_STRING => getName(in.getChar(start + 1).toInt).value
308-
case CONSTANT_INTEGER => in.getInt(start + 1)
309-
case CONSTANT_FLOAT => in.getFloat(start + 1)
310-
case CONSTANT_LONG => in.getLong(start + 1)
311-
case CONSTANT_DOUBLE => in.getDouble(start + 1)
309+
Constant((in1.buf(start - initBp).toInt: @switch) match {
310+
case CONSTANT_STRING => getName(in1.getChar(start + 1 - initBp).toInt).value
311+
case CONSTANT_INTEGER => in1.getInt(start + 1 - initBp)
312+
case CONSTANT_FLOAT => in1.getFloat(start + 1 - initBp)
313+
case CONSTANT_LONG => in1.getLong(start + 1 - initBp)
314+
case CONSTANT_DOUBLE => in1.getDouble(start + 1 - initBp)
312315
case CONSTANT_CLASS => getClassOrArrayType(index).typeSymbol.tpe_* // !!! Is this necessary or desirable?
313316
case _ => errorBadTag(start)
314317
})

0 commit comments

Comments
 (0)