]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
(refs #7245) The first version of decompiler for SCL compilations 64/564/2
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Mon, 29 May 2017 09:23:24 +0000 (12:23 +0300)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Mon, 29 May 2017 09:55:40 +0000 (12:55 +0300)
It is intentional that the new fragment
org.simantics.scl.compiler.decompiler is not added to the module
listings in bundles/pom.xml, because currently this feature is intended
only for development purposes.

Change-Id: Iff184f783c1a924ff00823486b4c13aa957ca184

12 files changed:
bundles/org.simantics.scl.compiler.decompiler/.classpath [new file with mode: 0644]
bundles/org.simantics.scl.compiler.decompiler/.project [new file with mode: 0644]
bundles/org.simantics.scl.compiler.decompiler/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.scl.compiler.decompiler/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.scl.compiler.decompiler/build.properties [new file with mode: 0644]
bundles/org.simantics.scl.compiler.decompiler/src/org/simantics/scl/compiler/internal/decompiler/impl/DecompilerImpl.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/decompilation/DecompilerFactory.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/decompilation/IDecompiler.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ExpressionClassLoader.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/MutableClassLoader.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/SCLCompilerConfiguration.java

diff --git a/bundles/org.simantics.scl.compiler.decompiler/.classpath b/bundles/org.simantics.scl.compiler.decompiler/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?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>
diff --git a/bundles/org.simantics.scl.compiler.decompiler/.project b/bundles/org.simantics.scl.compiler.decompiler/.project
new file mode 100644 (file)
index 0000000..c8b32a7
--- /dev/null
@@ -0,0 +1,28 @@
+<?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>
diff --git a/bundles/org.simantics.scl.compiler.decompiler/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.scl.compiler.decompiler/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..0c68a61
--- /dev/null
@@ -0,0 +1,7 @@
+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
diff --git a/bundles/org.simantics.scl.compiler.decompiler/META-INF/MANIFEST.MF b/bundles/org.simantics.scl.compiler.decompiler/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..f4e9fa7
--- /dev/null
@@ -0,0 +1,13 @@
+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"
diff --git a/bundles/org.simantics.scl.compiler.decompiler/build.properties b/bundles/org.simantics.scl.compiler.decompiler/build.properties
new file mode 100644 (file)
index 0000000..34d2e4d
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/bundles/org.simantics.scl.compiler.decompiler/src/org/simantics/scl/compiler/internal/decompiler/impl/DecompilerImpl.java b/bundles/org.simantics.scl.compiler.decompiler/src/org/simantics/scl/compiler/internal/decompiler/impl/DecompilerImpl.java
new file mode 100644 (file)
index 0000000..8cc1033
--- /dev/null
@@ -0,0 +1,43 @@
+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) {
+        }
+    }
+    
+}
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/decompilation/DecompilerFactory.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/decompilation/DecompilerFactory.java
new file mode 100644 (file)
index 0000000..d2cbcd0
--- /dev/null
@@ -0,0 +1,26 @@
+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;
+    }
+}
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/decompilation/IDecompiler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/decompilation/IDecompiler.java
new file mode 100644 (file)
index 0000000..4640acf
--- /dev/null
@@ -0,0 +1,9 @@
+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);
+}
index 0c134ee5c1130b5e9e730dd9552e01401f367c43..45e3027207f86ab6be25dff2863a20d6c6bbd42a 100644 (file)
@@ -60,6 +60,7 @@ public class ExpressionClassLoader extends ClassLoader implements MutableClassLo
         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))
index adf36f8af062a615b069bf86993233dc2d484759..422d38dc6c340dd6d6c9a785bdeac458781a6e5b 100644 (file)
@@ -16,5 +16,6 @@ public interface MutableClassLoader {
     String getFreshPackageName();
     THashMap<Constant, Object> getConstantCache();
     ClassLoader getClassLoader();
+    byte[] getBytes(String className);
 
 }
index aeb21ffa63b333a5aae9cd1b018c75aad4549e29..4ed45005b9659aa8fc42f1c6790e1c8f851abf64 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.scl.compiler.runtime;
 
+import java.io.OutputStreamWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -13,12 +14,19 @@ import org.simantics.scl.compiler.environment.GlobalOnlyEnvironment;
 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;
     
@@ -66,6 +74,7 @@ public class RuntimeModule {
                         */
         }
         
+        @Override
         public byte[] getBytes(String name) {
             // Non-SCL classes are not handled here
             if(!name.startsWith(SCL_PACKAGE_PREFIX))
@@ -93,7 +102,7 @@ public class RuntimeModule {
                 return parentModule.classLoader.getBytes(name);
             }
         }
-        
+
         synchronized Class<?> getLocalClass(String name) throws ClassNotFoundException {
             // Is class already loaded
             Class<?> clazz = findLoadedClass(name);
@@ -107,7 +116,9 @@ public class RuntimeModule {
                 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);
         }
         
@@ -139,8 +150,8 @@ public class RuntimeModule {
             {
                 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);
                 }
 
@@ -187,6 +198,13 @@ public class RuntimeModule {
         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));
+        }
     }
 
     
index 763bc9d9cdfdb35562474fc43f3cd1d8c03082a1..57f7102cb7dbec38a03c0268a2d3333203ac3690 100644 (file)
@@ -10,6 +10,7 @@ public interface SCLCompilerConfiguration {
     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;
@@ -19,7 +20,6 @@ public interface SCLCompilerConfiguration {
     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;