summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/fjbg.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala17
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java25
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JClass.java11
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JCode.java1
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java14
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java2
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java6
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java2
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JMember.java1
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java8
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JType.java2
-rw-r--r--test/files/neg/bug1133msg.check4
-rw-r--r--test/files/neg/bug1133msg.scala33
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
+ }
+ }
+}