mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Fix support of async <clinit> when called by getstatic/putstatic
This commit is contained in:
parent
c023ac2053
commit
24efd1f49c
|
@ -20,6 +20,7 @@ import org.teavm.model.TextLocation;
|
|||
public class InitClassStatement extends Statement {
|
||||
private TextLocation location;
|
||||
private String className;
|
||||
private boolean async;
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
|
@ -37,6 +38,14 @@ public class InitClassStatement extends Statement {
|
|||
this.location = location;
|
||||
}
|
||||
|
||||
public boolean isAsync() {
|
||||
return async;
|
||||
}
|
||||
|
||||
public void setAsync(boolean async) {
|
||||
this.async = async;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(StatementVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
|
|
|
@ -328,11 +328,7 @@ class StatementGenerator implements InstructionVisitor {
|
|||
Map<Integer, List<Integer>> switchMap = new HashMap<>();
|
||||
for (int i = 0; i < insn.getEntries().size(); ++i) {
|
||||
SwitchTableEntry entry = insn.getEntries().get(i);
|
||||
List<Integer> conditions = switchMap.get(entry.getTarget().getIndex());
|
||||
if (conditions == null) {
|
||||
conditions = new ArrayList<>();
|
||||
switchMap.put(entry.getTarget().getIndex(), conditions);
|
||||
}
|
||||
List<Integer> conditions = switchMap.computeIfAbsent(entry.getTarget().getIndex(), k -> new ArrayList<>());
|
||||
conditions.add(entry.getCondition());
|
||||
}
|
||||
List<Integer> targets = new ArrayList<>(switchMap.keySet());
|
||||
|
@ -590,6 +586,8 @@ class StatementGenerator implements InstructionVisitor {
|
|||
public void visit(InitClassInstruction insn) {
|
||||
InitClassStatement stmt = Statement.initClass(insn.getClassName());
|
||||
stmt.setLocation(currentLocation);
|
||||
stmt.setAsync(async);
|
||||
async = false;
|
||||
statements.add(stmt);
|
||||
}
|
||||
|
||||
|
|
|
@ -121,18 +121,10 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
|||
this.async = async;
|
||||
}
|
||||
|
||||
public MethodNode getCurrentMethod() {
|
||||
return currentMethod;
|
||||
}
|
||||
|
||||
public void setCurrentMethod(MethodNode currentMethod) {
|
||||
this.currentMethod = currentMethod;
|
||||
}
|
||||
|
||||
public int getCurrentPart() {
|
||||
return currentPart;
|
||||
}
|
||||
|
||||
public void setCurrentPart(int currentPart) {
|
||||
this.currentPart = currentPart;
|
||||
}
|
||||
|
@ -433,6 +425,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
|||
pushLocation(statement.getLocation());
|
||||
}
|
||||
writer.appendClass(statement.getClassName()).append("_$callClinit();").softNewLine();
|
||||
if (statement.isAsync()) {
|
||||
emitSuspendChecker();
|
||||
}
|
||||
if (statement.getLocation() != null) {
|
||||
popLocation();
|
||||
}
|
||||
|
|
|
@ -15,17 +15,35 @@
|
|||
*/
|
||||
package org.teavm.model.util;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.common.*;
|
||||
import org.teavm.model.*;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphSplittingBackend;
|
||||
import org.teavm.common.GraphUtils;
|
||||
import org.teavm.common.IntegerArray;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.InitClassInstruction;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.JumpInstruction;
|
||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class AsyncProgramSplitter {
|
||||
private List<Part> parts = new ArrayList<>();
|
||||
private Map<Long, Integer> partMap = new HashMap<>();
|
||||
|
@ -68,6 +86,10 @@ public class AsyncProgramSplitter {
|
|||
if (!asyncMethods.contains(findRealMethod(invoke.getMethod()))) {
|
||||
continue;
|
||||
}
|
||||
} else if (insn instanceof InitClassInstruction) {
|
||||
if (!isSplittingClassInitializer(((InitClassInstruction) insn).getClassName())) {
|
||||
continue;
|
||||
}
|
||||
} else if (!(insn instanceof MonitorEnterInstruction)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -164,6 +186,16 @@ public class AsyncProgramSplitter {
|
|||
partMap.clear();
|
||||
}
|
||||
|
||||
private boolean isSplittingClassInitializer(String className) {
|
||||
ClassReader cls = classSource.get(className);
|
||||
if (cls == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MethodReader method = cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID));
|
||||
return method != null && asyncMethods.contains(method.getReference());
|
||||
}
|
||||
|
||||
private MethodReference findRealMethod(MethodReference method) {
|
||||
String clsName = method.getClassName();
|
||||
while (clsName != null) {
|
||||
|
@ -215,10 +247,6 @@ public class AsyncProgramSplitter {
|
|||
return Arrays.copyOf(result, result.length);
|
||||
}
|
||||
|
||||
public int getBlockSuccessor(int index, int blockIndex) {
|
||||
return parts.get(index).blockSuccessors[blockIndex];
|
||||
}
|
||||
|
||||
public int[] getSplitPoints(int index) {
|
||||
return parts.get(index).splitPoints.clone();
|
||||
}
|
||||
|
|
|
@ -121,10 +121,15 @@ public class VMTest {
|
|||
assertEquals(0, initCount);
|
||||
assertEquals("foo", AsyncClinitClass.foo());
|
||||
assertEquals(1, initCount);
|
||||
assertEquals(AsyncClinitClass.state, "ok");
|
||||
assertEquals("ok", AsyncClinitClass.state);
|
||||
assertEquals("bar", AsyncClinitClass.bar());
|
||||
assertEquals(1, initCount);
|
||||
assertEquals(AsyncClinitClass.state, "ok");
|
||||
assertEquals("ok", AsyncClinitClass.state);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncClinitField() {
|
||||
assertEquals("ok", AsyncClinitClass.state);
|
||||
}
|
||||
|
||||
static int initCount = 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user