From a22be1267ace5faa9c16787910ed32227367177d Mon Sep 17 00:00:00 2001 From: Iulian Dragos Date: Tue, 17 May 2011 09:51:59 +0000 Subject: Error reporting when the generated code size ex... Error reporting when the generated code size exceeds JVM limits (65,535 bytes per method). Closed #4573. review by extempore. --- lib/fjbg.jar.desired.sha1 | 2 +- src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 16 +++++++++++++++- src/fjbg/ch/epfl/lamp/fjbg/JCode.java | 17 +++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1 index fd3def241f..6120c0f6e9 100644 --- a/lib/fjbg.jar.desired.sha1 +++ b/lib/fjbg.jar.desired.sha1 @@ -1 +1 @@ -bd8e22a955eeb82671c5fdb8a7a14bc7f25e9eb1 ?fjbg.jar +9638fa48db649c01ea7a0237008c932653e7c19d ?fjbg.jar diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 6cbd37720b..f28fdd6c9b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -82,7 +82,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with else new ClassBytecodeWriter with JavapBytecodeWriter { } } val codeGenerator = new BytecodeGenerator(bytecodeWriter) - classes.values foreach (codeGenerator genClass _) + classes.values foreach { c => + try codeGenerator.genClass(c) + catch { + case e: JCode.CodeSizeTooBigException => + log("Skipped class %s because it has methods that are too long.".format(c.toString)) + } + } bytecodeWriter.close() classes.clear() } @@ -785,6 +791,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with addExceptionsAttribute(jmethod, excs) addAnnotations(jmethod, others) addParamAnnotations(jmethod, m.params.map(_.sym.annotations)) + + // check for code size + try jmethod.freeze() + catch { + case e: JCode.CodeSizeTooBigException => + clasz.cunit.error(m.symbol.pos, "Code size exceeds JVM limits: %d".format(e.codeSize)) + throw e + } } private def addRemoteException(jmethod: JMethod, meth: Symbol) { diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JCode.java index 332cc7c518..d80f9f5f94 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JCode.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JCode.java @@ -22,6 +22,8 @@ import ch.epfl.lamp.util.ByteArray; public class JCode { protected boolean frozen = false; + public static int MAX_CODE_SIZE = 65535; + protected final FJBGContext context; protected final JMethod owner; @@ -57,8 +59,8 @@ public class JCode { this.owner = owner; owner.setCode(this); int size = stream.readInt(); - if (size >= 65536) // section 4.10 - throw new Error("code size must be less than 65536: " + size); + if (size > MAX_CODE_SIZE) // section 4.10 + throw new Error("code size must be less than " + MAX_CODE_SIZE + ": " + size); this.codeArray = new ByteArray(stream, size); } @@ -97,8 +99,19 @@ public class JCode { // Freezing ////////////////////////////////////////////////////////////////////// + public static class CodeSizeTooBigException extends OffsetTooBigException { + public int codeSize; + + public CodeSizeTooBigException(int size) { + codeSize = size; + } + } + public void freeze() throws OffsetTooBigException { assert !frozen; + + if (getSize() > MAX_CODE_SIZE) throw new CodeSizeTooBigException(getSize()); + patchAllOffset(); codeArray.freeze(); frozen = true; -- cgit v1.2.3