mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Remove unused classes
This commit is contained in:
parent
9fb97fd53f
commit
6483f518cf
|
@ -238,6 +238,7 @@ public class TCollections extends TObject {
|
|||
return binarySearch(list, key, naturalOrder);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static TComparator<Object> naturalOrder = (o1, o2) -> o1 != null
|
||||
? ((TComparable<Object>) o1).compareTo(o2)
|
||||
: -((TComparable<Object>) o2).compareTo(o1);
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class CommutatedWriter extends Writer {
|
||||
private ThreadLocal<StringBuilder> buffer = new ThreadLocal<>();
|
||||
private Writer innerWriter;
|
||||
|
||||
public CommutatedWriter(Writer innerWriter) {
|
||||
this.innerWriter = innerWriter;
|
||||
}
|
||||
|
||||
private StringBuilder getBuffer() {
|
||||
if (buffer.get() == null) {
|
||||
buffer.set(new StringBuilder());
|
||||
}
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int c) throws IOException {
|
||||
getBuffer().append(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] cbuf) throws IOException {
|
||||
getBuffer().append(cbuf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
getBuffer().append(cbuf, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String str) throws IOException {
|
||||
getBuffer().append(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String str, int off, int len) throws IOException {
|
||||
getBuffer().append(str, off, len + off);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer append(CharSequence csq) throws IOException {
|
||||
getBuffer().append(csq);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer append(CharSequence csq, int start, int end) throws IOException {
|
||||
getBuffer().append(csq, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer append(char c) throws IOException {
|
||||
getBuffer().append(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
StringBuilder sb = getBuffer();
|
||||
innerWriter.write(sb.toString());
|
||||
buffer.set(null);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.common;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface FiniteExecutor extends Executor {
|
||||
void complete();
|
||||
|
||||
void executeFast(Runnable runnable);
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.common;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class SimpleFiniteExecutor implements FiniteExecutor {
|
||||
private Queue<Runnable> queue = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
queue.add(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeFast(Runnable runnable) {
|
||||
execute(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() {
|
||||
while (!queue.isEmpty()) {
|
||||
queue.remove().run();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.common;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class ThreadPoolFiniteExecutor implements FiniteExecutor {
|
||||
private List<Thread> threads = new ArrayList<>();
|
||||
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||
private AtomicInteger runningTasks = new AtomicInteger();
|
||||
private final Object monitor = new Object();
|
||||
private AtomicReference<RuntimeException> thrownException = new AtomicReference<>();
|
||||
private ThreadLocal<Queue<Runnable>> localQueueues = new ThreadLocal<>();
|
||||
|
||||
public ThreadPoolFiniteExecutor(int numThreads) {
|
||||
for (int i = 0; i < numThreads; ++i) {
|
||||
Thread thread = new Thread(this::takeTask);
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
runningTasks.incrementAndGet();
|
||||
try {
|
||||
queue.put(command);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeFast(Runnable runnable) {
|
||||
localQueueues.get().add(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() {
|
||||
synchronized (monitor) {
|
||||
while (true) {
|
||||
if (thrownException.get() != null) {
|
||||
throw thrownException.get();
|
||||
}
|
||||
if (runningTasks.get() == 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
monitor.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void takeTask() {
|
||||
Queue<Runnable> localQueue = new ArrayDeque<>();
|
||||
localQueueues.set(localQueue);
|
||||
try {
|
||||
while (true) {
|
||||
Runnable task = queue.take();
|
||||
try {
|
||||
task.run();
|
||||
while (!localQueue.isEmpty()) {
|
||||
localQueue.remove().run();
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
thrownException.set(e);
|
||||
} finally {
|
||||
if (runningTasks.decrementAndGet() == 0 || thrownException.get() != null) {
|
||||
synchronized (monitor) {
|
||||
monitor.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (Thread thread : threads) {
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,358 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript.backend;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.ast.ClassNode;
|
||||
import org.teavm.ast.cache.EmptyRegularMethodNodeCache;
|
||||
import org.teavm.ast.cache.MethodNodeCache;
|
||||
import org.teavm.ast.decompilation.Decompiler;
|
||||
import org.teavm.codegen.AliasProvider;
|
||||
import org.teavm.codegen.DefaultAliasProvider;
|
||||
import org.teavm.codegen.DefaultNamingStrategy;
|
||||
import org.teavm.codegen.MinifyingAliasProvider;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.codegen.SourceWriterBuilder;
|
||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||
import org.teavm.debugging.information.SourceLocation;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.Renderer;
|
||||
import org.teavm.javascript.RenderingException;
|
||||
import org.teavm.javascript.spi.GeneratedBy;
|
||||
import org.teavm.javascript.spi.Generator;
|
||||
import org.teavm.javascript.spi.InjectedBy;
|
||||
import org.teavm.javascript.spi.Injector;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.ListableClassHolderSource;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.RaiseInstruction;
|
||||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
import org.teavm.model.util.AsyncMethodFinder;
|
||||
import org.teavm.model.util.ProgramUtils;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.TeaVMEntryPoint;
|
||||
import org.teavm.vm.TeaVMTarget;
|
||||
import org.teavm.vm.TeaVMTargetController;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||
|
||||
public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||
private TeaVMTargetController controller;
|
||||
private boolean minifying = true;
|
||||
private final Map<MethodReference, Generator> methodGenerators = new HashMap<>();
|
||||
private final Map<MethodReference, Injector> methodInjectors = new HashMap<>();
|
||||
private final List<RendererListener> rendererListeners = new ArrayList<>();
|
||||
private DebugInformationEmitter debugEmitter;
|
||||
private MethodNodeCache astCache = new EmptyRegularMethodNodeCache();
|
||||
private final Set<MethodReference> asyncMethods = new HashSet<>();
|
||||
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public List<ClassHolderTransformer> getTransformers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DependencyListener> getDependencyListeners() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(TeaVMTargetController controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(RendererListener listener) {
|
||||
rendererListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(MethodReference methodRef, Generator generator) {
|
||||
methodGenerators.put(methodRef, generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(MethodReference methodRef, Injector injector) {
|
||||
methodInjectors.put(methodRef, injector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports whether this TeaVM instance uses obfuscation when generating the JavaScript code.
|
||||
*
|
||||
* @see #setMinifying(boolean)
|
||||
* @return whether TeaVM produces obfuscated code.
|
||||
*/
|
||||
public boolean isMinifying() {
|
||||
return minifying;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether this TeaVM instance uses obfuscation when generating the JavaScript code.
|
||||
*
|
||||
* @see #isMinifying()
|
||||
* @param minifying whether TeaVM should obfuscate code.
|
||||
*/
|
||||
public void setMinifying(boolean minifying) {
|
||||
this.minifying = minifying;
|
||||
}
|
||||
|
||||
public MethodNodeCache getAstCache() {
|
||||
return astCache;
|
||||
}
|
||||
|
||||
public void setAstCache(MethodNodeCache methodAstCache) {
|
||||
this.astCache = methodAstCache;
|
||||
}
|
||||
|
||||
public DebugInformationEmitter getDebugEmitter() {
|
||||
return debugEmitter;
|
||||
}
|
||||
|
||||
public void setDebugEmitter(DebugInformationEmitter debugEmitter) {
|
||||
this.debugEmitter = debugEmitter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresRegisterAllocation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TeaVMHostExtension> getHostExtensions() {
|
||||
return Collections.singletonList(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeDependencies(DependencyChecker dependencyChecker) {
|
||||
dependencyChecker.linkMethod(new MethodReference(Class.class.getName(), "getClass",
|
||||
ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(String.class, "<init>", char[].class, void.class),
|
||||
null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(String.class, "getChars", int.class, int.class, char[].class,
|
||||
int.class, void.class), null).use();
|
||||
|
||||
MethodDependency internDep = dependencyChecker.linkMethod(new MethodReference(String.class, "intern",
|
||||
String.class), null);
|
||||
internDep.getVariable(0).propagate(dependencyChecker.getType("java.lang.String"));
|
||||
internDep.use();
|
||||
|
||||
dependencyChecker.linkMethod(new MethodReference(String.class, "length", int.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Object.class, "clone", Object.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Thread.class, "currentThread", Thread.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Thread.class, "getMainThread", Thread.class), null).use();
|
||||
dependencyChecker.linkMethod(
|
||||
new MethodReference(Thread.class, "setCurrentThread", Thread.class, void.class), null).use();
|
||||
MethodDependency exceptionCons = dependencyChecker.linkMethod(new MethodReference(
|
||||
NoClassDefFoundError.class, "<init>", String.class, void.class), null);
|
||||
|
||||
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoClassDefFoundError.class.getName()));
|
||||
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
|
||||
exceptionCons = dependencyChecker.linkMethod(new MethodReference(NoSuchFieldError.class, "<init>",
|
||||
String.class, void.class), null);
|
||||
exceptionCons.use();
|
||||
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoSuchFieldError.class.getName()));
|
||||
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
|
||||
exceptionCons = dependencyChecker.linkMethod(new MethodReference(NoSuchMethodError.class, "<init>",
|
||||
String.class, void.class), null);
|
||||
exceptionCons.use();
|
||||
exceptionCons.getVariable(0).propagate(dependencyChecker.getType(NoSuchMethodError.class.getName()));
|
||||
exceptionCons.getVariable(1).propagate(dependencyChecker.getType("java.lang.String"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(ListableClassHolderSource classes, OutputStream output, BuildTarget target) {
|
||||
try (Writer writer = new OutputStreamWriter(output, "UTF-8")) {
|
||||
emit(classes, writer, target);
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void emit(ListableClassHolderSource classes, Writer writer, BuildTarget target) {
|
||||
List<ClassNode> clsNodes = modelToAst(classes);
|
||||
if (controller.wasCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
||||
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, controller.getUnprocessedClassSource());
|
||||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||
builder.setMinified(minifying);
|
||||
SourceWriter sourceWriter = builder.build(writer);
|
||||
|
||||
Renderer renderer = new Renderer(sourceWriter, classes, controller.getClassLoader(), controller.getServices(),
|
||||
asyncMethods, asyncFamilyMethods, controller.getDiagnostics());
|
||||
renderer.setProperties(controller.getProperties());
|
||||
renderer.setMinifying(minifying);
|
||||
if (debugEmitter != null) {
|
||||
for (String className : classes.getClassNames()) {
|
||||
ClassHolder cls = classes.get(className);
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getProgram() != null) {
|
||||
emitCFG(debugEmitter, method.getProgram());
|
||||
}
|
||||
}
|
||||
if (controller.wasCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
renderer.setDebugEmitter(debugEmitter);
|
||||
}
|
||||
renderer.getDebugEmitter().setLocationProvider(sourceWriter);
|
||||
for (Map.Entry<MethodReference, Injector> entry : methodInjectors.entrySet()) {
|
||||
renderer.addInjector(entry.getKey(), entry.getValue());
|
||||
}
|
||||
try {
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.begin(renderer, target);
|
||||
}
|
||||
sourceWriter.append("\"use strict\";").newLine();
|
||||
renderer.renderRuntime();
|
||||
renderer.render(clsNodes);
|
||||
renderer.renderStringPool();
|
||||
for (Map.Entry<String, TeaVMEntryPoint> entry : controller.getEntryPoints().entrySet()) {
|
||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws();
|
||||
MethodReference ref = entry.getValue().getReference();
|
||||
sourceWriter.append(naming.getFullNameFor(ref));
|
||||
sourceWriter.append(";").newLine();
|
||||
}
|
||||
for (Map.Entry<String, String> entry : controller.getExportedClasses().entrySet()) {
|
||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws()
|
||||
.appendClass(entry.getValue()).append(";").newLine();
|
||||
}
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.complete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO Error occured", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ClassNode> modelToAst(ListableClassHolderSource classes) {
|
||||
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph(),
|
||||
controller.getDiagnostics());
|
||||
asyncFinder.find(classes);
|
||||
asyncMethods.addAll(asyncFinder.getAsyncMethods());
|
||||
asyncFamilyMethods.addAll(asyncFinder.getAsyncFamilyMethods());
|
||||
|
||||
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), asyncMethods, asyncFamilyMethods);
|
||||
decompiler.setRegularMethodCache(controller.isIncremental() ? astCache : null);
|
||||
|
||||
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
|
||||
decompiler.addGenerator(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (MethodReference injectedMethod : methodInjectors.keySet()) {
|
||||
decompiler.addMethodToSkip(injectedMethod);
|
||||
}
|
||||
List<String> classOrder = decompiler.getClassOrdering(classes.getClassNames());
|
||||
List<ClassNode> classNodes = new ArrayList<>();
|
||||
for (String className : classOrder) {
|
||||
ClassHolder cls = classes.get(className);
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
preprocessNativeMethod(method);
|
||||
if (controller.wasCancelled()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
classNodes.add(decompiler.decompile(cls));
|
||||
}
|
||||
return classNodes;
|
||||
}
|
||||
|
||||
private void preprocessNativeMethod(MethodHolder method) {
|
||||
if (!method.getModifiers().contains(ElementModifier.NATIVE)
|
||||
|| methodGenerators.get(method.getReference()) != null
|
||||
|| methodInjectors.get(method.getReference()) != null
|
||||
|| method.getAnnotations().get(GeneratedBy.class.getName()) != null
|
||||
|| method.getAnnotations().get(InjectedBy.class.getName()) != null) {
|
||||
return;
|
||||
}
|
||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||
|
||||
Program program = new Program();
|
||||
method.setProgram(program);
|
||||
BasicBlock block = program.createBasicBlock();
|
||||
Variable exceptionVar = program.createVariable();
|
||||
ConstructInstruction newExceptionInsn = new ConstructInstruction();
|
||||
newExceptionInsn.setType(NoSuchMethodError.class.getName());
|
||||
newExceptionInsn.setReceiver(exceptionVar);
|
||||
block.getInstructions().add(newExceptionInsn);
|
||||
|
||||
Variable constVar = program.createVariable();
|
||||
StringConstantInstruction constInsn = new StringConstantInstruction();
|
||||
constInsn.setConstant("Native method implementation not found: " + method.getReference());
|
||||
constInsn.setReceiver(constVar);
|
||||
block.getInstructions().add(constInsn);
|
||||
|
||||
InvokeInstruction initExceptionInsn = new InvokeInstruction();
|
||||
initExceptionInsn.setInstance(exceptionVar);
|
||||
initExceptionInsn.setMethod(new MethodReference(NoSuchMethodError.class, "<init>", String.class, void.class));
|
||||
initExceptionInsn.setType(InvocationType.SPECIAL);
|
||||
initExceptionInsn.getArguments().add(constVar);
|
||||
block.getInstructions().add(initExceptionInsn);
|
||||
|
||||
RaiseInstruction raiseInsn = new RaiseInstruction();
|
||||
raiseInsn.setException(exceptionVar);
|
||||
block.getInstructions().add(raiseInsn);
|
||||
|
||||
controller.getDiagnostics().error(new CallLocation(method.getReference()),
|
||||
"Native method {{m0}} has no implementation", method.getReference());
|
||||
}
|
||||
|
||||
private void emitCFG(DebugInformationEmitter emitter, Program program) {
|
||||
Map<TextLocation, TextLocation[]> cfg = ProgramUtils.getLocationCFG(program);
|
||||
for (Map.Entry<TextLocation, TextLocation[]> entry : cfg.entrySet()) {
|
||||
SourceLocation location = map(entry.getKey());
|
||||
SourceLocation[] successors = new SourceLocation[entry.getValue().length];
|
||||
for (int i = 0; i < entry.getValue().length; ++i) {
|
||||
successors[i] = map(entry.getValue()[i]);
|
||||
}
|
||||
emitter.addSuccessors(location, successors);
|
||||
}
|
||||
}
|
||||
|
||||
private static SourceLocation map(TextLocation location) {
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
return new SourceLocation(location.getFileName(), location.getLine());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user