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 {
|
public class InitClassStatement extends Statement {
|
||||||
private TextLocation location;
|
private TextLocation location;
|
||||||
private String className;
|
private String className;
|
||||||
|
private boolean async;
|
||||||
|
|
||||||
public String getClassName() {
|
public String getClassName() {
|
||||||
return className;
|
return className;
|
||||||
|
@ -37,6 +38,14 @@ public class InitClassStatement extends Statement {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAsync() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsync(boolean async) {
|
||||||
|
this.async = async;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(StatementVisitor visitor) {
|
public void acceptVisitor(StatementVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -328,11 +328,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
Map<Integer, List<Integer>> switchMap = new HashMap<>();
|
Map<Integer, List<Integer>> switchMap = new HashMap<>();
|
||||||
for (int i = 0; i < insn.getEntries().size(); ++i) {
|
for (int i = 0; i < insn.getEntries().size(); ++i) {
|
||||||
SwitchTableEntry entry = insn.getEntries().get(i);
|
SwitchTableEntry entry = insn.getEntries().get(i);
|
||||||
List<Integer> conditions = switchMap.get(entry.getTarget().getIndex());
|
List<Integer> conditions = switchMap.computeIfAbsent(entry.getTarget().getIndex(), k -> new ArrayList<>());
|
||||||
if (conditions == null) {
|
|
||||||
conditions = new ArrayList<>();
|
|
||||||
switchMap.put(entry.getTarget().getIndex(), conditions);
|
|
||||||
}
|
|
||||||
conditions.add(entry.getCondition());
|
conditions.add(entry.getCondition());
|
||||||
}
|
}
|
||||||
List<Integer> targets = new ArrayList<>(switchMap.keySet());
|
List<Integer> targets = new ArrayList<>(switchMap.keySet());
|
||||||
|
@ -590,6 +586,8 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
public void visit(InitClassInstruction insn) {
|
public void visit(InitClassInstruction insn) {
|
||||||
InitClassStatement stmt = Statement.initClass(insn.getClassName());
|
InitClassStatement stmt = Statement.initClass(insn.getClassName());
|
||||||
stmt.setLocation(currentLocation);
|
stmt.setLocation(currentLocation);
|
||||||
|
stmt.setAsync(async);
|
||||||
|
async = false;
|
||||||
statements.add(stmt);
|
statements.add(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,18 +121,10 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
this.async = async;
|
this.async = async;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodNode getCurrentMethod() {
|
|
||||||
return currentMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCurrentMethod(MethodNode currentMethod) {
|
public void setCurrentMethod(MethodNode currentMethod) {
|
||||||
this.currentMethod = currentMethod;
|
this.currentMethod = currentMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCurrentPart() {
|
|
||||||
return currentPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCurrentPart(int currentPart) {
|
public void setCurrentPart(int currentPart) {
|
||||||
this.currentPart = currentPart;
|
this.currentPart = currentPart;
|
||||||
}
|
}
|
||||||
|
@ -433,6 +425,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
writer.appendClass(statement.getClassName()).append("_$callClinit();").softNewLine();
|
writer.appendClass(statement.getClassName()).append("_$callClinit();").softNewLine();
|
||||||
|
if (statement.isAsync()) {
|
||||||
|
emitSuspendChecker();
|
||||||
|
}
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,35 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.util;
|
package org.teavm.model.util;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayDeque;
|
||||||
import org.teavm.common.*;
|
import java.util.ArrayList;
|
||||||
import org.teavm.model.*;
|
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.InvokeInstruction;
|
||||||
import org.teavm.model.instructions.JumpInstruction;
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class AsyncProgramSplitter {
|
public class AsyncProgramSplitter {
|
||||||
private List<Part> parts = new ArrayList<>();
|
private List<Part> parts = new ArrayList<>();
|
||||||
private Map<Long, Integer> partMap = new HashMap<>();
|
private Map<Long, Integer> partMap = new HashMap<>();
|
||||||
|
@ -68,6 +86,10 @@ public class AsyncProgramSplitter {
|
||||||
if (!asyncMethods.contains(findRealMethod(invoke.getMethod()))) {
|
if (!asyncMethods.contains(findRealMethod(invoke.getMethod()))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (insn instanceof InitClassInstruction) {
|
||||||
|
if (!isSplittingClassInitializer(((InitClassInstruction) insn).getClassName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
} else if (!(insn instanceof MonitorEnterInstruction)) {
|
} else if (!(insn instanceof MonitorEnterInstruction)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +186,16 @@ public class AsyncProgramSplitter {
|
||||||
partMap.clear();
|
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) {
|
private MethodReference findRealMethod(MethodReference method) {
|
||||||
String clsName = method.getClassName();
|
String clsName = method.getClassName();
|
||||||
while (clsName != null) {
|
while (clsName != null) {
|
||||||
|
@ -215,10 +247,6 @@ public class AsyncProgramSplitter {
|
||||||
return Arrays.copyOf(result, result.length);
|
return Arrays.copyOf(result, result.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBlockSuccessor(int index, int blockIndex) {
|
|
||||||
return parts.get(index).blockSuccessors[blockIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getSplitPoints(int index) {
|
public int[] getSplitPoints(int index) {
|
||||||
return parts.get(index).splitPoints.clone();
|
return parts.get(index).splitPoints.clone();
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,10 +121,15 @@ public class VMTest {
|
||||||
assertEquals(0, initCount);
|
assertEquals(0, initCount);
|
||||||
assertEquals("foo", AsyncClinitClass.foo());
|
assertEquals("foo", AsyncClinitClass.foo());
|
||||||
assertEquals(1, initCount);
|
assertEquals(1, initCount);
|
||||||
assertEquals(AsyncClinitClass.state, "ok");
|
assertEquals("ok", AsyncClinitClass.state);
|
||||||
assertEquals("bar", AsyncClinitClass.bar());
|
assertEquals("bar", AsyncClinitClass.bar());
|
||||||
assertEquals(1, initCount);
|
assertEquals(1, initCount);
|
||||||
assertEquals(AsyncClinitClass.state, "ok");
|
assertEquals("ok", AsyncClinitClass.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void asyncClinitField() {
|
||||||
|
assertEquals("ok", AsyncClinitClass.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int initCount = 0;
|
static int initCount = 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user