--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.simantics.scl.compiler.decompiler</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: SCL bytecode decompiler
+Bundle-SymbolicName: org.simantics.scl.compiler.decompiler
+Bundle-Version: 1.0.0.qualifier
+Fragment-Host: org.simantics.scl.compiler;bundle-version="0.6.1"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.jboss.windup.decompiler.procyon;bundle-version="4.0.0",
+ org.jboss.windup.decompiler.procyon.windup-procyon-compilertools;bundle-version="1.0.0",
+ org.jboss.windup.decompiler.procyon.windup-procyon-core;bundle-version="1.0.0",
+ org.jboss.windup.decompiler.procyon.windup-procyon-reflection;bundle-version="1.0.0",
+ org.jboss.windup.decompiler.api.forge-addon;bundle-version="4.0.0",
+ org.jboss.windup.utils.windup-utils.forge-addon;bundle-version="4.0.0"
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+package org.simantics.scl.compiler.internal.decompiler.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.simantics.scl.compiler.internal.decompilation.IDecompiler;
+import org.simantics.scl.compiler.runtime.MutableClassLoader;
+
+import com.strobel.assembler.metadata.Buffer;
+import com.strobel.assembler.metadata.ITypeLoader;
+import com.strobel.core.VerifyArgument;
+import com.strobel.decompiler.Decompiler;
+import com.strobel.decompiler.DecompilerSettings;
+import com.strobel.decompiler.PlainTextOutput;
+
+public class DecompilerImpl implements IDecompiler {
+ @Override
+ public void decompile(MutableClassLoader classLoader, String className, Writer output) {
+ VerifyArgument.isNonNegative(3.0, "asd");
+ DecompilerSettings settings = DecompilerSettings.javaDefaults();
+ settings.setTypeLoader(new ITypeLoader() {
+ @Override
+ public boolean tryLoadType(String internalName, Buffer buffer) {
+ byte[] bytes = classLoader.getBytes(internalName.replace('/', '.'));
+ if(bytes == null)
+ return false;
+
+ buffer.reset(bytes.length);
+ System.arraycopy(bytes, 0, buffer.array(), 0, bytes.length);
+ return true;
+ }
+ });
+ Decompiler.decompile(
+ className,
+ new PlainTextOutput(output),
+ settings);
+ try {
+ output.flush();
+ } catch (IOException e) {
+ }
+ }
+
+}
--- /dev/null
+package org.simantics.scl.compiler.internal.decompilation;
+
+public class DecompilerFactory {
+ private static boolean initialized;
+ private static IDecompiler DECOMPILER;
+ public static IDecompiler getDecompiler() {
+ if(!initialized) {
+ try {
+ Class<?> clazz = DecompilerFactory.class.getClassLoader().loadClass("org.simantics.scl.compiler.internal.decompiler.impl.DecompilerImpl");
+ if(clazz != null) {
+ DECOMPILER = (IDecompiler)clazz.newInstance();
+ }
+ } catch(ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch(NoClassDefFoundError e) {
+ e.printStackTrace();
+ }
+ initialized = true;
+ }
+ return DECOMPILER;
+ }
+}
--- /dev/null
+package org.simantics.scl.compiler.internal.decompilation;
+
+import java.io.Writer;
+
+import org.simantics.scl.compiler.runtime.MutableClassLoader;
+
+public interface IDecompiler {
+ void decompile(MutableClassLoader classLoader, String className, Writer output);
+}
return defineClass(name, bytes, 0, bytes.length);
}
+ @Override
public byte[] getBytes(String name) {
// Non-SCL classes are not handled here
if(!name.startsWith(SCL_PACKAGE_PREFIX))
String getFreshPackageName();
THashMap<Constant, Object> getConstantCache();
ClassLoader getClassLoader();
+ byte[] getBytes(String className);
}
package org.simantics.scl.compiler.runtime;
+import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
+import org.simantics.scl.compiler.internal.decompilation.DecompilerFactory;
+import org.simantics.scl.compiler.internal.decompilation.IDecompiler;
import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
import org.simantics.scl.compiler.top.ValueNotFound;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import gnu.trove.map.hash.THashMap;
public class RuntimeModule {
+ private static final Logger LOGGER = LoggerFactory.getLogger(RuntimeModule.class);
+
public static final boolean VALIDATE_CLASS_NAMES = true;
public static final boolean TRACE_CLASS_CREATION = false;
*/
}
+ @Override
public byte[] getBytes(String name) {
// Non-SCL classes are not handled here
if(!name.startsWith(SCL_PACKAGE_PREFIX))
return parentModule.classLoader.getBytes(name);
}
}
-
+
synchronized Class<?> getLocalClass(String name) throws ClassNotFoundException {
// Is class already loaded
Class<?> clazz = findLoadedClass(name);
bytes = localClasses.get(internalName);
if(bytes == null)
throw new ClassNotFoundException(name);
- }
+ }
+ if(SCLCompilerConfiguration.SHOW_DECOMPILED_BYTECODE)
+ showDecompiledBytecode(internalName);
return defineClass(name, bytes, 0, bytes.length);
}
{
RuntimeModule parentModule = parentModuleMap.get(requestedModuleName);
if(parentModule == null) {
- System.err.println("requestedModuleName = " + requestedModuleName);
- System.err.println("this.moduleName = " + this.moduleName);
+ LOGGER.error("requestedModuleName = " + requestedModuleName);
+ LOGGER.error("this.moduleName = " + this.moduleName);
throw new ClassNotFoundException(name);
}
public ClassLoader getClassLoader() {
return this;
}
+
+ private void showDecompiledBytecode(String className) {
+ IDecompiler decompiler = DecompilerFactory.getDecompiler();
+ if(decompiler == null)
+ return;
+ decompiler.decompile(this, className, new OutputStreamWriter(System.out));
+ }
}
public static final boolean SHOW_SSA_BEFORE_LAMBDA_LIFTING = false;
public static final boolean SHOW_FINAL_SSA = false;
public static final boolean SHOW_COMPILED_BYTECODE = false;
+ public static final boolean SHOW_DECOMPILED_BYTECODE = false;
public static final boolean SHOW_EXPRESSION_BEFORE_EVALUATION = false;
public static final boolean SHOW_INTERPRETED_EXPRESSION = false;
public static final boolean VALIDATE_AFTER_OPTIMIZATIONS = false;
public static final boolean TRACE_CONSTRAINT_SOLVER = false;
public static final boolean PRINT_OPTIMIZATION_TRANSFORMATIONS = false;
- public static final boolean EXCEPTIONS_TO_COMPILATION_ERRORS = false;
public static final boolean NULL_CHECK_THREAD_LOCAL_VARIABLES = false;