mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Merge branch 'synchronized-methods'
This commit is contained in:
commit
a89a6b1748
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -109,6 +110,40 @@ class DependencyGraphBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method.hasModifier(ElementModifier.SYNCHRONIZED)) {
|
||||||
|
List<DependencyNode> syncNodes = new ArrayList<>();
|
||||||
|
|
||||||
|
MethodDependency methodDep = dependencyChecker.linkMethod(
|
||||||
|
new MethodReference(Object.class, "monitorEnter", Object.class, void.class), null);
|
||||||
|
syncNodes.add(methodDep.getVariable(1));
|
||||||
|
methodDep.use();
|
||||||
|
|
||||||
|
methodDep = dependencyChecker.linkMethod(
|
||||||
|
new MethodReference(Object.class, "monitorEnterSync", Object.class, void.class), null);
|
||||||
|
syncNodes.add(methodDep.getVariable(1));
|
||||||
|
methodDep.use();
|
||||||
|
|
||||||
|
methodDep = dependencyChecker.linkMethod(
|
||||||
|
new MethodReference(Object.class, "monitorExit", Object.class, void.class), null);
|
||||||
|
syncNodes.add(methodDep.getVariable(1));
|
||||||
|
methodDep.use();
|
||||||
|
|
||||||
|
methodDep = dependencyChecker.linkMethod(
|
||||||
|
new MethodReference(Object.class, "monitorExitSync", Object.class, void.class), null);
|
||||||
|
syncNodes.add(methodDep.getVariable(1));
|
||||||
|
methodDep.use();
|
||||||
|
|
||||||
|
if (method.hasModifier(ElementModifier.STATIC)) {
|
||||||
|
for (DependencyNode node : syncNodes) {
|
||||||
|
node.propagate(dependencyChecker.getType("java.lang.Class"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (DependencyNode node : syncNodes) {
|
||||||
|
nodes[0].connect(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExceptionConsumer createExceptionConsumer(MethodDependency methodDep, BasicBlockReader block) {
|
private ExceptionConsumer createExceptionConsumer(MethodDependency methodDep, BasicBlockReader block) {
|
||||||
|
|
|
@ -383,6 +383,9 @@ public class Decompiler {
|
||||||
if (modifiers.contains(ElementModifier.ENUM)) {
|
if (modifiers.contains(ElementModifier.ENUM)) {
|
||||||
result.add(NodeModifier.ENUM);
|
result.add(NodeModifier.ENUM);
|
||||||
}
|
}
|
||||||
|
if (modifiers.contains(ElementModifier.SYNCHRONIZED)) {
|
||||||
|
result.add(NodeModifier.SYNCHRONIZED);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -725,18 +725,43 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
writer.softNewLine();
|
writer.softNewLine();
|
||||||
writer.outdent().append("}").softNewLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
|
|
||||||
|
if (methodNode.getModifiers().contains(NodeModifier.SYNCHRONIZED)) {
|
||||||
|
writer.append("try").ws().append('{').indent().softNewLine();
|
||||||
|
}
|
||||||
writer.append(mainLoopName()).append(":").ws().append("while").ws().append("(true)")
|
writer.append(mainLoopName()).append(":").ws().append("while").ws().append("(true)")
|
||||||
.ws().append("{").ws();
|
.ws().append("{").ws();
|
||||||
writer.append("switch").ws().append("(").append(pointerName()).append(")").ws()
|
writer.append("switch").ws().append("(").append(pointerName()).append(")").ws()
|
||||||
.append('{').softNewLine();
|
.append('{').softNewLine();
|
||||||
for (int i = 0; i < methodNode.getBody().size(); ++i) {
|
for (int i = 0; i < methodNode.getBody().size(); ++i) {
|
||||||
writer.append("case ").append(i).append(":").indent().softNewLine();
|
writer.append("case ").append(i).append(":").indent().softNewLine();
|
||||||
|
if (i == 0 && methodNode.getModifiers().contains(NodeModifier.SYNCHRONIZED)) {
|
||||||
|
writer.appendMethodBody(new MethodReference(Object.class, "monitorEnter",
|
||||||
|
Object.class, void.class));
|
||||||
|
writer.append("(");
|
||||||
|
appendMonitor(methodNode);
|
||||||
|
writer.append(");").softNewLine();
|
||||||
|
emitSuspendChecker();
|
||||||
|
}
|
||||||
AsyncMethodPart part = methodNode.getBody().get(i);
|
AsyncMethodPart part = methodNode.getBody().get(i);
|
||||||
part.getStatement().acceptVisitor(Renderer.this);
|
part.getStatement().acceptVisitor(Renderer.this);
|
||||||
writer.outdent();
|
writer.outdent();
|
||||||
}
|
}
|
||||||
writer.append("default:").ws().appendFunction("$rt_invalidPointer").append("();").softNewLine();
|
writer.append("default:").ws().appendFunction("$rt_invalidPointer").append("();").softNewLine();
|
||||||
writer.append("}}").softNewLine();
|
writer.append("}}").softNewLine();
|
||||||
|
|
||||||
|
if (methodNode.getModifiers().contains(NodeModifier.SYNCHRONIZED)) {
|
||||||
|
writer.outdent().append("}").ws().append("finally").ws().append('{').indent().softNewLine();
|
||||||
|
writer.append("if").ws().append("(!").appendFunction("$rt_suspending").append("())")
|
||||||
|
.ws().append("{").indent().softNewLine();
|
||||||
|
writer.appendMethodBody(new MethodReference(Object.class, "monitorExit",
|
||||||
|
Object.class, void.class));
|
||||||
|
writer.append("(");
|
||||||
|
appendMonitor(methodNode);
|
||||||
|
writer.append(");").softNewLine();
|
||||||
|
writer.outdent().append('}').softNewLine();
|
||||||
|
writer.outdent().append('}').softNewLine();
|
||||||
|
}
|
||||||
|
|
||||||
writer.appendFunction("$rt_nativeThread").append("().").append(pushName).append("(");
|
writer.appendFunction("$rt_nativeThread").append("().").append(pushName).append("(");
|
||||||
for (int i = firstToSave; i < variableCount; ++i) {
|
for (int i = firstToSave; i < variableCount; ++i) {
|
||||||
writer.append(variableName(i)).append(',').ws();
|
writer.append(variableName(i)).append(',').ws();
|
||||||
|
@ -794,6 +819,15 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void appendMonitor(MethodNode methodNode) throws IOException {
|
||||||
|
if (methodNode.getModifiers().contains(NodeModifier.STATIC)) {
|
||||||
|
writer.appendFunction("$rt_cls").append("(")
|
||||||
|
.appendClass(methodNode.getReference().getClassName()).append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(variableName(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void pushLocation(NodeLocation location) {
|
private void pushLocation(NodeLocation location) {
|
||||||
LocationStackEntry prevEntry = locationStack.peek();
|
LocationStackEntry prevEntry = locationStack.peek();
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
|
|
|
@ -22,5 +22,6 @@ package org.teavm.javascript.ast;
|
||||||
public enum NodeModifier {
|
public enum NodeModifier {
|
||||||
STATIC,
|
STATIC,
|
||||||
INTERFACE,
|
INTERFACE,
|
||||||
ENUM
|
ENUM,
|
||||||
|
SYNCHRONIZED
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,10 @@ public class AsyncMethodFinder {
|
||||||
if (asyncMethods.contains(method.getReference()) || method.getProgram() == null) {
|
if (asyncMethods.contains(method.getReference()) || method.getProgram() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (method.hasModifier(ElementModifier.SYNCHRONIZED)) {
|
||||||
|
add(method.getReference());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ProgramReader program = method.getProgram();
|
ProgramReader program = method.getProgram();
|
||||||
AsyncInstructionReader insnReader = new AsyncInstructionReader();
|
AsyncInstructionReader insnReader = new AsyncInstructionReader();
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.util;
|
package org.teavm.model.util;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.IntOpenHashSet;
|
||||||
|
import com.carrotsearch.hppc.IntSet;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
|
@ -51,15 +53,19 @@ public class LivenessAnalyzer {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
for (Instruction insn : block.getInstructions()) {
|
for (Instruction insn : block.getInstructions()) {
|
||||||
insn.acceptVisitor(usageExtractor);
|
insn.acceptVisitor(usageExtractor);
|
||||||
|
IntSet usedVars = new IntOpenHashSet();
|
||||||
for (Variable var : usageExtractor.getUsedVariables()) {
|
for (Variable var : usageExtractor.getUsedVariables()) {
|
||||||
Task task = new Task();
|
Task task = new Task();
|
||||||
task.block = i;
|
task.block = i;
|
||||||
task.var = var.getIndex();
|
task.var = var.getIndex();
|
||||||
stack.push(task);
|
stack.push(task);
|
||||||
|
usedVars.add(var.getIndex());
|
||||||
}
|
}
|
||||||
insn.acceptVisitor(defExtractor);
|
insn.acceptVisitor(defExtractor);
|
||||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||||
definitions[var.getIndex()] = i;
|
if (!usedVars.contains(var.getIndex())) {
|
||||||
|
definitions[var.getIndex()] = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user