mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
WASM: add support for Enum.valueOf and Class.isEnum
This commit is contained in:
parent
d09affce85
commit
3ad16e80c7
|
@ -111,7 +111,7 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnum() {
|
public boolean isEnum() {
|
||||||
return platformClass.getMetadata().isEnum();
|
return Platform.isEnum(platformClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TClass<?> getComponentType() {
|
public TClass<?> getComponentType() {
|
||||||
|
|
|
@ -18,11 +18,6 @@ package org.teavm.classlib.java.lang;
|
||||||
import org.teavm.classlib.java.io.TSerializable;
|
import org.teavm.classlib.java.io.TSerializable;
|
||||||
import org.teavm.interop.Rename;
|
import org.teavm.interop.Rename;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
* @param <E> type of enum.
|
|
||||||
*/
|
|
||||||
public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComparable<E>, TSerializable {
|
public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComparable<E>, TSerializable {
|
||||||
private TString name;
|
private TString name;
|
||||||
private int ordinal;
|
private int ordinal;
|
||||||
|
|
|
@ -107,10 +107,8 @@ public class BinaryWriter {
|
||||||
public byte[] getData() {
|
public byte[] getData() {
|
||||||
byte[] result = new byte[address];
|
byte[] result = new byte[address];
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int index = 0;
|
|
||||||
for (DataValue value : values) {
|
for (DataValue value : values) {
|
||||||
offset = writeData(result, offset, value);
|
offset = writeData(result, offset, value);
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
return Arrays.copyOf(result, offset);
|
return Arrays.copyOf(result, offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ public class WasmClassGenerator {
|
||||||
DataPrimitives.ADDRESS, /* array type */
|
DataPrimitives.ADDRESS, /* array type */
|
||||||
DataPrimitives.INT, /* isInstance function */
|
DataPrimitives.INT, /* isInstance function */
|
||||||
DataPrimitives.ADDRESS, /* parent */
|
DataPrimitives.ADDRESS, /* parent */
|
||||||
|
DataPrimitives.ADDRESS, /* enum values */
|
||||||
DataPrimitives.ADDRESS /* layout */);
|
DataPrimitives.ADDRESS /* layout */);
|
||||||
private IntegerArray staticGcRoots = new IntegerArray(1);
|
private IntegerArray staticGcRoots = new IntegerArray(1);
|
||||||
private int staticGcRootsAddress;
|
private int staticGcRootsAddress;
|
||||||
|
@ -86,7 +87,8 @@ public class WasmClassGenerator {
|
||||||
private static final int CLASS_ARRAY_TYPE = 7;
|
private static final int CLASS_ARRAY_TYPE = 7;
|
||||||
private static final int CLASS_IS_INSTANCE = 8;
|
private static final int CLASS_IS_INSTANCE = 8;
|
||||||
private static final int CLASS_PARENT = 9;
|
private static final int CLASS_PARENT = 9;
|
||||||
private static final int CLASS_LAYOUT = 10;
|
private static final int CLASS_ENUM_VALUES = 10;
|
||||||
|
private static final int CLASS_LAYOUT = 11;
|
||||||
|
|
||||||
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
|
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
|
||||||
TagRegistry tagRegistry, BinaryWriter binaryWriter) {
|
TagRegistry tagRegistry, BinaryWriter binaryWriter) {
|
||||||
|
@ -193,6 +195,7 @@ public class WasmClassGenerator {
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
String name = ((ValueType.Object) binaryData.type).getClassName();
|
String name = ((ValueType.Object) binaryData.type).getClassName();
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
VirtualTable vtable = vtableProvider.lookup(name);
|
VirtualTable vtable = vtableProvider.lookup(name);
|
||||||
int vtableSize = vtable != null ? vtable.getEntries().size() : 0;
|
int vtableSize = vtable != null ? vtable.getEntries().size() : 0;
|
||||||
|
@ -238,9 +241,34 @@ public class WasmClassGenerator {
|
||||||
staticGcRoots.add(binaryData.fieldLayout.get(field.getFieldName()));
|
staticGcRoots.add(binaryData.fieldLayout.get(field.getFieldName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClassReader cls = classSource.get(name);
|
||||||
|
if (cls != null && cls.hasModifier(ElementModifier.ENUM)) {
|
||||||
|
header.setAddress(CLASS_ENUM_VALUES, generateEnumValues(cls, binaryData));
|
||||||
|
flags |= RuntimeClass.ENUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.setInt(CLASS_FLAGS, flags);
|
||||||
|
|
||||||
return vtable != null ? wrapper : header;
|
return vtable != null ? wrapper : header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int generateEnumValues(ClassReader cls, ClassBinaryData binaryData) {
|
||||||
|
FieldReader[] fields = cls.getFields().stream()
|
||||||
|
.filter(field -> field.hasModifier(ElementModifier.ENUM))
|
||||||
|
.toArray(FieldReader[]::new);
|
||||||
|
DataValue sizeValue = DataPrimitives.ADDRESS.createValue();
|
||||||
|
sizeValue.setAddress(0, fields.length);
|
||||||
|
int valuesAddress = binaryWriter.append(sizeValue);
|
||||||
|
|
||||||
|
for (FieldReader field : fields) {
|
||||||
|
DataValue fieldRefValue = DataPrimitives.ADDRESS.createValue();
|
||||||
|
fieldRefValue.setAddress(0, binaryData.fieldLayout.get(field.getName()));
|
||||||
|
binaryWriter.append(fieldRefValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return valuesAddress;
|
||||||
|
}
|
||||||
|
|
||||||
private List<FieldReference> getReferenceFields(ClassReader cls) {
|
private List<FieldReference> getReferenceFields(ClassReader cls) {
|
||||||
return cls.getFields().stream()
|
return cls.getFields().stream()
|
||||||
.filter(field -> !field.hasModifier(ElementModifier.STATIC))
|
.filter(field -> !field.hasModifier(ElementModifier.STATIC))
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.teavm.interop.Unmanaged;
|
||||||
public class RuntimeClass extends RuntimeJavaObject {
|
public class RuntimeClass extends RuntimeJavaObject {
|
||||||
public static final int INITIALIZED = 1;
|
public static final int INITIALIZED = 1;
|
||||||
public static final int PRIMITIVE = 2;
|
public static final int PRIMITIVE = 2;
|
||||||
|
public static final int ENUM = 4;
|
||||||
|
|
||||||
public int size;
|
public int size;
|
||||||
public int flags;
|
public int flags;
|
||||||
|
@ -31,6 +32,7 @@ public class RuntimeClass extends RuntimeJavaObject {
|
||||||
public RuntimeClass arrayType;
|
public RuntimeClass arrayType;
|
||||||
public IsSupertypeFunction isSupertypeOf;
|
public IsSupertypeFunction isSupertypeOf;
|
||||||
public RuntimeClass parent;
|
public RuntimeClass parent;
|
||||||
|
public Address enumValues;
|
||||||
public Address layout;
|
public Address layout;
|
||||||
|
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
|
|
|
@ -19,7 +19,9 @@ import java.lang.annotation.Annotation;
|
||||||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
import org.teavm.backend.javascript.spi.GeneratedBy;
|
||||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.DelegateTo;
|
import org.teavm.interop.DelegateTo;
|
||||||
|
import org.teavm.interop.Unmanaged;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
import org.teavm.jso.browser.Window;
|
import org.teavm.jso.browser.Window;
|
||||||
|
@ -49,6 +51,7 @@ public final class Platform {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@Unmanaged
|
||||||
private static boolean isInstanceLowLevel(RuntimeClass self, RuntimeObject object) {
|
private static boolean isInstanceLowLevel(RuntimeClass self, RuntimeObject object) {
|
||||||
return isAssignableLowLevel(RuntimeClass.getClass(object), self);
|
return isAssignableLowLevel(RuntimeClass.getClass(object), self);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +74,7 @@ public final class Platform {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@Unmanaged
|
||||||
private static boolean isAssignableLowLevel(RuntimeClass from, RuntimeClass to) {
|
private static boolean isAssignableLowLevel(RuntimeClass from, RuntimeClass to) {
|
||||||
return to.isSupertypeOf.apply(from);
|
return to.isSupertypeOf.apply(from);
|
||||||
}
|
}
|
||||||
|
@ -119,8 +123,44 @@ public final class Platform {
|
||||||
|
|
||||||
@GeneratedBy(PlatformGenerator.class)
|
@GeneratedBy(PlatformGenerator.class)
|
||||||
@PluggableDependency(PlatformGenerator.class)
|
@PluggableDependency(PlatformGenerator.class)
|
||||||
|
@DelegateTo("getEnumConstantsLowLevel")
|
||||||
public static native Enum<?>[] getEnumConstants(PlatformClass cls);
|
public static native Enum<?>[] getEnumConstants(PlatformClass cls);
|
||||||
|
|
||||||
|
private static Enum<?>[] getEnumConstantsLowLevel(PlatformClass cls) {
|
||||||
|
int size = getEnumConstantsSize(cls);
|
||||||
|
if (size < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum<?>[] constants = new Enum<?>[size];
|
||||||
|
fillEnumConstants(cls, constants);
|
||||||
|
return constants;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DelegateTo("getEnumConstantsSizeImpl")
|
||||||
|
private static native int getEnumConstantsSize(PlatformClass cls);
|
||||||
|
|
||||||
|
@Unmanaged
|
||||||
|
private static int getEnumConstantsSizeImpl(RuntimeClass cls) {
|
||||||
|
Address enumValues = cls.enumValues;
|
||||||
|
if (enumValues == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return enumValues.getAddress().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DelegateTo("fillEnumConstantsImpl")
|
||||||
|
private static native void fillEnumConstants(PlatformClass cls, Enum<?>[] array);
|
||||||
|
|
||||||
|
@Unmanaged
|
||||||
|
private static void fillEnumConstantsImpl(RuntimeClass cls, Address[] array) {
|
||||||
|
Address enumValues = cls.enumValues;
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
enumValues = enumValues.add(Address.sizeOf());
|
||||||
|
array[i] = enumValues.getAddress().getAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GeneratedBy(PlatformGenerator.class)
|
@GeneratedBy(PlatformGenerator.class)
|
||||||
@PluggableDependency(PlatformGenerator.class)
|
@PluggableDependency(PlatformGenerator.class)
|
||||||
public static native Annotation[] getAnnotations(PlatformClass cls);
|
public static native Annotation[] getAnnotations(PlatformClass cls);
|
||||||
|
@ -158,16 +198,28 @@ public final class Platform {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@Unmanaged
|
||||||
private static boolean isPrimitiveLowLevel(RuntimeClass cls) {
|
private static boolean isPrimitiveLowLevel(RuntimeClass cls) {
|
||||||
return (cls.flags & RuntimeClass.PRIMITIVE) != 0;
|
return (cls.flags & RuntimeClass.PRIMITIVE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DelegateTo("isEnumLowLevel")
|
||||||
|
public static boolean isEnum(PlatformClass cls) {
|
||||||
|
return cls.getMetadata().isEnum();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmanaged
|
||||||
|
private static boolean isEnumLowLevel(RuntimeClass cls) {
|
||||||
|
return (cls.flags & RuntimeClass.ENUM) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
@DelegateTo("getArrayItemLowLevel")
|
@DelegateTo("getArrayItemLowLevel")
|
||||||
public static PlatformClass getArrayItem(PlatformClass cls) {
|
public static PlatformClass getArrayItem(PlatformClass cls) {
|
||||||
return cls.getMetadata().getArrayItem();
|
return cls.getMetadata().getArrayItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@Unmanaged
|
||||||
private static RuntimeClass getArrayItemLowLevel(RuntimeClass cls) {
|
private static RuntimeClass getArrayItemLowLevel(RuntimeClass cls) {
|
||||||
return cls.itemType;
|
return cls.itemType;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user