Improve error reporting for JIT VerifyErrors.
diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/CodeBlockImpl.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/CodeBlockImpl.java
index 0dc37e2..6c0e41d 100644
--- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/CodeBlockImpl.java
+++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/CodeBlockImpl.java
@@ -1000,6 +1000,9 @@
} catch (Exception e) {
frame.setPc(pc);
throw new VMException(frame, e);
+ } catch (VerifyError e) {
+ frame.setPc(pc);
+ throw new VMException(frame, e);
}
}
}
diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/CodeBlockJIT.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/CodeBlockJIT.java
index ca90522..4b15335 100644
--- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/CodeBlockJIT.java
+++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/jit/CodeBlockJIT.java
@@ -63,25 +63,9 @@
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (codeBlocks.containsKey(name)) {
final byte[] b = internalJit(codeBlocks.get(name), name);
+ byteCode.put(name, b);
if (isDumpBytecode()) {
- try {
- final String path = name.substring(0, name.lastIndexOf('.')).replace('.', File.separatorChar);
- final File p = new File(System.getProperty("java.io.tmpdir") + File.separatorChar + path);
- p.mkdirs();
- final File f = new File(p, name.substring(name.lastIndexOf('.') + 1) + ".class");
- f.createNewFile();
- final FileOutputStream fos = new FileOutputStream(f);
- try {
- fos.write(b);
- } finally {
- fos.close();
- }
- ATLLogger.info(String.format("Wrote JIT-ed code block %s to %s",
- codeBlocks.get(name), f.getAbsolutePath()));
- } catch (IOException e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
+ dumpByteCode(name, b);
}
return defineClass(name, b, 0, b.length);
}
@@ -101,6 +85,10 @@
* The execution environment to JIT for.
*/
protected final ExecEnv env;
+ /**
+ * {@link Map} of class names to generated bytecode.
+ */
+ protected final Map<String, byte[]> byteCode = Collections.synchronizedMap(new HashMap<String, byte[]>());
/**
* Creates a new {@link CodeBlockJIT}.
@@ -129,8 +117,16 @@
InvocationTargetException, NoSuchMethodException {
final String className = getNextClassName();
codeBlocks.put(className, cb);
- return (JITCodeBlock)classLoader.findClass(className)
- .getConstructor(CodeBlock.class).newInstance(cb);
+ try {
+ return (JITCodeBlock)classLoader.findClass(className)
+ .getConstructor(CodeBlock.class).newInstance(cb);
+ } catch (VerifyError e) {
+ final byte[] b = byteCode.get(className);
+ if (b != null) {
+ dumpByteCode(className, b);
+ }
+ throw e;
+ }
}
/**
@@ -385,6 +381,32 @@
cb.setJITCodeBlock(null);
}
codeBlocks.clear();
+ byteCode.clear();
+ }
+
+ /**
+ * Dumps generated bytecode to the temp directory.
+ * @param name the class name
+ * @param b the bytecode to dump
+ */
+ private void dumpByteCode(String name, byte[] b) {
+ try {
+ final String path = name.substring(0, name.lastIndexOf('.')).replace('.', File.separatorChar);
+ final File p = new File(System.getProperty("java.io.tmpdir") + File.separatorChar + path);
+ p.mkdirs();
+ final File f = new File(p, name.substring(name.lastIndexOf('.') + 1) + ".class");
+ f.createNewFile();
+ final FileOutputStream fos = new FileOutputStream(f);
+ try {
+ fos.write(b);
+ } finally {
+ fos.close();
+ }
+ ATLLogger.info(String.format("Wrote JIT-ed code block %s to %s",
+ codeBlocks.get(name), f.getAbsolutePath()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}