mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: implement Class.getSuperclass and Object.clone, fix issue with resource maps
This commit is contained in:
parent
fe0304ee67
commit
349ed8fc2d
|
@ -344,7 +344,7 @@ public class TObject {
|
||||||
@PluggableDependency(ObjectDependencyPlugin.class)
|
@PluggableDependency(ObjectDependencyPlugin.class)
|
||||||
protected Object clone() throws TCloneNotSupportedException {
|
protected Object clone() throws TCloneNotSupportedException {
|
||||||
if (PlatformDetector.isWebAssemblyGC()) {
|
if (PlatformDetector.isWebAssemblyGC()) {
|
||||||
throw new TCloneNotSupportedException();
|
return cloneObject();
|
||||||
}
|
}
|
||||||
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
||||||
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
||||||
|
@ -355,6 +355,8 @@ public class TObject {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private native TObject cloneObject();
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static RuntimeObject cloneLowLevel(RuntimeObject self) {
|
private static RuntimeObject cloneLowLevel(RuntimeObject self) {
|
||||||
RuntimeClass cls = RuntimeClass.getClass(self);
|
RuntimeClass cls = RuntimeClass.getClass(self);
|
||||||
|
|
|
@ -98,7 +98,8 @@ public class WasmGCDependencies {
|
||||||
analyzer.linkMethod(new MethodReference(WasmGCSupport.class, "aiiobe", ArrayIndexOutOfBoundsException.class))
|
analyzer.linkMethod(new MethodReference(WasmGCSupport.class, "aiiobe", ArrayIndexOutOfBoundsException.class))
|
||||||
.use();
|
.use();
|
||||||
analyzer.linkMethod(new MethodReference(WasmGCSupport.class, "cce", ClassCastException.class)).use();
|
analyzer.linkMethod(new MethodReference(WasmGCSupport.class, "cce", ClassCastException.class)).use();
|
||||||
analyzer.linkMethod(new MethodReference(WasmGCSupport.class, "cnse", CloneNotSupportedException.class)).use();
|
analyzer.linkMethod(new MethodReference(WasmGCSupport.class, "throwCloneNotSupportedException",
|
||||||
|
void.class)).use();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void contributeInitializerUtils() {
|
private void contributeInitializerUtils() {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
class WasmGCVirtualTableBuilder {
|
class WasmGCVirtualTableBuilder {
|
||||||
|
private static final MethodReference CLONE_METHOD = new MethodReference(Object.class, "clone", Object.class);
|
||||||
ListableClassReaderSource classes;
|
ListableClassReaderSource classes;
|
||||||
Collection<MethodReference> methodsAtCallSites;
|
Collection<MethodReference> methodsAtCallSites;
|
||||||
Predicate<MethodReference> isVirtual;
|
Predicate<MethodReference> isVirtual;
|
||||||
|
@ -170,7 +171,7 @@ class WasmGCVirtualTableBuilder {
|
||||||
if (method.getProgram() == null && !method.hasModifier(ElementModifier.NATIVE)) {
|
if (method.getProgram() == null && !method.hasModifier(ElementModifier.NATIVE)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!isVirtual.test(method.getReference())) {
|
if (!isVirtual.test(method.getReference()) && !method.getReference().equals(CLONE_METHOD)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
table.currentImplementors.put(method.getDescriptor(), method.getReference());
|
table.currentImplementors.put(method.getDescriptor(), method.getReference());
|
||||||
|
|
|
@ -82,6 +82,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
classGenerator = new WasmGCClassGenerator(
|
classGenerator = new WasmGCClassGenerator(
|
||||||
module,
|
module,
|
||||||
classes,
|
classes,
|
||||||
|
hierarchy,
|
||||||
functionTypes,
|
functionTypes,
|
||||||
tags,
|
tags,
|
||||||
metadataRequirements,
|
metadataRequirements,
|
||||||
|
|
|
@ -67,8 +67,11 @@ import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
|
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||||
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
|
@ -93,6 +96,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
|
|
||||||
private final WasmModule module;
|
private final WasmModule module;
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
|
private ClassHierarchy hierarchy;
|
||||||
private WasmFunctionTypes functionTypes;
|
private WasmFunctionTypes functionTypes;
|
||||||
private TagRegistry tagRegistry;
|
private TagRegistry tagRegistry;
|
||||||
private ClassMetadataRequirements metadataRequirements;
|
private ClassMetadataRequirements metadataRequirements;
|
||||||
|
@ -129,6 +133,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
private int virtualTableFieldOffset;
|
private int virtualTableFieldOffset;
|
||||||
private int arrayLengthOffset = -1;
|
private int arrayLengthOffset = -1;
|
||||||
private int arrayGetOffset = -1;
|
private int arrayGetOffset = -1;
|
||||||
|
private int cloneOffset = -1;
|
||||||
private WasmStructure arrayVirtualTableStruct;
|
private WasmStructure arrayVirtualTableStruct;
|
||||||
private WasmFunction arrayGetObjectFunction;
|
private WasmFunction arrayGetObjectFunction;
|
||||||
private WasmFunction arrayLengthObjectFunction;
|
private WasmFunction arrayLengthObjectFunction;
|
||||||
|
@ -137,6 +142,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
private List<WasmStructure> nonInitializedStructures = new ArrayList<>();
|
private List<WasmStructure> nonInitializedStructures = new ArrayList<>();
|
||||||
|
|
||||||
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
||||||
|
ClassHierarchy hierarchy,
|
||||||
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
||||||
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
|
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
|
||||||
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
|
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
|
||||||
|
@ -144,6 +150,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories) {
|
List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
|
this.hierarchy = hierarchy;
|
||||||
this.functionTypes = functionTypes;
|
this.functionTypes = functionTypes;
|
||||||
this.tagRegistry = tagRegistry;
|
this.tagRegistry = tagRegistry;
|
||||||
this.metadataRequirements = metadataRequirements;
|
this.metadataRequirements = metadataRequirements;
|
||||||
|
@ -359,6 +366,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
return classEnclosingClassOffset;
|
return classEnclosingClassOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getClassParentOffset() {
|
||||||
|
standardClasses.classClass().getStructure().init();
|
||||||
|
return classParentOffset;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getClassNameOffset() {
|
public int getClassNameOffset() {
|
||||||
standardClasses.classClass().getStructure().init();
|
standardClasses.classClass().getStructure().init();
|
||||||
|
@ -383,6 +396,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
return virtualTableFieldOffset;
|
return virtualTableFieldOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCloneOffset() {
|
||||||
|
standardClasses.classClass().getStructure().init();
|
||||||
|
return cloneOffset;
|
||||||
|
}
|
||||||
|
|
||||||
private void initPrimitiveClass(WasmGCClassInfo classInfo, ValueType.Primitive type) {
|
private void initPrimitiveClass(WasmGCClassInfo classInfo, ValueType.Primitive type) {
|
||||||
classInfo.initializer = target -> {
|
classInfo.initializer = target -> {
|
||||||
int kind;
|
int kind;
|
||||||
|
@ -469,6 +488,17 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
var owner = getClassInfo(cls.getOwnerName());
|
var owner = getClassInfo(cls.getOwnerName());
|
||||||
target.add(setClassField(classInfo, classEnclosingClassOffset, new WasmGetGlobal(owner.pointer)));
|
target.add(setClassField(classInfo, classEnclosingClassOffset, new WasmGetGlobal(owner.pointer)));
|
||||||
}
|
}
|
||||||
|
if (metadataReq.cloneMethod()) {
|
||||||
|
WasmFunction cloneFunction;
|
||||||
|
if (hierarchy.isSuperType("java.lang.Cloneable", name, false)) {
|
||||||
|
cloneFunction = generateCloneFunction(classInfo, name);
|
||||||
|
} else {
|
||||||
|
cloneFunction = functionProvider.forStaticMethod(new MethodReference(
|
||||||
|
WasmGCSupport.class, "throwCloneNotSupportedException", void.class));
|
||||||
|
}
|
||||||
|
cloneFunction.setReferenced(true);
|
||||||
|
target.add(setClassField(classInfo, cloneOffset, new WasmFunctionReference(cloneFunction)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (virtualTable != null && virtualTable.isConcrete()) {
|
if (virtualTable != null && virtualTable.isConcrete()) {
|
||||||
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
|
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
|
||||||
|
@ -481,6 +511,38 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WasmFunction generateCloneFunction(WasmGCClassInfo classInfo, String className) {
|
||||||
|
var function = new WasmFunction(functionTypes.of(standardClasses.objectClass().getType(),
|
||||||
|
standardClasses.objectClass().getType()));
|
||||||
|
function.setName(names.topLevel(className + "@clone"));
|
||||||
|
module.functions.add(function);
|
||||||
|
|
||||||
|
var objLocal = new WasmLocal(standardClasses.objectClass().getType(), "obj");
|
||||||
|
var castObjLocal = new WasmLocal(classInfo.getType(), "castObj");
|
||||||
|
function.add(objLocal);
|
||||||
|
function.add(castObjLocal);
|
||||||
|
|
||||||
|
var cast = new WasmCast(new WasmGetLocal(objLocal), classInfo.getStructure().getReference());
|
||||||
|
function.getBody().add(new WasmSetLocal(castObjLocal, cast));
|
||||||
|
|
||||||
|
var copy = new WasmStructNew(classInfo.structure);
|
||||||
|
for (var i = 0; i < classInfo.structure.getFields().size(); ++i) {
|
||||||
|
if (i == MONITOR_FIELD_OFFSET) {
|
||||||
|
copy.getInitializers().add(new WasmNullConstant(WasmType.Reference.EQ));
|
||||||
|
} else {
|
||||||
|
var fieldType = classInfo.structure.getFields().get(i).getType();
|
||||||
|
var getExpr = new WasmStructGet(classInfo.structure, new WasmGetLocal(castObjLocal), i);
|
||||||
|
if (fieldType instanceof WasmStorageType.Packed) {
|
||||||
|
getExpr.setSignedType(WasmSignedType.UNSIGNED);
|
||||||
|
}
|
||||||
|
copy.getInitializers().add(getExpr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function.getBody().add(new WasmReturn(copy));
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
private void fillVirtualTableMethods(List<WasmExpression> target, WasmStructure structure, WasmGlobal global,
|
private void fillVirtualTableMethods(List<WasmExpression> target, WasmStructure structure, WasmGlobal global,
|
||||||
WasmGCVirtualTable virtualTable) {
|
WasmGCVirtualTable virtualTable) {
|
||||||
var usedVt = virtualTable.getFirstUsed();
|
var usedVt = virtualTable.getFirstUsed();
|
||||||
|
@ -500,15 +562,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
var itemType = ((ValueType.Array) type).getItemType();
|
var itemType = ((ValueType.Array) type).getItemType();
|
||||||
|
|
||||||
for (var entry : virtualTable.getEntries()) {
|
for (var entry : virtualTable.getEntries()) {
|
||||||
if (entry.getMethod().getName().equals("clone")) {
|
fillVirtualTableEntry(target, global, structure, virtualTable, entry);
|
||||||
var function = generateArrayCloneMethod(objectStructure, itemType);
|
|
||||||
function.setReferenced(true);
|
|
||||||
var ref = new WasmFunctionReference(function);
|
|
||||||
var fieldIndex = virtualTableFieldOffset + entry.getIndex();
|
|
||||||
target.add(new WasmStructSet(structure, new WasmGetGlobal(global), fieldIndex, ref));
|
|
||||||
} else {
|
|
||||||
fillVirtualTableEntry(target, global, structure, virtualTable, entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = metadataRequirements.getInfo(type);
|
var info = metadataRequirements.getInfo(type);
|
||||||
|
@ -773,7 +827,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
var classField = new WasmField(standardClasses.classClass().getType().asStorage());
|
var classField = new WasmField(standardClasses.classClass().getType().asStorage());
|
||||||
classField.setName(names.forMemberField(FAKE_CLASS_FIELD));
|
classField.setName(names.forMemberField(FAKE_CLASS_FIELD));
|
||||||
fields.add(classField);
|
fields.add(classField);
|
||||||
var monitorField = new WasmField(WasmType.Reference.ANY.asStorage());
|
var monitorField = new WasmField(WasmType.Reference.EQ.asStorage());
|
||||||
monitorField.setName(names.forMemberField(FAKE_MONITOR_FIELD));
|
monitorField.setName(names.forMemberField(FAKE_MONITOR_FIELD));
|
||||||
fields.add(monitorField);
|
fields.add(monitorField);
|
||||||
}
|
}
|
||||||
|
@ -836,6 +890,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
new WasmGetGlobal(itemTypeInfo.pointer)
|
new WasmGetGlobal(itemTypeInfo.pointer)
|
||||||
));
|
));
|
||||||
fillArrayVirtualTableMethods(classInfo.getValueType(), target, classInfo.pointer, classInfo.structure);
|
fillArrayVirtualTableMethods(classInfo.getValueType(), target, classInfo.pointer, classInfo.structure);
|
||||||
|
var metadataReq = metadataRequirements.getInfo(type);
|
||||||
|
if (metadataReq.cloneMethod()) {
|
||||||
|
var cloneFunction = generateArrayCloneMethod(classInfo.structure, type.getItemType());
|
||||||
|
cloneFunction.setReferenced(true);
|
||||||
|
target.add(setClassField(classInfo, cloneOffset, new WasmFunctionReference(cloneFunction)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,7 +1043,10 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
classNameOffset = fields.size();
|
classNameOffset = fields.size();
|
||||||
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "name"));
|
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "name"));
|
||||||
classSimpleNameOffset = fields.size();
|
classSimpleNameOffset = fields.size();
|
||||||
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "simpleNAme"));
|
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "simpleName"));
|
||||||
|
cloneOffset = fields.size();
|
||||||
|
fields.add(createClassField(functionTypes.of(standardClasses.objectClass().getType(),
|
||||||
|
standardClasses.objectClass().getType()).getReference().asStorage(), "clone"));
|
||||||
virtualTableFieldOffset = fields.size();
|
virtualTableFieldOffset = fields.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1146,7 +1209,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
standardClasses.classClass().getStructure(),
|
standardClasses.classClass().getStructure(),
|
||||||
new WasmGetLocal(targetVar),
|
new WasmGetLocal(targetVar),
|
||||||
classParentOffset,
|
classParentOffset,
|
||||||
new WasmGetGlobal(standardClasses.classClass().pointer)
|
new WasmGetGlobal(standardClasses.objectClass().pointer)
|
||||||
));
|
));
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ public interface WasmGCClassInfoProvider {
|
||||||
|
|
||||||
int getClassEnclosingClassOffset();
|
int getClassEnclosingClassOffset();
|
||||||
|
|
||||||
|
int getClassParentOffset();
|
||||||
|
|
||||||
int getNewArrayFunctionOffset();
|
int getNewArrayFunctionOffset();
|
||||||
|
|
||||||
int getClassNameOffset();
|
int getClassNameOffset();
|
||||||
|
@ -52,6 +54,8 @@ public interface WasmGCClassInfoProvider {
|
||||||
|
|
||||||
int getArrayLengthOffset();
|
int getArrayLengthOffset();
|
||||||
|
|
||||||
|
int getCloneOffset();
|
||||||
|
|
||||||
default WasmGCClassInfo getClassInfo(String name) {
|
default WasmGCClassInfo getClassInfo(String name) {
|
||||||
return getClassInfo(ValueType.object(name));
|
return getClassInfo(ValueType.object(name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,14 @@ public class ClassIntrinsic implements WasmGCIntrinsic {
|
||||||
result.setLocation(invocation.getLocation());
|
result.setLocation(invocation.getLocation());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
case "getSuperclass": {
|
||||||
|
var cls = context.generate(invocation.getArguments().get(0));
|
||||||
|
var clsStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure();
|
||||||
|
var result = new WasmStructGet(clsStruct, cls,
|
||||||
|
context.classInfoProvider().getClassParentOffset());
|
||||||
|
result.setLocation(invocation.getLocation());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
case "getNameImpl":
|
case "getNameImpl":
|
||||||
return generateGetName(invocation, context);
|
return generateGetName(invocation, context);
|
||||||
case "setNameImpl":
|
case "setNameImpl":
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
@ -52,6 +53,8 @@ public class ObjectIntrinsic implements WasmGCIntrinsic {
|
||||||
return generateGetIdentity(invocation, context);
|
return generateGetIdentity(invocation, context);
|
||||||
case "setWasmGCIdentity":
|
case "setWasmGCIdentity":
|
||||||
return generateSetIdentity(invocation, context);
|
return generateSetIdentity(invocation, context);
|
||||||
|
case "cloneObject":
|
||||||
|
return generateClone(invocation, context);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
@ -130,4 +133,23 @@ public class ObjectIntrinsic implements WasmGCIntrinsic {
|
||||||
return new WasmStructSet(objectStruct, instance, WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET,
|
return new WasmStructSet(objectStruct, instance, WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET,
|
||||||
identityWrapper);
|
identityWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WasmExpression generateClone(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
var objectStruct = context.classInfoProvider().getClassInfo("java.lang.Object").getStructure();
|
||||||
|
var classStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure();
|
||||||
|
|
||||||
|
var block = new WasmBlock(false);
|
||||||
|
block.setType(objectStruct.getReference());
|
||||||
|
var obj = context.exprCache().create(context.generate(invocation.getArguments().get(0)),
|
||||||
|
objectStruct.getReference(), invocation.getLocation(), block.getBody());
|
||||||
|
var cls = new WasmStructGet(objectStruct, obj.expr(), WasmGCClassInfoProvider.CLASS_FIELD_OFFSET);
|
||||||
|
var functionRef = new WasmStructGet(classStruct, cls, context.classInfoProvider().getCloneOffset());
|
||||||
|
var call = new WasmCallReference(functionRef, context.functionTypes().of(
|
||||||
|
objectStruct.getReference(), objectStruct.getReference()));
|
||||||
|
call.getArguments().add(obj.expr());
|
||||||
|
block.getBody().add(call);
|
||||||
|
|
||||||
|
obj.release();
|
||||||
|
return block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
private void fillObject() {
|
private void fillObject() {
|
||||||
var intrinsic = new ObjectIntrinsic();
|
var intrinsic = new ObjectIntrinsic();
|
||||||
add(new MethodReference(Object.class, "getClass", Class.class), intrinsic);
|
add(new MethodReference(Object.class, "getClass", Class.class), intrinsic);
|
||||||
|
add(new MethodReference(Object.class, "cloneObject", Object.class), intrinsic);
|
||||||
add(new MethodReference(Object.class.getName(), "getMonitor",
|
add(new MethodReference(Object.class.getName(), "getMonitor",
|
||||||
ValueType.object("java.lang.Object$Monitor")), intrinsic);
|
ValueType.object("java.lang.Object$Monitor")), intrinsic);
|
||||||
add(new MethodReference(Object.class.getName(), "setMonitor",
|
add(new MethodReference(Object.class.getName(), "setMonitor",
|
||||||
|
@ -83,6 +84,7 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
add(new MethodReference(Class.class, "getNameImpl", String.class), intrinsic);
|
add(new MethodReference(Class.class, "getNameImpl", String.class), intrinsic);
|
||||||
add(new MethodReference(Class.class, "setNameImpl", String.class, void.class), intrinsic);
|
add(new MethodReference(Class.class, "setNameImpl", String.class, void.class), intrinsic);
|
||||||
add(new MethodReference(Class.class, "getEnclosingClass", Class.class), intrinsic);
|
add(new MethodReference(Class.class, "getEnclosingClass", Class.class), intrinsic);
|
||||||
|
add(new MethodReference(Class.class, "getSuperclass", Class.class), intrinsic);
|
||||||
add(new MethodReference(Class.class, "getSimpleNameCache", Class.class, String.class), intrinsic);
|
add(new MethodReference(Class.class, "getSimpleNameCache", Class.class, String.class), intrinsic);
|
||||||
add(new MethodReference(Class.class, "setSimpleNameCache", Class.class, String.class, void.class), intrinsic);
|
add(new MethodReference(Class.class, "setSimpleNameCache", Class.class, String.class, void.class), intrinsic);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ public class WasmGCSupport {
|
||||||
return new ClassCastException();
|
return new ClassCastException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CloneNotSupportedException cnse() {
|
public static void throwCloneNotSupportedException() throws CloneNotSupportedException {
|
||||||
return new CloneNotSupportedException();
|
throw new CloneNotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int nextObjectId() {
|
public static int nextObjectId() {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.transformation.gc;
|
package org.teavm.backend.wasm.transformation.gc;
|
||||||
|
|
||||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
|
||||||
import org.teavm.interop.Import;
|
import org.teavm.interop.Import;
|
||||||
import org.teavm.model.AccessLevel;
|
import org.teavm.model.AccessLevel;
|
||||||
import org.teavm.model.AnnotationHolder;
|
import org.teavm.model.AnnotationHolder;
|
||||||
|
@ -29,7 +28,6 @@ import org.teavm.model.MethodHolder;
|
||||||
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.emit.ProgramEmitter;
|
|
||||||
import org.teavm.model.instructions.GetFieldInstruction;
|
import org.teavm.model.instructions.GetFieldInstruction;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
@ -51,11 +49,6 @@ public class BaseClassesTransformation implements ClassHolderTransformer {
|
||||||
method.setProgram(null);
|
method.setProgram(null);
|
||||||
method.getModifiers().add(ElementModifier.NATIVE);
|
method.getModifiers().add(ElementModifier.NATIVE);
|
||||||
break;
|
break;
|
||||||
case "clone": {
|
|
||||||
var em = ProgramEmitter.create(method, context.getHierarchy());
|
|
||||||
em.invoke(WasmGCSupport.class, "cnse", CloneNotSupportedException.class).raise();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
if (method.getProgram() != null) {
|
if (method.getProgram() != null) {
|
||||||
transformMonitorFieldAccess(method.getProgram());
|
transformMonitorFieldAccess(method.getProgram());
|
||||||
|
@ -80,6 +73,7 @@ public class BaseClassesTransformation implements ClassHolderTransformer {
|
||||||
case "getEnclosingClass":
|
case "getEnclosingClass":
|
||||||
case "getSimpleNameCache":
|
case "getSimpleNameCache":
|
||||||
case "setSimpleNameCache":
|
case "setSimpleNameCache":
|
||||||
|
case "getSuperclass":
|
||||||
method.setProgram(null);
|
method.setProgram(null);
|
||||||
method.getModifiers().add(ElementModifier.NATIVE);
|
method.getModifiers().add(ElementModifier.NATIVE);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -120,6 +120,14 @@ public class ClassMetadataRequirements {
|
||||||
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).arrayLength = true;
|
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).arrayLength = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var clone = dependencyInfo.getMethod(new MethodReference(Object.class, "cloneObject", Object.class));
|
||||||
|
if (clone != null) {
|
||||||
|
var classNames = clone.getVariable(0).getTypes();
|
||||||
|
for (var className : classNames) {
|
||||||
|
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).cloneMethod = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Info getInfo(String className) {
|
public Info getInfo(String className) {
|
||||||
|
@ -168,6 +176,7 @@ public class ClassMetadataRequirements {
|
||||||
boolean newArray;
|
boolean newArray;
|
||||||
boolean arrayLength;
|
boolean arrayLength;
|
||||||
boolean arrayGet;
|
boolean arrayGet;
|
||||||
|
boolean cloneMethod;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean name() {
|
public boolean name() {
|
||||||
|
@ -213,6 +222,11 @@ public class ClassMetadataRequirements {
|
||||||
public boolean arrayGet() {
|
public boolean arrayGet() {
|
||||||
return arrayGet;
|
return arrayGet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cloneMethod() {
|
||||||
|
return cloneMethod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Info {
|
public interface Info {
|
||||||
|
@ -233,5 +247,7 @@ public class ClassMetadataRequirements {
|
||||||
boolean arrayLength();
|
boolean arrayLength();
|
||||||
|
|
||||||
boolean arrayGet();
|
boolean arrayGet();
|
||||||
|
|
||||||
|
boolean cloneMethod();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public final class ResourceMapHelper {
|
||||||
|
|
||||||
public static Resource get(ResourceMap<?> map, String key) {
|
public static Resource get(ResourceMap<?> map, String key) {
|
||||||
var count = entryCount(map);
|
var count = entryCount(map);
|
||||||
var initialIndex = Math.abs(key.hashCode()) % count;
|
var initialIndex = Integer.remainderUnsigned(key.hashCode(), count);
|
||||||
for (var i = initialIndex; i < count; ++i) {
|
for (var i = initialIndex; i < count; ++i) {
|
||||||
var entry = entry(map, i);
|
var entry = entry(map, i);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user