Skip to content

Commit 5cbb5a7

Browse files
committed
Merge pull request scala#3268 from adriaanm/support-3021
Report error on code size overflow, log method name.
2 parents 2aa9da5 + 3fa2c97 commit 5cbb5a7

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

src/asm/scala/tools/asm/MethodWriter.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1853,7 +1853,12 @@ final int getSize() {
18531853
int size = 8;
18541854
if (code.length > 0) {
18551855
if (code.length > 65536) {
1856-
throw new RuntimeException("Method code too large!");
1856+
String nameString = "";
1857+
int i = 0;
1858+
// find item that corresponds to the index of our name
1859+
while (i < cw.items.length && (cw.items[i] == null || cw.items[i].index != name)) i++;
1860+
if (cw.items[i] != null) nameString = cw.items[i].strVal1 +"'s ";
1861+
throw new RuntimeException("Method "+ nameString +"code too large!");
18571862
}
18581863
cw.newUTF8("Code");
18591864
size += 18 + code.length + 8 * handlerCount;

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,17 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
450450
}
451451

452452
// -----------------------------------------------------------------------------------------
453-
// utitilies useful when emitting plain, mirror, and beaninfo classes.
453+
// utilities useful when emitting plain, mirror, and beaninfo classes.
454454
// -----------------------------------------------------------------------------------------
455455

456456
def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) {
457457
try {
458458
val arr = jclass.toByteArray()
459459
bytecodeWriter.writeClass(label, jclassName, arr, sym)
460460
} catch {
461-
case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") =>
462-
// TODO check where ASM throws the equivalent of CodeSizeTooBigException
463-
log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).")
461+
case e: java.lang.RuntimeException if e != null && (e.getMessage contains "too large!") =>
462+
reporter.error(sym.pos,
463+
s"Could not write class $jclassName because it exceeds JVM code size limits. ${e.getMessage}")
464464
}
465465
}
466466

@@ -1402,7 +1402,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
14021402
addInnerClasses(clasz.symbol, jclass)
14031403
jclass.visitEnd()
14041404
writeIfNotTooBig("" + c.symbol.name, thisName, jclass, c.symbol)
1405-
14061405
}
14071406

14081407
/**

test/files/run/large_code.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
newSource1.scala:1: error: Could not write class BigEnoughToFail because it exceeds JVM code size limits. Method tooLong's code too large!
2+
class BigEnoughToFail {
3+
^

test/files/run/large_code.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import scala.tools.partest._
2+
import java.io.{Console => _, _}
3+
4+
// a cold run of partest takes about 15s for this test on my laptop
5+
object Test extends DirectTest {
6+
override def extraSettings: String = "-usejavacp -d " + testOutput.path
7+
8+
// test that we hit the code size limit and error out gracefully
9+
// 5958 is the magic number (2^16/11 -- each `a(1,2,3,4,5,6)` is 11 bytes of bytecode)
10+
override def code
11+
= s"""
12+
|class BigEnoughToFail {
13+
| def a(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int): Unit = {}
14+
| def tooLong: Unit = {
15+
| ${(1 to 5958) map (_ => "a(1,2,3,4,5,6)") mkString(";")}
16+
| }
17+
|}""".stripMargin.trim
18+
19+
override def show(): Unit = {
20+
Console.withErr(System.out) {
21+
compile()
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)