mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
classlib: faster implementation of System.arraycopy
This commit is contained in:
parent
b11ad994fd
commit
61eb666503
|
@ -57,7 +57,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
|
||||||
writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().softNewLine();
|
writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().softNewLine();
|
||||||
writer.append(dest + ".data[" + destPos + "++] = " + src + ".data[" + srcPos + "++];").softNewLine();
|
writer.append(dest + ".data[" + destPos + "++] = " + src + ".data[" + srcPos + "++];").softNewLine();
|
||||||
writer.outdent().append("}").softNewLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
writer.outdent().append("} else {").indent().softNewLine();
|
writer.outdent().append("}").ws().append("else").ws().append("{").indent().softNewLine();
|
||||||
writer.append(srcPos + " = (" + srcPos + " + " + length + ") | 0;").softNewLine();
|
writer.append(srcPos + " = (" + srcPos + " + " + length + ") | 0;").softNewLine();
|
||||||
writer.append(destPos + " = (" + destPos + " + " + length + ") | 0;").softNewLine();
|
writer.append(destPos + " = (" + destPos + " + " + length + ") | 0;").softNewLine();
|
||||||
writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().softNewLine();
|
writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().softNewLine();
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.teavm.backend.c.intrinsic.RuntimeInclude;
|
import org.teavm.backend.c.intrinsic.RuntimeInclude;
|
||||||
|
@ -115,10 +116,18 @@ public final class TSystem extends TObject {
|
||||||
doArrayCopy(src, srcPos, dest, destPos, length);
|
doArrayCopy(src, srcPos, dest, destPos, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fastArraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
|
||||||
|
if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > Array.getLength(src)
|
||||||
|
|| destPos + length > Array.getLength(dest)) {
|
||||||
|
throw new TIndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
doArrayCopy(src, srcPos, dest, destPos, length);
|
||||||
|
}
|
||||||
|
|
||||||
@GeneratedBy(SystemNativeGenerator.class)
|
@GeneratedBy(SystemNativeGenerator.class)
|
||||||
@DelegateTo("doArrayCopyLowLevel")
|
@DelegateTo("doArrayCopyLowLevel")
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
private static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
|
static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
|
||||||
|
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
static void doArrayCopyLowLevel(RuntimeArray src, int srcPos, RuntimeArray dest, int destPos, int length) {
|
static void doArrayCopyLowLevel(RuntimeArray src, int srcPos, RuntimeArray dest, int destPos, int length) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.model.optimization;
|
package org.teavm.model.optimization;
|
||||||
|
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
|
|
||||||
|
@ -25,4 +26,6 @@ public interface MethodOptimizationContext {
|
||||||
DependencyInfo getDependencyInfo();
|
DependencyInfo getDependencyInfo();
|
||||||
|
|
||||||
ClassReaderSource getClassSource();
|
ClassReaderSource getClassSource();
|
||||||
|
|
||||||
|
ClassHierarchy getHierarchy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 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.model.optimization;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.IntHashSet;
|
||||||
|
import com.carrotsearch.hppc.IntStack;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
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.AbstractInstructionVisitor;
|
||||||
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
|
import org.teavm.model.instructions.CastInstruction;
|
||||||
|
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||||
|
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||||
|
import org.teavm.model.instructions.GetElementInstruction;
|
||||||
|
import org.teavm.model.instructions.GetFieldInstruction;
|
||||||
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
import org.teavm.model.instructions.NullCheckInstruction;
|
||||||
|
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||||
|
|
||||||
|
public class SystemArrayCopyOptimization implements MethodOptimization {
|
||||||
|
private static final MethodReference ARRAY_COPY_METHOD = new MethodReference(System.class,
|
||||||
|
"arraycopy", Object.class, int.class, Object.class, int.class, int.class, void.class);
|
||||||
|
private static final MethodReference FAST_ARRAY_COPY_METHOD = new MethodReference(System.class,
|
||||||
|
"fastArraycopy", Object.class, int.class, Object.class, int.class, int.class, void.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean optimize(MethodOptimizationContext context, Program program) {
|
||||||
|
TypeInference typeInference = null;
|
||||||
|
var somethingChanged = false;
|
||||||
|
for (var block : program.getBasicBlocks()) {
|
||||||
|
for (var instruction : block) {
|
||||||
|
if (instruction instanceof InvokeInstruction) {
|
||||||
|
var invoke = (InvokeInstruction) instruction;
|
||||||
|
var method = invoke.getMethod();
|
||||||
|
if (method.equals(ARRAY_COPY_METHOD)) {
|
||||||
|
if (typeInference == null) {
|
||||||
|
typeInference = new TypeInference(program, context.getMethod().getDescriptor());
|
||||||
|
}
|
||||||
|
var sourceType = typeInference.typeOf(invoke.getArguments().get(0));
|
||||||
|
var destType = typeInference.typeOf(invoke.getArguments().get(2));
|
||||||
|
if (sourceType != null && destType != null) {
|
||||||
|
if (sourceType.equals(destType)
|
||||||
|
|| context.getHierarchy().isSuperType(destType, sourceType, false)) {
|
||||||
|
invoke.setMethod(FAST_ARRAY_COPY_METHOD);
|
||||||
|
somethingChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return somethingChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TypeInference {
|
||||||
|
private ValueType[] types;
|
||||||
|
private int[] assignments;
|
||||||
|
private int[] elementAssignments;
|
||||||
|
private int[][] phis;
|
||||||
|
private boolean[] present;
|
||||||
|
private boolean[] calculating;
|
||||||
|
|
||||||
|
TypeInference(Program program, MethodDescriptor descriptor) {
|
||||||
|
types = new ValueType[program.variableCount()];
|
||||||
|
assignments = new int[program.variableCount()];
|
||||||
|
elementAssignments = new int[program.variableCount()];
|
||||||
|
phis = new int[program.variableCount()][];
|
||||||
|
Arrays.fill(assignments, -1);
|
||||||
|
Arrays.fill(elementAssignments, -1);
|
||||||
|
present = new boolean[program.variableCount()];
|
||||||
|
calculating = new boolean[program.variableCount()];
|
||||||
|
|
||||||
|
var visitor = new InitialTypeVisitor(types, assignments, elementAssignments);
|
||||||
|
var params = Math.min(descriptor.parameterCount(), program.variableCount() - 1);
|
||||||
|
for (var i = 0; i < params; ++i) {
|
||||||
|
visitor.type(program.variableAt(i + 1), descriptor.parameterType(i));
|
||||||
|
}
|
||||||
|
for (var block : program.getBasicBlocks()) {
|
||||||
|
for (var insn : block) {
|
||||||
|
insn.acceptVisitor(visitor);
|
||||||
|
}
|
||||||
|
for (var phi : block.getPhis()) {
|
||||||
|
var sourceIndexes = new IntHashSet();
|
||||||
|
for (var incoming : phi.getIncomings()) {
|
||||||
|
sourceIndexes.add(incoming.getValue().getIndex());
|
||||||
|
}
|
||||||
|
var inputs = sourceIndexes.toArray();
|
||||||
|
Arrays.sort(inputs);
|
||||||
|
phis[phi.getReceiver().getIndex()] = inputs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < types.length; ++i) {
|
||||||
|
if (types[i] != null) {
|
||||||
|
present[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType typeOf(Variable variable) {
|
||||||
|
if (!present[variable.getIndex()]) {
|
||||||
|
calculate(variable.getIndex());
|
||||||
|
}
|
||||||
|
return types[variable.getIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculate(int initialVariable) {
|
||||||
|
var stack = new IntStack();
|
||||||
|
stack.push(initialVariable);
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
var variable = stack.pop();
|
||||||
|
if (calculating[variable]) {
|
||||||
|
calculating[variable] = false;
|
||||||
|
present[variable] = true;
|
||||||
|
var inputs = phis[variable];
|
||||||
|
ValueType type;
|
||||||
|
if (inputs != null) {
|
||||||
|
type = null;
|
||||||
|
var initialized = false;
|
||||||
|
for (var input : inputs) {
|
||||||
|
if (calculating[input]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (initialized) {
|
||||||
|
if (!type.equals(types[input])) {
|
||||||
|
type = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = types[input];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (assignments[variable] >= 0) {
|
||||||
|
type = types[assignments[variable]];
|
||||||
|
} else if (elementAssignments[variable] >= 0) {
|
||||||
|
type = types[elementAssignments[variable]];
|
||||||
|
type = type instanceof ValueType.Array ? ((ValueType.Array) type).getItemType() : null;
|
||||||
|
} else {
|
||||||
|
type = null;
|
||||||
|
}
|
||||||
|
types[variable] = type;
|
||||||
|
} else {
|
||||||
|
calculating[variable] = true;
|
||||||
|
stack.push(variable);
|
||||||
|
var inputs = phis[variable];
|
||||||
|
if (inputs != null) {
|
||||||
|
for (var input : inputs) {
|
||||||
|
if (!calculating[input] && !present[input]) {
|
||||||
|
stack.push(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var assign = assignments[variable];
|
||||||
|
if (assign >= 0 && !present[assign]) {
|
||||||
|
stack.push(assign);
|
||||||
|
}
|
||||||
|
var elemAssign = elementAssignments[variable];
|
||||||
|
if (elemAssign >= 0 && !present[elemAssign]) {
|
||||||
|
stack.push(elemAssign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class InitialTypeVisitor extends AbstractInstructionVisitor {
|
||||||
|
private ValueType[] types;
|
||||||
|
private int[] assignments;
|
||||||
|
private int[] elementAssignments;
|
||||||
|
|
||||||
|
InitialTypeVisitor(ValueType[] types, int[] assignments, int[] elementAssignments) {
|
||||||
|
this.types = types;
|
||||||
|
this.assignments = assignments;
|
||||||
|
this.elementAssignments = elementAssignments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
|
types[insn.getReceiver().getIndex()] = insn.getItemType();
|
||||||
|
super.visit(insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructMultiArrayInstruction insn) {
|
||||||
|
var type = insn.getItemType();
|
||||||
|
for (var i = 1; i < insn.getDimensions().size(); ++i) {
|
||||||
|
type = ValueType.arrayOf(type);
|
||||||
|
}
|
||||||
|
types[insn.getReceiver().getIndex()] = insn.getItemType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastInstruction insn) {
|
||||||
|
type(insn.getReceiver(), insn.getTargetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvokeInstruction insn) {
|
||||||
|
type(insn.getReceiver(), insn.getMethod().getReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetFieldInstruction insn) {
|
||||||
|
type(insn.getReceiver(), insn.getFieldType());
|
||||||
|
}
|
||||||
|
|
||||||
|
void type(Variable target, ValueType type) {
|
||||||
|
if (target != null && type instanceof ValueType.Array) {
|
||||||
|
types[target.getIndex()] = ((ValueType.Array) type).getItemType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnwrapArrayInstruction insn) {
|
||||||
|
assignments[insn.getReceiver().getIndex()] = insn.getArray().getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetElementInstruction insn) {
|
||||||
|
elementAssignments[insn.getReceiver().getIndex()] = insn.getArray().getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignInstruction insn) {
|
||||||
|
assignments[insn.getReceiver().getIndex()] = insn.getAssignee().getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NullCheckInstruction insn) {
|
||||||
|
assignments[insn.getReceiver().getIndex()] = insn.getValue().getIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 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.vm;
|
||||||
|
|
||||||
|
import org.teavm.dependency.AbstractDependencyListener;
|
||||||
|
import org.teavm.dependency.DependencyAgent;
|
||||||
|
import org.teavm.dependency.MethodDependency;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public class StdlibDependencyListener extends AbstractDependencyListener {
|
||||||
|
private static final MethodReference ARRAY_COPY_METHOD = new MethodReference(System.class,
|
||||||
|
"arraycopy", Object.class, int.class, Object.class, int.class, int.class, void.class);
|
||||||
|
private static final MethodReference FAST_ARRAY_COPY_METHOD = new MethodReference(System.class,
|
||||||
|
"fastArraycopy", Object.class, int.class, Object.class, int.class, int.class, void.class);
|
||||||
|
private boolean reached;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||||
|
if (!reached && method.getReference().equals(ARRAY_COPY_METHOD)) {
|
||||||
|
reached = true;
|
||||||
|
agent.linkMethod(FAST_ARRAY_COPY_METHOD).use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -90,6 +90,7 @@ import org.teavm.model.optimization.RedundantJumpElimination;
|
||||||
import org.teavm.model.optimization.RedundantNullCheckElimination;
|
import org.teavm.model.optimization.RedundantNullCheckElimination;
|
||||||
import org.teavm.model.optimization.RepeatedFieldReadElimination;
|
import org.teavm.model.optimization.RepeatedFieldReadElimination;
|
||||||
import org.teavm.model.optimization.ScalarReplacement;
|
import org.teavm.model.optimization.ScalarReplacement;
|
||||||
|
import org.teavm.model.optimization.SystemArrayCopyOptimization;
|
||||||
import org.teavm.model.optimization.UnreachableBasicBlockElimination;
|
import org.teavm.model.optimization.UnreachableBasicBlockElimination;
|
||||||
import org.teavm.model.optimization.UnusedVariableElimination;
|
import org.teavm.model.optimization.UnusedVariableElimination;
|
||||||
import org.teavm.model.text.ListingBuilder;
|
import org.teavm.model.text.ListingBuilder;
|
||||||
|
@ -375,6 +376,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
return !cancelled;
|
return !cancelled;
|
||||||
});
|
});
|
||||||
target.contributeDependencies(dependencyAnalyzer);
|
target.contributeDependencies(dependencyAnalyzer);
|
||||||
|
dependencyAnalyzer.addDependencyListener(new StdlibDependencyListener());
|
||||||
dependencyAnalyzer.processDependencies();
|
dependencyAnalyzer.processDependencies();
|
||||||
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
|
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -782,6 +784,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return dependencyAnalyzer.getClassSource();
|
return dependencyAnalyzer.getClassSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassHierarchy getHierarchy() {
|
||||||
|
return dependencyAnalyzer.getClassHierarchy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MethodOptimization> getOptimizations() {
|
private List<MethodOptimization> getOptimizations() {
|
||||||
|
@ -806,6 +813,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
optimizations.add(new ClassInitElimination());
|
optimizations.add(new ClassInitElimination());
|
||||||
optimizations.add(new UnreachableBasicBlockElimination());
|
optimizations.add(new UnreachableBasicBlockElimination());
|
||||||
optimizations.add(new UnusedVariableElimination());
|
optimizations.add(new UnusedVariableElimination());
|
||||||
|
optimizations.add(new SystemArrayCopyOptimization());
|
||||||
return optimizations;
|
return optimizations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.Test;
|
||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.model.AccessLevel;
|
import org.teavm.model.AccessLevel;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
|
@ -154,6 +155,11 @@ public class RepeatedFieldReadEliminationTest {
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassHierarchy getHierarchy() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new RepeatedFieldReadElimination().optimize(context, program);
|
new RepeatedFieldReadElimination().optimize(context, program);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ListingParseUtils;
|
import org.teavm.model.ListingParseUtils;
|
||||||
|
@ -116,6 +117,11 @@ public class ScalarReplacementTest {
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassHierarchy getHierarchy() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new ScalarReplacement().optimize(context, program);
|
new ScalarReplacement().optimize(context, program);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user