mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: cast receivers on devirtualized calls to actual argument type, avoid this cast when possible
This commit is contained in:
parent
75bead66b3
commit
a8d97ad387
|
@ -15,23 +15,23 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.gc;
|
package org.teavm.backend.wasm.gc;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import org.teavm.model.ClassHierarchy;
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassReader;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.analysis.BaseTypeInference;
|
import org.teavm.model.analysis.BaseTypeInference;
|
||||||
|
import org.teavm.model.instructions.InvocationType;
|
||||||
|
|
||||||
public class PreciseTypeInference extends BaseTypeInference<ValueType> {
|
public class PreciseTypeInference extends BaseTypeInference<ValueType> {
|
||||||
public static final ValueType OBJECT_TYPE = ValueType.object("java.lang.Object");
|
public static final ValueType OBJECT_TYPE = ValueType.object("java.lang.Object");
|
||||||
private ClassHierarchy hierarchy;
|
private ClassHierarchy hierarchy;
|
||||||
|
private WasmGCMethodReturnTypes returnTypes;
|
||||||
|
|
||||||
public PreciseTypeInference(Program program, MethodReference reference, ClassHierarchy hierarchy) {
|
public PreciseTypeInference(Program program, MethodReference reference, ClassHierarchy hierarchy,
|
||||||
|
WasmGCMethodReturnTypes returnTypes) {
|
||||||
super(program, reference);
|
super(program, reference);
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
|
this.returnTypes = returnTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,7 +87,7 @@ public class PreciseTypeInference extends BaseTypeInference<ValueType> {
|
||||||
} else if (hierarchy.isSuperType(q, p, false)) {
|
} else if (hierarchy.isSuperType(q, p, false)) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
return ValueType.object(findCommonSuperclass(first, second));
|
return ValueType.object(WasmGCUtil.findCommonSuperclass(hierarchy, first, second));
|
||||||
} else {
|
} else {
|
||||||
return OBJECT_TYPE;
|
return OBJECT_TYPE;
|
||||||
}
|
}
|
||||||
|
@ -96,34 +96,16 @@ public class PreciseTypeInference extends BaseTypeInference<ValueType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String findCommonSuperclass(ClassReader a, ClassReader b) {
|
|
||||||
var firstPath = findPathToRoot(a);
|
|
||||||
Collections.reverse(firstPath);
|
|
||||||
var secondPath = findPathToRoot(b);
|
|
||||||
Collections.reverse(secondPath);
|
|
||||||
if (firstPath.get(0) != secondPath.get(0)) {
|
|
||||||
return "java.lang.Object";
|
|
||||||
}
|
|
||||||
var max = Math.max(firstPath.size(), secondPath.size());
|
|
||||||
var index = 1;
|
|
||||||
while (index < max && firstPath.get(index) == secondPath.get(index)) {
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
return firstPath.get(index).getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ClassReader> findPathToRoot(ClassReader cls) {
|
|
||||||
var path = new ArrayList<ClassReader>();
|
|
||||||
while (cls != null) {
|
|
||||||
path.add(cls);
|
|
||||||
cls = cls.getParent() != null ? hierarchy.getClassSource().get(cls.getParent()) : null;
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ValueType elementType(ValueType valueType) {
|
protected ValueType elementType(ValueType valueType) {
|
||||||
return ((ValueType.Array) valueType).getItemType();
|
return ((ValueType.Array) valueType).getItemType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ValueType methodReturnType(InvocationType invocationType, MethodReference methodRef) {
|
||||||
|
if (invocationType == InvocationType.SPECIAL) {
|
||||||
|
return returnTypes.returnTypeOf(methodRef);
|
||||||
|
}
|
||||||
|
return super.methodReturnType(invocationType, methodRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.backend.wasm.gc;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.dependency.DependencyInfo;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
public class WasmGCMethodReturnTypes {
|
||||||
|
private DependencyInfo dependencyInfo;
|
||||||
|
private ClassHierarchy hierarchy;
|
||||||
|
private Map<MethodReference, ValueType> cache = new HashMap<>();
|
||||||
|
|
||||||
|
public WasmGCMethodReturnTypes(DependencyInfo dependencyInfo, ClassHierarchy hierarchy) {
|
||||||
|
this.dependencyInfo = dependencyInfo;
|
||||||
|
this.hierarchy = hierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueType returnTypeOf(MethodReference reference) {
|
||||||
|
return cache.computeIfAbsent(reference, this::calculateReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueType calculateReturnType(MethodReference reference) {
|
||||||
|
if (!(reference.getReturnType() instanceof ValueType.Object)) {
|
||||||
|
return reference.getReturnType();
|
||||||
|
}
|
||||||
|
var method = dependencyInfo.getMethod(reference);
|
||||||
|
if (method == null) {
|
||||||
|
return reference.getReturnType();
|
||||||
|
}
|
||||||
|
var types = method.getResult().getTypes();
|
||||||
|
if (types.length == 0) {
|
||||||
|
return reference.getReturnType();
|
||||||
|
}
|
||||||
|
var type = hierarchy.getClassSource().get(types[0]);
|
||||||
|
if (type == null) {
|
||||||
|
return reference.getReturnType();
|
||||||
|
}
|
||||||
|
for (var i = 1; i < types.length; ++i) {
|
||||||
|
var otherType = hierarchy.getClassSource().get(types[i]);
|
||||||
|
if (otherType == null) {
|
||||||
|
return reference.getReturnType();
|
||||||
|
}
|
||||||
|
type = hierarchy.getClassSource().get(WasmGCUtil.findCommonSuperclass(hierarchy, type, otherType));
|
||||||
|
}
|
||||||
|
return ValueType.object(type.getName());
|
||||||
|
}
|
||||||
|
}
|
54
core/src/main/java/org/teavm/backend/wasm/gc/WasmGCUtil.java
Normal file
54
core/src/main/java/org/teavm/backend/wasm/gc/WasmGCUtil.java
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 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.backend.wasm.gc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
|
||||||
|
public final class WasmGCUtil {
|
||||||
|
private WasmGCUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String findCommonSuperclass(ClassHierarchy hierarchy, ClassReader a, ClassReader b) {
|
||||||
|
var firstPath = findPathToRoot(hierarchy, a);
|
||||||
|
Collections.reverse(firstPath);
|
||||||
|
var secondPath = findPathToRoot(hierarchy, b);
|
||||||
|
Collections.reverse(secondPath);
|
||||||
|
if (firstPath.get(0) != secondPath.get(0)) {
|
||||||
|
return "java.lang.Object";
|
||||||
|
}
|
||||||
|
var max = Math.max(firstPath.size(), secondPath.size());
|
||||||
|
var index = 1;
|
||||||
|
while (index < max && firstPath.get(index) == secondPath.get(index)) {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return firstPath.get(index).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ClassReader> findPathToRoot(ClassHierarchy hierarchy, ClassReader cls) {
|
||||||
|
var path = new ArrayList<ClassReader>();
|
||||||
|
while (cls != null) {
|
||||||
|
path.add(cls);
|
||||||
|
cls = cls.getParent() != null ? hierarchy.getClassSource().get(cls.getParent()) : null;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,9 +23,11 @@ import org.teavm.model.util.VariableCategoryProvider;
|
||||||
public class WasmGCVariableCategoryProvider implements VariableCategoryProvider {
|
public class WasmGCVariableCategoryProvider implements VariableCategoryProvider {
|
||||||
private ClassHierarchy hierarchy;
|
private ClassHierarchy hierarchy;
|
||||||
private PreciseTypeInference inference;
|
private PreciseTypeInference inference;
|
||||||
|
private WasmGCMethodReturnTypes returnTypes;
|
||||||
|
|
||||||
public WasmGCVariableCategoryProvider(ClassHierarchy hierarchy) {
|
public WasmGCVariableCategoryProvider(ClassHierarchy hierarchy, WasmGCMethodReturnTypes returnTypes) {
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
|
this.returnTypes = returnTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreciseTypeInference getTypeInference() {
|
public PreciseTypeInference getTypeInference() {
|
||||||
|
@ -34,7 +36,7 @@ public class WasmGCVariableCategoryProvider implements VariableCategoryProvider
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getCategories(Program program, MethodReference method) {
|
public Object[] getCategories(Program program, MethodReference method) {
|
||||||
inference = new PreciseTypeInference(program, method, hierarchy);
|
inference = new PreciseTypeInference(program, method, hierarchy, returnTypes);
|
||||||
var result = new Object[program.variableCount()];
|
var result = new Object[program.variableCount()];
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
var type = inference.typeOf(program.variableAt(i));
|
var type = inference.typeOf(program.variableAt(i));
|
||||||
|
|
|
@ -846,6 +846,10 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
accept(argument);
|
accept(argument);
|
||||||
call.getArguments().add(result);
|
call.getArguments().add(result);
|
||||||
}
|
}
|
||||||
|
if (expr.getType() == InvocationType.SPECIAL) {
|
||||||
|
var firstArg = call.getArguments().get(0);
|
||||||
|
call.getArguments().set(0, mapFirstArgumentForCall(firstArg, function, expr.getMethod()));
|
||||||
|
}
|
||||||
if (callSiteId != null) {
|
if (callSiteId != null) {
|
||||||
callSiteId.addToLastArg(call.getArguments());
|
callSiteId.addToLastArg(call.getArguments());
|
||||||
}
|
}
|
||||||
|
@ -903,13 +907,17 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected WasmExpression mapFirstArgumentForCall(WasmExpression argument, WasmFunction function,
|
||||||
|
MethodReference method) {
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract WasmExpression generateVirtualCall(
|
protected abstract WasmExpression generateVirtualCall(
|
||||||
WasmLocal instance,
|
WasmLocal instance,
|
||||||
MethodReference method,
|
MethodReference method,
|
||||||
List<WasmExpression> arguments
|
List<WasmExpression> arguments
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
private boolean needsCallSiteId() {
|
private boolean needsCallSiteId() {
|
||||||
return isManaged();
|
return isManaged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
|
import org.teavm.backend.wasm.gc.WasmGCMethodReturnTypes;
|
||||||
import org.teavm.backend.wasm.generate.WasmNameProvider;
|
import org.teavm.backend.wasm.generate.WasmNameProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassGenerator;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassGenerator;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
|
@ -45,6 +46,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
public final WasmFunctionTypes functionTypes;
|
public final WasmFunctionTypes functionTypes;
|
||||||
private final WasmGCClassGenerator classGenerator;
|
private final WasmGCClassGenerator classGenerator;
|
||||||
private final WasmGCMethodGenerator methodGenerator;
|
private final WasmGCMethodGenerator methodGenerator;
|
||||||
|
private final WasmGCMethodReturnTypes returnTypes;
|
||||||
|
|
||||||
public WasmGCDeclarationsGenerator(
|
public WasmGCDeclarationsGenerator(
|
||||||
WasmModule module,
|
WasmModule module,
|
||||||
|
@ -60,6 +62,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
var virtualTables = createVirtualTableProvider(classes, virtualMethods);
|
var virtualTables = createVirtualTableProvider(classes, virtualMethods);
|
||||||
functionTypes = new WasmFunctionTypes(module);
|
functionTypes = new WasmFunctionTypes(module);
|
||||||
var names = new WasmNameProvider();
|
var names = new WasmNameProvider();
|
||||||
|
returnTypes = new WasmGCMethodReturnTypes(dependencyInfo, hierarchy);
|
||||||
methodGenerator = new WasmGCMethodGenerator(
|
methodGenerator = new WasmGCMethodGenerator(
|
||||||
module,
|
module,
|
||||||
hierarchy,
|
hierarchy,
|
||||||
|
@ -69,6 +72,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
functionTypes,
|
functionTypes,
|
||||||
names,
|
names,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
|
returnTypes,
|
||||||
customGenerators
|
customGenerators
|
||||||
);
|
);
|
||||||
var tags = new TagRegistry(classes, hierarchy);
|
var tags = new TagRegistry(classes, hierarchy);
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class WasmGCStandardClasses {
|
||||||
|
|
||||||
public WasmGCClassInfo stringClass() {
|
public WasmGCClassInfo stringClass() {
|
||||||
if (stringClassInfo == null) {
|
if (stringClassInfo == null) {
|
||||||
stringClassInfo = classGenerator.getClassInfo("java.lang.Class");
|
stringClassInfo = classGenerator.getClassInfo("java.lang.String");
|
||||||
}
|
}
|
||||||
return stringClassInfo;
|
return stringClassInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,6 +357,31 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
result = invocation(expr, null, false);
|
result = invocation(expr, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected WasmExpression mapFirstArgumentForCall(WasmExpression argument, WasmFunction function,
|
||||||
|
MethodReference method) {
|
||||||
|
argument.acceptVisitor(typeInference);
|
||||||
|
var actualType = typeInference.getResult();
|
||||||
|
var expectedType = function.getType().getParameterTypes().get(0);
|
||||||
|
if (actualType == expectedType || !(actualType instanceof WasmType.CompositeReference)
|
||||||
|
|| !(expectedType instanceof WasmType.CompositeReference)) {
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
var actualComposite = ((WasmType.CompositeReference) actualType).composite;
|
||||||
|
var expectedComposite = ((WasmType.CompositeReference) expectedType).composite;
|
||||||
|
if (!(actualComposite instanceof WasmStructure) || !(expectedComposite instanceof WasmStructure)) {
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
var actualStruct = (WasmStructure) actualComposite;
|
||||||
|
var expectedStruct = (WasmStructure) expectedComposite;
|
||||||
|
if (!actualStruct.isSupertypeOf(expectedStruct)) {
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WasmCast(argument, expectedComposite.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(QualificationExpr expr) {
|
public void visit(QualificationExpr expr) {
|
||||||
if (expr.getQualified() == null) {
|
if (expr.getQualified() == null) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.teavm.ast.decompilation.Decompiler;
|
||||||
import org.teavm.backend.lowlevel.generate.NameProvider;
|
import org.teavm.backend.lowlevel.generate.NameProvider;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
|
import org.teavm.backend.wasm.gc.WasmGCMethodReturnTypes;
|
||||||
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||||
|
@ -76,6 +77,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
private WasmGCClassInfoProvider classInfoProvider;
|
private WasmGCClassInfoProvider classInfoProvider;
|
||||||
private WasmGCStandardClasses standardClasses;
|
private WasmGCStandardClasses standardClasses;
|
||||||
private WasmGCStringProvider strings;
|
private WasmGCStringProvider strings;
|
||||||
|
private WasmGCMethodReturnTypes returnTypes;
|
||||||
|
|
||||||
public WasmGCMethodGenerator(
|
public WasmGCMethodGenerator(
|
||||||
WasmModule module,
|
WasmModule module,
|
||||||
|
@ -86,6 +88,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
WasmFunctionTypes functionTypes,
|
WasmFunctionTypes functionTypes,
|
||||||
NameProvider names,
|
NameProvider names,
|
||||||
Diagnostics diagnostics,
|
Diagnostics diagnostics,
|
||||||
|
WasmGCMethodReturnTypes returnTypes,
|
||||||
WasmGCCustomGeneratorProvider customGenerators
|
WasmGCCustomGeneratorProvider customGenerators
|
||||||
) {
|
) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
|
@ -96,6 +99,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
this.functionTypes = functionTypes;
|
this.functionTypes = functionTypes;
|
||||||
this.names = names;
|
this.names = names;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
|
this.returnTypes = returnTypes;
|
||||||
this.customGenerators = customGenerators;
|
this.customGenerators = customGenerators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +143,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmFunction createStaticFunction(MethodReference methodReference) {
|
private WasmFunction createStaticFunction(MethodReference methodReference) {
|
||||||
var returnType = typeMapper.mapType(methodReference.getReturnType());
|
var returnType = typeMapper.mapType(returnTypes.returnTypeOf(methodReference));
|
||||||
var parameterTypes = new WasmType[methodReference.parameterCount()];
|
var parameterTypes = new WasmType[methodReference.parameterCount()];
|
||||||
for (var i = 0; i < parameterTypes.length; ++i) {
|
for (var i = 0; i < parameterTypes.length; ++i) {
|
||||||
parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i));
|
parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i));
|
||||||
|
@ -166,7 +170,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmFunction createInstanceFunction(MethodReference methodReference) {
|
private WasmFunction createInstanceFunction(MethodReference methodReference) {
|
||||||
var returnType = typeMapper.mapType(methodReference.getReturnType());
|
var returnType = typeMapper.mapType(returnTypes.returnTypeOf(methodReference));
|
||||||
var parameterTypes = new WasmType[methodReference.parameterCount() + 1];
|
var parameterTypes = new WasmType[methodReference.parameterCount() + 1];
|
||||||
parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName()));
|
parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName()));
|
||||||
for (var i = 0; i < methodReference.parameterCount(); ++i) {
|
for (var i = 0; i < methodReference.parameterCount(); ++i) {
|
||||||
|
@ -206,7 +210,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
|
|
||||||
private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
|
private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
|
||||||
var decompiler = getDecompiler();
|
var decompiler = getDecompiler();
|
||||||
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy);
|
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy, returnTypes);
|
||||||
var allocator = new RegisterAllocator(categoryProvider);
|
var allocator = new RegisterAllocator(categoryProvider);
|
||||||
allocator.allocateRegisters(method.getReference(), method.getProgram(), friendlyToDebugger);
|
allocator.allocateRegisters(method.getReference(), method.getProgram(), friendlyToDebugger);
|
||||||
var ast = decompiler.decompileRegular(method);
|
var ast = decompiler.decompileRegular(method);
|
||||||
|
|
|
@ -38,6 +38,16 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
this.supertype = supertype;
|
this.supertype = supertype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSupertypeOf(WasmStructure subtype) {
|
||||||
|
while (subtype != null) {
|
||||||
|
if (subtype == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
subtype = subtype.getSupertype();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(WasmCompositeTypeVisitor visitor) {
|
public void acceptVisitor(WasmCompositeTypeVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -1030,7 +1030,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
writer.writeByte(0xfb);
|
writer.writeByte(0xfb);
|
||||||
writer.writeByte(23);
|
writer.writeByte(23);
|
||||||
writer.writeType(expression.getTargetType(), module);
|
writer.writeHeapType(expression.getTargetType(), module);
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.teavm.model.instructions.FloatConstantInstruction;
|
||||||
import org.teavm.model.instructions.GetElementInstruction;
|
import org.teavm.model.instructions.GetElementInstruction;
|
||||||
import org.teavm.model.instructions.GetFieldInstruction;
|
import org.teavm.model.instructions.GetFieldInstruction;
|
||||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||||
|
import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||||
import org.teavm.model.instructions.LongConstantInstruction;
|
import org.teavm.model.instructions.LongConstantInstruction;
|
||||||
|
@ -169,7 +170,7 @@ public abstract class BaseTypeInference<T> {
|
||||||
|
|
||||||
protected abstract T elementType(T t);
|
protected abstract T elementType(T t);
|
||||||
|
|
||||||
protected T methodReturnType(MethodReference methodRef) {
|
protected T methodReturnType(InvocationType invocationType, MethodReference methodRef) {
|
||||||
return mapType(methodRef.getReturnType());
|
return mapType(methodRef.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +294,7 @@ public abstract class BaseTypeInference<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvokeInstruction insn) {
|
public void visit(InvokeInstruction insn) {
|
||||||
type(insn.getReceiver(), methodReturnType(insn.getMethod()));
|
type(insn.getReceiver(), methodReturnType(insn.getType(), insn.getMethod()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.analysis.BaseTypeInference;
|
import org.teavm.model.analysis.BaseTypeInference;
|
||||||
|
import org.teavm.model.instructions.InvocationType;
|
||||||
|
|
||||||
class JSTypeInference extends BaseTypeInference<JSType> {
|
class JSTypeInference extends BaseTypeInference<JSType> {
|
||||||
private JSTypeHelper typeHelper;
|
private JSTypeHelper typeHelper;
|
||||||
|
@ -85,7 +86,7 @@ class JSTypeInference extends BaseTypeInference<JSType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected JSType methodReturnType(MethodReference methodRef) {
|
protected JSType methodReturnType(InvocationType invocationType, MethodReference methodRef) {
|
||||||
if (!methodRef.getReturnType().isObject(Object.class)) {
|
if (!methodRef.getReturnType().isObject(Object.class)) {
|
||||||
return mapType(methodRef.getReturnType());
|
return mapType(methodRef.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user