mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
C backend: make more tests pass
This commit is contained in:
parent
fa07100024
commit
18eb3ee058
|
@ -41,6 +41,7 @@ import org.teavm.classlib.java.lang.reflect.TModifier;
|
|||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.DelegateTo;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
import org.teavm.jso.core.JSArray;
|
||||
import org.teavm.platform.Platform;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
|
@ -82,14 +83,26 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
return platformClass;
|
||||
}
|
||||
|
||||
@DelegateTo("isInstanceLowLevel")
|
||||
public boolean isInstance(TObject obj) {
|
||||
return Platform.isInstance(Platform.getPlatformObject(obj), platformClass);
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private boolean isInstanceLowLevel(RuntimeObject obj) {
|
||||
return obj != null && isAssignableFromLowLevel(RuntimeClass.getClass(obj));
|
||||
}
|
||||
|
||||
@DelegateTo("isAssignableFromLowLevel")
|
||||
public boolean isAssignableFrom(TClass<?> obj) {
|
||||
return Platform.isAssignable(obj.getPlatformClass(), platformClass);
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private boolean isAssignableFromLowLevel(RuntimeClass other) {
|
||||
return Address.ofObject(this).<RuntimeClass>toStructure().isSupertypeOf.apply(other);
|
||||
}
|
||||
|
||||
@DelegateTo("getNameLowLevel")
|
||||
public TString getName() {
|
||||
if (name == null) {
|
||||
|
@ -98,6 +111,7 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private RuntimeObject getNameLowLevel() {
|
||||
RuntimeClass runtimeClass = Address.ofObject(this).toStructure();
|
||||
return runtimeClass.name;
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.teavm.ast.RegularMethodNode;
|
|||
import org.teavm.common.Graph;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.util.AsyncProgramSplitter;
|
||||
|
@ -40,6 +41,8 @@ public class Optimizer {
|
|||
public void optimize(RegularMethodNode method, Program program, boolean friendlyToDebugger) {
|
||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||
stats.analyze(program);
|
||||
applyParametersToWriteStats(stats, method.getReference());
|
||||
|
||||
boolean[] preservedVars = new boolean[stats.writes.length];
|
||||
BreakEliminator breakEliminator = new BreakEliminator();
|
||||
breakEliminator.eliminate(method.getBody());
|
||||
|
@ -72,6 +75,7 @@ public class Optimizer {
|
|||
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||
stats.analyze(splitter.getProgram(i));
|
||||
applyParametersToWriteStats(stats, method.getReference());
|
||||
|
||||
AsyncMethodPart part = method.getBody().get(i);
|
||||
BreakEliminator breakEliminator = new BreakEliminator();
|
||||
|
@ -101,6 +105,12 @@ public class Optimizer {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyParametersToWriteStats(ReadWriteStatsBuilder stats, MethodReference method) {
|
||||
for (int i = 0; i <= method.parameterCount(); ++i) {
|
||||
stats.writes[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
private void findEscapingLiveVars(LivenessAnalyzer liveness, Graph cfg, AsyncProgramSplitter splitter,
|
||||
int partIndex, boolean[] output) {
|
||||
Program originalProgram = splitter.getOriginalProgram();
|
||||
|
|
|
@ -68,6 +68,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
Statement resultStmt;
|
||||
private final boolean[] preservedVars;
|
||||
private final int[] writeFrequencies;
|
||||
private final int[] initialWriteFrequences;
|
||||
private final int[] readFrequencies;
|
||||
private final Object[] constants;
|
||||
private List<Statement> resultSequence;
|
||||
|
@ -80,6 +81,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
boolean friendlyToDebugger) {
|
||||
this.preservedVars = preservedVars;
|
||||
this.writeFrequencies = writeFrequencies;
|
||||
this.initialWriteFrequences = writeFrequencies.clone();
|
||||
this.readFrequencies = readFrequencies;
|
||||
this.constants = constants;
|
||||
this.friendlyToDebugger = friendlyToDebugger;
|
||||
|
@ -276,7 +278,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
return;
|
||||
}
|
||||
|
||||
if (constants[index] != null) {
|
||||
if (!preservedVars[index] && initialWriteFrequences[index] == 1 && constants[index] != null) {
|
||||
ConstantExpr constantExpr = new ConstantExpr();
|
||||
constantExpr.setValue(constants[index]);
|
||||
constantExpr.setLocation(expr.getLocation());
|
||||
|
@ -555,7 +557,8 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
|||
left = resultExpr;
|
||||
} else {
|
||||
int varIndex = ((VariableExpr) statement.getLeftValue()).getIndex();
|
||||
if (writeFrequencies[varIndex] == 1 && constants[varIndex] != null) {
|
||||
if (!preservedVars[varIndex] && initialWriteFrequences[varIndex] == 1
|
||||
&& constants[varIndex] != null) {
|
||||
resultStmt = new SequentialStatement();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -422,4 +422,9 @@ public class CTarget implements TeaVMTarget {
|
|||
public String[] getPlatformTags() {
|
||||
return new String[] { PlatformMarkers.C, PlatformMarkers.LOW_LEVEL };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,12 @@ public class StringPoolGenerator {
|
|||
for (int j = 0; j < string.length(); ++j) {
|
||||
char c = string.charAt(j);
|
||||
switch (c) {
|
||||
case '\\':
|
||||
writer.print("\\\\");
|
||||
break;
|
||||
case '"':
|
||||
writer.print("\\\"");
|
||||
break;
|
||||
case '\r':
|
||||
writer.print("\\r");
|
||||
break;
|
||||
|
@ -81,7 +87,9 @@ public class StringPoolGenerator {
|
|||
writer.print("\\t");
|
||||
break;
|
||||
default:
|
||||
if (c < 32 || c > 127) {
|
||||
if (c < 32) {
|
||||
writer.print("\\x" + Character.forDigit(c >> 4, 16) + Character.forDigit(c & 0xF, 16));
|
||||
} else if (c > 127) {
|
||||
writer.print("\\u"
|
||||
+ Character.forDigit(c >> 12, 16)
|
||||
+ Character.forDigit((c >> 8) & 15, 16)
|
||||
|
|
|
@ -30,6 +30,7 @@ public class PlatformIntrinsic implements Intrinsic {
|
|||
switch (method.getName()) {
|
||||
case "getPlatformObject":
|
||||
case "asJavaClass":
|
||||
case "createQueue":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -42,6 +43,9 @@ public class PlatformIntrinsic implements Intrinsic {
|
|||
case "asJavaClass":
|
||||
context.emit(invocation.getArguments().get(0));
|
||||
break;
|
||||
case "createQueue":
|
||||
context.writer().print("NULL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -458,4 +458,9 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
public String[] getPlatformTags() {
|
||||
return new String[] { PlatformMarkers.JAVASCRIPT };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -749,4 +749,9 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
public String[] getPlatformTags() {
|
||||
return new String[] { PlatformMarkers.WEBASSEMBLY, PlatformMarkers.LOW_LEVEL };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -87,6 +87,7 @@ public class DependencyAnalyzer implements DependencyInfo {
|
|||
Map<MethodReference, DependencyPlugin> dependencyPlugins = new HashMap<>();
|
||||
private boolean completing;
|
||||
private Map<String, SuperClassFilter> superClassFilters = new HashMap<>();
|
||||
boolean asyncSupported;
|
||||
|
||||
public DependencyAnalyzer(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
||||
Diagnostics diagnostics) {
|
||||
|
@ -116,6 +117,10 @@ public class DependencyAnalyzer implements DependencyInfo {
|
|||
agent = new DependencyAgent(this);
|
||||
}
|
||||
|
||||
public void setAsyncSupported(boolean asyncSupported) {
|
||||
this.asyncSupported = asyncSupported;
|
||||
}
|
||||
|
||||
public DependencyAgent getAgent() {
|
||||
return agent;
|
||||
}
|
||||
|
|
|
@ -148,20 +148,25 @@ class DependencyGraphBuilder {
|
|||
if (method.hasModifier(ElementModifier.SYNCHRONIZED)) {
|
||||
List<DependencyNode> syncNodes = new ArrayList<>();
|
||||
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
MethodDependency methodDep;
|
||||
if (dependencyAnalyzer.asyncSupported) {
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorEnter", Object.class, void.class), null);
|
||||
syncNodes.add(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
syncNodes.add(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorEnterSync", Object.class, void.class), null);
|
||||
syncNodes.add(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorExit", Object.class, void.class), null);
|
||||
syncNodes.add(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
if (dependencyAnalyzer.asyncSupported) {
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorExit", Object.class, void.class), null);
|
||||
syncNodes.add(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorExitSync", Object.class, void.class), null);
|
||||
|
@ -696,25 +701,29 @@ class DependencyGraphBuilder {
|
|||
|
||||
@Override
|
||||
public void monitorEnter(VariableReader objectRef) {
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
if (dependencyAnalyzer.asyncSupported) {
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorEnter", Object.class, void.class), null);
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorEnterSync", Object.class, void.class), null);
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void monitorExit(VariableReader objectRef) {
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorExit", Object.class, void.class), null);
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
if (dependencyAnalyzer.asyncSupported) {
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorExit", Object.class, void.class), null);
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
methodDep = dependencyAnalyzer.linkMethod(
|
||||
MethodDependency methodDep = dependencyAnalyzer.linkMethod(
|
||||
new MethodReference(Object.class, "monitorExitSync", Object.class, void.class), null);
|
||||
nodes[objectRef.getIndex()].connect(methodDep.getVariable(1));
|
||||
methodDep.use();
|
||||
|
|
|
@ -47,6 +47,7 @@ public class RuntimeClass extends RuntimeObject {
|
|||
public RuntimeClass parent;
|
||||
public Address enumValues;
|
||||
public Address layout;
|
||||
public RuntimeObject simpleName;
|
||||
|
||||
@Unmanaged
|
||||
public static int computeCanary(int size, int tag) {
|
||||
|
|
|
@ -358,6 +358,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
return;
|
||||
}
|
||||
|
||||
dependencyAnalyzer.setAsyncSupported(target.isAsyncSupported());
|
||||
dependencyAnalyzer.setInterruptor(() -> progressListener.progressReached(0) == TeaVMProgressFeedback.CONTINUE);
|
||||
target.contributeDependencies(dependencyAnalyzer);
|
||||
dependencyAnalyzer.processDependencies();
|
||||
|
|
|
@ -46,4 +46,6 @@ public interface TeaVMTarget {
|
|||
void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException;
|
||||
|
||||
String[] getPlatformTags();
|
||||
|
||||
boolean isAsyncSupported();
|
||||
}
|
||||
|
|
|
@ -234,10 +234,16 @@ public final class Platform {
|
|||
return cls.itemType;
|
||||
}
|
||||
|
||||
@DelegateTo("getNameLowLevel")
|
||||
public static String getName(PlatformClass cls) {
|
||||
return cls.getMetadata().getName();
|
||||
}
|
||||
|
||||
@Unmanaged
|
||||
private static RuntimeObject getNameLowLevel(RuntimeClass cls) {
|
||||
return cls.name;
|
||||
}
|
||||
|
||||
@JSBody(script = "return $rt_global;")
|
||||
private static native JSObject getGlobal();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user