Error reporting when the generated code size exceeds JVM limits (65,535 bytes per method). Closed #4573. review by extempore.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@24985 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
dragos 2011-05-17 09:51:59 +00:00
parent cbb21fd949
commit 8e38b90267
3 changed files with 30 additions and 3 deletions

Binary file not shown.

View File

@ -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) {

View File

@ -21,6 +21,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;