diff options
-rw-r--r-- | lib/fjbg.jar.desired.sha1 | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 17 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java | 25 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JClass.java | 11 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JCode.java | 1 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java | 14 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java | 2 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java | 6 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java | 2 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JMember.java | 1 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java | 8 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JType.java | 2 | ||||
-rw-r--r-- | test/files/neg/bug1133msg.check | 4 | ||||
-rw-r--r-- | test/files/neg/bug1133msg.scala | 33 |
14 files changed, 104 insertions, 24 deletions
diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1 index 862868d030..1b63db3e08 100644 --- a/lib/fjbg.jar.desired.sha1 +++ b/lib/fjbg.jar.desired.sha1 @@ -1 +1 @@ -3997a32211461f0f7de1e4eb37e964cd134ea003 ?fjbg.jar +cbe214571e5ab811a8c3b5c9a5995aec066d2e36 ?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 5a02de0907..7afa36c0ba 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -15,6 +15,8 @@ import scala.tools.nsc.symtab._ import scala.tools.nsc.symtab.classfile.ClassfileConstants._ import ch.epfl.lamp.fjbg._ +import FJBGContext.FJBGWrapper +import JCode.OffsetTooBigException import JAccessFlags._ import JObjectType.{ JAVA_LANG_STRING, JAVA_LANG_OBJECT } import java.io.{ DataOutputStream } @@ -138,6 +140,15 @@ abstract class GenJVM extends SubComponent { val emitLines = debugLevel >= 2 val emitVars = debugLevel >= 3 + def analyzeException(culprit: String, t: Throwable): Unit = t match { + case x: FJBGWrapper => + analyzeException(x.culprit, x.getCause()) + case _: OffsetTooBigException => + clasz.cunit.error(clasz.symbol.pos, "cannot emit bytecode for " + culprit + ": " + t.getMessage) + case x => + throw x + } + /** Write a class to disk, adding the Scala signature (pickled type * information) and inner classes. * @@ -148,8 +159,10 @@ abstract class GenJVM extends SubComponent { addInnerClasses(jclass) val outfile = getFile(sym, jclass, ".class") val outstream = new DataOutputStream(outfile.bufferedOutput) - jclass.writeTo(outstream) - outstream.close() + try jclass.writeTo(outstream) + catch { case x => analyzeException(jclass.getName(), x) } + finally outstream.close() + informProgress("wrote " + outfile) } diff --git a/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java b/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java index 569a9ac272..cfc4ed00e5 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java @@ -28,6 +28,31 @@ public class FJBGContext { MINOR_VERSION = minor; } + public static class FJBGWrapper extends RuntimeException { + public String culprit; + public FJBGWrapper(Throwable cause) { + super(cause); + this.culprit = "<unknown>"; + } + public FJBGWrapper(String culprit, Throwable cause) { + super(cause); + this.culprit = culprit; + } + } + + static FJBGWrapper mkFatal(String culprit, Throwable t) { + return new FJBGWrapper(culprit, t); + } + static FJBGWrapper mkFatal(Throwable t) { + return new FJBGWrapper(t); + } + static RuntimeException mkFatal(Object obj) { + return new FJBGWrapper(new java.lang.Error(obj.toString())); + } + static RuntimeException mkFatal(String message) { + return new FJBGWrapper(new java.lang.Error(message)); + } + // Factory methods ////////////////////////////////////////////////////////////////////// diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JClass.java b/src/fjbg/ch/epfl/lamp/fjbg/JClass.java index 0fc604424a..3839af4156 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JClass.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JClass.java @@ -310,8 +310,15 @@ public class JClass extends JMember { stream.writeShort(methods.size()); Iterator methodsIt = methods.iterator(); - while (methodsIt.hasNext()) - ((JMethod)methodsIt.next()).writeTo(stream); + while (methodsIt.hasNext()) { + JMethod m = (JMethod)methodsIt.next(); + try { + m.writeTo(stream); + } + catch (Throwable t) { + throw FJBGContext.mkFatal(name + "." + m.getName(), t); + } + } // Attributes JAttribute.writeTo(attributes, stream); diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JCode.java index f7d275c8a7..2506a06c03 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JCode.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JCode.java @@ -889,7 +889,6 @@ public class JCode { public OffsetTooBigException() { super(); } public OffsetTooBigException(String message) { super(message); } } - protected void checkOffset16(int offset) throws OffsetTooBigException { if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) throw new OffsetTooBigException("offset too big to fit" diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java b/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java index 34b38c828d..5ca4f14215 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java @@ -125,7 +125,7 @@ public class JCodeIterator { else return 4; } else - throw new Error("Unknown size for instruction " + opcode); + throw FJBGContext.mkFatal("Unknown size for instruction " + opcode); } /** @@ -144,7 +144,7 @@ public class JCodeIterator { int npairsPos = pc + 1 + pad4(pc + 1) + 4; return 1 + codeArray.getS4(npairsPos); } else - throw new Error("Unknown successors for instruction " + opcode); + throw FJBGContext.mkFatal("Unknown successors for instruction " + opcode); } /** @@ -185,7 +185,7 @@ public class JCodeIterator { return pc + codeArray.getS4(defaultPos + 2*4 + 4 + 8 * (index - 1)); } default: - throw new Error(); + throw FJBGContext.mkFatal(""); } } @@ -226,7 +226,7 @@ public class JCodeIterator { else return 0; // (IINC) } default : - throw new Error(opcode.toString()); + throw FJBGContext.mkFatal(opcode.toString()); } } else return JType.getTotalSize(opcode.getProducedDataTypes()); @@ -281,7 +281,7 @@ public class JCodeIterator { case JOpcode.cMULTIANEWARRAY : return codeArray.getU1(pc + 3); default: - throw new Error(opcode.toString()); + throw FJBGContext.mkFatal(opcode.toString()); } } } @@ -315,7 +315,7 @@ public class JCodeIterator { return 0; // (IINC) } default: - throw new Error("JOpcode implementation error"); + throw FJBGContext.mkFatal("JOpcode implementation error"); } } } @@ -358,7 +358,7 @@ public class JCodeIterator { // return JOpcode.OPCODES[op].getConsumedDataTypes().length; // else return 0; // (IINC) // case 197 : return codeArray.getU1(pc + 3); // MULTIANEWARRAY -// default : throw new Error("JOpcode implementation error"); +// default : throw FJBGContext.mkFatal("JOpcode implementation error"); // } // } else return opcode.getConsumedDataTypes().length; // } diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java b/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java index 0df4498d8e..765411d5fb 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java @@ -104,7 +104,7 @@ public class JConstantPool { case 12 : return "Methodref"; case 13 : return "InterfaceMethodref"; case 14 : return "NameAndType"; - default : throw new Error("invalid constant pool tag : " + tag); + default : throw FJBGContext.mkFatal("invalid constant pool tag : " + tag); } } diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java index 69b522b622..cbb0ce37db 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java @@ -463,7 +463,7 @@ public class JExtendedCode extends JCode { JOpcode[] conv = typeConversions[fromType.getTag() - 4][toType.getTag() - 4]; if (conv == forbidden) { - throw new Error("inconvertible types : " + fromType.toString() + throw FJBGContext.mkFatal("inconvertible types : " + fromType.toString() + " -> " + toType.toString()); } else if (conv != nothingToDo) { for (int i = 0; i < conv.length; i++) { @@ -518,7 +518,7 @@ public class JExtendedCode extends JCode { try { emitGOTO(label); } catch (OffsetTooBigException e) { - throw new Error(e); + throw FJBGContext.mkFatal(e); } } } @@ -532,7 +532,7 @@ public class JExtendedCode extends JCode { try { emitGOTO(targetPC); } catch (OffsetTooBigException e) { - throw new Error(e); + throw FJBGContext.mkFatal(e); } } } diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java b/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java index fec7310bdf..b97657c196 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java @@ -110,7 +110,7 @@ abstract public class JFieldOrMethod extends JMember { freeze(); } catch (JCode.OffsetTooBigException e) { - throw new Error(e); + throw FJBGContext.mkFatal(owner.name + "." + name, e); } } stream.writeShort(accessFlags); diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JMember.java b/src/fjbg/ch/epfl/lamp/fjbg/JMember.java index 8d082fb90d..3b4ce38094 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JMember.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JMember.java @@ -13,7 +13,6 @@ import java.util.Iterator; */ abstract public class JMember { - protected boolean frozen = false; protected final FJBGContext context; diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java b/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java index f7ee688784..ca144a6b8d 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java @@ -1201,7 +1201,7 @@ public class JOpcode { case cDUP2_X2: return 6; default: - throw new Error(this.toString()); + throw FJBGContext.mkFatal(this.toString()); } } } @@ -1220,7 +1220,7 @@ public class JOpcode { case cDUP2_X2: return 4; default: - throw new Error(this.toString()); + throw FJBGContext.mkFatal(this.toString()); } } } @@ -1240,7 +1240,7 @@ public class JOpcode { case cDUP_X1: return 3; default: - throw new Error(this.toString()); + throw FJBGContext.mkFatal(this.toString()); } } } @@ -1256,7 +1256,7 @@ public class JOpcode { case cDUP2: case cDUP2_X1: case cPOP2: case cSWAP: return 2; default: - throw new Error(this.toString()); + throw FJBGContext.mkFatal(this.toString()); } } } diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JType.java b/src/fjbg/ch/epfl/lamp/fjbg/JType.java index b926a59f5a..a62925d1b0 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JType.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JType.java @@ -100,7 +100,7 @@ abstract public class JType { } catch (IllegalArgumentException e) { throw new IllegalArgumentException("invalid signature " + signature); } catch (IOException e) { - throw new Error(e); + throw FJBGContext.mkFatal(e); } } diff --git a/test/files/neg/bug1133msg.check b/test/files/neg/bug1133msg.check new file mode 100644 index 0000000000..5b499ef12f --- /dev/null +++ b/test/files/neg/bug1133msg.check @@ -0,0 +1,4 @@ +bug1133msg.scala:1: error: cannot emit bytecode for Match$.badMethod: offset too big to fit in 16 bits: 53273 +object Match { + ^ +one error found diff --git a/test/files/neg/bug1133msg.scala b/test/files/neg/bug1133msg.scala new file mode 100644 index 0000000000..b4a29aff4d --- /dev/null +++ b/test/files/neg/bug1133msg.scala @@ -0,0 +1,33 @@ +object Match { + def someMethod = 5 + + def badMethod(s: String) = s match { + case Extractor1(Extractor2(Extractor3("dog", "dog", "dog"), x2, x3), b, c, Extractor3("b", "b", f), e) => println(e) + case Extractor3(Extractor2(Extractor1("a", "aa", "aaa", "aa", "a"), Extractor2("a", "aa", "aaa"), e), y, z) => println(e) + case Extractor2(Extractor3("a", "a", x), Extractor3("b", "b", y), Extractor3("c", "c", z)) => println(z) + case _ => println("fail") + } + + def someOtherMethod = 10 + + object Extractor1 { + def unapply(x: Any) = x match { + case x: String => Some(x, x+x, x+x+x, x+x, x) + case _ => None + } + } + + object Extractor2 { + def unapply(x: Any) = x match { + case x: String => Some(x, x+x, x+x+x) + case _ => None + } + } + + object Extractor3 { + def unapply(x: Any) = x match { + case x: String => Some(x, x, x) + case _ => None + } + } +} |